Atlas HELM — Design Philosophy (Living Doc)¶
🔴 Status: v2.0 · set 2026-05-29 (session
340d5f53Phase 210 mid-arc checkpoint, after the 4-bento arc landed in sessions386fd1f6/d5943817/7d86a59c/1271fa43/57998126) · INTENTIONALLY FLUID. Expected lifespan: Always evolving. Iterate every session that touches HELM visual surfaces. Promoted from: Sush's directive 2026-05-29 — "document everything and add todos so when we move between sessions each session understands this philosophy and we will keep it fluid to make room for evolution — the idea is to make the best tool so that I feel like using and it provides immense value for me to keep going back." Owner: Sush + Atlas, co-designed each session. Atlas writes here; Sush approves direction shifts. 🆕 v2.0 (Phase 210): Mid-arc cold-eye review after the 4-bento system landed (Today / Overview / Books / Customers). New sections §0.5 (checkpoint), §3.6 (eligibility + wedge test), §3.7 (patterns by confidence), §8.5 (implementation debt), §9.5 (bias checks). Rubber-duck pushed back on 7 over-claims; demotions adopted.
0 · Why this doc exists¶
HELM is Sush's daily-driver cockpit. Every session that touches a visual surface (today-tab, overview-tab, customer card, scout card, etc.) MUST read this file first. Without a shared philosophy, sessions drift into "fix what's in front of me" mode and the cumulative result is inconsistency.
This doc is the constitution. The phase queue (~/.copilot/atlas-portfolio-phases.md) is the calendar. Together they make a design system that survives session amnesia.
Cardinal commitment: The goal is to make a tool Sush wants to open. Immense value. Pull, not push. If a design decision doesn't move us closer to that, kill it.
0.5 · Mid-arc checkpoint (Phase 210 · v2.0)¶
After the 4-bento arc landed (Today / Overview / Books × 3 SSPs / Customers), a cold-eye review surfaced three buckets. Future sessions inherit this calibration as the starting point.
Proven (locked, don't re-debate)¶
grid-template-areas(Path A) — designer control + named slots. Composes cleanly. Mobile collapse works. No retreats from this in any of the 4 tabs.- Cold-user wedge per tab — Today=NOW · Overview=BOOK SHAPE · Books=PERSON BOOK SHAPE · Customers=NAMED INDIVIDUALS. The wedge test is what stopped Customers from being a Books clone. See §3.6.
- Fold-not-lose discipline — every dropped section gets FOLDED into a slot (Hero chips, tooltip, coverage strip), never just deleted. Preserves info density without preserving chrome.
- Drill-zone sibling pattern — bento = SURVEY layer (top), drill zone = POWER-USER layer (full-width siblings below: tables, 54-card grids, deep-dive charts).
- Plex Sans family swap — Phase 201 landed cleanly. Plex Serif italic for Atlas brief IS the signature voice move it was meant to be.
- Tab-specific class prefix —
.today-.ov-.bb-.cb-. The Customers.cb-card(not.c360-card) decision saved a click-handler collision. Always pick a fresh prefix when bento'ing over an existing rich card. - Architecture-gate (Rule #5) for layout-shaped phases — for the bento arc specifically, surfacing 3-4 paths BEFORE writing renderer produced zero rework loops. This is reliable WHEN the work is layout/architecture-shaped. Don't claim the gate fires automatically for ad-hoc polish.
Provisional (used in 2-3 of 4 bentos · adopt OR diverge with a reason)¶
- 3-beat Atlas brief structure — Customers cracked it (state → movement/risk → next action, composed at render-time, Plex Serif italic). Overview uses thesis + 3 bullets. Books renders pre-baked SSP insight prose. Today uses
atlas-brief.jsACT TODAY / ON YOUR RADAR. Not universal — yet. Newer bentos can adopt the 3-beat shape; existing ones evolve only if the data shape makes it worth it. - Customer names italicised in cyan — Customers did this. Overview brief uses
<em>with amber. Books escapes raw insight text. Not universal. When the surface mentions named customers, cyan italic is the right choice; not all briefs are name-dense. - Sub-nav ≤9 anchors capped at one row — Overview/Books/Customers all chose 9 (the latter two probably copied Overview's count). Today has no bento sub-nav at all. Promote as "cap at one visual row, ≤9 anchors" — not "exactly 9".
- Sign-filtered delta strips — 3 +gainers + 2 −decliners (Customers movers). Used in Customers; Overview's diff strip is mixed-tone but not sign-filtered. Pattern works when you have a polar dataset.
- Diversity-fill + severity-fill for Top-3 — Overview cracked, Books and Customers reused. Pattern is locked WHERE Top-3 is "ranked-list-of-things-from-a-bucket-pool." Today's hot-pipeline 3 slots are semantically distinct (closing-soon · past-close · stale) so the algorithm doesn't apply.
- Rule #6 probe before renderer — fired explicitly in 202/204/205b, implicit in 205a. 20 min each time. Pattern paid back hours each invocation. Promote to MANDATORY for any new bento; treat as recommended for bento polish phases.
Drifted (we have a problem · needs cleanup)¶
- 🔴 Amber discipline violated across 11 source files.
var(--amber)is currently used as priority numbers, eyebrows, P2 chips, IMMINENT tag, sync-busy state, helm-pill-ok, active nav, scout buttons, hover transforms, focus rings, command buttons. The §5 audit named this in v1.0. We haven't fixed it. Needs a taxonomy audit (Row 211), not a blanket flip — some sites are legitimate stakes, some are pure chrome. See §5 for the 3-bucket classification. - 🟡 Sticky-hero (§6 add-on #1) marked ✅ in v1.5 was a fact-drift bug. Phase 203 shipped sticky-hero, Phase 203.1 hotfixed it, Phase 203.2 REVERTED it (Electron-specific visual bug not reproducible in headless Playwright). Status corrected in §6.
- 🟡 Bento module placement is inconsistent. Today bento lives in
today-tab.js(85KB). Books bento lives inssp-book.js(61KB). Overview bento lives inrender.js(209KB). Only Customers bento got its own module (customers-bento.js, 40KB). The real pain is Overview-in-render.js; Today/Books are tidy-bug not value-bug. See §8.5. - 🟡 Polish-layer "should-it-propagate" question never answered.
data-freshnessink anddata-empty="1"chip-collapse exist only in Today. The right question is not "propagate them everywhere" but "audit applicability per tab" — see §6 for the corrected reasoning.
What 4 bentos taught us about the doc itself¶
This doc was v1.0 BEFORE we shipped any bento. v1.5 added one tab's story-shape table per phase. v2.0 is the first time we're stepping back to ask "which patterns actually GENERALISE?" The honest answer is: fewer than v1.5 implied. Tightening the language here makes the doc more useful, not less ambitious.
1 · Cold-user persona — the "Sush walking up to HELM at 8:42 AM" test¶
Every design decision passes through this filter:
- Who: Sush, Copilot Solution Engineer, MS NZ. Daily-driver — opens HELM first thing morning, mid-day, late-afternoon.
- What he wants in priority order:
- "What do I do RIGHT NOW?" (5-second answer)
- "What's COMING UP today/tomorrow?"
- "What did I MISS?" (only if it matters)
- "What CHANGED since last time?" (delta surface)
- "What's interesting?" (curiosity — Scout, brief insights)
- What he doesn't want: kitchen-sink dashboards · stacked-rectangle uniformity · guilt-trip openings · empty-state noise · amber-overload · prose where data would do.
5-Second Test: When Sush opens any tab, can he get the answer to "what should I do right now?" in 5 seconds? If no, the tab fails the test.
2 · The Master Design Principle — Bento Mosaic¶
"We're not hard set on one type of card — we can have tall cards, rectangular cards, square cards all sitting adjacent to each other but working together to create a master layout. The page looks busy and purposeful and each card has a way of storytelling. Different storytelling will adopt different design but it all coexists and tightly live together like a creeper and a tree and a plant all exist together in harmony." — Sush, 2026-05-29
The principle in one line: Each card has a SHAPE that fits its STORY. Cards puzzle-piece into a master layout, not stack as uniform rectangles.
Why this works:
- Shape = signal. A 2×2 square says "anchor metric." A 4×1 strip says "timeline/flow." A 1×3 tall says "ranked list." A 1×1 chip says "glance only." Cold user reads shape BEFORE content.
- Density = clarity, not noise — when each card earns its shape, busy ≠ cluttered. Pinterest, Bloomberg Terminal, Linear, Apple iCloud all prove this.
- Visual gravity — a large hero card surrounded by smaller satellites feels EARNED. Same hero alone-in-a-column feels arbitrary.
- Ecosystem coexistence — different cards don't compete; they harmonize. Like a tree + creeper + plant in one ecosystem.
References that already do this well:
- Apple iCloud / macOS Sonoma widgets
- Linear's dashboard (Cmd+K + the homepage)
- Vercel's project overview
- Raycast Pro dashboard
- PAC v0.2 cockpit (Sush's reference: Downloads/pac-v02-fullscreen.png)
- Bloomberg Terminal (the data-density extreme)
3 · Story-Shape Mapping — what shape each card wants¶
Today tab¶
| Card | Story it tells | Natural shape | Why |
|---|---|---|---|
| Hero countdown | "MBIE in 4h — THIS is next" | 2×2 anchor square | Gravity well. The single biggest pull. |
| Hero timeline | "Shape of your remaining day" | 4×1 horizontal strip | Time IS horizontal. Sub-card under hero. |
| Top 3 actions | "Do these 3 things" | 1×3 stacked tall card | Ranked list IS vertical. Must be visible without scroll. |
| Atlas brief (voice + actToday) | "Atlas's read on the day" | 2×3 tall narrative card | Prose wants room to breathe. Serif voice (humanist). |
| Hot pipeline (3 signals) | "3 money signals — each distinct" | 3 × 1×1 squares in a row | Each = own story, not bucket. Allow per-card iconography. |
| Needs action mail | "5 threads need your reply" | 1×2 tall list | Vertical list IS the shape. |
| Chrono ribbon | "Next 24h forward" | 1×4 sticky right rail | What it already is. Sticky on scroll. |
| Scout picks | "3 internal repos worth a look" | 3×1 horizontal strip at bottom OR chip teaser at top | Curiosity teaser, not anchor. |
| Missed yesterday | "1 thing slipped" | TINY chrome chip | Not card-worthy. Demote out of hero treatment. |
| Pulse preview | "Top tasks" | FOLD into Top 3 actions | Duplicate of My Tasks tab. |
| Today meetings list | "Time-sorted today" | DROP | Redundant with timeline. |
| DIGEST button | "Generate Friday digest" | CHIP in chrome | Action, not content. |
Outcome: 12 sections → ~8 cards + 2 chrome chips. Composes into a deliberate master grid.
Overview tab (Phase 204 · v4.0.5-overview-bento · 2026-05-29)¶
Cold-user reframe: Overview answers "how is my whole book shaped right now?" (book-level survey, this week, this quarter). Today tab answers "what do I do RIGHT NOW?" (next 24-48h). That division is the wedge — it lets us DROP the duplicate Today block from Overview entirely.
| Card | Story it tells | Natural shape | Why |
|---|---|---|---|
| Hero portfolio | "Here's your book in 3 numbers + chips" | 6×2 anchor | Single biggest pull. Primary 3 (customers · open opps · total value) + secondary chips (util% · idle licenses) + since-snapshot delta strip below |
| Top 3 plays | "3 highest-leverage moves this week" | 3×2 stacked tall | Ranked list IS vertical. Distilled from Top Signals' 6 categories via diversity-first + severity-fill |
| Atlas portfolio brief | "Atlas's read on the whole book" | 3×3 tall narrative | Plex Serif italic — the "Atlas SPEAKING" voice. Light variant (1 thesis + 3 bullets), not wholesale composeBriefing (dense, doesn't fit serif) |
| Diff strip | "What moved since last snapshot" | 9×1 horizontal strip | Compact mode: max 5 chips + "+N more" tail. Compresses the existing diff-grid auto-fit so it fits one row |
| 3 SSP patches (Tam · Riki · Ben) | "Health per book — parallel" | 3 × 4-col row | Each = own story, equal-weight. Stale-insight notice EMBEDDED inside each patch (no separate Atlas SSP commentary section) |
| Portfolio Pulse | "8 cross-tab signals at a glance" | 12×2 full-width block | Slot defines footprint; internal .pulse-grid auto-flows. Don't hardcode 12×2 for forever-8 |
| Pipeline by Stage | "Funnel distribution + per-stage Atlas commentary" | 12×1 strip | Bars want horizontal room |
| Drill zone (BELOW bento, full-width sibling) | |||
| SSP Deep-Dive charts | "Per-customer adoption inside each book" | full-width stacked | Drill, not bento. CSS Grid would force them into a slot they don't fit |
| Portfolio Leaderboard (54 rows) | "Sortable everything" | full-width table | Drill, not bento |
Today block (renderTodayViewSection) |
"Past-close, closing-soon..." | DROP | Duplicate of Today tab; wrong question for this tab |
| Adoption Rollup banner | "8 Copilot footprint numbers" | FOLD into Hero + Pulse | 4 tiles already on Pulse; util% + idle → Hero chips |
| Pipeline KPI tiles | "Book size, opps, total value, pipeline-by-SSP" | FOLD into Hero + Patches | First 3 = Hero numbers; SSP-breakdown = already in patches |
| Atlas SSP commentary (standalone) | "Atlas's read per SSP" | EMBED into each patch | Tighter coupling, no separate section header |
Outcome: 12 sections → 7 bento cards + drill zone with 2 wide surfaces. Sub-nav pills: 9 anchors (Book / Plays / Brief / Diff / SSPs / Pulse / Stages / Deep-dive / Leaderboard).
Implementation pattern: Same grid-template-areas + direct-child-with-grid-area approach as Today bento (§7), but Option B 12-col with NO sticky right rail because (a) Phase 203c sticky-hero bug still open — don't ship a second sticky surface, (b) momentum data already lives in Pulse B2/B3 movers, (c) Overview is survey, not next-move.
Books tab — per-SSP cockpit bento (Phase 205a · v4.0.6-books-bento · 2026-05-29)¶
Cold-user reframe: Books answers "how is THIS one person's book shaped right now?" — same survey shape as Overview, but scoped to one SSP. So Books bento = Overview bento minus the 3-patches row (only one SSP per cockpit). Cleanest pattern transfer in the bento queue. ONE renderBookBentoForSsp called 3× for Tam · Riki · Ben (identical topology, different data).
| Card | Story it tells | Natural shape | Why |
|---|---|---|---|
| Hero (per-SSP) | "Tam's book in 3 numbers + chips" — # customers · # opps · $value + util / idle chips + since-snapshot delta (filtered to this SSP's owned opps) | 6×2 anchor | Same anchor weight as Overview hero |
| Top 3 plays | "3 highest-leverage plays for Tam this week" | 3×2 stacked tall | Distilled from per-customer recs; allows priority-2 fallback for sparse books; category-diverse + severity-fill |
| Atlas brief (per-SSP) | "Atlas's read on Tam's book" — Plex Serif italic prose | 3×3 tall narrative | Extracted from sspInsights[sspName]; lighter chrome than the wholesale renderAtlasCommentary wrap |
| Time-sensitive | "What's hot this week in Tam's book" — compact chips | 9×1 horizontal strip | Format: Past close · 3 · $1.2M · Westpac (count + value + top customer per chip) · max 5 chips + "+N more" |
| Top 3 risks | "3 risks to watch in Tam's book" | 6×1 horizontal | Separate pool from actions (CHURN RISK / ENABLEMENT / SENTIMENT / etc.) · same diversity-fill algorithm |
| Health snapshot | "Quick-glance Tam-book health" | 6×1 row of 3 mini-tiles | idle-license customers · MoM decliners · weak admin posture — counts only, drill via Customers table |
| Stage funnel | "Pipeline by sales stage in Tam's book" | 12×1 wide strip | Full-width bars, scopes to this SSP's owned opps |
| Drill zone (BELOW bento, full-width siblings per cockpit) | |||
| Customers table | Sortable per-customer detail for this SSP | full-width table | Drill, not bento (tables don't bento) |
| All Opps table | Every open opp owned by this SSP | full-width table | Drill, not bento |
Header KPI strip (old renderHeader) |
"7 KPIs at top: customers / licenses / MAU / free / util / opps / pipeline" | FOLD into Hero | Don't duplicate the same numbers above + below bento — slim the header to chrome only |
| Atlas commentary as standalone section | "Atlas brief" | FOLD into bento Brief slot | Same content, lighter chrome |
| Actions+Risks as one combined section | "Recs" | SPLIT into 2 slots | Two distinct stories, two distinct shapes — better than nested columns |
Outcome: 7 sections per cockpit → 7 bento cards + drill zone with 2 wide tables. Sub-nav pills per cockpit: 9 anchors (Hero / Plays / Brief / Time / Risks / Health / Funnel / Customers / All-opps) + COMPACT toggle.
Architectural note (compact toggle): Bento cards use .bb-card class (NOT .cockpit-section), so the existing COMPACT toggle only folds drill-zone tables — sensible "show me less" behaviour. Don't reuse .cockpit-section for bento cards; that's what made the COMPACT exemption clean.
Customers tab — survey-of-names bento (Phase 205b · v4.1.0-customers-bento · 2026-05-29)¶
Cold-user reframe: Customers answers "WHICH customers right now?" — every card surfaces NAMED individuals (Westpac · NZTA · Police) rather than aggregates. That's the wedge that earns this tab its own bento vs Overview (aggregates) and Books (per-SSP survey). Cold user lands and reads the NAMES first.
| Card | Story it tells | Natural shape | Why |
|---|---|---|---|
| Hero | "54 customers · 26 active · $720M + the ONE customer of the week (top mover by name)" | 6×2 anchor | Single biggest pull. Lands a NAME (cotw) inside the anchor + 3 primary numbers (customers / open opps / total value) + util/idle/Lynx-coverage chips + since-snapshot delta |
| Top 3 to call | "Westpac · BNZ · Genesis — and why (top rec per name, category-diverse)" | 3×2 stacked tall | Named individuals, not aggregates. Mirrors Overview top-3 algorithm (priority-1 first, category-diverse pass 1, fill pass 2, priority-2 fallback) but every row = ONE customer not ONE signal |
| Atlas brief (customer-set voice) | "Atlas's read on your customer set as individuals — 3-beat narrative" | 3×3 tall narrative | Plex Serif italic. Composed at render-time (no pre-baked atlasInsight in current dist). 3-beat structure (rubber-duck #12): portfolio state → movement/risk → next action. Names italicised in cyan |
| Adoption movers strip | "↗ NZTA +259% · ↗ Waikato +145% · ↘ Spark −18% · ..." | 9×1 horizontal | Sign-filtered chips (rubber-duck #8): top 3 positive gainers + top 2 negative decliners; "+N more" tail |
| Whitespace leaders | "5,053 free Chat — NZ Police · 4,232 — MSD · ..." | 6×1 horizontal | Distinct from Top-3 (rubber-duck #7): pure free-Chat conversion pool by NAME, top 5 |
| Health tiles | "3 NAMED red-flag tiles: idle queens (top: NZTA · 240) · decliners (top: X · −Y%) · weak admin (top: Z · N%)" | 6×1 row of 3 mini-tiles | Each tile shows COUNT + TOP-1 NAME. Weak admin uses classifyAdminPosture.enabledScore not just flagAdminRisks (rubber-duck #9) |
| Lynx-coverage strip | "Trust this tab — 52/54 with Lynx · 51 momentum · 52 free chat · 37 idle · 2 dark" | 12×1 strip | Honesty layer (rubber-duck #13). Industry/geo data = 0 in current snapshot, so this slot preserves the candor the old .c360-overview-caveat banner used to carry. Each chip tinted by completeness tone (full=green, partial=amber, empty=muted, dark=red) |
| Drill zone (BELOW bento, full-width siblings) | |||
.c360-controls (existing) |
Power-user sort + filter chrome | full-width | Stays untouched. Sub-nav points at #c360-controls so existing JS sort/filter handlers keep working |
.c360-grid 54 cards (existing) |
Rich per-customer detail (adoption funnel, momentum, conversion, penetration, admin posture, top rec, Atlas note, agent toolbar) | full-width grid | Stays untouched — the workhorse cards remain visually unchanged. Drill, not bento |
Old .c360-overview-bar (6 stats) |
totals | FOLDED into Hero chips | Lynx-coverage already on Coverage strip; util/idle already on Hero chips |
Old .c360-overview-caveat banner |
data freshness note | FOLDED into Hero title tooltip + Coverage strip | Same honesty, redistributed where each card lives |
Outcome: 1 overview-bar + 1 caveat + 1 controls + 54 cards → 7 bento cards + drill zone (controls + 54 cards). Sub-nav pills: 9 anchors (Hero / Call / Brief / Movers / Whitespace / Health / Coverage / Filters / Grid). No COMPACT toggle (rubber-duck #3) — Customers tab doesn't have .cockpit-section semantics so a COMPACT would be a no-op.
Implementation pattern: Same grid-template-areas 12-col CSS Grid as Books/Overview. New src/customers-bento.js module exports renderCustomersBento(customers, snapshot, opts) + renderCustomersSubnav() + CUSTOMERS_BENTO_CSS. Bento cards use .cb-card chrome (NOT .c360-card — rubber-duck #5: the existing rich card has a global click-to-account-page handler bound by class; new bento cards must not inherit that). Mobile collapse @1100px to single column; sub-collapse @640px stacks the 3 hero numbers vertically (Plex Sans Condensed 36px $247M doesn't fit 91px columns).
Three Rule #6 probe wins (data shape verified BEFORE writing renderer):
1. Industry/geo data = 0/54 in current snapshot → slot 7 became Lynx-coverage strip instead (caught at probe stage, no wasted code)
2. atlasInsight = 0/54 → brief composed at render-time using a 3-beat structure (not pre-baked LLM prose)
3. 52/54 with Lynx · 51 MoM · 52 free chat · 37 idle confirmed → 6 of 7 slots have real signal to render
3.5 · When NOT to bento (added Phase 205a · 2026-05-29)¶
Not every tab should be bento. The bento mosaic is for survey tabs — where the cold-user question is "what's the shape?" and the answer-shape is a deliberate composition of differently-sized cards.
Tabs that ARE survey-shaped (and SHOULD bento): - Today — "what do I do RIGHT NOW?" - Overview — "how is my whole book shaped?" - Books (per SSP) — "how is this person's book shaped?" - Customers — "how is my customer set shaped?" (Phase 205b queued) - Activity — "what's flowing through my channels?" (Phase 205c queued — though may need a different bento flavour for time-stream content)
Tabs that are NOT survey-shaped (and should NOT bento): - Pipeline (Opportunities) — power-user sortable/filterable table. The cold-user question is "let me filter and sort to find specific opps." Forcing bento onto a 1,408-row table is anti-pattern — tables ARE tables. (Phase 205d will polish chrome to match bento tabs visually without bento'izing.)
The smell signal that a tab shouldn't bento: if the dominant content is ONE big sortable/filterable thing (table, list, feed), bento adds chrome without adding clarity. Polish the table's own chrome instead.
Counter-test: if the tab has 5+ distinct stories that want differently-sized real estate, bento is the right tool. If it has 1 dominant story and the rest are filter widgets, leave the table alone.
This insight was banked at Row 205 split (the original monolithic "bento-rest-tabs" row got split into 205a/b/c/d when surfacing that Pipeline doesn't fit). The architecture-gate (Rule #5) caught it; without that gate we'd have forced bento on a table.
3.6 · Bento eligibility + cold-user wedge test (added Phase 210 · v2.0)¶
§3.5 said when NOT to bento. This is the positive companion: what EARNS a tab its own bento.
The 2-question gate (both must be YES)¶
- Cold-user wedge test: Does this tab answer a question DIFFERENT from every other already-bento'd tab?
- Today = "what do I do RIGHT NOW?"
- Overview = "how is my whole book shaped?"
- Books (per SSP) = "how is THIS one person's book shaped?"
- Customers = "WHICH customers right now?" (every card surfaces NAMED individuals — wedge that prevented this being a Books-clone)
-
If the new tab's question collapses to one of the above, it's duplication. Polish the existing tab instead.
-
Composition test: Does the tab have 5+ distinct stories that want differently-sized real estate?
- Story = a coherent answer to a sub-question (e.g. "next meeting," "what moved this week," "who needs a call," "what's flowing through the funnel").
- If 1 dominant story + filter widgets → table/feed pattern, not bento (per §3.5).
Honest failure mode of the wedge test¶
The wedge test is a decision aid, not a guarantee. Tabs existed before bento. The wedge for Today/Overview/Books was retrofit during the bento exercise; only Customers had its wedge discovered live during architecture-gate. So treat the wedge as the test that prevents bad new bentos, not as proof that every existing bento is essential. The Activity-tab decision (Phase 205c queued) is the next real wedge check — "what's flowing through my channels?" may or may not earn a bento; it might be feeds-shaped (which we said in §3.5 don't bento).
What the drill zone is for (the relief valve)¶
Bento is the SURVEY layer. The drill zone (full-width siblings BELOW bento) is the POWER-USER layer. Every bento tab so far has one:
- Today — chrono ribbon (sticky right rail, not a sibling — different pattern)
- Overview — SSP deep-dive charts + 54-row leaderboard
- Books — Customers table + All Opps table (per cockpit)
- Customers — .c360-controls + 54 .c360-card grid (untouched workhorse)
The drill zone is where TABLES and 54-card grids live. Bento isn't trying to replace them; it's trying to make them findable by surfacing the shape above.
3.7 · Patterns by confidence level (added Phase 210 · v2.0)¶
A correction layer over §3 and §6. Use this to decide what to apply when you start a new HELM surface.
Locked (apply by default · don't re-debate)¶
| Pattern | Where verified |
|---|---|
grid-template-areas with named slots (Path A) |
All 4 bentos |
Direct-child grid anatomy (each slot = own <section>, not wrappers) |
Overview rubber-duck #1, all 4 bentos |
| Fold-not-lose for dropped sections | All 4 bentos |
| Drill-zone sibling (full-width under bento) | All 4 bentos |
Tab-specific class prefix (.today- .ov- .bb- .cb-) |
All 4 bentos; Customers prevented click-handler collision |
| Mobile collapse @1100px (sub-collapse @640px for hero numbers) | All 4 bentos; Customers found the 640px need at smoke time |
| Cold-user wedge test before adding a new bento tab | Customers (the test that worked live) |
| Rule #5 architecture-gate for bento phases | 4-of-4 zero rework loops |
| Rule #6 data-shape probe before renderer | Mandatory; pays back hours per invocation |
| Inline phase-local CSS in renderer module | Pattern from Today, repeated in Overview/Books/Customers (matches phase-local convention) |
| Each bento renders standalone (no cross-tab data deps) | Build-time data → static HTML model |
Provisional (use unless you have a reason not to · note the reason if you diverge)¶
| Pattern | Where verified | When to diverge |
|---|---|---|
| 3-beat Atlas brief (state → movement → action) | Customers cracked, composable at render-time | When you have pre-baked LLM prose (Books) OR a domain-specific structure (Today's ACT/RADAR) |
| Customer names italicised in cyan | Customers brief | When the surface isn't name-dense (Overview is signal-dense, not name-dense) |
| Sub-nav anchors cap (~7-9, one visual row) | Overview/Books/Customers all 9 | Today has none and works fine for a 4-card-row layout |
| Sign-filtered delta strips (mixed +/−) | Customers movers | When dataset is single-direction (e.g. only stale events) |
| Diversity-fill + severity-fill for Top-3 | Overview/Books/Customers | When the 3 slots are semantically distinct already (Today's hot-pipeline 3) |
| Slim chrome-only header (KPIs folded into Hero) | Books (cockpit-head-slim) |
When the tab needs persistent KPI tiles for above-the-fold (e.g. trading dashboards) |
Sub-nav anchors with scroll-margin-top: 96px |
Overview/Books/Customers | When tab has no sub-nav (Today) — N/A, not an exception |
Not universal (don't promote · these are context-specific patterns)¶
| Pattern | Where used | Why not universal |
|---|---|---|
data-freshness ink (fresh/ok/stale/unknown) |
Today only | Only useful when cards have independent recency sources. Overview/Books/Customers cards all share one snapshot → ink would imply false precision. Audit per-card before propagating. |
data-empty="1" chip-collapse |
Today single-row hot/scout slots only | Scoped to slots where empty == nothing-to-show. Multi-row slots keep card shape per §3 so bento composition doesn't break on quiet days. |
| Sticky hero | NOT shipped (Phase 203.2 revert) | Open Electron-specific bug. Don't re-enable without Phase 203c investigation. |
| COMPACT toggle | Books only (folds drill-zone tables) | Books has .cockpit-section semantics that survive folding. Customers explicitly chose NO COMPACT (no .cockpit-section → it would be a no-op). Today has no .cockpit-section semantics in bento area. |
| Per-card sparklines | Pending data layer (Row 203b) | Needs time-series scrape; current data is per-snapshot only. |
| Right-side sticky chrono rail | Today only | Today's bento has a 9-col + 280px layout for the rail. Overview explicitly chose NO right rail (momentum already in Pulse). Don't add chrono pattern to other tabs without a 24h-forward dataset. |
How to use this table¶
When you start a new HELM surface, ask in order: 1. Locked patterns → apply by default. 2. Provisional patterns → apply unless you can write a one-line reason in the row spec for diverging. 3. Not-universal patterns → don't pick up by default. If you think you need one, prove the context fit (e.g. "this tab has independent recency per card, so freshness ink earns its place").
4 · Typography System — IBM Plex Sans family + JetBrains Mono¶
Current (v1 — pre-bento)¶
Target (v2 — bento-ready)¶
--sans: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
--sans-cond: "IBM Plex Sans Condensed", "IBM Plex Sans", sans-serif;
--serif: "IBM Plex Serif", Georgia, serif;
--mono: "JetBrains Mono", "Cascadia Code", "Consolas", monospace;
Why IBM Plex Sans over Inter¶
- PAC uses it. Sush already loves PAC's feel. Don't ship a different sans than PAC.
- More personality. Inter is the default SaaS sans (Linear, Vercel, Figma, GitHub, every YC startup) — neutral to the point of generic.
- Engineered voice. Plex was designed by Bold Monday for IBM as their global voice — quietly humanist, slightly mechanical, distinctive at small sizes.
- Full family. Sans + Sans Condensed + Serif + Mono all coexist visually. We get a typographic SYSTEM, not a single face.
- Tabular figures + true italic — built in, no opt-in needed.
Family deployment plan¶
| Surface | Face | Weight | Use |
|---|---|---|---|
| Body / UI / card prose | IBM Plex Sans | 400 | Default text |
| Card titles / hero countdown digits | IBM Plex Sans Condensed | 600/700 | Tighter glyph, more impact at scale |
| Hero countdown numbers | IBM Plex Sans Condensed | 800 + tabular-nums | Maximum gravity |
| Eyebrows / tags / status pills | JetBrains Mono | 400/700 uppercase | "Data" voice |
| Code / verdicts / signal IDs | JetBrains Mono | 400 | Code voice |
| Atlas brief narrative | IBM Plex Serif italic | 400 | "Authored" voice — distinct from data feel |
| Numbers (money, counts, ages) | IBM Plex Sans tabular-nums | 500 | Aligned columns |
The Plex Serif for atlas-brief is the signature move — it tells the cold user "this is Atlas SPEAKING, not data being shown."
Font-weight contrast rules¶
- 300 (extra light) — explicitly reserved (use sparingly, decorative only)
- 400 — body default
- 500 — emphasis inline, tabular numbers
- 600 — card titles, hot signals
- 700 — eyebrows, tags
- 800 — hero numbers ONLY
5 · Color Discipline — Amber reserved for STAKES¶
Current palette (B2 production, locked at v3.0.0-foundation):
| Token | Hex | Reserved for |
|---|---|---|
--amber |
#c89853 |
STAKES SIGNAL ONLY — customer meeting imminent, money at risk, deadline urgent |
--cyan |
#7a9aab |
Customer / account identity (cyan customer names, cyan-bordered EXTERNAL meetings) |
--bg |
#050507 |
Page background (near-black) |
--panel |
#0f0f12 |
Card background tier 1 |
--panel-2 |
#18181c |
Card background tier 2 (internal/focus blocks) |
--border |
#1e1e23 |
Strong borders (interactive elements) |
--border-soft |
#15151a |
Soft borders (chrome dividers — most cards) |
--text-bright |
#e8e8e0 |
Hero text, active state |
--text |
(slate) | Body |
--text-dim |
#777771 |
Tertiary, eyebrows |
--text-muted |
#545450 |
Quaternary, empty-state placeholders |
--ink-green / --red |
(TBD) | Reserved for "yes/no" semantic states (Pulse status dot, "live" tag) |
The "Amber Discipline" rule¶
When everything is amber, nothing is amber. Reserve amber for the SINGLE class of "customer × time × money at stake." If you find yourself adding var(--amber) to a non-stakes signal, use a slate/cyan/text-bright token instead.
Amber taxonomy (added Phase 210 · v2.0)¶
Spot-check of var(--amber) usages across 11 source files (today-tab, ssp-book, customers-bento, render, scout-tab, my-tasks-tab, engagement-tabs, atlas-brief, digest-tab, prep-packet, pulse-preview, feedback-buttons). The audit confirms §5's prediction: amber is overused. Three buckets:
| Bucket | Examples | Verdict |
|---|---|---|
| A — Legitimate stakes signal | .hero-countdown-tag-imminent, countdown digits, customer timeline block, hot-pipeline value, warning/partial coverage states, P2 priority chip when actually P2 |
Keep amber. This is what the token is for. |
| B — Semantic warn/partial/stale | .bb-time-chip-warn, .cb-cov-chip-partial, .cb-health-tile-warn, helm-pill-ok (when "ok" means aging data) |
Move to a --warn token (or rename amber to a stakes-only token + introduce --warn). Currently aliased to amber, conceptually distinct. |
| C — Chrome / nav / decorative / generic | .today-section-eyebrow, .helm-sub.active, .today-scout-ai, .today-weekly-digest, hover/focus rings, .today-action-pri (default amber even when P1), command-button colors, scout-pager-all |
Drop amber. Use slate ladder (text-bright / text / text-dim) or cyan for identity. |
The current cumulative effect is that opening HELM presents an amber-saturated visual field where the IMMINENT customer meeting can't out-shout the active nav pill. Bucket C is the worst offender by volume.
What Row 211 should do (not a blanket flip)¶
DON'T: sed-replace var(--amber) everywhere. That breaks bucket A and B sites.
DO: classify each ~80 var(--amber) site into A / B / C. Bucket A: keep. Bucket B: introduce or use a --warn token (semantic), keep the same hex for now if needed. Bucket C: flip to slate ladder or cyan per the cyan-discipline rule.
Acceptance: after Row 211, opening HELM should produce visible amber ONLY in legitimate stakes contexts. The IMMINENT tag stands out again because nav/eyebrows/buttons stop competing with it.
The "Cyan Discipline" rule¶
Cyan = customer identity. If a token is referring to a customer (name, account, TPID), cyan. Otherwise not.
5.5 · WCAG Accessibility — token contrast targets (added 2026-06-10)¶
🔴 Rule (locked): every text token in theme.css must hit at least WCAG AA (4.5:1) contrast on --bg. --text-bright should hit AAA (7:1). --text-muted is the floor token — if it's below AA, the whole "muted ladder" is broken because there's no token below it that can be content.
Why this rule exists¶
The original "TARS muted ladder" philosophy (set Phase 121, comment in theme.css) said: "only the active item lights up; everything else gets out of the way." This produced --text-muted #545450 at 2.68:1 on --bg #050507 — a hard WCAG FAIL. Sush flagged readability strain on 2026-06-10 after using HELM heavily for FY27 prep.
Root cause class: "Aesthetic intent + token defaults can converge on values that violate accessibility floor. The philosophy is right (muted hierarchy); the specific hex values were wrong." This is a Rule #11 class to remember — every new token that ships needs a contrast pass.
Token contrast budget (locked 2026-06-10)¶
| Token | Role | Hex | Contrast on --bg #000 |
WCAG | Notes |
|---|---|---|---|---|---|
--text-bright |
Hero / NOW signals | #e8e8e0 |
17.2:1 | AAA | Reserve — imminent meeting, hot risk, urgent email |
--text |
Default body text | #a4a49d |
8.5:1 | AAA | Main content reading layer |
--text-dim |
Secondary metadata | #9c9c92 |
7.7:1 | AAA | Subtitles, secondary labels, evidence text |
--text-muted |
Tertiary, separators | #7c7c75 |
5.1:1 | AA | Footnotes, "·" separators, faint chrome |
Promotion to --text-bright requires justification: what makes THIS item the NOW signal? If everything goes bright, nothing is bright. Cap usage at <10% of text on screen.
Demotion below --text-muted is FORBIDDEN. If a future session wants to add a --text-faint or --text-ghost token below 5:1, it must justify against this rule. The "muted ladder" cannot include illegible steps.
The "Pure black bg" choice (locked 2026-06-10)¶
--bg: #000000 (was #050507 since Phase 121). Pure black instead of near-black because:
1. All text contrasts measurably improve (5.1 → 5.1, 7.7 → 7.7, 8.5 → 8.5, 17.2 → 17.2 vs slightly lower)
2. Surface panels (--panel #0f0f12, --panel-2 #18181c) gain more visible lift — the card-on-canvas pattern reads stronger
3. Matches the "TARS console" aesthetic intent — a purpose-built tool, not a window on a desktop background
4. OLED battery savings (irrelevant for desktop but a free win)
Tradeoff accepted: some designers consider pure black harsh. Counter: HELM is a tool, not an entertainment surface — function over comfort. If it strains eyes in long sessions we can pull back to #0a0a0c later (still WCAG-compliant for all current tokens).
When evolving tokens¶
Run the contrast check before shipping. Probe pattern:
// node scripts/probes/contrast-check.cjs (write this when needed)
function ratio(bg, fg) { /* WCAG 2.1 formula — see fy27 session 2026-06-10 */ }
console.log(`--text-muted on --bg: ${ratio('#000','#7c7c75')} (AA = 4.5)`);
If a session changes any text token or --bg, add the contrast verification to the BUILD-LOG entry. Future-Atlas should be able to read the BUILD-LOG and know the WCAG status of every change.
Companion file¶
atlas-portfolio/styles/theme.css lines 21-50 (the :root block) is the source of truth. Comments in the file repeat the targets above so the constraint is locally visible at the edit site.
6 · Better-than-asked design moves (queued for future phases)¶
These are NOT in v1 bento. They're the evolution path. Status updated v2.0 (Phase 210) — sticky-hero correction + propagation reasoning.
- Sticky hero column —
position: stickyon hero card so it stays visible while satellites scroll. ❌ REVERTED. Phase 203 shipped, Phase 203.1 hotfixed, Phase 203.2 reverted due to Electron-specific visual bug (hero moving with scroll + overlapping below; not reproducible from headless Playwright). Open at Row 203c sticky-hero-investigation — needs HELM-side DevTools to diagnose. Do not re-enable without fix. - Cards that grow/shrink with content — empty needs-action collapses to chip; full one expands. ⚠️ PARTIAL: Today only. Scoped to single-row hot/scout slots per §3.7 "not universal" — applying everywhere risks breaking bento composition. Per-tab applicability audit needed before propagating (Row 212).
- Mini sparklines INSIDE cards — hot pipeline gets 1-line WoW trend; scout gets star-momentum line. ⏸ DEFERRED to Row 203b. Rule #6 probe found no time-series data exists; building data layer first.
- "Pinned" pattern — Sush drag-pins a card to a pinned zone. Persists per-day via localStorage. Queued (Row 208 in v0.4 numbering; needs renumber).
- Card-level freshness ink — thin colored top-border per card (fresh/stale/unknown). Micro-status without real estate. ⚠️ PARTIAL: Today only. Per §3.7, propagating to Overview/Books/Customers would imply false precision because their cards share one snapshot's recency. Per-tab applicability audit needed (Row 212): a tab earns freshness ink only when its cards have independent recency sources.
- Two-state cards — click to expand 1×1 → 2×2 with detail. Click again to collapse. ⚠️ PARTIAL: inline drawer (Phase 207, v4.0.6-cross-card, 2026-06-01). Shipped as inline detail drawer (card grows vertically inside its grid slot via hidden
<div class="card-drawer">revealed by[data-expanded="1"]on parent), not literal 1×1→2×2 grid resize. Rationale: literalgrid-column/row spanoverride ongrid-template-areasslots cascades layout bugs and breaks bento composition (§3). Inline drawer preserves layout integrity. Literal 2×2 deferred to Phase 207b if wanted. - Cross-card hover halos — hover Westpac on Hot Pipeline → highlights Westpac everywhere (timeline block, needs-action row, hero if applicable). Bloomberg Terminal pattern. ✅ SHIPPED Phase 207 (v4.0.6-cross-card, 2026-06-01). JS event-delegation on
[data-cross-card-target="1"][data-customer-tpid]; CSS.cross-card-haloadds subtle cyan outline +--cyan-glowbox-shadow (composes additively with existing freshness ink). pointerover/pointerout with relatedTarget churn-guard avoids flicker between same-customer cards. focusin/focusout for keyboard. Top-3 cards intentionally excluded (atlas-brief prose lacks structured customer — see Phase 207 BUILD-LOG follow-ups for plumbing). Scout cards intentionally excluded (no customer association — MSFT internal repos). Today-tab only; cross-tab focus is Phase 209 (tab-to-tab-context). - Quiet-day creative space — ≥3 cards empty → grid collapses into 1 "// HORIZON CLEAR" panel with "go deep on X" suggestion. Queued.
- "SINCE last open" delta strip — already exists at top; could be deeper (per-card delta hints). Time-aware greeting chip ✅ Phase 203 shipped (5 NZ-wallclock brackets); per-card delta hints remain queued.
- Tab-to-tab context preservation — selecting Westpac on Today carries to Customers tab. Queued.
7 · Implementation pattern — CSS Grid grid-template-areas (Path A)¶
The bento layout is built with explicit grid-template-areas per tab, not auto-flow. Two reasons:
- Designer control. Path A gives us deliberate composition. Each card has a NAMED HOME.
- PAC uses it. Sush already loves how PAC composes. Don't break what works.
Today tab — proposed master grid¶
12-col × N-row · 16px gap · max-width 1400px · 280px sticky right rail
┌──────────────────────────────────┬──────────────┐
│ HERO (col 1-6, row 1-2) │ │
│ │ │
├──────────────────────────────────┤ CHRONO │
│ TOP-3 (col 7-9, row 1-2) │ RIBBON │
│ │ (col 10-12,│
├──────────────────────────────────┤ row 1-N │
│ TIMELINE (col 1-9, row 3) — strip │ sticky) │
├────────────┬────────────┬────────┤ │
│ HOT-1 │ HOT-2 │ HOT-3 │ │
│ (col 1-3) │ (col 4-6) │ (col 7-9)│ │
├────────────┴────────────┴────────┤ │
│ NEEDS-ACTION (col 1-5, row 5-6) │ │
│ │ │
├──────────────────────────────────┤ │
│ ATLAS-BRIEF (col 6-9, row 5-6) │ │
│ serif italic, narrative voice │ │
├──────────────────────────────────┤ │
│ SCOUT-1 │ SCOUT-2 │ SCOUT-3 (row 7)│ │
└──────────────────────────────────┴──────────────┘
[missed chip in chrome top right]
CSS skeleton:
.today-grid {
display: grid;
grid-template-columns: repeat(12, 1fr) 280px;
grid-template-areas:
"hero hero hero hero hero hero top3 top3 top3 . . . chrono"
"hero hero hero hero hero hero top3 top3 top3 . . . chrono"
"timeline timeline timeline timeline timeline timeline timeline timeline timeline . . . chrono"
"hot1 hot1 hot1 hot2 hot2 hot2 hot3 hot3 hot3 . . . chrono"
"needs needs needs needs needs brief brief brief brief . . . chrono"
"needs needs needs needs needs brief brief brief brief . . . chrono"
"scout1 scout1 scout1 scout2 scout2 scout2 scout3 scout3 scout3 . . . chrono";
gap: 16px;
max-width: 1400px;
}
.today-hero { grid-area: hero; }
.today-top3 { grid-area: top3; }
.today-timeline-card { grid-area: timeline; }
.today-hot-1 { grid-area: hot1; }
/* ... etc ... */
.today-chrono { grid-area: chrono; position: sticky; top: 80px; }
Mobile/narrow-viewport graceful collapse¶
@media (max-width: 1100px) {
.today-grid {
grid-template-columns: 1fr;
grid-template-areas:
"hero" "top3" "timeline"
"hot1" "hot2" "hot3"
"needs" "brief"
"scout1" "scout2" "scout3"
"chrono";
}
}
8 · Risks & guardrails¶
- 🚨 Don't propagate to other tabs in same phase. Pilot on Today only. Validate. Then propagate.
- 🚨 Card-content fit matters. A 1×3 tall card with 1 row of content looks broken. Set MIN-content thresholds per card; if not met, card disappears OR uses a minimum-content placeholder.
- 🚨 Mobile collapse is non-negotiable. Electron's resizable window means narrow widths happen. Always test the 1-column fallback before shipping.
- 🚨 Don't kill the regression suites. Each new card class needs smokes (verifying it renders / hides correctly). Add to
smoke-bento-today.mjsetc. - 🚨 Standing Rule #1 (scope): M365 / Copilot / Agent 365 ONLY. Bento is design-system work, not scope expansion.
- 🚨 Rule #7 (Render-is-Not-Done-Until-HELM-Shows-It): every bento phase ends with
node scripts/build.mjs+ mirror to installed HELM + visual confirmation in HELM (Sush). - 🚨 Don't let Inter and Plex coexist mid-migration. When swapping fonts, do it cleanly per tab — partial-state HELM looks worse than either old or new.
8.5 · Implementation debt surfaced at Phase 210 checkpoint¶
Three pain points worth naming, with priority calibrated to user-value not tidy-code.
High pain — render.js is 209KB and Overview bento is inside it¶
Overview bento added ~30KB of renderer + CSS to render.js (already the largest file at 209KB). Future Overview iterations get harder, and any non-Overview change in render.js (which orchestrates the whole HTML composition) risks accidentally touching bento code.
Resolution path: extract Overview bento → src/overview-bento.js exporting renderOverviewBento, renderOverviewSubnav, OVERVIEW_BENTO_CSS. Mirror the Customers pattern. Pure refactor, no visual change. ~2h.
Medium pain — duplicated bento CSS patterns across 4 files¶
Each bento renderer ships its own copy of: bento-card chrome (border/border-soft, panel/panel-2 fill, scroll-margin-top, mobile collapse), eyebrow styling, subnav pill styling, drill-zone divider. ~150-200 lines repeated 4 times.
Resolution path: extract a styles/bento-base.css with the shared chrome tokens + .bento-slot base class + .bento-subnav pattern. Each tab's <X>_BENTO_CSS becomes only its slot-specific styling. Saves ~400-600 lines net + makes the next bento tab (Activity, if it ever bentos) cheap to add.
Low pain — Today/Books bento extraction¶
Today bento lives in today-tab.js (85KB). Books bento lives in ssp-book.js (61KB). Both files are functional and the extraction is tidy-bug, not value-bug. Defer until next functional touch on those tabs. When you next add a feature inside today/books bento, extract as part of the same phase. Don't spend a refactor session on this alone.
Why this section exists¶
The rubber-duck at Phase 210 plan stage pushed back on "extract all 3 because Customers did it." That's tidy-code reasoning, not value reasoning. The honest priority order is: fix the file that hurts (render.js), share the chrome that duplicates (bento-base.css), leave the rest until you have a reason to touch them.
9 · The Iteration Mindset¶
Per Sush's directive: "we will constantly iterate this."
This doc is v1. Expect v2/v3/v10. Each session that touches HELM design should: 1. Read this doc first. 2. Apply the principles to the current task. 3. If a principle doesn't hold or a new pattern emerges, EDIT THIS DOC. Note the date + version bump. 4. Update the phase queue if the change opens new work.
What this doc is NOT: - Not a finished spec. It's a SHARED REFERENCE. - Not a contract — Sush can override any principle at any session start. - Not exhaustive — patterns we haven't tried yet aren't here yet.
What this doc IS: - The thing future-Atlas reads when Sush says "polish the X tab." - The thing that prevents session amnesia from causing visual drift. - The thing that turns 50 sessions of small fixes into a coherent system.
9.5 · Bias checks before promoting a pattern (added Phase 210 · v2.0)¶
Atlas typically writes both the philosophy AND the bentos themselves. That's a conflict-of-interest in self-review. Before adding a new "principle" to §3.7 "locked" or §6 "shipped", run this checklist:
- Coverage test — Am I promoting a pattern used by all 4 bentos, or only 2? If 2-3, it goes in §3.7 "provisional" not "locked."
- User-value test — Is this a user-value issue (Sush sees / uses / benefits) or a tidy-code preference (only I notice)? Tidy-code goes in §8.5 with priority "low," not in §3.7.
- Regression-risk test — If I propagate this, what could break? If the answer is "nothing visible, just code-paths" → it's tidy-bug, defer.
- Sush-validation test — Did Sush HELM-confirm the outcome, or did smoke just pass? Smoke green ≠ user-validated. If only smoke validated, mark "RC pending HELM" not "shipped."
- Universality test — Does the pattern survive Activity (feeds) / Pipeline (table) / Digest (single-stream)? Or is it survey-tab-only? Survey-only patterns go in the per-tab table in §3, not in §3.7.
- Honesty test — Was the pattern discovered during a phase, or retrofitted in the writeup? Retrofit framing is fine for a single decision (Customers wedge was a real discovery; Today/Overview/Books wedges were retrofit), but the doc should say so.
If a candidate fails 2+ checks, demote or drop. The doc's authority depends on its accuracy.
10 · Change log¶
| Date | Session | Author | Change |
|---|---|---|---|
| 2026-05-29 | 386fd1f6 |
Atlas | v1.0 — initial philosophy doc. Bento mosaic principle + IBM Plex Sans typography + Today tab story-shape mapping + Path A grid-template-areas + 8 better-than-asked queued features + amber/cyan discipline rules. Promoted from Sush's 2026-05-29 directive. |
| 2026-05-29 | 7d86a59c |
Atlas | v1.2 — Phase 203 polish-layer notes folded into §6 add-ons. (a) Sticky hero implementation requires both align-self: start AND min-height (220px on hero kept the anchor presence — without it the 2-row grid span lets content-sized hero shrink visually too much). Mobile @1100px disables sticky to avoid a pinned wall in single-column layout. (b) Freshness ink uses box-shadow: inset 0 2px 0 instead of border-top: 2px solid — same visual but no box-model impact, and the inset shadow doesn't fight the existing 1px border. Tokens reused (no new colors). Degraded PULSE manifests (overallStatus !== "complete") coerce fresh-age to "unknown" so the ink doesn't falsely vouch for a half-failed refresh. The "ok" tier (2-12h) has NO ink — absence = good news (Toyota Production System pattern). (c) Empty-card chip-collapse is SCOPED to single-row slots (hot/scout) only; multi-row named-area cards (top3/needs/brief) keep their layout shape per §3 (placeholder cards stay card-shaped to keep bento composition intentional on quiet days). (d) Sparklines DEFERRED to Phase 203b — Rule #6 probe found scout momentum is a single computed score with no time-series, and hot pipeline has no WoW value-trend stored. Building the data layer first (203b) before rendering. (e) Time-aware greeting chip is build-time — refreshes on every PULSE rebuild; acceptable for daily-driver pattern. New helpers computeFreshness + computeGreeting are unit-tested with fixed timestamps in smoke-today-bento-polish.mjs to avoid time-of-day flakes. |
| 2026-05-29 | 1271fa43 |
Atlas | v1.3 — Phase 204 (Overview bento) added a per-tab story-shape table in §3 (now grouped as "Today tab" + "Overview tab" sub-sections). Architecture-gate decision: Option B (12-col, no sticky right rail) picked over Option A (9-col + 280px sticky momentum rail). Two reasons logged: (1) Phase 203c sticky-hero bug is still open — don't ship a second sticky surface until we understand why the first one broke (Electron-specific, not reproducible from CLI); (2) momentum information already exists in Pulse B2/B3 (top movers ↑↓) — extracting to a rail duplicates without adding. Rubber-duck consulted at plan stage — caught 11 blind spots, all adopted: direct-child grid anatomy (each slot = own <section>; SSP patches split into 3 named children, never wrap .ssp-patch-grid), top-3 scoring (category-diversity pass first then severity-fill, not naive priority×magnitude), diff strip compact mode (max 5 chips + "+N more" tail), HELM-gated tag (RC only until Sush confirms in HELM), Hero hierarchy (primary 3 + secondary chips, not 5 equal-weight), brief lighter variant (1 thesis + 3 bullets, NOT wholesale composeBriefing), Pulse internal flex (slot defines footprint, .pulse-grid auto-flows), drill zone sibling not child, CSS inline in render.js (matches Today phase-local convention), subnav anchors on cells + scroll-margin-top: 96px, stale-insight warning preserved (embedded inside patches). NEW renderers: renderOverviewHero · renderOverviewTop3 · renderOverviewBriefCard · renderOverviewDiffStrip · renderOverviewSspPatchSlots · renderOverviewPulseBlock · renderOverviewStagesCard. NEW smoke scripts/smoke-overview-bento.mjs 80+ checks GREEN (static + Playwright DOM + geometry + mobile collapse + no-horizontal-overflow). Critical regressions GREEN: smoke-today-bento, smoke-today-bento-polish, smoke-e2e (Overview visible, all 7 other tabs visible, zero console errors). smoke-headless pre-existing failure (v0.2-era a[data-tab="customer"] selector) noted but unrelated. Tag v4.0.5-overview-bento shipped and Sush HELM-confirmed with strong positive: "OG i love the overview tab - so good. visually appealing enough space different card layout different barcharts etc. perfect work Atlas! good job!". |
| 2026-05-29 | 1271fa43 |
Atlas | v1.4 — Phase 205a (Books bento per-SSP cockpit) added a third story-shape table in §3 ("Books tab — per-SSP cockpit bento") AND added a brand-new §3.5 "When NOT to bento" sub-section banking the insight that surfaced when splitting Row 205 → 205a/b/c/d: Pipeline (Opportunities) is a power-user sortable table and SHOULD NOT bento. Tables ARE tables; bento is for survey tabs (where the cold-user question is "what's the shape?"). The smell signal: if dominant content is ONE big sortable/filterable thing (table/list/feed), bento adds chrome without adding clarity. Rubber-duck consulted at plan stage — caught 12 blind spots, all adopted: (1) pass diff to Books renderAllSspBookCockpits + scope-by-SSP-owner filter via bbScopeDiffToSsp; (2) don't duplicate header KPIs (move old renderHeader 7-KPI strip into .bb-hero and slim header to chrome-only cockpit-head-slim); (3) don't wrap renderAtlasCommentary wholesale (extract insight text only, render Books-specific brief with lighter chrome); (4) COMPACT toggle exemption (bento cards use .bb-card NOT .cockpit-section so COMPACT only folds drill-zone tables — sensible "show me less"); (5) hero utilization label precise ("book-wide" with tooltip explaining tenant-wide-not-Tam-owned); (6) actions/risks bucket helpers bbIsAction/bbIsRisk/bbPickTopRecs (allows priority-2 fallback for sparse books, includes RENEWAL/ADOPTION/PIPELINE categories the original split omitted); (7) time strip chip format count · value · top customer not just counts; (8) CSS export+import pattern (BOOKS_BENTO_CSS from ssp-book.js → injected once in render.js <style> block); (9) anchor IDs per-cockpit unique (tam-jump-*/riki-jump-*/ben-jump-* no collision); (10) explicit scroll-margin-top: 96px for .books-grid-bento > section[id] AND .books-drill [id]; (11) smoke checks beyond Overview parity (3 grids · 7 children each · drill sibling per cockpit · .bb-card not .cockpit-section for bento · no MACC/ACR/Azure text); (12) HELM-gated tag (RC only until Sush confirms). One renderBookBentoForSsp called 3× (Tam/Riki/Ben) — identical topology, different data. NEW smoke scripts/smoke-books-bento.mjs 100+ checks GREEN (more than Overview smoke because of 3-cockpit pattern verification). Critical regressions GREEN: smoke-overview-bento (Phase 204 unaffected), smoke-today-bento (Phase 202), smoke-today-bento-polish (Phase 203), smoke-e2e (zero console errors, all 7 tabs intact). Tag v4.0.6-books-bento held as RC pending Sush HELM verify (Rule #7). |
| 2026-05-29 | 57998126 |
Atlas | v1.5 — Phase 205b (Customers bento) added fourth story-shape table in §3 ("Customers tab — survey-of-names bento"). Cold-user wedge: Customers = NAMED INDIVIDUALS (vs Overview aggregates, vs Books per-SSP, vs Today next-24h). Architecture-gate (Rule #5) surfaced 4 paths; Sush picked Option D (survey-of-names bento above + existing 54-card grid as drill zone). Three Rule #6 probe wins: industry/geo=0/54 → slot 7 became Lynx-coverage strip · atlasInsight=0/54 → brief composed at render-time using 3-beat structure · 52/54 Lynx coverage confirmed → 6 of 7 slots have real signal. Rubber-duck consulted; 15 findings adopted. NEW src/customers-bento.js (40KB · the only standalone bento module in the project — pattern other 3 should adopt). Tag v4.1.0-customers-bento shipped, RC pending Sush HELM spot-check per the 205a-feedback lighter-checklist pattern. |
| 2026-05-29 | 340d5f53 |
Atlas | v2.0 — Mid-arc cold-eye checkpoint (Phase 210) after the 4-bento system landed. Rubber-duck pushed back on 7 over-claims; demotions adopted. Major structural changes: (1) NEW §0.5 Mid-arc checkpoint — three buckets (proven / provisional / drifted). Reframes which patterns are settled science vs still evolving. (2) NEW §3.6 Bento eligibility + cold-user wedge test — positive companion to §3.5 (what EARNS a bento, not just what doesn't). 2-question gate (wedge test + composition test). Honest failure mode noted: wedge for Today/Overview/Books was retrofit; only Customers had it discovered live. (3) NEW §3.7 Patterns by confidence — three-tier classification (locked / provisional / not-universal). Demoted from "universal" to "provisional or context-specific": 3-beat brief (only Customers full implementation), customer-names-in-cyan-italic (Customers only; Overview uses amber), sub-nav 9 anchors (Today has none; not universal), data-freshness ink (would imply false precision on Overview/Books/Customers single-snapshot data), data-empty="1" chip-collapse (Today single-row slots only by design). (4) §5 EXPANDED with amber taxonomy — 3-bucket classification (A: legitimate stakes / B: warn-partial-stale needing semantic --warn token / C: chrome-nav-decorative needing slate-or-cyan flip). Audit confirmed amber is in 11 source files used in all 3 buckets indiscriminately. Row 211 should be a taxonomy audit, NOT a blanket flip. (5) §6 CORRECTED fact-drift on sticky hero — was marked ✅ shipped in v1.5, actually REVERTED Phase 203.2 (Electron-specific bug not reproducible in headless Playwright). Status now ❌ open at Row 203c. (6) NEW §8.5 Implementation debt — render.js 209KB with Overview bento inside it is high-pain; duplicated bento CSS across 4 files is medium-pain; Today/Books bento module extraction is low-pain (tidy-bug, defer until next functional touch). (7) NEW §9.5 Bias checks before promoting a pattern — 6-item checklist (coverage / user-value / regression-risk / Sush-validation / universality / honesty) for the conflict-of-interest where Atlas writes both the doc AND the bentos. Convert §9.5 from earlier-draft confession to operational checklist. Net additions ~12KB. Critique-driven demotions made the doc more useful, not less ambitious. Follow-up rows proposed in phase queue: Row 211 (amber taxonomy audit · 2-3h) · Row 212 (polish-layer applicability audit + targeted propagation · 1-2h) · Row 213 (Overview bento extraction + bento-base.css shared chrome · 2-3h). Sush approves direction at next session kickoff. |
11 · Quick cross-references¶
- Phase queue:
~/.copilot/atlas-portfolio-phases.md— look for Phase 200+ "HELM Design Evolution" - Current theme tokens (B2 palette):
styles/theme.css(:rootblock) - Story-shape source for current today-tab cards:
src/today-tab.js - PAC reference theme:
C:\ssClawy\pac-archive\src\renderer\src\shared\theme.css - PAC reference HTMLs:
C:\ssClawy\pac-archive\(5 mockup HTMLs from v0.2 cockpit) - Cosmos Atlas DNA (sparklines + per-card narrative):
learning-docs/docs/reference/cosmos-philosophy.md - Standing rules:
~/.copilot/copilot-instructions.md(Rules #1–#7)