@bongos/core 1.25.19 → 1.25.21

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 (131) hide show
  1. package/.bongos-core.json +237 -112
  2. package/clients/bongos-client/README.md +1 -1
  3. package/clients/bongos-client/bongos-client.global.js +12 -0
  4. package/clients/bongos-client/index.cjs +12 -0
  5. package/clients/bongos-client/index.d.ts +26 -9
  6. package/clients/bongos-client/index.mjs +12 -0
  7. package/docs/adr/0406-every-project-gets-a-sandbox-that-follows-main-and-live-moves-only-when-a-person-promotes.md +10 -0
  8. package/docs/adr/0407-a-project-grant-is-made-by-the-owner-not-witnessed-at-sign-in.md +3 -1
  9. package/docs/api/openapi.json +444 -37
  10. package/docs/api-reference.md +11 -5
  11. package/docs/copy-inventory.md +223 -221
  12. package/docs/copy-registry.json +262 -244
  13. package/docs/module-api-changelog.md +4 -0
  14. package/docs/page-readings.json +348 -347
  15. package/docs/project-context.template.md +1 -1
  16. package/modules/front-door-guide/handoff.js +120 -0
  17. package/modules/front-door-guide/module.json +1 -1
  18. package/modules/front-door-guide/routes/front-door-guide-plan.js +24 -0
  19. package/modules/government/board.js +8 -7
  20. package/modules/government/charter-advice.js +10 -3
  21. package/modules/government/charter.js +88 -4
  22. package/modules/government/migrations/government_039_vote_cast_via_filed.sql +22 -0
  23. package/modules/government/routes/government.js +12 -12
  24. package/modules/government/sole-member.js +75 -0
  25. package/modules/hall-ui/public/ai-studio.html +1 -1
  26. package/modules/hall-ui/public/atlas.html +1 -1
  27. package/modules/hall-ui/public/blockers.html +1 -1
  28. package/modules/hall-ui/public/board-room.html +1 -1
  29. package/modules/hall-ui/public/city.html +1 -1
  30. package/modules/hall-ui/public/collab.html +1 -1
  31. package/modules/hall-ui/public/commands.html +1 -1
  32. package/modules/hall-ui/public/copy-desk.html +1 -1
  33. package/modules/hall-ui/public/deploy.html +1 -1
  34. package/modules/hall-ui/public/genesis-home.js +35 -9
  35. package/modules/hall-ui/public/goal-map.html +1 -1
  36. package/modules/hall-ui/public/goals.html +1 -1
  37. package/modules/hall-ui/public/government.html +1 -1
  38. package/modules/hall-ui/public/home-city-draw.js +14 -1
  39. package/modules/hall-ui/public/idea.html +1 -1
  40. package/modules/hall-ui/public/ideas.html +1 -1
  41. package/modules/hall-ui/public/index.html +1 -1
  42. package/modules/hall-ui/public/market-watch-item.html +1 -1
  43. package/modules/hall-ui/public/market-watch-rules.html +1 -1
  44. package/modules/hall-ui/public/market-watch.html +1 -1
  45. package/modules/hall-ui/public/modules.html +1 -1
  46. package/modules/hall-ui/public/money.html +1 -1
  47. package/modules/hall-ui/public/my-agents.html +1 -1
  48. package/modules/hall-ui/public/primer.html +1 -1
  49. package/modules/hall-ui/public/profile.html +1 -1
  50. package/modules/hall-ui/public/project-settings.html +1 -1
  51. package/modules/hall-ui/public/roster.html +1 -1
  52. package/modules/hall-ui/public/settings.html +1 -1
  53. package/modules/hall-ui/public/shell.js +32 -20
  54. package/modules/hall-ui/public/street.html +1 -1
  55. package/modules/hall-ui/public/studio.html +1 -1
  56. package/modules/hall-ui/public/style.css +9 -4
  57. package/modules/hall-ui/public/task.html +1 -1
  58. package/modules/hall-ui/public/thinking.html +1 -1
  59. package/modules/hall-ui/public/tweak-editor.html +1 -1
  60. package/modules/hall-ui/public/watch.html +1 -1
  61. package/modules/hall-ui/public/work.html +1 -1
  62. package/modules/lifecycle/home-city.js +17 -3
  63. package/modules/onboarding/founding-mode.js +45 -1
  64. package/modules/onboarding/genesis-home.js +16 -2
  65. package/modules/onboarding/guide-handoff.js +109 -0
  66. package/modules/onboarding/routes/genesis-work.js +9 -5
  67. package/modules/platform-identity/module.json +1 -1
  68. package/modules/platform-identity/project-standing.js +49 -0
  69. package/modules/platform-identity/routes/my-projects.js +8 -0
  70. package/modules/provisioning/grants.js +126 -0
  71. package/modules/provisioning/guide-handoff.js +65 -0
  72. package/modules/provisioning/migrations/provisioning_038_render_promote.sql +43 -0
  73. package/modules/provisioning/migrations/provisioning_039_project_grants.sql +40 -0
  74. package/modules/provisioning/module.json +2 -1
  75. package/modules/provisioning/project-refusal.js +107 -0
  76. package/modules/provisioning/provisioning.js +4 -4
  77. package/modules/provisioning/render-lookup.js +36 -1
  78. package/modules/provisioning/render-promote.js +80 -0
  79. package/modules/provisioning/route-helpers.js +70 -16
  80. package/modules/provisioning/routes/env-manifest.js +21 -5
  81. package/modules/provisioning/routes/grants.js +141 -0
  82. package/modules/provisioning/routes/provisioning.js +12 -9
  83. package/modules/provisioning/routes/render-standup.js +82 -3
  84. package/modules/public-landing/public/projects.html +178 -1
  85. package/package-lock.json +2 -2
  86. package/package.json +1 -1
  87. package/release-notes.json +28 -0
  88. package/scripts/bongos/genesis.js +11 -1
  89. package/scripts/bongos/government-walk-sole.js +41 -0
  90. package/scripts/bongos/government-walk.js +15 -16
  91. package/scripts/bongos/provision-render-common.js +48 -0
  92. package/scripts/bongos/provision-render-promote.js +93 -0
  93. package/scripts/bongos/provision-render-sandbox.js +14 -2
  94. package/scripts/bongos/provision-render.js +4 -36
  95. package/scripts/bongos/provision.js +1 -0
  96. package/scripts/bongos/render-api.js +17 -2
  97. package/scripts/gds/government-walk-sole.js +6 -0
  98. package/scripts/gds/provision-render-common.js +6 -0
  99. package/scripts/gds/provision-render-promote.js +6 -0
  100. package/src/bongos/founding-page-gate.js +67 -0
  101. package/src/bongos/serve-internal.js +3 -0
  102. package/src/branding.js +4 -0
  103. package/src/module-api.js +1 -1
  104. package/tests/fleet_cost_view.mjs +2 -0
  105. package/tests/founding_mode.mjs +84 -8
  106. package/tests/founding_page_gate.mjs +105 -0
  107. package/tests/front_door_guide_existing.mjs +1 -0
  108. package/tests/genesis_government.mjs +5 -1
  109. package/tests/genesis_home.mjs +41 -0
  110. package/tests/government_charter_advice.mjs +49 -0
  111. package/tests/government_charter_forms.mjs +14 -3
  112. package/tests/government_seed.mjs +1 -0
  113. package/tests/government_sole_member.mjs +153 -0
  114. package/tests/guide_handoff.mjs +322 -0
  115. package/tests/home_city.mjs +52 -0
  116. package/tests/nav_permission_atoms.mjs +1 -1
  117. package/tests/project_catalog_routes.mjs +2 -0
  118. package/tests/provision_settings_apply.mjs +2 -1
  119. package/tests/provisioning_env_manifest.mjs +4 -0
  120. package/tests/provisioning_env_manifest_edit_delete.mjs +2 -0
  121. package/tests/provisioning_project_grants.mjs +458 -0
  122. package/tests/provisioning_project_owner_gate.mjs +3 -1
  123. package/tests/provisioning_project_refusal.mjs +316 -0
  124. package/tests/provisioning_render_route.mjs +1 -1
  125. package/tests/provisioning_restart.mjs +2 -0
  126. package/tests/provisioning_settings.mjs +2 -0
  127. package/tests/provisioning_settings_apply.mjs +1 -1
  128. package/tests/provisioning_settings_env.mjs +2 -2
  129. package/tests/provisioning_teardown_intent.mjs +2 -2
  130. package/tests/render_promote.mjs +309 -0
  131. package/tests/render_sandbox.mjs +9 -4
@@ -62,7 +62,7 @@
62
62
  <script src="/builders/shell-game.js?v=2026-11-11-view2"></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-11-view2"></script>
65
+ <script src="/builders/shell.js?v=2026-11-13-founding"></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>
@@ -64,7 +64,7 @@
64
64
  <script src="/builders/shell-game.js?v=2026-11-11-view2"></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-11-view2"></script>
67
+ <script src="/builders/shell.js?v=2026-11-13-founding"></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>
@@ -116,7 +116,7 @@
116
116
  <script src="/builders/shell-game.js?v=2026-11-11-view2" defer></script>
117
117
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers" defer></script>
118
118
  <script src="/builders/craft-mode.js?v=2026-11-10-visor" defer></script>
119
- <script src="/builders/shell.js?v=2026-11-11-view2" defer></script>
119
+ <script src="/builders/shell.js?v=2026-11-13-founding" defer></script>
120
120
  <script src="/builders/hall-dialog.js" defer></script>
121
121
  <!-- task 1005148: the visor (glass over the scene, game mode only; ADR 0399), after the shell and hall-dialog.js -->
122
122
  <script src="/builders/visor.js?v=2026-11-11-helm3" defer></script>
@@ -163,7 +163,7 @@
163
163
  <script src="/builders/shell-game.js?v=2026-11-11-view2"></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-11-view2"></script>
166
+ <script src="/builders/shell.js?v=2026-11-13-founding"></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>
@@ -55,7 +55,7 @@
55
55
  <script src="/builders/shell-game.js?v=2026-11-11-view2"></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-11-view2"></script>
58
+ <script src="/builders/shell.js?v=2026-11-13-founding"></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>
@@ -181,7 +181,7 @@
181
181
  <script src="/builders/shell-game.js?v=2026-11-11-view2"></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-11-view2"></script>
184
+ <script src="/builders/shell.js?v=2026-11-13-founding"></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>
@@ -82,7 +82,7 @@
82
82
  <script src="/builders/shell-game.js?v=2026-11-11-view2"></script>
83
83
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
84
84
  <script src="/builders/craft-mode.js?v=2026-11-10-visor"></script>
85
- <script src="/builders/shell.js?v=2026-11-11-view2"></script>
85
+ <script src="/builders/shell.js?v=2026-11-13-founding"></script>
86
86
  <script src="/builders/hall-dialog.js"></script>
87
87
  <script src="/builders/palette.js" defer></script>
88
88
  <script src="/builders/hall-kit.js"></script>
@@ -35,9 +35,11 @@
35
35
 
36
36
  // What saving the plan did to the government, when it was not settled in the same
37
37
  // click. The server's charter outcome (modules/onboarding/genesis-home.js
38
- // applyGovernmentChoice); in_force and none need no sentence.
38
+ // applyGovernmentChoice). The server's own words come first (task 1005130): an
39
+ // already-in-force choice is said plainly, never silently; none needs no sentence.
39
40
  function charterNote(c) {
40
41
  if (!c) return '';
42
+ if ((c.state === 'in_force' || c.state === 'sitting' || c.state === 'adopted') && c.message) return c.message;
41
43
  if (c.state === 'sitting') return 'Your starting government is in the Board Room for a vote.';
42
44
  if (c.state === 'needs_council') return 'A Foundation needs a council first. Add a council rank, then choose Foundation on the Charter.';
43
45
  if (c.state === 'not_filed') return 'The plan is saved, but the government could not be changed just now. You can change it on the Charter.';
@@ -133,7 +135,9 @@
133
135
 
134
136
  // The starting government: the real academic names, each with its plain sentence
135
137
  // (spec D10), the recommended one picked. Read from the government module's own
136
- // constitution view so the names and explanations are never typed twice.
138
+ // constitution view so the names and explanations are never typed twice. Task
139
+ // 1005130: what is in force is said first and its form is marked, and each form says
140
+ // who decides and what closing something takes, in the server's own words.
137
141
  function governmentHtml(gov) {
138
142
  if (!gov || !gov.forms || !gov.forms.length) return '';
139
143
  var rec = gov.recommended && gov.recommended.key;
@@ -142,9 +146,12 @@
142
146
  return '<fieldset class="genesis__pick genesis__pick--gov"><legend>Starting government</legend>'
143
147
  + '<label class="genesis__expected">Builders you expect in the first year '
144
148
  + '<input type="number" min="1" max="100000" value="' + esc(String(gov.headcount || 1)) + '" data-expected></label>'
149
+ + (gov.in_force && gov.in_force.line ? '<p class="genesis__later">' + esc(gov.in_force.line) + '</p>' : '')
145
150
  + avail.map(function (f) {
146
- var hint = f.explanation + (f.key === rec && gov.recommended.why ? ' Recommended: ' + gov.recommended.why : '');
147
- return radio('gov', f.key, f.name + (f.key === rec ? ' · recommended' : ''), hint, f.key === rec);
151
+ var duty = f.who_decides ? ' ' + f.who_decides + ' ' + (f.to_close || '') : '';
152
+ var hint = f.explanation + duty + (f.key === rec && gov.recommended.why ? ' Recommended: ' + gov.recommended.why : '');
153
+ var tags = (f.current ? ' · in force now' : '') + (f.key === rec ? ' · recommended' : '');
154
+ return radio('gov', f.key, f.name + tags, hint, f.key === rec);
148
155
  }).join('')
149
156
  + (later.length ? '<p class="genesis__later">Coming later: ' + later.map(function (f) { return esc(f.name); }).join(', ') + '.</p>' : '')
150
157
  + '</fieldset>';
@@ -171,9 +178,24 @@
171
178
  return s.total ? s.finished + ' of ' + s.total + ' done' : 'in progress';
172
179
  }
173
180
 
181
+ // The government district's buildings, by the city's key (city-draw.js CIVIC_SLOTS).
182
+ var BUILDING = {
183
+ charter: 'Charter', release: 'Release', planning: 'Planning', automation: 'Automation', treasury: 'Treasury',
184
+ rules: 'Rules', disputes: 'Disputes', people: 'People', review: 'Review',
185
+ };
186
+ function gainsText(s) {
187
+ var wakes = (s.wakes || []).map(function (id) { return ROOM[id] || id; });
188
+ var raises = (s.raises || []).map(function (k) { return BUILDING[k] || k; });
189
+ var parts = [];
190
+ if (wakes.length) parts.push('Wakes ' + wakes.join(', '));
191
+ if (raises.length) parts.push('raises ' + raises.join(', '));
192
+ if (!wakes.length && s.earns) parts.push(s.earns.charAt(0).toLowerCase() + s.earns.slice(1));
193
+ var line = parts.join(' · ');
194
+ return line ? line.charAt(0).toUpperCase() + line.slice(1) : '';
195
+ }
196
+
174
197
  function stagesHtml(g) {
175
198
  return '<ol class="genesis__stages">' + g.stages.map(function (s) {
176
- var wakes = (s.wakes || []).map(function (id) { return ROOM[id] || id; });
177
199
  // A demo's stage is minutes long (task 1004506): say how long, and due at a time.
178
200
  var due = s.minutes
179
201
  ? ' · ' + s.minutes + ' min' + (s.state === 'now' && s.due ? ', due ' + new Date(s.due).toLocaleTimeString(undefined, { hour: 'numeric', minute: '2-digit' }) : '')
@@ -181,7 +203,9 @@
181
203
  return '<li class="genesis__stage is-' + s.state + '">'
182
204
  + '<span class="genesis__stage-n">0' + s.number + '</span>'
183
205
  + '<span class="genesis__stage-t"><b>' + esc(s.label) + '</b>'
184
- + '<span>' + esc(wakes.length ? 'Wakes ' + wakes.join(', ') : '') + esc(due) + '</span>'
206
+ // task 1005112: what finishing the stage gives — the rooms it wakes, the district
207
+ // buildings it raises, and for a stage that wakes no room, what it earns.
208
+ + '<span>' + esc(gainsText(s)) + esc(due) + '</span>'
185
209
  + (s.state === 'later' && s.can_close ? '<span><button type="button" class="btn-ghost" data-genesis-close="' + esc(s.key) + '">Put to the board</button></span>' : '')
186
210
  + '</span>'
187
211
  + '<span class="genesis__stage-st">' + esc(stateText(s)) + '</span></li>';
@@ -221,13 +245,15 @@
221
245
  var state = t.state === 'done' || t.state === 'locked' ? t.state : 'open';
222
246
  var check = window.OTB.CHECK_SVG || '';
223
247
  var mark = '<span class="genesis__mark" aria-hidden="true">' + (state === 'done' ? check : '') + '</span>';
224
- var said = { done: 'Done', open: 'To do', locked: 'Locked' }[state];
248
+ // Only the states the status pill does not already say: an open row's pill names its
249
+ // own status, and a second word beside it could disagree with it.
250
+ var said = { done: 'Done: ', locked: 'Locked: ' }[state] || '';
225
251
  var after = (t.waits_on || []).map(function (w) { return w.title; }).filter(Boolean);
226
252
  var tail = state === 'locked'
227
253
  ? '<span class="genesis__task-wait">' + esc(after.length ? 'after ' + after.join(', ') : 'after an earlier task') + '</span>'
228
254
  : window.OTB.statusPill(t.status, { small: true, extraClass: 'genesis__task-st' }) + copyButtonHtml(t);
229
255
  return '<li class="genesis__task is-' + state + '">' + mark
230
- + '<span class="sr-only">' + said + ': </span>'
256
+ + (said ? '<span class="sr-only">' + said + '</span>' : '')
231
257
  + '<a class="genesis__task-t" href="/task/' + encodeURIComponent(t.id) + '">' + esc(t.title) + '</a>'
232
258
  + tail + '</li>';
233
259
  }
@@ -366,7 +392,7 @@
366
392
  var q = expected ? '?headcount=' + encodeURIComponent(expected) : '';
367
393
  return send('GET', '/government/constitution' + q).then(function (c) {
368
394
  var ch = c && c.charter;
369
- return ch ? { forms: ch.forms || [], recommended: c.recommended || null, headcount: expected || c.headcount || 1 } : null;
395
+ return ch ? { forms: ch.forms || [], in_force: ch.in_force || null, recommended: c.recommended || null, headcount: expected || c.headcount || 1 } : null;
370
396
  }).catch(function () { return null; });
371
397
  }
372
398
 
@@ -142,7 +142,7 @@
142
142
  <script src="/builders/shell-game.js?v=2026-11-11-view2"></script>
143
143
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
144
144
  <script src="/builders/craft-mode.js?v=2026-11-10-visor"></script>
145
- <script src="/builders/shell.js?v=2026-11-11-view2"></script>
145
+ <script src="/builders/shell.js?v=2026-11-13-founding"></script>
146
146
  <script src="/builders/hall-dialog.js"></script>
147
147
  <!-- task 1005148: the visor (glass over the scene, game mode only; ADR 0399), after the shell and hall-dialog.js -->
148
148
  <script src="/builders/visor.js?v=2026-11-11-helm3"></script>
@@ -254,7 +254,7 @@
254
254
  <script src="/builders/shell-game.js?v=2026-11-11-view2"></script>
255
255
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
256
256
  <script src="/builders/craft-mode.js?v=2026-11-10-visor"></script>
257
- <script src="/builders/shell.js?v=2026-11-11-view2"></script>
257
+ <script src="/builders/shell.js?v=2026-11-13-founding"></script>
258
258
  <script src="/builders/hall-dialog.js"></script>
259
259
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
260
260
  <script src="/builders/palette.js" defer></script>
@@ -158,7 +158,7 @@
158
158
  <script src="/builders/shell-game.js?v=2026-11-11-view2"></script>
159
159
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
160
160
  <script src="/builders/craft-mode.js?v=2026-11-10-visor"></script>
161
- <script src="/builders/shell.js?v=2026-11-11-view2"></script>
161
+ <script src="/builders/shell.js?v=2026-11-13-founding"></script>
162
162
  <script src="/builders/hall-dialog.js"></script>
163
163
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
164
164
  <script src="/builders/palette.js" defer></script>
@@ -172,6 +172,8 @@
172
172
  return {
173
173
  weeks, W, areas, unplaced: all.length - areas.length,
174
174
  px: TOWER_PX / tallest, people, sites, waiting, ideas, version,
175
+ // task 1005112: while founding, the district buildings not raised yet (server-decided)
176
+ unbuilt: d.founding && d.founding.unbuilt && typeof d.founding.unbuilt === 'object' ? Object.assign({}, d.founding.unbuilt) : null,
175
177
  width: GROUND.w, depth: GROUND.d,
176
178
  };
177
179
  }
@@ -362,12 +364,23 @@
362
364
  const CI = Gov.isoTheme();
363
365
  const k = Gov.isoKit(TW, TH, vb.OX, vb.OY, CIVIC_S, CI, true);
364
366
  const kids = [face([P(CORE.x0, CORE.y0), P(CORE.x1, CORE.y0), P(CORE.x1, CORE.y1), P(CORE.x0, CORE.y1)], I.plaza, I.plazaLine)];
367
+ const unbuilt = m.unbuilt || {};
368
+ let raised = 0;
365
369
  Gov.CIVIC_SLOTS.slice().sort((p, q) => (p[1] + p[2]) - (q[1] + q[2])).forEach((sl) => {
370
+ // task 1005112: a building whose genesis stage is still ahead is a marked-out
371
+ // foundation on the plaza, and rises when that stage is done.
372
+ if (unbuilt[sl[0]]) {
373
+ const x0 = sl[1] - 0.55, y0 = sl[2] - 0.55, w = 1.1;
374
+ kids.push(node('path', { d: pts([P(x0, y0), P(x0 + w, y0), P(x0 + w, y0 + w), P(x0, y0 + w)]), fill: 'none', stroke: I.plazaLine, 'stroke-width': 1, 'stroke-dasharray': '3 3', class: 'hc-face hc-foundation', 'data-building': sl[0] }));
375
+ return;
376
+ }
377
+ raised += 1;
366
378
  const list = [];
367
379
  Gov.isoInstitution(list, k, sl[0], sl[1] - 0.6, sl[2] - 0.6, {});
368
380
  list.forEach((pa) => kids.push(node('path', { d: pa.d, fill: pa.f, stroke: pa.s, 'stroke-width': pa.w, 'stroke-dasharray': pa.dash, 'stroke-linejoin': 'round', class: 'hc-face' })));
369
381
  });
370
- return node('a', { href: Gov.STREET_HREF || '/street', class: 'hc-door hc-core' + quiet('core'), 'aria-label': 'The government district: nine buildings, one for each part of the government. Walk the street.', 'data-tip': 'Government', 'data-tip-body': 'The Cloud Bongos core: nine buildings, one for each part of the government. Click to walk the street.' }, kids);
382
+ const told = raised === Gov.CIVIC_SLOTS.length ? 'nine buildings, one for each part of the government' : raised + ' of nine buildings raised so far; each founding stage raises more';
383
+ return node('a', { href: Gov.STREET_HREF || '/street', class: 'hc-door hc-core' + quiet('core'), 'aria-label': 'The government district: ' + told + '. Walk the street.', 'data-tip': 'Government', 'data-tip-body': 'The Cloud Bongos core: ' + told + '. Click to walk the street.' }, kids);
371
384
  }
372
385
 
373
386
  // The art museum and its garden, after the Cleveland Museum of Art: a long white
@@ -54,7 +54,7 @@
54
54
  <script src="/builders/shell-game.js?v=2026-11-11-view2"></script>
55
55
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
56
56
  <script src="/builders/craft-mode.js?v=2026-11-10-visor"></script>
57
- <script src="/builders/shell.js?v=2026-11-11-view2"></script>
57
+ <script src="/builders/shell.js?v=2026-11-13-founding"></script>
58
58
  <script src="/builders/hall-dialog.js"></script>
59
59
  <script src="/builders/palette.js" defer></script>
60
60
  <!-- task-detail.js still owns the #/idea/N and #/blocker/N overlay, so a ref
@@ -229,7 +229,7 @@
229
229
  <script src="/builders/shell-game.js?v=2026-11-11-view2"></script>
230
230
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
231
231
  <script src="/builders/craft-mode.js?v=2026-11-10-visor"></script>
232
- <script src="/builders/shell.js?v=2026-11-11-view2"></script>
232
+ <script src="/builders/shell.js?v=2026-11-13-founding"></script>
233
233
  <script src="/builders/hall-dialog.js"></script>
234
234
  <script src="/builders/palette.js" defer></script>
235
235
  <!-- task 1004727: the ONE karma vote control every task/idea list renders -->
@@ -106,7 +106,7 @@
106
106
  <script src="/builders/shell-game.js?v=2026-11-11-view2" defer></script>
107
107
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers" defer></script>
108
108
  <script src="/builders/craft-mode.js?v=2026-11-10-visor" defer></script>
109
- <script src="/builders/shell.js?v=2026-11-11-view2" defer></script>
109
+ <script src="/builders/shell.js?v=2026-11-13-founding" defer></script>
110
110
  <script src="/builders/hall-dialog.js" defer></script>
111
111
  <!-- task 1005148: the visor (glass over the scene, game mode only; ADR 0399), after the shell and hall-dialog.js -->
112
112
  <script src="/builders/visor.js?v=2026-11-12-runner" defer></script>
@@ -75,7 +75,7 @@
75
75
  <script src="/builders/shell-game.js?v=2026-11-11-view2"></script>
76
76
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
77
77
  <script src="/builders/craft-mode.js?v=2026-11-10-visor"></script>
78
- <script src="/builders/shell.js?v=2026-11-11-view2"></script>
78
+ <script src="/builders/shell.js?v=2026-11-13-founding"></script>
79
79
  <script src="/builders/hall-dialog.js"></script>
80
80
  <script src="/builders/palette.js" defer></script>
81
81
  <script src="/builders/hall-kit.js"></script>
@@ -44,7 +44,7 @@
44
44
  <script src="/builders/shell-game.js?v=2026-11-11-view2"></script>
45
45
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
46
46
  <script src="/builders/craft-mode.js?v=2026-11-10-visor"></script>
47
- <script src="/builders/shell.js?v=2026-11-11-view2"></script>
47
+ <script src="/builders/shell.js?v=2026-11-13-founding"></script>
48
48
  <script src="/builders/hall-dialog.js"></script>
49
49
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
50
50
  <script src="/builders/palette.js" defer></script>
@@ -186,7 +186,7 @@
186
186
  <script src="/builders/shell-game.js?v=2026-11-11-view2"></script>
187
187
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
188
188
  <script src="/builders/craft-mode.js?v=2026-11-10-visor"></script>
189
- <script src="/builders/shell.js?v=2026-11-11-view2"></script>
189
+ <script src="/builders/shell.js?v=2026-11-13-founding"></script>
190
190
  <script src="/builders/hall-dialog.js"></script>
191
191
  <script src="/builders/palette.js" defer></script>
192
192
  <script src="/builders/hall-kit.js"></script>
@@ -129,7 +129,7 @@
129
129
  <script src="/builders/shell-game.js?v=2026-11-11-view2"></script>
130
130
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
131
131
  <script src="/builders/craft-mode.js?v=2026-11-10-visor"></script>
132
- <script src="/builders/shell.js?v=2026-11-11-view2"></script>
132
+ <script src="/builders/shell.js?v=2026-11-13-founding"></script>
133
133
  <script src="/builders/hall-dialog.js"></script>
134
134
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
135
135
  <script src="/builders/palette.js" defer></script>
@@ -83,7 +83,7 @@
83
83
  <script src="/builders/shell-game.js?v=2026-11-11-view2"></script>
84
84
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
85
85
  <script src="/builders/craft-mode.js?v=2026-11-10-visor"></script>
86
- <script src="/builders/shell.js?v=2026-11-11-view2"></script>
86
+ <script src="/builders/shell.js?v=2026-11-13-founding"></script>
87
87
  <script src="/builders/hall-dialog.js"></script>
88
88
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
89
89
  <script src="/builders/palette.js" defer></script>
@@ -85,7 +85,7 @@
85
85
  <script src="/builders/shell-game.js?v=2026-11-11-view2"></script>
86
86
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
87
87
  <script src="/builders/craft-mode.js?v=2026-11-10-visor"></script>
88
- <script src="/builders/shell.js?v=2026-11-11-view2"></script>
88
+ <script src="/builders/shell.js?v=2026-11-13-founding"></script>
89
89
  <script src="/builders/hall-dialog.js"></script>
90
90
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
91
91
  <script src="/builders/palette.js" defer></script>
@@ -114,7 +114,7 @@
114
114
  <script src="/builders/shell-game.js?v=2026-11-11-view2"></script>
115
115
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
116
116
  <script src="/builders/craft-mode.js?v=2026-11-10-visor"></script>
117
- <script src="/builders/shell.js?v=2026-11-11-view2"></script>
117
+ <script src="/builders/shell.js?v=2026-11-13-founding"></script>
118
118
  <script src="/builders/hall-dialog.js"></script>
119
119
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
120
120
  <script src="/builders/palette.js" defer></script>
@@ -251,7 +251,7 @@
251
251
  <script src="/builders/shell-game.js?v=2026-11-11-view2"></script>
252
252
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
253
253
  <script src="/builders/craft-mode.js?v=2026-11-10-visor"></script>
254
- <script src="/builders/shell.js?v=2026-11-11-view2"></script>
254
+ <script src="/builders/shell.js?v=2026-11-13-founding"></script>
255
255
  <script src="/builders/hall-dialog.js"></script>
256
256
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
257
257
  <script src="/builders/palette.js" defer></script>
@@ -78,7 +78,7 @@
78
78
  <script src="/builders/shell-game.js?v=2026-11-11-view2"></script>
79
79
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
80
80
  <script src="/builders/craft-mode.js?v=2026-11-10-visor"></script>
81
- <script src="/builders/shell.js?v=2026-11-11-view2"></script>
81
+ <script src="/builders/shell.js?v=2026-11-13-founding"></script>
82
82
  <script src="/builders/hall-dialog.js"></script>
83
83
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
84
84
  <script src="/builders/palette.js" defer></script>
@@ -60,7 +60,7 @@
60
60
  <script src="/builders/shell-game.js?v=2026-11-11-view2"></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-11-view2"></script>
63
+ <script src="/builders/shell.js?v=2026-11-13-founding"></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>
@@ -420,7 +420,7 @@
420
420
  <script src="/builders/shell-game.js?v=2026-11-11-view2"></script>
421
421
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
422
422
  <script src="/builders/craft-mode.js?v=2026-11-10-visor"></script>
423
- <script src="/builders/shell.js?v=2026-11-11-view2"></script>
423
+ <script src="/builders/shell.js?v=2026-11-13-founding"></script>
424
424
  <script src="/builders/hall-dialog.js"></script>
425
425
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
426
426
  <script src="/builders/palette.js" defer></script>
@@ -696,29 +696,39 @@
696
696
  // ?denied=<permission>[&reason=unavailable]. Render the refusal — "you are
697
697
  // signed in; you lack X" — then strip the query so a refresh or a shared link
698
698
  // doesn't re-show a stale notice. Cosmetic only; the gate already ran.
699
+ function navItemById(id) {
700
+ var hit = null;
701
+ NAV.forEach(function (g) { g.items.forEach(function (it) { if (it.id === id) hit = it; }); });
702
+ return hit;
703
+ }
699
704
  function renderDeniedNotice() {
700
705
  // Hand-parsed (no URLSearchParams): shell.js is dependency-free by design,
701
706
  // and the hall unit tests boot it in a bare vm context.
702
707
  var search = (window.location && window.location.search) || '';
703
708
  var m = /[?&]denied=([^&]+)/.exec(search);
704
- if (!m) return;
705
- var denied = decodeURIComponent(m[1]);
706
- if (!/^[a-z0-9_.-]{1,80}$/i.test(denied)) return;
709
+ // task 1005112: a founding project's sleeping room sends its page here, naming it.
710
+ var sl = /[?&]asleep=([a-z-]{1,40})(?:&opens=([a-z]{1,20}))?(?:&|$)/.exec(search);
711
+ if (!m && !sl) return;
712
+ var denied = m ? decodeURIComponent(m[1]) : '';
713
+ if (m && !/^[a-z0-9_.-]{1,80}$/i.test(denied)) return;
707
714
  var unavailable = /[?&]reason=unavailable(?:&|$)/.test(search);
715
+ var room = sl && navItemById(sl[1]);
708
716
  var topbar = document.getElementById('app-topbar');
709
717
  if (!topbar) return;
710
718
  var el = document.createElement('div');
711
719
  el.className = 'denied-notice';
712
720
  el.setAttribute('role', 'status');
713
721
  el.innerHTML =
714
- '<span>' + (unavailable
722
+ '<span>' + (sl
723
+ ? esc(room ? room.label : 'That room') + ' isn’t open yet. It ' + esc(WAKE_TEXT[sl[2]] || 'opens later') + '. Finish that stage of founding here on Home.'
724
+ : unavailable
715
725
  ? 'You’re signed in, but access to that page couldn’t be verified just now (the permission system didn’t answer), so it stayed closed. Try again in a minute.'
716
726
  : 'You’re signed in, but that page needs the <code>' + esc(denied) + '</code> permission — your current role doesn’t hold it.') +
717
727
  '</span>' +
718
728
  '<button type="button" class="denied-notice__close" aria-label="Dismiss">×</button>';
719
729
  el.querySelector('.denied-notice__close').addEventListener('click', function () { el.remove(); });
720
730
  topbar.insertAdjacentElement('afterend', el);
721
- var rest = search.replace(/[?&](?:denied|reason)=[^&]*/g, '').replace(/^&/, '?');
731
+ var rest = search.replace(/[?&](?:denied|reason|asleep|opens)=[^&]*/g, '').replace(/^&/, '?');
722
732
  history.replaceState(null, '', window.location.pathname + rest + window.location.hash);
723
733
  }
724
734
 
@@ -916,8 +926,10 @@
916
926
  // OFF is the default and the fallback, and OFF REMOVES rather than hides: the band
917
927
  // element and every asleep class and tag are taken out of the DOM, so a hall that
918
928
  // is not founding is byte-for-byte the hall it was (tests/founding_mode.mjs pins
919
- // it). Cosmetic only — an asleep room still opens; nothing is enforced (ADR 0016).
920
- // The asleep tag in words a person would say, never a raw stage slug.
929
+ // it). task 1005112: an asleep room is HIDDEN, not dimmed, and the server refuses its
930
+ // page (src/bongos/founding-page-gate.js, the same /me answer), so this only draws.
931
+ // A room that woke since this browser last looked arrives marked, once.
932
+ // The stage in words a person would say, never a raw stage slug (the refusal notice).
921
933
  var WAKE_TEXT = {
922
934
  scope: 'opens after scope', strategize: 'opens after strategy', charter: 'opens after the charter',
923
935
  legalize: 'opens after legal setup', legislation: 'opens after legislation', alive: 'opens when alive'
@@ -930,11 +942,9 @@
930
942
  // mode — returns before touching a single node. That is the strongest form of the
931
943
  // no-hijack condition: nothing is read, created, classed or removed.
932
944
  if (!on && root.dataset.founding !== 'on') return;
933
- document.querySelectorAll('#app-sidebar .nav-item--asleep').forEach(function (el) {
945
+ document.querySelectorAll('#app-sidebar .nav-item--asleep, #app-sidebar .nav-item--arrived').forEach(function (el) {
934
946
  el.classList.remove('nav-item--asleep');
935
- delete el.dataset.wakes;
936
- var tag = el.querySelector('[data-wakes-tag]');
937
- if (tag && tag.parentNode) tag.parentNode.removeChild(tag);
947
+ if (!on) el.classList.remove('nav-item--arrived'); // the mark lasts the page, not one pass
938
948
  });
939
949
  var band = document.getElementById('founding-band');
940
950
  if (!on) {
@@ -943,17 +953,19 @@
943
953
  return;
944
954
  }
945
955
  root.dataset.founding = 'on';
956
+ // One key per browser ORIGIN, which is one project: a project's hall is its own host.
957
+ var seen = null, KEY = 'hall-founding-asleep';
958
+ try { seen = JSON.parse(window.localStorage.getItem(KEY) || 'null'); } catch (_) { seen = null; }
959
+ if (seen && typeof seen === 'object') Object.keys(seen).forEach(function (id) {
960
+ var el = !(id in f.asleep) && document.getElementById('nav-' + id);
961
+ if (el) el.classList.add('nav-item--arrived');
962
+ });
963
+ try { window.localStorage.setItem(KEY, JSON.stringify(f.asleep)); } catch (_) { /* private mode */ }
946
964
  Object.keys(f.asleep).forEach(function (id) {
965
+ // Hidden whole (style.css), so it carries no "opens after" label: the stage that
966
+ // opens it is said on Home instead, and on the refusal notice below.
947
967
  var el = document.getElementById('nav-' + id);
948
- if (!el) return;
949
- var stage = String(f.asleep[id]);
950
- el.classList.add('nav-item--asleep');
951
- el.dataset.wakes = stage;
952
- var tag = document.createElement('span');
953
- tag.className = 'nav-item__wakes';
954
- tag.setAttribute('data-wakes-tag', '');
955
- tag.textContent = WAKE_TEXT[stage] || 'opens later';
956
- el.appendChild(tag);
968
+ if (el) el.classList.add('nav-item--asleep');
957
969
  });
958
970
  if (!band) {
959
971
  var body = document.querySelector('.app-body');
@@ -228,7 +228,7 @@
228
228
  <script src="/builders/shell-game.js?v=2026-11-11-view2"></script>
229
229
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
230
230
  <script src="/builders/craft-mode.js?v=2026-11-10-visor"></script>
231
- <script src="/builders/shell.js?v=2026-11-11-view2"></script>
231
+ <script src="/builders/shell.js?v=2026-11-13-founding"></script>
232
232
  <script src="/builders/hall-dialog.js"></script>
233
233
  <script src="/builders/palette.js" defer></script>
234
234
  <script src="/builders/gov-living.js?v=2026-10-09-positions1"></script>
@@ -225,7 +225,7 @@
225
225
  <script src="/builders/shell-game.js?v=2026-11-11-view2"></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-11-view2"></script>
228
+ <script src="/builders/shell.js?v=2026-11-13-founding"></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
@@ -1082,10 +1082,15 @@ html[data-theme="dark"] .gplate__light { display: none; }
1082
1082
  .genesis__grid { grid-template-columns: minmax(0, 1fr); }
1083
1083
  .genesis__life { grid-template-columns: repeat(3, minmax(0, 1fr)); }
1084
1084
  }
1085
- .nav-item--asleep { opacity: 0.55; }
1086
- .nav-item__wakes { display: none; margin-left: auto; font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-faint); }
1087
- .app-sidebar:hover .nav-item__wakes,
1088
- .app-sidebar:focus-within .nav-item__wakes { display: inline; }
1085
+ /* task 1005112: a room a founding project has not opened is not in the sidebar at all
1086
+ (the server refuses its page too, src/bongos/founding-page-gate.js), and a group whose
1087
+ every room sleeps hides its head with it. A room that woke since this browser last
1088
+ looked arrives with a mark, once: the stage's reward, not a silent re-render. */
1089
+ .nav-item--asleep { display: none; }
1090
+ html[data-founding="on"] .nav-group:not(:has(.nav-item:not(.nav-item--asleep):not([hidden]))) { display: none; }
1091
+ .nav-item--arrived { position: relative; color: var(--ink); background: color-mix(in srgb, var(--accent) 14%, transparent); animation: nav-arrive 1.6s var(--ds-ease, ease) 2; }
1092
+ .nav-item--arrived::after { content: ""; position: absolute; top: 8px; right: 8px; width: 6px; height: 6px; border-radius: var(--ds-radius-pill); background: var(--accent); }
1093
+ @keyframes nav-arrive { 50% { background: color-mix(in srgb, var(--accent) 32%, transparent); } }
1089
1094
 
1090
1095
  /* task 1003737: the nav count badge — the hall's only badge mechanism, built
1091
1096
  once and generically (shell.js `count:` names a need id; see the NAV model).
@@ -60,7 +60,7 @@
60
60
  <script src="/builders/shell-game.js?v=2026-11-11-view2"></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-11-view2"></script>
63
+ <script src="/builders/shell.js?v=2026-11-13-founding"></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>
@@ -143,7 +143,7 @@
143
143
  <script src="/builders/shell-game.js?v=2026-11-11-view2"></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-11-view2"></script>
146
+ <script src="/builders/shell.js?v=2026-11-13-founding"></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-11-helm3"></script>
@@ -146,7 +146,7 @@
146
146
  <script src="/builders/shell-game.js?v=2026-11-11-view2"></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-11-view2"></script>
149
+ <script src="/builders/shell.js?v=2026-11-13-founding"></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>
@@ -272,7 +272,7 @@
272
272
  <script src="/builders/shell-game.js?v=2026-11-11-view2"></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-11-view2"></script>
275
+ <script src="/builders/shell.js?v=2026-11-13-founding"></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>
@@ -175,7 +175,7 @@
175
175
  <script src="/builders/shell-game.js?v=2026-11-11-view2"></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-11-view2"></script>
178
+ <script src="/builders/shell.js?v=2026-11-13-founding"></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>