Robot 2

Squiggle Ops — Gateway

:root{
–bg:#060609;
–panel:#0f1720;
–accent:#ff7a18;
–accent2:#1bd1a3;
–muted:#9aa6b2;
–glass: rgba(255,255,255,0.03);
–danger:#ff4d6d;
}
html,body{
height:100%;
margin:0;
font-family: -apple-system, BlinkMacSystemFont, “Segoe UI”, Roboto, “Helvetica Neue”, Arial;
background: linear-gradient(180deg, #03030a 0%, #07111a 100%);
color:#e6eef6;
-webkit-font-smoothing:antialiased;
-webkit-text-size-adjust:100%;
}
.wrap{
max-width:980px;
margin:18px auto;
padding:18px;
}
header{
display:flex;
gap:12px;
align-items:center;
margin-bottom:16px;
}
.logo{
width:72px;height:72px;border-radius:14px;
background:linear-gradient(135deg,#071b2a,#072b0f);
display:flex;align-items:center;justify-content:center;
box-shadow: 0 6px 18px rgba(0,0,0,0.6), inset 0 1px 0 rgba(255,255,255,0.02);
border:1px solid rgba(255,255,255,0.03);
}
.logo svg{width:52px;height:52px;}
h1{font-size:20px;margin:0}
p.lead{margin:0;color:var(–muted);font-size:13px}

main{display:grid;grid-template-columns: 1fr 360px; gap:16px; margin-top:18px;}
/* Left (dashboard) */
.panel{
background: linear-gradient(180deg, rgba(255,255,255,0.02), rgba(255,255,255,0.015));
border-radius:12px;padding:14px;border:1px solid rgba(255,255,255,0.03);
box-shadow: 0 6px 24px rgba(2,6,23,0.6);
}
.meter{
padding:12px;border-radius:10px;background:linear-gradient(90deg, rgba(255,255,255,0.01), rgba(255,255,255,0.02));
display:flex;gap:12px;align-items:center;
}
.barWrap{flex:1}
.bar{
width:100%;height:18px;border-radius:9px;background:rgba(255,255,255,0.04);overflow:hidden;position:relative;
}
.barInner{
height:100%;width:0%;background:linear-gradient(90deg,var(–accent2),var(–accent));border-radius:9px;transition:width 600ms cubic-bezier(.2,.9,.25,1);
box-shadow:0 4px 14px rgba(0,0,0,0.45), inset 0 1px 0 rgba(255,255,255,0.03);
}
.meter .value{min-width:72px;text-align:right;font-weight:700;letter-spacing:0.6px}

.split{
display:flex;gap:8px;margin-top:12px;
}
.split .box{flex:1;padding:8px;border-radius:8px;background:var(–glass);border:1px solid rgba(255,255,255,0.02);text-align:center}
.split .box h3{margin:0;font-size:14px}
.split .box p{margin:6px 0 0;color:var(–muted);font-size:12px}

.weapons{
display:flex;gap:8px;margin-top:14px;flex-wrap:wrap;
}
.btn{
display:inline-flex;align-items:center;justify-content:center;gap:8px;
background:linear-gradient(180deg, rgba(255,255,255,0.02), rgba(255,255,255,0.01));
border:1px solid rgba(255,255,255,0.03);
padding:10px 12px;border-radius:10px;color:inherit;font-weight:700;cursor:pointer;
min-width:112px;user-select:none;
transition:transform 140ms ease,box-shadow 140ms ease;
}
.btn:active{transform:translateY(2px)}
.btn.primary{background: linear-gradient(90deg, var(–accent2), var(–accent)); color:#071018; box-shadow: 0 8px 30px rgba(255,122,24,0.14);}
.btn.warn{background:linear-gradient(90deg,#ffb5b5,#ff7a7a); color:#200;}
.controls{display:flex;gap:8px;margin-top:12px;flex-wrap:wrap}

/* Right column (launcher + logs) */
.launcher{
display:flex;flex-direction:column;gap:10px;
}
.bigLaunch{
padding:16px;border-radius:12px;background:linear-gradient(135deg,#07121a,#0a1620);
text-align:center;border:1px solid rgba(255,255,255,0.03);
}
.bigLaunch .protocol{
font-weight:700;color:var(–accent);letter-spacing:0.8px;font-size:13px;margin-bottom:8px;
}
.bigLaunch .launchBtn{width:100%;padding:12px;border-radius:12px;font-size:16px}
.small-note{font-size:12px;color:var(–muted)}

.log{
max-height:320px;overflow:auto;padding:10px;border-radius:10px;background:rgba(0,0,0,0.12);
border:1px solid rgba(255,255,255,0.02);font-size:13px;
}
.log p{margin:6px 0;color:var(–muted);font-family:monospace;font-size:13px}

footer{margin-top:18px;text-align:center;color:var(–muted);font-size:12px}
.pill{display:inline-block;padding:6px 8px;border-radius:999px;background:rgba(255,255,255,0.02);border:1px solid rgba(255,255,255,0.02);font-weight:700}
@media (max-width:880px){
main{grid-template-columns:1fr; }
.logo{width:56px;height:56px}
}

Squiggle Ops

PWA gateway • Dashboard • Launcher

Core Control Dashboard
Persist: on

Energy
0%

0

Weapons Console
Haptics: local

⚡ Blast
🛡️ Shield
∅ Nullify
🔥 Ignition
⤴ Charge
⤵ Drain
⟲ Reset
🔒 Toggle Persist
Notes: Save to Home Screen for an app-like experience. Some PWA features (service worker) require HTTPS.

Built for Home Screen • Save with Share → Add to Home Screen • © Squiggle Ops

(function(){
// State
const STORAGE_KEY = ‘squiggle_ops_state_v1’;
let state = {
energy: 48,
core: 52,
net: 46,
persist: true,
logs: []
};

// Init DOM
const energyBar = document.getElementById(‘energyBar’);
const energyValue = document.getElementById(‘energyValue’);
const energyPerc = document.getElementById(‘energyPerc’);
const coreVal = document.getElementById(‘coreVal’);
const netVal = document.getElementById(‘netVal’);
const logArea = document.getElementById(‘logArea’);
const persistStatus = document.getElementById(‘persistStatus’);

function log(msg){
const t = new Date().toLocaleTimeString();
state.logs.unshift(‘[‘+t+’] ‘+msg);
if(state.logs.length>80) state.logs.pop();
renderLogs();
persistStateDebounced();
}
function renderLogs(){
logArea.innerHTML = state.logs.map(l=>’

‘+escapeHtml(l)+’

‘).join(”);
}
function escapeHtml(s){ return (s+”).replace(/[&”]/g, c => ({‘&’:’&’,”:’>’,’”‘:’"’}[c])); }

function render(){
const e = Math.max(0,Math.min(100, Math.round(state.energy)));
energyBar.style.width = e + ‘%’;
energyValue.textContent = Math.round(state.energy);
energyPerc.textContent = e + ‘%’;
coreVal.textContent = Math.round(state.core);
netVal.textContent = Math.round(state.net);
persistStatus.textContent = ‘Persist: ‘ + (state.persist ? ‘on’ : ‘off’);
}

// Load from localStorage
function loadState(){
try{
const raw = localStorage.getItem(STORAGE_KEY);
if(raw){
const s = JSON.parse(raw);
state = Object.assign(state, s);
}
}catch(e){ console.warn(‘load failed’,e) }
}
function saveState(){
try{
if(state.persist) localStorage.setItem(STORAGE_KEY, JSON.stringify(state));
else localStorage.removeItem(STORAGE_KEY);
}catch(e){ console.warn(‘save failed’,e) }
}
const persistStateDebounced = debounce(saveState, 300);

// Helpers
function debounce(fn, ms){ let t; return (…a)=>{ clearTimeout(t); t=setTimeout(()=>fn(…a), ms); };}

// Controls: weapon behavior
document.getElementById(‘blastBtn’).addEventListener(‘click’, ()=>{
state.energy = Math.max(0, state.energy – 12);
state.core = Math.max(0, state.core – 6);
log(‘Blast fired — energy -12’);
flash(‘#ff7a18’);
render(); persistStateDebounced();
});
document.getElementById(‘shieldBtn’).addEventListener(‘click’, ()=>{
state.energy = Math.max(0, state.energy – 6);
state.net = Math.min(100, state.net + 4);
log(‘Shield activated — energy -6, net +4’);
flash(‘#1bd1a3’);
render(); persistStateDebounced();
});
document.getElementById(‘nullBtn’).addEventListener(‘click’, ()=>{
state.energy = Math.max(0, state.energy – 10);
state.core = Math.max(0, state.core – 10);
log(‘Nullify pulse — systems stabilized’);
flash(‘#9aa6b2’);
render(); persistStateDebounced();
});
document.getElementById(‘igniteBtn’).addEventListener(‘click’, ()=>{
state.energy = Math.min(100, state.energy + 14);
state.core = Math.min(100, state.core + 8);
log(‘Ignition sequence — energy +14’);
flash(‘#ff4d6d’);
render(); persistStateDebounced();
});

document.getElementById(‘chargeBtn’).addEventListener(‘click’, ()=>{
state.energy = Math.min(100, state.energy + 8);
state.net = Math.min(100, state.net + 3);
log(‘Manual charge +8’);
render(); persistStateDebounced();
});
document.getElementById(‘drainBtn’).addEventListener(‘click’, ()=>{
state.energy = Math.max(0, state.energy – 8);
state.net = Math.max(0, state.net – 4);
log(‘Manual drain -8’);
render(); persistStateDebounced();
});
document.getElementById(‘resetBtn’).addEventListener(‘click’, ()=>{
state.energy = 48; state.core = 52; state.net = 46;
log(‘Systems reset’);
render(); persistStateDebounced();
});
document.getElementById(‘togglePersist’).addEventListener(‘click’, ()=>{
state.persist = !state.persist;
log(‘Persist ‘ + (state.persist ? ‘enabled’:’disabled’));
render(); persistStateDebounced();
});

// Export / Import
document.getElementById(‘exportState’).addEventListener(‘click’, ()=>{
const data = JSON.stringify(state, null, 2);
const blob = new Blob([data], {type:’application/json’});
const url = URL.createObjectURL(blob);
const a = document.createElement(‘a’);
a.href = url; a.download = ‘squiggle_state.json’;
document.body.appendChild(a); a.click(); a.remove();
URL.revokeObjectURL(url);
log(‘State exported’);
});
document.getElementById(‘importState’).addEventListener(‘click’, ()=>{
const input = document.createElement(‘input’);
input.type=’file’; input.accept=’application/json’;
input.onchange = e=>{
const f = e.target.files[0];
if(!f) return;
const r = new FileReader();
r.onload = ev=>{
try{
const s = JSON.parse(ev.target.result);
state = Object.assign(state, s);
log(‘State imported’);
render(); persistStateDebounced();
}catch(err){ log(‘Import failed’); }
};
r.readAsText(f);
};
input.click();
});
document.getElementById(‘clearState’).addEventListener(‘click’, ()=>{
if(confirm(‘Clear all local state?’)) {
state = {energy:48,core:52,net:46,persist:true,logs:[]};
saveState(); render(); log(‘State cleared’);
}
});

// Visual flash
function flash(color){
const el = document.querySelector(‘.logo’);
const prev = el.style.boxShadow;
el.style.boxShadow = ‘0 0 30px 6px ‘+color;
setTimeout(()=> el.style.boxShadow = prev, 220);
// small vibration on supported devices
if(navigator.vibrate) navigator.vibrate(40);
}

// Protocol launcher (attempt)
document.getElementById(‘openProtocol’).addEventListener(‘click’, ()=>{
openProtocol(‘squiggle://ausar.merr.amon.ops’);
});

function openProtocol(url){
// Try: iframe method (works for many mobile scenarios)
log(‘Attempting to open protocol: ‘ + url);
const start = Date.now();
// create invisible iframe
const ifr = document.createElement(‘iframe’);
ifr.style.display=’none’;
document.body.appendChild(ifr);
try {
ifr.src = url;
} catch(e){
// fallback to location change
window.location = url;
}
setTimeout(()=>{
try{ ifr.remove(); } catch(e){}
// If still on page after a short time, assume not installed
if(Date.now() – start {
// grow energy slowly, capped at 100
if(state.energy {
self.skipWaiting();
e.waitUntil(caches.open(CACHE_NAME).then(c=>c.addAll(assets)).catch(()=>{}));
});
self.addEventListener(‘activate’, e => { e.waitUntil(self.clients.claim()); });
self.addEventListener(‘fetch’, e => {
e.respondWith(caches.match(e.request).then(r=>r || fetch(e.request)).catch(()=>fetch(e.request)));
});
`;
const blob = new Blob([swCode], {type:’application/javascript’});
const swUrl = URL.createObjectURL(blob);
navigator.serviceWorker.register(swUrl).then(reg => {
log(‘Service worker attempted to register (may require HTTPS).’);
}).catch(err=>{
console.warn(‘SW register failed’,err);
log(‘Service worker registration failed (HTTPS required).’);
});
}catch(e){
console.warn(‘sw fail’,e);
log(‘Service worker not available’);
}
}

// Load & start
loadState();
render();
renderLogs();
startAutoCharge();

// Small UX polish: ensure localStorage toggle text is correct
persistStatus.addEventListener(‘click’, ()=>{ state.persist = !state.persist; render(); persistStateDebounced(); log(‘Persist toggled via pill’); });

// Save on page hide
window.addEventListener(‘pagehide’, saveState);
window.addEventListener(‘beforeunload’, saveState);

// initial log
log(‘Dashboard ready’);
})();