@bongos/core 1.19.445 → 1.19.447

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 (45) hide show
  1. package/.bongos-core.json +67 -47
  2. package/docs/copy-inventory.md +354 -352
  3. package/docs/copy-registry.json +406 -388
  4. package/docs/module-api-changelog.md +4 -0
  5. package/modules/hall-ui/public/atlas.html +1 -2
  6. package/modules/hall-ui/public/collab.html +1 -2
  7. package/modules/hall-ui/public/copy-desk.css +11 -11
  8. package/modules/hall-ui/public/copy-desk.html +1 -2
  9. package/modules/hall-ui/public/diagrams.html +1 -2
  10. package/modules/hall-ui/public/drachmae.html +1 -2
  11. package/modules/hall-ui/public/gate.html +1 -2
  12. package/modules/hall-ui/public/goals.html +1 -2
  13. package/modules/hall-ui/public/government.html +1 -2
  14. package/modules/hall-ui/public/harbor.html +1 -2
  15. package/modules/hall-ui/public/idea.html +1 -2
  16. package/modules/hall-ui/public/ideas.css +6 -8
  17. package/modules/hall-ui/public/ideas.html +1 -2
  18. package/modules/hall-ui/public/index.html +3 -4
  19. package/modules/hall-ui/public/index.states.json +17 -0
  20. package/modules/hall-ui/public/modules.html +1 -2
  21. package/modules/hall-ui/public/my-projects.html +1 -2
  22. package/modules/hall-ui/public/not-ready.html +1 -2
  23. package/modules/hall-ui/public/pair.html +1 -2
  24. package/modules/hall-ui/public/people.html +1 -2
  25. package/modules/hall-ui/public/primer.html +1 -2
  26. package/modules/hall-ui/public/profile.html +1 -2
  27. package/modules/hall-ui/public/ranks.html +1 -2
  28. package/modules/hall-ui/public/roadmap.html +1 -2
  29. package/modules/hall-ui/public/scouting.html +1 -2
  30. package/modules/hall-ui/public/sessions.html +1 -2
  31. package/modules/hall-ui/public/settings.html +1 -2
  32. package/modules/hall-ui/public/shell.js +35 -2
  33. package/modules/hall-ui/public/style.css +1023 -455
  34. package/modules/hall-ui/public/task.html +1 -2
  35. package/modules/hall-ui/public/watch.css +1 -1
  36. package/modules/hall-ui/public/watch.html +1 -2
  37. package/modules/hall-ui/public/work.css +226 -100
  38. package/modules/hall-ui/public/work.html +15 -4
  39. package/modules/hall-ui/public/work.js +1 -1
  40. package/modules/hall-ui/public/work.states.json +19 -0
  41. package/package-lock.json +2 -2
  42. package/package.json +1 -1
  43. package/src/module-api.js +1 -1
  44. package/tests/hall_board_world.mjs +153 -0
  45. package/tests/hall_tokens.mjs +371 -0
@@ -8,7 +8,6 @@
8
8
  <link rel="icon" href="data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><text x='16' y='24' font-size='24' text-anchor='middle' font-family='sans-serif'>⌂</text></svg>">
9
9
  <link rel="preconnect" href="https://fonts.googleapis.com">
10
10
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
11
- <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
12
11
  <link rel="stylesheet" href="/builders/style.css?v=2026-07-03-roadmap1">
13
12
  <style>
14
13
  /* Page-local styles for the task-detail page (task 751) — the full-page
@@ -56,7 +55,7 @@
56
55
  <p class="page-head__sub" id="task-sub">Loading task…</p>
57
56
  </div>
58
57
 
59
- <main>
58
+ <main id="hall-main">
60
59
  <section class="scroll" id="task-scroll" aria-labelledby="task-h">
61
60
  <div id="task-body">
62
61
  <p class="deeplink-card__title" id="task-h">Loading…</p>
@@ -185,7 +185,7 @@ table.watch tr:hover td { background: var(--surface-2); }
185
185
 
186
186
  /* Invite by GitHub username (task 1003044) — the Access requests section's own
187
187
  form: the way in on an invite-only project, a shortcut on an apply one. */
188
- .watch-invite { margin: 0 0 14px; padding: 12px 14px; border: 1px solid var(--line, #e5e0d6); border-radius: 10px; }
188
+ .watch-invite { margin: 0 0 14px; padding: 12px 14px; border: 1px solid var(--rule-soft); border-radius: 10px; }
189
189
  .watch-invite__label { display: block; font-weight: 600; margin-bottom: 6px; }
190
190
  .watch-invite__row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
191
191
  .watch-invite__row input[type="text"] { flex: 1 1 200px; min-width: 0; }
@@ -8,7 +8,6 @@
8
8
  <link rel="icon" href="data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><text x='16' y='24' font-size='24' text-anchor='middle' font-family='sans-serif'>⌂</text></svg>">
9
9
  <link rel="preconnect" href="https://fonts.googleapis.com">
10
10
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
11
- <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
12
11
  <link rel="stylesheet" href="/builders/style.css?v=2026-07-02-shell1">
13
12
  <!-- Page-local styles (task 2173) — extracted from the old inline <style>
14
13
  block per the hall placement rules; the attention tiles + tabs come from
@@ -25,7 +24,7 @@
25
24
  <div class="app-content">
26
25
  <div class="page-head"><p class="page-head__sub" id="watch-sub">Loading…</p></div>
27
26
 
28
- <main>
27
+ <main id="hall-main">
29
28
  <!-- Restricted notice — shown by watch.js when the viewer is not an Archon. -->
30
29
  <section class="scroll" id="sealed-scroll" aria-labelledby="sealed-h" hidden>
31
30
  <h2 id="sealed-h" class="scroll__h">Archons only</h2>
@@ -1,128 +1,182 @@
1
1
  /* work.css — page-local styles for the Work Board (task 2170; extracted from
2
2
  work.html's old inline <style> per the hall placement rules). Only what the
3
- shared kit doesn't carry lives here: in-flight actions, claimable task
4
- cards (dense 2-line layout), history list, bulk toolbar. Shared pieces —
5
- .pager--paged, .count-pill, .kit-tabs, .filters overflow — are in
6
- style.css. Everything derives from the shared design tokens so instance
7
- packs reskin this page along with the rest of the hall. */
3
+ shared kit doesn't carry lives here: in-flight actions, the claimable card's
4
+ own bits, history list, bulk toolbar. Shared pieces — .pager--paged,
5
+ .count-pill, .kit-tabs, .filters overflow — are in style.css.
6
+
7
+ RE-SKINNED INTO THE CHROME WORLD by task 1003304 (goal 1000081), v3 "the
8
+ glass hall". Every compat alias this sheet used to spend is retired: --surface
9
+ → --bg-card, --surface-2 → --glass, --border → --rule-soft, --border-strong →
10
+ --rule, --accent-weak → --accent-tint, --accent-text → --accent-ink. The three
11
+ rgba(255,255,255,…) literals on the bulk toolbar are gone with the inverted
12
+ surface that needed them. What is NOT retired is the status vocabulary
13
+ (--ok / --warn / --danger and their -weak fills): the board renders
14
+ verification state, which DESIGN.md §Reuse names as the one sanctioned
15
+ exception to the Fifteen Rule.
16
+
17
+ goals.html LOADS THIS SHEET TOO — a change here lands on both pages. */
18
+
19
+ /* The board's page head, in v3's LABEL voice: the display face is saved for
20
+ section headings, so the page's own name is quiet (mock: .greeting). It
21
+ overrides the pre-shell .page-head h1 compat rule in style.css, which is
22
+ 22px/650 and belongs to the pages nobody has re-skinned yet. */
23
+ .page-head--board .page-head__h {
24
+ margin: 0 0 6px;
25
+ font-family: var(--label-face);
26
+ font-size: 14px;
27
+ font-weight: 400;
28
+ letter-spacing: var(--label-space);
29
+ text-transform: var(--label-case);
30
+ color: var(--ink);
31
+ text-shadow: var(--type-halo);
32
+ }
33
+ .page-head--board .page-head__sub { font-size: 14px; max-width: var(--measure); }
8
34
 
9
35
  .kbd {
10
36
  display: inline-block;
11
37
  padding: 0 6px;
12
- border: 1px solid var(--border-strong);
38
+ border: var(--line) solid var(--rule);
13
39
  border-radius: 5px;
14
- background: var(--surface-2);
40
+ background: var(--glass);
41
+ font-family: var(--font-mono);
15
42
  font-size: 0.85em;
16
- font-weight: 600;
17
43
  color: var(--ink-soft);
18
44
  }
19
45
 
20
- .wip-builder { color: var(--ink); font-weight: 600; }
46
+ .wip-builder { color: var(--ink); font-weight: 500; }
21
47
  .wip-builder small { color: var(--ink-soft); font-weight: 400; }
22
48
 
23
- /* Filtered-count line under the filter bar. */
49
+ /* Filtered-count line under the filter bar — the label voice, with the number
50
+ itself stepping up to ink so the count reads before the words. */
24
51
  .claim-count-line {
25
- margin: 0 0 10px;
26
- font-size: 12.5px;
52
+ margin: 0 0 12px;
53
+ font-family: var(--label-face);
54
+ font-size: var(--label-size);
55
+ letter-spacing: var(--label-space);
56
+ text-transform: var(--label-case);
27
57
  color: var(--ink-faint);
28
58
  }
29
59
 
30
- /* ---- #616 / task 2170: claim/release actions + the dense task card ---- */
31
-
32
- /* task 2170 (owner call 2026-07-10): denser 2-line cards. The card keeps its
33
- grid but tightens padding and type, actions go horizontal, and the touches
34
- path-dump becomes a "✎ N files" chip with the full list in the tooltip. */
35
- .task { padding: 8px 12px; gap: 2px 12px; }
36
- .task__title { font-size: 13px; line-height: 1.35; }
37
- .task__meta { margin-top: 1px; row-gap: 2px; }
60
+ /* ---- #616 / task 2170 / task 1003304: claim + copy on the claimable card ----
61
+ The card's geometry, tags, credits figure, checkbox and copy button all live
62
+ in style.css's work-board section now (they are the re-skin). What stays here
63
+ is the page-local behaviour: the primary door, the two meta chips, and the
64
+ fact that the whole card is a selection target. */
38
65
 
39
- .task__actions {
40
- display: flex;
41
- align-items: center;
42
- gap: 6px;
43
- }
44
- /* Claim is the primary action — filled accent so it reads above Copy. */
66
+ /* The page's one primary action, and the only accent FILL on the board.
67
+ --accent-on is the dark ink that goes on the salmon: white on it fails AA and
68
+ DESIGN.md bans it outright, which is what the old `color: #fff` was. */
45
69
  .task__claim {
70
+ display: inline-flex;
71
+ align-items: center;
72
+ justify-content: center;
73
+ min-height: 34px;
74
+ min-width: 74px;
75
+ padding: 0 16px;
46
76
  background: var(--accent);
47
- border: 1px solid var(--accent-deep);
48
- color: #fff;
49
- border-radius: var(--radius-sm);
50
- font-size: 12.5px;
51
- font-weight: 600;
52
- padding: 5px 14px;
77
+ border: 0;
78
+ color: var(--accent-on);
79
+ border-radius: var(--radius-pill);
80
+ font-size: 13.5px;
81
+ font-weight: 500;
82
+ text-transform: lowercase;
53
83
  cursor: pointer;
54
84
  white-space: nowrap;
55
85
  transition: background 150ms, opacity 150ms;
56
86
  }
57
- .task__claim:hover { background: var(--accent-deep); }
58
- .task__claim:disabled { opacity: 0.55; cursor: default; }
87
+ .task__claim:hover:not(:disabled) { background: var(--accent-lift); color: var(--accent-on); }
88
+ .task__claim:disabled { background: var(--glass); color: var(--ink-faint); cursor: default; }
59
89
 
60
- /* Files a claimable task is responsible for — a compact count chip in the
61
- meta row; the full path list rides the tooltip (task 2170 density pass). */
90
+ /* Files a claimable task is responsible for — a compact count chip in the meta
91
+ row; the full path list rides the tooltip (task 2170 density pass). The mono
92
+ fact voice: this is a number the ledger produced. */
62
93
  .task__touches {
94
+ font-family: var(--font-mono);
95
+ font-size: 11.5px;
96
+ font-variant-numeric: tabular-nums;
63
97
  color: var(--ink-faint);
64
- font-size: 12px;
65
98
  white-space: nowrap;
66
99
  cursor: help;
67
100
  }
68
101
 
69
102
  /* How old the task is (task 1002955, OTBKit.ageChipHtml). Quiet by default —
70
103
  it's orientation, not a call to act — but a task past the stale threshold
71
- steps up from faint to soft+bold so a queue that has been sitting reads at a
72
- glance instead of needing the API. The exact date is on the tooltip, hence
73
- `cursor: help`. Deliberately NOT --warn: that token is a dark amber paired
74
- with --warn-weak behind it, and as bare text it loses contrast on the dark
75
- theme's card. --ink-soft steps up legibly in both. */
104
+ steps up from faint to soft so a queue that has been sitting reads at a
105
+ glance. The exact date is on the tooltip, hence `cursor: help`. Deliberately
106
+ NOT --warn: that token is the verification vocabulary and as bare text on the
107
+ dark card it loses contrast. --ink-soft steps up legibly in both modes. */
76
108
  .task__age {
109
+ font-family: var(--font-mono);
110
+ font-size: 11.5px;
111
+ font-variant-numeric: tabular-nums;
77
112
  color: var(--ink-faint);
78
- font-size: 12px;
79
113
  white-space: nowrap;
80
114
  cursor: help;
81
115
  }
82
- .task__age--stale { color: var(--ink-soft); font-weight: 600; }
116
+ .task__age--stale { color: var(--ink-soft); }
83
117
 
118
+ /* The three tag variants that carry meaning beyond "a fact". Each keeps the
119
+ outlined shape style.css gives .task__tag and only changes what it says. */
84
120
  .task__tag--newcomer {
85
121
  background: var(--ok-weak);
86
122
  color: var(--ok);
87
123
  border-color: color-mix(in srgb, var(--ok) 30%, transparent);
88
124
  }
89
125
  .task__tag--mine {
90
- background: var(--accent-weak);
91
- color: var(--accent-text);
126
+ background: var(--accent-tint);
127
+ color: var(--accent-ink);
92
128
  border-color: color-mix(in srgb, var(--accent) 35%, transparent);
93
129
  }
94
130
  /* task 1498 / ADR 0084: per-task rank floor. Outlined + emphasized (not a
95
- filled tag) so a gated task reads as "authority required", distinct from
96
- the filled newcomer tag. */
131
+ filled tag) so a gated task reads as "authority required", distinct from the
132
+ filled newcomer tag. --warn is the verification vocabulary, kept on purpose. */
97
133
  .task__tag--rank {
98
134
  background: transparent;
99
135
  color: var(--warn);
100
136
  border-color: color-mix(in srgb, var(--warn) 45%, transparent);
101
- font-weight: 600;
102
- letter-spacing: 0.02em;
103
137
  }
104
- /* task 1752: the open (no floor) state — muted/neutral so "Any rank" reads as
105
- "open to all", not as a warning like the gated --rank tag above. */
138
+ /* task 1752: the open (no floor) state — muted so "Any rank" reads as "open to
139
+ all", not as a warning like the gated --rank tag above. */
106
140
  .task__tag--rank-open {
107
141
  background: transparent;
108
142
  color: var(--ink-faint);
109
- border-color: var(--border);
143
+ border-color: var(--rule-soft);
110
144
  }
111
145
  /* task 1753: the whole card is clickable → toggles selection (task 1869). */
112
146
  .task { cursor: pointer; }
113
- .backlog-count { font-size: 13px; color: var(--ink-faint); margin-left: 8px; }
147
+ .backlog-count {
148
+ font-family: var(--font-mono);
149
+ font-size: 11px;
150
+ font-variant-numeric: tabular-nums;
151
+ color: var(--ink-faint);
152
+ margin-left: 8px;
153
+ }
114
154
  #backlog-list .history__row { cursor: pointer; }
115
155
 
156
+ /* The Ready queue is .scroll--bare, so its pager has no panel to sit in and
157
+ takes its own — v3's board does exactly this (the cards ARE the panels, and a
158
+ pager floating on the bare ground has nothing to belong to). */
159
+ #ready-pager-mount .pager {
160
+ background: var(--bg-card);
161
+ border-radius: var(--radius);
162
+ padding: 12px 22px;
163
+ margin-top: 14px;
164
+ }
165
+
116
166
  /* In-flight table: release action on the viewer's own claims. */
117
167
  .wip__action { text-align: right; white-space: nowrap; }
118
168
  .wip__release {
119
- background: var(--surface);
120
- border: 1px solid var(--border-strong);
169
+ display: inline-flex;
170
+ align-items: center;
171
+ justify-content: center;
172
+ min-height: 30px;
173
+ padding: 0 14px;
174
+ background: none;
175
+ border: var(--line) solid var(--rule);
121
176
  color: var(--ink-soft);
122
- border-radius: var(--radius-sm);
123
- font-size: 12px;
124
- font-weight: 600;
125
- padding: 4px 11px;
177
+ border-radius: var(--radius-pill);
178
+ font-size: 13px;
179
+ text-transform: lowercase;
126
180
  cursor: pointer;
127
181
  transition: background 150ms, color 150ms, border-color 150ms;
128
182
  }
@@ -133,77 +187,149 @@
133
187
  }
134
188
  .wip__release:disabled { opacity: 0.55; cursor: default; }
135
189
  .wip__mine-none { color: var(--ink-faint); }
136
- .wip__row--mine { background: var(--accent-weak); }
190
+ .wip__row--mine { background: var(--accent-tint); }
137
191
 
138
- /* Recently-shipped history. */
139
- .history { display: flex; flex-direction: column; gap: 2px; margin-top: 6px; }
192
+ /* Recently-shipped history — v1's bare ledger row inside v3's panel: one
193
+ --rule-soft hairline on top, no fill, no radius. The first row drops its rule
194
+ AND its top padding so the list starts flush against the panel's own air,
195
+ which is the single adaptation v3 makes to v1's ledger. */
196
+ .history { display: flex; flex-direction: column; gap: 0; margin-top: 6px; }
140
197
  .history__row {
141
198
  display: flex; align-items: baseline; gap: 12px;
142
- padding: 6px 4px;
143
- border-bottom: 1px solid var(--rule-soft);
199
+ padding: 14px 0;
200
+ border-top: var(--line) solid var(--rule-soft);
201
+ border-bottom: none;
144
202
  }
145
- .history__row:last-child { border-bottom: none; }
203
+ .history__row:first-child { border-top: 0; padding-top: 0; }
146
204
  .history__id {
147
- font-weight: 600; color: var(--ink-soft);
205
+ font-family: var(--font-mono);
206
+ font-size: 12.5px;
207
+ color: var(--ink-faint);
148
208
  font-variant-numeric: tabular-nums; min-width: 3.2em;
149
209
  }
150
210
  .history__title { flex: 1 1 auto; color: var(--ink); min-width: 0; }
151
- .history__when { color: var(--ink-faint); font-size: 12.5px; white-space: nowrap; }
211
+ .history__when { color: var(--ink-soft); font-size: 12.5px; white-space: nowrap; font-variant-numeric: tabular-nums; }
152
212
 
153
213
  @media (max-width: 640px) {
154
- .task__actions { grid-column: 2; justify-self: start; }
214
+ .task__actions { grid-column: 1 / -1; justify-self: start; padding-top: 6px; }
155
215
  }
156
216
 
157
- /* ---- task 1759: multi-select + the bottom bulk-action toolbar ---- */
217
+ /* ---- task 1759: multi-select + the bottom bulk-action toolbar ----
218
+ Re-cut for the 24px floor and the world (task 1003304). The floating dark
219
+ pill is gone: it painted an INVERTED surface (background: var(--ink)) with
220
+ three rgba(255,255,255,…) literals on top, which was correct only for as long
221
+ as --ink stayed dark — a light-on-dark instance pack would have inverted it
222
+ into unreadability. v3's bulk bar is a glass band across the foot of the
223
+ content column instead, inset by the rail, so it never has to invert. */
158
224
 
159
225
  .wip__select-cell { width: 1%; text-align: center; }
160
- .wip__select { width: 15px; height: 15px; cursor: pointer; accent-color: var(--accent); }
226
+ .wip__select {
227
+ appearance: none;
228
+ -webkit-appearance: none;
229
+ position: relative;
230
+ width: 24px;
231
+ height: 24px;
232
+ margin: 0;
233
+ cursor: pointer;
234
+ }
235
+ .wip__select::before {
236
+ content: "";
237
+ position: absolute;
238
+ left: 5px;
239
+ top: 5px;
240
+ width: 14px;
241
+ height: 14px;
242
+ border: var(--line) solid var(--rule);
243
+ border-radius: 3px;
244
+ }
245
+ .wip__select:checked::before { background: var(--accent); border-color: var(--accent); }
246
+ .wip__select:checked::after {
247
+ content: "";
248
+ position: absolute;
249
+ left: 9px;
250
+ top: 8px;
251
+ width: 4px;
252
+ height: 8px;
253
+ border: solid var(--accent-on);
254
+ border-width: 0 1.5px 1.5px 0;
255
+ transform: rotate(42deg);
256
+ }
161
257
 
162
258
  .bulk-toolbar {
163
259
  position: fixed;
164
- left: 50%;
165
- bottom: 20px;
166
- transform: translateX(-50%);
167
- z-index: 120;
260
+ left: var(--sidebar-w);
261
+ right: 0;
262
+ bottom: 0;
263
+ /* The chrome tier, not above it: the toast (z 100) has to stay readable over
264
+ this bar, and the drawer + its scrim have to cover it. */
265
+ z-index: var(--z-topbar);
168
266
  display: flex;
169
267
  align-items: center;
170
- gap: 14px;
268
+ gap: 16px;
171
269
  flex-wrap: wrap;
172
- background: var(--ink);
173
- color: var(--bg-card);
174
- padding: 10px 16px;
175
- border-radius: var(--radius);
176
- box-shadow: var(--shadow-pop);
177
- max-width: min(92vw, 720px);
270
+ padding: 12px 20px;
271
+ /* TWO layers, and the bottom one is why. The topbar and the rail can be bare
272
+ --glass because the page GROUND is behind them; this bar sits over the task
273
+ cards, and in light --glass is a 5% ink tint with the blur at 0px, so the
274
+ card underneath read straight through it and the buttons landed on top of a
275
+ task title (looked at, 1280w light). Painting --bg under the tint makes the
276
+ bar opaque without giving up the glass character or spending a literal. */
277
+ background: linear-gradient(var(--glass), var(--glass)), var(--bg);
278
+ border-top: var(--line) solid var(--glass-edge);
279
+ backdrop-filter: blur(var(--glass-blur));
280
+ -webkit-backdrop-filter: blur(var(--glass-blur));
281
+ color: var(--ink);
178
282
  }
179
283
  .bulk-toolbar[hidden] { display: none; }
180
- .bulk-toolbar__count { font-size: 13px; font-weight: 600; white-space: nowrap; }
181
- .bulk-toolbar__actions { display: flex; gap: 8px; flex-wrap: wrap; }
284
+ .bulk-toolbar__count {
285
+ font-family: var(--label-face);
286
+ font-size: var(--label-size);
287
+ letter-spacing: var(--label-space);
288
+ text-transform: var(--label-case);
289
+ color: var(--ink);
290
+ white-space: nowrap;
291
+ }
292
+ .bulk-toolbar__actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-left: auto; }
182
293
  .bulk-toolbar__btn {
183
- background: rgba(255, 255, 255, 0.12);
184
- border: 1px solid rgba(255, 255, 255, 0.25);
185
- color: var(--bg-card);
186
- border-radius: var(--radius-sm);
187
- font-size: 12.5px;
188
- font-weight: 600;
189
- padding: 6px 12px;
294
+ display: inline-flex;
295
+ align-items: center;
296
+ justify-content: center;
297
+ min-height: 30px;
298
+ padding: 0 14px;
299
+ background: var(--glass);
300
+ border: var(--line) solid var(--glass-edge);
301
+ color: var(--ink);
302
+ border-radius: var(--radius-pill);
303
+ font-size: 13px;
304
+ text-transform: lowercase;
190
305
  cursor: pointer;
191
306
  white-space: nowrap;
192
307
  transition: background 150ms, opacity 150ms;
193
308
  }
194
- .bulk-toolbar__btn:hover:not(:disabled) { background: rgba(255, 255, 255, 0.22); }
195
- .bulk-toolbar__btn:disabled { opacity: 0.4; cursor: not-allowed; }
309
+ .bulk-toolbar__btn:hover:not(:disabled) { background: var(--glass-strong); }
310
+ .bulk-toolbar__btn:disabled { color: var(--ink-faint); border-color: var(--rule-soft); cursor: not-allowed; }
196
311
  .bulk-toolbar__clear {
312
+ min-height: 30px;
313
+ padding: 0 10px;
197
314
  background: transparent;
198
315
  border: none;
199
- color: var(--bg-card);
200
- opacity: 0.75;
201
- font-size: 12.5px;
316
+ color: var(--ink-soft);
317
+ font-size: 13px;
318
+ text-transform: lowercase;
319
+ text-decoration: underline;
320
+ text-underline-offset: 4px;
202
321
  cursor: pointer;
203
- padding: 4px 6px;
204
322
  }
205
- .bulk-toolbar__clear:hover { opacity: 1; }
323
+ .bulk-toolbar__clear:hover { color: var(--ink); }
206
324
 
207
- @media (max-width: 640px) {
208
- .bulk-toolbar { left: 12px; right: 12px; bottom: 12px; transform: none; max-width: none; }
325
+ /* The shell's .app-content already ends in 108px of bottom air at desktop
326
+ width, which is what clears the bar — but at 768 it drops to 48px for the
327
+ phone, and there the bar is TALLER (its actions wrap to their own row). So
328
+ the phone width buys the room back, scoped to this page: goals.html loads
329
+ this sheet too and has no bulk toolbar to clear. */
330
+ @media (max-width: 768px) {
331
+ /* At the drawer breakpoint the sidebar leaves the flow, so the bar spans. */
332
+ .bulk-toolbar { left: 0; padding: 10px 14px; gap: 10px; }
333
+ .bulk-toolbar__actions { margin-left: 0; width: 100%; }
334
+ body[data-page="work"] .app-content { padding-bottom: 200px; }
209
335
  }
@@ -8,7 +8,6 @@
8
8
  <link rel="icon" href="data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><text x='16' y='24' font-size='24' text-anchor='middle' font-family='sans-serif'>⌂</text></svg>">
9
9
  <link rel="preconnect" href="https://fonts.googleapis.com">
10
10
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
11
- <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
12
11
  <link rel="stylesheet" href="/builders/style.css?v=2026-07-02-shell1">
13
12
  <!-- Page-local styles (task 2170) — extracted from the old inline <style>
14
13
  block per the hall placement rules; shared pager/count-pill styles now
@@ -23,11 +22,17 @@
23
22
  <div class="app-body">
24
23
  <header class="app-topbar" id="app-topbar"></header>
25
24
  <div class="app-content">
26
- <div class="page-head">
25
+ <!-- task 1003304: the board's own <h1>. The hall predates the
26
+ one-header-main-h1 floor and this page had none — the topbar's
27
+ lowercase "tasks" is chrome, not a heading. v3 sets the page head in
28
+ the LABEL voice and saves the display face for section headings, so
29
+ this is quiet on purpose (see .page-head--board in work.css). -->
30
+ <div class="page-head page-head--board">
31
+ <h1 class="page-head__h">Work board</h1>
27
32
  <p class="page-head__sub" id="work-sub">Loading tasks…</p>
28
33
  </div>
29
34
 
30
- <main>
35
+ <main id="hall-main">
31
36
  <!-- Gate notice — shown by work.js when the viewer is signed in but hasn't
32
37
  yet acknowledged the primer (the claimable feed is primer-gated
33
38
  server-side). The server already bars an UNAUTHENTICATED visitor from
@@ -49,7 +54,13 @@
49
54
 
50
55
  <!-- READY — the claimable queue: the page's primary object, above the
51
56
  fold as the default tab. -->
52
- <section class="scroll" id="claim-scroll" aria-labelledby="claim-h">
57
+ <!-- task 1003304: BARE, and that is the whole re-skin. In v3 a claimable
58
+ task IS a --bg-card panel (docs/design/mocks/hall/board/v3.html:
59
+ #board is a plain .sec, never .sec--sheet), so leaving this section
60
+ a .scroll would paint a card inside a card. The other three tabs
61
+ hold rows and tables, which v3 does put inside a panel — they keep
62
+ theirs. -->
63
+ <section class="scroll scroll--bare" id="claim-scroll" aria-labelledby="claim-h">
53
64
  <h2 id="claim-h" class="scroll__h">Ready — tasks to do<span class="count-pill" id="ready-count" hidden></span></h2>
54
65
  <p class="scroll__lede">Click <span class="kbd">Claim</span> to take a task right here — no terminal needed. Then click <span class="kbd">📋</span> to copy the task prompt and paste it into a fresh Claude Code session to begin.</p>
55
66
 
@@ -403,7 +403,7 @@
403
403
  <div class="task${selected ? ' task--selected' : ''}" data-task-id="${t.id}">
404
404
  <div class="task__id">
405
405
  <input type="checkbox" class="task__select" data-task-id="${t.id}" aria-label="Select task ${t.id} for bulk actions"${selected ? ' checked' : ''}>
406
- <span>#${t.id}</span>
406
+ <span class="task__num">#${t.id}</span>
407
407
  <button class="task__open" type="button" data-task-id="${t.id}" title="Open task details" aria-label="Open details for task ${t.id}">⤢</button>
408
408
  </div>
409
409
  <div class="task__body">
@@ -0,0 +1,19 @@
1
+ {
2
+ "_": "The hall's Work Board through modules/ui-design/kit/render.js (task 1003304). Written with the re-skin so the board's four tabs and its selection state are measured at 1440/390/320 in both modes, not just looked at. The populated look is the hall-preview harness (scripts/hall-preview/server.js); this file is the FLOORS.",
3
+ "page": "/builders/work",
4
+ "surface": "hall-ui",
5
+ "stub": { "prefix": "/builders/" },
6
+ "modeQuery": false,
7
+ "_feeds": "The kit's stub carries a small fixture set, not the hall's task feeds, so the board renders its EMPTY and SKELETON states here — which is the point: an empty queue is a state the floors must hold in. The feed 404s are declared, never hidden.",
8
+ "ignoreRequests": ["/api/(gds|bongos)/me$", "/api/(gds|bongos)/me/", "/api/(gds|bongos)/tasks", "/api/(gds|bongos)/claims", "/api/(gds|bongos)/goals", "/api/(gds|bongos)/inbox/", "/api/(gds|bongos)/versions"],
9
+ "ignoreConsole": ["/api/(gds|bongos)/", "\b401\b", "\b404\b", "Unauthorized", "Not Found", "load failed"],
10
+ "states": {
11
+ "ready": { "auth": true, "expect": { "visible": ["#claim-scroll"], "hidden": ["#wip-scroll", "#backlog-scroll", "#history-scroll"] } },
12
+ "in-progress": { "auth": true, "url": "/builders/work#in-progress", "actions": [["wait", 400]], "expect": { "visible": ["#wip-scroll"] } },
13
+ "backlog": { "auth": true, "url": "/builders/work#backlog", "actions": [["wait", 400]], "expect": { "visible": ["#backlog-scroll"] } },
14
+ "completed": { "auth": true, "url": "/builders/work#completed", "actions": [["wait", 400]], "expect": { "visible": ["#history-scroll"] } },
15
+ "filters-open": { "auth": true, "actions": [["clickIfVisible", "#work-filters [aria-expanded=\"false\"]"], ["wait", 250]] },
16
+ "out": { "auth": false }
17
+ },
18
+ "reducedMotion": { "auth": true }
19
+ }
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.19.445",
3
+ "version": "1.19.447",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.19.445",
9
+ "version": "1.19.447",
10
10
  "license": "AGPL-3.0-or-later",
11
11
  "dependencies": {
12
12
  "express": "^4.21.2",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.19.445",
3
+ "version": "1.19.447",
4
4
  "description": "Cloud Bongos — the AI-first build platform core (GDS + platform surfaces + module system), installed as a versioned dependency (ADR 0108).",
5
5
  "license": "AGPL-3.0-or-later",
6
6
  "main": "src/platform-server.js",
package/src/module-api.js CHANGED
@@ -33,7 +33,7 @@ const { validateOrRespond, LIMITS, parseId, asyncHandler, corsPublicGet, parsePa
33
33
  // there. scripts/gds/bump-version.js still rewrites the literal below; it appends
34
34
  // the entry to that file. Look for a version's history there, not here.
35
35
  // ---------------------------------------------------------------------------
36
- const CORE_VERSION = '1.19.445'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
36
+ const CORE_VERSION = '1.19.447'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
37
37
 
38
38
  // A namespaced logger so a module's log lines are attributable + consistent.
39
39
  // Usage: const log = api.logger('dev-box'); log.info('mounted');