@bongos/core 1.24.80 → 1.24.81

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 (106) hide show
  1. package/.bongos-core.json +125 -110
  2. package/docs/adr/0402-helm-is-the-halls-look-and-the-hall-is-dark-only.md +142 -0
  3. package/docs/adr/README.md +1 -0
  4. package/docs/copy-inventory.md +26 -31
  5. package/docs/copy-registry.json +29 -86
  6. package/docs/module-api-changelog.md +2 -0
  7. package/docs/page-inventory.json +1 -3
  8. package/docs/page-readings.json +94 -94
  9. package/modules/hall-ui/public/ai-studio.html +5 -3
  10. package/modules/hall-ui/public/ai-studio.states.json +1 -0
  11. package/modules/hall-ui/public/atlas.html +3 -3
  12. package/modules/hall-ui/public/atlas.states.json +1 -0
  13. package/modules/hall-ui/public/blockers.html +3 -3
  14. package/modules/hall-ui/public/board-room.html +3 -3
  15. package/modules/hall-ui/public/board-room.states.json +1 -0
  16. package/modules/hall-ui/public/city.css +1 -3
  17. package/modules/hall-ui/public/city.html +5 -8
  18. package/modules/hall-ui/public/city.js +10 -55
  19. package/modules/hall-ui/public/city.states.json +7 -32
  20. package/modules/hall-ui/public/collab.html +3 -3
  21. package/modules/hall-ui/public/collab.states.json +1 -0
  22. package/modules/hall-ui/public/commands.html +3 -3
  23. package/modules/hall-ui/public/commands.states.json +1 -0
  24. package/modules/hall-ui/public/controls.css +63 -11
  25. package/modules/hall-ui/public/copy-desk.html +3 -3
  26. package/modules/hall-ui/public/copy-desk.states.json +1 -0
  27. package/modules/hall-ui/public/deploy.html +3 -3
  28. package/modules/hall-ui/public/deploy.states.json +1 -0
  29. package/modules/hall-ui/public/goal-map.html +3 -3
  30. package/modules/hall-ui/public/goals.html +3 -3
  31. package/modules/hall-ui/public/goals.states.json +1 -0
  32. package/modules/hall-ui/public/government.html +3 -3
  33. package/modules/hall-ui/public/government.states.json +1 -0
  34. package/modules/hall-ui/public/idea.html +3 -3
  35. package/modules/hall-ui/public/idea.states.json +1 -0
  36. package/modules/hall-ui/public/ideas.html +3 -3
  37. package/modules/hall-ui/public/ideas.states.json +1 -0
  38. package/modules/hall-ui/public/index-founding.states.json +1 -0
  39. package/modules/hall-ui/public/index-genesis-decide.states.json +1 -0
  40. package/modules/hall-ui/public/index-genesis-demo.states.json +1 -0
  41. package/modules/hall-ui/public/index-genesis.states.json +1 -0
  42. package/modules/hall-ui/public/index.html +4 -4
  43. package/modules/hall-ui/public/index.states.json +1 -0
  44. package/modules/hall-ui/public/market-watch-item.html +3 -3
  45. package/modules/hall-ui/public/market-watch-item.states.json +1 -0
  46. package/modules/hall-ui/public/market-watch-rules.html +3 -3
  47. package/modules/hall-ui/public/market-watch-rules.states.json +1 -0
  48. package/modules/hall-ui/public/market-watch.html +3 -3
  49. package/modules/hall-ui/public/market-watch.states.json +1 -0
  50. package/modules/hall-ui/public/modules.html +3 -3
  51. package/modules/hall-ui/public/modules.states.json +1 -0
  52. package/modules/hall-ui/public/money.html +3 -3
  53. package/modules/hall-ui/public/money.states.json +1 -0
  54. package/modules/hall-ui/public/my-agents.html +3 -3
  55. package/modules/hall-ui/public/my-agents.states.json +1 -0
  56. package/modules/hall-ui/public/primer.html +3 -3
  57. package/modules/hall-ui/public/primer.states.json +1 -0
  58. package/modules/hall-ui/public/profile.html +3 -3
  59. package/modules/hall-ui/public/profile.states.json +1 -0
  60. package/modules/hall-ui/public/project-settings.html +3 -3
  61. package/modules/hall-ui/public/roster.html +3 -3
  62. package/modules/hall-ui/public/roster.states.json +1 -0
  63. package/modules/hall-ui/public/settings.html +3 -3
  64. package/modules/hall-ui/public/settings.states.json +1 -0
  65. package/modules/hall-ui/public/shell-game.css +87 -42
  66. package/modules/hall-ui/public/shell-game.js +41 -8
  67. package/modules/hall-ui/public/shell.js +8 -40
  68. package/modules/hall-ui/public/street-card.states.json +1 -0
  69. package/modules/hall-ui/public/street.css +1 -5
  70. package/modules/hall-ui/public/street.html +5 -9
  71. package/modules/hall-ui/public/street.js +8 -59
  72. package/modules/hall-ui/public/street.states.json +7 -32
  73. package/modules/hall-ui/public/studio.html +3 -3
  74. package/modules/hall-ui/public/studio.states.json +1 -0
  75. package/modules/hall-ui/public/style.css +124 -65
  76. package/modules/hall-ui/public/task.html +3 -3
  77. package/modules/hall-ui/public/task.states.json +1 -0
  78. package/modules/hall-ui/public/thinking.html +3 -3
  79. package/modules/hall-ui/public/thinking.states.json +1 -0
  80. package/modules/hall-ui/public/tweak-editor.html +3 -3
  81. package/modules/hall-ui/public/tweak-editor.states.json +1 -0
  82. package/modules/hall-ui/public/watch.html +3 -3
  83. package/modules/hall-ui/public/watch.states.json +1 -0
  84. package/modules/hall-ui/public/work-founding.states.json +1 -0
  85. package/modules/hall-ui/public/work.html +3 -3
  86. package/modules/hall-ui/public/work.states.json +1 -0
  87. package/modules/hall-ui/records/start-screen.md +6 -2
  88. package/modules/hall-ui/specimens/components.states.json +2 -1
  89. package/modules/ui-design/public/brand.html +2 -2
  90. package/package-lock.json +2 -2
  91. package/package.json +1 -1
  92. package/release-notes.json +6 -0
  93. package/scripts/hall-preview/README.md +2 -3
  94. package/src/bongos/serve-internal.js +7 -2
  95. package/src/hall-helm.js +79 -0
  96. package/src/module-api.js +1 -1
  97. package/tests/design_reference.mjs +1 -1
  98. package/tests/hall_builders_page_pass.mjs +2 -1
  99. package/tests/hall_city.mjs +15 -29
  100. package/tests/hall_controls.mjs +52 -4
  101. package/tests/hall_helm.mjs +187 -0
  102. package/tests/hall_record_world.mjs +4 -2
  103. package/tests/hall_start_screen.mjs +65 -2
  104. package/tests/hall_street.mjs +13 -26
  105. package/tests/hall_topbar_320.mjs +4 -2
  106. package/tests/nav_permission_atoms.mjs +1 -1
@@ -1,8 +1,13 @@
1
1
  {
2
- "_": "THE STREET (task 1004525, goal 1000125) and inside every building and district (task 1004526) through modules/ui-design/kit/render.js. The page draws GET /government/docket, GET /goals, GET /goals/rollups and the viewer's GET /builders/:id/earnings; against the kit's own stub none exists, so every state renders the bare street (the nine civic buildings, no districts, no pins) with the readings saying the docket could not be read: a real state the floors must hold in. To look at the populated street, run it against the hall-preview harness, whose government__docket.json fixture carries the reference design's seven sample matters (3 need you, 2 moving, 2 settled) and whose goals fixtures carry the open goals:\n\n node scripts/hall-preview/server.js --port 4625 --fixture-me\n node modules/ui-design/kit/render.js --states modules/hall-ui/public/street.states.json --base-in http://localhost:4625 --base-out http://localhost:4625\n\nThe page follows the OS mode until the switch is pressed (then the hall's own 'hall-theme' preference), so the kit's dark/light emulation renders both modes.",
2
+ "_": "THE STREET (task 1004525, goal 1000125) and inside every building and district (task 1004526) through modules/ui-design/kit/render.js. The page draws GET /government/docket, GET /goals, GET /goals/rollups and the viewer's GET /builders/:id/earnings; against the kit's own stub none exists, so every state renders the bare street (the nine civic buildings, no districts, no pins) with the readings saying the docket could not be read: a real state the floors must hold in. To look at the populated street, run it against the hall-preview harness, whose government__docket.json fixture carries the reference design's seven sample matters (3 need you, 2 moving, 2 settled) and whose goals fixtures carry the open goals:\n\n node scripts/hall-preview/server.js --port 4625 --fixture-me\n node modules/ui-design/kit/render.js --states modules/hall-ui/public/street.states.json --base-in http://localhost:4625 --base-out http://localhost:4625\n\nThe hall is dark only (task 1005192, ADR 0402): the page has no light/dark switch, so this file names the one mode.",
3
3
  "page": "/builders/street",
4
+ "modes": ["dark"],
4
5
  "_storage": "The hall asks a first-visit question (the session mode picker, craft-mode.js) over every page; seeding \"already asked\" renders the page a returning builder sees (task 1005080).",
5
- "storage": { "session": { "hall-craft-asked": "1" } },
6
+ "storage": {
7
+ "session": {
8
+ "hall-craft-asked": "1"
9
+ }
10
+ },
6
11
  "surface": "hall-ui",
7
12
  "stub": {
8
13
  "prefix": "/builders/",
@@ -40,7 +45,6 @@
40
45
  "visible": [
41
46
  "#streetBoard",
42
47
  "#streetSigns",
43
- "#streetMode",
44
48
  "#streetHome",
45
49
  "#app-topbar",
46
50
  "#fullscreen-toggle"
@@ -78,7 +82,6 @@
78
82
  "visible": [
79
83
  "#streetBoard",
80
84
  "#streetSigns",
81
- "#streetMode",
82
85
  "#fullscreen-toggle"
83
86
  ],
84
87
  "hidden": [
@@ -122,34 +125,6 @@
122
125
  ]
123
126
  }
124
127
  },
125
- "switched": {
126
- "auth": true,
127
- "_": "The light/dark switch pressed once: the other mode, the street redrawn in it.",
128
- "actions": [
129
- [
130
- "wait",
131
- 600
132
- ],
133
- [
134
- "clickIfVisible",
135
- "[data-craft-close]"
136
- ],
137
- [
138
- "click",
139
- "#streetMode"
140
- ],
141
- [
142
- "wait",
143
- 400
144
- ]
145
- ],
146
- "expect": {
147
- "visible": [
148
- "#streetBoard",
149
- "#streetSigns"
150
- ]
151
- }
152
- },
153
128
  "focus": {
154
129
  "auth": true,
155
130
  "_": "Keyboard: the wordmark back to the city focused, its ring drawn.",
@@ -12,7 +12,7 @@
12
12
  <link rel="icon" href="/modules/ui-design/public/brand/favicon.svg" type="image/svg+xml">
13
13
  <link rel="preconnect" href="https://fonts.googleapis.com">
14
14
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
15
- <link rel="stylesheet" href="/builders/style.css?v=2026-11-10-options">
15
+ <link rel="stylesheet" href="/builders/style.css?v=2026-11-11-helm">
16
16
  <link rel="stylesheet" href="/builders/studio.css?v=2026-10-09-day">
17
17
  <link rel="stylesheet" href="/builders/approval-queue.css?v=2026-09-29-aqfix">
18
18
  <link rel="stylesheet" href="/builders/home-gallery.css?v=2026-11-04-studio">
@@ -222,10 +222,10 @@
222
222
  <div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
223
223
 
224
224
  <script src="/builders/dom-utils.js?v=2026-11-05-numbers"></script>
225
- <script src="/builders/shell-game.js?v=2026-11-10-options"></script>
225
+ <script src="/builders/shell-game.js?v=2026-11-11-helm"></script>
226
226
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
227
227
  <script src="/builders/craft-mode.js?v=2026-11-10-visor"></script>
228
- <script src="/builders/shell.js?v=2026-11-10-character"></script>
228
+ <script src="/builders/shell.js?v=2026-11-11-helm"></script>
229
229
  <script src="/builders/hall-dialog.js"></script>
230
230
  <script src="/builders/palette.js" defer></script>
231
231
  <!-- The kit, for its ONE renderer: the full-size ship-time visual figure
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "_": "The studio home (task 1003971 / BV2.TW16), built 1:1 on docs/design/mocks/tweak-mode/Main.dc.html: the night room, the greeting and its sub-line (editable in place as a tweak of builders:studio), the tally, Resume, and three quick actions opening glass panels (the Tweak/CopyWrite Flow, the Approval queue, Artist Review Status). Behind a quiet door, the older reviews (R06 of goal 1000074, task 1003117; retired in TW14) still answer the reviews filed before Tweak Mode. Against the kit's own stub the page renders its unread states (no copy-desk feeds). TO SEE IT POPULATED, point the kit at the hall-preview harness: `node scripts/hall-preview/server.js --port 4636 --fixture-me` then `render.js --base-in http://builders.localhost:4636 --base-out http://builders.localhost:4636`. The harness answers the tally, the pages and the next page from copy-desk__tally.json, copy-desk__pages.json and copy-desk__next.json (built by the real composers), Resume's counter from copy-desk__pages__draft.json, the studio's own lines from copy-desk__pages__draft-studio.json, the claim and the draft save from its CANNED WRITES, and the older reviews from tasks.json (whose first row IS a cascade artist review).",
3
3
  "page": "/builders/studio",
4
+ "modes": ["dark"],
4
5
  "_storage": "The hall asks a first-visit question (the session mode picker, craft-mode.js) over every page; seeding \"already asked\" renders the page a returning builder sees (task 1005080).",
5
6
  "storage": { "session": { "hall-craft-asked": "1" } },
6
7
  "surface": "hall-ui",
@@ -32,15 +32,19 @@
32
32
  grounds in both modes with ~9% of headroom. tests/hall_tokens.mjs measures
33
33
  them; do not hand-tune one without re-running it.
34
34
 
35
- b. THE HALL KEEPS BOTH MODES, ON ITS OWN SWITCH. The apex went dark only
36
- (ADR 0204), so light is the hall's alone. shell.js writes
37
- html[data-theme] — NOT the world's html[data-mode] — so the dark tier is
38
- written twice on THAT pair: html[data-theme="dark"] and, for first paint
39
- before the script runs, @media (prefers-color-scheme: dark)
40
- html:not([data-theme]). Both bodies are byte-identical; the twins rule is
41
- what keeps them so. html[data-theme="dark"] is (0,1,1) and outranks the
42
- pack's injected :root (0,1,0), which is what lets dark win over the pack
43
- while the instance's accent survives.
35
+ b. THE HALL IS DARK ONLY, AND ITS DARK TIER IS HELM (task 1005192, ADR
36
+ 0402). The server stamps html[data-theme="dark"] on every hall page and
37
+ shell.js sets it again; nothing offers light. The attribute is the
38
+ hall's own — NOT the world's html[data-mode] — and the dark tier is
39
+ still written twice on that pair: html[data-theme="dark"] and @media
40
+ (prefers-color-scheme: dark) html:not([data-theme]), for a page read
41
+ without the server's stamp. Both bodies are byte-identical; the twins
42
+ rule is what keeps them so. html[data-theme="dark"] is (0,1,1) and
43
+ outranks the pack's injected :root (0,1,0), which is what lets the night
44
+ win over the pack while the instance's accent survives. The light values
45
+ in :root are no longer rendered by the hall; they stay until the light
46
+ tier's own removal (the ADR 0204 precedent), so the sheets and tests
47
+ that still measure light keep measuring.
44
48
 
45
49
  c. --line IS A WIDTH HERE, NOT A COLOUR (DESIGN.md warns about exactly this
46
50
  name). The hairline's COLOUR is --rule / --rule-soft.
@@ -253,9 +257,67 @@
253
257
  --plate: none;
254
258
  --plate-blend: lighten;
255
259
  --plate-veil: none;
256
- }
257
260
 
258
- /* ---------- dark theme ----------
261
+ /* ---- HELM: the hall's look (task 1005192, ADR 0402). The kit's recipes,
262
+ named once here so no page sheet types one in. None of them flips
263
+ with the mode; the Helm NEUTRALS are the dark tier below, which is
264
+ the only tier the hall renders.
265
+
266
+ TYPE, TWO VOICES. The name voice names a thing (a title, a button, an
267
+ eyebrow): the display face in wide tracked capitals. Everything said
268
+ to you is the body face in plain sentences. --helm-display and
269
+ --helm-body are the Helm faces themselves; html[data-faces="helm"]
270
+ (below the dark twins) hands them to --font-display / --font-body for
271
+ a hall whose pack has not chosen faces of its own. ---- */
272
+ --helm-display: "Barlow Condensed", "Arial Narrow", "Segoe UI", system-ui, sans-serif;
273
+ --helm-body: "Barlow", "Segoe UI", system-ui, -apple-system, sans-serif;
274
+ --name-face: var(--font-display);
275
+ --name-weight: 500;
276
+ --name-weight-lit: 600;
277
+ --name-case: uppercase;
278
+ --name-space: .24em;
279
+ --name-space-wide: .3em;
280
+ --name-space-tight: .16em;
281
+ /* a title's glow: the soft ink, never the accent (the accent is for what you
282
+ can act on) */
283
+ --name-glow: 0 0 22px color-mix(in srgb, var(--ink-soft) 45%, transparent);
284
+
285
+ /* SHAPE, THREE MOVES (the arc is the visor's and is not in this slice).
286
+ THE CUT CORNER is anything you can press: top-left and bottom-right cut,
287
+ no pill. A clip-path clips an outline, so a cut control's focus is the
288
+ inset two-tone ring --press-focus: the focus colour on the edge, then a
289
+ band of the ground, so one of the two reads on any fill. */
290
+ --cut: 12px;
291
+ --cut-sm: 8px;
292
+ --cut-path: polygon(var(--cut) 0, 100% 0, 100% calc(100% - var(--cut)), calc(100% - var(--cut)) 100%, 0 100%, 0 var(--cut));
293
+ --cut-path-sm: polygon(var(--cut-sm) 0, 100% 0, 100% calc(100% - var(--cut-sm)), calc(100% - var(--cut-sm)) 100%, 0 100%, 0 var(--cut-sm));
294
+ --press-radius: 0px;
295
+ --press-fill: var(--surface-2);
296
+ --press-focus: inset 0 0 0 2px var(--focus), inset 0 0 0 4px var(--bg);
297
+ /* THE SEGMENT is progress: one small skewed bar per step. */
298
+ --seg-w: 40px;
299
+ --seg-h: 8px;
300
+ --seg-gap: var(--ds-space-hair);
301
+ --seg-skew: -28deg;
302
+
303
+ /* THE PANEL OVER ART: the ground at 72%, closed left and right by the strong
304
+ hairline. --helm-inset is how far a full-height panel stands off the left
305
+ edge: nothing on a phone, growing to its full step on a desk, with no
306
+ breakpoint. */
307
+ --night-glass: color-mix(in srgb, var(--bg) 72%, transparent);
308
+ --line-strong: 1.5px;
309
+ --helm-panel-w: 400px;
310
+ --helm-row: 60px;
311
+ --helm-mark: 60px;
312
+ --helm-inset: clamp(0px, calc((100vw - var(--helm-panel-w)) * .1), 96px);
313
+ }
314
+
315
+ /* ---------- dark theme: the Helm neutrals ----------
316
+ The only tier the hall renders (task 1005192, ADR 0402). Each colour has one
317
+ job: NIGHT is the ground and every panel (--bg; --bg-card is the night
318
+ lifted a step, for a panel at rest); ICE is information you read
319
+ (--ink-soft, and the hairlines as ice at 40% and 20%); WHITE is names and
320
+ numbers (--ink); the pack's --accent is only what you can act on.
259
321
  Only the NEUTRALS and the mode-dependent derivations flip; the pack's
260
322
  accent/sea/terracotta + fonts survive (the Unpinned Accent Rule — a dark
261
323
  block may pin no accent literal, or a re-themed instance cannot reach dark),
@@ -265,24 +327,24 @@
265
327
 
266
328
  html[data-theme="dark"] {
267
329
  color-scheme: dark;
268
- --bg: #000000;
269
- --bg-card: #101012;
270
- --bg-deep: #000000;
271
- --bg-frame: #08080a;
330
+ --bg: #050d16;
331
+ --bg-card: #0a1622;
332
+ --bg-deep: #050d16;
333
+ --bg-frame: #07111b;
272
334
  --ink: #ffffff;
273
- --ink-soft: #c0c0c0;
274
- --ink-faint: #a8a8a8;
275
- --rule: rgba(255, 255, 255, .16);
276
- --rule-soft: rgba(255, 255, 255, .08);
277
- --glass: rgba(255, 255, 255, .11);
278
- --glass-strong: rgba(255, 255, 255, .17);
279
- --glass-edge: rgba(255, 255, 255, .13);
335
+ --ink-soft: #c8f1f7;
336
+ --ink-faint: #a9cdd4;
337
+ --rule: rgba(200, 241, 247, .4);
338
+ --rule-soft: rgba(200, 241, 247, .2);
339
+ --glass: rgba(200, 241, 247, .1);
340
+ --glass-strong: rgba(200, 241, 247, .16);
341
+ --glass-edge: rgba(200, 241, 247, .2);
280
342
  --glass-blur: 18px;
281
- --void: #000000;
343
+ --void: #050d16;
282
344
  --void-ink: var(--ink);
283
- --void-edge: rgba(255, 255, 255, .16);
345
+ --void-edge: rgba(200, 241, 247, .4);
284
346
  --accent-ink: var(--accent);
285
- --accent-tint: color-mix(in srgb, var(--accent) 22%, #0b0a09);
347
+ --accent-tint: color-mix(in srgb, var(--accent) 22%, #050d16);
286
348
  --accent-glow: 0 8px 28px color-mix(in srgb, var(--accent) 38%, transparent);
287
349
  --ok: #4ade80;
288
350
  --ok-weak: color-mix(in srgb, #4ade80 14%, var(--bg-card));
@@ -293,36 +355,36 @@ html[data-theme="dark"] {
293
355
  --info: color-mix(in srgb, var(--sea) 80%, #ffffff);
294
356
  --info-weak: color-mix(in srgb, var(--info) 14%, var(--bg-card));
295
357
  --focus: var(--accent);
296
- --label-face: var(--font-body);
358
+ --label-face: var(--font-display);
297
359
  --label-size: var(--ds-text-2xs-plus);
298
- --label-space: .1em;
360
+ --label-space: .2em;
299
361
  --type-halo: 0 2px 18px rgba(0, 0, 0, .94), 0 0 54px rgba(0, 0, 0, .72);
300
362
  --surface-2: color-mix(in srgb, var(--ink) 6%, var(--bg-card));
301
- --plate-veil: linear-gradient(to bottom, rgba(0, 0, 0, .82), rgba(0, 0, 0, .93));
363
+ --plate-veil: linear-gradient(to bottom, rgba(5, 13, 22, .82), rgba(5, 13, 22, .93));
302
364
  }
303
365
  html[data-theme="dark"] body { background: var(--bg); }
304
366
 
305
367
  @media (prefers-color-scheme: dark) {
306
368
  html:not([data-theme]) {
307
369
  color-scheme: dark;
308
- --bg: #000000;
309
- --bg-card: #101012;
310
- --bg-deep: #000000;
311
- --bg-frame: #08080a;
370
+ --bg: #050d16;
371
+ --bg-card: #0a1622;
372
+ --bg-deep: #050d16;
373
+ --bg-frame: #07111b;
312
374
  --ink: #ffffff;
313
- --ink-soft: #c0c0c0;
314
- --ink-faint: #a8a8a8;
315
- --rule: rgba(255, 255, 255, .16);
316
- --rule-soft: rgba(255, 255, 255, .08);
317
- --glass: rgba(255, 255, 255, .11);
318
- --glass-strong: rgba(255, 255, 255, .17);
319
- --glass-edge: rgba(255, 255, 255, .13);
375
+ --ink-soft: #c8f1f7;
376
+ --ink-faint: #a9cdd4;
377
+ --rule: rgba(200, 241, 247, .4);
378
+ --rule-soft: rgba(200, 241, 247, .2);
379
+ --glass: rgba(200, 241, 247, .1);
380
+ --glass-strong: rgba(200, 241, 247, .16);
381
+ --glass-edge: rgba(200, 241, 247, .2);
320
382
  --glass-blur: 18px;
321
- --void: #000000;
383
+ --void: #050d16;
322
384
  --void-ink: var(--ink);
323
- --void-edge: rgba(255, 255, 255, .16);
385
+ --void-edge: rgba(200, 241, 247, .4);
324
386
  --accent-ink: var(--accent);
325
- --accent-tint: color-mix(in srgb, var(--accent) 22%, #0b0a09);
387
+ --accent-tint: color-mix(in srgb, var(--accent) 22%, #050d16);
326
388
  --accent-glow: 0 8px 28px color-mix(in srgb, var(--accent) 38%, transparent);
327
389
  --ok: #4ade80;
328
390
  --ok-weak: color-mix(in srgb, #4ade80 14%, var(--bg-card));
@@ -333,16 +395,27 @@ html[data-theme="dark"] body { background: var(--bg); }
333
395
  --info: color-mix(in srgb, var(--sea) 80%, #ffffff);
334
396
  --info-weak: color-mix(in srgb, var(--info) 14%, var(--bg-card));
335
397
  --focus: var(--accent);
336
- --label-face: var(--font-body);
398
+ --label-face: var(--font-display);
337
399
  --label-size: var(--ds-text-2xs-plus);
338
- --label-space: .1em;
400
+ --label-space: .2em;
339
401
  --type-halo: 0 2px 18px rgba(0, 0, 0, .94), 0 0 54px rgba(0, 0, 0, .72);
340
402
  --surface-2: color-mix(in srgb, var(--ink) 6%, var(--bg-card));
341
- --plate-veil: linear-gradient(to bottom, rgba(0, 0, 0, .82), rgba(0, 0, 0, .93));
403
+ --plate-veil: linear-gradient(to bottom, rgba(5, 13, 22, .82), rgba(5, 13, 22, .93));
342
404
  }
343
405
  html:not([data-theme]) body { background: var(--bg); }
344
406
  }
345
407
 
408
+ /* The Helm faces (task 1005192, ADR 0402). The server stamps data-faces="helm"
409
+ on a hall page whose pack still names the platform's default faces
410
+ (src/hall-helm.js) and links the two families. (0,1,1) outranks the pack's
411
+ spliced :root, so the hall reads Barlow while the landing keeps the pack's
412
+ face; a hall that wears faces of its own never gets the attribute and keeps
413
+ them. */
414
+ html[data-faces="helm"] {
415
+ --font-display: var(--helm-display);
416
+ --font-body: var(--helm-body);
417
+ }
418
+
346
419
  /* The Kill Switch Rule (DESIGN.md). Nothing escapes it, and no motion is
347
420
  authored in JavaScript, because JavaScript motion escapes it. */
348
421
  @media (prefers-reduced-motion: reduce) {
@@ -1182,23 +1255,7 @@ html[data-handoff="on"] .app-content { padding: 0; }
1182
1255
  .topbar-menu:hover { color: var(--ink); }
1183
1256
  .topbar-menu svg { width: 16px; height: 16px; }
1184
1257
 
1185
- .theme-toggle {
1186
- display: inline-flex;
1187
- align-items: center;
1188
- justify-content: center;
1189
- width: 32px; height: 32px;
1190
- border: 0;
1191
- border-radius: var(--radius-pill);
1192
- background: none;
1193
- color: var(--ink-soft);
1194
- cursor: pointer;
1195
- padding: 0;
1196
- flex-shrink: 0;
1197
- }
1198
- .theme-toggle:hover { color: var(--ink); }
1199
- .theme-toggle svg { width: 16px; height: 16px; }
1200
-
1201
- /* task 1475: the accessibility zoom control — sibling of the theme toggle.
1258
+ /* task 1475: the accessibility zoom control.
1202
1259
  Widens to fit the "125%"/"150%" label when zoom is active. */
1203
1260
  .zoom-toggle {
1204
1261
  display: inline-flex;
@@ -1991,7 +2048,7 @@ html.pb-editing main { padding-bottom: 180px; }
1991
2048
  tighter and each icon button is 28px — still above the 24px floor — so the
1992
2049
  whole row fits with room to spare. Pinned in tests/hall_topbar_320.mjs. */
1993
2050
  .app-topbar { gap: var(--ds-space-hair); padding: 0 var(--ds-space-xs); }
1994
- .topbar-menu, .theme-toggle, .fullscreen-toggle { width: 28px; height: 28px; }
2051
+ .topbar-menu, .fullscreen-toggle { width: 28px; height: 28px; }
1995
2052
  .zoom-toggle { min-width: 28px; height: 28px; padding: 0 6px; }
1996
2053
  .topbar-side .topbar-jump { min-width: 28px; padding: 0 6px; }
1997
2054
  }
@@ -2073,11 +2130,13 @@ html.pb-editing main { padding-bottom: 180px; }
2073
2130
  /* Focus: the world's two-tone ring — a 2px accent-derived outline at 3px offset
2074
2131
  inside an 8px --bg halo, so the indicator keeps its own edge over whatever it
2075
2132
  lands on (a bare outline measured 1.1:1 over the light bar). The rail's items
2076
- ring inside themselves instead, or the halo would spill out of the 64px strip. */
2133
+ ring inside themselves instead, or the halo would spill out of the 64px strip.
2134
+ A CUT control (controls.css) hands in --focus-ring: its clip-path would clip
2135
+ the outline and the halo away, so its ring is the inset two-tone one. */
2077
2136
  :focus-visible {
2078
2137
  outline: 2px solid var(--focus);
2079
2138
  outline-offset: 3px;
2080
- box-shadow: 0 0 0 8px var(--bg);
2139
+ box-shadow: var(--focus-ring, 0 0 0 8px var(--bg));
2081
2140
  border-radius: var(--radius-sm);
2082
2141
  }
2083
2142
  .nav-item:focus-visible,
@@ -8,7 +8,7 @@
8
8
  <link rel="icon" href="/modules/ui-design/public/brand/favicon.svg" type="image/svg+xml">
9
9
  <link rel="preconnect" href="https://fonts.googleapis.com">
10
10
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
11
- <link rel="stylesheet" href="/builders/style.css?v=2026-11-10-options">
11
+ <link rel="stylesheet" href="/builders/style.css?v=2026-11-11-helm">
12
12
  <!-- The record archetype (shared with idea.html) and this page's own two
13
13
  shapes. Promoted out of an inline <style> by task 1003305 — the block was
14
14
  the hall's last substantive one and sat at its hall_audit ratchet. -->
@@ -57,10 +57,10 @@
57
57
  <!-- The app shell (sidebar + top bar + footer). Dependency-free; runs at parse
58
58
  time so the chrome exists before the deferred page scripts execute. -->
59
59
  <script src="/builders/dom-utils.js?v=2026-11-05-numbers"></script>
60
- <script src="/builders/shell-game.js?v=2026-11-10-options"></script>
60
+ <script src="/builders/shell-game.js?v=2026-11-11-helm"></script>
61
61
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
62
62
  <script src="/builders/craft-mode.js?v=2026-11-10-visor"></script>
63
- <script src="/builders/shell.js?v=2026-11-10-character"></script>
63
+ <script src="/builders/shell.js?v=2026-11-11-helm"></script>
64
64
  <script src="/builders/hall-dialog.js"></script>
65
65
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
66
66
  <script src="/builders/palette.js" defer></script>
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "_": "The hall's TASK RECORD through modules/ui-design/kit/render.js (task 1003305). The record's own controls — the dependency links, the lifecycle buttons, the figure band, the way back — only exist once a task has LOADED, so the floors here are run against the hall-preview harness rather than the kit's own stub, which carries the public-landing feeds and not the hall's:\n\n node scripts/hall-preview/server.js --port 4612 --fixture-me\n node modules/ui-design/kit/render.js --states modules/hall-ui/public/task.states.json --base-in http://builders.localhost:4612 --base-out http://builders.localhost:4612\n\nRun against the kit's own stubs instead and every state renders `no such task`, which is a real state and is the `missing` one below — just not the one the re-skin changed.",
3
3
  "page": "/task/2166",
4
+ "modes": ["dark"],
4
5
  "_storage": "The hall asks a first-visit question (the session mode picker, craft-mode.js) over every page; seeding \"already asked\" renders the page a returning builder sees (task 1005080).",
5
6
  "storage": { "session": { "hall-craft-asked": "1" } },
6
7
  "surface": "hall-ui",
@@ -12,7 +12,7 @@
12
12
  links, injected into this head by the server like every hall page's
13
13
  (tests/hall_tokens.mjs: no hall page hardcodes a web-font stylesheet).
14
14
  The template carried its own Google Fonts link for the same two faces. -->
15
- <link rel="stylesheet" href="/builders/style.css?v=2026-11-10-options">
15
+ <link rel="stylesheet" href="/builders/style.css?v=2026-11-11-helm">
16
16
  <link rel="stylesheet" href="/builders/visor.css?v=2026-11-10-visor">
17
17
  <link rel="stylesheet" href="/builders/thinking.css?v=2026-11-10-visor">
18
18
  </head>
@@ -140,10 +140,10 @@
140
140
  </div>
141
141
 
142
142
  <script src="/builders/dom-utils.js?v=2026-11-05-numbers"></script>
143
- <script src="/builders/shell-game.js?v=2026-11-10-options"></script>
143
+ <script src="/builders/shell-game.js?v=2026-11-11-helm"></script>
144
144
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
145
145
  <script src="/builders/craft-mode.js?v=2026-11-10-visor"></script>
146
- <script src="/builders/shell.js?v=2026-11-10-character"></script>
146
+ <script src="/builders/shell.js?v=2026-11-11-helm"></script>
147
147
  <script src="/builders/hall-dialog.js"></script>
148
148
  <!-- task 1005148: the visor (glass over the scene, game mode only; ADR 0399), after the shell and hall-dialog.js -->
149
149
  <script src="/builders/visor.js?v=2026-11-10-visor"></script>
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "_": "THE SKY (task 1004231 / sky part 3 of 5, goal 1000095; ADR 0331) through modules/ui-design/kit/render.js. The page draws GET /sky + GET /sky/mine; against the kit's own stub neither exists, so every state below renders the EMPTY sky — a real state the floors must hold in (the composer, the tour, the list drawer and the lenses all exist with no thought filed). To look at the populated sky, run it against the hall-preview harness, whose sky.json + sky__mine.json fixtures carry the wells and one of each of the five objects:\n\n node scripts/hall-preview/server.js --port 4615 --fixture-me\n node modules/ui-design/kit/render.js --states modules/hall-ui/public/thinking.states.json --base-in http://localhost:4615 --base-out http://localhost:4615\n\nThe tour opens by itself on a first visit (sky-tour-seen), so states that want the bare sky skip it first.\n\nIN THE HALL (task 1004327): the page sits in the hall chrome, so it renders in BOTH modes — the chrome follows the hall theme and the sky's stage stays the void in both. The full-* states press the shell's full-screen switch: the sidebar and the top bar leave, and the one button that brings them back floats top right.",
3
3
  "page": "/builders/thinking",
4
+ "modes": ["dark"],
4
5
  "_storage": "The hall asks a first-visit question (the session mode picker, craft-mode.js) over every page; seeding \"already asked\" renders the page a returning builder sees (task 1005080).",
5
6
  "storage": { "session": { "hall-craft-asked": "1" } },
6
7
  "surface": "hall-ui",
@@ -10,7 +10,7 @@
10
10
  <link rel="icon" href="/modules/ui-design/public/brand/favicon.svg" type="image/svg+xml">
11
11
  <link rel="preconnect" href="https://fonts.googleapis.com">
12
12
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
13
- <link rel="stylesheet" href="/builders/style.css?v=2026-11-10-options">
13
+ <link rel="stylesheet" href="/builders/style.css?v=2026-11-11-helm">
14
14
  <link rel="stylesheet" href="/builders/tweak-editor.css?v=2026-09-29-tw27-aqfix">
15
15
  </head>
16
16
  <!-- THE TWEAK EDITOR (task 1004321 / BV2.TW10, goal 1000095; ADR 0341 D4 and
@@ -143,10 +143,10 @@
143
143
  <div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
144
144
 
145
145
  <script src="/builders/dom-utils.js?v=2026-11-05-numbers"></script>
146
- <script src="/builders/shell-game.js?v=2026-11-10-options"></script>
146
+ <script src="/builders/shell-game.js?v=2026-11-11-helm"></script>
147
147
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
148
148
  <script src="/builders/craft-mode.js?v=2026-11-10-visor"></script>
149
- <script src="/builders/shell.js?v=2026-11-10-character"></script>
149
+ <script src="/builders/shell.js?v=2026-11-11-helm"></script>
150
150
  <script src="/builders/hall-dialog.js"></script>
151
151
  <script src="/builders/palette.js" defer></script>
152
152
  <script src="/builders/brand-holes.js?v=2026-09-29-aqfix"></script>
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "_": "The tweak editor (task 1004321 / BV2.TW10), built 1:1 on docs/design/mocks/tweak-mode/Editor.dc.html. Against the kit's own stub the page renders its could-not-read state (no /copy-desk feed), a state the floors must hold in. TO SEE IT POPULATED, point the kit at the hall-preview harness: `node scripts/hall-preview/server.js --port 4631 --fixture-me`, then `render.js --page '/builders/tweak-editor?page=landing:index' --base-in http://builders.localhost:4631 --base-out http://builders.localhost:4631`. The harness answers the read from fixtures/copy-desk__pages__draft.json (the real landing:index reading with the artboard's two rewrites as the saved draft), next up from copy-desk__next.json, and the autosave, the submit and the claim from its canned writes.",
3
3
  "page": "/builders/tweak-editor?page=landing:index",
4
+ "modes": ["dark"],
4
5
  "_storage": "The hall asks a first-visit question (the session mode picker, craft-mode.js) over every page; seeding \"already asked\" renders the page a returning builder sees (task 1005080).",
5
6
  "storage": { "session": { "hall-craft-asked": "1" } },
6
7
  "surface": "hall-ui",
@@ -11,7 +11,7 @@
11
11
  <link rel="icon" href="/modules/ui-design/public/brand/favicon.svg" type="image/svg+xml">
12
12
  <link rel="preconnect" href="https://fonts.googleapis.com">
13
13
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
14
- <link rel="stylesheet" href="/builders/style.css?v=2026-11-10-options">
14
+ <link rel="stylesheet" href="/builders/style.css?v=2026-11-11-helm">
15
15
  <!-- The oversight family's sheet (task 1003469): the figure band, the group
16
16
  head, the row, the form. Then the page's own: severities, the report
17
17
  reader, the grade trend. The attention tiles + tabs come from style.css's
@@ -269,10 +269,10 @@
269
269
  <!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
270
270
  chrome exists before the page script runs. -->
271
271
  <script src="/builders/dom-utils.js?v=2026-11-05-numbers"></script>
272
- <script src="/builders/shell-game.js?v=2026-11-10-options"></script>
272
+ <script src="/builders/shell-game.js?v=2026-11-11-helm"></script>
273
273
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
274
274
  <script src="/builders/craft-mode.js?v=2026-11-10-visor"></script>
275
- <script src="/builders/shell.js?v=2026-11-10-character"></script>
275
+ <script src="/builders/shell.js?v=2026-11-11-helm"></script>
276
276
  <script src="/builders/hall-dialog.js"></script>
277
277
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
278
278
  <script src="/builders/palette.js" defer></script>
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "_": "Watch — the attention board behind requireGovernmentPage. The SEALED state (a viewer below the gate) is a real render, not an error page, so it is a state here. Written with the re-skin (task 1003307) so this page is MEASURED at three widths in both modes rather than looked at once.",
3
3
  "page": "/builders/watch",
4
+ "modes": ["dark"],
4
5
  "_storage": "The hall asks a first-visit question (the session mode picker, craft-mode.js) over every page; seeding \"already asked\" renders the page a returning builder sees (task 1005080).",
5
6
  "storage": { "session": { "hall-craft-asked": "1" } },
6
7
  "surface": "hall-ui",
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "_": "Project founding mode (task 1004422) on an ordinary hall page: the founding band above the topbar and today's nav items asleep, rendered from a /me that says founding (kit fixture me-founding.json, the real server shaper's output at stage strategize). The page itself is work.states.json's; only the identity differs. The no-founding case is every other hall states file.",
3
3
  "page": "/builders/work",
4
+ "modes": ["dark"],
4
5
  "_storage": "The hall asks a first-visit question (the session mode picker, craft-mode.js) over every page; seeding \"already asked\" renders the page a returning builder sees (task 1005080).",
5
6
  "storage": { "session": { "hall-craft-asked": "1" } },
6
7
  "surface": "hall-ui",
@@ -8,7 +8,7 @@
8
8
  <link rel="icon" href="/modules/ui-design/public/brand/favicon.svg" type="image/svg+xml">
9
9
  <link rel="preconnect" href="https://fonts.googleapis.com">
10
10
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
11
- <link rel="stylesheet" href="/builders/style.css?v=2026-11-10-options">
11
+ <link rel="stylesheet" href="/builders/style.css?v=2026-11-11-helm">
12
12
  <!-- Page-local styles (task 2170) — extracted from the old inline <style>
13
13
  block per the hall placement rules; shared pager/count-pill styles now
14
14
  live in style.css's hall-kit section. -->
@@ -172,10 +172,10 @@
172
172
  <!-- The app shell (sidebar + top bar + footer). Dependency-free; runs at parse
173
173
  time so the chrome exists before the deferred page scripts execute. -->
174
174
  <script src="/builders/dom-utils.js?v=2026-11-05-numbers"></script>
175
- <script src="/builders/shell-game.js?v=2026-11-10-options"></script>
175
+ <script src="/builders/shell-game.js?v=2026-11-11-helm"></script>
176
176
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
177
177
  <script src="/builders/craft-mode.js?v=2026-11-10-visor"></script>
178
- <script src="/builders/shell.js?v=2026-11-10-character"></script>
178
+ <script src="/builders/shell.js?v=2026-11-11-helm"></script>
179
179
  <script src="/builders/hall-dialog.js"></script>
180
180
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
181
181
  <script src="/builders/palette.js" defer></script>
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "_": "The hall's Work Board through modules/ui-design/kit/render.js (task 1003304). Written with the re-skin so the board's four tabs and its selection state are measured at 1440/390/320 in both modes, not just looked at. The populated look is the hall-preview harness (scripts/hall-preview/server.js); this file is the FLOORS.",
3
3
  "page": "/builders/work",
4
+ "modes": ["dark"],
4
5
  "_storage": "The hall asks a first-visit question (the session mode picker, craft-mode.js) over every page; seeding \"already asked\" renders the page a returning builder sees (task 1005080).",
5
6
  "storage": { "session": { "hall-craft-asked": "1" } },
6
7
  "surface": "hall-ui",
@@ -11,11 +11,15 @@ Covers: Home (`shell-game.js` `start()`, `shell-game.css`, the hand-off in `welc
11
11
  - **Tips rotate** (`localStorage 'hall-game-tip'` counts them), so each load shows the next one. A tip must be true of the hall today; the first one is the Escape rule from `game-mode.md` (rewritten by task 1005144: Escape opens the options menu).
12
12
  - **The craft picker waits for the world.** While the start screen is up the shell asks no picker (`onAccess` returned true). `done` runs once the screen is gone and asks `OTBCraftMode.onAccess` then.
13
13
  - **Keys.** While either screen is up it keeps every key: the arrows and Tab walk the menu, Escape folds Extras away and does nothing else, so the shell's Escape cannot flip the bars underneath. Once the world shows, the last Escape opens the options menu (task 1005144); the screen's capture listener calls `preventDefault`, so the menu never opens from under it.
14
- - **The look.** The painting under the hall's `--scrim`, and on it one card of the hall's own tokens per screen (`--bg-card`, `--ink`, `--rule`; Start is the hall's primary pill, `--accent` under `--accent-on`), so both follow the hall's theme and the sheet holds no colour literal (`tests/hall_audit.mjs`). Sizes, corners and spacing are `--ds-*` tokens only; the sheet has no `@media` (the column is `max-width` in `rem` and wraps). The fade into the world is one CSS opacity transition, stopped by the hall's reduced-motion rule.
14
+ - **The look is Helm (task 1005192, [ADR 0402](../../../docs/adr/0402-helm-is-the-halls-look-and-the-hall-is-dark-only.md)).** The start screen is one full-height night panel over the painting (`--night-glass`, an ice hairline left and right at `--line-strong`), `--helm-panel-w` wide. On a desk it stands off the left edge by `--helm-inset`; that token is a `clamp`, so on a phone the panel is the whole width and the sheet still has no `@media`. In it: the mark (the project's logo when it has one) over the name in the name voice; Start as a full-width accent bar under `--accent-on` that names its key ("Enter", drawn by CSS so the choice's own text stays "Start"); the other four as quiet rows on `--rule-soft` hairlines; and at the foot, over the strong hairline, the tip the load screen will show next (`#gs-line`), with the Quit note under it when the browser keeps the tab. The rows are list rows in a panel, so they are bars, not cut buttons. A row's focus is the inset two-tone ring (`--press-focus`), which is what makes focus visible on the accent bar.
15
+ - **The load screen is the same panel, centred** over the painting under the hall's `--scrim`: the week in the name voice (`#gs-when`), one segment per week of the history (`#gs-segs`, the shared `.segs` / `.seg`; filled up to the week being shown, counted the way the sentence words it, and hidden from a screen reader because the sentence says the same), the city, and the tip under a hairline. With no city there are no segments.
16
+ - **The literal floor is zero.** Every colour, size, corner, shadow, face and measure in `shell-game.css` is a hall-tier token (`style.css`); `tests/hall_start_screen.mjs` fails on a typed one. The fade into the world is one CSS opacity transition, stopped by the hall's reduced-motion rule.
15
17
 
16
18
  ## For the tasks after this one
17
19
 
18
20
  - R04 (task 1005144): point Options at the options menu and move Achievements/Extras targets if those pages lose their interfaces. Escape on the start screen is free for the menu to use.
19
21
  - `shell-game.js` is loaded on every hall page but only Home calls `start()`; `shell-game.css` is linked on Home only. A second page that wants the start screen links the sheet and calls `start()` with its own still.
20
22
 
21
- Tests: `tests/hall_start_screen.mjs` (the hand-off and pure parts in a vm; both screens, Quit, the no-city and reduced-motion paths in a real browser).
23
+ - New art for the start screen (the city in the clouds) is task 1005196; `welcome-boot.js` still hands in the welcome's painting.
24
+
25
+ Tests: `tests/hall_start_screen.mjs` (the hand-off and pure parts in a vm; both screens, the panel's place at desk and phone widths, the segments, Quit, the no-city and reduced-motion paths in a real browser).
@@ -1,6 +1,7 @@
1
1
  {
2
- "_": "The hall's shared components, each in each tone and state (task 1005086, goal 1000138): the status pill, the panel, the empty state, the loading state, the toast per kind, the tabs and view toggle, the buttons, the field and the dialog. Rendered by the ui-design kit in both modes at 1440/390/320: node modules/ui-design/kit/render.js --states modules/hall-ui/specimens/components.states.json. The public design-system reference (task 1005083) is meant to build on this.",
2
+ "_": "The hall's shared components, each in each tone and state (task 1005086, goal 1000138): the status pill, the panel, the empty state, the loading state, the toast per kind, the tabs and view toggle, the buttons, the field and the dialog. Rendered by the ui-design kit, dark only like the hall (task 1005192), at 1440/390/320: node modules/ui-design/kit/render.js --states modules/hall-ui/specimens/components.states.json. The public design-system reference (task 1005083) is meant to build on this.",
3
3
  "page": "/components",
4
+ "modes": ["dark"],
4
5
  "surface": "modules/hall-ui/specimens",
5
6
  "stub": {
6
7
  "prefix": "/"