@bongos/core 1.19.458 → 1.19.460

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/.bongos-core.json +117 -42
  2. package/.claude/skills/design/SKILL.md +10 -0
  3. package/docs/adr/0219-a-look-is-a-branding-pack-the-style-library.md +30 -0
  4. package/docs/adr/README.md +1 -0
  5. package/docs/branding-contract.md +1 -1
  6. package/docs/copy-inventory.md +52 -61
  7. package/docs/copy-registry.json +92 -203
  8. package/docs/file-map.md +1 -1
  9. package/docs/module-api-changelog.md +4 -0
  10. package/docs/recipes/ui-look-before-you-ship.md +2 -0
  11. package/modules/hall-ui/public/collab-lib.js +40 -4
  12. package/modules/hall-ui/public/collab.css +18 -34
  13. package/modules/hall-ui/public/collab.html +17 -17
  14. package/modules/hall-ui/public/collab.js +75 -39
  15. package/modules/hall-ui/public/collab.states.json +2 -2
  16. package/modules/hall-ui/public/copy-desk.css +64 -109
  17. package/modules/hall-ui/public/copy-desk.html +76 -69
  18. package/modules/hall-ui/public/copy-desk.js +175 -80
  19. package/modules/hall-ui/public/copy-desk.states.json +59 -2
  20. package/modules/hall-ui/public/oversight.css +11 -2
  21. package/modules/lifecycle/help-requests.js +18 -8
  22. package/modules/ui-design/kit/README.md +7 -5
  23. package/modules/ui-design/kit/check-mock.js +12 -5
  24. package/modules/ui-design/kit/contrast.js +13 -6
  25. package/modules/ui-design/kit/lib.js +39 -2
  26. package/modules/ui-design/kit/probe.js +4 -1
  27. package/modules/ui-design/kit/render.js +7 -4
  28. package/modules/ui-design/kit/serve.js +9 -2
  29. package/modules/ui-design/styles/README.md +54 -2
  30. package/modules/ui-design/styles/chrome-world/DESIGN.md +56 -0
  31. package/modules/ui-design/styles/chrome-world/mock.html +275 -0
  32. package/modules/ui-design/styles/chrome-world/mock.states.json +11 -0
  33. package/modules/ui-design/styles/chrome-world/pack.json +33 -0
  34. package/modules/ui-design/styles/expedition/DESIGN.md +141 -0
  35. package/modules/ui-design/styles/expedition/mock.html +285 -0
  36. package/modules/ui-design/styles/expedition/mock.states.json +11 -0
  37. package/modules/ui-design/styles/expedition/pack.json +33 -0
  38. package/modules/ui-design/styles/grove/DESIGN.md +148 -0
  39. package/modules/ui-design/styles/grove/mock.html +294 -0
  40. package/modules/ui-design/styles/grove/mock.states.json +11 -0
  41. package/modules/ui-design/styles/grove/pack.json +33 -0
  42. package/package-lock.json +2 -2
  43. package/package.json +1 -1
  44. package/src/module-api.js +1 -1
  45. package/tests/collab_page.mjs +13 -7
  46. package/tests/cosmos_token_contrast.mjs +9 -2
  47. package/tests/hall_collab_world.mjs +214 -0
  48. package/tests/hall_tokens.mjs +15 -6
  49. package/tests/ui_design_styles.mjs +218 -0
  50. package/tests/world_tokens.mjs +9 -2
@@ -0,0 +1,11 @@
1
+ {
2
+ "_doc": "The specimen's states for the kit (task 1003323): node modules/ui-design/kit/render.js --states modules/ui-design/styles/chrome-world/mock.states.json --style chrome-world. Both modes; the mock reads ?mode= itself.",
3
+ "page": "/mock",
4
+ "surface": "modules/ui-design/styles/chrome-world",
5
+ "modes": ["dark", "light"],
6
+ "states": {
7
+ "rest": { "auth": false },
8
+ "signed-in": { "auth": true, "url": "/mock?state=signed-in", "expect": { "visible": [".who"], "hidden": [".pill.in"] } }
9
+ },
10
+ "reducedMotion": { "auth": false }
11
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "_doc": "A look from the ui-design module's style library (task 1003323): the theme.ui overlay a branding pack carries, and nothing else. The stub lays it over the instance's pack (STYLE=chrome-world); an instance adopts it by copying `theme` into config/branding.json. This is the CANONICAL entry: byte-for-byte config/branding.neutral.json's theme.ui (tests/ui_design_styles.mjs pins it), pointing at the repo-root DESIGN.md for its recipes.",
3
+ "name": "chrome-world",
4
+ "title": "The Chrome World",
5
+ "summary": "One iridescent chrome sculpture in a black void, pale grey paper in light, one warm salmon that lights only what is pressable or live.",
6
+ "origin": "docs/design/mocks/world/chrome-blobs (the world round, task 1003296; the owner's pick, built at task 1003298 and recorded in DESIGN.md, ADR 0196)",
7
+ "theme": {
8
+ "ui": {
9
+ "colors": {
10
+ "bg": "#edecee",
11
+ "bgCard": "#fbfafc",
12
+ "bgDeep": "#e2e1e4",
13
+ "bgFrame": "#f6f5f7",
14
+ "ink": "#17181a",
15
+ "inkSoft": "#55565a",
16
+ "inkFaint": "#65656a",
17
+ "rule": "#c6c6c8",
18
+ "ruleSoft": "#dcdbdd",
19
+ "accent": "#fb9569",
20
+ "accentDeep": "#a3481a",
21
+ "sea": "#5b6fd0",
22
+ "terracotta": "#c9512c"
23
+ },
24
+ "fonts": {
25
+ "display": "\"Manrope\", \"Segoe UI\", system-ui, -apple-system, sans-serif",
26
+ "body": "\"Manrope\", \"Segoe UI\", system-ui, -apple-system, sans-serif",
27
+ "links": [
28
+ "https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400&family=Manrope:wght@300;400;500;600&display=swap"
29
+ ]
30
+ }
31
+ }
32
+ }
33
+ }
@@ -0,0 +1,141 @@
1
+ ---
2
+ name: The Expedition
3
+ description: A printed field journal. Warm paper under a halftone screen, hairline frames instead of a grid, big heavy neo-grotesque headlines, one lamp yellow that lights only the mark, the primary door and the live step.
4
+ colors:
5
+ # ---- contract tier, LIGHT: the thirteen this look's pack.json carries, value for value
6
+ # (tests/ui_design_styles.mjs holds the two in lockstep). Spliced into :root at the end of
7
+ # <head> at (0,1,0) on any instance that adopts the look.
8
+ bg: "#f4f3ef"
9
+ bg-card: "#ffffff"
10
+ bg-deep: "#e9e7e0"
11
+ bg-frame: "#eceae3"
12
+ ink: "#141412"
13
+ ink-soft: "#55544f"
14
+ ink-faint: "#66645b"
15
+ rule: "#d9d7cf"
16
+ rule-soft: "#e8e6df"
17
+ accent: "#ffd214"
18
+ accent-deep: "#7f6209"
19
+ sea: "#427d97"
20
+ terracotta: "#b4592f"
21
+ # ---- contract tier, DARK: NOT this look's to set. A pack carries light values only; dark is
22
+ # each sheet's own black tier (bg #000000, ink #ffffff, rules as white at 16% / 8%), which the
23
+ # look reaches through its accent and its faces. Written here so a reader knows what dark IS.
24
+ bg-dark: "#000000"
25
+ ink-dark: "#ffffff"
26
+ accent-deep-dark: "color-mix(in srgb, var(--accent) 70%, #ffffff)"
27
+ # ---- derived: the accent's jobs. The yellow is a FILL colour and never paints words: every
28
+ # accent-as-text job goes to accent-deep, and the ink that sits ON the yellow is near black.
29
+ accent-ink: "var(--accent-deep)"
30
+ accent-ink-dark: "var(--accent)"
31
+ accent-on: "color-mix(in srgb, var(--accent) 10%, #000000)"
32
+ accent-lift: "color-mix(in srgb, var(--accent) 70%, #ffffff)"
33
+ accent-tint: "color-mix(in srgb, var(--accent) 18%, var(--bg-card))"
34
+ accent-tint-dark: "color-mix(in srgb, var(--accent) 16%, #000000)"
35
+ focus: "var(--accent-deep)"
36
+ focus-dark: "var(--accent)"
37
+ # ---- derived: the print materials
38
+ dots: "rgba(0, 0, 0, .085)"
39
+ dots-dark: "rgba(255, 255, 255, .10)"
40
+ frame: "var(--ink)"
41
+ frame-dark: "rgba(255, 255, 255, .28)"
42
+ glass: "var(--bg-card)"
43
+ glass-dark: "rgba(255, 255, 255, .06)"
44
+ typography:
45
+ display: { fontFamily: "Archivo, Hanken Grotesk, Helvetica Neue, Helvetica, Arial, sans-serif", fontSize: "clamp(38px, 7.2vw, 96px)", fontWeight: 700, lineHeight: 0.92, letterSpacing: "-0.035em", textTransform: "uppercase" }
46
+ headline: { fontFamily: "{typography.display.fontFamily}", fontSize: "clamp(24px, 3vw, 40px)", fontWeight: 600, lineHeight: 1.04, letterSpacing: "-0.025em" }
47
+ body: { fontFamily: "Archivo, Hanken Grotesk, Helvetica Neue, Helvetica, Arial, sans-serif", fontSize: "16px", fontWeight: 400, lineHeight: 1.5 }
48
+ label: { fontFamily: "JetBrains Mono, ui-monospace, Cascadia Mono, Consolas, monospace", fontSize: "11px", fontWeight: 400, letterSpacing: "0.12em", textTransform: "uppercase" }
49
+ mono: { fontFamily: "{typography.label.fontFamily}", fontSize: "13px", fontWeight: 400, fontFeature: "tabular-nums" }
50
+ rounded:
51
+ pill: "999px"
52
+ panel: "0"
53
+ tile: "0"
54
+ spacing:
55
+ dot-pitch: "5px"
56
+ band: "clamp(40px, 7vh, 72px)"
57
+ gutter: "clamp(16px, 4vw, 26px)"
58
+ container: "1180px"
59
+ components:
60
+ mark-plate: { backgroundColor: "{colors.accent}", textColor: "{colors.accent-on}", height: "36px", padding: "0 12px", rounded: "0" }
61
+ door-primary: { backgroundColor: "{colors.accent}", textColor: "{colors.accent-on}", rounded: "{rounded.pill}", height: "48px", padding: "0 28px" }
62
+ door-secondary: { backgroundColor: "transparent", textColor: "{colors.ink}", border: "1px solid {colors.ink}", rounded: "{rounded.pill}", height: "48px" }
63
+ rail-cell-lit: { backgroundColor: "{colors.accent-tint}", textColor: "{colors.ink}" }
64
+ ledger-row: { textColor: "{colors.ink}", padding: "14px 0", border: "1px solid {colors.rule}" }
65
+ ---
66
+
67
+ # Style: The Expedition
68
+
69
+ **Origin.** The `natgeo-editorial` candidate of the world round ([task 1003296](https://cloudbongos.com/builders#/task/1003296), `docs/design/mocks/world/natgeo-editorial/`), kept by the owner in round 1 and not picked in round 2. Ported into the style library ([task 1003323](https://cloudbongos.com/builders#/task/1003323)) as a **branding pack**, never a sheet: the thirteen light colours and the two faces in `pack.json`, retuned twice against the contract (ink-faint deepened from `#6f6d64` to `#66645b` so the thinnest pair clears 4.5:1 on the paper; sea lifted from `#2c5464` to `#427d97` for the hall's info state in dark). The candidate's own near-black dark ground (`#0e0e0e`) does not travel: a pack carries light values only, and dark is the sheets' black tier.
70
+
71
+ ## Overview
72
+
73
+ **Creative North Star: "The field journal, printed"**
74
+
75
+ A page in this look is a sheet of warm paper that has been through a press. There is a halftone screen over the whole ground, ink and photograph alike, so nothing on the page is perfectly flat; structure is a hairline frame around a compartment rather than a grid of cards; and the type is a neo-grotesque set very large and very heavy for chapter titles, small and grey for everything secondary, in narrow columns. One lamp yellow is the only colour: it is the plate behind the mark, the fill of the primary door, and the cell of the one live step. Nothing else is yellow, which is why the yellow is believed.
76
+
77
+ **Key Characteristics:**
78
+
79
+ - Warm paper (`#f4f3ef`) under a printed dot screen; pure black in dark, where the screen turns to white dots.
80
+ - Frames, not cards: a 1px ink rule around a compartment, corners at 0 on every container.
81
+ - Archivo at 700, uppercase, tight, for the display voice; the same family at 400 in a narrow column for body.
82
+ - One lamp yellow (`accent`) as a fill only; a deep olive (`accent-deep`) wherever the accent must be read.
83
+ - Pills for buttons and discs, zero radius for everything that holds content.
84
+
85
+ ## Colors
86
+
87
+ - **Lamp yellow** (`accent`, `#ffd214`): the one colour. It fills the mark's plate, the primary door and the lit rail cell. It **never paints text**: at 1.4:1 against white it cannot, so every accent-as-text job (`accent-ink`, links, the focus ring on paper) is `accent-deep`.
88
+ - **Deep olive** (`accent-deep`, `#7f6209`): the yellow's text-safe twin, 5.18:1 on the paper and 5.75:1 on the card. In dark it is derived (`color-mix(in srgb, var(--accent) 70%, #ffffff)`), never restated.
89
+ - **Ink on yellow** (`accent-on`): `color-mix(in srgb, var(--accent) 10%, #000000)`, a near black warmed by the yellow. White on this yellow would measure 1.4:1 and is banned.
90
+ - **Sea** (`#427d97`) and **Terracotta** (`#b4592f`): held because every pack carries them. Sea is a lake blue the journal may spend on a second voice (a map's water, a diagram); it sits in the narrow lightness band the contract needs, because the hall derives its info state from sea at 80% into white in dark and at 86% into black in light, and the candidate's deeper `#2c5464` could not carry the dark half. Terracotta is the error and warn source.
91
+ - **Paper, card, deep, frame** (`bg`, `bg-card`, `bg-deep`, `bg-frame`): the ground and its tonal layers. Card is pure white, the only white on the page, so a white compartment reads as a pasted-in photograph.
92
+ - **Ink, ink-soft, ink-faint**: near-black display and body ink, a warm grey for secondary prose, a deeper warm grey for labels. Ink-faint on paper is the thinnest pair (5.34:1); do not lighten it.
93
+ - **Rule, rule-soft**: the hairlines. The frame around a compartment takes `ink` itself (`frame`), not a rule: a frame is structure, a rule is a divider.
94
+
95
+ ## Typography
96
+
97
+ **Display Font:** Archivo 700 (with Hanken Grotesk, Helvetica Neue, Helvetica, Arial, sans-serif)
98
+ **Body Font:** Archivo 400/500/600 (same stack)
99
+ **Label / Mono Font:** JetBrains Mono 400 (with ui-monospace, Cascadia Mono, Consolas)
100
+
101
+ **Character:** One neo-grotesque doing two jobs. At display size it is set at 700, uppercase, with tracking pulled to `-0.035em` and line-height under 1, so a headline reads as a printed chapter title. At body size it is plain and set in a narrow column with generous leading. The mono carries the labels on paper; in dark the labels take the grotesque, because mono caps that read as precise on paper read as thin on black.
102
+
103
+ ## Shapes
104
+
105
+ **Pill or zero.** Buttons, discs and inputs are full pills. Every container is a rectangle with no radius. There is no third shape. The bar is a hairline rule with the mark on its yellow plate; the rail is five compartments inside one frame; the ledger is the journal's index.
106
+
107
+ ## Materials
108
+
109
+ - **The screen.** A radial-gradient dot pattern in black at 8.5% on a 5px pitch over the whole page ground; white at 10% on 4.5px in dark. It is the one texture and it goes over everything.
110
+ - **Frames.** A 1px `frame` rule (ink on paper, white at 28% on black) around a compartment; hairline `rule-soft` dividers inside.
111
+ - **Plates** (when a surface adds them): printed as inverted engravings multiplied into the paper in light; lightened onto black in dark. A surface's plates are its own; this look brings none.
112
+
113
+ ## Motion
114
+
115
+ Felt, not seen. State transitions at 200ms on `cubic-bezier(.2,.7,.3,1)`; no ambient loops in this look. The kill switch stands as the platform's.
116
+
117
+ ## Do's and Don'ts
118
+
119
+ ### Do
120
+
121
+ - **Do** fill with `accent` and write with `accent-deep`; put `accent-on` on any yellow.
122
+ - **Do** frame a compartment with `frame` and divide inside it with `rule-soft`.
123
+ - **Do** keep every container square and every control a pill.
124
+ - **Do** set display type heavy, uppercase and tight; keep body copy in a narrow column.
125
+ - **Do** let the screen show through: a solid panel on the paper is a photograph, not a card.
126
+
127
+ ### Don't
128
+
129
+ - **Don't** write words in the lamp yellow, or put white on it.
130
+ - **Don't** round a container, or drop a shadow under one; a frame is the whole elevation system.
131
+ - **Don't** use an em dash or en dash in visible copy, an emoji, gradient text, a coloured text glow, or a trust strip.
132
+ - **Don't** pin the accent, sea or terracotta in a dark block; dark derives.
133
+ - **Don't** declare a `:root` in a page; page tokens live on `body`.
134
+
135
+ ## Accessibility Floors
136
+
137
+ The platform's, unchanged: 4.5:1 body text and 3:1 large text and non-text in both modes, measured from the real stylesheet; every control 24px on both sides (the pills are 46 and 48); the kill switch at the foot of the token layer. This pack measures clean against every pair the landing's `world.css`, the hub's `cosmos.css` and the hall's `style.css` paint (`tests/ui_design_styles.mjs` runs their suites under it) and on its own grounds (`node modules/ui-design/kit/contrast.js --pack expedition`).
138
+
139
+ ## Adopting this look
140
+
141
+ Copy `pack.json`'s `theme` into the instance's `config/branding.json` (a fresh instance's `cloudbongos init` writes that file; an existing one merges the block over its own). Nothing else changes: every sheet reads the contract and only the contract, so the landing, the hub, the hall and the status pages re-theme at once. What stays the platform's: the dark ground (black), the hall's fixed green / amber / red verification vocabulary, the status ledger's pillars, and every derived recipe a sheet already carries. Look before you ship: `node modules/ui-design/kit/render.js --page / --style expedition`.
@@ -0,0 +1,285 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>{{productName}} · the expedition, on a sheet</title>
7
+ <script>
8
+ (function(){try{var q=new URLSearchParams(location.search);var m=q.get('mode');if(m==='light'||m==='dark')document.documentElement.setAttribute('data-mode',m);}catch(e){}})();
9
+ </script>
10
+ <style>
11
+ html { color-scheme: light; }
12
+ body {
13
+ /* the expedition's derived tier, by the recipes in this style's DESIGN.md. The fifteen
14
+ arrive from the pack the stub splices after this sheet; nothing below is a colour of its
15
+ own: a var(), a color-mix(), or black or white with alpha. The paper carries a printed
16
+ halftone screen (dots of ink at low alpha) and hairline frames; corners are 0 on every
17
+ container and a pill on every control. */
18
+ --font-mono: "JetBrains Mono", ui-monospace, "Cascadia Mono", Consolas, monospace;
19
+ --glass: var(--bg-card);
20
+ --glass-strong: var(--bg-deep);
21
+ --glass-edge: var(--rule);
22
+ --accent-ink: var(--accent-deep);
23
+ --accent-lift: color-mix(in srgb, var(--accent) 70%, #ffffff);
24
+ --accent-tint: color-mix(in srgb, var(--accent) 18%, var(--bg-card));
25
+ --accent-on: color-mix(in srgb, var(--accent) 10%, #000000);
26
+ --accent-glow: 0 0 0 0 transparent;
27
+ --focus: var(--accent-deep);
28
+ --type-halo: none;
29
+ --dots: rgba(0, 0, 0, .085);
30
+ --dot-pitch: 5px;
31
+ --frame: var(--ink);
32
+ --label-face: var(--font-mono);
33
+ --label-size: 11px;
34
+ --label-space: .12em;
35
+ --radius: 0;
36
+ --radius-sm: 0;
37
+ --radius-pill: 999px;
38
+ --top-h: 64px;
39
+ --gutter: clamp(16px, 4vw, 26px);
40
+ --band: clamp(40px, 7vh, 72px);
41
+ margin: 0;
42
+ background: var(--bg);
43
+ background-image: radial-gradient(var(--dots) .9px, transparent 1px);
44
+ background-size: var(--dot-pitch) var(--dot-pitch);
45
+ color: var(--ink);
46
+ font-family: var(--font-body);
47
+ font-size: 16px;
48
+ line-height: 1.5;
49
+ -webkit-font-smoothing: antialiased;
50
+ }
51
+ :root[data-mode="dark"] body {
52
+ color-scheme: dark;
53
+ --bg: #000000;
54
+ --bg-card: color-mix(in srgb, #ffffff 7%, #000000);
55
+ --bg-deep: #000000;
56
+ --bg-frame: color-mix(in srgb, #ffffff 4%, #000000);
57
+ --ink: #ffffff;
58
+ --ink-soft: rgba(255, 255, 255, .72);
59
+ --ink-faint: rgba(255, 255, 255, .62);
60
+ --rule: rgba(255, 255, 255, .18);
61
+ --rule-soft: rgba(255, 255, 255, .09);
62
+ --accent-deep: color-mix(in srgb, var(--accent) 70%, #ffffff);
63
+ --glass: rgba(255, 255, 255, .06);
64
+ --glass-strong: rgba(255, 255, 255, .12);
65
+ --glass-edge: rgba(255, 255, 255, .18);
66
+ --accent-ink: var(--accent);
67
+ --accent-tint: color-mix(in srgb, var(--accent) 16%, #000000);
68
+ --focus: var(--accent);
69
+ --dots: rgba(255, 255, 255, .10);
70
+ --dot-pitch: 4.5px;
71
+ --frame: rgba(255, 255, 255, .28);
72
+ --label-face: var(--font-body);
73
+ --label-size: 11.5px;
74
+ --label-space: .1em;
75
+ }
76
+ @media (prefers-color-scheme: dark) {
77
+ :root:not([data-mode="light"]) body {
78
+ color-scheme: dark;
79
+ --bg: #000000;
80
+ --bg-card: color-mix(in srgb, #ffffff 7%, #000000);
81
+ --bg-deep: #000000;
82
+ --bg-frame: color-mix(in srgb, #ffffff 4%, #000000);
83
+ --ink: #ffffff;
84
+ --ink-soft: rgba(255, 255, 255, .72);
85
+ --ink-faint: rgba(255, 255, 255, .62);
86
+ --rule: rgba(255, 255, 255, .18);
87
+ --rule-soft: rgba(255, 255, 255, .09);
88
+ --accent-deep: color-mix(in srgb, var(--accent) 70%, #ffffff);
89
+ --glass: rgba(255, 255, 255, .06);
90
+ --glass-strong: rgba(255, 255, 255, .12);
91
+ --glass-edge: rgba(255, 255, 255, .18);
92
+ --accent-ink: var(--accent);
93
+ --accent-tint: color-mix(in srgb, var(--accent) 16%, #000000);
94
+ --focus: var(--accent);
95
+ --dots: rgba(255, 255, 255, .10);
96
+ --dot-pitch: 4.5px;
97
+ --frame: rgba(255, 255, 255, .28);
98
+ --label-face: var(--font-body);
99
+ --label-size: 11.5px;
100
+ --label-space: .1em;
101
+ }
102
+ }
103
+
104
+ *, *::before, *::after { box-sizing: border-box; }
105
+ a { color: inherit; }
106
+ :focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; }
107
+ .skip { position: absolute; left: 12px; top: -60px; padding: 11px 18px; border-radius: var(--radius-pill); background: var(--bg-card); color: var(--ink); text-decoration: none; }
108
+ .skip:focus { top: 12px; }
109
+ .wrap { max-width: 1180px; margin: 0 auto; padding: 0 var(--gutter); }
110
+
111
+ /* the framed bar: a hairline rule, a yellow plate behind the mark */
112
+ .bar { height: var(--top-h); border-bottom: 1px solid var(--frame); background: var(--bg); }
113
+ .bar .wrap { height: 100%; display: flex; align-items: center; gap: 18px; }
114
+ .mark { display: inline-flex; align-items: center; height: 36px; padding: 0 12px; background: var(--accent); color: var(--accent-on); font-weight: 700; letter-spacing: -.01em; text-transform: uppercase; font-size: 14px; text-decoration: none; }
115
+ .nav { margin-left: auto; display: flex; align-items: center; gap: 4px; }
116
+ .nav a { text-decoration: none; text-transform: uppercase; font-family: var(--label-face); font-size: 12px; letter-spacing: .1em; color: var(--ink-soft); padding: 14px 10px; display: inline-block; line-height: 16px; }
117
+ .nav a:hover { color: var(--ink); }
118
+ .pill { display: inline-flex; align-items: center; height: 46px; padding: 0 22px; border-radius: var(--radius-pill); text-decoration: none; font-weight: 600; letter-spacing: 0; text-transform: none; font-family: var(--font-body); font-size: 15px; transition: background-color 200ms cubic-bezier(.2, .7, .3, 1); }
119
+ .pill.in { background: var(--ink); color: var(--bg); }
120
+ .who { display: none; align-items: center; gap: 8px; height: 46px; padding: 0 6px; border-radius: var(--radius-pill); border: 1px solid var(--rule); }
121
+ .who .dot { width: 30px; height: 30px; border-radius: 50%; background: var(--bg-deep); border: 1px solid var(--rule); }
122
+ body[data-state="signed-in"] .pill.in { display: none; }
123
+ body[data-state="signed-in"] .who { display: inline-flex; }
124
+
125
+ /* the bands: framed columns, not padded cards */
126
+ .band { padding: var(--band) 0; border-top: 1px solid var(--rule); }
127
+ .band:first-of-type { border-top: 0; }
128
+ h1 { font-family: var(--font-display); font-weight: 700; font-size: clamp(38px, 7.2vw, 96px); line-height: .92; letter-spacing: -.035em; text-transform: uppercase; margin: 0 0 18px; max-width: 12ch; }
129
+ h2 { font-family: var(--font-display); font-weight: 600; font-size: clamp(24px, 3vw, 40px); line-height: 1.04; letter-spacing: -.025em; margin: 0 0 14px; }
130
+ .lede { color: var(--ink-soft); max-width: 52ch; margin: 0; font-size: 15px; }
131
+ .label { font-family: var(--label-face); font-size: var(--label-size); letter-spacing: var(--label-space); text-transform: uppercase; color: var(--ink-faint); }
132
+ .kicker { display: inline-block; border-left: 3px solid var(--accent); padding-left: 10px; margin-bottom: 14px; }
133
+
134
+ /* the thirteen, as a specimen strip inside a frame */
135
+ .sw { display: grid; grid-template-columns: repeat(auto-fill, minmax(72px, 1fr)); gap: 0; margin: 0; padding: 0; list-style: none; border: 1px solid var(--frame); }
136
+ .sw li { margin: 0; padding: 10px; border-right: 1px solid var(--rule-soft); border-bottom: 1px solid var(--rule-soft); }
137
+ .sw i { display: block; height: 52px; border: 1px solid var(--rule); background: var(--c); }
138
+ .sw b { display: block; margin-top: 6px; font-family: var(--font-mono); font-weight: 400; font-size: 11px; color: var(--ink-faint); overflow-wrap: anywhere; }
139
+
140
+ /* the door pair: pills on paper, the primary in lamp yellow */
141
+ .doors { display: inline-flex; flex-wrap: wrap; gap: 8px; }
142
+ .door { display: inline-flex; align-items: center; height: 48px; padding: 0 28px; border-radius: var(--radius-pill); text-decoration: none; font-weight: 600; transition: background-color 200ms cubic-bezier(.2, .7, .3, 1); }
143
+ .door.go { background: var(--accent); color: var(--accent-on); }
144
+ .door.go:hover { background: var(--accent-lift); }
145
+ .door.more { color: var(--ink); border: 1px solid var(--ink); }
146
+ .door.more:hover { background: var(--glass-strong); }
147
+
148
+ /* the lifecycle rail: compartments with a visible frame */
149
+ .rail { display: grid; grid-template-columns: repeat(5, 1fr); gap: 0; margin: 0; padding: 0; list-style: none; border: 1px solid var(--frame); }
150
+ .rail li { padding: 14px; border-right: 1px solid var(--rule-soft); }
151
+ .rail li:last-child { border-right: 0; }
152
+ .rail .dot { display: block; width: 8px; height: 8px; border: 1px solid var(--ink-faint); margin-bottom: 10px; }
153
+ .rail .lit { background: var(--accent-tint); }
154
+ .rail .lit .dot { background: var(--accent); border-color: var(--accent-deep); }
155
+ .rail .lit .label { color: var(--ink); }
156
+ .rail p { margin: 6px 0 0; color: var(--ink-soft); font-size: 14px; }
157
+
158
+ /* ledger rows: the journal's index */
159
+ .ledger { margin: 0; padding: 0; list-style: none; border-top: 1px solid var(--frame); }
160
+ .ledger li { display: grid; grid-template-columns: 88px 1fr 152px 96px; gap: 20px; align-items: baseline; padding: 14px 0; border-bottom: 1px solid var(--rule); }
161
+ .ledger .id { font-family: var(--font-mono); font-size: 13px; color: var(--ink-faint); font-variant-numeric: tabular-nums; }
162
+ .ledger .by, .ledger .when { color: var(--ink-soft); font-size: 15px; }
163
+ .ledger .when { text-align: right; font-variant-numeric: tabular-nums; }
164
+ .ledger a { color: var(--accent-ink); text-underline-offset: 3px; display: inline-block; padding: 2px 0; }
165
+
166
+ footer { border-top: 1px solid var(--frame); padding: 26px 0 40px; }
167
+ footer .wrap { display: flex; flex-wrap: wrap; gap: 8px 22px; align-items: baseline; color: var(--ink-soft); font-size: 14px; }
168
+ footer p { margin: 0; flex: 1 1 320px; }
169
+ footer a { color: var(--accent-ink); display: inline-block; padding: 4px 0; font-family: var(--label-face); font-size: 12px; letter-spacing: .08em; text-transform: uppercase; }
170
+
171
+ @media (max-width: 900px) {
172
+ body { --top-h: 60px; }
173
+ .rail { grid-template-columns: 1fr; }
174
+ .rail li { border-right: 0; border-bottom: 1px solid var(--rule-soft); }
175
+ .rail li:last-child { border-bottom: 0; }
176
+ }
177
+ @media (max-width: 600px) {
178
+ .ledger li { grid-template-columns: 1fr; gap: 4px; }
179
+ .ledger .when { text-align: left; }
180
+ .nav a { display: none; }
181
+ }
182
+ @media (prefers-reduced-motion: reduce) {
183
+ *, *::before, *::after { animation: none !important; transition: none !important; }
184
+ }
185
+ </style>
186
+ </head>
187
+ <body>
188
+ <!-- THESIS: the expedition as a specimen sheet. The thirteen colours and the two faces the pack carries, laid through this look's own derived recipes (its DESIGN.md frontmatter): a framed bar with the mark on a yellow plate, an uppercase neo-grotesque display voice, a halftone screen printed over the paper, door pills with the primary in lamp yellow, a compartmented rail with one lit cell, the journal's index as ledger rows. This page declares no :root and no colour of its own: the pack is spliced by the stub (STYLE=expedition) and every value is a var() or a color-mix() of it. Dark restates the platform's black tier on body, since a mock links no sheet; this look reaches dark through its yellow and its faces, which is all a pack carries. STATES: rest (signed out), signed-in. MODES: ?mode=dark|light. -->
189
+ <a class="skip" href="#main">Skip to content</a>
190
+ <header class="bar">
191
+ <div class="wrap">
192
+ <a class="mark" href="/">{{productName}}</a>
193
+ <nav class="nav" aria-label="Primary">
194
+ <a href="#swatches">Projects</a>
195
+ <a href="#type">Docs</a>
196
+ <a class="pill in" href="#main">Sign in</a>
197
+ <span class="who"><span class="dot" aria-hidden="true"></span><span class="label">builder</span></span>
198
+ </nav>
199
+ </div>
200
+ </header>
201
+ <main id="main" tabindex="-1">
202
+ <section class="band">
203
+ <div class="wrap">
204
+ <p class="label kicker">A look from the style library</p>
205
+ <h1>The expedition</h1>
206
+ <p class="lede">A printed field journal. Warm paper under a halftone screen, hairline frames instead of a grid, headlines set big and heavy, and one lamp yellow that lights only the mark, the primary door and the live step.</p>
207
+ </div>
208
+ </section>
209
+ <section class="band" id="swatches">
210
+ <div class="wrap">
211
+ <h2>The thirteen</h2>
212
+ <ul class="sw">
213
+ <li><i style="--c: var(--bg)"></i><b>bg</b></li>
214
+ <li><i style="--c: var(--bg-card)"></i><b>bg-card</b></li>
215
+ <li><i style="--c: var(--bg-deep)"></i><b>bg-deep</b></li>
216
+ <li><i style="--c: var(--bg-frame)"></i><b>bg-frame</b></li>
217
+ <li><i style="--c: var(--ink)"></i><b>ink</b></li>
218
+ <li><i style="--c: var(--ink-soft)"></i><b>ink-soft</b></li>
219
+ <li><i style="--c: var(--ink-faint)"></i><b>ink-faint</b></li>
220
+ <li><i style="--c: var(--rule)"></i><b>rule</b></li>
221
+ <li><i style="--c: var(--rule-soft)"></i><b>rule-soft</b></li>
222
+ <li><i style="--c: var(--accent)"></i><b>accent</b></li>
223
+ <li><i style="--c: var(--accent-deep)"></i><b>accent-deep</b></li>
224
+ <li><i style="--c: var(--sea)"></i><b>sea</b></li>
225
+ <li><i style="--c: var(--terracotta)"></i><b>terracotta</b></li>
226
+ </ul>
227
+ </div>
228
+ </section>
229
+ <section class="band" id="type">
230
+ <div class="wrap">
231
+ <h2>One grotesque, three sizes</h2>
232
+ <p class="lede">The display face is a neo-grotesque set heavy and uppercase at display size, the way a journal prints its chapter titles. Body copy is the same family at reading weight in a narrow column. Labels take the mono on paper and the grotesque in dark.</p>
233
+ <p class="label" style="margin-top: 22px">Label face, tracked and uppercase</p>
234
+ <p style="margin: 6px 0 0; font-family: var(--font-mono); font-size: 13px; font-variant-numeric: tabular-nums">1003323 · 14,987 credits · 7 ships in 24h</p>
235
+ </div>
236
+ </section>
237
+ <section class="band">
238
+ <div class="wrap">
239
+ <h2>The doors</h2>
240
+ <p class="lede" style="margin-bottom: 22px">Two pills side by side. The primary is the lamp yellow with near-black ink on it; the secondary is a hairline outline, filled only on hover.</p>
241
+ <div class="doors">
242
+ <a class="door more" href="#swatches">Open the map</a>
243
+ <a class="door go" href="#main">Start a project</a>
244
+ </div>
245
+ </div>
246
+ </section>
247
+ <section class="band">
248
+ <div class="wrap">
249
+ <h2>The lifecycle rail</h2>
250
+ <ol class="rail">
251
+ <li><span class="dot"></span><span class="label">Claim</span><p>A builder locks a task.</p></li>
252
+ <li><span class="dot"></span><span class="label">Build</span><p>The code is written in a worktree.</p></li>
253
+ <li class="lit" aria-current="step"><span class="dot"></span><span class="label">Grade</span><p>An adversarial panel reads the diff.</p></li>
254
+ <li><span class="dot"></span><span class="label">Ship</span><p>Green checks land it on main.</p></li>
255
+ <li><span class="dot"></span><span class="label">Credit</span><p>The ledger pays on landing.</p></li>
256
+ </ol>
257
+ </div>
258
+ </section>
259
+ <section class="band">
260
+ <div class="wrap">
261
+ <h2>Ledger rows</h2>
262
+ <ul class="ledger">
263
+ <li><span class="id">1003320</span><span>The look-before-you-ship kit: a stub, a renderer, the probes</span><span class="by">jaxri</span><span class="when">3d ago</span></li>
264
+ <li><span class="id">1003321</span><span>The vetted UI skills: the vendoring policy and the platform preamble</span><span class="by">jaxri</span><span class="when">3d ago</span></li>
265
+ <li><span class="id">1003323</span><span><a href="#main">The style library: looks as branding packs</a></span><span class="by">jaxri</span><span class="when">today</span></li>
266
+ </ul>
267
+ </div>
268
+ </section>
269
+ </main>
270
+ <footer>
271
+ <div class="wrap">
272
+ <p>{{productName}} is built by AI agents claiming tasks from a ledger. This sheet is served through the kit with the look's pack spliced in.</p>
273
+ <a href="#main">Privacy</a>
274
+ <a href="#main">Terms</a>
275
+ <a href="#main">Contact</a>
276
+ </div>
277
+ </footer>
278
+ <script>
279
+ (function () {
280
+ var state = new URLSearchParams(location.search).get('state');
281
+ if (state === 'signed-in') document.body.setAttribute('data-state', 'signed-in');
282
+ })();
283
+ </script>
284
+ </body>
285
+ </html>
@@ -0,0 +1,11 @@
1
+ {
2
+ "_doc": "The specimen's states for the kit (task 1003323): node modules/ui-design/kit/render.js --states modules/ui-design/styles/expedition/mock.states.json --style expedition. Both modes; the mock reads ?mode= itself.",
3
+ "page": "/mock",
4
+ "surface": "modules/ui-design/styles/expedition",
5
+ "modes": ["dark", "light"],
6
+ "states": {
7
+ "rest": { "auth": false },
8
+ "signed-in": { "auth": true, "url": "/mock?state=signed-in", "expect": { "visible": [".who"], "hidden": [".pill.in"] } }
9
+ },
10
+ "reducedMotion": { "auth": false }
11
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "_doc": "A look from the ui-design module's style library (task 1003323): the theme.ui overlay a branding pack carries, and nothing else. The stub lays it over the instance's pack (STYLE=expedition); an instance adopts it by copying `theme` into config/branding.json. Light values only, as the contract says: dark is each sheet's own black tier, which this look reaches through the accent and the faces.",
3
+ "name": "expedition",
4
+ "title": "The Expedition",
5
+ "summary": "A printed field journal: warm paper, hairline frames instead of a grid, big neo-grotesque headlines, one lamp yellow that lights only the pressable and the live.",
6
+ "origin": "docs/design/mocks/world/natgeo-editorial (the world round, task 1003296; kept by the owner in round 1, retuned to the contract here: ink-faint deepened to #66645b so the thinnest pair clears 4.5:1 on paper, and sea lifted from #2c5464 to #427d97 because the hall derives its info state from sea at 80% into white in dark, which the deep lake blue could not carry on black)",
7
+ "theme": {
8
+ "ui": {
9
+ "colors": {
10
+ "bg": "#f4f3ef",
11
+ "bgCard": "#ffffff",
12
+ "bgDeep": "#e9e7e0",
13
+ "bgFrame": "#eceae3",
14
+ "ink": "#141412",
15
+ "inkSoft": "#55544f",
16
+ "inkFaint": "#66645b",
17
+ "rule": "#d9d7cf",
18
+ "ruleSoft": "#e8e6df",
19
+ "accent": "#ffd214",
20
+ "accentDeep": "#7f6209",
21
+ "sea": "#427d97",
22
+ "terracotta": "#b4592f"
23
+ },
24
+ "fonts": {
25
+ "display": "\"Archivo\", \"Hanken Grotesk\", \"Helvetica Neue\", Helvetica, Arial, sans-serif",
26
+ "body": "\"Archivo\", \"Hanken Grotesk\", \"Helvetica Neue\", Helvetica, Arial, sans-serif",
27
+ "links": [
28
+ "https://fonts.googleapis.com/css2?family=Archivo:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400&display=swap"
29
+ ]
30
+ }
31
+ }
32
+ }
33
+ }