@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
@@ -8,7 +8,9 @@
8
8
  <title>Studio — {{worldName}}</title>
9
9
  <meta name="description" content="Make something with AI in the studio: bring sketches, pictures or a PDF, say what you want, and get an answer and pictures back.">
10
10
  <link rel="icon" href="/modules/ui-design/public/brand/favicon.svg" type="image/svg+xml">
11
- <link rel="stylesheet" href="/builders/style.css?v=2026-11-10-options">
11
+ <link rel="preconnect" href="https://fonts.googleapis.com">
12
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
13
+ <link rel="stylesheet" href="/builders/style.css?v=2026-11-11-helm">
12
14
  <link rel="stylesheet" href="/builders/studio.css?v=2026-10-09-day">
13
15
  <link rel="stylesheet" href="/builders/ai-studio.css?v=2026-10-29-ais1">
14
16
  </head>
@@ -87,10 +89,10 @@
87
89
  <div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
88
90
 
89
91
  <script src="/builders/dom-utils.js?v=2026-11-05-numbers"></script>
90
- <script src="/builders/shell-game.js?v=2026-11-10-options"></script>
92
+ <script src="/builders/shell-game.js?v=2026-11-11-helm"></script>
91
93
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
92
94
  <script src="/builders/craft-mode.js?v=2026-11-10-visor"></script>
93
- <script src="/builders/shell.js?v=2026-11-10-character"></script>
95
+ <script src="/builders/shell.js?v=2026-11-11-helm"></script>
94
96
  <script src="/builders/hall-dialog.js"></script>
95
97
  <script src="/builders/palette.js" defer></script>
96
98
  <script src="/builders/tweak-editor-lib.js?v=2026-09-28-tw23"></script>
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "_": "The studio's AI pages (task 1004921, goal 1000136), built 1:1 on option C of the AI Studio options canvas plus the owner's addition (change the request on the result and make it again). Against the kit's own stub the page renders its could-not-read states (no ai-studio feeds). TO SEE IT POPULATED, point the kit at the hall-preview harness with the module on: `node scripts/hall-preview/server.js --port 4637 --fixture-me --modules-on ai-studio` then `render.js --base-in http://builders.localhost:4637 --base-out http://builders.localhost:4637`. The harness answers keys, balance, the top-up quote and the request list from the ai-studio__*.json fixtures; a request by id (1002 running, 1003 failed, 1004 own Gemini key, any other the finished result on the balance); an upload, a request and a top-up from its CANNED WRITES; and every file as a stand-in picture. ?from=1001 opens the steps on that request's files and words, which is how the populated steps render without an upload.",
3
3
  "page": "/builders/ai-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",
@@ -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
  <!-- task 1003472: the island index under the map is a run of oversight rows,
13
13
  and the detail panel's facts are the family's lines, so the family sheet
14
14
  loads first and atlas.css holds only the scene. -->
@@ -90,10 +90,10 @@
90
90
  <div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
91
91
 
92
92
  <script src="/builders/dom-utils.js?v=2026-11-05-numbers"></script>
93
- <script src="/builders/shell-game.js?v=2026-11-10-options"></script>
93
+ <script src="/builders/shell-game.js?v=2026-11-11-helm"></script>
94
94
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
95
95
  <script src="/builders/craft-mode.js?v=2026-11-10-visor"></script>
96
- <script src="/builders/shell.js?v=2026-11-10-character"></script>
96
+ <script src="/builders/shell.js?v=2026-11-11-helm"></script>
97
97
  <script src="/builders/hall-dialog.js"></script>
98
98
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
99
99
  <script src="/builders/palette.js" defer></script>
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "_": "Repo atlas — the self-drawing module map. Its SEMANTIC node palette is fixed by ADR 0094 and is not the token tier's business; everything around it (the panel, the view switch, the caption, the detail card, the legend, the island index) is chrome and rides the world. Written with the re-skin (task 1003307) so this page is MEASURED at three widths in both modes rather than looked at once; the redesign (task 1003472) added the `truth`, `detail` and `index` states. Populated look: the hall-preview harness serves modules/hall-ui/public/atlas.json when scripts/bongos/gen-atlas.js has written it (the file is generated on deploy and gitignored, so run the generator first).",
3
3
  "page": "/builders/atlas",
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
  <link rel="stylesheet" href="/builders/hall-ask.css">
13
13
  <!-- task 1003455: the row shape (title + facts) is the oversight family's,
14
14
  the same archetype collab/copy-desk/watch/gate already ride. -->
@@ -59,10 +59,10 @@
59
59
  <!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
60
60
  chrome exists before the page script runs. -->
61
61
  <script src="/builders/dom-utils.js?v=2026-11-05-numbers"></script>
62
- <script src="/builders/shell-game.js?v=2026-11-10-options"></script>
62
+ <script src="/builders/shell-game.js?v=2026-11-11-helm"></script>
63
63
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
64
64
  <script src="/builders/craft-mode.js?v=2026-11-10-visor"></script>
65
- <script src="/builders/shell.js?v=2026-11-10-character"></script>
65
+ <script src="/builders/shell.js?v=2026-11-11-helm"></script>
66
66
  <script src="/builders/hall-dialog.js"></script>
67
67
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
68
68
  <script src="/builders/palette.js" defer></script>
@@ -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
  <link rel="stylesheet" href="/builders/hall-ask.css">
13
13
  <link rel="stylesheet" href="/builders/oversight.css">
14
14
  <!-- The room's own sheet: the sitting card and the ballot controls moved here
@@ -61,10 +61,10 @@
61
61
  <div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
62
62
 
63
63
  <script src="/builders/dom-utils.js?v=2026-11-05-numbers"></script>
64
- <script src="/builders/shell-game.js?v=2026-11-10-options"></script>
64
+ <script src="/builders/shell-game.js?v=2026-11-11-helm"></script>
65
65
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
66
66
  <script src="/builders/craft-mode.js?v=2026-11-10-visor"></script>
67
- <script src="/builders/shell.js?v=2026-11-10-character"></script>
67
+ <script src="/builders/shell.js?v=2026-11-11-helm"></script>
68
68
  <script src="/builders/hall-dialog.js"></script>
69
69
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
70
70
  <script src="/builders/palette.js" defer></script>
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "_": "Board Room — the sittings, the ballot and the vote form, carved out of the /government tab strip onto its own page by ADR 0266. Unlike its neighbours in the Government group this page is gated on the `board.vote.cast` atom (xenos floor) rather than page.view.government, so the sealed state here means the permission was withheld, not that the reader stands below a rung.",
3
3
  "page": "/builders/board-room",
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",
@@ -78,8 +78,6 @@ html:has(body[data-page="city"]) { height: 100%; }
78
78
  /* the header: wordmark left, the sun/moon switch right */
79
79
  .city-top { position: absolute; left: 32px; right: 32px; top: 0; height: 64px; display: flex; align-items: center; justify-content: space-between; z-index: 3; }
80
80
  .city-mark { font-weight: 500; font-size: 17px; letter-spacing: -0.015em; text-transform: lowercase; }
81
- .city-mode { background: none; border: 1px solid var(--rule); border-radius: 999px; height: 36px; padding: 0 11px; display: flex; align-items: center; gap: 8px; cursor: pointer; color: var(--ink); font-family: var(--font-body); }
82
- .city-mode svg { display: block; stroke-width: 1.4; }
83
81
 
84
82
  /* THE STAGE IN THE HALL (task 1004544, the sky's mechanism from task 1004327).
85
83
  <main class="city-main"> is the box under the hall's top bar and beside its
@@ -139,7 +137,7 @@ html[data-fullscreen="on"] .city-top { right: 184px; }
139
137
  .city-start { display: inline-flex; align-items: center; box-sizing: border-box; font-family: var(--font-body); font-size: 17px; font-weight: 500; height: 56px; padding: 0 38px; border-radius: 999px; border: 0; cursor: pointer; background: var(--accent); color: var(--accent-on); text-transform: lowercase; text-decoration: none; transition: transform 200ms cubic-bezier(.2,.7,.3,1); }
140
138
  .city-start:hover { background: var(--accent-lift); transform: translateY(-2px); }
141
139
  .city-line { margin: 0; font-size: 14px; font-weight: 400; line-height: 1.4; color: var(--ink-soft); font-variant-numeric: tabular-nums; text-align: center; }
142
- .city-mode:focus-visible, .city-start:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
140
+ .city-start:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
143
141
 
144
142
  @media (max-width: 560px) {
145
143
  .city-top { left: 16px; right: 16px; }
@@ -11,9 +11,9 @@
11
11
  links, injected into this head by the server like every hall page's
12
12
  (tests/hall_tokens.mjs: no hall page hardcodes a web-font stylesheet).
13
13
  The prototype carried its own Google Fonts link for the same two faces. -->
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
  <link rel="stylesheet" href="/builders/visor.css?v=2026-11-10-visor">
16
- <link rel="stylesheet" href="/builders/city.css?v=2026-11-10-visor">
16
+ <link rel="stylesheet" href="/builders/city.css?v=2026-11-11-helm">
17
17
  <!-- the ask card in the glass language, shared with the street's deck (task 1004702) -->
18
18
  <link rel="stylesheet" href="/builders/street-deck.css?v=2026-10-17-tidy">
19
19
  </head>
@@ -70,9 +70,6 @@
70
70
  <main id="hall-main" class="city-main">
71
71
  <div class="city-top">
72
72
  <span class="city-mark">{{productName}}</span>
73
- <button type="button" class="city-mode" id="cityMode" aria-label="Switch to light mode" title="Switch to light mode">
74
- <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" aria-hidden="true"><path id="cityModeIcon" d=""></path></svg>
75
- </button>
76
73
  </div>
77
74
  <div class="city-plaque" id="cityPlaque" aria-label="The government at a glance" hidden></div>
78
75
 
@@ -107,10 +104,10 @@
107
104
  </div>
108
105
 
109
106
  <script src="/builders/dom-utils.js?v=2026-11-05-numbers"></script>
110
- <script src="/builders/shell-game.js?v=2026-11-10-options" defer></script>
107
+ <script src="/builders/shell-game.js?v=2026-11-11-helm" defer></script>
111
108
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers" defer></script>
112
109
  <script src="/builders/craft-mode.js?v=2026-11-10-visor" defer></script>
113
- <script src="/builders/shell.js?v=2026-11-10-character" defer></script>
110
+ <script src="/builders/shell.js?v=2026-11-11-helm" defer></script>
114
111
  <script src="/builders/hall-dialog.js" defer></script>
115
112
  <!-- task 1005148: the visor (glass over the scene, game mode only; ADR 0399), after the shell and hall-dialog.js -->
116
113
  <script src="/builders/visor.js?v=2026-11-10-visor" defer></script>
@@ -129,6 +126,6 @@
129
126
  <script src="/builders/street-deck.js?v=2026-10-13-glass1" defer></script>
130
127
  <script src="/builders/city-decide.js?v=2026-10-23-decide12" defer></script>
131
128
  <script src="/builders/city-switchboard.js?v=2026-10-23-board5" defer></script>
132
- <script src="/builders/city.js?v=2026-11-10-visor" defer></script>
129
+ <script src="/builders/city.js?v=2026-11-11-helm" defer></script>
133
130
  </body>
134
131
  </html>
@@ -24,11 +24,9 @@
24
24
  // A feed that fails leaves its part of the city out; it never draws sample
25
25
  // data. Without gov-living.js the page draws the city it drew before.
26
26
  //
27
- // THE SWITCH. Light and dark use the hall's own preference ('hall-theme' in
28
- // localStorage, else the OS setting) and the hall's own attribute
29
- // (html[data-theme]), so the city opens in the mode every other hall page is
30
- // in, and a change here carries back to them. The drawing's faces come from
31
- // the mode, so a toggle redraws the city from the last feeds (no refetch).
27
+ // THE MODE. The hall is dark only (task 1005192, ADR 0402), so the city has no
28
+ // light/dark switch and reads no stored choice: it draws its night faces. Day
29
+ // and night come back as art (the city and its sky), never as a control.
32
30
  //
33
31
  // MOTION is CSS only (city.css); nothing here animates. The scale write on
34
32
  // resize is layout, not motion; the card changes a class.
@@ -42,9 +40,6 @@
42
40
  'use strict';
43
41
  var City = window.GovCity;
44
42
  var SVG_NS = 'http://www.w3.org/2000/svg';
45
- var THEME_KEY = 'hall-theme';
46
- var SUN = 'M7 1.5V3M7 11v1.5M1.5 7H3M11 7h1.5M3.1 3.1l1 1M9.9 9.9l1 1M3.1 10.9l1-1M9.9 4.1l1-1M9.5 7A2.5 2.5 0 1 1 4.5 7A2.5 2.5 0 1 1 9.5 7Z';
47
- var MOON = 'M11.5 8.6A5 5 0 0 1 5.4 2.5A5 5 0 1 0 11.5 8.6Z';
48
43
  var FEEDS = {
49
44
  docket: '/api/bongos/government/docket',
50
45
  goals: '/api/bongos/goals',
@@ -72,54 +67,18 @@
72
67
  };
73
68
 
74
69
  var $ = function (id) { return document.getElementById(id); };
75
- var media = window.matchMedia ? window.matchMedia('(prefers-color-scheme: dark)') : null;
76
70
  var data = { docket: null, goals: [], rollups: [], loaded: false, raw: {} };
77
71
  var model = null;
78
72
  var openKey = null;
79
73
  var drewLiving = false;
80
74
 
81
- // ---------- light / dark ----------
82
- // A choice made on this page when storage is blocked (private mode) still
83
- // holds for this page view.
84
- var chosen = null;
85
- function storedTheme() {
86
- try { var v = window.localStorage.getItem(THEME_KEY); if (v === 'dark' || v === 'light') return v; } catch (_) { /* blocked */ }
87
- return chosen;
88
- }
89
- function effectiveTheme() { return storedTheme() || (media && media.matches ? 'dark' : 'light'); }
90
- function applyTheme() {
91
- var t = effectiveTheme();
92
- document.documentElement.setAttribute('data-theme', t);
93
- var btn = $('cityMode');
94
- var label = t === 'dark' ? 'Switch to light mode' : 'Switch to dark mode';
95
- if (btn) { btn.setAttribute('aria-label', label); btn.setAttribute('title', label); }
96
- var icon = $('cityModeIcon');
97
- if (icon) icon.setAttribute('d', t === 'dark' ? SUN : MOON);
98
- return t;
99
- }
100
- function toggleTheme() {
101
- var next = effectiveTheme() === 'dark' ? 'light' : 'dark';
102
- chosen = next;
103
- try { window.localStorage.setItem(THEME_KEY, next); } catch (_) { /* private mode: this page only */ }
104
- draw(applyTheme());
105
- syncShell();
106
- }
107
- // IN THE HALL (task 1004544) the shell's top bar carries the hall's own theme
108
- // switch beside this one. Both write the same 'hall-theme' preference and the
109
- // same html[data-theme]; each repaints when the other flips it, so the two
110
- // icons and the drawing's faces never disagree.
75
+ // ---------- the mode: dark only (task 1005192, ADR 0402) ----------
76
+ // The drawing's faces come from the mode, and the hall has one.
111
77
  var painted = null;
112
- function syncShell() {
113
- var shell = window.OTBShell;
114
- painted = effectiveTheme();
115
- if (shell && typeof shell.applyTheme === 'function' && storedTheme() === painted) shell.applyTheme();
116
- }
117
- function watchShellTheme() {
118
- if (typeof MutationObserver !== 'function') return;
119
- new MutationObserver(function () {
120
- var t = document.documentElement.getAttribute('data-theme');
121
- if ((t === 'dark' || t === 'light') && t !== painted) { painted = t; chosen = t; draw(applyTheme()); }
122
- }).observe(document.documentElement, { attributes: true, attributeFilter: ['data-theme'] });
78
+ function effectiveTheme() { return 'dark'; }
79
+ function applyTheme() {
80
+ document.documentElement.setAttribute('data-theme', 'dark');
81
+ return 'dark';
123
82
  }
124
83
 
125
84
  // ---------- fit the 1440 x 900 artboard to the window ----------
@@ -747,9 +706,6 @@
747
706
  if (start) start.setAttribute('href', '#decide');
748
707
  if (start) start.addEventListener('click', function (e) { if (window.GovCityDecide && window.GovDeck) { if (e.preventDefault) e.preventDefault(); openDecide(null); } });
749
708
  window.addEventListener('hashchange', function () { var h = window.location && window.location.hash; if (/^#decide/.test(h || '')) openDecide(h.split('=')[1] || null); });
750
- var btn = $('cityMode');
751
- if (btn) btn.addEventListener('click', toggleTheme);
752
- if (media && media.addEventListener) media.addEventListener('change', function () { if (!storedTheme()) draw(applyTheme()); });
753
709
  window.addEventListener('resize', fit);
754
710
  var card = $('cityCard');
755
711
  // the card's keys work wherever focus is while it is open (Tab never walks its buttons)
@@ -771,11 +727,10 @@
771
727
  fit();
772
728
  painted = applyTheme();
773
729
  draw(painted);
774
- watchShellTheme();
775
730
  return load().then(function (r) { var h = window.location && window.location.hash; if (/^#decide/.test(h || '')) openDecide(h.split('=')[1] || null); return r; });
776
731
  }
777
732
 
778
- window.GovCityPage = { boot: boot, draw: draw, load: load, fit: fit, openCard: openCard, closeCard: closeCard, openDecide: function (scope, how) { openDecide(scope, how); return decide; }, FEEDS: FEEDS, LIVING_FEEDS: LIVING_FEEDS, THEME_KEY: THEME_KEY };
733
+ window.GovCityPage = { boot: boot, draw: draw, load: load, fit: fit, openCard: openCard, closeCard: closeCard, openDecide: function (scope, how) { openDecide(scope, how); return decide; }, FEEDS: FEEDS, LIVING_FEEDS: LIVING_FEEDS };
779
734
  window.GovCityPage.ready = boot();
780
735
  // task 1005148: the Governor City as the visor's scene. No camera until R13, so no movement
781
736
  // actions (ADR 0399 §2.2); the card's own keys are listed for the sheet.
@@ -1,8 +1,13 @@
1
1
  {
2
- "_": "THE GOVERNOR CITY's home (task 1004524, goal 1000125) through modules/ui-design/kit/render.js. The page draws GET /government/docket, GET /goals and GET /goals/rollups; against the kit's own stub none exists, so every state renders the city with no districts and no pins and the line saying the docket could not be read: a real state the floors must hold in. To look at the populated city, 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 4624 --fixture-me\n node modules/ui-design/kit/render.js --states modules/hall-ui/public/city.states.json --base-in http://localhost:4624 --base-out http://localhost:4624\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 GOVERNOR CITY's home (task 1004524, goal 1000125) through modules/ui-design/kit/render.js. The page draws GET /government/docket, GET /goals and GET /goals/rollups; against the kit's own stub none exists, so every state renders the city with no districts and no pins and the line saying the docket could not be read: a real state the floors must hold in. To look at the populated city, 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 4624 --fixture-me\n node modules/ui-design/kit/render.js --states modules/hall-ui/public/city.states.json --base-in http://localhost:4624 --base-out http://localhost:4624\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/city",
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/"
@@ -38,7 +43,6 @@
38
43
  "#cityStage",
39
44
  "#cityStart",
40
45
  "#cityLine",
41
- "#cityMode",
42
46
  "#app-topbar",
43
47
  "#fullscreen-toggle"
44
48
  ],
@@ -75,7 +79,6 @@
75
79
  "visible": [
76
80
  "#cityStage",
77
81
  "#cityStart",
78
- "#cityMode",
79
82
  "#fullscreen-toggle"
80
83
  ],
81
84
  "hidden": [
@@ -91,34 +94,6 @@
91
94
  ]
92
95
  }
93
96
  },
94
- "switched": {
95
- "auth": true,
96
- "_": "The sun/moon switch pressed once: the other mode, the city redrawn in it.",
97
- "actions": [
98
- [
99
- "wait",
100
- 600
101
- ],
102
- [
103
- "clickIfVisible",
104
- "[data-craft-close]"
105
- ],
106
- [
107
- "click",
108
- "#cityMode"
109
- ],
110
- [
111
- "wait",
112
- 400
113
- ]
114
- ],
115
- "expect": {
116
- "visible": [
117
- "#cityStage",
118
- "#cityStart"
119
- ]
120
- }
121
- },
122
97
  "focus": {
123
98
  "auth": true,
124
99
  "_": "Keyboard: the start button focused, its ring drawn.",
@@ -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
  <link rel="stylesheet" href="/builders/oversight.css">
13
13
  <link rel="stylesheet" href="/builders/collab.css">
14
14
  </head>
@@ -160,10 +160,10 @@
160
160
  <div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
161
161
 
162
162
  <script src="/builders/dom-utils.js?v=2026-11-05-numbers"></script>
163
- <script src="/builders/shell-game.js?v=2026-11-10-options"></script>
163
+ <script src="/builders/shell-game.js?v=2026-11-11-helm"></script>
164
164
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
165
165
  <script src="/builders/craft-mode.js?v=2026-11-10-visor"></script>
166
- <script src="/builders/shell.js?v=2026-11-10-character"></script>
166
+ <script src="/builders/shell.js?v=2026-11-11-helm"></script>
167
167
  <script src="/builders/hall-dialog.js"></script>
168
168
  <script src="/builders/palette.js" defer></script>
169
169
  <script src="/builders/collab-lib.js?v=2026-09-24-archive"></script>
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "_": "Collab — the two-sided ask board. ASKED OF YOU comes first because it is the half where someone is waiting, and the empty state of that half is the page's most common render. Written with the re-skin (task 1003307) so this page is MEASURED at three widths in both modes rather than looked at once; the redesign (task 1003471) put four asks and two of the viewer's own in the harness so the rows can be looked at.",
3
3
  "page": "/builders/collab",
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
  <link rel="stylesheet" href="/builders/commands.css">
13
13
  </head>
14
14
  <body data-page="commands" data-page-title="Commands">
@@ -52,10 +52,10 @@
52
52
  <div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
53
53
 
54
54
  <script src="/builders/dom-utils.js?v=2026-11-05-numbers"></script>
55
- <script src="/builders/shell-game.js?v=2026-11-10-options"></script>
55
+ <script src="/builders/shell-game.js?v=2026-11-11-helm"></script>
56
56
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
57
57
  <script src="/builders/craft-mode.js?v=2026-11-10-visor"></script>
58
- <script src="/builders/shell.js?v=2026-11-10-character"></script>
58
+ <script src="/builders/shell.js?v=2026-11-11-helm"></script>
59
59
  <script src="/builders/hall-dialog.js"></script>
60
60
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
61
61
  <script src="/builders/palette.js" defer></script>
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "_": "The Commands page (task 1004473): every skill and every bongos CLI verb as two grouped ledgers, filled from GET /specialities/installed-skills and GET /cli/commands. Against the kit's stub both reads 404, so the page renders its 'not available' state, which the floors must hold too. The populated look was verified against a real local server (bongos dev), since both lists are read from disk.",
3
3
  "page": "/builders/commands",
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,8 +10,8 @@
10
10
  THE BUTTON — `.btn` and three modifiers:
11
11
  .btn primary: the accent fill with --accent-on, the DARK ink.
12
12
  White on the salmon fails AA and DESIGN.md bans it.
13
- 46px, a full pill: DESIGN.md's door height.
14
- .btn--ghost the quiet sibling: no fill, one hairline, soft ink.
13
+ 46px: DESIGN.md's door height.
14
+ .btn--ghost the quiet sibling: the press fill, one hairline, soft ink.
15
15
  .btn--sm the row size, for a button that repeats down a list or
16
16
  sits in a table: 30px, still over the 24px floor.
17
17
  .btn--text a button that reads as a link: no fill, no edge, the
@@ -31,6 +31,21 @@
31
31
  text .cb-ask__door
32
32
  A new page writes `.btn` and its modifiers, never a new name.
33
33
 
34
+ THE SHAPE AND THE VOICE ARE HELM'S IN THE HALL (task 1005192, ADR 0402).
35
+ Anything you can press takes the CUT CORNER (top-left and bottom-right, the
36
+ hall tier's --cut-path) and names itself in the NAME VOICE (the display
37
+ face, wide tracked capitals: --name-face / --name-weight / --name-space-tight
38
+ / --name-case). Every one of those is a hall-tier token spent with a
39
+ fallback, and the fallback is the pill and the lowercase body voice this
40
+ sheet drew before: the status page links this sheet without the hall's tier,
41
+ so there the fallbacks stand and nothing on it moves.
42
+ A clip-path clips an outline, so in the hall a cut button's focus is the
43
+ inset two-tone ring --press-focus (the focus colour on the edge, a band of
44
+ the ground inside it: one of the two reads on any fill). A cut also removes
45
+ the hairline at the two cut corners, so the ghost takes the press fill
46
+ (--press-fill) and reads as a shape rather than as a broken outline.
47
+ The text button is a link in a sentence: no cut, no capitals.
48
+
34
49
  THE FIELD — one text input / select / textarea, `.input` for a field the
35
50
  element selectors do not reach. 40px, a pill (a textarea takes the tile
36
51
  corner), an edge that clears 3:1 against the card in both modes so the
@@ -54,17 +69,21 @@
54
69
  min-height: 46px;
55
70
  min-width: 46px;
56
71
  padding: 0 var(--ds-space-md);
57
- font-family: var(--font-body);
72
+ font-family: var(--name-face, var(--font-body));
58
73
  font-size: var(--ds-text-lg);
59
- font-weight: 500;
74
+ font-weight: var(--name-weight, 500);
60
75
  line-height: 1.2;
61
- text-transform: lowercase;
76
+ letter-spacing: var(--name-space-tight, normal);
77
+ text-transform: var(--name-case, lowercase);
62
78
  text-decoration: none;
63
79
  white-space: nowrap;
64
80
  /* transparent rather than absent: a modifier that sets only a border COLOUR
65
81
  (collab.css's .btn--quiet) cannot paint an edge that was never reserved. */
66
82
  border: var(--line) solid transparent;
67
- border-radius: var(--radius-pill);
83
+ border-radius: var(--press-radius, var(--radius-pill));
84
+ clip-path: var(--cut-path, none);
85
+ /* the hall's :focus-visible rule (style.css) spends this in place of its halo */
86
+ --focus-ring: var(--press-focus);
68
87
  cursor: pointer;
69
88
  transition: background-color var(--ds-dur-fast) var(--ds-ease),
70
89
  border-color var(--ds-dur-fast) var(--ds-ease),
@@ -97,7 +116,7 @@
97
116
  .btn--ghost, .btn--quiet, .btn-ghost, .landing__btn--quiet, .td-btn, .wip__release,
98
117
  .pbtn, .settings-btn, .sessions-row__end, .event-sound-preview {
99
118
  color: var(--ink-soft);
100
- background: transparent;
119
+ background: var(--press-fill, transparent);
101
120
  border-color: var(--rule);
102
121
  }
103
122
  .btn--ghost:hover:not(:disabled), .btn--quiet:hover:not(:disabled), .btn-ghost:hover:not(:disabled),
@@ -105,7 +124,7 @@
105
124
  .pbtn:hover:not(:disabled), .settings-btn:hover:not(:disabled),
106
125
  .sessions-row__end:hover:not(:disabled), .event-sound-preview:hover:not(:disabled) {
107
126
  color: var(--ink);
108
- background: transparent;
127
+ background: var(--press-fill, transparent);
109
128
  border-color: var(--ink-faint);
110
129
  text-decoration: none;
111
130
  }
@@ -142,6 +161,7 @@
142
161
  min-width: 30px;
143
162
  padding: 0 var(--ds-space-sm);
144
163
  font-size: var(--ds-text-sm);
164
+ clip-path: var(--cut-path-sm, none);
145
165
  }
146
166
 
147
167
  /* text — a button that reads as a link: the sentence's own size and case, the
@@ -151,9 +171,13 @@
151
171
  min-height: 24px;
152
172
  min-width: 24px;
153
173
  padding: 0 2px;
174
+ font-family: inherit;
154
175
  font-size: inherit;
155
176
  font-weight: inherit;
177
+ letter-spacing: inherit;
156
178
  text-transform: none;
179
+ clip-path: none;
180
+ --focus-ring: initial;
157
181
  color: var(--accent-ink);
158
182
  background: transparent;
159
183
  border-color: transparent;
@@ -166,16 +190,44 @@
166
190
  }
167
191
  .btn--text:disabled { color: var(--ink-faint); background: transparent; }
168
192
 
169
- /* Focus keeps the pill. The shell's two-tone ring (style.css :focus-visible)
170
- sets the tile corner for the general case; a pill under it would square off. */
193
+ /* Focus keeps the button's own corner. The shell's two-tone ring (style.css
194
+ :focus-visible) sets the tile corner for the general case; a pill under it
195
+ would square off. In the hall the button is cut, and the cut clips that
196
+ outline and its halo away, so the ring is drawn INSIDE the shape instead:
197
+ the base rule hands --press-focus to the shell's ring as --focus-ring. */
171
198
  .btn:focus-visible, .btn-accent:focus-visible, .btn-ghost:focus-visible,
172
199
  .landing__btn:focus-visible, .task__claim:focus-visible, .td-btn:focus-visible,
173
200
  .wip__release:focus-visible, .setup-gate__save:focus-visible, .pbtn:focus-visible,
174
201
  .settings-btn:focus-visible, .sessions-row__end:focus-visible,
175
202
  .event-sound-preview:focus-visible, button.craft-save:focus-visible {
176
- border-radius: var(--radius-pill);
203
+ border-radius: var(--press-radius, var(--radius-pill));
177
204
  }
178
205
 
206
+ /* ---------- the segment (task 1005192, ADR 0402) ----------
207
+ HELM'S PROGRESS: one small skewed bar per step, in a row. A step that is done
208
+ is filled with the soft ink (information you read); one still to come is an
209
+ outline; the accent fills only a step the reader can act on now (.seg--now).
210
+ Always beside words that say the same thing: a row of bars is never the only
211
+ reading. The measures are the hall tier's (--seg-*). */
212
+ .segs {
213
+ display: flex;
214
+ flex-wrap: wrap;
215
+ gap: var(--seg-gap);
216
+ margin: 0;
217
+ padding: 0 var(--seg-gap);
218
+ list-style: none;
219
+ }
220
+ .seg {
221
+ box-sizing: border-box;
222
+ flex: 0 1 var(--seg-w);
223
+ min-width: var(--seg-h);
224
+ height: var(--seg-h);
225
+ border: var(--line-strong) solid var(--rule);
226
+ transform: skewX(var(--seg-skew));
227
+ }
228
+ .seg--done { background: var(--ink-soft); border-color: transparent; }
229
+ .seg--now { background: var(--accent); border-color: transparent; }
230
+
179
231
  /* ---------- the field ----------
180
232
  The four element selectors the hall always styled keep their weight (0,1,1),
181
233
  so nothing that leaned on them moves in the cascade. The other text types
@@ -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
  <link rel="stylesheet" href="/builders/oversight.css">
13
13
  <link rel="stylesheet" href="/builders/copy-desk.css">
14
14
  </head>
@@ -178,10 +178,10 @@
178
178
  <div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
179
179
 
180
180
  <script src="/builders/dom-utils.js?v=2026-11-05-numbers"></script>
181
- <script src="/builders/shell-game.js?v=2026-11-10-options"></script>
181
+ <script src="/builders/shell-game.js?v=2026-11-11-helm"></script>
182
182
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
183
183
  <script src="/builders/craft-mode.js?v=2026-11-10-visor"></script>
184
- <script src="/builders/shell.js?v=2026-11-10-character"></script>
184
+ <script src="/builders/shell.js?v=2026-11-11-helm"></script>
185
185
  <script src="/builders/hall-dialog.js"></script>
186
186
  <script src="/builders/palette.js" defer></script>
187
187
  <script src="/builders/hall-kit.js"></script>
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "_": "Copy desk — the one-voice review queue. Its three dialogs are real <dialog>s, so their ::backdrop is the sheet's single sanctioned literal (black with alpha as a scrim). Written with the re-skin (task 1003307) so this page is MEASURED at three widths in both modes rather than looked at once; the redesign (task 1003471) put a queue, ten duplicates and a search's hits in the harness so the rows and the dialogs can be looked at; task 1003114 (R03) added the proposal composer and the `proposer` state that opens it.",
3
3
  "page": "/builders/copy-desk",
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",