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]>
119 lines
13 KiB
HTML
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>
|