From f238326fe9d4071f052fa08ab3c6960299d1f4e4 Mon Sep 17 00:00:00 2001 From: Nader Helmy Date: Tue, 28 Jul 2026 11:54:10 -0500 Subject: [PATCH 1/6] docs: defer colour and type to the one canonical design system The primary was the same value as another token in two of these files: action in atrib-internal, ink in atrib-cloud. A product whose pitch is that a decision can be checked cannot spend its brand colour on one of the outcomes, and a product whose primary is its body text has none. Cobalt is the primary. Literata, Libre Franklin and IoskeleyMono replace Inter and General Sans, all SIL OFL and all served from our own origin. Frontmatter values are left as written. They are a machine-readable contract and rewriting them is a separate decision. --- DESIGN.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/DESIGN.md b/DESIGN.md index 65c03aa0..7b040c13 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -4,6 +4,24 @@ Version: 0.2 Status: active working design contract Last updated: 2026-07-23 +> **Colour and type tokens are superseded** by +> `atrib-web/designs/fable5-authored-territories-20260721/DESIGN-SYSTEM.md`, +> read alongside `ANTI-REFERENCES.md` beside it. Protocol language, explorer IA +> and the asset contract are unaffected. +> +> The explorer keeps its dark instrument mode. Its canvas moves from neutral +> `#0a0a0a` to the water column's own `#050914`: amber measures 9.07 there +> against 9.02 today, so the hue costs nothing in contrast. The rest of the +> chrome this file pins in the asset contract moves with it, at the same +> contrast steps and hue 220 to 230: surface `#0a1027`, raised `#101929`, border +> `#212946`, muted `#7e879a`. `foreground` `#f5f4ee` and `accent` `#e8a04f` are +> unchanged, and cobalt `#7d9bd6` joins as the primary at depth. +> +> `Inter` is replaced by Literata for headings and Libre Franklin for reading. +> IoskeleyMono is unchanged. All three are SIL OFL and served from the site's own +> origin, so nothing in the brand depends on a third party staying up. +> Superseded 2026-07-28. + ## Purpose atrib makes agent activity verifiable. Productized atrib is a verifiable action layer for agents: control what runs, coordinate what carries forward, and prove what happened. The design system should make that idea feel concrete: not a vague AI platform, not a crypto dashboard, not an observability clone. The interface should feel like signed evidence entering a chain and becoming usable by the next agent, team, or verifier. From d616144ace112ec5ec3c2913e2654a3518b05ce5 Mon Sep 17 00:00:00 2001 From: Nader Helmy Date: Tue, 28 Jul 2026 13:33:24 -0500 Subject: [PATCH 2/6] feat: put the explorer on the shared ladder and the water column's floor The mark linked to the explorer's own root, so a reader who followed the evidence link from the site had no way back. It goes to atrib.dev now, from here as from everywhere. The estate ladder joins the header and the surface map joins the footer, both generated from atrib-web/lib/surfaces.json by scripts/render-nav.mjs so they cannot drift from the other surfaces. The explorer's own sections move to their own row: mixing "where am I in the estate" with "where am I in this page" is what made three surfaces read as three products. The canvas moves from neutral #0a0a0a to the column's own #050914. Amber measures 9.07 there against 9.02 before, and every neutral solves contrast(x, floor) equal to contrast(old, #0a0a0a) at hue 220 to 232, so each step survives to two decimals. Cobalt joins as the primary; the explorer had none, which is why amber was carrying headings as well as evidence. Status colours were Tailwind's default 400 ramp, a palette belonging to no part of this product. Four now come from the design system. warn is deliberately left: our review colour is hue 35 and the evidence mark is hue 32, so lifting it to this ground makes them the same colour, and choosing what "needs a human" looks like at depth is a decision rather than a mapping. The new-row highlight was a wash applied twice, on the row and again on the cell. Every chip here is a colour on a 12% tint of itself, which leaves the dimmest at 4.56, so a wash underneath pushed all six chip colours under 4.5 and the worst to 2.00. It is a rail now, in the gutter rather than behind the text. Two event-type chips read 3.76 and 2.50 against their own tint at 11px and were lifted at their own hue. The categorical scheme is unchanged: those hues encode protocol event types per D056 and D058, not brand. Measured after, compositing translucent layers: zero contrast failures across 627 elements. --- apps/dashboard/index.html | 244 +++++++++++++++++++++++++++----------- 1 file changed, 177 insertions(+), 67 deletions(-) diff --git a/apps/dashboard/index.html b/apps/dashboard/index.html index 1a9f5f35..99f81df6 100644 --- a/apps/dashboard/index.html +++ b/apps/dashboard/index.html @@ -18,8 +18,8 @@ - - + + @@ -48,25 +48,35 @@ */ :root { - /* Product token aliases, kept in sync with the public website. */ - --color-background: #0a0a0a; - --color-surface: #131210; - --color-surface-raised: #1c1a17; + /* Product token aliases, kept in sync with the public website. The ground + is the water column's own floor rather than a neutral near-black, so the + instrument sits on the same hue axis as the painting the site opens with. + Amber measures 9.07 here against 9.02 on the old #0a0a0a: the hue costs + nothing in contrast. Every neutral below solves + contrast(x, floor) == contrast(old, #0a0a0a) at hue 220 to 232, so every + step of the previous palette survives to two decimals. + Canonical: atrib-web/designs/fable5-authored-territories-20260721/DESIGN-SYSTEM.md */ + --color-background: #050914; + --color-surface: #0a1027; + --color-surface-raised: #101929; --color-foreground: #f5f4ee; - --color-muted: #8a877e; - --color-muted-foreground: #b8b5ac; - --color-border: #2d2a25; - --color-border-strong: #423e36; + --color-muted: #7e879a; + --color-muted-foreground: #afb4c9; + --color-border: #212946; + --color-border-strong: #343d5b; --color-accent: #e8a04f; --color-accent-strong: #f0b46c; + /* Cobalt is the brand. The explorer had no primary at all, which is why + amber was carrying headings as well as evidence. */ + --color-primary: #7d9bd6; /* Surface */ --bg: var(--color-background); --surface: var(--color-surface); --surface-2: var(--color-surface-raised); - --surface-hover: #24211d; + --surface-hover: #17203a; --border: var(--color-border); - --border-subtle: #211f1b; + --border-subtle: #191d36; /* Text */ --text: var(--color-foreground); @@ -80,21 +90,31 @@ --accent-subtle: rgba(232, 160, 79, 0.12); --accent-border: rgba(232, 160, 79, 0.3); - /* Status */ - --ok: #34d399; - --ok-subtle: rgba(52, 211, 153, 0.12); - --ok-border: rgba(52, 211, 153, 0.3); + /* Status. These were Tailwind's default 400 ramp, a palette belonging to + no part of this product. Four of them now come from the design system's + deep ramp, at the same contrast they had before. + + --warn is the exception and is deliberately unchanged. The system's + "needs review" colour is #965800, hue 35, and the evidence mark is + #e8a04f, hue 32. On paper they are told apart by lightness, 5.3 against + 2.0. Lifted to this ground they land two degrees apart and become the + same colour, which would break the rule that amber marks signed things + and nothing else. That is a design decision, not a mapping, so it is + left open rather than guessed at. See DESIGN-SYSTEM.md. */ + --ok: #99e0c3; + --ok-subtle: rgba(153, 224, 195, 0.12); + --ok-border: rgba(153, 224, 195, 0.3); --warn: #fbbf24; --warn-subtle: rgba(251, 191, 36, 0.12); --warn-border: rgba(251, 191, 36, 0.3); - --err: #f87171; - --err-subtle: rgba(248, 113, 113, 0.12); - --err-border: rgba(248, 113, 113, 0.3); - --info: #60a5fa; - --info-subtle: rgba(96, 165, 250, 0.12); - --info-border: rgba(96, 165, 250, 0.3); - --muted: #9ca3af; - --muted-subtle: rgba(156, 163, 175, 0.1); + --err: #ffb4a3; + --err-subtle: rgba(255, 180, 163, 0.12); + --err-border: rgba(255, 180, 163, 0.3); + --info: #7d9bd6; + --info-subtle: rgba(125, 155, 214, 0.12); + --info-border: rgba(125, 155, 214, 0.3); + --muted: #7e879a; + --muted-subtle: rgba(126, 135, 154, 0.1); /* Per event_type chip colors */ --et-tool-call: var(--info); @@ -108,7 +128,7 @@ --et-observation-border: rgba(192, 132, 252, 0.3); --et-extension: var(--muted); --et-extension-subtle: var(--muted-subtle); - --et-extension-border: rgba(156, 163, 175, 0.25); + --et-extension-border: rgba(126, 135, 154, 0.25); /* atrib-system event types (e.g. directory_anchor, byte 0x04 per D056). Pink sits well outside both the agent-action triad (blue tool_call, amber transaction, purple observation) and the verification-badge @@ -124,10 +144,10 @@ pretending the upstream is recoverable here. Muted-warning style (warm grey) so the dangling marker reads as "incomplete" without competing with the err-red used for verification failures. */ - --et-dangling: #92400e; - --et-dangling-subtle: rgba(146, 64, 14, 0.12); - --et-dangling-border: rgba(146, 64, 14, 0.3); - --ref-external: #9ca3af; + --et-dangling: #bd7d57; + --et-dangling-subtle: rgba(189, 125, 87, 0.12); + --et-dangling-border: rgba(189, 125, 87, 0.3); + --ref-external: #7e879a; --ref-missing: var(--err); --ref-unresolved: var(--warn); /* Annotation event_type (D058, byte 0x05): the recall-fidelity @@ -148,9 +168,14 @@ semantics are different: annotation comments, revision supersedes. Indigo signals "structural change of stance" and reads as deeper / weightier than annotation's commentary tone. */ - --et-revision: #6366f1; - --et-revision-subtle: rgba(99, 102, 241, 0.12); - --et-revision-border: rgba(99, 102, 241, 0.3); + /* Lifted from #6366f1 and #92400e, which read 3.76 and 2.50 against their + own 12% chip tint and so were unreadable at 11px. Both keep their hue to + the degree; only lightness moved, to the dimmest value that clears 4.5 + with headroom. The categorical scheme itself is unchanged: these hues + encode protocol event types per D056 and D058, not brand. */ + --et-revision: #7e81f7; + --et-revision-subtle: rgba(126, 129, 247, 0.12); + --et-revision-border: rgba(126, 129, 247, 0.3); /* Edge-type colors (graph viz), organized in two semantic tiers. Tier 1 (vibrant): the edges that carry meaning beyond @@ -281,7 +306,7 @@ gap: 16px; padding: 14px max(20px, calc((100vw - var(--container)) / 2 + 20px)); border-bottom: 1px solid var(--border); - background: rgba(10, 11, 14, 0.85); + background: rgba(5, 9, 20, 0.85); backdrop-filter: saturate(180%) blur(12px); -webkit-backdrop-filter: saturate(180%) blur(12px); position: sticky; top: 0; z-index: 50; @@ -303,21 +328,38 @@ padding-left: 10px; border-left: 1px solid var(--border); margin-left: 2px; } - body > header nav { + body > header nav, nav.local { display: flex; gap: 4px; align-items: center; min-width: 0; overflow-x: auto; scrollbar-width: none; } - body > header nav::-webkit-scrollbar { display: none; } - body > header nav a { + body > header nav::-webkit-scrollbar, nav.local::-webkit-scrollbar { display: none; } + /* The estate ladder is quiet and monospaced, matching every other surface. + You cannot navigate to where you already are, so the current surface is a + label that reads brighter rather than a link. */ + body > header nav.ladder a, body > header nav.ladder span { + font: 400 12px/1 var(--font-mono); padding: 8px 10px; + border-radius: var(--radius-sm); color: var(--text-3); flex-shrink: 0; + } + body > header nav.ladder a:hover { background: var(--surface-2); color: var(--text); text-decoration: none; } + body > header nav.ladder [aria-current] { color: var(--text); } + nav.local { + position: sticky; top: 53px; z-index: 49; + padding: 8px max(20px, calc((100vw - var(--container)) / 2 + 20px)); + border-bottom: 1px solid var(--border); + background: rgba(5, 9, 20, 0.85); + backdrop-filter: saturate(180%) blur(12px); + -webkit-backdrop-filter: saturate(180%) blur(12px); + } + body > header nav a, nav.local a { color: var(--text-2); font: 500 13px/1 var(--font-sans); padding: 8px 12px; border-radius: var(--radius-sm); flex-shrink: 0; transition: background 120ms ease, color 120ms ease; } - body > header nav a:hover { background: var(--surface-2); color: var(--text); text-decoration: none; } - body > header nav a.active { color: var(--accent); background: var(--accent-subtle); } + body > header nav a:hover, nav.local a:hover { background: var(--surface-2); color: var(--text); text-decoration: none; } + body > header nav a.active, nav.local a.active { color: var(--accent); background: var(--accent-subtle); } @media (max-width: 520px) { body > header { gap: 10px; @@ -848,12 +890,20 @@ table.feed tbody td .mono { font: 12.5px/1 var(--font-mono); color: var(--text-2); } - /* New-row highlight: a sustained amber wash (not a flicker). The cell-level - * animation matches the row-level so striped table backgrounds don't - * override on tr. Holds full color for ~3.5s, fades over ~3s. Total - * ~6.5s, long enough to actually catch the eye scanning the table. */ - table.feed tbody tr.new, - table.feed tbody tr.new td { + /* New-row highlight: a sustained cobalt rail, held ~3.5s then faded over ~3s, + * long enough to catch the eye scanning the table. + * + * It was a wash, and a wash cannot work here. Every chip in this table is its + * own colour on a 12% tint of that same colour, which leaves the dimmest of + * them at 4.56 against the surface: one notch above the floor. Tinting the + * row underneath pushes it below, and the old rule applied its tint twice, on + * the row and again on the cell, so during the flash all six chip colours + * fell under 4.5 and the worst reached 2.00. The doubling was deliberate, to + * stop the striped row background overriding it, which is a real problem that + * a rail does not have. + * + * A rail costs nothing: it sits in the gutter rather than behind the text. */ + table.feed tbody tr.new td:first-child { animation: rowEnter 6500ms ease-out; } .evidence-authority { @@ -900,14 +950,13 @@ } } @keyframes rowEnter { - 0% { background-color: rgba(252, 211, 77, 0.18); } - 50% { background-color: rgba(252, 211, 77, 0.18); } - 100% { background-color: transparent; } + 0% { box-shadow: inset 3px 0 0 var(--color-primary); } + 50% { box-shadow: inset 3px 0 0 var(--color-primary); } + 100% { box-shadow: inset 3px 0 0 transparent; } } @media (prefers-reduced-motion: reduce) { .hero .eyebrow .pulse, .feed-head .live-tag .dot { animation: none; } - table.feed tbody tr.new, - table.feed tbody tr.new td { animation: none; } + table.feed tbody tr.new td:first-child { animation: none; } } /* ─── Chips & badges ─────────────────────────────────────────────────── */ @@ -948,7 +997,7 @@ .badge.warn { background: var(--warn-subtle); color: var(--warn); border-color: var(--warn-border); } .badge.err { background: var(--err-subtle); color: var(--err); border-color: var(--err-border); } .badge.info { background: var(--info-subtle); color: var(--info); border-color: var(--info-border); } - .badge.dim { background: var(--muted-subtle); color: var(--muted); border-color: rgba(156, 163, 175, 0.2); } + .badge.dim { background: var(--muted-subtle); color: var(--muted); border-color: rgba(126, 135, 154, 0.2); } .verify-badges { display: inline-flex; gap: 4px; flex-wrap: wrap; } @@ -1053,7 +1102,7 @@ } .proof-step.dim .mark { background: var(--muted-subtle); - border-color: rgba(156, 163, 175, 0.2); + border-color: rgba(126, 135, 154, 0.2); color: var(--muted); } .proof-step strong { @@ -1105,6 +1154,29 @@ display: grid; grid-template-columns: 1fr 1fr; gap: 32px; color: var(--text-3); font-size: 13px; } + /* The surface map, generated from atrib-web/lib/surfaces.json by + scripts/render-nav.mjs. Every atrib surface, grouped by what the reader + would be doing when they want it. The working proof used to be reachable + from nowhere at all. */ + footer .surface-map { + grid-column: 1 / -1; + border-top: 1px solid var(--border-subtle); padding-top: 28px; + display: grid; gap: 28px 24px; + grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); + } + footer .surface-map h2 { + margin: 0 0 12px; font: 400 11px/1 var(--font-mono); + text-transform: uppercase; letter-spacing: 0.14em; color: var(--text-3); + } + footer .surface-map ul { margin: 0; padding: 0; list-style: none; display: grid; gap: 14px; } + footer .surface-map a, footer .surface-map [aria-current] { + font: 400 12px/1 var(--font-mono); color: var(--accent-strong); + } + footer .surface-map [aria-current] { color: var(--text); } + footer .surface-map p { + margin: 5px 0 0; max-width: 28ch; font-size: 12px; line-height: 1.5; + color: var(--text-3); + } footer h3 { margin: 0 0 12px; font: 500 11px/1 var(--font-sans); text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-2); @@ -1761,19 +1833,29 @@
- + atrib explorer
-
+
@@ -1785,12 +1867,37 @@

Endpoints

Links

+
+ + + + + +