@bongos/core 1.19.927 → 1.19.929
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 +83 -53
- package/docs/copy-inventory.md +36 -15
- package/docs/copy-registry.json +239 -28
- package/docs/file-map.md +1 -1
- package/docs/module-api-changelog.md +4 -0
- package/modules/hall-ui/public/atlas.html +1 -1
- package/modules/hall-ui/public/blockers.html +1 -1
- package/modules/hall-ui/public/board-room.html +1 -1
- package/modules/hall-ui/public/collab.html +1 -1
- package/modules/hall-ui/public/copy-desk.html +1 -1
- package/modules/hall-ui/public/deploy.html +1 -1
- package/modules/hall-ui/public/diagrams.html +1 -1
- package/modules/hall-ui/public/drachmae.html +1 -1
- package/modules/hall-ui/public/gate.html +1 -1
- package/modules/hall-ui/public/goals.html +1 -1
- package/modules/hall-ui/public/government.html +1 -1
- package/modules/hall-ui/public/idea-objects.js +109 -0
- package/modules/hall-ui/public/idea.html +1 -1
- package/modules/hall-ui/public/ideas.html +1 -1
- package/modules/hall-ui/public/index.html +1 -1
- package/modules/hall-ui/public/modules.html +1 -1
- package/modules/hall-ui/public/people.html +1 -1
- package/modules/hall-ui/public/primer.html +1 -1
- package/modules/hall-ui/public/profile.html +1 -1
- package/modules/hall-ui/public/project-settings.html +1 -1
- package/modules/hall-ui/public/ranks.html +1 -1
- package/modules/hall-ui/public/roadmap.html +1 -1
- package/modules/hall-ui/public/roster.html +1 -1
- package/modules/hall-ui/public/sessions.html +1 -1
- package/modules/hall-ui/public/settings.html +1 -1
- package/modules/hall-ui/public/shell.js +11 -0
- package/modules/hall-ui/public/studio.html +1 -1
- package/modules/hall-ui/public/task.html +1 -1
- package/modules/hall-ui/public/thinking.css +286 -0
- package/modules/hall-ui/public/thinking.html +74 -0
- package/modules/hall-ui/public/thinking.js +418 -0
- package/modules/hall-ui/public/thinking.states.json +20 -0
- package/modules/hall-ui/public/watch.html +1 -1
- package/modules/hall-ui/public/work.html +1 -1
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/scripts/gds/provision-config.js +11 -0
- package/scripts/gds/provision-core-upgrade.js +90 -10
- package/scripts/gds/provision.js +3 -3
- package/src/bongos/serve-internal.js +7 -1
- package/src/module-api.js +1 -1
- package/tests/core_upgrade_runner.mjs +153 -0
- package/tests/hall_nav.mjs +1 -1
- package/tests/hall_page_gate_map.mjs +6 -0
- package/tests/hall_thinking_room.mjs +366 -0
- package/tests/helpers.mjs +124 -0
- package/tests/nav_permission_atoms.mjs +1 -1
- package/tests/provision.mjs +41 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
// modules/hall-ui/public/idea-objects.js — THE FIVE OBJECTS, as a reader's
|
|
2
|
+
// words (task 1004098 / BV2.R03 "the room", goal 1000095).
|
|
3
|
+
//
|
|
4
|
+
// The server derives which object a thought IS — once, in
|
|
5
|
+
// modules/ideas/idea-state.js, from the ledger (ADR 0322). This file is the
|
|
6
|
+
// other half of that decision and deliberately does NOT re-derive anything: it
|
|
7
|
+
// maps a state the server already answered onto the word, the sentence and the
|
|
8
|
+
// mark a surface draws for it. `resolveIdeaState` is the authority on WHICH of
|
|
9
|
+
// the five; this is the authority on how one LOOKS.
|
|
10
|
+
//
|
|
11
|
+
// IT IS SHARED BECAUSE TWO SURFACES DRAW THESE AND A THIRD WILL. The room
|
|
12
|
+
// (this task) is the first, the sky (BV2.R26) is the next, and the idea record
|
|
13
|
+
// is the obvious third. A vocabulary copied into each of them is how the sky
|
|
14
|
+
// ends up calling a thought "burned out" while the room beside it says
|
|
15
|
+
// "declined" — the same failure the resolver exists to prevent, one layer up.
|
|
16
|
+
// The descent on /idea/:id is deliberately NOT a consumer: a descent row is a
|
|
17
|
+
// TASK, and marking one with an idea-level object would be exactly the
|
|
18
|
+
// re-derivation this pair of files refuses (see idea.js, "what a row is marked
|
|
19
|
+
// by").
|
|
20
|
+
//
|
|
21
|
+
// THE WORDS ARE THE DESIGN'S, taken from docs/design/ideator-surface-direction.md
|
|
22
|
+
// §"The five objects" rather than invented here, so the surface says what the
|
|
23
|
+
// owner said. Where that table is a fragment ("it burned, then the project
|
|
24
|
+
// removed it"), it is spelled into a sentence and nothing more.
|
|
25
|
+
//
|
|
26
|
+
// NO DOM, no fetch, no state. One frozen table and three lookups, so a page
|
|
27
|
+
// under test can read it without booting a page.
|
|
28
|
+
(function () {
|
|
29
|
+
'use strict';
|
|
30
|
+
|
|
31
|
+
// Canonical order. It is the order the design lists them in and the order a
|
|
32
|
+
// filter row draws them in — brightest and most actionable first, folded and
|
|
33
|
+
// declined last — so two surfaces cannot disagree about where a pill sits.
|
|
34
|
+
var ORDER = ['star', 'protostar', 'satellite', 'remnant', 'cold-body'];
|
|
35
|
+
|
|
36
|
+
var OBJECTS = {
|
|
37
|
+
star: {
|
|
38
|
+
label: 'burning',
|
|
39
|
+
noun: 'star',
|
|
40
|
+
blurb: 'caused work that is still alive. it dims as pieces of that work are removed',
|
|
41
|
+
},
|
|
42
|
+
protostar: {
|
|
43
|
+
label: 'waiting',
|
|
44
|
+
noun: 'protostar',
|
|
45
|
+
blurb: 'filed, not yet ignited',
|
|
46
|
+
},
|
|
47
|
+
satellite: {
|
|
48
|
+
label: 'folded in',
|
|
49
|
+
noun: 'satellite',
|
|
50
|
+
blurb: 'folded into another thought. it orbits that one now, and its value counts there',
|
|
51
|
+
},
|
|
52
|
+
remnant: {
|
|
53
|
+
label: 'burned out',
|
|
54
|
+
noun: 'remnant',
|
|
55
|
+
blurb: 'it burned, then the project removed it. it keeps every bit of its size',
|
|
56
|
+
},
|
|
57
|
+
'cold-body': {
|
|
58
|
+
label: 'declined',
|
|
59
|
+
noun: 'cold body',
|
|
60
|
+
blurb: 'declined at triage. it never ignited, so it has no size at all',
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// An unknown state is passed through rather than swallowed, the way idea.js
|
|
65
|
+
// passes through an unknown descent relation: a sixth object would be a real
|
|
66
|
+
// answer the server gave, and drawing it unstyled beats drawing nothing or,
|
|
67
|
+
// worse, silently drawing it as a protostar.
|
|
68
|
+
function objectFor(state) {
|
|
69
|
+
var key = String(state || '');
|
|
70
|
+
return OBJECTS[key] || { label: key || 'unknown', noun: key || 'unknown', blurb: '' };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// POSITION is the second axis and it is only load-bearing for a protostar —
|
|
74
|
+
// the design is explicit that a star has a position too, and that the
|
|
75
|
+
// distinction only MEANS something for a thought nothing has claimed yet.
|
|
76
|
+
// So this returns a sentence for exactly that case and null otherwise,
|
|
77
|
+
// rather than letting every row carry a word that tells a reader nothing.
|
|
78
|
+
function positionWord(state) {
|
|
79
|
+
if (!state || state.state !== 'protostar') return null;
|
|
80
|
+
if (state.position !== 'well') return 'nothing has claimed it';
|
|
81
|
+
return state.awaitingNod ? 'waiting for a nod' : 'has a home';
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Brightness as a reader's phrase. THE THREE ANSWERS ARE THREE, never two:
|
|
85
|
+
// a number → this share of the work it caused is still alive
|
|
86
|
+
// null → the removal facts could not be read at all
|
|
87
|
+
// no work → nothing to be alive or dead yet
|
|
88
|
+
// Collapsing "we could not look" into "none of it survived" is the exact
|
|
89
|
+
// mistake modules/ideas/idea-state.js step 3 was written to prevent, and it
|
|
90
|
+
// would render a healthy instance as a field of hollow rings the moment the
|
|
91
|
+
// lifecycle module failed to mount.
|
|
92
|
+
function brightnessWord(state) {
|
|
93
|
+
if (!state || state.hasWork !== true) return null;
|
|
94
|
+
if (state.attributable !== true || state.brightness === null || state.brightness === undefined) {
|
|
95
|
+
return 'still alive — unknown';
|
|
96
|
+
}
|
|
97
|
+
var pct = Math.round(Number(state.brightness) * 100);
|
|
98
|
+
if (pct >= 100) return 'all of it still alive';
|
|
99
|
+
if (pct <= 0) return 'none of it still alive';
|
|
100
|
+
return pct + '% still alive';
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
window.OTBIdeaObjects = {
|
|
104
|
+
ORDER: ORDER,
|
|
105
|
+
objectFor: objectFor,
|
|
106
|
+
positionWord: positionWord,
|
|
107
|
+
brightnessWord: brightnessWord,
|
|
108
|
+
};
|
|
109
|
+
})();
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
|
|
53
53
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
54
54
|
|
|
55
|
-
<script src="/builders/shell.js?v=2026-09-20-
|
|
55
|
+
<script src="/builders/shell.js?v=2026-09-20-room1"></script>
|
|
56
56
|
<script src="/builders/palette.js" defer></script>
|
|
57
57
|
<script src="/builders/dom-utils.js?v=2026-06-23-contrib" defer></script>
|
|
58
58
|
<!-- task-detail.js still owns the #/idea/N and #/blocker/N overlay, so a ref
|
|
@@ -192,7 +192,7 @@
|
|
|
192
192
|
|
|
193
193
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
194
194
|
|
|
195
|
-
<script src="/builders/shell.js?v=2026-09-20-
|
|
195
|
+
<script src="/builders/shell.js?v=2026-09-20-room1"></script>
|
|
196
196
|
<script src="/builders/palette.js" defer></script>
|
|
197
197
|
<script src="/builders/dom-utils.js?v=2026-06-23-contrib"></script>
|
|
198
198
|
<!-- task 1003069 (R08) — the quick-filing form's routed result links a task
|
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
<script src="/builders/brand-apply.js?v=2026-06-27-r75" defer></script>
|
|
103
103
|
<!-- The app shell (sidebar + top bar + view router). Dependency-free; loaded
|
|
104
104
|
BEFORE builders.js so the chrome ids exist when events are wired. -->
|
|
105
|
-
<script src="/builders/shell.js?v=2026-09-20-
|
|
105
|
+
<script src="/builders/shell.js?v=2026-09-20-room1" defer></script>
|
|
106
106
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
107
107
|
<script src="/builders/palette.js" defer></script>
|
|
108
108
|
<!-- task 2166: the shared component kit (window.OTBKit) — pager/ledger/rail.
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
|
|
81
81
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
82
82
|
|
|
83
|
-
<script src="/builders/shell.js?v=2026-09-20-
|
|
83
|
+
<script src="/builders/shell.js?v=2026-09-20-room1"></script>
|
|
84
84
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
85
85
|
<script src="/builders/palette.js" defer></script>
|
|
86
86
|
<script src="/builders/dom-utils.js?v=2026-06-23-contrib"></script>
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
|
|
56
56
|
<!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
|
|
57
57
|
chrome exists before the page script runs. -->
|
|
58
|
-
<script src="/builders/shell.js?v=2026-09-20-
|
|
58
|
+
<script src="/builders/shell.js?v=2026-09-20-room1"></script>
|
|
59
59
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
60
60
|
<script src="/builders/palette.js" defer></script>
|
|
61
61
|
<!-- shared frontend toolkit (window.OTB — rank labels, number formats) + the
|
|
@@ -115,7 +115,7 @@
|
|
|
115
115
|
|
|
116
116
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
117
117
|
|
|
118
|
-
<script src="/builders/shell.js?v=2026-09-20-
|
|
118
|
+
<script src="/builders/shell.js?v=2026-09-20-room1"></script>
|
|
119
119
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
120
120
|
<script src="/builders/palette.js" defer></script>
|
|
121
121
|
<!-- the shared markdown reader (window.OTBMdReader) — primer.js renders through
|
|
@@ -187,7 +187,7 @@
|
|
|
187
187
|
|
|
188
188
|
<!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
|
|
189
189
|
chrome exists before the page script runs. -->
|
|
190
|
-
<script src="/builders/shell.js?v=2026-09-20-
|
|
190
|
+
<script src="/builders/shell.js?v=2026-09-20-room1"></script>
|
|
191
191
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
192
192
|
<script src="/builders/palette.js" defer></script>
|
|
193
193
|
<!-- shared frontend toolkit (window.OTB) — loaded before profile.js, which pulls from it. -->
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
|
|
59
59
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
60
60
|
|
|
61
|
-
<script src="/builders/shell.js?v=2026-09-20-
|
|
61
|
+
<script src="/builders/shell.js?v=2026-09-20-room1"></script>
|
|
62
62
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
63
63
|
<script src="/builders/palette.js" defer></script>
|
|
64
64
|
<script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
|
|
69
69
|
<!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
|
|
70
70
|
chrome exists before the page script runs. -->
|
|
71
|
-
<script src="/builders/shell.js?v=2026-09-20-
|
|
71
|
+
<script src="/builders/shell.js?v=2026-09-20-room1"></script>
|
|
72
72
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
73
73
|
<script src="/builders/palette.js" defer></script>
|
|
74
74
|
<!-- shared frontend toolkit (window.OTB) — loaded before ranks.js, which pulls from it. -->
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
|
|
42
42
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
43
43
|
|
|
44
|
-
<script src="/builders/shell.js?v=2026-09-20-
|
|
44
|
+
<script src="/builders/shell.js?v=2026-09-20-room1"></script>
|
|
45
45
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
46
46
|
<script src="/builders/palette.js" defer></script>
|
|
47
47
|
<script src="/builders/dom-utils.js?v=2026-06-14-domutils"></script>
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
|
|
51
51
|
<!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
|
|
52
52
|
chrome exists before the page script runs. -->
|
|
53
|
-
<script src="/builders/shell.js?v=2026-09-20-
|
|
53
|
+
<script src="/builders/shell.js?v=2026-09-20-room1"></script>
|
|
54
54
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
55
55
|
<script src="/builders/palette.js" defer></script>
|
|
56
56
|
<!-- shared frontend toolkit (window.OTB — rank labels, number formats) + the
|
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
|
|
100
100
|
<!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
|
|
101
101
|
chrome exists before the page script runs. -->
|
|
102
|
-
<script src="/builders/shell.js?v=2026-09-20-
|
|
102
|
+
<script src="/builders/shell.js?v=2026-09-20-room1"></script>
|
|
103
103
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
104
104
|
<script src="/builders/palette.js" defer></script>
|
|
105
105
|
<!-- shared frontend toolkit (window.OTB) — loaded BEFORE sessions.js so it can pull from it. -->
|
|
@@ -416,7 +416,7 @@
|
|
|
416
416
|
|
|
417
417
|
<!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
|
|
418
418
|
chrome exists before the page scripts run. -->
|
|
419
|
-
<script src="/builders/shell.js?v=2026-09-20-
|
|
419
|
+
<script src="/builders/shell.js?v=2026-09-20-room1"></script>
|
|
420
420
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
421
421
|
<script src="/builders/palette.js" defer></script>
|
|
422
422
|
<!-- shared frontend toolkit (window.OTB) — loaded before consuming IIFEs. -->
|
|
@@ -216,6 +216,17 @@
|
|
|
216
216
|
// behind the ideator craft would hide the ideator's own surface from
|
|
217
217
|
// everyone else who has a thought, which is most of the value.
|
|
218
218
|
{ id: 'ideas', label: 'Ideas', icon: 'goals', href: '/ideas', gate: 'signed' },
|
|
219
|
+
// task 1004098 (BV2.R03 of goal 1000095): THE ROOM — what you filed and
|
|
220
|
+
// what became of it. Directly under Ideas because the two are the daily
|
|
221
|
+
// loop: you file on one and you find out on the other, and the whole
|
|
222
|
+
// criterion (`ideator-nothing-is-lost`) is that the second half must be
|
|
223
|
+
// reachable without asking anyone. NOT in the 'You' group beside Standing
|
|
224
|
+
// and Profile, even though it is your own view: that group is your
|
|
225
|
+
// numbers, and this page's subject is the project's work, seen from the
|
|
226
|
+
// thought that caused it. gate 'signed' for the same reason Ideas is —
|
|
227
|
+
// there is no permission gate on having a thought, and the route reads the
|
|
228
|
+
// VIEWER's own trail, so there is nothing here a rank could protect.
|
|
229
|
+
{ id: 'thinking', label: 'Your thinking', icon: 'goals', href: '/thinking', gate: 'signed' },
|
|
219
230
|
{ id: 'copy-desk', label: 'Copy desk', icon: 'docs', href: '/copy-desk', gate: 'signed', module: 'copy-desk' },
|
|
220
231
|
// task 1003117 (R06 of goal 1000074): the Studio — artist mode, "a place an
|
|
221
232
|
// artist wants to be, not a form". Beside the copy desk (the artist's other
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
|
|
67
67
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
68
68
|
|
|
69
|
-
<script src="/builders/shell.js?v=2026-09-20-
|
|
69
|
+
<script src="/builders/shell.js?v=2026-09-20-room1"></script>
|
|
70
70
|
<script src="/builders/palette.js" defer></script>
|
|
71
71
|
<script src="/builders/dom-utils.js?v=2026-06-23-contrib"></script>
|
|
72
72
|
<!-- The kit, for its ONE renderer: the full-size ship-time visual figure
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
|
|
58
58
|
<!-- The app shell (sidebar + top bar + footer). Dependency-free; runs at parse
|
|
59
59
|
time so the chrome exists before the deferred page scripts execute. -->
|
|
60
|
-
<script src="/builders/shell.js?v=2026-09-20-
|
|
60
|
+
<script src="/builders/shell.js?v=2026-09-20-room1"></script>
|
|
61
61
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
62
62
|
<script src="/builders/palette.js" defer></script>
|
|
63
63
|
<!-- shared frontend toolkit (window.OTB) — loaded FIRST so task.js can pull from it. -->
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
/* thinking.css — what THE ROOM has that no other hall page has
|
|
2
|
+
(task 1004098 / BV2.R03, goal 1000095).
|
|
3
|
+
|
|
4
|
+
The composition is the shell's: `.page-head--board`, `.scroll`, `.ledger` and
|
|
5
|
+
the kit's `.kit-tabs` strip all come from style.css and are not restated here.
|
|
6
|
+
What is left is the three shapes only this page has — the figure run over the
|
|
7
|
+
list, the size bar, and the mark for the five objects — plus the cells the
|
|
8
|
+
ledger has no opinion about.
|
|
9
|
+
|
|
10
|
+
NO COLOUR THAT IS NOT A TOKEN. Every value below is one of the world's
|
|
11
|
+
fifteen or a color-mix of them, so the page inherits dark and light from the
|
|
12
|
+
pack rather than declaring either: there is not one mode-specific rule in this
|
|
13
|
+
sheet, which is why it needs no dark twin. `--line` is a WIDTH; a hairline's
|
|
14
|
+
colour is `--rule` / `--rule-soft`.
|
|
15
|
+
|
|
16
|
+
NO MOTION. Nothing here transitions or animates, so the sheet sits entirely
|
|
17
|
+
inside the Kill Switch rather than needing to be excused by it. The one thing
|
|
18
|
+
that could have moved — a size bar growing as the background pages land —
|
|
19
|
+
deliberately does not: the bar is a measurement, and a measurement that
|
|
20
|
+
animates on every re-render turns a quiet page into a twitching one. */
|
|
21
|
+
|
|
22
|
+
/* ---- the figures over the list -------------------------------------------
|
|
23
|
+
The same object as the descent's `.ig-desc__figs` on /idea/:id, and that is
|
|
24
|
+
on purpose rather than by accident: the two pages state the same kind of fact
|
|
25
|
+
(a count over a body of work) and a reader moving between them should not
|
|
26
|
+
have to learn a second shape for it. It is not SHARED code, because the
|
|
27
|
+
descent's figures live in the idea record's own sheet and hoisting them into
|
|
28
|
+
style.css to serve two pages is an archetype decision, not a page's. If a
|
|
29
|
+
third surface wants them — the sky will — that is the moment. */
|
|
30
|
+
.tr-figs {
|
|
31
|
+
display: flex;
|
|
32
|
+
flex-wrap: wrap;
|
|
33
|
+
gap: var(--sp-md) var(--sp-lg);
|
|
34
|
+
margin: 0 0 var(--sp-md);
|
|
35
|
+
}
|
|
36
|
+
.tr-fig { display: grid; gap: 6px; }
|
|
37
|
+
.tr-fig__n {
|
|
38
|
+
font-size: 32px;
|
|
39
|
+
font-weight: 300;
|
|
40
|
+
line-height: 1;
|
|
41
|
+
letter-spacing: -0.03em;
|
|
42
|
+
font-variant-numeric: tabular-nums;
|
|
43
|
+
color: var(--ink);
|
|
44
|
+
}
|
|
45
|
+
/* Only ONE figure is warm, and it is the live one — "still burning" is the
|
|
46
|
+
number the page exists to make visible, and an accent spent on all four would
|
|
47
|
+
say nothing. "burned out" goes faint for the same reason it does in the
|
|
48
|
+
descent: the record of work that happened is not an error to shout. */
|
|
49
|
+
.tr-fig[data-tone="warm"] .tr-fig__n { color: var(--accent-deep); }
|
|
50
|
+
.tr-fig[data-tone="dim"] .tr-fig__n { color: var(--ink-faint); }
|
|
51
|
+
.tr-fig__label {
|
|
52
|
+
font-family: var(--label-face);
|
|
53
|
+
font-size: var(--label-size);
|
|
54
|
+
letter-spacing: var(--label-space);
|
|
55
|
+
text-transform: var(--label-case);
|
|
56
|
+
color: var(--ink-faint);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/* ---- the filter strip ---------------------------------------------------- */
|
|
60
|
+
/* The strip itself is `.kit-tabs`; all this adds is the air under it, because
|
|
61
|
+
the kit's own margin assumes a panel directly beneath and here a table
|
|
62
|
+
follows. */
|
|
63
|
+
.tr-filters { margin: 0 0 var(--sp-sm); }
|
|
64
|
+
/* `.kit-tabs` sets `overflow-x: auto`, which per spec makes the OTHER axis
|
|
65
|
+
`auto` too — and the strip's own `.setup__tab { margin-bottom: -1px }` leaves
|
|
66
|
+
it exactly 1px taller than its box, so a vertical scrollbar appears beside a
|
|
67
|
+
horizontal strip that cannot scroll vertically. It is the shared component's
|
|
68
|
+
defect rather than this page's, and it is not fixed in style.css from here:
|
|
69
|
+
that rule is on every page carrying a tab strip, and quietly changing the
|
|
70
|
+
hall's chrome inside a page's task is how a sheet stops being reviewable.
|
|
71
|
+
Scoped to this page, with the shared fix filed separately. */
|
|
72
|
+
.tr-filters .kit-tabs { overflow-y: hidden; }
|
|
73
|
+
|
|
74
|
+
/* ---- the rows ------------------------------------------------------------ */
|
|
75
|
+
/* The four short columns are pinned and the two prose ones share what is left,
|
|
76
|
+
so the row's SUBJECT — the thought — gets the width instead of losing it to
|
|
77
|
+
an outcome sentence that happens to be long. `width` on a th is a hint under
|
|
78
|
+
`table-layout: auto`, which is what is wanted here: a pinned column still
|
|
79
|
+
gives way rather than clipping when a cell genuinely needs more. */
|
|
80
|
+
.tr-table { table-layout: auto; }
|
|
81
|
+
.tr-table th:nth-child(1) { width: 34%; }
|
|
82
|
+
.tr-table th:nth-child(2) { width: 100px; }
|
|
83
|
+
.tr-table th:nth-child(3) { width: 30%; }
|
|
84
|
+
.tr-table th:nth-child(4) { width: 104px; }
|
|
85
|
+
.tr-table th:nth-child(5) { width: 142px; }
|
|
86
|
+
/* The thought is the row's subject, so it is the one cell that may take the
|
|
87
|
+
width and the one cell whose link reads at body size. */
|
|
88
|
+
.tr-thought a {
|
|
89
|
+
display: inline-block;
|
|
90
|
+
min-height: 24px;
|
|
91
|
+
padding: 3px 0;
|
|
92
|
+
line-height: 18px;
|
|
93
|
+
color: var(--ink);
|
|
94
|
+
border-bottom: var(--line) solid var(--rule);
|
|
95
|
+
}
|
|
96
|
+
.tr-thought a:hover { border-bottom-color: var(--ink); text-decoration: none; }
|
|
97
|
+
.tr-became { font-size: 13.5px; color: var(--ink-soft); }
|
|
98
|
+
.tr-became a {
|
|
99
|
+
display: inline-block;
|
|
100
|
+
min-height: 24px;
|
|
101
|
+
padding: 3px 0;
|
|
102
|
+
line-height: 18px;
|
|
103
|
+
color: var(--ink-soft);
|
|
104
|
+
border-bottom: var(--line) solid var(--rule-soft);
|
|
105
|
+
}
|
|
106
|
+
.tr-became a:hover { color: var(--ink); border-bottom-color: var(--ink); text-decoration: none; }
|
|
107
|
+
.tr-quiet { color: var(--ink-faint); }
|
|
108
|
+
/* The one actionable phrase on the page — a task sitting at backlog inside a
|
|
109
|
+
goal is one promote from claimable — so it is the only thing in a row that
|
|
110
|
+
takes the accent, and it says the word as well as wearing the colour. */
|
|
111
|
+
.tr-nod { color: var(--accent-ink); }
|
|
112
|
+
|
|
113
|
+
/* ---- size ---------------------------------------------------------------- */
|
|
114
|
+
/* Bar and number together, never the bar alone: size is long-tailed and its
|
|
115
|
+
compressed width is a comparison, not a quantity. The direction is explicit
|
|
116
|
+
that the true figure stays available wherever the drawing is. */
|
|
117
|
+
.tr-sizecell { white-space: nowrap; }
|
|
118
|
+
.tr-size { display: inline-flex; align-items: center; gap: 10px; }
|
|
119
|
+
.tr-size__bar {
|
|
120
|
+
display: block;
|
|
121
|
+
flex: none;
|
|
122
|
+
width: 56px;
|
|
123
|
+
height: 3px;
|
|
124
|
+
border-radius: 999px;
|
|
125
|
+
/* The track is the unfilled remainder; the fill is the accent at the server's
|
|
126
|
+
own compressed width. One element, so a row costs no extra box. */
|
|
127
|
+
background:
|
|
128
|
+
linear-gradient(to right, var(--fill, var(--accent)) 0 var(--w, 0%), transparent var(--w, 0%) 100%),
|
|
129
|
+
var(--rule-soft);
|
|
130
|
+
}
|
|
131
|
+
/* Every bit of its size, none of its colour — the remnant's whole picture. See
|
|
132
|
+
thinking.js sizeHtml() for why this is set from the state and not from the
|
|
133
|
+
number. `--ink-faint` and not `--rule`: at the hairline's weight a full-width
|
|
134
|
+
bar stops clearing the 3:1 non-text floor on the dark ground, and this bar is
|
|
135
|
+
the one that must still read as LARGE. */
|
|
136
|
+
.tr-size[data-lit="out"] { --fill: var(--ink-faint); }
|
|
137
|
+
.tr-size__n {
|
|
138
|
+
font-size: 13px;
|
|
139
|
+
font-variant-numeric: tabular-nums;
|
|
140
|
+
color: var(--ink-soft);
|
|
141
|
+
}
|
|
142
|
+
/* A size computed from a descent rather than from payouts that were made. It is
|
|
143
|
+
a footnote, not a warning — the number is real, it just means something
|
|
144
|
+
slightly different, and the title says which. */
|
|
145
|
+
.tr-hist {
|
|
146
|
+
display: block;
|
|
147
|
+
margin-top: 2px;
|
|
148
|
+
font-size: 11.5px;
|
|
149
|
+
color: var(--ink-faint);
|
|
150
|
+
text-decoration: none;
|
|
151
|
+
border-bottom: var(--line) dotted var(--rule);
|
|
152
|
+
cursor: help;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/* ---- the five objects ---------------------------------------------------- */
|
|
156
|
+
/* THE MARK RESTATES THE WORD IN SHAPE. Every object below differs from the
|
|
157
|
+
others by geometry — filled, haloed, ringed, outlined — and not only by tone,
|
|
158
|
+
because a mark distinguished by colour alone tells a colour-blind reader
|
|
159
|
+
nothing. That is the sheet's existing rule for the grade badge and the
|
|
160
|
+
descent's glyph; this is the same rule applied to a vocabulary of five.
|
|
161
|
+
|
|
162
|
+
`--lit` is the server's brightness, between 0 and 1, set per row by
|
|
163
|
+
thinking.js. It rides the star's opacity — and the star's ALONE, because the
|
|
164
|
+
other four objects have no live share to show and dimming them would invent
|
|
165
|
+
one. A star whose brightness could not be READ arrives with --lit: 1 and says
|
|
166
|
+
so in words (idea-objects.js brightnessWord); a full glyph over "still alive
|
|
167
|
+
— unknown" is the honest pair. The floor of 0.35 is a contrast floor: below
|
|
168
|
+
it the mark stops clearing 3:1 against the ground and a dim star becomes an
|
|
169
|
+
absent one, which is the wrong reading entirely — a star is never nothing. */
|
|
170
|
+
.tr-objcell { white-space: nowrap; }
|
|
171
|
+
.tr-obj { display: inline-flex; align-items: flex-start; gap: 10px; }
|
|
172
|
+
.tr-obj__glyph {
|
|
173
|
+
flex: none;
|
|
174
|
+
width: 9px;
|
|
175
|
+
height: 9px;
|
|
176
|
+
margin-top: 5px;
|
|
177
|
+
border-radius: 50%;
|
|
178
|
+
background: var(--ink-faint);
|
|
179
|
+
}
|
|
180
|
+
.tr-obj__body { display: grid; gap: 2px; min-width: 0; }
|
|
181
|
+
.tr-obj__label { font-size: 13.5px; color: var(--ink); }
|
|
182
|
+
.tr-obj__sub { font-size: 12px; color: var(--ink-faint); }
|
|
183
|
+
|
|
184
|
+
/* star — filled, accent, dimmed by its live share. */
|
|
185
|
+
.tr-obj[data-object="star"] .tr-obj__glyph {
|
|
186
|
+
background: var(--accent);
|
|
187
|
+
opacity: max(0.35, var(--lit, 1));
|
|
188
|
+
}
|
|
189
|
+
/* protostar — small and haloed: matter gathering, not yet burning. The halo is
|
|
190
|
+
a ring of the accent mixed back into the ground, so it reads as glow rather
|
|
191
|
+
than as a second border. */
|
|
192
|
+
.tr-obj[data-object="protostar"] .tr-obj__glyph {
|
|
193
|
+
width: 7px;
|
|
194
|
+
height: 7px;
|
|
195
|
+
margin-top: 6px;
|
|
196
|
+
background: var(--ink-soft);
|
|
197
|
+
box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 18%, transparent);
|
|
198
|
+
}
|
|
199
|
+
/* satellite — a small body with an orbit around it, detached from the mark so
|
|
200
|
+
it reads as something going round rather than as a thick edge. */
|
|
201
|
+
.tr-obj[data-object="satellite"] .tr-obj__glyph {
|
|
202
|
+
width: 6px;
|
|
203
|
+
height: 6px;
|
|
204
|
+
margin-top: 6px;
|
|
205
|
+
background: var(--ink-soft);
|
|
206
|
+
outline: var(--line) solid var(--rule);
|
|
207
|
+
outline-offset: 4px;
|
|
208
|
+
}
|
|
209
|
+
/* remnant — the hollow ring, and the largest mark of the five. A thought that
|
|
210
|
+
caused a great deal of work the project then tore out renders LARGE and DEAD:
|
|
211
|
+
that is the whole reason size and brightness are two channels, so the object
|
|
212
|
+
that carries it must not be the quietest thing in the column. `--ink-faint`
|
|
213
|
+
and not `--rule`: at the hairline's weight this measured under the 3:1
|
|
214
|
+
non-text floor on the dark ground, the same finding the descent's "out" glyph
|
|
215
|
+
recorded. */
|
|
216
|
+
.tr-obj[data-object="remnant"] .tr-obj__glyph {
|
|
217
|
+
width: 12px;
|
|
218
|
+
height: 12px;
|
|
219
|
+
margin-top: 4px;
|
|
220
|
+
background: transparent;
|
|
221
|
+
box-shadow: inset 0 0 0 1.5px var(--ink-faint);
|
|
222
|
+
}
|
|
223
|
+
/* cold body — the smallest mark there is, a dark point with a hairline edge. It
|
|
224
|
+
never ignited, so it has no size at all, and the mark says that by being the
|
|
225
|
+
one object with nothing inside it and nothing around it. */
|
|
226
|
+
.tr-obj[data-object="cold-body"] .tr-obj__glyph {
|
|
227
|
+
width: 6px;
|
|
228
|
+
height: 6px;
|
|
229
|
+
margin-top: 6px;
|
|
230
|
+
background: var(--surface-2);
|
|
231
|
+
box-shadow: inset 0 0 0 var(--line) var(--ink-faint);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/* ---- notes + the empty state --------------------------------------------- */
|
|
235
|
+
.tr-note { font-size: 13.5px; color: var(--ink-faint); margin: 0; }
|
|
236
|
+
.tr-empty {
|
|
237
|
+
margin: 0;
|
|
238
|
+
padding: var(--sp-md) 0;
|
|
239
|
+
font-size: 14px;
|
|
240
|
+
color: var(--ink-soft);
|
|
241
|
+
max-width: var(--measure);
|
|
242
|
+
}
|
|
243
|
+
.tr-foot {
|
|
244
|
+
margin: var(--sp-md) 0 0;
|
|
245
|
+
font-size: 13px;
|
|
246
|
+
color: var(--ink-faint);
|
|
247
|
+
max-width: var(--measure);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/* ---- the phone ----------------------------------------------------------- */
|
|
251
|
+
/* Nothing below widens the document — the page never scrolls sideways, and the
|
|
252
|
+
restacking here is what makes that true without leaning on the shell's strip
|
|
253
|
+
at all. */
|
|
254
|
+
@media (max-width: 640px) {
|
|
255
|
+
.tr-fig__n { font-size: 26px; }
|
|
256
|
+
/* THE TABLE STOPS BEING A TABLE. The shell would give it a horizontal strip
|
|
257
|
+
(`:has(> .ledger)`) and the page would still measure clean — but five
|
|
258
|
+
columns inside a 390px strip is a table nobody can read: the thought column
|
|
259
|
+
collapses to one word per line while the object scrolls off the right, so
|
|
260
|
+
the row's two most important facts end up on opposite sides of a gesture.
|
|
261
|
+
A strip is the right answer for a ledger whose columns are a grid of
|
|
262
|
+
numbers; this one is a sentence plus three facts about it, and those stack.
|
|
263
|
+
The row becomes one flex line-box: the thought takes the width, and filed,
|
|
264
|
+
size and object run under it. */
|
|
265
|
+
.tr-table,
|
|
266
|
+
.tr-table tbody,
|
|
267
|
+
.tr-table td { display: block; width: auto; }
|
|
268
|
+
.tr-table thead { display: none; }
|
|
269
|
+
.tr-table tr {
|
|
270
|
+
display: flex;
|
|
271
|
+
flex-wrap: wrap;
|
|
272
|
+
align-items: baseline;
|
|
273
|
+
gap: 6px 16px;
|
|
274
|
+
padding: 14px 0;
|
|
275
|
+
border-bottom: 1px solid var(--rule-soft);
|
|
276
|
+
}
|
|
277
|
+
.tr-table tr:last-child { border-bottom: 0; }
|
|
278
|
+
.tr-table td { padding: 0; border: 0; }
|
|
279
|
+
.tr-table .tr-thought { flex-basis: 100%; font-size: 15px; }
|
|
280
|
+
/* Dropped on a phone: the outcome prose, the longest cell in the row and the
|
|
281
|
+
only one the idea's own record — one tap away on the title — states in
|
|
282
|
+
full. Size and object stay, because they are the two facts this page exists
|
|
283
|
+
for and the two the record does not put side by side. */
|
|
284
|
+
.tr-table .tr-became { display: none; }
|
|
285
|
+
.tr-obj__sub { white-space: normal; }
|
|
286
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<title>Your thinking — {{worldName}}</title>
|
|
7
|
+
<meta name="description" content="Everything you filed and what became of it: what it became, how much work it caused, and whether that work is still alive.">
|
|
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
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
10
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
11
|
+
<link rel="stylesheet" href="/builders/style.css?v=2026-07-02-shell1">
|
|
12
|
+
<link rel="stylesheet" href="/builders/thinking.css">
|
|
13
|
+
</head>
|
|
14
|
+
<!-- THE PAGE THE SPEC CALLS "THE ROOM" (task 1004098 / BV2.R03). The file is
|
|
15
|
+
`thinking` and not `room` because `room.css` is already taken, by the hall's
|
|
16
|
+
READING-ROOM archetype (the primer, diagrams, drachmae — task 1003306,
|
|
17
|
+
ADR 0228), and `board-room` is the government surface. Three unrelated
|
|
18
|
+
rooms in one directory is a collision waiting to be made by whoever next
|
|
19
|
+
links a sheet into a page; the page's own h1 is the design's phrase, so
|
|
20
|
+
nothing about the vocabulary is lost by naming the file after it. -->
|
|
21
|
+
<body data-page="thinking" data-page-title="Your thinking">
|
|
22
|
+
|
|
23
|
+
<div class="app">
|
|
24
|
+
<aside class="app-sidebar" id="app-sidebar" aria-label="Primary"></aside>
|
|
25
|
+
<div class="app-scrim" id="app-scrim" hidden></div>
|
|
26
|
+
<div class="app-body">
|
|
27
|
+
<header class="app-topbar" id="app-topbar"></header>
|
|
28
|
+
<div class="app-content">
|
|
29
|
+
<!-- The LABEL voice, like every other working surface: the page's own name
|
|
30
|
+
is the least interesting thing on it (modules/hall-ui/CLAUDE.md, the
|
|
31
|
+
two page-head voices). The room is a working surface, not a document,
|
|
32
|
+
so it takes the board's head and not the reading room's. -->
|
|
33
|
+
<div class="page-head page-head--board">
|
|
34
|
+
<h1 class="page-head__h">Your thinking</h1>
|
|
35
|
+
<p class="page-head__sub" id="tr-sub">Loading what you filed…</p>
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
<main id="hall-main">
|
|
39
|
+
<section class="scroll" id="tr-scroll" aria-labelledby="tr-h">
|
|
40
|
+
<h2 id="tr-h" class="scroll__h">What you filed, and what became of it</h2>
|
|
41
|
+
<p class="scroll__lede">
|
|
42
|
+
Your own view of your own thinking. Size is the work a thought caused and
|
|
43
|
+
never falls; brightness is how much of that work is still alive — that is
|
|
44
|
+
the part that can go out.
|
|
45
|
+
</p>
|
|
46
|
+
|
|
47
|
+
<!-- The figures, the filters and the rows are all written by
|
|
48
|
+
thinking.js from ONE read, so nothing here can be a second copy of
|
|
49
|
+
a number the server already computed. -->
|
|
50
|
+
<div id="tr-figs" class="tr-figs" role="status" aria-live="polite"></div>
|
|
51
|
+
<div id="tr-filters" class="tr-filters" role="group" aria-label="Show only"></div>
|
|
52
|
+
<div id="tr-body"><p class="tr-note">Loading…</p></div>
|
|
53
|
+
<p class="tr-foot" id="tr-foot" hidden></p>
|
|
54
|
+
</section>
|
|
55
|
+
</main>
|
|
56
|
+
|
|
57
|
+
<footer class="app-foot" id="app-foot"></footer>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
63
|
+
|
|
64
|
+
<script src="/builders/shell.js?v=2026-09-20-room1"></script>
|
|
65
|
+
<script src="/builders/palette.js" defer></script>
|
|
66
|
+
<script src="/builders/dom-utils.js?v=2026-06-23-contrib"></script>
|
|
67
|
+
<!-- The filter strip is the kit's tab strip (makeTabs) rather than a fifth
|
|
68
|
+
hand-rolled pill row: it already carries the count pills, the hash sync and
|
|
69
|
+
the narrow-screen scroller this page would otherwise reinvent. -->
|
|
70
|
+
<script src="/builders/hall-kit.js"></script>
|
|
71
|
+
<script src="/builders/idea-objects.js?v=2026-09-20-r03"></script>
|
|
72
|
+
<script src="/builders/thinking.js?v=2026-09-20-r03"></script>
|
|
73
|
+
</body>
|
|
74
|
+
</html>
|