@bongos/core 1.24.24 → 1.24.26

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 (65) hide show
  1. package/.bongos-core.json +84 -69
  2. package/docs/copy-inventory.md +217 -212
  3. package/docs/copy-registry.json +298 -233
  4. package/docs/module-api-changelog.md +4 -0
  5. package/docs/page-readings.json +855 -852
  6. package/modules/hall-ui/public/ai-studio.html +1 -1
  7. package/modules/hall-ui/public/blockers.html +1 -1
  8. package/modules/hall-ui/public/blockers.js +3 -1
  9. package/modules/hall-ui/public/board-room.html +2 -0
  10. package/modules/hall-ui/public/collab.html +3 -3
  11. package/modules/hall-ui/public/collab.js +4 -0
  12. package/modules/hall-ui/public/commands.html +2 -2
  13. package/modules/hall-ui/public/copy-desk.html +2 -2
  14. package/modules/hall-ui/public/criterion-uat-ui.js +1 -1
  15. package/modules/hall-ui/public/deploy.html +2 -0
  16. package/modules/hall-ui/public/drachmae.html +1 -1
  17. package/modules/hall-ui/public/fleet.html +2 -0
  18. package/modules/hall-ui/public/gate.html +2 -0
  19. package/modules/hall-ui/public/goals-page.js +1 -1
  20. package/modules/hall-ui/public/goals.css +3 -2
  21. package/modules/hall-ui/public/goals.html +2 -2
  22. package/modules/hall-ui/public/goals.js +1 -1
  23. package/modules/hall-ui/public/government.html +2 -0
  24. package/modules/hall-ui/public/hall-widgets.js +9 -9
  25. package/modules/hall-ui/public/ideas.html +2 -2
  26. package/modules/hall-ui/public/index.html +2 -0
  27. package/modules/hall-ui/public/lightbulb.js +1 -1
  28. package/modules/hall-ui/public/market-watch-item.html +1 -1
  29. package/modules/hall-ui/public/market-watch-rules.html +1 -1
  30. package/modules/hall-ui/public/market-watch-settings.html +2 -0
  31. package/modules/hall-ui/public/market-watch.html +1 -1
  32. package/modules/hall-ui/public/modules.html +1 -1
  33. package/modules/hall-ui/public/my-agents.html +2 -2
  34. package/modules/hall-ui/public/primer.html +1 -1
  35. package/modules/hall-ui/public/profile.html +5 -5
  36. package/modules/hall-ui/public/project-settings.html +2 -0
  37. package/modules/hall-ui/public/ranks.html +3 -3
  38. package/modules/hall-ui/public/roadmap.html +1 -1
  39. package/modules/hall-ui/public/roster.html +1 -1
  40. package/modules/hall-ui/public/sessions.html +2 -0
  41. package/modules/hall-ui/public/settings-software-update.js +1 -1
  42. package/modules/hall-ui/public/settings-specialities.js +1 -1
  43. package/modules/hall-ui/public/settings.html +3 -1
  44. package/modules/hall-ui/public/settings.js +3 -0
  45. package/modules/hall-ui/public/studio.js +3 -3
  46. package/modules/hall-ui/public/style.css +90 -1
  47. package/modules/hall-ui/public/task-detail.js +2 -2
  48. package/modules/hall-ui/public/tweak-editor.html +1 -1
  49. package/modules/hall-ui/public/watch.html +2 -0
  50. package/modules/hall-ui/public/watch.js +1 -1
  51. package/modules/hall-ui/public/work.html +3 -3
  52. package/modules/hall-ui/records/loader.md +35 -0
  53. package/package-lock.json +2 -2
  54. package/package.json +1 -1
  55. package/release-notes.json +16 -0
  56. package/scripts/hall-preview/README.md +1 -0
  57. package/scripts/hall-preview/server.js +9 -0
  58. package/src/bongos/apex-hall-redirects.js +53 -0
  59. package/src/bongos/package-registry.js +3 -2
  60. package/src/bongos/routes/core-update.js +11 -3
  61. package/src/bongos/serve-internal.js +3 -18
  62. package/src/bongos/software-update.js +36 -16
  63. package/src/module-api.js +1 -1
  64. package/tests/hall_loading.mjs +153 -0
  65. package/tests/software_update.mjs +94 -3
@@ -73,7 +73,7 @@
73
73
  <!-- The view, painted by ai-studio.js. The page's one <h1> is each
74
74
  view's own question or figure. -->
75
75
  <div class="ais-page" id="ais-page">
76
- <p class="ais-quiet">Opening…</p>
76
+ <p class="hall-loading hall-loading--page" role="status">Opening…</p>
77
77
  </div>
78
78
  <input type="file" id="ais-file" class="ais-file" multiple accept="image/png,image/jpeg,image/gif,image/webp,application/pdf" tabindex="-1" aria-hidden="true">
79
79
  <input type="file" id="ais-camera-file" class="ais-file" accept="image/*" capture="environment" tabindex="-1" aria-hidden="true">
@@ -44,7 +44,7 @@
44
44
  <h2 id="blockers-h" class="scroll__h">Requires project owner fix<span class="count-pill" id="blockers-count" hidden></span></h2>
45
45
  <div id="blockers-file-area"></div>
46
46
  <div id="blockers-body">
47
- <p class="profile__placeholder">Loading…</p>
47
+ <p class="hall-loading hall-loading--page" role="status">Loading…</p>
48
48
  </div>
49
49
  </section>
50
50
  </main>
@@ -297,7 +297,9 @@
297
297
  }
298
298
 
299
299
  function mountShell() {
300
- body.innerHTML = '<ul class="ov-rows" id="blockers-list"></ul>' + kit.pagerBarHtml(pager.prefix, { label: 'blockers' });
300
+ // The loader holds the list until renderList's first paint replaces it (task 1005043).
301
+ body.innerHTML = '<ul class="ov-rows" id="blockers-list"><li class="hall-loading hall-loading--page" role="status">Loading…</li></ul>'
302
+ + kit.pagerBarHtml(pager.prefix, { label: 'blockers' });
301
303
  kit.wirePager(pager, function () { fetchPage(); });
302
304
  }
303
305
 
@@ -32,6 +32,8 @@
32
32
  </div>
33
33
 
34
34
  <main id="hall-main">
35
+ <!-- task 1005043: the page loader, shown until any section below is revealed. -->
36
+ <p class="hall-loading hall-loading--page hall-loading--wait" role="status">Loading…</p>
35
37
  <!-- task 1003469: the sealed state is a panel with a heading, not a bare
36
38
  line on the ground. board-room.js writes the floor into the lede from
37
39
  the pack's rank label, so the copy cannot drift. Unlike its
@@ -49,7 +49,7 @@
49
49
  <span class="cb-block__age" id="cb-for-me-age" hidden></span>
50
50
  <span class="cb-faces" id="cb-for-me-faces" aria-hidden="true"></span>
51
51
  </div>
52
- <ul class="ov-rows" id="cb-for-me"></ul>
52
+ <ul class="ov-rows" id="cb-for-me"><li class="hall-loading" role="status">Loading…</li></ul>
53
53
  <div class="empty-state cb-empty" id="cb-for-me-empty" hidden>
54
54
  <p>Nobody is waiting on you. Requests reach you by role —
55
55
  <a href="/builders/settings">set yours in Settings</a>.</p>
@@ -79,7 +79,7 @@
79
79
  <h2 class="scroll__h" id="cb-mine-h">Your asks <span class="cb-block__n" id="cb-mine-n"></span></h2>
80
80
  <span class="cb-block__age" id="cb-mine-age" hidden></span>
81
81
  </div>
82
- <ul class="ov-rows" id="cb-mine"></ul>
82
+ <ul class="ov-rows" id="cb-mine"><li class="hall-loading" role="status">Loading…</li></ul>
83
83
  <div class="empty-state cb-empty" id="cb-mine-empty" hidden><p>You have no open asks.</p></div>
84
84
  <button class="btn-ghost cb-more" id="cb-mine-more" type="button" aria-expanded="false" aria-controls="cb-mine" hidden></button>
85
85
  </section>
@@ -91,7 +91,7 @@
91
91
  <span class="cb-block__age" id="cb-all-age" hidden></span>
92
92
  <span class="cb-faces" id="cb-all-faces" aria-hidden="true"></span>
93
93
  </div>
94
- <ul class="ov-rows" id="cb-all"></ul>
94
+ <ul class="ov-rows" id="cb-all"><li class="hall-loading" role="status">Loading…</li></ul>
95
95
  <div class="empty-state cb-empty" id="cb-all-empty" hidden><p>Nobody has an open ask right now.</p></div>
96
96
  <button class="btn-ghost cb-more" id="cb-all-more" type="button" aria-expanded="false" aria-controls="cb-all" hidden></button>
97
97
  </section>
@@ -843,5 +843,9 @@
843
843
  const sub = $('#cb-sub');
844
844
  // V6: a message that stops someone points at the next move in the same breath.
845
845
  if (sub) sub.textContent = 'Could not load requests — reload to try again.';
846
+ // task 1005043: the loaders stop, and the same words stand where the asks would have.
847
+ ['for-me', 'mine', 'all'].forEach((k) => { const host = $(`#cb-${k}`); if (host) host.innerHTML = ''; });
848
+ const first = $('#cb-for-me');
849
+ if (first) first.innerHTML = '<li class="empty-state"><p>Could not load requests — reload to try again.</p></li>';
846
850
  });
847
851
  })();
@@ -33,14 +33,14 @@
33
33
  <span><span class="fact-pill fact-pill--info">Shown to Claude</span> Claude can start it when you ask in plain words.</span>
34
34
  <span><span class="fact-pill cmd-how--typed">Type it yourself</span> Kept out of Claude's menu to save room; type <code>/name</code> to run it.</span>
35
35
  </div>
36
- <div id="skills-body" aria-live="polite"><p class="cmd-error">Loading the slash commands…</p></div>
36
+ <div id="skills-body" aria-live="polite"><p class="hall-loading" role="status">Loading the slash commands…</p></div>
37
37
  <p class="cmd-note">Some commands refuse below a certain rank.</p>
38
38
  </section>
39
39
 
40
40
  <section class="scroll" id="cli-scroll" aria-labelledby="cli-h">
41
41
  <h2 id="cli-h" class="scroll__h">Terminal commands (bongos)</h2>
42
42
  <p class="scroll__lede">The same work from any terminal. <code>bongos help</code> lists them there.</p>
43
- <div id="cli-body" aria-live="polite"><p class="cmd-error">Loading the terminal commands…</p></div>
43
+ <div id="cli-body" aria-live="polite"><p class="hall-loading" role="status">Loading the terminal commands…</p></div>
44
44
  </section>
45
45
  </main>
46
46
 
@@ -46,7 +46,7 @@
46
46
  <h2 id="cd-flags-h" class="scroll__h">Flagged</h2>
47
47
  <p class="scroll__lede">Copy someone has judged as needing attention, with their reason. Anyone can file one; closing it needs the <span id="cd-close-rank">Metic</span> rank or above, or that it is your own.</p>
48
48
  <div id="cd-filters"></div>
49
- <div id="cd-flags"><div class="empty-state"><p>Loading…</p></div></div>
49
+ <div id="cd-flags"><div class="empty-state"><p class="hall-loading" role="status">Loading…</p></div></div>
50
50
  </section>
51
51
 
52
52
  <!-- The one signal a machine can compute with no judgement layer at all
@@ -55,7 +55,7 @@
55
55
  <section class="scroll" id="cd-dupes-scroll" aria-labelledby="cd-dupes-h">
56
56
  <h2 id="cd-dupes-h" class="scroll__h">Said more than once</h2>
57
57
  <p class="scroll__lede">The same sentence, in several places. Sometimes that is right and the answer is to dismiss it; sometimes it is seven copies of an error message that should have been one. Nobody has looked at the ones marked untouched.</p>
58
- <div id="cd-dupes"><div class="empty-state"><p>Loading…</p></div></div>
58
+ <div id="cd-dupes"><div class="empty-state"><p class="hall-loading" role="status">Loading…</p></div></div>
59
59
  </section>
60
60
 
61
61
  <!-- Find any string in the product and flag it. Without this the queue
@@ -195,7 +195,7 @@
195
195
  if (existing) { existing.remove(); btn.setAttribute('aria-expanded', 'false'); return; }
196
196
  const panel = document.createElement('div');
197
197
  panel.className = 'uat-panel';
198
- panel.textContent = 'Loading…';
198
+ panel.innerHTML = '<p class="hall-loading hall-loading--inline" role="status">Loading…</p>';
199
199
  row.appendChild(panel);
200
200
  btn.setAttribute('aria-expanded', 'true');
201
201
  try {
@@ -28,6 +28,8 @@
28
28
  </div>
29
29
 
30
30
  <main id="hall-main">
31
+ <!-- task 1005043: the page loader, shown until any section below is revealed. -->
32
+ <p class="hall-loading hall-loading--page hall-loading--wait" role="status">Loading…</p>
31
33
  <section class="scroll" id="dp-sealed" aria-labelledby="dp-sealed-h" hidden>
32
34
  <h2 class="scroll__h" id="dp-sealed-h">Restricted</h2>
33
35
  <p class="scroll__lede" id="dp-sealed-body">This page opens at a higher rank.</p>
@@ -51,7 +51,7 @@
51
51
  <nav class="primer-toc__inner">
52
52
  <p class="primer-toc__heading" id="primer-toc-heading">On this page</p>
53
53
  <ol class="primer-toc__list" id="primer-toc-list" aria-labelledby="primer-toc-heading">
54
- <li class="primer-toc__placeholder">Loading…</li>
54
+ <li class="hall-loading hall-loading--inline" role="status">Loading…</li>
55
55
  </ol>
56
56
  </nav>
57
57
  </aside>
@@ -27,6 +27,8 @@
27
27
  </div>
28
28
 
29
29
  <main id="hall-main">
30
+ <!-- task 1005043: the page loader, shown until any section below is revealed. -->
31
+ <p class="hall-loading hall-loading--page hall-loading--wait" role="status">Loading…</p>
30
32
  <section class="scroll" id="fl-sealed" aria-labelledby="fl-sealed-h" hidden>
31
33
  <h2 class="scroll__h" id="fl-sealed-h">Restricted</h2>
32
34
  <p class="scroll__lede">This page opens at a higher rank.</p>
@@ -27,6 +27,8 @@
27
27
  </div>
28
28
 
29
29
  <main id="hall-main">
30
+ <!-- task 1005043: the page loader, shown until any section below is revealed. -->
31
+ <p class="hall-loading hall-loading--page hall-loading--wait" role="status">Loading…</p>
30
32
  <!-- task 1003469: the sealed state is a panel with a heading, not a bare
31
33
  line on the ground. gate.js writes the real floor into the lede from
32
34
  the pack's rank label, so the copy cannot drift from ADR 0157. -->
@@ -741,7 +741,7 @@
741
741
  // the goal's tasks load, and reset the To-do count + hide the bulk toolbar.
742
742
  const todoList = $('#goal-todo-list');
743
743
  const doneBody = document.querySelector('#goal-done tbody');
744
- if (todoList) todoList.innerHTML = '<div class="profile__placeholder">…</div>';
744
+ if (todoList) todoList.innerHTML = '<div class="hall-loading" role="status">Loading…</div>';
745
745
  if (doneBody) doneBody.innerHTML = skeletonRows(3, 5);
746
746
  const todoCount = $('#goal-todo-count');
747
747
  if (todoCount) todoCount.textContent = '';
@@ -407,9 +407,10 @@
407
407
  .gr-pills--muted .gr-pill { color: var(--ink-faint); }
408
408
  .gr-pills--muted .gr-pill__mark { stroke: var(--ink-faint); }
409
409
 
410
- /* Boot skeleton: row-shaped, in the skeleton tone (--bg-deep is black in dark). */
410
+ /* Boot skeleton: row-shaped, in the skeleton tone (--bg-deep is black in dark).
411
+ The ring breathes with the bars, in the hall loader's beat (task 1005043). */
411
412
  .gr-row--skel { pointer-events: none; }
412
- .gr-skel__ring { display: block; width: var(--ring); height: var(--ring); border-radius: 50%; background: var(--skeleton); }
413
+ .gr-skel__ring { display: block; width: var(--ring); height: var(--ring); border-radius: 50%; background: var(--skeleton); animation: hall-loading-breathe .8s ease-in-out infinite alternate-reverse; }
413
414
  .gr-row--skel .kit-skel { display: block; width: 60%; }
414
415
  .gr-row--skel .kit-skel + .kit-skel { width: 40%; margin-top: 10px; }
415
416
 
@@ -156,7 +156,7 @@
156
156
  <div id="goal-work-filters"></div>
157
157
  <p class="claim-count-line" id="goal-todo-count" aria-live="polite"></p>
158
158
  <div class="task-list" id="goal-todo-list">
159
- <div class="profile__placeholder">…</div>
159
+ <div class="hall-loading" role="status">Loading…</div>
160
160
  </div>
161
161
  <div id="goal-todo-pager-mount"></div>
162
162
  </div>
@@ -167,7 +167,7 @@
167
167
  <th class="ledger__sortable" id="goal-done-sort-credits" role="button" tabindex="0" aria-sort="none" data-currency-label="caps">Credits</th>
168
168
  <th class="ledger__sortable" id="goal-done-sort-shipped" role="button" tabindex="0" aria-sort="none">Shipped</th>
169
169
  </tr></thead>
170
- <tbody><tr><td colspan="5" class="ledger__empty">…</td></tr></tbody></table>
170
+ <tbody><tr><td colspan="5" class="ledger__empty"><span class="hall-loading" role="status">Loading…</span></td></tr></tbody></table>
171
171
  <div id="goal-done-pager-mount"></div>
172
172
  </div>
173
173
  </div>
@@ -107,7 +107,7 @@
107
107
 
108
108
  const SKELETON =
109
109
  '<h2 id="goals-h" class="scroll__h">Goals</h2>' +
110
- '<div id="goals-body"><div class="profile__placeholder">Loading your goals…</div></div>';
110
+ '<div id="goals-body"><div class="hall-loading" role="status">Loading your goals…</div></div>';
111
111
 
112
112
  async function load() {
113
113
  if (!host) return;
@@ -27,6 +27,8 @@
27
27
  </div>
28
28
 
29
29
  <main id="hall-main">
30
+ <!-- task 1005043: the page loader, shown until any section below is revealed. -->
31
+ <p class="hall-loading hall-loading--page hall-loading--wait" role="status">Loading…</p>
30
32
  <!-- task 1003469: the sealed state is a panel with a heading, not a bare
31
33
  line on the ground. government.js writes the real floor into the
32
34
  lede from the pack's rank label, so the copy cannot drift. -->
@@ -51,14 +51,14 @@
51
51
  w('welcome-scroll', 'Welcome', 0,
52
52
  '<button type="button" class="welcome__minimize" id="welcome-minimize" aria-label="Minimize the welcome panel" title="Minimize">−</button>' +
53
53
  '<h2 id="welcome-h" class="scroll__h">Welcome</h2>' +
54
- '<div class="welcome" id="welcome-body"><div class="profile__placeholder">…</div></div>',
54
+ '<div class="welcome" id="welcome-body"><div class="hall-loading" role="status">Loading…</div></div>',
55
55
  { view: 'home', zone: 'home-banner', welcomeChip: true, sectionClass: 'scroll scroll--welcome', labelledby: 'welcome-h', hiddenByDefault: true });
56
56
 
57
57
  // 0b. Onboarding checklist — V3.R75 (#294).
58
58
  w('onboarding-scroll', 'Getting started', 10,
59
59
  '<h2 id="onboarding-h" class="scroll__h">Getting started</h2>' +
60
60
  '<p class="scroll__lede">A short path to finding your feet. Tick the steps you’ve done; the rest are tracked for you.</p>' +
61
- '<ol class="onboarding-list" id="onboarding-list"><li class="onboarding-item onboarding-item--placeholder">…</li></ol>' +
61
+ '<ol class="onboarding-list" id="onboarding-list"><li class="hall-loading" role="status">Loading…</li></ol>' +
62
62
  '<p class="ledger__note" id="onboarding-status" hidden></p>',
63
63
  { view: 'home', zone: 'home-banner', labelledby: 'onboarding-h', hiddenByDefault: true });
64
64
 
@@ -114,7 +114,7 @@
114
114
  '<div class="home-split__col">' +
115
115
  '<h3 class="ginbox__sec-h" id="home-recent-subh" hidden>Recently shipped</h3>' +
116
116
  '<table class="ledger" id="home-recent-table"><thead><tr><th>№</th><th>Work</th><th data-currency-label="caps">Credits</th><th>Shipped</th></tr></thead>' +
117
- '<tbody><tr><td colspan="4" class="ledger__empty">…</td></tr></tbody></table>' +
117
+ '<tbody><tr><td colspan="4" class="ledger__empty"><span class="hall-loading" role="status">Loading…</span></td></tr></tbody></table>' +
118
118
  '<p class="card-foot"><a href="#accomplishments-work">All your work →</a></p>' +
119
119
  '</div>' +
120
120
  '</div>',
@@ -157,7 +157,7 @@
157
157
  // the band sits above the rail sections and is never a rail entry.
158
158
  w('profile-scroll', 'Profile', 20,
159
159
  '<h2 id="profile-h" class="sr-only">Profile</h2>' +
160
- '<div class="profile" id="profile-body"><div class="profile__placeholder">…</div></div>',
160
+ '<div class="profile" id="profile-body"><div class="hall-loading" role="status">Loading…</div></div>',
161
161
  { view: 'standing', sectionClass: 'scroll scroll--profile', labelledby: 'profile-h' });
162
162
 
163
163
  /* -- Work — "what have I shipped, and how was it judged" -- */
@@ -179,7 +179,7 @@
179
179
  '<span id="ships-count" aria-live="polite" class="filter__count"></span>' +
180
180
  '</div>' +
181
181
  '<table class="ledger" id="recent-ships"><thead><tr><th>№</th><th>Work</th><th data-currency-label="caps">Credits</th><th>Shipped</th></tr></thead>' +
182
- '<tbody><tr><td colspan="4" class="ledger__empty">…</td></tr></tbody></table>' +
182
+ '<tbody><tr><td colspan="4" class="ledger__empty"><span class="hall-loading" role="status">Loading…</span></td></tr></tbody></table>' +
183
183
  // task 2174: the hand-rolled prev/next bar gives way to the OTBKit pager
184
184
  // (per-page select, page indicator, clamping) — same #ships-* id prefix.
185
185
  window.OTBKit.pagerBarHtml('ships', { label: 'shipped work' }),
@@ -190,7 +190,7 @@
190
190
  '<h2 id="marks-h" class="scroll__h">Reviews</h2>' +
191
191
  '<div class="profile__placeholder" id="marks-empty" style="display:none;">No work reviewed yet.</div>' +
192
192
  '<table class="ledger" id="recent-grades"><thead><tr><th>№</th><th>Work</th><th>Score</th><th>Verdict</th><th>Reviewed</th></tr></thead>' +
193
- '<tbody><tr><td colspan="5" class="ledger__empty">…</td></tr></tbody></table>' +
193
+ '<tbody><tr><td colspan="5" class="ledger__empty"><span class="hall-loading" role="status">Loading…</span></td></tr></tbody></table>' +
194
194
  '<p class="ledger__note" id="grades-rolling-note" hidden></p>',
195
195
  { view: 'standing', group: 'work', labelledby: 'marks-h' });
196
196
 
@@ -201,7 +201,7 @@
201
201
  '<h2 id="karma-h" class="scroll__h">Karma</h2>' +
202
202
  '<p class="scroll__lede">Ideas passed, peer votes and approvals earn karma. Shipped work earns ' + curLabel() + '.</p>' +
203
203
  '<table class="ledger" id="karma-feed"><thead><tr><th>When</th><th>Delta</th><th>Reason</th><th>Granted by</th></tr></thead>' +
204
- '<tbody><tr><td colspan="4" class="ledger__empty">…</td></tr></tbody></table>',
204
+ '<tbody><tr><td colspan="4" class="ledger__empty"><span class="hall-loading" role="status">Loading…</span></td></tr></tbody></table>',
205
205
  { view: 'standing', group: 'karma', labelledby: 'karma-h', hiddenByDefault: true });
206
206
 
207
207
  // 4b. Peer acclaim — V3.R25 (#245). Hidden until data.
@@ -209,7 +209,7 @@
209
209
  '<h2 id="acclaim-h" class="scroll__h">Peer recognition</h2>' +
210
210
  '<p class="scroll__lede">Vote on others’ finished work. A vote counts toward their karma after a week.</p>' +
211
211
  '<table class="ledger" id="acclaim-feed"><thead><tr><th>Work</th><th>By</th><th>Votes</th></tr></thead>' +
212
- '<tbody><tr><td colspan="3" class="ledger__empty">…</td></tr></tbody></table>' +
212
+ '<tbody><tr><td colspan="3" class="ledger__empty"><span class="hall-loading" role="status">Loading…</span></td></tr></tbody></table>' +
213
213
  // task 1002446: the last unpaged list in the hall. The feed is already
214
214
  // client-side, so the kit's pager fits without touching the endpoint.
215
215
  window.OTBKit.pagerBarHtml('acclaim', { label: 'entries' }),
@@ -236,7 +236,7 @@
236
236
  w('honours-scroll', 'Achievements', 60,
237
237
  '<h2 id="ach-h" class="scroll__h">Achievements</h2>' +
238
238
  '<p class="scroll__lede">Earned ones are lit; the rest show what is left.</p>' +
239
- '<div class="ach-grid" id="ach-grid"><div class="profile__placeholder">…</div></div>',
239
+ '<div class="ach-grid" id="ach-grid"><div class="hall-loading" role="status">Loading…</div></div>',
240
240
  { view: 'standing', group: 'achievements', labelledby: 'ach-h' });
241
241
 
242
242
  // task 1003441: the Leaderboard widget is GONE from this page. It is a real
@@ -129,7 +129,7 @@
129
129
  Anyone can develop one — the author keeps the credit for having had it,
130
130
  and you are recorded as its developer.
131
131
  </p>
132
- <div id="fi-queue"><p class="fi-note">Loading…</p></div>
132
+ <div id="fi-queue"><p class="hall-loading" role="status">Loading…</p></div>
133
133
  </section>
134
134
 
135
135
  <!-- The composer. The idea detail view lives on its own page (R153).
@@ -180,7 +180,7 @@
180
180
  one step earlier, and it would silently ignore a per-project
181
181
  template (R156). -->
182
182
  <div id="fi-fields" class="fi-fields">
183
- <p class="fi-note">Loading the five questions…</p>
183
+ <p class="hall-loading" role="status">Loading the five questions…</p>
184
184
  </div>
185
185
 
186
186
  <!-- The scope recommendation (BV2.R13). Rendered from the same
@@ -69,6 +69,8 @@
69
69
  .view/.view-zone wrappers are shell layout only. -->
70
70
  <main class="app-views" id="hall-main">
71
71
  <section class="view" id="view-home" data-view-title="Home">
72
+ <!-- task 1005043: Home's loader, shown until a card mounts into a zone. -->
73
+ <p class="hall-loading hall-loading--page hall-loading--zones" role="status">Loading…</p>
72
74
  <div class="view-zone" id="zone-home-banner">
73
75
  <!-- Landing card for signed-out visitors (builders.js renderLanding)
74
76
  + the re-open affordance for a dismissed welcome banner. -->
@@ -83,7 +83,7 @@
83
83
  '<button class="pn__submit" type="button" data-lb-submit>Turn into ideas</button>' +
84
84
  '</div>' +
85
85
  '<section class="pn__list" aria-labelledby="lb-list-h"><h3 class="pn__list-h" id="lb-list-h">Ideas from this page</h3>' +
86
- '<div id="lb-list"><p class="pn__quiet">Loading…</p></div>' +
86
+ '<div id="lb-list"><p class="hall-loading" role="status">Loading…</p></div>' +
87
87
  '</section>';
88
88
  }
89
89
  function listHtml(ideas) {
@@ -26,7 +26,7 @@
26
26
 
27
27
  <main id="hall-main">
28
28
  <a class="mw-back" href="/market-watch">‹ Market Watch</a>
29
- <p class="mw-quiet" id="mw-loading">Loading the case file…</p>
29
+ <p class="hall-loading hall-loading--page" id="mw-loading" role="status">Loading the case file…</p>
30
30
 
31
31
  <section class="mw-panel mw-off" id="mw-off" hidden>
32
32
  <span class="mw-label">market watch</span>
@@ -28,7 +28,7 @@
28
28
  <main id="hall-main" class="mwr">
29
29
  <div id="mwr-slider"></div>
30
30
  <div class="mwr-pipe" id="mwr-pipe" aria-label="the watch, step by step"></div>
31
- <section class="mwr-panel" id="mwr-panel" aria-live="polite"><p class="mwr-empty">Loading the watch rules…</p></section>
31
+ <section class="mwr-panel" id="mwr-panel" aria-live="polite"><p class="hall-loading hall-loading--page" role="status">Loading the watch rules…</p></section>
32
32
  <h2 class="mwr-lbl">cost of one run, by step</h2>
33
33
  <div id="mwr-cost"></div>
34
34
  </main>
@@ -25,6 +25,8 @@
25
25
  </div>
26
26
 
27
27
  <main id="hall-main">
28
+ <!-- task 1005043: the page loader, shown until any section below is revealed. -->
29
+ <p class="hall-loading hall-loading--page hall-loading--wait" role="status">Loading…</p>
28
30
  <!-- What a reader who is not the owner sees. The routes are the wall (403); this is
29
31
  only what stands in for an empty gauge. -->
30
32
  <section class="scroll" id="mws-sealed" aria-labelledby="mws-sealed-h" hidden>
@@ -25,7 +25,7 @@
25
25
  </div>
26
26
 
27
27
  <main id="hall-main">
28
- <p class="mw-quiet" id="mw-loading">Loading the watch…</p>
28
+ <p class="hall-loading hall-loading--page" id="mw-loading" role="status">Loading the watch…</p>
29
29
 
30
30
  <!-- Market Watch is off on this project: a quiet line, never an error. -->
31
31
  <section class="mw-panel mw-off" id="mw-off" hidden>
@@ -56,7 +56,7 @@
56
56
  <span class="ov-group__name">Shipped with the core</span>
57
57
  <span class="ov-group__n" id="core-n"></span>
58
58
  </div>
59
- <ul class="ov-rows" id="core-grid"><li class="mod-loading">Loading the catalog…</li></ul>
59
+ <ul class="ov-rows" id="core-grid"><li class="hall-loading" role="status">Loading the catalog…</li></ul>
60
60
  </div>
61
61
 
62
62
  <!-- Built by this project — the pool `bongos module submit` draws from
@@ -41,13 +41,13 @@
41
41
  <section class="scroll ma-desk" id="ma-desk" aria-labelledby="ma-desk-h">
42
42
  <h2 class="scroll__h" id="ma-desk-h">Your agents</h2>
43
43
  <p class="scroll__lede" id="ma-desk-lede">One line each. Tap to change; it saves straight away.</p>
44
- <div id="ma-rows" aria-live="polite"><p class="ma-quiet">Reading your settings…</p></div>
44
+ <div id="ma-rows" aria-live="polite"><p class="hall-loading" role="status">Reading your settings…</p></div>
45
45
  </section>
46
46
 
47
47
  <aside class="scroll ma-reads" id="ma-reads" aria-labelledby="ma-reads-h">
48
48
  <h2 class="scroll__h" id="ma-reads-h">What your agent reads first</h2>
49
49
  <p class="scroll__lede">At the start of every session, in this order.</p>
50
- <div id="ma-reads-body" aria-live="polite"><p class="ma-quiet">Reading…</p></div>
50
+ <div id="ma-reads-body" aria-live="polite"><p class="hall-loading" role="status">Reading…</p></div>
51
51
  </aside>
52
52
  </div>
53
53
  </main>
@@ -52,7 +52,7 @@
52
52
  <nav class="primer-toc__inner">
53
53
  <p class="primer-toc__heading" id="primer-toc-heading">In this primer</p>
54
54
  <ol class="primer-toc__list" id="primer-toc-list" aria-labelledby="primer-toc-heading">
55
- <li class="primer-toc__placeholder">Loading…</li>
55
+ <li class="hall-loading hall-loading--inline" role="status">Loading…</li>
56
56
  </ol>
57
57
  </nav>
58
58
  </aside>
@@ -52,7 +52,7 @@
52
52
  <section class="scroll" id="standing-scroll" aria-labelledby="standing-h" data-group="overview">
53
53
  <h2 id="standing-h" class="sr-only">About</h2>
54
54
  <div class="profile profile--ident" id="profile-head">
55
- <div class="profile__placeholder">…</div>
55
+ <div class="hall-loading" role="status">Loading…</div>
56
56
  </div>
57
57
  </section>
58
58
 
@@ -63,7 +63,7 @@
63
63
  <section class="scroll" id="numbers-scroll" aria-labelledby="numbers-h" data-group="overview">
64
64
  <h2 id="numbers-h" class="scroll__h">By the numbers</h2>
65
65
  <div id="numbers-body">
66
- <p class="profile__placeholder">Loading…</p>
66
+ <p class="hall-loading" role="status">Loading…</p>
67
67
  </div>
68
68
  </section>
69
69
 
@@ -79,7 +79,7 @@
79
79
  first"). profile-charts.js fills it and re-draws on change. -->
80
80
  <div id="charts-controls"></div>
81
81
  <div class="pcharts" id="charts-grid">
82
- <p class="pchart__note">…</p>
82
+ <p class="hall-loading" role="status">Loading…</p>
83
83
  </div>
84
84
  </section>
85
85
 
@@ -87,7 +87,7 @@
87
87
  <section class="scroll scroll--bare" id="ach-scroll" aria-labelledby="ach-h" data-group="overview">
88
88
  <h2 id="ach-h" class="scroll__h">Achievements</h2>
89
89
  <div class="ach-grid" id="ach-grid">
90
- <div class="profile__placeholder">…</div>
90
+ <div class="hall-loading" role="status">Loading…</div>
91
91
  </div>
92
92
  </section>
93
93
 
@@ -120,7 +120,7 @@
120
120
  </tr>
121
121
  </thead>
122
122
  <tbody>
123
- <tr><td colspan="4">…</td></tr>
123
+ <tr><td colspan="4"><span class="hall-loading" role="status">Loading…</span></td></tr>
124
124
  </tbody>
125
125
  </table>
126
126
  <div id="works-pager"></div>
@@ -27,6 +27,8 @@
27
27
  </div>
28
28
 
29
29
  <main id="hall-main">
30
+ <!-- task 1005043: the page loader, shown until any section below is revealed. -->
31
+ <p class="hall-loading hall-loading--page hall-loading--wait" role="status">Loading…</p>
30
32
  <!-- The sealed state is a panel with a heading, not a bare line on the ground
31
33
  (task 1003469). The page gate is the real wall; this is what a reader who
32
34
  followed a link sees instead of an empty page. -->
@@ -29,7 +29,7 @@
29
29
  <section class="scroll" id="standing-scroll" aria-labelledby="standing-h">
30
30
  <h2 id="standing-h" class="scroll__h">Where you stand</h2>
31
31
  <div class="ranks-standing" id="standing-body">
32
- <div class="profile__placeholder">…</div>
32
+ <div class="hall-loading" role="status">Loading…</div>
33
33
  </div>
34
34
  </section>
35
35
 
@@ -49,7 +49,7 @@
49
49
  <h2 id="ladder-h" class="scroll__h">The ranks, lowest to highest</h2>
50
50
  <p class="scroll__lede">Each rank opens more of the system. Yours and the one above are shown in full; the rest open as you get closer.</p>
51
51
  <ol class="ranks-ladder" id="ladder-body">
52
- <li class="rank-card rank-card--placeholder">…</li>
52
+ <li class="hall-loading" role="status">Loading…</li>
53
53
  </ol>
54
54
  </section>
55
55
 
@@ -57,7 +57,7 @@
57
57
  <section class="scroll" id="rise-scroll" aria-labelledby="rise-h">
58
58
  <h2 id="rise-h" class="scroll__h">How you advance</h2>
59
59
  <div class="ranks-rise" id="rise-body">
60
- <div class="profile__placeholder">…</div>
60
+ <div class="hall-loading" role="status">Loading…</div>
61
61
  </div>
62
62
  </section>
63
63
  </main>
@@ -30,7 +30,7 @@
30
30
 
31
31
  <main id="hall-main">
32
32
  <div id="rm-root">
33
- <div class="profile__placeholder">Loading the roadmap…</div>
33
+ <div class="hall-loading hall-loading--page" role="status">Loading the roadmap…</div>
34
34
  </div>
35
35
  </main>
36
36
 
@@ -39,7 +39,7 @@
39
39
  <div class="roster-roles" id="roster-roles" role="group" aria-label="Show"></div>
40
40
  <div id="roster-filters"></div>
41
41
  <div id="roster-body">
42
- <div class="profile__placeholder">Loading the roster…</div>
42
+ <div class="hall-loading hall-loading--page" role="status">Loading the roster…</div>
43
43
  </div>
44
44
  </section>
45
45
  </main>
@@ -29,6 +29,8 @@
29
29
  </div>
30
30
 
31
31
  <main id="hall-main">
32
+ <!-- task 1005043: the page loader, shown until any section below is revealed. -->
33
+ <p class="hall-loading hall-loading--page hall-loading--wait" role="status">Loading…</p>
32
34
  <!-- Access notice — shown by sessions.js when the viewer is below the
33
35
  floor. The heading and the line are written from the pack's rank
34
36
  label (ADR 0157: metic and up), so the static text never renders. -->
@@ -275,7 +275,7 @@
275
275
  if (asked) return;
276
276
  asked = true;
277
277
  const body = byId('su-body');
278
- if (body) body.innerHTML = '<p class="panel-hint">Checking for a newer version…</p>';
278
+ if (body) body.innerHTML = '<p class="hall-loading hall-loading--inline" role="status">Checking for a newer version…</p>';
279
279
  try {
280
280
  const res = await api.request('GET', `${API}/software-update`);
281
281
  if (res.status === 401) { window.location.assign(`${API}/auth/web/start`); return; }
@@ -276,7 +276,7 @@
276
276
  return `
277
277
  <form class="speciality-offer" data-id="${escapeHtml(String(s.id))}">
278
278
  <h4 class="speciality-create__h">What ${escapeHtml(s.name)} offers</h4>
279
- <div class="speciality-offer__choices">${state.offerChoices || '<p class="prow__hint">Loading this project’s skills…</p>'}</div>
279
+ <div class="speciality-offer__choices">${state.offerChoices || '<p class="hall-loading hall-loading--inline" role="status">Loading this project’s skills…</p>'}</div>
280
280
  <div class="speciality-actions">
281
281
  <button type="submit" class="btn" ${state.offerChoices ? '' : 'disabled'}>Save what it offers</button>
282
282
  </div>
@@ -54,6 +54,8 @@
54
54
  <nav class="section-rail" id="settings-rail" aria-label="Settings sections"></nav>
55
55
 
56
56
  <div class="settings-groups" id="settings-groups" data-active="account">
57
+ <!-- task 1005043: the panel loader, until settings.js has read who is viewing (hideLayout). -->
58
+ <p class="hall-loading hall-loading--page" id="settings-loading" role="status">Loading…</p>
57
59
 
58
60
  <!-- ============ group: account ============ -->
59
61
 
@@ -344,7 +346,7 @@
344
346
  </label>
345
347
  <details id="speciality-create-offer" class="speciality-offer-box">
346
348
  <summary>Skills it offers <small>(optional)</small></summary>
347
- <div id="speciality-create-skills"><p class="prow__hint">Loading this project’s skills…</p></div>
349
+ <div id="speciality-create-skills"><p class="hall-loading hall-loading--inline" role="status">Loading this project’s skills…</p></div>
348
350
  </details>
349
351
  <div class="speciality-actions">
350
352
  <button type="submit" class="btn">Create speciality</button>