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. diff --git a/apps/dashboard/index.html b/apps/dashboard/index.html index 1a9f5f35..a4a6a7c5 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,30 @@
- + atrib explorer
-
+
@@ -1785,12 +1868,42 @@

Endpoints

Links

+
+ + + + + + +