@bongos/core 1.24.50 → 1.24.52
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.
- package/.bongos-core.json +104 -89
- package/docs/copy-inventory.md +259 -277
- package/docs/copy-registry.json +461 -634
- package/docs/file-map.md +1 -1
- package/docs/module-api-changelog.md +4 -0
- package/docs/page-inventory.json +35 -2
- package/docs/page-readings.json +518 -547
- package/modules/hall-ui/public/ai-studio.html +1 -0
- package/modules/hall-ui/public/approval-queue.css +3 -11
- package/modules/hall-ui/public/approval-queue.js +13 -20
- package/modules/hall-ui/public/atlas.html +1 -0
- package/modules/hall-ui/public/blockers.html +1 -0
- package/modules/hall-ui/public/board-room.html +1 -0
- package/modules/hall-ui/public/bulk-toolbar.js +5 -1
- package/modules/hall-ui/public/city.html +1 -0
- package/modules/hall-ui/public/collab.html +1 -0
- package/modules/hall-ui/public/commands.html +1 -0
- package/modules/hall-ui/public/controls.css +100 -0
- package/modules/hall-ui/public/copy-desk.css +7 -11
- package/modules/hall-ui/public/copy-desk.html +17 -16
- package/modules/hall-ui/public/copy-desk.js +13 -9
- package/modules/hall-ui/public/deploy.html +1 -0
- package/modules/hall-ui/public/goal-inbox.js +32 -17
- package/modules/hall-ui/public/goal-map.html +1 -0
- package/modules/hall-ui/public/goals-page.js +7 -1
- package/modules/hall-ui/public/goals.html +1 -0
- package/modules/hall-ui/public/government.html +1 -0
- package/modules/hall-ui/public/government.js +10 -2
- package/modules/hall-ui/public/hall-dialog.js +255 -0
- package/modules/hall-ui/public/hall-kit.js +9 -2
- package/modules/hall-ui/public/idea.html +1 -0
- package/modules/hall-ui/public/ideas.html +1 -0
- package/modules/hall-ui/public/index.html +1 -0
- package/modules/hall-ui/public/market-watch-item.html +2 -1
- package/modules/hall-ui/public/market-watch-lib.js +16 -9
- package/modules/hall-ui/public/market-watch-rules.html +1 -0
- package/modules/hall-ui/public/market-watch.css +2 -3
- package/modules/hall-ui/public/market-watch.html +2 -1
- package/modules/hall-ui/public/modules.html +1 -0
- package/modules/hall-ui/public/money.html +1 -0
- package/modules/hall-ui/public/my-agents.html +1 -0
- package/modules/hall-ui/public/oversight.css +3 -33
- package/modules/hall-ui/public/primer.html +1 -0
- package/modules/hall-ui/public/profile.html +1 -0
- package/modules/hall-ui/public/project-settings.html +1 -0
- package/modules/hall-ui/public/roster.html +1 -0
- package/modules/hall-ui/public/settings-ai-keys.js +5 -1
- package/modules/hall-ui/public/settings-passkeys.js +5 -1
- package/modules/hall-ui/public/settings-sessions.js +10 -2
- package/modules/hall-ui/public/settings.html +1 -0
- package/modules/hall-ui/public/settings.js +5 -1
- package/modules/hall-ui/public/street.html +1 -0
- package/modules/hall-ui/public/studio.css +6 -32
- package/modules/hall-ui/public/studio.html +4 -3
- package/modules/hall-ui/public/studio.js +40 -35
- package/modules/hall-ui/public/style.css +2 -8
- package/modules/hall-ui/public/task.html +1 -0
- package/modules/hall-ui/public/task.js +26 -12
- package/modules/hall-ui/public/thinking.html +1 -0
- package/modules/hall-ui/public/tweak-editor.html +1 -0
- package/modules/hall-ui/public/watch.html +1 -0
- package/modules/hall-ui/public/work.html +1 -0
- package/modules/hall-ui/public/work.js +7 -1
- package/modules/status-ui/public/index.html +43 -43
- package/modules/status-ui/public/status.js +26 -27
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +12 -0
- package/src/module-api.js +1 -1
- package/tests/bulk_toolbar.mjs +1 -1
- package/tests/hall_approval_queue.mjs +8 -2
- package/tests/hall_audit.mjs +1 -1
- package/tests/hall_city.mjs +1 -1
- package/tests/hall_collab_world.mjs +9 -6
- package/tests/hall_dialog.mjs +401 -0
- package/tests/hall_error_envelope.mjs +1 -1
- package/tests/hall_oversight_world.mjs +9 -7
- package/tests/hall_record_world.mjs +1 -1
- package/tests/hall_street.mjs +1 -1
- package/tests/hall_studio_home.mjs +1 -1
- package/tests/home_attention_cards.mjs +2 -0
- package/tests/kind_axis_unset.mjs +1 -1
- package/tests/loading_mark.mjs +6 -6
- package/tests/market_watch_pages.mjs +3 -1
- package/tests/status_company_attribution.mjs +1 -1
- package/tests/status_page_wording.mjs +129 -0
|
@@ -90,6 +90,7 @@
|
|
|
90
90
|
<script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
|
|
91
91
|
<script src="/builders/craft-mode.js?v=2026-11-05-goals"></script>
|
|
92
92
|
<script src="/builders/shell.js?v=2026-11-07-brand-mark"></script>
|
|
93
|
+
<script src="/builders/hall-dialog.js"></script>
|
|
93
94
|
<script src="/builders/palette.js" defer></script>
|
|
94
95
|
<script src="/builders/tweak-editor-lib.js?v=2026-09-28-tw23"></script>
|
|
95
96
|
<script src="/builders/studio-lib.js?v=2026-10-09-day"></script>
|
|
@@ -26,7 +26,6 @@
|
|
|
26
26
|
--aq-glass: rgba(255, 255, 255, .075);
|
|
27
27
|
--aq-glass-edge: rgba(255, 255, 255, .18);
|
|
28
28
|
--aq-glass-rim: rgba(255, 255, 255, .22);
|
|
29
|
-
--aq-drop: rgba(0, 0, 0, .55);
|
|
30
29
|
--aq-ink: #ffffff;
|
|
31
30
|
--aq-ink-soft: #c0c0c0;
|
|
32
31
|
--aq-ink-faint: #a8a8a8;
|
|
@@ -44,14 +43,8 @@
|
|
|
44
43
|
--aq-rule: rgba(255, 255, 255, .12);
|
|
45
44
|
--aq-face: var(--font-body, Manrope, "Segoe UI", system-ui, sans-serif);
|
|
46
45
|
--aq-mono: var(--font-mono, "JetBrains Mono", ui-monospace, Consolas, monospace);
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
z-index: var(--z-modal, 160);
|
|
50
|
-
display: flex;
|
|
51
|
-
align-items: center;
|
|
52
|
-
justify-content: center;
|
|
53
|
-
padding: 24px;
|
|
54
|
-
box-sizing: border-box;
|
|
46
|
+
/* the layer, the placement and the gutter are the shared .hall-scrim's
|
|
47
|
+
(controls.css, task 1005085); only the artboard's tint is its own */
|
|
55
48
|
background: var(--aq-scrim);
|
|
56
49
|
color: var(--aq-ink);
|
|
57
50
|
font-family: var(--aq-face);
|
|
@@ -60,7 +53,6 @@ html[data-theme="dark"] .aq-overlay { --aq-scrim: rgba(4, 5, 9, .42); }
|
|
|
60
53
|
@media (prefers-color-scheme: dark) {
|
|
61
54
|
html:not([data-theme]) .aq-overlay { --aq-scrim: rgba(4, 5, 9, .42); }
|
|
62
55
|
}
|
|
63
|
-
.aq-overlay[hidden] { display: none; }
|
|
64
56
|
html.aq-open { overflow: hidden; }
|
|
65
57
|
|
|
66
58
|
/* FITS THE SCREEN (task 1004381). The artboard's 1180 by 820 is a ceiling, never
|
|
@@ -80,7 +72,7 @@ html.aq-open { overflow: hidden; }
|
|
|
80
72
|
border: 1px solid var(--aq-glass-edge);
|
|
81
73
|
backdrop-filter: blur(30px) saturate(160%);
|
|
82
74
|
-webkit-backdrop-filter: blur(30px) saturate(160%);
|
|
83
|
-
box-shadow: inset 0 1px 0 var(--aq-glass-rim),
|
|
75
|
+
box-shadow: inset 0 1px 0 var(--aq-glass-rim), var(--ds-shadow-pop);
|
|
84
76
|
display: flex;
|
|
85
77
|
flex-direction: column;
|
|
86
78
|
gap: 16px;
|
|
@@ -79,11 +79,16 @@
|
|
|
79
79
|
};
|
|
80
80
|
|
|
81
81
|
const scrim = document.createElement('div');
|
|
82
|
-
|
|
82
|
+
// The shared overlay layer (controls.css .hall-scrim, task 1005085); the
|
|
83
|
+
// glass inside is the artboard's own.
|
|
84
|
+
scrim.className = 'hall-scrim aq-overlay';
|
|
83
85
|
scrim.hidden = true;
|
|
84
86
|
scrim.innerHTML = '<div class="aq-dialog" role="dialog" aria-modal="true" aria-labelledby="aq-title" tabindex="-1"></div>';
|
|
85
87
|
root.appendChild(scrim);
|
|
86
88
|
const dialog = scrim.querySelector('.aq-dialog');
|
|
89
|
+
// The hall's one dialog behaviour (hall-dialog.js, task 1005085): Escape, the
|
|
90
|
+
// focus trap, a click on the scrim, the scroll lock and focus back to the opener.
|
|
91
|
+
const modal = window.OTBDialog.bind(scrim, { panel: dialog, lockClass: 'aq-open', initialFocus: () => dialog, onClose: closed });
|
|
87
92
|
|
|
88
93
|
const current = () => state.queue[state.idx] || null;
|
|
89
94
|
|
|
@@ -296,14 +301,11 @@
|
|
|
296
301
|
// `pageId` (optional) lands on that page's card when it is in the queue, so a
|
|
297
302
|
// row elsewhere that says "needs to be reviewed" opens its own card.
|
|
298
303
|
async function open(pageId, { reload = true } = {}) {
|
|
299
|
-
state.opener = document.activeElement;
|
|
300
304
|
state.open = true;
|
|
301
305
|
state.error = null;
|
|
302
306
|
state.noteOpen = false;
|
|
303
|
-
scrim.hidden = false;
|
|
304
|
-
document.documentElement.classList.add('aq-open');
|
|
305
307
|
paint();
|
|
306
|
-
|
|
308
|
+
modal.open();
|
|
307
309
|
if (reload || !state.loaded) await loadQueue();
|
|
308
310
|
if (typeof pageId === 'string') {
|
|
309
311
|
const at = state.queue.findIndex((q) => q.page_id === pageId);
|
|
@@ -315,17 +317,17 @@
|
|
|
315
317
|
if (first) first.focus();
|
|
316
318
|
}
|
|
317
319
|
|
|
318
|
-
function close() {
|
|
320
|
+
function close() { modal.close(); }
|
|
321
|
+
|
|
322
|
+
// Whatever closed it (the close button, Escape, the scrim), the queue settles here.
|
|
323
|
+
function closed() {
|
|
319
324
|
state.open = false;
|
|
320
|
-
scrim.hidden = true;
|
|
321
|
-
document.documentElement.classList.remove('aq-open');
|
|
322
325
|
// A decided page leaves the queue for good; the next open starts fresh.
|
|
323
326
|
if (state.outcome.size) {
|
|
324
327
|
state.queue = state.queue.filter((q) => !state.outcome.has(q.task_id));
|
|
325
328
|
state.outcome.clear();
|
|
326
329
|
state.idx = 0;
|
|
327
330
|
}
|
|
328
|
-
if (state.opener && state.opener.focus) state.opener.focus();
|
|
329
331
|
}
|
|
330
332
|
|
|
331
333
|
// A switch repaints the dialog, so the pressed pill is focused again: a
|
|
@@ -338,7 +340,6 @@
|
|
|
338
340
|
}
|
|
339
341
|
|
|
340
342
|
scrim.addEventListener('click', (ev) => {
|
|
341
|
-
if (ev.target === scrim) return close();
|
|
342
343
|
const t = ev.target.closest('button');
|
|
343
344
|
if (!t || t.disabled) return undefined;
|
|
344
345
|
if (('close' in t.dataset)) return close();
|
|
@@ -353,17 +354,9 @@
|
|
|
353
354
|
return undefined;
|
|
354
355
|
});
|
|
355
356
|
|
|
357
|
+
// Escape and the Tab trap are the shared dialog's (OTBDialog.bind above).
|
|
356
358
|
scrim.addEventListener('keydown', (ev) => {
|
|
357
|
-
if (ev.key === '
|
|
358
|
-
if (ev.key === 'Enter' && ev.target && ev.target.id === 'aq-note') { ev.preventDefault(); decide('sent'); return; }
|
|
359
|
-
if (ev.key !== 'Tab') return;
|
|
360
|
-
// Keep focus inside the dialog while it is open (aria-modal).
|
|
361
|
-
const f = [...dialog.querySelectorAll('button:not([disabled]), input, [tabindex="0"]')];
|
|
362
|
-
if (!f.length) return;
|
|
363
|
-
const first = f[0];
|
|
364
|
-
const last = f[f.length - 1];
|
|
365
|
-
if (ev.shiftKey && document.activeElement === first) { ev.preventDefault(); last.focus(); }
|
|
366
|
-
else if (!ev.shiftKey && document.activeElement === last) { ev.preventDefault(); first.focus(); }
|
|
359
|
+
if (ev.key === 'Enter' && ev.target && ev.target.id === 'aq-note') { ev.preventDefault(); decide('sent'); }
|
|
367
360
|
});
|
|
368
361
|
|
|
369
362
|
scrim.addEventListener('input', (ev) => {
|
|
@@ -93,6 +93,7 @@
|
|
|
93
93
|
<script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
|
|
94
94
|
<script src="/builders/craft-mode.js?v=2026-11-05-goals"></script>
|
|
95
95
|
<script src="/builders/shell.js?v=2026-11-07-brand-mark"></script>
|
|
96
|
+
<script src="/builders/hall-dialog.js"></script>
|
|
96
97
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
97
98
|
<script src="/builders/palette.js" defer></script>
|
|
98
99
|
<script src="/builders/atlas.js?v=2026-09-02-index" defer></script>
|
|
@@ -62,6 +62,7 @@
|
|
|
62
62
|
<script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
|
|
63
63
|
<script src="/builders/craft-mode.js?v=2026-11-05-goals"></script>
|
|
64
64
|
<script src="/builders/shell.js?v=2026-11-07-brand-mark"></script>
|
|
65
|
+
<script src="/builders/hall-dialog.js"></script>
|
|
65
66
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
66
67
|
<script src="/builders/palette.js" defer></script>
|
|
67
68
|
<!-- the branding pack's currency label, loaded BEFORE blockers.js. -->
|
|
@@ -64,6 +64,7 @@
|
|
|
64
64
|
<script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
|
|
65
65
|
<script src="/builders/craft-mode.js?v=2026-11-05-goals"></script>
|
|
66
66
|
<script src="/builders/shell.js?v=2026-11-07-brand-mark"></script>
|
|
67
|
+
<script src="/builders/hall-dialog.js"></script>
|
|
67
68
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
68
69
|
<script src="/builders/palette.js" defer></script>
|
|
69
70
|
<script src="/builders/hall-kit.js"></script>
|
|
@@ -246,8 +246,12 @@
|
|
|
246
246
|
if (!entries.length) return;
|
|
247
247
|
const label = entries.length === 1 ? `#${entries[0][1]}` : `${entries.length} tasks`;
|
|
248
248
|
const pronoun = entries.length === 1 ? 'It returns' : 'They return';
|
|
249
|
-
if (!window.confirm(`Release ${label}? ${pronoun} to the queue and no ${curLabel()} are earned.`)) return;
|
|
250
249
|
const btn = el('release');
|
|
250
|
+
if (!(await window.OTBDialog.confirm({
|
|
251
|
+
title: `Release ${label}?`,
|
|
252
|
+
body: `${pronoun} to the queue and no ${curLabel()} are earned.`,
|
|
253
|
+
confirmLabel: 'Release', danger: true, trigger: btn,
|
|
254
|
+
}))) return;
|
|
251
255
|
if (btn) { btn.disabled = true; btn.textContent = 'Releasing…'; }
|
|
252
256
|
try {
|
|
253
257
|
const out = await claimAction.releaseMany(entries);
|
|
@@ -109,6 +109,7 @@
|
|
|
109
109
|
<script src="/builders/shell-trail.js?v=2026-11-05-numbers" defer></script>
|
|
110
110
|
<script src="/builders/craft-mode.js?v=2026-11-05-goals" defer></script>
|
|
111
111
|
<script src="/builders/shell.js?v=2026-11-07-brand-mark" defer></script>
|
|
112
|
+
<script src="/builders/hall-dialog.js" defer></script>
|
|
112
113
|
<script src="/builders/palette.js" defer></script>
|
|
113
114
|
<script src="/builders/gov-living.js?v=2026-10-09-positions1" defer></script>
|
|
114
115
|
<script src="/builders/gov-feeds.js?v=2026-10-09-living3" defer></script>
|
|
@@ -163,6 +163,7 @@
|
|
|
163
163
|
<script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
|
|
164
164
|
<script src="/builders/craft-mode.js?v=2026-11-05-goals"></script>
|
|
165
165
|
<script src="/builders/shell.js?v=2026-11-07-brand-mark"></script>
|
|
166
|
+
<script src="/builders/hall-dialog.js"></script>
|
|
166
167
|
<script src="/builders/palette.js" defer></script>
|
|
167
168
|
<script src="/builders/collab-lib.js?v=2026-09-24-archive"></script>
|
|
168
169
|
<script src="/builders/collab.js?v=2026-09-24-archive"></script>
|
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
<script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
|
|
56
56
|
<script src="/builders/craft-mode.js?v=2026-11-05-goals"></script>
|
|
57
57
|
<script src="/builders/shell.js?v=2026-11-07-brand-mark"></script>
|
|
58
|
+
<script src="/builders/hall-dialog.js"></script>
|
|
58
59
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
59
60
|
<script src="/builders/palette.js" defer></script>
|
|
60
61
|
<script src="/builders/hall-kit.js"></script>
|
|
@@ -221,3 +221,103 @@ select:disabled, input[type="text"]:disabled, input[type="search"]:disabled, tex
|
|
|
221
221
|
cursor: not-allowed;
|
|
222
222
|
}
|
|
223
223
|
select option { background: var(--bg-card); color: var(--ink); }
|
|
224
|
+
|
|
225
|
+
/* ---------- the danger button ----------
|
|
226
|
+
The one fill a confirm spends on an act that cannot be taken back (delete a
|
|
227
|
+
rank, end every session). The status red, with the card's own ground as its
|
|
228
|
+
text: --danger is measured at 4.5:1 against --bg-card in both modes
|
|
229
|
+
(tests/hall_tokens.mjs), so the pair holds whichever way round it is read. */
|
|
230
|
+
.btn--danger {
|
|
231
|
+
color: var(--bg-card);
|
|
232
|
+
background: var(--danger);
|
|
233
|
+
border-color: transparent;
|
|
234
|
+
}
|
|
235
|
+
.btn--danger:hover:not(:disabled) {
|
|
236
|
+
color: var(--bg-card);
|
|
237
|
+
background: color-mix(in srgb, var(--danger) 86%, var(--ink));
|
|
238
|
+
text-decoration: none;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/* ---------- the dialog (task 1005085) ----------
|
|
242
|
+
THE HALL'S ONE DIALOG. hall-dialog.js builds it (OTBDialog.open / .confirm)
|
|
243
|
+
or binds a page's own <dialog class="hall-dialog"> (OTBDialog.bind). It is
|
|
244
|
+
DESIGN.md's panel lifted over the page: bg-card, one hairline, the panel
|
|
245
|
+
corner, and the one shadow the hall spends, on an element that floats over
|
|
246
|
+
the scrim. A native dialog opens with showModal(), so it sits in the top
|
|
247
|
+
layer; the z-index is the ladder's modal step for any reader that does not.
|
|
248
|
+
.hall-scrim is the same layer for a div overlay (the approval queue's and the
|
|
249
|
+
studio's glass): fixed over the page, centred, darkened by --scrim. */
|
|
250
|
+
.hall-dialog {
|
|
251
|
+
z-index: var(--ds-z-modal);
|
|
252
|
+
box-sizing: border-box;
|
|
253
|
+
width: min(480px, calc(100vw - 2 * var(--ds-space-sm)));
|
|
254
|
+
max-height: calc(100dvh - 2 * var(--ds-space-md));
|
|
255
|
+
overflow-y: auto;
|
|
256
|
+
margin: auto;
|
|
257
|
+
padding: var(--ds-space-md);
|
|
258
|
+
color: var(--ink);
|
|
259
|
+
background: var(--bg-card);
|
|
260
|
+
border: var(--line) solid var(--rule);
|
|
261
|
+
border-radius: var(--ds-radius-panel);
|
|
262
|
+
box-shadow: var(--ds-shadow-pop);
|
|
263
|
+
}
|
|
264
|
+
.hall-dialog--wide { width: min(720px, calc(100vw - 2 * var(--ds-space-sm))); }
|
|
265
|
+
.hall-dialog::backdrop { background: var(--scrim); }
|
|
266
|
+
.hall-scrim {
|
|
267
|
+
position: fixed;
|
|
268
|
+
inset: 0;
|
|
269
|
+
z-index: var(--ds-z-modal);
|
|
270
|
+
display: flex;
|
|
271
|
+
align-items: center;
|
|
272
|
+
justify-content: center;
|
|
273
|
+
box-sizing: border-box;
|
|
274
|
+
padding: var(--ds-space-md);
|
|
275
|
+
background: var(--scrim);
|
|
276
|
+
}
|
|
277
|
+
.hall-scrim[hidden] { display: none; }
|
|
278
|
+
.hall-scrim > .hall-dialog { max-height: 100%; }
|
|
279
|
+
.hall-dialog__head {
|
|
280
|
+
display: flex;
|
|
281
|
+
align-items: flex-start;
|
|
282
|
+
gap: var(--ds-space-xs);
|
|
283
|
+
margin: 0 0 var(--ds-space-xs);
|
|
284
|
+
}
|
|
285
|
+
.hall-dialog__title {
|
|
286
|
+
flex: 1;
|
|
287
|
+
margin: 0;
|
|
288
|
+
font-family: var(--font-display);
|
|
289
|
+
font-size: var(--ds-text-3xl);
|
|
290
|
+
font-weight: 500;
|
|
291
|
+
line-height: 1.25;
|
|
292
|
+
color: var(--ink);
|
|
293
|
+
}
|
|
294
|
+
.hall-dialog__x {
|
|
295
|
+
flex: none;
|
|
296
|
+
min-width: 32px;
|
|
297
|
+
min-height: 32px;
|
|
298
|
+
margin: -4px -6px 0 0;
|
|
299
|
+
padding: 0;
|
|
300
|
+
font: inherit;
|
|
301
|
+
font-size: var(--ds-text-4xl);
|
|
302
|
+
line-height: 1;
|
|
303
|
+
color: var(--ink-soft);
|
|
304
|
+
background: transparent;
|
|
305
|
+
border: 0;
|
|
306
|
+
border-radius: var(--radius-pill);
|
|
307
|
+
cursor: pointer;
|
|
308
|
+
}
|
|
309
|
+
.hall-dialog__x:hover { color: var(--ink); }
|
|
310
|
+
.hall-dialog__body p {
|
|
311
|
+
margin: 0 0 var(--ds-space-xs);
|
|
312
|
+
font-size: var(--ds-text-md);
|
|
313
|
+
line-height: 1.5;
|
|
314
|
+
color: var(--ink-soft);
|
|
315
|
+
}
|
|
316
|
+
.hall-dialog__body p:last-child { margin-bottom: 0; }
|
|
317
|
+
.hall-dialog__actions {
|
|
318
|
+
display: flex;
|
|
319
|
+
flex-wrap: wrap;
|
|
320
|
+
justify-content: flex-end;
|
|
321
|
+
gap: var(--ds-space-xs);
|
|
322
|
+
margin-top: var(--ds-space-md);
|
|
323
|
+
}
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
R02 of goal 1000074), rebuilt on the hall's row archetype by task 1003471:
|
|
3
3
|
the counts are the shell's glass .stat-row, every list is a run of
|
|
4
4
|
oversight.css's .ov-row, the filters and the search are the kit's .filters,
|
|
5
|
-
the
|
|
6
|
-
left here is what only this page has: the quoted
|
|
7
|
-
reason as prose, the places a duplicate lives
|
|
5
|
+
the three dialogs are the hall's one dialog (controls.css .hall-dialog,
|
|
6
|
+
task 1005085). What is left here is what only this page has: the quoted
|
|
7
|
+
string as evidence, the reason as prose, the places a duplicate lives.
|
|
8
8
|
|
|
9
9
|
px and tokens throughout, and state is COLOUR — the pill's verification
|
|
10
10
|
vocabulary — never opacity. Opacity dims the panel behind the text as well
|
|
@@ -67,16 +67,12 @@
|
|
|
67
67
|
.cd-find .filter input[type="search"] { width: 100%; }
|
|
68
68
|
.cd-search-count { margin: 0 0 14px; }
|
|
69
69
|
|
|
70
|
-
/* The three dialogs are the
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
white on black). That is why it was a literal; task 1003495 gave the value a
|
|
74
|
-
home in style.css as --scrim instead, so the sheet keeps none. */
|
|
75
|
-
.cd-dialog { width: min(480px, calc(100vw - 32px)); color: var(--ink); }
|
|
76
|
-
.cd-dialog::backdrop { background: var(--scrim); }
|
|
70
|
+
/* The three dialogs are the hall's one dialog (controls.css .hall-dialog: the
|
|
71
|
+
panel, the scrim, the shadow, task 1005085). What stays is the form inside. */
|
|
72
|
+
.cd-dialog .cd-dialog__target { margin: var(--ds-space-xs) 0 0; font-size: var(--ds-text-sm-plus); line-height: 1.5; color: var(--ink-soft); }
|
|
77
73
|
.cd-dialog .ov-form { margin: 14px 0 0; }
|
|
78
74
|
.cd-dialog textarea { resize: vertical; line-height: 1.5; }
|
|
79
|
-
.
|
|
75
|
+
.cd-dialog .cd-dialog__err { min-height: 18px; margin: 8px 0 0; font-size: 13px; line-height: 1.45; color: var(--danger); }
|
|
80
76
|
|
|
81
77
|
/* The placeholder rule, shown only for a sentence that has holes in it (task
|
|
82
78
|
1003114 / R03). It is a CONSTRAINT, not a footnote — losing a hole is the one
|
|
@@ -77,10 +77,10 @@
|
|
|
77
77
|
<!-- The flag composer. A dialog rather than an inline field because the reason is
|
|
78
78
|
the point: a one-line input invites "typo", and the queue is only worth
|
|
79
79
|
reading if the reasons are. A native <dialog> (its own focus trap and
|
|
80
|
-
Escape) dressed as the
|
|
81
|
-
<dialog id="cd-dialog" class="
|
|
80
|
+
Escape) dressed as the hall's one dialog (controls.css .hall-dialog, task 1005085). -->
|
|
81
|
+
<dialog id="cd-dialog" class="hall-dialog cd-dialog" aria-labelledby="cd-dialog-h">
|
|
82
82
|
<form method="dialog" id="cd-form">
|
|
83
|
-
<h3 class="
|
|
83
|
+
<h3 class="hall-dialog__title" id="cd-dialog-h">Flag this copy</h3>
|
|
84
84
|
<p class="cd-dialog__target" id="cd-dialog-target"></p>
|
|
85
85
|
<div class="ov-form">
|
|
86
86
|
<div class="ov-field ov-field--wide">
|
|
@@ -103,17 +103,17 @@
|
|
|
103
103
|
<p class="ov-form__why">The artist reads this instead of guessing. A pointer with no judgement costs them a look and tells them nothing.</p>
|
|
104
104
|
</div>
|
|
105
105
|
<p class="cd-dialog__err" id="cd-dialog-err" role="alert"></p>
|
|
106
|
-
<div class="
|
|
107
|
-
<button type="button" class="btn
|
|
108
|
-
<button type="button" class="btn
|
|
106
|
+
<div class="hall-dialog__actions">
|
|
107
|
+
<button type="button" class="btn btn--ghost" id="cd-cancel">Cancel</button>
|
|
108
|
+
<button type="button" class="btn" id="cd-submit">File the flag</button>
|
|
109
109
|
</div>
|
|
110
110
|
</form>
|
|
111
111
|
</dialog>
|
|
112
112
|
|
|
113
113
|
<!-- Closing a flag asks for a note for the same reason opening one does. -->
|
|
114
|
-
<dialog id="cd-close-dialog" class="
|
|
114
|
+
<dialog id="cd-close-dialog" class="hall-dialog cd-dialog" aria-labelledby="cd-close-h">
|
|
115
115
|
<form method="dialog" id="cd-close-form">
|
|
116
|
-
<h3 class="
|
|
116
|
+
<h3 class="hall-dialog__title" id="cd-close-h">Close this flag</h3>
|
|
117
117
|
<p class="cd-dialog__target" id="cd-close-target"></p>
|
|
118
118
|
<div class="ov-form">
|
|
119
119
|
<div class="ov-field ov-field--wide">
|
|
@@ -135,9 +135,9 @@
|
|
|
135
135
|
<p class="ov-form__why">The next person to notice this sentence reads your note instead of re-litigating it.</p>
|
|
136
136
|
</div>
|
|
137
137
|
<p class="cd-dialog__err" id="cd-close-err" role="alert"></p>
|
|
138
|
-
<div class="
|
|
139
|
-
<button type="button" class="btn
|
|
140
|
-
<button type="button" class="btn
|
|
138
|
+
<div class="hall-dialog__actions">
|
|
139
|
+
<button type="button" class="btn btn--ghost" id="cd-close-cancel">Cancel</button>
|
|
140
|
+
<button type="button" class="btn" id="cd-close-submit">Close it</button>
|
|
141
141
|
</div>
|
|
142
142
|
</form>
|
|
143
143
|
</dialog>
|
|
@@ -147,9 +147,9 @@
|
|
|
147
147
|
wrong, a proposal says this is what it should say instead, and one of them
|
|
148
148
|
creates work on the board. The textarea opens PREFILLED with the current
|
|
149
149
|
wording — an artist edits a sentence, they do not retype it from memory. -->
|
|
150
|
-
<dialog id="cd-propose-dialog" class="
|
|
150
|
+
<dialog id="cd-propose-dialog" class="hall-dialog cd-dialog" aria-labelledby="cd-propose-h">
|
|
151
151
|
<form method="dialog" id="cd-propose-form">
|
|
152
|
-
<h3 class="
|
|
152
|
+
<h3 class="hall-dialog__title" id="cd-propose-h">Propose new wording</h3>
|
|
153
153
|
<p class="cd-dialog__target" id="cd-propose-target"></p>
|
|
154
154
|
<div class="ov-form">
|
|
155
155
|
<div class="ov-field ov-field--wide">
|
|
@@ -168,9 +168,9 @@
|
|
|
168
168
|
<p class="ov-form__why">Nothing changes yet. This files a task carrying your wording; whoever claims it lands the diff, and it ships graded like every other change.</p>
|
|
169
169
|
</div>
|
|
170
170
|
<p class="cd-dialog__err" id="cd-propose-err" role="alert"></p>
|
|
171
|
-
<div class="
|
|
172
|
-
<button type="button" class="btn
|
|
173
|
-
<button type="button" class="btn
|
|
171
|
+
<div class="hall-dialog__actions">
|
|
172
|
+
<button type="button" class="btn btn--ghost" id="cd-propose-cancel">Cancel</button>
|
|
173
|
+
<button type="button" class="btn" id="cd-propose-submit">File the change</button>
|
|
174
174
|
</div>
|
|
175
175
|
</form>
|
|
176
176
|
</dialog>
|
|
@@ -181,6 +181,7 @@
|
|
|
181
181
|
<script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
|
|
182
182
|
<script src="/builders/craft-mode.js?v=2026-11-05-goals"></script>
|
|
183
183
|
<script src="/builders/shell.js?v=2026-11-07-brand-mark"></script>
|
|
184
|
+
<script src="/builders/hall-dialog.js"></script>
|
|
184
185
|
<script src="/builders/palette.js" defer></script>
|
|
185
186
|
<script src="/builders/hall-kit.js"></script>
|
|
186
187
|
<script src="/builders/copy-desk.js?v=2026-09-01-redesign"></script>
|
|
@@ -354,6 +354,10 @@
|
|
|
354
354
|
// the composer
|
|
355
355
|
// ---------------------------------------------------------------------------
|
|
356
356
|
|
|
357
|
+
// The three dialogs are the hall's one dialog (hall-dialog.js, task 1005085):
|
|
358
|
+
// the shared Escape, focus trap, scrim click and focus return.
|
|
359
|
+
const dialog = (sel) => window.OTBDialog.bind($(sel));
|
|
360
|
+
|
|
357
361
|
function openComposer(t) {
|
|
358
362
|
target = t;
|
|
359
363
|
$('#cd-dialog-target').innerHTML = t.string_id
|
|
@@ -361,7 +365,7 @@
|
|
|
361
365
|
: `${pill('', 'whole surface')} <span class="ov-key ov-key--faint">${escapeHtml(t.surface)}</span>`;
|
|
362
366
|
$('#cd-reason').value = '';
|
|
363
367
|
$('#cd-dialog-err').textContent = '';
|
|
364
|
-
|
|
368
|
+
dialog('#cd-dialog').open();
|
|
365
369
|
}
|
|
366
370
|
|
|
367
371
|
async function submitFlag() {
|
|
@@ -387,7 +391,7 @@
|
|
|
387
391
|
$('#cd-dialog-err').textContent = d.what_this_means || d.why || err.message || 'Could not file the flag.';
|
|
388
392
|
return;
|
|
389
393
|
}
|
|
390
|
-
|
|
394
|
+
dialog('#cd-dialog').close();
|
|
391
395
|
toast('Flagged. It is in the queue.');
|
|
392
396
|
await loadQueue();
|
|
393
397
|
if ($('#cd-search').value.trim()) await runSearch();
|
|
@@ -423,7 +427,7 @@
|
|
|
423
427
|
+ `Keep all ${n} — move them if the new sentence needs them elsewhere, but do not remove one: `
|
|
424
428
|
+ 'the values come from the code, and dropping one is a code change.';
|
|
425
429
|
}
|
|
426
|
-
|
|
430
|
+
dialog('#cd-propose-dialog').open();
|
|
427
431
|
}
|
|
428
432
|
|
|
429
433
|
async function submitProposal() {
|
|
@@ -463,7 +467,7 @@
|
|
|
463
467
|
err.textContent = d.what_this_means || d.why || e.message || 'Could not file the change.';
|
|
464
468
|
return;
|
|
465
469
|
}
|
|
466
|
-
|
|
470
|
+
dialog('#cd-propose-dialog').close();
|
|
467
471
|
const task = (res.data && res.data.task) || {};
|
|
468
472
|
toast(res.data && res.data.created === false
|
|
469
473
|
? `Already filed — task #${task.id} carries this exact change.`
|
|
@@ -486,7 +490,7 @@
|
|
|
486
490
|
$('#cd-close-note').value = '';
|
|
487
491
|
$('#cd-close-task').value = '';
|
|
488
492
|
$('#cd-close-err').textContent = '';
|
|
489
|
-
|
|
493
|
+
dialog('#cd-close-dialog').open();
|
|
490
494
|
}
|
|
491
495
|
|
|
492
496
|
async function submitClose() {
|
|
@@ -506,7 +510,7 @@
|
|
|
506
510
|
$('#cd-close-err').textContent = d.what_this_means || d.why || err.message || 'Could not close the flag.';
|
|
507
511
|
return;
|
|
508
512
|
}
|
|
509
|
-
|
|
513
|
+
dialog('#cd-close-dialog').close();
|
|
510
514
|
toast('Closed.');
|
|
511
515
|
await loadQueue();
|
|
512
516
|
}
|
|
@@ -560,11 +564,11 @@
|
|
|
560
564
|
if (closeBtn) openCloser(closeBtn.dataset.flag);
|
|
561
565
|
});
|
|
562
566
|
|
|
563
|
-
$('#cd-cancel').addEventListener('click', () =>
|
|
567
|
+
$('#cd-cancel').addEventListener('click', () => dialog('#cd-dialog').close());
|
|
564
568
|
$('#cd-submit').addEventListener('click', submitFlag);
|
|
565
|
-
$('#cd-propose-cancel').addEventListener('click', () =>
|
|
569
|
+
$('#cd-propose-cancel').addEventListener('click', () => dialog('#cd-propose-dialog').close());
|
|
566
570
|
$('#cd-propose-submit').addEventListener('click', submitProposal);
|
|
567
|
-
$('#cd-close-cancel').addEventListener('click', () =>
|
|
571
|
+
$('#cd-close-cancel').addEventListener('click', () => dialog('#cd-close-dialog').close());
|
|
568
572
|
$('#cd-close-submit').addEventListener('click', submitClose);
|
|
569
573
|
|
|
570
574
|
(async () => {
|
|
@@ -82,6 +82,7 @@
|
|
|
82
82
|
<script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
|
|
83
83
|
<script src="/builders/craft-mode.js?v=2026-11-05-goals"></script>
|
|
84
84
|
<script src="/builders/shell.js?v=2026-11-07-brand-mark"></script>
|
|
85
|
+
<script src="/builders/hall-dialog.js"></script>
|
|
85
86
|
<script src="/builders/palette.js" defer></script>
|
|
86
87
|
<script src="/builders/hall-kit.js"></script>
|
|
87
88
|
<!-- the shared ask card the move is drawn with (task 1004829) -->
|
|
@@ -583,10 +583,10 @@
|
|
|
583
583
|
// The slices still render into their divs below (kept off-screen in
|
|
584
584
|
// #attention-slices), and refresh() rebuilds the cards from what they hold.
|
|
585
585
|
'<div class="attn-cards" id="attention-cards"></div>' +
|
|
586
|
-
'<dialog class="
|
|
587
|
-
'<div class="
|
|
588
|
-
'<button type="button" class="
|
|
589
|
-
'<div class="attn-dialog__body" id="attention-dialog-body"></div>' +
|
|
586
|
+
'<dialog class="hall-dialog hall-dialog--wide" id="attention-dialog" aria-labelledby="attention-dialog-h">' +
|
|
587
|
+
'<div class="hall-dialog__head"><h3 class="hall-dialog__title" id="attention-dialog-h"></h3>' +
|
|
588
|
+
'<button type="button" class="hall-dialog__x" id="attention-dialog-x" data-dialog-close aria-label="Close">×</button></div>' +
|
|
589
|
+
'<div class="hall-dialog__body attn-dialog__body" id="attention-dialog-body"></div>' +
|
|
590
590
|
'</dialog>' +
|
|
591
591
|
'<div id="attention-slices" hidden>' +
|
|
592
592
|
// task 1003464: the system's own notices — rebase owed, an input the
|
|
@@ -692,36 +692,51 @@
|
|
|
692
692
|
cards.innerHTML = html.join('');
|
|
693
693
|
}
|
|
694
694
|
|
|
695
|
-
|
|
696
|
-
|
|
695
|
+
// The window is the hall's one dialog (hall-dialog.js, task 1005085): the
|
|
696
|
+
// shared panel, scrim, Escape, focus trap and focus return. Closing it by any
|
|
697
|
+
// road (the mark, Escape, the scrim) moves the slice back and redraws the cards.
|
|
698
|
+
let lastCard = null;
|
|
699
|
+
function windowHandle() {
|
|
700
|
+
const dlg = host && host.querySelector('#attention-dialog');
|
|
701
|
+
if (!dlg) return null;
|
|
702
|
+
return window.OTBDialog.bind(dlg, {
|
|
703
|
+
onClose: restoreSlice,
|
|
704
|
+
// the cards were redrawn, so the opener is gone: focus its successor
|
|
705
|
+
returnFocus: (op) => (op && op.isConnected ? op
|
|
706
|
+
: (lastCard && host.querySelector(`[data-attn-open="${CSS.escape(lastCard)}"]`)) || host.querySelector('.attn-card')),
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
function openCard(id, trigger) {
|
|
711
|
+
const h = windowHandle();
|
|
697
712
|
const div = host.querySelector(`#attention-slices > #${CSS.escape(id)}`);
|
|
698
|
-
if (!
|
|
713
|
+
if (!h || !div) return;
|
|
699
714
|
host.querySelector('#attention-dialog-h').textContent = sliceFacts(div).title;
|
|
700
715
|
host.querySelector('#attention-dialog-body').appendChild(div);
|
|
701
716
|
openSlice = div;
|
|
702
|
-
|
|
717
|
+
lastCard = id;
|
|
718
|
+
h.open(trigger);
|
|
703
719
|
}
|
|
704
720
|
|
|
705
|
-
function
|
|
706
|
-
const dlg = host && host.querySelector('#attention-dialog');
|
|
721
|
+
function restoreSlice() {
|
|
707
722
|
if (openSlice) {
|
|
708
723
|
host.querySelector('#attention-slices').appendChild(openSlice);
|
|
709
724
|
openSlice = null;
|
|
710
725
|
}
|
|
711
|
-
if (dlg && dlg.open && typeof dlg.close === 'function') dlg.close();
|
|
712
726
|
renderCards();
|
|
713
727
|
}
|
|
714
728
|
|
|
729
|
+
function closeCard() {
|
|
730
|
+
const h = windowHandle();
|
|
731
|
+
if (h && h.isOpen()) h.close();
|
|
732
|
+
else restoreSlice();
|
|
733
|
+
}
|
|
734
|
+
|
|
715
735
|
function wireCards() {
|
|
716
736
|
host.addEventListener('click', (e) => {
|
|
717
737
|
const card = e.target.closest('[data-attn-open]');
|
|
718
|
-
if (card)
|
|
719
|
-
if (e.target.closest('#attention-dialog-x')) { closeCard(); return; }
|
|
720
|
-
// a click on the backdrop lands on the <dialog> itself
|
|
721
|
-
if (e.target.id === 'attention-dialog') closeCard();
|
|
738
|
+
if (card) openCard(card.getAttribute('data-attn-open'), card);
|
|
722
739
|
});
|
|
723
|
-
const dlg = host.querySelector('#attention-dialog');
|
|
724
|
-
if (dlg) dlg.addEventListener('close', () => { if (openSlice) closeCard(); });
|
|
725
740
|
}
|
|
726
741
|
|
|
727
742
|
// The card's shared visibility contract: any slice renderer calls refresh()
|
|
@@ -141,6 +141,7 @@
|
|
|
141
141
|
<script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
|
|
142
142
|
<script src="/builders/craft-mode.js?v=2026-11-05-goals"></script>
|
|
143
143
|
<script src="/builders/shell.js?v=2026-11-07-brand-mark"></script>
|
|
144
|
+
<script src="/builders/hall-dialog.js"></script>
|
|
144
145
|
<script src="/builders/palette.js" defer></script>
|
|
145
146
|
|
|
146
147
|
<script src="/builders/idea-objects.js?v=2026-09-27-split"></script>
|
|
@@ -540,8 +540,14 @@
|
|
|
540
540
|
async function doGoalRelease(claimId, taskId, btn) {
|
|
541
541
|
const key = `release:${claimId}`;
|
|
542
542
|
if (pendingClaims.has(key)) return;
|
|
543
|
-
|
|
543
|
+
// Held while the confirm is open too, so a second click cannot stack a second dialog.
|
|
544
544
|
pendingClaims.add(key);
|
|
545
|
+
const yes = await window.OTBDialog.confirm({
|
|
546
|
+
title: `Release your claim on #${taskId}?`,
|
|
547
|
+
body: `It returns to the queue and no ${curLabel()} are earned.`,
|
|
548
|
+
confirmLabel: 'Release', danger: true, trigger: btn,
|
|
549
|
+
});
|
|
550
|
+
if (!yes) { pendingClaims.delete(key); return; }
|
|
545
551
|
if (btn) { btn.disabled = true; btn.textContent = 'Releasing…'; }
|
|
546
552
|
try {
|
|
547
553
|
const out = await claimAction.release(claimId, taskId);
|
|
@@ -254,6 +254,7 @@
|
|
|
254
254
|
<script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
|
|
255
255
|
<script src="/builders/craft-mode.js?v=2026-11-05-goals"></script>
|
|
256
256
|
<script src="/builders/shell.js?v=2026-11-07-brand-mark"></script>
|
|
257
|
+
<script src="/builders/hall-dialog.js"></script>
|
|
257
258
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
258
259
|
<script src="/builders/palette.js" defer></script>
|
|
259
260
|
<!-- task 1004727: the ONE karma vote control every task/idea list renders -->
|
|
@@ -158,6 +158,7 @@
|
|
|
158
158
|
<script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
|
|
159
159
|
<script src="/builders/craft-mode.js?v=2026-11-05-goals"></script>
|
|
160
160
|
<script src="/builders/shell.js?v=2026-11-07-brand-mark"></script>
|
|
161
|
+
<script src="/builders/hall-dialog.js"></script>
|
|
161
162
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
162
163
|
<script src="/builders/palette.js" defer></script>
|
|
163
164
|
<script src="/builders/hall-kit.js"></script>
|