@bongos/core 1.19.1051 → 1.19.1053

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 (56) hide show
  1. package/.bongos-core.json +66 -61
  2. package/docs/copy-inventory.md +138 -146
  3. package/docs/copy-registry.json +294 -458
  4. package/docs/module-api-changelog.md +4 -0
  5. package/modules/hall-ui/public/atlas.html +1 -1
  6. package/modules/hall-ui/public/blockers.html +1 -1
  7. package/modules/hall-ui/public/board-room.html +1 -1
  8. package/modules/hall-ui/public/collab.html +1 -1
  9. package/modules/hall-ui/public/copy-desk.html +1 -1
  10. package/modules/hall-ui/public/deploy.html +1 -1
  11. package/modules/hall-ui/public/diagrams.html +1 -1
  12. package/modules/hall-ui/public/drachmae.html +1 -1
  13. package/modules/hall-ui/public/fleet.html +1 -1
  14. package/modules/hall-ui/public/gate.html +1 -1
  15. package/modules/hall-ui/public/goal-map.html +18 -24
  16. package/modules/hall-ui/public/goal-map.states.json +2 -2
  17. package/modules/hall-ui/public/goals.html +1 -1
  18. package/modules/hall-ui/public/government.html +1 -1
  19. package/modules/hall-ui/public/idea.html +1 -1
  20. package/modules/hall-ui/public/ideas.html +1 -1
  21. package/modules/hall-ui/public/index.html +1 -1
  22. package/modules/hall-ui/public/modules.html +1 -1
  23. package/modules/hall-ui/public/primer.html +1 -1
  24. package/modules/hall-ui/public/profile.html +1 -1
  25. package/modules/hall-ui/public/project-settings.html +1 -1
  26. package/modules/hall-ui/public/ranks.html +1 -1
  27. package/modules/hall-ui/public/roadmap.html +1 -1
  28. package/modules/hall-ui/public/roster.html +1 -1
  29. package/modules/hall-ui/public/sessions.html +1 -1
  30. package/modules/hall-ui/public/settings.html +1 -1
  31. package/modules/hall-ui/public/shell.js +77 -1
  32. package/modules/hall-ui/public/sky-data.js +34 -19
  33. package/modules/hall-ui/public/sky-interaction.js +36 -30
  34. package/modules/hall-ui/public/sky-layout.js +11 -6
  35. package/modules/hall-ui/public/sky-panel.js +3 -2
  36. package/modules/hall-ui/public/sky-tour.js +37 -26
  37. package/modules/hall-ui/public/studio.html +10 -4
  38. package/modules/hall-ui/public/studio.states.json +76 -1
  39. package/modules/hall-ui/public/style.css +53 -0
  40. package/modules/hall-ui/public/task.html +1 -1
  41. package/modules/hall-ui/public/thinking.css +56 -16
  42. package/modules/hall-ui/public/thinking.html +52 -41
  43. package/modules/hall-ui/public/thinking.states.json +20 -3
  44. package/modules/hall-ui/public/watch.html +1 -1
  45. package/modules/hall-ui/public/work.html +1 -1
  46. package/modules/hall-ui/records/sky.md +20 -0
  47. package/package-lock.json +2 -2
  48. package/package.json +1 -1
  49. package/release-notes.json +12 -0
  50. package/src/module-api.js +1 -1
  51. package/tests/goal_map_page.mjs +54 -28
  52. package/tests/hall_audit.mjs +2 -1
  53. package/tests/hall_fullscreen.mjs +196 -0
  54. package/tests/hall_sky.mjs +49 -12
  55. package/tests/helpers.mjs +2 -1
  56. package/tests/nav_permission_atoms.mjs +1 -1
@@ -2589,5 +2589,9 @@ is load-bearing: the script throws rather than guess if it is missing, and
2589
2589
  landed since 1.19.1049 with no explicit bump. run 36324195800. (task 1002620)
2590
2590
  1.19.1051 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2591
2591
  landed since 1.19.1050 with no explicit bump. run 36369343116. (task 1002620)
2592
+ 1.19.1052 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2593
+ landed since 1.19.1051 with no explicit bump. run 36372902384. (task 1002620)
2594
+ 1.19.1053 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2595
+ landed since 1.19.1052 with no explicit bump. run 36375859084. (task 1002620)
2592
2596
  ---------------------------------------------------------------------------
2593
2597
  ```
@@ -91,7 +91,7 @@
91
91
 
92
92
  <div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
93
93
 
94
- <script src="/builders/shell.js?v=2026-09-26-nopeople"></script>
94
+ <script src="/builders/shell.js?v=2026-09-27-fullscreen"></script>
95
95
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
96
96
  <script src="/builders/palette.js" defer></script>
97
97
  <script src="/builders/atlas.js?v=2026-09-02-index" defer></script>
@@ -50,7 +50,7 @@
50
50
 
51
51
  <!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
52
52
  chrome exists before the page script runs. -->
53
- <script src="/builders/shell.js?v=2026-09-26-nopeople"></script>
53
+ <script src="/builders/shell.js?v=2026-09-27-fullscreen"></script>
54
54
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
55
55
  <script src="/builders/palette.js" defer></script>
56
56
  <!-- shared frontend toolkit (window.OTB — rank labels, number formats) + the
@@ -60,7 +60,7 @@
60
60
 
61
61
  <div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
62
62
 
63
- <script src="/builders/shell.js?v=2026-09-26-nopeople"></script>
63
+ <script src="/builders/shell.js?v=2026-09-27-fullscreen"></script>
64
64
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
65
65
  <script src="/builders/palette.js" defer></script>
66
66
  <script src="/builders/dom-utils.js?v=2026-06-16-board"></script>
@@ -148,7 +148,7 @@
148
148
 
149
149
  <div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
150
150
 
151
- <script src="/builders/shell.js?v=2026-09-26-nopeople"></script>
151
+ <script src="/builders/shell.js?v=2026-09-27-fullscreen"></script>
152
152
  <script src="/builders/palette.js" defer></script>
153
153
  <script src="/builders/dom-utils.js?v=2026-06-23-contrib"></script>
154
154
  <script src="/builders/collab-lib.js?v=2026-09-24-archive"></script>
@@ -177,7 +177,7 @@
177
177
 
178
178
  <div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
179
179
 
180
- <script src="/builders/shell.js?v=2026-09-26-nopeople"></script>
180
+ <script src="/builders/shell.js?v=2026-09-27-fullscreen"></script>
181
181
  <script src="/builders/palette.js" defer></script>
182
182
  <script src="/builders/dom-utils.js?v=2026-06-23-contrib"></script>
183
183
  <script src="/builders/hall-kit.js"></script>
@@ -69,7 +69,7 @@
69
69
 
70
70
  <div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
71
71
 
72
- <script src="/builders/shell.js?v=2026-09-26-nopeople"></script>
72
+ <script src="/builders/shell.js?v=2026-09-27-fullscreen"></script>
73
73
  <script src="/builders/palette.js" defer></script>
74
74
  <script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
75
75
  <script src="/builders/hall-kit.js"></script>
@@ -97,7 +97,7 @@
97
97
 
98
98
  <!-- The app shell (sidebar + top bar + footer). Dependency-free; runs at parse
99
99
  time so the chrome exists before the deferred page scripts execute. -->
100
- <script src="/builders/shell.js?v=2026-09-26-nopeople"></script>
100
+ <script src="/builders/shell.js?v=2026-09-27-fullscreen"></script>
101
101
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
102
102
  <script src="/builders/palette.js" defer></script>
103
103
  <script src="/builders/diagram-viewer.js?v=2026-06-14-diagviewer-1" defer></script>
@@ -98,7 +98,7 @@
98
98
 
99
99
  <div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
100
100
 
101
- <script src="/builders/shell.js?v=2026-09-26-nopeople"></script>
101
+ <script src="/builders/shell.js?v=2026-09-27-fullscreen"></script>
102
102
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
103
103
  <script src="/builders/palette.js" defer></script>
104
104
  <script src="/builders/md-reader.js?v=2026-09-02-mdreader-2"></script>
@@ -54,7 +54,7 @@
54
54
 
55
55
  <div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
56
56
 
57
- <script src="/builders/shell.js?v=2026-09-26-nopeople"></script>
57
+ <script src="/builders/shell.js?v=2026-09-27-fullscreen"></script>
58
58
  <script src="/builders/palette.js" defer></script>
59
59
  <script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
60
60
  <script src="/builders/hall-kit.js"></script>
@@ -76,7 +76,7 @@
76
76
  <div id="gate-modal-root"></div>
77
77
  <div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
78
78
 
79
- <script src="/builders/shell.js?v=2026-09-26-nopeople"></script>
79
+ <script src="/builders/shell.js?v=2026-09-27-fullscreen"></script>
80
80
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
81
81
  <script src="/builders/palette.js" defer></script>
82
82
  <script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
@@ -11,7 +11,7 @@
11
11
  <!-- The faces (Manrope, JetBrains Mono) come from the branding pack's font
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
- <link rel="stylesheet" href="/builders/thinking.css?v=2026-09-25-sky4">
14
+ <link rel="stylesheet" href="/builders/thinking.css?v=2026-09-27-split">
15
15
  </head>
16
16
  <!-- THE PROJECT SKY (task 1004232 / sky part 4 of 5, goal 1000095; ADR 0331,
17
17
  ADR 0227 §11). The SAME page as /thinking — docs/design/mocks/sky/
@@ -25,13 +25,15 @@
25
25
  URL and took the nav slot the map was denied, under Goals (owner,
26
26
  2026-09-24; ADR 0227 §11).
27
27
 
28
- The markup is thinking.html's, verbatim but for three things: the body
29
- says which lens is home (`data-sky-lens="all"` — sky-tour.js boots into it
30
- and the tour hands back to it), the brand line and the lens switcher start
31
- in that lens, and the canvas's own words say what this sky draws. The
32
- sheet and the seven sky-*.js files are SHARED with /thinking, never
33
- copied: the switcher's "simple" and "your thinking" leave for /thinking,
34
- and /thinking's "the whole project" leaves for here. The same rule as
28
+ THE WHOLE PROJECT ONLY (task 1004328, owner decision 2026-09-27). The
29
+ sheet, the seven sky-*.js files and the drawing are SHARED with /thinking,
30
+ never copied; the lenses and the tools are not. This page has one lens,
31
+ "the whole project" (`data-sky-lens="all"`), so it carries no switcher,
32
+ and it no longer offers "simple" or "your thinking". Its tools are the
33
+ project map's: explore and its start dialog, "my ideas" (your thoughts
34
+ laid over the map), routes, the ledger drawer. The ideator's pills
35
+ (recent, claude layer, my influence) are /thinking's alone, and nothing
36
+ here leaves for that page as a lens. The same rule as
35
37
  /thinking on chrome: none — the sky is a full-screen surface with its own
36
38
  header, and the hall's doors (the goal, the task, the record) open from
37
39
  the panel.
@@ -58,16 +60,8 @@
58
60
  <h1>the sky <em id="lensWord">— the whole project</em></h1>
59
61
  <div class="stats" id="stats"></div>
60
62
  </header>
61
- <div class="lens" role="group" aria-label="Filter" id="lensGroup">
62
- <button type="button" id="lensSimple" aria-pressed="false">simple</button>
63
- <button type="button" id="lensMine" aria-pressed="false">your thinking</button>
64
- <button type="button" id="lensAll" aria-pressed="true">the whole project</button>
65
- </div>
66
63
  <div class="tools" id="tools">
67
64
  <button type="button" class="pill" id="roomBtn" aria-pressed="false" title="The same sky, as a list (L)">list</button>
68
- <button type="button" class="pill" id="recentBtn" aria-pressed="false" hidden title="Only the thoughts of the last thirty days.">recent</button>
69
- <button type="button" class="pill" id="claudeBtn" aria-pressed="false" hidden title="Show the thoughts a session filed under your name. Off by default: only what a person filed.">claude layer</button>
70
- <button type="button" class="pill" id="influenceBtn" aria-pressed="false" hidden title="Only the goals your thoughts touched — everything else fades.">my influence</button>
71
65
  <button type="button" class="pill" id="exploreBtn" aria-pressed="true" title="Explore: the sky reveals itself as you follow routes from where you begin.">explore</button>
72
66
  <button type="button" class="pill" id="ideasBtn" aria-pressed="false" title="Lay your thoughts over the project map.">my ideas</button>
73
67
  <button type="button" class="pill" id="rehearse" aria-pressed="false" hidden title="What if: invents removals, dimming and nods — none has happened in the ledger yet — so you can see how the dead would read. Sizes are never invented.">what if</button>
@@ -131,13 +125,13 @@
131
125
  </div>
132
126
  </footer>
133
127
 
134
- <script src="/builders/idea-objects.js?v=2026-09-25-sky4"></script>
135
- <script src="/builders/sky-data.js?v=2026-09-25-sky4"></script>
136
- <script src="/builders/sky-layout.js?v=2026-09-25-sky4"></script>
137
- <script src="/builders/sky-draw.js?v=2026-09-25-sky4"></script>
138
- <script src="/builders/sky-interaction.js?v=2026-09-25-sky4"></script>
139
- <script src="/builders/sky-panel.js?v=2026-09-25-sky4"></script>
140
- <script src="/builders/sky-composer.js?v=2026-09-25-sky4"></script>
141
- <script src="/builders/sky-tour.js?v=2026-09-25-sky4"></script>
128
+ <script src="/builders/idea-objects.js?v=2026-09-27-split"></script>
129
+ <script src="/builders/sky-data.js?v=2026-09-27-split"></script>
130
+ <script src="/builders/sky-layout.js?v=2026-09-27-split"></script>
131
+ <script src="/builders/sky-draw.js?v=2026-09-27-split"></script>
132
+ <script src="/builders/sky-interaction.js?v=2026-09-27-split"></script>
133
+ <script src="/builders/sky-panel.js?v=2026-09-27-split"></script>
134
+ <script src="/builders/sky-composer.js?v=2026-09-27-split"></script>
135
+ <script src="/builders/sky-tour.js?v=2026-09-27-split"></script>
142
136
  </body>
143
137
  </html>
@@ -1,5 +1,5 @@
1
1
  {
2
- "_": "THE PROJECT SKY (task 1004232 / sky part 4 of 5, goal 1000095; ADR 0331, ADR 0227 §11) through modules/ui-design/kit/render.js — the same page as /thinking (thinking.states.json) opened in its 'the whole project' lens. 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 lenses, the tools, the ledger drawer and the tour all exist with no goal read). To look at the populated sky — the wells sized by credits, the routes, the shuttle menu, explore's 'where do you begin' — run it against the hall-preview harness, whose sky.json + sky__mine.json fixtures carry the wells and the routes:\n\n node scripts/hall-preview/server.js --port 4620 --fixture-me\n node modules/ui-design/kit/render.js --states modules/hall-ui/public/goal-map.states.json --base-in http://localhost:4620 --base-out http://localhost:4620\n\nThe tour opens by itself on a first visit (sky-tour-seen), so states that want the bare sky skip it first; explore is on by default and asks where you begin the first time (sky-seen), so the 'sky' state renders that prompt on purpose.",
2
+ "_": "THE PROJECT SKY (task 1004232 / sky part 4 of 5, goal 1000095; ADR 0331, ADR 0227 §11) through modules/ui-design/kit/render.js — the same renderer as /thinking (thinking.states.json), but its own sky: its only lens is 'the whole project', and it carries no switcher (task 1004328). 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 tools, the ledger drawer and the tour all exist with no goal read). To look at the populated sky — the wells sized by credits, the routes, the shuttle menu, explore's 'where do you begin' — run it against the hall-preview harness, whose sky.json + sky__mine.json fixtures carry the wells and the routes:\n\n node scripts/hall-preview/server.js --port 4620 --fixture-me\n node modules/ui-design/kit/render.js --states modules/hall-ui/public/goal-map.states.json --base-in http://localhost:4620 --base-out http://localhost:4620\n\nThe tour opens by itself on a first visit (sky-map-tour-seen — its own key, since the two tours differ), so states that want the bare sky skip it first; explore is on by default and asks where you begin the first time (sky-seen), so the 'sky' state renders that prompt on purpose.",
3
3
  "page": "/builders/goal-map",
4
4
  "surface": "hall-ui",
5
5
  "stub": { "prefix": "/builders/" },
@@ -16,7 +16,7 @@
16
16
  },
17
17
  "sky": {
18
18
  "auth": true,
19
- "_": "The 'the whole project' lens, bare: the brand line, the lenses, explore + my ideas + the clock in the tools, the legend — and explore's 'where do you begin' prompt on a first visit.",
19
+ "_": "The 'the whole project' lens, bare: the brand line, explore + my ideas + the clock in the tools, the legend — and explore's 'where do you begin' prompt on a first visit.",
20
20
  "actions": [["wait", 1200], ["clickIfVisible", "#tourSkip"], ["wait", 300]],
21
21
  "expect": { "visible": ["#sky", "#exploreBtn", "#ideasBtn"] }
22
22
  },
@@ -235,7 +235,7 @@
235
235
 
236
236
  <div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
237
237
 
238
- <script src="/builders/shell.js?v=2026-09-26-nopeople"></script>
238
+ <script src="/builders/shell.js?v=2026-09-27-fullscreen"></script>
239
239
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
240
240
  <script src="/builders/palette.js" defer></script>
241
241
  <script src="/builders/dom-utils.js?v=2026-06-14-domutils"></script>
@@ -134,7 +134,7 @@
134
134
 
135
135
  <div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
136
136
 
137
- <script src="/builders/shell.js?v=2026-09-26-nopeople"></script>
137
+ <script src="/builders/shell.js?v=2026-09-27-fullscreen"></script>
138
138
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
139
139
  <script src="/builders/palette.js" defer></script>
140
140
  <script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
@@ -52,7 +52,7 @@
52
52
 
53
53
  <div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
54
54
 
55
- <script src="/builders/shell.js?v=2026-09-26-nopeople"></script>
55
+ <script src="/builders/shell.js?v=2026-09-27-fullscreen"></script>
56
56
  <script src="/builders/palette.js" defer></script>
57
57
  <script src="/builders/dom-utils.js?v=2026-06-23-contrib" defer></script>
58
58
  <!-- task-detail.js still owns the #/idea/N and #/blocker/N overlay, so a ref
@@ -225,7 +225,7 @@
225
225
 
226
226
  <div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
227
227
 
228
- <script src="/builders/shell.js?v=2026-09-26-nopeople"></script>
228
+ <script src="/builders/shell.js?v=2026-09-27-fullscreen"></script>
229
229
  <script src="/builders/palette.js" defer></script>
230
230
  <script src="/builders/dom-utils.js?v=2026-06-23-contrib"></script>
231
231
  <!-- task 1003069 (R08) — the quick-filing form's routed result links a task
@@ -102,7 +102,7 @@
102
102
  <script src="/builders/brand-apply.js?v=2026-06-27-r75" defer></script>
103
103
  <!-- The app shell (sidebar + top bar + view router). Dependency-free; loaded
104
104
  BEFORE builders.js so the chrome ids exist when events are wired. -->
105
- <script src="/builders/shell.js?v=2026-09-26-nopeople" defer></script>
105
+ <script src="/builders/shell.js?v=2026-09-27-fullscreen" defer></script>
106
106
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
107
107
  <script src="/builders/palette.js" defer></script>
108
108
  <!-- task 2166: the shared component kit (window.OTBKit) — pager/ledger/rail.
@@ -80,7 +80,7 @@
80
80
 
81
81
  <div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
82
82
 
83
- <script src="/builders/shell.js?v=2026-09-26-nopeople"></script>
83
+ <script src="/builders/shell.js?v=2026-09-27-fullscreen"></script>
84
84
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
85
85
  <script src="/builders/palette.js" defer></script>
86
86
  <script src="/builders/dom-utils.js?v=2026-06-23-contrib"></script>
@@ -115,7 +115,7 @@
115
115
 
116
116
  <div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
117
117
 
118
- <script src="/builders/shell.js?v=2026-09-26-nopeople"></script>
118
+ <script src="/builders/shell.js?v=2026-09-27-fullscreen"></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>
121
121
  <!-- the shared markdown reader (window.OTBMdReader) — primer.js renders through
@@ -187,7 +187,7 @@
187
187
 
188
188
  <!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
189
189
  chrome exists before the page script runs. -->
190
- <script src="/builders/shell.js?v=2026-09-26-nopeople"></script>
190
+ <script src="/builders/shell.js?v=2026-09-27-fullscreen"></script>
191
191
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
192
192
  <script src="/builders/palette.js" defer></script>
193
193
  <!-- shared frontend toolkit (window.OTB) — loaded before profile.js, which pulls from it. -->
@@ -58,7 +58,7 @@
58
58
 
59
59
  <div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
60
60
 
61
- <script src="/builders/shell.js?v=2026-09-26-nopeople"></script>
61
+ <script src="/builders/shell.js?v=2026-09-27-fullscreen"></script>
62
62
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
63
63
  <script src="/builders/palette.js" defer></script>
64
64
  <script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
@@ -68,7 +68,7 @@
68
68
 
69
69
  <!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
70
70
  chrome exists before the page script runs. -->
71
- <script src="/builders/shell.js?v=2026-09-26-nopeople"></script>
71
+ <script src="/builders/shell.js?v=2026-09-27-fullscreen"></script>
72
72
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
73
73
  <script src="/builders/palette.js" defer></script>
74
74
  <!-- shared frontend toolkit (window.OTB) — loaded before ranks.js, which pulls from it. -->
@@ -41,7 +41,7 @@
41
41
 
42
42
  <div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
43
43
 
44
- <script src="/builders/shell.js?v=2026-09-26-nopeople"></script>
44
+ <script src="/builders/shell.js?v=2026-09-27-fullscreen"></script>
45
45
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
46
46
  <script src="/builders/palette.js" defer></script>
47
47
  <script src="/builders/dom-utils.js?v=2026-06-14-domutils"></script>
@@ -50,7 +50,7 @@
50
50
 
51
51
  <!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
52
52
  chrome exists before the page script runs. -->
53
- <script src="/builders/shell.js?v=2026-09-26-nopeople"></script>
53
+ <script src="/builders/shell.js?v=2026-09-27-fullscreen"></script>
54
54
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
55
55
  <script src="/builders/palette.js" defer></script>
56
56
  <!-- shared frontend toolkit (window.OTB — rank labels, number formats) + the
@@ -99,7 +99,7 @@
99
99
 
100
100
  <!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
101
101
  chrome exists before the page script runs. -->
102
- <script src="/builders/shell.js?v=2026-09-26-nopeople"></script>
102
+ <script src="/builders/shell.js?v=2026-09-27-fullscreen"></script>
103
103
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
104
104
  <script src="/builders/palette.js" defer></script>
105
105
  <!-- shared frontend toolkit (window.OTB) — loaded BEFORE sessions.js so it can pull from it. -->
@@ -436,7 +436,7 @@
436
436
 
437
437
  <!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
438
438
  chrome exists before the page scripts run. -->
439
- <script src="/builders/shell.js?v=2026-09-26-nopeople"></script>
439
+ <script src="/builders/shell.js?v=2026-09-27-fullscreen"></script>
440
440
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
441
441
  <script src="/builders/palette.js" defer></script>
442
442
  <!-- shared frontend toolkit (window.OTB) — loaded before consuming IIFEs. -->
@@ -497,11 +497,79 @@
497
497
  '<kbd class="topbar-jump__kbd" id="topbar-jump-kbd"></kbd>' +
498
498
  '</button>' +
499
499
  '<button class="zoom-toggle" id="zoom-toggle" type="button" aria-label="Text size"></button>' +
500
- '<button class="theme-toggle" id="theme-toggle" type="button" aria-label="Switch theme"></button></div>';
500
+ '<button class="theme-toggle" id="theme-toggle" type="button" aria-label="Switch theme"></button>' +
501
+ // task 1004327: the full-screen switch, LAST so it sits in the corner the
502
+ // collapsed bar keeps in full screen — the one control that stays put.
503
+ (fullscreenPage() ? '<button class="fullscreen-toggle" id="fullscreen-toggle" type="button" aria-pressed="false"></button>' : '') +
504
+ '</div>';
501
505
  var t = document.getElementById('topbar-title');
502
506
  if (t) t.textContent = title;
503
507
  }
504
508
 
509
+ // ---------- full screen (task 1004327) ----------
510
+ // One switch any page can opt into with <body data-fullscreen-switch>: it hides
511
+ // the sidebar, the top bar and the foot so the page fills the window, and the
512
+ // same button (the only thing left of the top bar) brings them back. Escape
513
+ // leaves too. The state is html[data-fullscreen="on"] — the data-theme /
514
+ // data-social pattern — so the chrome's hiding is style.css's, and a page that
515
+ // lays itself out against the chrome reads the same attribute.
516
+ //
517
+ // Remembered PER PAGE (`hall-fullscreen:<data-page>`): full screen is a choice
518
+ // about one surface, and the studio's must not follow the reader to the sky.
519
+ // Storage can throw in a private window; the chrome then just shows, which is
520
+ // the honest default.
521
+ var FULLSCREEN_KEY = 'hall-fullscreen:';
522
+ function fullscreenPage() {
523
+ var b = document.body;
524
+ if (!b || !b.hasAttribute || !b.hasAttribute('data-fullscreen-switch')) return null;
525
+ return (b.dataset && b.dataset.page) || 'page';
526
+ }
527
+ function storedFullscreen() {
528
+ var page = fullscreenPage();
529
+ if (!page) return false;
530
+ try { return window.localStorage.getItem(FULLSCREEN_KEY + page) === 'on'; } catch (_) { return false; }
531
+ }
532
+ function isFullscreen() { return document.documentElement.dataset.fullscreen === 'on'; }
533
+ var FULLSCREEN_ICONS = {
534
+ enter: '<svg viewBox="0 0 18 18" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 7V3h4M11 3h4v4M15 11v4h-4M7 15H3v-4"/></svg>',
535
+ leave: '<svg viewBox="0 0 18 18" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M7 3v4H3M15 7h-4V3M11 15v-4h4M3 11h4v4"/></svg>',
536
+ };
537
+ function applyFullscreen(on) {
538
+ if (!fullscreenPage()) on = false;
539
+ var root = document.documentElement;
540
+ if (on) root.dataset.fullscreen = 'on'; else delete root.dataset.fullscreen;
541
+ var btn = document.getElementById('fullscreen-toggle');
542
+ if (btn) {
543
+ var label = on ? 'Leave full screen (Esc)' : 'Full screen — hide the sidebar and top bar';
544
+ btn.setAttribute('aria-pressed', on ? 'true' : 'false');
545
+ btn.setAttribute('aria-label', on ? 'Leave full screen' : 'Full screen');
546
+ btn.title = label;
547
+ btn.innerHTML = on ? FULLSCREEN_ICONS.leave : FULLSCREEN_ICONS.enter;
548
+ }
549
+ if (on) closeDrawer();
550
+ }
551
+ function setFullscreen(on) {
552
+ var page = fullscreenPage();
553
+ if (!page) return;
554
+ try { window.localStorage.setItem(FULLSCREEN_KEY + page, on ? 'on' : 'off'); } catch (_) { /* private mode */ }
555
+ applyFullscreen(on);
556
+ // A page that sizes itself to its box (the sky's canvas) re-measures on the
557
+ // window's resize; the box just changed without the window doing so.
558
+ try { window.dispatchEvent(new Event('resize')); } catch (_) { /* old engine */ }
559
+ }
560
+ function inTextField(el) {
561
+ var tag = el && el.tagName ? String(el.tagName).toLowerCase() : '';
562
+ return tag === 'input' || tag === 'textarea' || tag === 'select' || !!(el && el.isContentEditable);
563
+ }
564
+ // Escape leaves full screen — unless something on the page used that press
565
+ // (a tour, a menu, the palette: each calls preventDefault) or the reader is in
566
+ // a text field, where Escape belongs to the field. Page listeners may be on
567
+ // the window AFTER this one, so the verdict waits for the dispatch to finish.
568
+ function onFullscreenKey(e) {
569
+ if (e.key !== 'Escape' || !isFullscreen() || e.defaultPrevented || inTextField(e.target)) return;
570
+ window.setTimeout(function () { if (!e.defaultPrevented && isFullscreen()) setFullscreen(false); }, 0);
571
+ }
572
+
505
573
  // ---------- theme (light / dark) ----------
506
574
  // The pack's :root override carries only light values; the dark neutrals live
507
575
  // in style.css under html[data-theme="dark"] (higher specificity than :root,
@@ -1020,6 +1088,11 @@
1020
1088
  if (theme) theme.addEventListener('click', toggleTheme);
1021
1089
  var zoom = document.getElementById('zoom-toggle');
1022
1090
  if (zoom) zoom.addEventListener('click', cycleZoom);
1091
+ var full = document.getElementById('fullscreen-toggle');
1092
+ if (full) {
1093
+ full.addEventListener('click', function () { setFullscreen(!isFullscreen()); });
1094
+ window.addEventListener('keydown', onFullscreenKey);
1095
+ }
1023
1096
  if (themeMedia && themeMedia.addEventListener) {
1024
1097
  themeMedia.addEventListener('change', function () { if (!storedTheme()) applyTheme(); });
1025
1098
  }
@@ -1098,6 +1171,7 @@
1098
1171
  renderFoot();
1099
1172
  applyTheme();
1100
1173
  applyZoom();
1174
+ applyFullscreen(storedFullscreen());
1101
1175
  applyAccess(null); // default: everything gated until access is known
1102
1176
  wire();
1103
1177
  if (IS_INDEX) {
@@ -1117,5 +1191,7 @@
1117
1191
  setView: setView,
1118
1192
  currentView: function () { return currentView; },
1119
1193
  closeDrawer: closeDrawer,
1194
+ isFullscreen: isFullscreen,
1195
+ setFullscreen: setFullscreen,
1120
1196
  };
1121
1197
  })();
@@ -29,23 +29,21 @@
29
29
  // GET /sky (which thoughts became goals or rings, from the ratify tables).
30
30
  // Nothing here guesses either from text.
31
31
  //
32
- // ONE PAGE, TWO DOORS (part 4, task 1004232). /thinking and /goal-map are the
33
- // same seven files over the same markup; the body's `data-sky-lens` says which
34
- // lens is HOME — 'mine' on /thinking (the ideator's sky), 'all' on /goal-map
35
- // (the project sky). `S.home` is read once here; sky-tour.js boots into it and
36
- // hands back to it after the tour, and sky-interaction.js's switcher leaves
37
- // for the other page rather than switching when the lens asked for lives
38
- // there. Every lens still exists inside either page, because the tour walks
39
- // all three.
32
+ // TWO SKIES, ONE RENDERER (task 1004328, owner decision 2026-09-27; it
33
+ // replaced part 4's "one page, two doors"). /thinking and /goal-map share
34
+ // these seven files, the sheet and the drawing, and nothing else: each page
35
+ // has its own lenses and its own tools. The body's `data-sky-lens` says which
36
+ // sky this is — 'mine' on /thinking, YOUR thinking only, with the lenses
37
+ // "simple" and "your thinking"; 'all' on /goal-map, the whole project, with
38
+ // the one lens "the whole project" and its features (explore, "my ideas"
39
+ // laid over the map, routes, the ledger of goals). `S.lenses` is the list a
40
+ // page may be in, and setLens never leaves it — not from a button, the tour,
41
+ // a jump or the panel. Neither page links to the other as a lens.
40
42
  //
41
- // ONE PAGE, TWO DOORS (part 4, task 1004232). /thinking and /goal-map are the
42
- // same seven files over the same markup; the body's `data-sky-lens` says which
43
- // lens is HOME — 'mine' on /thinking (the ideator's sky), 'all' on /goal-map
44
- // (the project sky). `S.home` is read once here; sky-tour.js boots into it and
45
- // hands back to it after the tour, and sky-interaction.js's switcher leaves
46
- // for the other page rather than switching when the lens asked for lives
47
- // there. Every lens still exists inside either page, because the tour walks
48
- // all three.
43
+ // A control belongs to one page's markup only (the switcher's buttons, the
44
+ // ideator's pills, the project map's pills, explore's start dialog), so the
45
+ // files touch those through hide / press / on below, which do nothing when
46
+ // the page does not carry the element.
49
47
 
50
48
  (() => {
51
49
  'use strict';
@@ -54,6 +52,10 @@
54
52
 
55
53
  // ---------------------------------------------------------------- helpers
56
54
  const $ = (id) => document.getElementById(id);
55
+ // A control one page carries and the other does not (task 1004328).
56
+ const hide = (id, v) => { const el = $(id); if (el) el.hidden = v; };
57
+ const press = (id, v) => { const el = $(id); if (el) el.setAttribute('aria-pressed', String(v)); };
58
+ const on = (id, ev, fn) => { const el = $(id); if (el) el.addEventListener(ev, fn); };
57
59
  const TAU = Math.PI * 2;
58
60
  const GOLDEN = 137.50776405003785 * Math.PI / 180;
59
61
  const reduce = !!(window.matchMedia && matchMedia('(prefers-reduced-motion: reduce)').matches);
@@ -64,6 +66,17 @@
64
66
  const lerp = (a, b, t) => a + (b - a) * t;
65
67
  const smooth = (v, a, b) => { const t = clamp((v - a) / (b - a), 0, 1); return t * t * (3 - 2 * t); };
66
68
  const ease = (t) => 1 - Math.pow(1 - t, 3);
69
+ // viewport — the box the sky is drawn in (task 1004327). On /thinking that is
70
+ // the hall's STAGE (main.sky-stage: under the top bar, beside the rail, or the
71
+ // whole window in full screen); on /goal-map, which has no stage, it is the
72
+ // window, exactly as the template measured. x/y are the box's offset in the
73
+ // window, which is what turns a pointer's clientX into a canvas coordinate.
74
+ function viewport() {
75
+ const st = document.querySelector('.sky-stage');
76
+ const r = st && st.getBoundingClientRect ? st.getBoundingClientRect() : null;
77
+ if (r && r.width > 0 && r.height > 0) return { x: r.left, y: r.top, w: r.width, h: r.height };
78
+ return { x: 0, y: 0, w: innerWidth, h: innerHeight };
79
+ }
67
80
  // esc — the prototype builds HTML strings, and every title, criterion and
68
81
  // goal name passes through here first, so a title never becomes markup.
69
82
  function esc(s) { return String(s ?? '').replace(/[&<>"']/g, (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c])); }
@@ -103,12 +116,14 @@
103
116
  // ---------------------------------------------------------------- shared state
104
117
  // Every `let` the prototype's closure held, on one object so seven files can
105
118
  // read and write the same page. Data-derived fields are filled by buildWorld.
119
+ // Which sky this page is — read once, before the state that depends on it.
120
+ const HOME = document.body.dataset.skyLens === 'all' ? 'all' : 'mine';
106
121
  const S = {
107
122
  goals: [], goalById: new Map(), taskById: new Map(), edges: [], BANDS: [], ASPECT: 1, BORN: { goals: {}, criteria: {} },
108
123
  baseIdeas: [], ideas: [], becameGoal: new Map(), becameCrit: new Map(), T0: NOW - 86400000,
109
124
  hasFiledVia: false, canNod: false, template: null, buildingVersionIds: [], loaded: false,
110
125
  rehearsal: false, claudeLayer: false, influence: false, ideasOnMap: false, recentOnly: false,
111
- lens: 'mine', home: document.body.dataset.skyLens === 'all' ? 'all' : 'mine', picked: null, hover: null, filter: 'all', gfilter: 'all', dirty: true, gravityGoal: null, flying: null, tourSpot: null,
126
+ lens: HOME, home: HOME, lenses: HOME === 'all' ? ['all'] : ['simple', 'mine'], tourKey: HOME === 'all' ? 'sky-map-tour-seen' : 'sky-tour-seen', picked: null, hover: null, filter: 'all', gfilter: 'all', dirty: true, gravityGoal: null, flying: null, tourSpot: null,
112
127
  clock: NOW, playing: false, clockHidden: store.get('sky-clock') === 'off',
113
128
  charted: new Map(), focusSet: null, explore: { on: store.get('sky-explore') !== 'off', seen: new Set(JSON.parse(store.get('sky-seen') || '[]')) },
114
129
  cam: { x: 0, y: 0, k: 0.12 }, flight: null, W: 0, H: 0, DPR: 1, t0: 0, shuttles: [],
@@ -196,7 +211,7 @@
196
211
  // buildWorld — the two reads (plus the versions) into the prototype's world.
197
212
  // Called once, after the reads; everything it derives lands on S.
198
213
  function buildWorld({ sky, mine, versions }) {
199
- S.ASPECT = clamp(innerWidth / Math.max(1, innerHeight), 1, 1.8);
214
+ const vp = viewport(); S.ASPECT = clamp(vp.w / Math.max(1, vp.h), 1, 1.8);
200
215
  S.BORN = bornFromSky(sky && sky.born);
201
216
  const BORN = S.BORN;
202
217
  const goals = ((sky && sky.goals) || []).map(goalFromSky).map((g) => ({ ...g, bornOf: BORN.goals[g.id] || null, born: toMs(g.createdAt) }));
@@ -312,7 +327,7 @@
312
327
  }
313
328
 
314
329
  Object.assign(SKY, {
315
- S, $, TAU, GOLDEN, reduce, NOW, hash, rng, clamp, lerp, smooth, ease, esc, fmtDate, fmtDay, ageDays, plain, short, store, tokens, toMs, hallBase, API, api,
330
+ S, $, hide, press, on, TAU, GOLDEN, reduce, NOW, hash, rng, clamp, lerp, smooth, ease, viewport, esc, fmtDate, fmtDay, ageDays, plain, short, store, tokens, toMs, hallBase, API, api,
316
331
  OBJ, objects, SESSION_VIAS, viaWord, bornFromSky, goalFromSky, ideaFromMine, bandsFor, wellRadius, ringR, taskAt, buildWorld, edgesOf,
317
332
  applyRehearsal, inLayer, shown, diameter, positionWord, brightnessWord, reach, became, temp, placeIdeas, touched, load,
318
333
  });