Files
Fenris/prototype/titlebox-health-presets/index.html
T

90 lines
18 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Fenris titlebox, health layout and presets prototype</title>
<style>
:root{color-scheme:dark;font-family:ui-monospace,SFMono-Regular,Consolas,Menlo,monospace}
*{box-sizing:border-box}body{margin:0;background:#06070a;color:var(--text);font:14px/1.35 ui-monospace,SFMono-Regular,Consolas,Menlo,monospace}.note{max-width:1180px;margin:18px auto 8px;padding:0 16px;color:#c0c6d0}.terminal{width:min(var(--term-w),calc(100vw - 32px));min-height:var(--term-h);margin:0 auto 108px;background:var(--bg);border:1px solid var(--line);box-shadow:0 24px 80px #000;border-radius:8px;overflow:hidden}.screen{padding:8px}.titlebox{height:38px;border:2px solid var(--accent);display:flex;align-items:center;justify-content:center;font-weight:900;font-size:17px;letter-spacing:.01em;color:var(--title);background:linear-gradient(180deg,var(--title-bg),transparent)}.titlebox .fallback{display:none}body[data-glyph=plain] .titlebox .emoji{display:none}body[data-glyph=plain] .titlebox .fallback{display:inline}.auth{margin-top:6px;color:var(--muted);border-left:4px solid var(--accent);padding:4px 8px;background:var(--panel-soft)}.grid{display:grid;grid-template-columns:3fr 2fr;gap:8px;margin-top:8px}.pane{border:1px solid var(--line);background:var(--panel);padding:9px 11px;min-height:130px}.headline{grid-column:1/-1;min-height:92px}.pane-title{color:var(--muted);margin:-19px 0 6px -2px;background:var(--panel);width:max-content;padding:0 6px}.big{font-size:18px;font-weight:900}.muted{color:var(--muted)}.accent{color:var(--accent)}.status-line{display:flex;gap:12px;align-items:center;justify-content:space-between;flex-wrap:wrap;margin-top:5px}.state{font-weight:900}.state .glyph{display:inline-block;width:2ch;text-align:center}.state.monitoring{color:var(--ok)}body:not(.reduced) .state.monitoring .glyph{animation:blink 1.5s steps(1,end) infinite}.state.collecting{color:var(--ok)}.state.paused,.state.waiting{color:var(--warn)}.state.interrupted,.state.error,.state.stale{color:var(--bad)}.state.unknown{color:var(--neutral)}@keyframes blink{50%{opacity:.18}}.pause-banner{display:none;margin-top:8px;border:2px solid var(--warn);background:var(--warn-bg);color:var(--warn-text);padding:7px 10px;font-weight:900}body[data-state=paused] .pause-banner{display:block}.facts{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:5px;margin-top:7px}.fact{border:1px solid var(--line-dim);padding:4px 6px;background:var(--panel-soft)}.fact b{color:var(--muted);font-weight:700}.history{min-height:240px}.range{display:flex;gap:5px;align-items:center;flex-wrap:wrap}.pill{border:1px solid var(--line);padding:2px 7px;border-radius:999px;background:var(--panel-soft);color:var(--text)}.pill.active{border-color:var(--accent);color:var(--accent);font-weight:900}.bars{display:grid;grid-template-columns:repeat(14,1fr);gap:3px;align-items:end;height:82px;margin:8px 0 2px;border-bottom:1px solid var(--line)}.bar{display:flex;flex-direction:column;justify-content:flex-end;align-items:center;min-width:0}.bar span{display:block;width:100%;text-align:center}.allocated{color:var(--graph)}.unalloc{color:var(--unalloc)}.gap{color:var(--gap)}.zero{color:var(--zero)}.partial{border-top:2px dashed var(--select)}.selected{outline:1px solid var(--select);outline-offset:1px}.day-row{display:grid;grid-template-columns:repeat(14,1fr);gap:3px;color:var(--muted);font-size:12px;text-align:center}.marker{color:var(--select);text-align:center;letter-spacing:.5ch}.legend{color:var(--muted);font-size:12px;margin-top:7px}.readout{border-top:1px dashed var(--line);padding-top:7px;margin-top:7px}.health{display:grid;grid-template-rows:auto auto;gap:8px}.subbox{border:1px solid var(--line-dim);padding:7px 8px;background:var(--panel-soft)}.subbox h3{margin:0 0 5px;font-size:14px;color:var(--accent)}.settings-grid{display:grid;grid-template-columns:auto 1fr;gap:3px 9px}.setting-control{color:var(--accent);font-weight:900}.service{margin-top:8px;border:1px solid var(--line);background:var(--panel);display:grid;grid-template-columns:1fr auto;gap:8px;padding:8px 10px}.continuity{margin-top:3px}.actions{display:flex;align-items:center;gap:10px;white-space:nowrap}.quit{border:2px solid var(--text);padding:3px 8px;font-weight:900;color:var(--text);background:var(--quit-bg)}.long-reason{display:none;color:var(--bad);margin-top:5px}body[data-state=error] .long-reason,body[data-state=stale] .long-reason,body[data-state=interrupted] .long-reason{display:block}.narrow-only{display:none}.switcher{position:fixed;z-index:10;bottom:14px;left:50%;transform:translateX(-50%);display:flex;gap:8px;align-items:center;flex-wrap:wrap;justify-content:center;max-width:calc(100vw - 20px);background:#f5f7fb;color:#151923;border-radius:999px;padding:8px 11px;box-shadow:0 8px 32px #000}.switcher label{font-weight:800}.switcher select,.switcher button{font:700 13px ui-monospace,monospace;border:1px solid #c8ced9;border-radius:999px;background:white;color:#151923;padding:6px 9px}.switcher button.active{background:#151923;color:white}.switcher .check{display:flex;align-items:center;gap:4px}.switcher input{accent-color:#151923}
body[data-preset=amber]{--bg:#0d0b07;--panel:#17120b;--panel-soft:#20180f;--title-bg:#22170a;--title:#f8e1ad;--text:#f3eadb;--muted:#c2ad8a;--line:#8a6432;--line-dim:#5a4022;--accent:#f0b35a;--graph:#f0b35a;--unalloc:#d38f3f;--gap:#6f604e;--zero:#d8c5a3;--select:#f8e08e;--ok:#5ee08b;--warn:#ffd166;--bad:#ff6b6b;--neutral:#b8bec9;--warn-bg:#3a2c0c;--warn-text:#fff3c7;--quit-bg:#2a1e10;--term-w:960px;--term-h:650px}
body[data-preset=nord]{--bg:#0b1118;--panel:#111827;--panel-soft:#162033;--title-bg:#172235;--title:#e5e9f0;--text:#e5e9f0;--muted:#a9b4c8;--line:#4c566a;--line-dim:#354154;--accent:#88c0d0;--graph:#88c0d0;--unalloc:#d08770;--gap:#677285;--zero:#c5ccd8;--select:#ebcb8b;--ok:#5ee08b;--warn:#ffd166;--bad:#ff6b6b;--neutral:#b8bec9;--warn-bg:#2f2a17;--warn-text:#fff0bd;--quit-bg:#172235;--term-w:960px;--term-h:650px}
body[data-preset=high]{--bg:#000;--panel:#000;--panel-soft:#111;--title-bg:#000;--title:#fff;--text:#fff;--muted:#d8d8d8;--line:#fff;--line-dim:#888;--accent:#00ffff;--graph:#ffff00;--unalloc:#ffaf00;--gap:#9b9b9b;--zero:#fff;--select:#00ffff;--ok:#00ff00;--warn:#ffff00;--bad:#ff4040;--neutral:#fff;--warn-bg:#333300;--warn-text:#fff;--quit-bg:#000;--term-w:960px;--term-h:650px}
body[data-width=wide]{--term-w:1180px;--term-h:760px}.wide-note{display:none}body[data-width=wide] .wide-note{display:inline}
body[data-width=narrow]{--term-w:620px;--term-h:600px;font-size:13px}body[data-width=narrow] .grid{grid-template-columns:1fr}body[data-width=narrow] .headline{grid-column:auto}body[data-width=narrow] .facts{grid-template-columns:repeat(2,minmax(0,1fr))}body[data-width=narrow] .bars,body[data-width=narrow] .day-row,body[data-width=narrow] .marker,body[data-width=narrow] .legend{display:none}body[data-width=narrow] .narrow-only{display:block;border:1px dashed var(--line);padding:8px;margin:8px 0;color:var(--warn)}body[data-width=narrow] .history{min-height:auto}body[data-width=narrow] .service{grid-template-columns:1fr}body[data-width=narrow] .actions{white-space:normal;justify-content:space-between}.sr{position:absolute;left:-10000px}
</style>
</head>
<body data-preset="amber" data-state="monitoring" data-width="normal" data-glyph="emoji">
<p class="note"><b>PROTOTYPE:</b> titlebox, health/settings grouping, theme presets and status accessibility for <i>Approve titlebox, health layout and colour presets</i>. Static throwaway; no production code.</p>
<main class="terminal" aria-label="Fenris terminal mockup">
<div class="screen">
<div class="titlebox" aria-label="Application title"><span class="emoji">🐺 Fenris by Bongbetic</span><span class="fallback">Fenris by Bongbetic</span></div>
<div class="auth">privileged actions will prompt for authentication (polkit) <span class="wide-note">· clears after first refresh</span></div>
<section class="pane headline">
<div class="pane-title">lifespan + monitoring</div>
<div class="big">Usage-adjusted theoretical lifespan: <span class="accent">8 yr 103 d remaining</span></div>
<div>if current habits continue · sustained regime: 46 days · scenario range: 7d 12.4 / 28d 11.1 / 90d 10.7 GB/day</div>
<div class="status-line"><div class="state monitoring" id="stateLine"><span class="glyph">●</span><span id="stateLabel">Monitoring</span></div><div id="stateReason">Last sample: 4 min ago · blink means enabled + fresh, not data refresh</div></div>
<div class="long-reason" id="longReason">last run failed (exit 3) · last good sample 4 min ago · collection stopped outside Fenris details stay visible without changing the status vocabulary</div>
<div class="pause-banner">‖ Paused — monitoring paused · paused time excluded from your usage habit</div>
<div class="facts"><div class="fact"><b>Boot</b><br><span id="bootFact">on</span></div><div class="fact"><b>Runtime</b><br><span id="runtimeFact">timer active</span></div><div class="fact"><b>Last collect</b><br><span id="collectFact">ok · 4 min ago</span></div><div class="fact"><b>Freshness</b><br><span id="freshFact">fresh</span></div></div>
</section>
<div class="grid">
<section class="pane history" tabindex="0" aria-label="Usage history graph pane">
<div class="pane-title">usage history</div>
<div class="range"><b>usage history · Local · UTC+05:30 · Asia/Kolkata</b><span class="pill">7</span><span class="pill active">14</span><span class="pill">28</span><span class="pill">90</span></div>
<div class="narrow-only">14-day write history: 9.2–18.6 GB/day · selected Wed 09 Sep · graph needs ≥80×24</div>
<div class="bars" aria-hidden="true">
<div class="bar"><span class="gap">░</span><span class="gap">░</span></div><div class="bar"><span class="zero">·</span></div><div class="bar"><span class="allocated">█</span><span class="allocated">█</span></div><div class="bar"><span class="allocated">█</span><span class="unalloc">▒</span><span class="unalloc">▒</span></div><div class="bar selected"><span class="allocated">█</span><span class="allocated">█</span><span class="allocated">█</span><span class="unalloc">▒</span></div><div class="bar"><span class="allocated">█</span></div><div class="bar"><span class="allocated">█</span><span class="allocated">█</span></div><div class="bar"><span class="gap">░</span><span class="gap">░</span><span class="gap">░</span></div><div class="bar"><span class="allocated">█</span><span class="allocated">█</span><span class="allocated">█</span><span class="allocated">█</span></div><div class="bar"><span class="allocated">█</span><span class="unalloc">▒</span></div><div class="bar"><span class="zero">·</span></div><div class="bar"><span class="allocated">█</span><span class="allocated">█</span></div><div class="bar partial"><span class="allocated">█</span><span class="allocated">█</span><span class="unalloc">▒</span></div><div class="bar partial"><span class="allocated">█</span></div>
</div>
<div class="marker">&nbsp;&nbsp;&nbsp;&nbsp;▼</div>
<div class="day-row"><span>27</span><span>28</span><span>29</span><span>30</span><span>31</span><span>01</span><span>02</span><span>03</span><span>04</span><span>05</span><span>06</span><span>07</span><span>08</span><span>09</span></div>
<div class="legend">legend: <span class="allocated">█ allocated</span> · <span class="unalloc">▒ unallocated</span> · <span class="gap">░ gap/no evidence</span> · <span class="zero">· 0 B</span> · ┄ partial · ▼ selected</div>
<div class="readout"><b>Wed 09 Sep</b> · writes 14.2 GB allocated + 2.0 GB unallocated · 21 evidenced hours · coverage 87% · partial · 13 h elapsed · so far<br><span class="muted">Enter/click drills into hourly detail; Esc/Backspace returns. Footer shows graph keys while graph is focused.</span></div>
</section>
<section class="pane health" tabindex="0" aria-label="Drive health and settings pane">
<div class="subbox"><h3>Drive health</h3><b>Samsung SSD 990 PRO</b><br>temperature 41°C · spare 100%<br>media errors 0 · unsafe shutdowns 2<br>power-on 1,184 h · 46 cycles · 2 TB<br><b>vendor wear</b>: 3% used · 18.4 TB written <span class="muted">(context, not a second projection)</span></div>
<div class="subbox"><h3>Settings</h3><div class="settings-grid"><span>device</span><span>/dev/disk/by-id/nvme-Samsung_990</span><span>baseline</span><span>verified override · 1,200 TBW</span><span>retention</span><span>raw 14 d · intervals/hours/days indefinite</span><span>theme</span><span class="setting-control" id="themeText">Amber preset · user preference</span><span>motion</span><span class="setting-control" id="motionText">normal blink</span></div></div>
</section>
</div>
<section class="service" aria-label="Service strip and actions">
<div><b>CONTINUITY</b> <span id="continuity">monitoring: active in background · persists across reboots</span><div class="continuity muted">p pause · r resume · c collect · d disclosures · graph focus: ←/→ select · Enter drill · 1/2/3/4 ranges · t preset · m motion</div></div>
<div class="actions"><span class="quit">q QUIT TUI</span></div>
</section>
</div>
</main>
<nav class="switcher" aria-label="Prototype controls">
<label>preset <select id="preset"><option value="amber">Amber</option><option value="nord">Nord</option><option value="high">High Contrast</option></select></label>
<label>state <select id="state"><option value="monitoring">Monitoring</option><option value="collecting">Collecting</option><option value="paused">Paused</option><option value="waiting">Waiting</option><option value="interrupted">Interrupted</option><option value="error">Error</option><option value="stale">Stale</option><option value="unknown">Unknown</option></select></label>
<label>size <select id="width"><option value="normal">80×24</option><option value="wide">140×40</option><option value="narrow">narrow</option></select></label>
<button id="glyph">wolf title</button>
<label class="check"><input id="motion" type="checkbox"> reduced motion</label>
</nav>
<script>
const states={
monitoring:{glyph:'●',label:'Monitoring',cls:'monitoring',reason:'Last sample: 4 min ago · blink means enabled + fresh, not data refresh',boot:'on',runtime:'timer active',collect:'ok · 4 min ago',fresh:'fresh',cont:'monitoring: active in background · persists across reboots'},
collecting:{glyph:'◐',label:'Collecting',cls:'collecting',reason:'run in flight (≤90 s) · underlying state: monitoring',boot:'on',runtime:'service activating',collect:'running now',fresh:'fresh',cont:'monitoring: active in background · persists across reboots'},
paused:{glyph:'‖',label:'Paused',cls:'paused',reason:'monitoring paused — paused time excluded from your usage habit',boot:'off',runtime:'timer inactive',collect:'ok before pause',fresh:'last sample 49 days ago',cont:'monitoring: does not start on next boot'},
waiting:{glyph:'○',label:'Waiting',cls:'waiting',reason:'awaiting another sample · first graph data is independent of lifespan warm-up',boot:'on',runtime:'timer active',collect:'ok · one sample',fresh:'empty / insufficient pair',cont:'monitoring: active in background · persists across reboots'},
interrupted:{glyph:'⊘',label:'Interrupted',cls:'interrupted',reason:'collection stopped outside Fenris — monitoring period still open',boot:'on',runtime:'timer inactive',collect:'unknown stop',fresh:'last sample 3 days ago',cont:'enabled but not currently collecting'},
error:{glyph:'✖',label:'Error',cls:'error',reason:'last run failed (exit 3) · last good sample 4 min ago',boot:'on',runtime:'timer active',collect:'FAILED exit 3',fresh:'fresh data, failed last run',cont:'monitoring: active in background · persists across reboots'},
stale:{glyph:'◌',label:'Stale',cls:'stale',reason:'last sample 3 days ago · timer active, no failure recorded',boot:'on',runtime:'timer active',collect:'ok then silent',fresh:'stale',cont:'monitoring: active in background · persists across reboots'},
unknown:{glyph:'?',label:'Unknown',cls:'unknown',reason:'service state unavailable',boot:'unknown',runtime:'unknown',collect:'unknown',fresh:'store facts unavailable',cont:'service state unavailable'}
};
function apply(){
const preset=document.getElementById('preset').value; const state=document.getElementById('state').value; const width=document.getElementById('width').value;
document.body.dataset.preset=preset; document.body.dataset.state=state; document.body.dataset.width=width;
const s=states[state]; const line=document.getElementById('stateLine'); line.className='state '+s.cls; line.querySelector('.glyph').textContent=s.glyph; document.getElementById('stateLabel').textContent=s.label; document.getElementById('stateReason').textContent=s.reason;
document.getElementById('bootFact').textContent=s.boot; document.getElementById('runtimeFact').textContent=s.runtime; document.getElementById('collectFact').textContent=s.collect; document.getElementById('freshFact').textContent=s.fresh; document.getElementById('continuity').textContent=s.cont;
document.getElementById('themeText').textContent={amber:'Amber preset · user preference',nord:'Nord preset · user preference',high:'High Contrast preset · user preference'}[preset];
const reduced=document.getElementById('motion').checked; document.body.classList.toggle('reduced',reduced); document.getElementById('motionText').textContent=reduced?'reduced motion · steady status dot':'normal blink';
const params=new URLSearchParams({preset,state,width,glyph:document.body.dataset.glyph,motion:reduced?'reduced':'normal'}); history.replaceState(null,'','?'+params);
}
const params=new URLSearchParams(location.search); for(const id of ['preset','state','width']) if(params.get(id)) document.getElementById(id).value=params.get(id)); if(params.get('glyph')==='plain') document.body.dataset.glyph='plain'; if(params.get('motion')==='reduced') document.getElementById('motion').checked=true;
document.getElementById('glyph').onclick=()=>{document.body.dataset.glyph=document.body.dataset.glyph==='emoji'?'plain':'emoji'; document.getElementById('glyph').textContent=document.body.dataset.glyph==='emoji'?'wolf title':'plain title'; apply()};
for(const id of ['preset','state','width','motion']) document.getElementById(id).addEventListener('change',apply);
apply();
</script>
</body>
</html>