Files
stack/agents/dewey/work/wui/mockups/index.html
T
jason.woltjeandClaude Opus 5.5 1f4882d2b4 docs(wui): Dewey's design work: brand board, five mockups, slice 1 S5 views and checks
Brand board revisions, the five dashboard mockups with their verify
script and evidence, the slice 1 S5 design note (SLICE1-VIEWS.md, rev 3
plus the S2c section 10 update), the Console mockup of inbox, tasks,
agents and trail (mockups/slice1/) and checks/slice1-verify.mjs (16
checks; check 16 pinned to bus at d27042fa). Also the CHAT-03 progress
log and the 2026-09-26 dirty-tree manifest. Design and evidence only;
no package code. Row 40 (#1522), committed on its own at Sage's
direction, 2026-10-09.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-09 17:54:50 -05:00

119 lines
13 KiB
HTML

<!doctype html>
<html lang="en" data-palette="harbor" data-mode="light">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Mosaic Stack web interface · five dashboard mockups</title>
<meta name="description" content="Comparison page for five Mosaic Stack web interface mockups. Prototype only; every action inside the mockups is simulated.">
<link rel="stylesheet" href="shared/app.css">
<style>
.wrap{max-width:1600px;margin:0 auto;padding:24px var(--pad)}
.hero{display:grid;gap:12px;margin-bottom:24px}.hero h1{font-size:clamp(1.6rem,1.2rem + 1.6vw,2.4rem)}
.controls{display:flex;gap:16px;flex-wrap:wrap;align-items:flex-end;padding:14px;background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);box-shadow:var(--shadow)}
.controls>label{min-width:180px}.controls .segmented{display:inline-flex}.controls .segmented label{min-width:0}
.designs{display:grid;gap:16px;grid-template-columns:repeat(auto-fill,minmax(min(100%,320px),1fr));margin:24px 0}
.design{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);padding:16px;display:flex;flex-direction:column;gap:10px;box-shadow:var(--shadow)}
.design h2{display:flex;align-items:baseline;gap:8px;margin:0;flex-wrap:wrap}.design h2 span{font-size:.8rem;color:var(--muted);font-weight:500}
.sketch{aspect-ratio:16/9;border:1px solid var(--line);border-radius:var(--r);background:var(--canvas);display:grid;gap:3px;padding:6px;overflow:hidden}
.sketch i{display:block;background:var(--raised);border-radius:3px}.sketch .a{background:var(--action);opacity:.7}.sketch .w{background:var(--warning);opacity:.55}
.sk-rail{grid-template-columns:14% 1fr;grid-template-rows:1fr}.sk-rail .col{display:grid;gap:3px;grid-template-rows:auto 1fr 1fr}
.sk-deck{grid-template-rows:12% 1fr}.sk-deck .row{display:grid;grid-template-columns:repeat(3,1fr);gap:3px}
.sk-console{grid-template-rows:12% 1fr;grid-template-columns:18% 1fr 22%}.sk-console .bar{grid-column:1/-1}
.sk-board{grid-template-rows:12% 1fr}.sk-board .row{display:grid;grid-template-columns:repeat(5,1fr);gap:3px}
.sk-stream{grid-template-columns:14% 1fr 24%}.sk-stream .col{display:grid;gap:3px}
.design ul{margin:0;padding-left:18px;font-size:.9rem;display:grid;gap:4px}
.design .actions{margin-top:auto}
.script ol{padding-left:20px;display:grid;gap:8px}
.grid2{display:grid;gap:16px;grid-template-columns:1fr}@media (min-width:960px){.grid2{grid-template-columns:1fr 1fr}}
.notes{width:100%;min-height:140px}
</style>
</head>
<body>
<a class="skip" href="#main">Skip to content</a>
<div id="announce" class="sr-only" aria-live="polite"></div>
<main id="main" class="wrap" tabindex="-1">
<header class="hero">
<a href="#" class="wordmark"><i>M</i>Mosaic Stack<small>prototype</small></a>
<h1>Five dashboard mockups for the web interface</h1>
<p>Each design is a complete, navigable prototype of the same feature set with the same sample data. The landing page in every one is the control board from owner decision MOSAIC-STACK-D-001: running agent sessions across projects, with a section for what is waiting on you. Pick the shape you want to iterate; the details inside it change next.</p>
<p class="small muted">Prototype only. Every button and form is simulated and says so. No backend, no credentials, no v1 code. Feature status tags come from <a href="../FEATURES.md">FEATURES.md</a>; the design brief is in <a href="../DESIGN.md">DESIGN.md</a>.</p>
</header>
<section class="controls" aria-labelledby="h-ctl">
<h2 id="h-ctl" class="sr-only">Appearance for all designs</h2>
<label>Palette<select id="palette" data-theme="palette"></select></label>
<fieldset class="mode-control"><legend>Mode</legend><div class="segmented" id="modes"></div></fieldset>
<label>Demo state<select id="state" class="demo-select"><option value="normal">Normal</option><option value="loading">Loading</option><option value="empty">Empty</option><option value="error">Error</option></select></label>
<p class="small muted" style="flex-basis:100%;margin:0">These choices open each design with that palette, mode, and state. Inside a design you can change them again from Settings. Manrope is the typeface throughout; the wordmark is a text placeholder until identity work lands.</p>
</section>
<section aria-labelledby="h-designs">
<h2 id="h-designs">The five designs</h2>
<div class="designs" id="designs"></div>
</section>
<div class="grid2">
<section class="panel script" aria-labelledby="h-script">
<h2 id="h-script">Review script (about ten minutes per design)</h2>
<ol>
<li><b>See what needs you.</b> Land on the control board. Can you tell within three seconds how many things are waiting and which one to open first?</li>
<li><b>Check a running session.</b> Open Darkwing in mosaic-stack/sessions. Notice the configuration-changed notice. It should inform, not block.</li>
<li><b>Launch with a conflict.</b> Go to Launch, keep Dewey in mosaic-stack/wui, submit. You should get a conflict with an offer to connect, and nothing launched twice. Then pick the retired workspace archive-2025 and submit to see a refusal.</li>
<li><b>Find work.</b> Open Work and filter by project. Expand a task to see mission, dependencies, and evidence.</li>
<li><b>Change appearance.</b> Settings: change palette and mode. Reload the page; the choice should persist.</li>
<li><b>Break it.</b> Set the demo state to Error and look at the control board. The message should say what failed and what is unchanged.</li>
<li><b>Phone width.</b> Narrow the window to under 700 px. Navigation should still reach every page.</li>
<li><b>Keyboard only.</b> Tab from the top. Skip link, navigation, every action, and Escape to close anything open. In Console, press Ctrl+K.</li>
</ol>
</section>
<section class="panel" aria-labelledby="h-compare">
<h2 id="h-compare">What differs, what is shared</h2>
<p>Shared across all five: route map, sample data, feature status tags, states (loading, empty, error, refusal, disabled), Manrope, ten palettes, three modes, keyboard access, and the simulated-action rule. What differs is the shell and how the control board organizes attention.</p>
<div class="table-wrap"><table><thead><tr><th scope="col">Design</th><th scope="col">Best when</th><th scope="col">Trade-off</th></tr></thead><tbody>
<tr><td>Rail</td><td>You live in it all day and want stable navigation on any width.</td><td>The rail costs width on phones; it becomes a drawer there.</td></tr>
<tr><td>Deck</td><td>You glance at it a few times a day and want the waiting row to shout.</td><td>Cards use more vertical space than a table for ten or more sessions.</td></tr>
<tr><td>Console</td><td>You run many sessions and prefer keyboard and density.</td><td>Densest and least forgiving on a phone; the inspector becomes a sheet.</td></tr>
<tr><td>Board</td><td>You think in states and want to see load per column at a glance.</td><td>Five columns need 1440 px or more to sit side by side; below that they scroll.</td></tr>
<tr><td>Stream</td><td>You check from a phone often and want an inbox plus a timeline.</td><td>Less structure for comparing sessions side by side.</td></tr>
</tbody></table></div>
<label for="notes" style="margin-top:12px">Your notes (kept in this browser only)</label>
<textarea id="notes" class="notes" placeholder="Which one, and what to change first?"></textarea>
<div class="actions"><button type="button" class="btn" id="download">Download notes</button><span class="small muted" id="notes-status"></span></div>
</section>
</div>
<footer class="foot"><span>Mosaic Stack web interface mockups · Dewey · 2026-09-12</span><a href="../README.md">Brand study and notes</a><a href="../VERIFY.md">Verification record</a></footer>
</main>
<script src="../brand.js"></script>
<script>
(() => {
const B = window.Brand; const $ = s => document.querySelector(s);
const STORE = 'mosaic-wui-mockup-v1';
const designs = [
['d1-rail.html', 'Rail', 'Left rail, two-column board', ['Icon rail with labels, collapsible to icons', 'Board: waiting list across the top, running table, activity and quick launch at the side', 'Ultrawide adds a fourth column for evidence and launch'], '<div class="sketch sk-rail"><i class="a"></i><div class="col"><i class="w"></i><i></i><i></i></div></div>'],
['d2-deck.html', 'Deck', 'Top tabs, card grid', ['Top bar with search and a tab strip', 'Waiting items as a highlighted card row', 'Sessions as cards; settled sessions and activity below'], '<div class="sketch sk-deck"><i class="a"></i><div class="row"><i class="w"></i><i class="w"></i><i class="w"></i></div><div class="row"><i></i><i></i><i></i></div></div>'],
['d3-console.html', 'Console', 'Command bar, tree, dense table, inspector', ['Ctrl+K palette for pages, sessions, palettes, and modes', 'Project and workspace tree on the left', 'Arrow keys through the table; Enter opens an inspector drawer'], '<div class="sketch sk-console"><i class="a bar"></i><i></i><div class="col" style="display:grid;gap:3px"><i class="w"></i><i></i><i></i><i></i></div><i></i></div>'],
['d4-board.html', 'Board', 'Kanban by session state', ['Columns: waiting on you, running, quiet wait, stalled, settled', 'Project filter chips above the board', 'Waiting actions live on the card itself'], '<div class="sketch sk-board"><i class="a"></i><div class="row"><i class="w"></i><i></i><i></i><i></i><i></i></div></div>'],
['d5-stream.html', 'Stream', 'Pinned inbox, time-ordered stream', ['Bottom tab bar on phones, side tabs on desktop', 'Inbox of waiting items stays pinned', 'Everything else flows past as a chronological stream'], '<div class="sketch sk-stream"><i class="a"></i><div class="col"><i></i><i></i><i></i></div><div class="col"><i class="w"></i><i></i></div></div>'],
];
let state = {palette: 'harbor', mode: matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light', chosen: false, demoState: 'normal'};
let storageOk = true;
try { const saved = JSON.parse(localStorage.getItem(STORE) || '{}'); if (B.palettes.some(p => p.id === saved.palette)) state.palette = saved.palette; if (['light','dim','dark'].includes(saved.mode)) { state.mode = saved.mode; state.chosen = true; } if (saved.demoState) state.demoState = saved.demoState; $('#notes').value = localStorage.getItem('mosaic-wui-notes-v1') || ''; } catch { storageOk = false; }
$('#palette').innerHTML = B.palettes.map(p => `<option value="${p.id}">${p.name}</option>`).join('');
$('#modes').innerHTML = ['light','dim','dark'].map(m => `<label><input type="radio" name="mode" value="${m}" data-theme="mode"><span>${m[0].toUpperCase() + m.slice(1)}</span></label>`).join('');
function persist() { if (!storageOk) return; try { localStorage.setItem(STORE, JSON.stringify({palette: state.palette, mode: state.chosen ? state.mode : undefined, demoState: state.demoState})); } catch { storageOk = false; } }
function apply() {
const p = B.palettes.find(x => x.id === state.palette); const t = B.tokens(p, state.mode);
for (const [k, v] of Object.entries(t)) document.documentElement.style.setProperty('--' + k, v);
document.documentElement.dataset.palette = p.id; document.documentElement.dataset.mode = state.mode; document.documentElement.style.colorScheme = state.mode === 'light' ? 'light' : 'dark';
$('#palette').value = p.id; document.querySelectorAll('[name=mode]').forEach(r => { r.checked = r.value === state.mode; }); $('#state').value = state.demoState;
const qs = `?palette=${p.id}&mode=${state.mode}&state=${state.demoState}`;
$('#designs').innerHTML = designs.map(([file, name, sub, points, sketch], i) => `<article class="design"><h2>${i + 1}. ${name} <span>${sub}</span></h2>${sketch}<ul>${points.map(x => `<li>${x}</li>`).join('')}</ul><div class="actions"><a class="btn primary" href="${file}${qs}">Open ${name}</a><a class="btn" href="${file}${qs}#/sessions/s-01a07cfa">Session view</a><a class="btn" href="${file}${qs}#/launch">Launch</a></div></article>`).join('');
persist();
}
document.addEventListener('change', e => { if (e.target.id === 'palette') { state.palette = e.target.value; apply(); } if (e.target.name === 'mode') { state.mode = e.target.value; state.chosen = true; apply(); } if (e.target.id === 'state') { state.demoState = e.target.value; apply(); } });
$('#notes').addEventListener('input', () => { try { localStorage.setItem('mosaic-wui-notes-v1', $('#notes').value); $('#notes-status').textContent = 'Saved in this browser.'; } catch { $('#notes-status').textContent = 'Storage unavailable. Download your notes before closing.'; } });
$('#download').addEventListener('click', () => { const url = URL.createObjectURL(new Blob([`Mosaic Stack WUI mockup review\nPalette ${state.palette}, mode ${state.mode}\n\n${$('#notes').value || 'No notes yet.'}\n`], {type: 'text/plain'})); const a = document.createElement('a'); a.href = url; a.download = 'mosaic-wui-review.txt'; a.click(); setTimeout(() => URL.revokeObjectURL(url), 1000); $('#announce').textContent = 'Notes prepared for download.'; });
apply();
if (!storageOk) $('#notes-status').textContent = 'Browser storage is unavailable; choices will not persist.';
})();
</script>
</body>
</html>