@bongos/core 1.24.80 → 1.24.82

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 (123) hide show
  1. package/.bongos-core.json +154 -124
  2. package/clients/bongos-client/README.md +1 -1
  3. package/clients/bongos-client/bongos-client.global.js +4 -0
  4. package/clients/bongos-client/index.cjs +4 -0
  5. package/clients/bongos-client/index.d.ts +5 -0
  6. package/clients/bongos-client/index.mjs +4 -0
  7. package/docs/adr/0402-helm-is-the-halls-look-and-the-hall-is-dark-only.md +142 -0
  8. package/docs/adr/README.md +1 -0
  9. package/docs/api/openapi.json +86 -2
  10. package/docs/api-reference.md +4 -2
  11. package/docs/copy-inventory.md +51 -50
  12. package/docs/copy-registry.json +121 -123
  13. package/docs/module-api-changelog.md +4 -0
  14. package/docs/page-inventory.json +2 -3
  15. package/docs/page-readings.json +226 -220
  16. package/modules/builder-settings/hall-view-prefs.js +50 -0
  17. package/modules/builder-settings/routes/settings.js +32 -0
  18. package/modules/hall-ui/public/ai-studio.html +5 -3
  19. package/modules/hall-ui/public/ai-studio.states.json +1 -0
  20. package/modules/hall-ui/public/atlas.html +3 -3
  21. package/modules/hall-ui/public/atlas.states.json +1 -0
  22. package/modules/hall-ui/public/blockers.html +3 -3
  23. package/modules/hall-ui/public/board-room.html +3 -3
  24. package/modules/hall-ui/public/board-room.states.json +1 -0
  25. package/modules/hall-ui/public/city.css +1 -3
  26. package/modules/hall-ui/public/city.html +6 -9
  27. package/modules/hall-ui/public/city.js +10 -55
  28. package/modules/hall-ui/public/city.states.json +7 -32
  29. package/modules/hall-ui/public/collab.html +3 -3
  30. package/modules/hall-ui/public/collab.states.json +1 -0
  31. package/modules/hall-ui/public/commands.html +3 -3
  32. package/modules/hall-ui/public/commands.states.json +1 -0
  33. package/modules/hall-ui/public/controls.css +63 -11
  34. package/modules/hall-ui/public/copy-desk.html +3 -3
  35. package/modules/hall-ui/public/copy-desk.states.json +1 -0
  36. package/modules/hall-ui/public/deploy.html +3 -3
  37. package/modules/hall-ui/public/deploy.states.json +1 -0
  38. package/modules/hall-ui/public/goal-map.html +4 -4
  39. package/modules/hall-ui/public/goals.html +3 -3
  40. package/modules/hall-ui/public/goals.states.json +1 -0
  41. package/modules/hall-ui/public/government.html +3 -3
  42. package/modules/hall-ui/public/government.states.json +1 -0
  43. package/modules/hall-ui/public/idea.html +3 -3
  44. package/modules/hall-ui/public/idea.states.json +1 -0
  45. package/modules/hall-ui/public/ideas.html +3 -3
  46. package/modules/hall-ui/public/ideas.states.json +1 -0
  47. package/modules/hall-ui/public/index-founding.states.json +1 -0
  48. package/modules/hall-ui/public/index-genesis-decide.states.json +1 -0
  49. package/modules/hall-ui/public/index-genesis-demo.states.json +1 -0
  50. package/modules/hall-ui/public/index-genesis.states.json +1 -0
  51. package/modules/hall-ui/public/index.html +5 -5
  52. package/modules/hall-ui/public/index.states.json +1 -0
  53. package/modules/hall-ui/public/market-watch-item.html +3 -3
  54. package/modules/hall-ui/public/market-watch-item.states.json +1 -0
  55. package/modules/hall-ui/public/market-watch-rules.html +3 -3
  56. package/modules/hall-ui/public/market-watch-rules.states.json +1 -0
  57. package/modules/hall-ui/public/market-watch.html +3 -3
  58. package/modules/hall-ui/public/market-watch.states.json +1 -0
  59. package/modules/hall-ui/public/modules.html +3 -3
  60. package/modules/hall-ui/public/modules.states.json +1 -0
  61. package/modules/hall-ui/public/money.html +3 -3
  62. package/modules/hall-ui/public/money.states.json +1 -0
  63. package/modules/hall-ui/public/my-agents.html +3 -3
  64. package/modules/hall-ui/public/my-agents.states.json +1 -0
  65. package/modules/hall-ui/public/options-menu.js +2 -1
  66. package/modules/hall-ui/public/primer.html +3 -3
  67. package/modules/hall-ui/public/primer.states.json +1 -0
  68. package/modules/hall-ui/public/profile.html +3 -3
  69. package/modules/hall-ui/public/profile.states.json +1 -0
  70. package/modules/hall-ui/public/project-settings.html +3 -3
  71. package/modules/hall-ui/public/roster.html +3 -3
  72. package/modules/hall-ui/public/roster.states.json +1 -0
  73. package/modules/hall-ui/public/settings-view.js +75 -0
  74. package/modules/hall-ui/public/settings.html +17 -4
  75. package/modules/hall-ui/public/settings.states.json +1 -0
  76. package/modules/hall-ui/public/shell-game.css +97 -42
  77. package/modules/hall-ui/public/shell-game.js +138 -40
  78. package/modules/hall-ui/public/shell.js +12 -43
  79. package/modules/hall-ui/public/street-card.states.json +1 -0
  80. package/modules/hall-ui/public/street.css +1 -5
  81. package/modules/hall-ui/public/street.html +5 -9
  82. package/modules/hall-ui/public/street.js +8 -59
  83. package/modules/hall-ui/public/street.states.json +7 -32
  84. package/modules/hall-ui/public/studio.html +3 -3
  85. package/modules/hall-ui/public/studio.states.json +1 -0
  86. package/modules/hall-ui/public/style.css +126 -65
  87. package/modules/hall-ui/public/task.html +3 -3
  88. package/modules/hall-ui/public/task.states.json +1 -0
  89. package/modules/hall-ui/public/thinking.html +4 -4
  90. package/modules/hall-ui/public/thinking.states.json +1 -0
  91. package/modules/hall-ui/public/tweak-editor.html +3 -3
  92. package/modules/hall-ui/public/tweak-editor.states.json +1 -0
  93. package/modules/hall-ui/public/visor.js +7 -1
  94. package/modules/hall-ui/public/watch.html +3 -3
  95. package/modules/hall-ui/public/watch.states.json +1 -0
  96. package/modules/hall-ui/public/work-founding.states.json +1 -0
  97. package/modules/hall-ui/public/work.html +3 -3
  98. package/modules/hall-ui/public/work.states.json +1 -0
  99. package/modules/hall-ui/records/game-mode.md +5 -4
  100. package/modules/hall-ui/records/start-screen.md +10 -2
  101. package/modules/hall-ui/specimens/components.states.json +2 -1
  102. package/modules/ui-design/public/brand.html +2 -2
  103. package/package-lock.json +2 -2
  104. package/package.json +1 -1
  105. package/release-notes.json +12 -0
  106. package/scripts/hall-preview/README.md +2 -3
  107. package/scripts/hall-preview/pref-writes.js +8 -1
  108. package/src/bongos/serve-internal.js +7 -2
  109. package/src/hall-helm.js +79 -0
  110. package/src/module-api.js +1 -1
  111. package/tests/design_reference.mjs +1 -1
  112. package/tests/hall_builders_page_pass.mjs +2 -1
  113. package/tests/hall_city.mjs +15 -29
  114. package/tests/hall_controls.mjs +52 -4
  115. package/tests/hall_fullscreen.mjs +42 -21
  116. package/tests/hall_helm.mjs +187 -0
  117. package/tests/hall_record_world.mjs +4 -2
  118. package/tests/hall_start_screen.mjs +103 -5
  119. package/tests/hall_street.mjs +13 -26
  120. package/tests/hall_topbar_320.mjs +4 -2
  121. package/tests/hall_view_prefs.mjs +42 -0
  122. package/tests/hall_visor.mjs +3 -2
  123. 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-view2">
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-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-10-character"></script>
228
+ <script src="/builders/shell.js?v=2026-11-11-view2"></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;
@@ -1266,6 +1323,8 @@ html[data-fullscreen="on"] .app-topbar {
1266
1323
  }
1267
1324
  html[data-fullscreen="on"] .app-topbar > :not(.topbar-side),
1268
1325
  html[data-fullscreen="on"] .topbar-side > :not(.fullscreen-toggle):not(.upd-pill) { display: none; }
1326
+ /* Game mode keeps its full screen: no way back to the bars inside it (task 1005200). */
1327
+ html[data-game="on"] .fullscreen-toggle { display: none; }
1269
1328
  /* task 1005191: the Update pill stays with the bars away. Game mode opens every page
1270
1329
  this way, and an update nobody can see is an update nobody takes. */
1271
1330
  html[data-fullscreen="on"] .upd-pill {
@@ -1991,7 +2050,7 @@ html.pb-editing main { padding-bottom: 180px; }
1991
2050
  tighter and each icon button is 28px — still above the 24px floor — so the
1992
2051
  whole row fits with room to spare. Pinned in tests/hall_topbar_320.mjs. */
1993
2052
  .app-topbar { gap: var(--ds-space-hair); padding: 0 var(--ds-space-xs); }
1994
- .topbar-menu, .theme-toggle, .fullscreen-toggle { width: 28px; height: 28px; }
2053
+ .topbar-menu, .fullscreen-toggle { width: 28px; height: 28px; }
1995
2054
  .zoom-toggle { min-width: 28px; height: 28px; padding: 0 6px; }
1996
2055
  .topbar-side .topbar-jump { min-width: 28px; padding: 0 6px; }
1997
2056
  }
@@ -2073,11 +2132,13 @@ html.pb-editing main { padding-bottom: 180px; }
2073
2132
  /* Focus: the world's two-tone ring — a 2px accent-derived outline at 3px offset
2074
2133
  inside an 8px --bg halo, so the indicator keeps its own edge over whatever it
2075
2134
  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. */
2135
+ ring inside themselves instead, or the halo would spill out of the 64px strip.
2136
+ A CUT control (controls.css) hands in --focus-ring: its clip-path would clip
2137
+ the outline and the halo away, so its ring is the inset two-tone one. */
2077
2138
  :focus-visible {
2078
2139
  outline: 2px solid var(--focus);
2079
2140
  outline-offset: 3px;
2080
- box-shadow: 0 0 0 8px var(--bg);
2141
+ box-shadow: var(--focus-ring, 0 0 0 8px var(--bg));
2081
2142
  border-radius: var(--radius-sm);
2082
2143
  }
2083
2144
  .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-view2">
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-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-10-character"></script>
63
+ <script src="/builders/shell.js?v=2026-11-11-view2"></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-view2">
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,13 +140,13 @@
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-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-10-character"></script>
146
+ <script src="/builders/shell.js?v=2026-11-11-view2"></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
- <script src="/builders/visor.js?v=2026-11-10-visor"></script>
149
+ <script src="/builders/visor.js?v=2026-11-11-view2"></script>
150
150
  <script src="/builders/palette.js" defer></script>
151
151
 
152
152
  <script src="/builders/idea-objects.js?v=2026-09-27-split"></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-view2">
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-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-10-character"></script>
149
+ <script src="/builders/shell.js?v=2026-11-11-view2"></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",
@@ -69,7 +69,13 @@
69
69
  var mode = typeof C.current === 'function' ? C.current() : null;
70
70
  return ACTIONS[mode] ? mode : null;
71
71
  }
72
- function actionsFor(id) { return ACTIONS[id] ? ACTIONS[id].slice() : []; }
72
+ // Game mode reaches only the game's places (task 1005200): an action that opens a classic
73
+ // page is off the glass until that page has a game version. A tool is always this page's.
74
+ function inGame(a) {
75
+ var G = window.OTBShellGame;
76
+ return !a.href || !G || typeof G.isPlace !== 'function' || G.isPlace(a.href);
77
+ }
78
+ function actionsFor(id) { return ACTIONS[id] ? ACTIONS[id].filter(inGame) : []; }
73
79
  function credits() {
74
80
  var C = craft();
75
81
  var me = C && typeof C.me === 'function' ? C.me() : null;
@@ -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-view2">
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-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-10-character"></script>
275
+ <script src="/builders/shell.js?v=2026-11-11-view2"></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-view2">
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-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-10-character"></script>
178
+ <script src="/builders/shell.js?v=2026-11-11-view2"></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",
@@ -7,14 +7,15 @@ Covers: every shelled hall page (`shell-game.js`, `shell.js`). Spec: `docs/specs
7
7
  - **Game mode is the existing full-screen switch, made hall-wide. There is no second full-screen mode.** The switch was already on every page (task 1004430) but remembered per page, so a reader had to turn it on 33 times. Game mode is one `localStorage` key, `hall-game`; while it is `on`, `shell.js` `storedFullscreen()` answers yes for every page, whatever that page remembers. What hides, the corner button and the Escape hand-off are the shell's, unchanged.
8
8
  - **`shell-game.js` holds the mode and nothing else**: `window.OTBShellGame` = `on()`, `set(bool)`, `hint()`. It stamps `html[data-game="on"]` for a sheet or script that wants to read the mode. `shell.js` reads it through a fallback object, so a page without the file is never in game mode. It is its own file because `shell.js` sits on the 1,500-line ratchet; the start screen and options menu (R03, R04) are expected to grow here, not in `shell.js`.
9
9
  - **Load order**: `shell-game.js` before `shell-trail.js` / `craft-mode.js` / `shell.js`, loaded the same way (deferred or not) as the shell on that page. Test-pinned.
10
- - **Leaving is for this page load only.** In game mode the corner button brings the bars back (Escape did too until task 1005144; it opens the options menu now), and nothing is written: the next page opens without them again, and a page's own `hall-fullscreen:<page>` memory is never overwritten. Turning game mode off (`set(false)`) hands each page back what it remembered. `OTBShell.setFullscreen(null)` is the "re-read what should show" call `set()` uses.
10
+ - **Game or classic, never both (task 1005200, owner 2026-11-11).** Inside game mode there is no way back to the bars: the corner button is hidden (`style.css`) and does nothing if pressed, Escape opens the options menu, and the "how to leave" line is never shown. The only switch is Options → Preferences → View (`settings-view.js`), plus the chooser at every sign-in (`records/start-screen.md`). A page's own `hall-fullscreen:<page>` memory is still never overwritten, so switching to classic hands each page back what it remembered.
11
+ - **Game mode reaches only the game's places** (`shell-game.js` `PLACES`: home, city, goal-map, thinking, atlas, settings, profile). Any other hall page `location.replace`s to the city on load, and so does switching to game on one. A screen embedded in the options menu is exempt. The visor drops an action whose `href` is not a place (`visor.js` `inGame`). A page joins `PLACES` when it has a game version.
12
+ - **The choice is kept on the account**: `GET/PATCH /api/bongos/me/hall-view` (`modules/builder-settings/hall-view-prefs.js`, key `hall_view` in `behavior_prefs`, null = never chosen). `hall-game` in localStorage is only the copy a page paints from; `sync()` reads the account on every page load and switches if another browser changed it.
11
13
  - **No page may opt out.** `<body data-fullscreen-switch="off">` would keep that page's sidebar in game mode; the test fails on one. A new hall page needs `#app-topbar` and the `shell-game.js` tag, like the rest.
12
- - **The "how to leave" line shows once per tab in game mode** (`sessionStorage 'hall-game-hint'`), not on every page load. Outside game mode the shell's rule is unchanged.
13
- - **How it is turned on today**: `?game=on` / `?game=off` on any hall URL, or `OTBShellGame.set()`. Nothing in the hall's interface sets it yet; the start screen (R03) is where that lands.
14
+ - **`?game=on` / `?game=off` are gone** (task 1005200): the address no longer switches the view.
14
15
 
15
16
  ## For the tasks after this one
16
17
 
17
18
  - A HUD or options menu that wants Escape must call `preventDefault()` on the press. `shell.js` `onFullscreenKey` waits one tick before leaving so a listener added after it still wins.
18
- - Since R04 (task 1005144, ADR 0401) the last Escape in game mode opens the options menu (`shell-game.js` `onEscape`), and on the menu it closes it again. The corner button is still the way back to the bars.
19
+ - Since R04 (task 1005144, ADR 0401) the last Escape in game mode opens the options menu (`shell-game.js` `onEscape`), and on the menu it closes it again. Since task 1005200 there is no way back to the bars inside game mode.
19
20
 
20
21
  Tests: `tests/hall_fullscreen.mjs` (the eight `game mode:` cases run the real `shell-game.js` + `shell.js`), and the script lists in `tests/hall_city.mjs`, `tests/hall_street.mjs`, `tests/hall_my_agents.mjs`, `tests/goal_map_page.mjs`.