@bongos/core 1.19.449 → 1.19.451
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 +59 -29
- package/docs/copy-inventory.md +67 -71
- package/docs/copy-registry.json +135 -221
- package/docs/file-map.md +1 -1
- package/docs/module-api-changelog.md +4 -0
- package/modules/hall-ui/public/diagram-viewer.css +51 -34
- package/modules/hall-ui/public/diagram-viewer.js +4 -1
- package/modules/hall-ui/public/diagrams.css +45 -0
- package/modules/hall-ui/public/diagrams.html +12 -20
- package/modules/hall-ui/public/diagrams.states.json +28 -0
- package/modules/hall-ui/public/primer.css +92 -400
- package/modules/hall-ui/public/primer.html +68 -26
- package/modules/hall-ui/public/primer.js +107 -308
- package/modules/hall-ui/public/primer.states.json +38 -0
- package/modules/hall-ui/public/ranks.html +9 -1
- package/modules/hall-ui/public/ranks.states.json +1 -1
- package/modules/hall-ui/public/roadmap.css +152 -86
- package/modules/hall-ui/public/roadmap.html +6 -1
- package/modules/hall-ui/public/roadmap.states.json +31 -0
- package/modules/hall-ui/public/room.css +441 -0
- package/modules/hall-ui/public/style.css +96 -24
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/scripts/gds/land-watch.js +28 -9
- package/scripts/hall-preview/server.js +29 -0
- package/src/module-api.js +1 -1
- package/tests/hall_audit.mjs +14 -10
- package/tests/hall_reading_world.mjs +430 -0
- package/tests/land_watch.mjs +48 -3
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
/* room.css — the READING-ROOM archetype: a long document read end to end
|
|
2
|
+
(task 1003306, goal 1000081). Shared by the primer (primer.html) and the
|
|
3
|
+
diagrams index (diagrams.html).
|
|
4
|
+
|
|
5
|
+
THE ARCHETYPE is v3 "the glass hall", the owner's pick from the composition
|
|
6
|
+
round — docs/design/hall-direction-v2.md §6, mock
|
|
7
|
+
docs/design/mocks/hall/reading/v3.html. Reading order, top to bottom: a
|
|
8
|
+
progress hairline under the topbar; the room's name alone over the ground
|
|
9
|
+
(the shell's .page-head--room); then a GLASS table of contents beside a
|
|
10
|
+
--bg-card article card. The glass/card split is the composition's argument:
|
|
11
|
+
wayfinding is chrome and belongs to the same material as the rail and the
|
|
12
|
+
topbar, the document is content and belongs on a panel the ground can never
|
|
13
|
+
reach the ink on.
|
|
14
|
+
|
|
15
|
+
WHY IT IS ITS OWN SHEET rather than more of primer.css: the primer and the
|
|
16
|
+
diagrams index are the same room over different documents — one renders
|
|
17
|
+
markdown, one renders five figures — and the framed figure is literally the
|
|
18
|
+
same object on both (diagram-viewer.js upgrades `figure.diagram img,
|
|
19
|
+
figure.primer-figure img` with one selector). Ranks, Economy, Repo Atlas and
|
|
20
|
+
Modules inherit this archetype next. Page-specific shapes stay page-local:
|
|
21
|
+
primer.css keeps the acknowledge gate, diagrams.css keeps the legend strip.
|
|
22
|
+
|
|
23
|
+
WHY THE CLASSES ARE STILL `primer-`: two live surfaces spell them —
|
|
24
|
+
diagram-viewer.js's upgrade selector and tests/hall_audit.mjs's pinned
|
|
25
|
+
phone-overflow rule — so the sheet is named for the ROOM and the prefix is
|
|
26
|
+
left alone. Renaming would churn a JS selector and a pinned test to buy a
|
|
27
|
+
reader nothing.
|
|
28
|
+
|
|
29
|
+
THE PANEL IS THE SHELL'S. The article, the failure notes and the skeleton all
|
|
30
|
+
carry `.scroll` in their markup and this sheet only adds the reading padding:
|
|
31
|
+
v3 has exactly three card levels and a fourth is a design decision, not a
|
|
32
|
+
local override (modules/hall-ui/CLAUDE.md, Hard rules).
|
|
33
|
+
|
|
34
|
+
Everything below spends the world's real token names. No compat alias
|
|
35
|
+
(--surface / --surface-2 / --border / --border-strong / --accent-weak /
|
|
36
|
+
--accent-text) appears here — they exist for pages nobody has re-skinned, so
|
|
37
|
+
spending one is legal CSS that quietly opts this sheet back out of the world.
|
|
38
|
+
`--line` is a WIDTH; the hairline's colour is --rule / --rule-soft. */
|
|
39
|
+
|
|
40
|
+
/* ---- the room's composition tokens ---------------------------------------
|
|
41
|
+
On `body`, never in a page `:root`: the branding pack's :root is spliced at
|
|
42
|
+
the end of <head> at (0,1,0), so a page-local one is outranked one way and
|
|
43
|
+
defeats re-branding the other.
|
|
44
|
+
--measure is NOT redeclared. It is the shell's measured 48ch, and a `ch`
|
|
45
|
+
scales with the font size — so the same token renders the same ~60 characters
|
|
46
|
+
whether the room reads at 15px or 17px. Re-deriving it per page size is the
|
|
47
|
+
`ch` arithmetic that put 90 characters on this page in the first place. */
|
|
48
|
+
body.room {
|
|
49
|
+
--room-gap: var(--sp-lg);
|
|
50
|
+
--room-toc-w: 246px;
|
|
51
|
+
--room-pad: clamp(24px, 3.4vw, 58px);
|
|
52
|
+
--room-size: 17px;
|
|
53
|
+
--room-lead: 1.75;
|
|
54
|
+
--room-h2: clamp(24px, 2.8vw, 34px);
|
|
55
|
+
--room-h3: 20px;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/* ---- 1. the reading hairline --------------------------------------------
|
|
59
|
+
Sticky rather than fixed: it belongs to the content column, so it scrolls out
|
|
60
|
+
of the way with the head instead of hovering over the whole viewport. Under
|
|
61
|
+
the topbar in the z ladder (--z-progress < --z-topbar) for the same reason —
|
|
62
|
+
it is the article's progress, not app chrome. */
|
|
63
|
+
.primer-progress {
|
|
64
|
+
position: sticky;
|
|
65
|
+
top: var(--topbar-h);
|
|
66
|
+
z-index: var(--z-progress);
|
|
67
|
+
height: 3px;
|
|
68
|
+
background: color-mix(in srgb, var(--accent) 14%, transparent);
|
|
69
|
+
pointer-events: none;
|
|
70
|
+
}
|
|
71
|
+
.primer-progress__bar {
|
|
72
|
+
height: 100%;
|
|
73
|
+
width: 0;
|
|
74
|
+
background: var(--accent);
|
|
75
|
+
transition: width 200ms cubic-bezier(.2, .7, .3, 1);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/* ---- 2. the reading column ----------------------------------------------
|
|
79
|
+
ONE ceiling for the room, on the room's own body scope. --content-max (1120)
|
|
80
|
+
is a working surface's width; a document read at it is more empty ground than
|
|
81
|
+
page. The cap sits on the room's main rather than on each page's wrapper so
|
|
82
|
+
the primer's two columns and the diagrams index's stacked figures end at the
|
|
83
|
+
same edge — a reading room that changes width between its own pages reads as
|
|
84
|
+
two different rooms.
|
|
85
|
+
This is the room's own composition, not a shell override: it is scoped to the
|
|
86
|
+
body class a page opts into, and it sets a measure, not shell layout (the
|
|
87
|
+
rule tests/hall_record_world.mjs pins is `.app-content > main`, which reaches
|
|
88
|
+
into the shell's grid for every page at once). */
|
|
89
|
+
body.room #hall-main,
|
|
90
|
+
body.room .page-head { max-width: var(--room-max); }
|
|
91
|
+
|
|
92
|
+
.primer-layout {
|
|
93
|
+
display: grid;
|
|
94
|
+
grid-template-columns: var(--room-toc-w) minmax(0, 1fr);
|
|
95
|
+
gap: var(--room-gap);
|
|
96
|
+
align-items: start;
|
|
97
|
+
padding-bottom: var(--sp-md);
|
|
98
|
+
}
|
|
99
|
+
/* the article column, so the notes, the skeleton and the gate stack under the
|
|
100
|
+
card rather than beside the contents */
|
|
101
|
+
.primer-col { min-width: 0; }
|
|
102
|
+
|
|
103
|
+
/* ---- 3. the table of contents, as glass ---------------------------------- */
|
|
104
|
+
|
|
105
|
+
.primer-toc {
|
|
106
|
+
position: sticky;
|
|
107
|
+
top: calc(var(--topbar-h) + var(--sp-md));
|
|
108
|
+
align-self: start;
|
|
109
|
+
}
|
|
110
|
+
.primer-toc__toggle {
|
|
111
|
+
display: none;
|
|
112
|
+
width: 100%;
|
|
113
|
+
align-items: center;
|
|
114
|
+
justify-content: space-between;
|
|
115
|
+
gap: 8px;
|
|
116
|
+
min-height: 44px;
|
|
117
|
+
padding: 8px 16px;
|
|
118
|
+
background: var(--glass);
|
|
119
|
+
-webkit-backdrop-filter: blur(var(--glass-blur));
|
|
120
|
+
backdrop-filter: blur(var(--glass-blur));
|
|
121
|
+
border: var(--line) solid var(--glass-edge);
|
|
122
|
+
border-radius: var(--radius);
|
|
123
|
+
font-family: var(--font-body);
|
|
124
|
+
font-size: 14.5px;
|
|
125
|
+
color: var(--ink);
|
|
126
|
+
cursor: pointer;
|
|
127
|
+
}
|
|
128
|
+
.primer-toc__chevron { transition: transform 200ms cubic-bezier(.2, .7, .3, 1); }
|
|
129
|
+
.primer-toc__toggle[aria-expanded="true"] .primer-toc__chevron { transform: rotate(180deg); }
|
|
130
|
+
.primer-toc__inner {
|
|
131
|
+
background: var(--glass);
|
|
132
|
+
-webkit-backdrop-filter: blur(var(--glass-blur));
|
|
133
|
+
backdrop-filter: blur(var(--glass-blur));
|
|
134
|
+
border: var(--line) solid var(--glass-edge);
|
|
135
|
+
border-radius: var(--radius);
|
|
136
|
+
padding: var(--sp-md) var(--sp-sm) var(--sp-sm);
|
|
137
|
+
}
|
|
138
|
+
.primer-toc__heading {
|
|
139
|
+
margin: 0 0 var(--sp-sm);
|
|
140
|
+
padding: 0 var(--sp-xs);
|
|
141
|
+
font-family: var(--label-face);
|
|
142
|
+
font-size: var(--label-size);
|
|
143
|
+
font-weight: 400;
|
|
144
|
+
letter-spacing: var(--label-space);
|
|
145
|
+
text-transform: var(--label-case);
|
|
146
|
+
color: var(--ink-faint);
|
|
147
|
+
}
|
|
148
|
+
.primer-toc__list { list-style: none; margin: 0; padding: 0; counter-reset: toc; }
|
|
149
|
+
.primer-toc__list li { margin: 0; }
|
|
150
|
+
/* the numeral is a two-digit mono column, so a long list never re-spaces around
|
|
151
|
+
its tenth row the way an upper-roman VIII did */
|
|
152
|
+
.primer-toc__list a {
|
|
153
|
+
display: flex;
|
|
154
|
+
align-items: baseline;
|
|
155
|
+
gap: 11px;
|
|
156
|
+
min-height: 34px;
|
|
157
|
+
padding: 8px var(--sp-xs);
|
|
158
|
+
border-left: 2px solid transparent;
|
|
159
|
+
border-radius: var(--radius-sm);
|
|
160
|
+
font-size: 14px;
|
|
161
|
+
line-height: 1.4;
|
|
162
|
+
color: var(--ink-soft);
|
|
163
|
+
text-decoration: none;
|
|
164
|
+
transition: color 200ms cubic-bezier(.2, .7, .3, 1);
|
|
165
|
+
}
|
|
166
|
+
.primer-toc__list a::before {
|
|
167
|
+
counter-increment: toc;
|
|
168
|
+
content: counter(toc, decimal-leading-zero);
|
|
169
|
+
flex: none;
|
|
170
|
+
font: 400 11px/1.4 var(--font-mono);
|
|
171
|
+
font-variant-numeric: tabular-nums;
|
|
172
|
+
color: var(--ink-faint);
|
|
173
|
+
}
|
|
174
|
+
.primer-toc__list a:hover { color: var(--ink); text-decoration: none; }
|
|
175
|
+
.primer-toc__list a.is-active {
|
|
176
|
+
color: var(--ink);
|
|
177
|
+
background: var(--glass-strong);
|
|
178
|
+
border-left-color: var(--accent);
|
|
179
|
+
border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
|
|
180
|
+
}
|
|
181
|
+
.primer-toc__list a.is-active::before { color: var(--ink-soft); }
|
|
182
|
+
.primer-toc__placeholder {
|
|
183
|
+
padding: 8px var(--sp-xs);
|
|
184
|
+
font-size: 14px;
|
|
185
|
+
color: var(--ink-faint);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/* ---- 4. the article ------------------------------------------------------
|
|
189
|
+
The card itself is `.scroll`; this is the reading pad and the rhythm. */
|
|
190
|
+
|
|
191
|
+
.primer-article {
|
|
192
|
+
padding: var(--room-pad);
|
|
193
|
+
margin: 0;
|
|
194
|
+
counter-reset: sec;
|
|
195
|
+
font-size: var(--room-size);
|
|
196
|
+
line-height: var(--room-lead);
|
|
197
|
+
color: var(--ink);
|
|
198
|
+
}
|
|
199
|
+
/* PROSE is measured; a table, a figure and a code block may take the whole card,
|
|
200
|
+
and that width is the only reason the card is wider than the measure. */
|
|
201
|
+
.primer-article > p,
|
|
202
|
+
.primer-article > ul,
|
|
203
|
+
.primer-article > ol,
|
|
204
|
+
.primer-article > blockquote,
|
|
205
|
+
.primer-article > h2,
|
|
206
|
+
.primer-article > h3 { max-width: var(--measure); }
|
|
207
|
+
|
|
208
|
+
/* the document's own h1 is suppressed — the page head already names the room,
|
|
209
|
+
and a second h1 in <main> fails the one-header-main-h1 floor outright */
|
|
210
|
+
.primer-article h1 { display: none; }
|
|
211
|
+
|
|
212
|
+
.primer-article h2 {
|
|
213
|
+
margin: calc(var(--sp-xl) * 1.4) 0 var(--sp-md);
|
|
214
|
+
font-family: var(--font-display);
|
|
215
|
+
font-weight: 300;
|
|
216
|
+
font-size: var(--room-h2);
|
|
217
|
+
line-height: 1.06;
|
|
218
|
+
letter-spacing: -0.035em;
|
|
219
|
+
color: var(--ink);
|
|
220
|
+
/* anchor jumps land below the sticky top bar AND its hairline */
|
|
221
|
+
scroll-margin-top: calc(var(--topbar-h) + 28px);
|
|
222
|
+
}
|
|
223
|
+
/* the section number sits above the headline rather than beside it, so a long
|
|
224
|
+
title stays one uninterrupted shape at every width */
|
|
225
|
+
.primer-article h2::before {
|
|
226
|
+
counter-increment: sec;
|
|
227
|
+
content: counter(sec, decimal-leading-zero);
|
|
228
|
+
display: block;
|
|
229
|
+
margin-bottom: 14px;
|
|
230
|
+
font-family: var(--label-face);
|
|
231
|
+
font-size: var(--label-size);
|
|
232
|
+
letter-spacing: var(--label-space);
|
|
233
|
+
font-variant-numeric: tabular-nums;
|
|
234
|
+
color: var(--ink-faint);
|
|
235
|
+
}
|
|
236
|
+
.primer-article > h2:first-child { margin-top: 0; }
|
|
237
|
+
.primer-article h3 {
|
|
238
|
+
margin: var(--sp-lg) 0 var(--sp-xs);
|
|
239
|
+
font-family: var(--font-display);
|
|
240
|
+
font-weight: 400;
|
|
241
|
+
font-size: var(--room-h3);
|
|
242
|
+
letter-spacing: -0.02em;
|
|
243
|
+
color: var(--ink);
|
|
244
|
+
scroll-margin-top: calc(var(--topbar-h) + 28px);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
.primer-article p { margin: 0 0 var(--sp-md); }
|
|
248
|
+
.primer-article p:last-child { margin-bottom: 0; }
|
|
249
|
+
/* the subtitle line at the very top of the document */
|
|
250
|
+
.primer-article > p > em:only-child { color: var(--ink-soft); }
|
|
251
|
+
|
|
252
|
+
.primer-article ul, .primer-article ol { margin: 0 0 var(--sp-lg); padding-left: 1.4em; }
|
|
253
|
+
.primer-article li { margin: 0 0 12px; }
|
|
254
|
+
.primer-article li:last-child { margin-bottom: 0; }
|
|
255
|
+
.primer-article li::marker { color: var(--ink-faint); }
|
|
256
|
+
|
|
257
|
+
/* 1px of vertical padding takes an inline link past the 24px floor without
|
|
258
|
+
costing the line its own leading (the .scroll__lede precedent, task 1003304) */
|
|
259
|
+
.primer-article a {
|
|
260
|
+
display: inline-block;
|
|
261
|
+
min-height: 24px;
|
|
262
|
+
padding: 1px 0;
|
|
263
|
+
color: var(--accent-ink);
|
|
264
|
+
text-decoration: underline;
|
|
265
|
+
text-underline-offset: 4px;
|
|
266
|
+
text-decoration-thickness: 1px;
|
|
267
|
+
}
|
|
268
|
+
.primer-article a:hover { color: var(--ink); }
|
|
269
|
+
.primer-article strong { font-weight: 600; color: var(--ink); }
|
|
270
|
+
.primer-article em { font-style: italic; }
|
|
271
|
+
|
|
272
|
+
.primer-article code {
|
|
273
|
+
font: 400 .85em/1.4 var(--font-mono);
|
|
274
|
+
background: var(--glass);
|
|
275
|
+
padding: 2px 6px;
|
|
276
|
+
border-radius: 4px;
|
|
277
|
+
}
|
|
278
|
+
.primer-article pre {
|
|
279
|
+
margin: 0 0 var(--sp-lg);
|
|
280
|
+
padding: var(--sp-md) var(--sp-lg);
|
|
281
|
+
overflow-x: auto;
|
|
282
|
+
background: var(--glass);
|
|
283
|
+
border: var(--line) solid var(--glass-edge);
|
|
284
|
+
border-radius: var(--radius);
|
|
285
|
+
}
|
|
286
|
+
.primer-article pre code {
|
|
287
|
+
background: none;
|
|
288
|
+
padding: 0;
|
|
289
|
+
border-radius: 0;
|
|
290
|
+
font-size: 13.5px;
|
|
291
|
+
line-height: 1.8;
|
|
292
|
+
color: var(--ink-soft);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/* blockquotes only render since task 1003306 unified the two markdown parsers —
|
|
296
|
+
primer.js had no blockquote rule at all and md-reader.js has always emitted
|
|
297
|
+
them, so the primer silently dropped every aside into a paragraph. */
|
|
298
|
+
.primer-article blockquote {
|
|
299
|
+
margin: var(--sp-lg) 0;
|
|
300
|
+
padding: var(--sp-md) var(--sp-lg);
|
|
301
|
+
background: var(--glass);
|
|
302
|
+
border: var(--line) solid var(--glass-edge);
|
|
303
|
+
border-left: 2px solid var(--rule);
|
|
304
|
+
border-radius: 0 var(--radius) var(--radius) 0;
|
|
305
|
+
color: var(--ink-soft);
|
|
306
|
+
}
|
|
307
|
+
.primer-article blockquote p { margin: 0; max-width: var(--measure); }
|
|
308
|
+
|
|
309
|
+
.primer-article hr {
|
|
310
|
+
border: none;
|
|
311
|
+
border-top: var(--line) solid var(--rule-soft);
|
|
312
|
+
margin: var(--sp-xl) 0;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
.primer-article table {
|
|
316
|
+
width: 100%;
|
|
317
|
+
border-collapse: collapse;
|
|
318
|
+
margin: 0 0 var(--sp-lg);
|
|
319
|
+
font-size: 14.5px;
|
|
320
|
+
font-variant-numeric: tabular-nums;
|
|
321
|
+
}
|
|
322
|
+
.primer-article th, .primer-article td {
|
|
323
|
+
text-align: left;
|
|
324
|
+
vertical-align: top;
|
|
325
|
+
padding: 13px 16px 13px 0;
|
|
326
|
+
border-bottom: var(--line) solid var(--rule-soft);
|
|
327
|
+
}
|
|
328
|
+
.primer-article th {
|
|
329
|
+
font-family: var(--label-face);
|
|
330
|
+
font-size: var(--label-size);
|
|
331
|
+
font-weight: 400;
|
|
332
|
+
letter-spacing: var(--label-space);
|
|
333
|
+
text-transform: var(--label-case);
|
|
334
|
+
color: var(--ink-faint);
|
|
335
|
+
}
|
|
336
|
+
.primer-article tr:last-child td { border-bottom: 0; }
|
|
337
|
+
|
|
338
|
+
/* ---- 5. the framed figure ------------------------------------------------
|
|
339
|
+
ONE rule, both rooms: diagram-viewer.js upgrades `figure.diagram img,
|
|
340
|
+
figure.primer-figure img` into a pannable canvas, and until (or unless) the
|
|
341
|
+
SVG fetch succeeds the PNG stays in this frame. Glass rather than a card, so
|
|
342
|
+
a figure inside the article reads as inset and a figure on the diagrams index
|
|
343
|
+
reads as the same object. */
|
|
344
|
+
.primer-figure, figure.diagram {
|
|
345
|
+
margin: var(--sp-xl) 0;
|
|
346
|
+
padding: var(--sp-lg) var(--sp-md);
|
|
347
|
+
background: var(--glass);
|
|
348
|
+
border: var(--line) solid var(--glass-edge);
|
|
349
|
+
border-radius: var(--radius);
|
|
350
|
+
}
|
|
351
|
+
.primer-figure:last-child, figure.diagram:last-child { margin-bottom: 0; }
|
|
352
|
+
.primer-figure img, figure.diagram img {
|
|
353
|
+
display: block;
|
|
354
|
+
width: 100%;
|
|
355
|
+
max-width: 100%;
|
|
356
|
+
height: auto;
|
|
357
|
+
}
|
|
358
|
+
/* diagram-viewer.js inserts its canvas INSIDE the figure and hides the <img>,
|
|
359
|
+
so the frame has to belong to exactly one of them or the diagram ends up in
|
|
360
|
+
two nested boxes. The figure keeps it; the canvas gives its own up. (Its
|
|
361
|
+
fullscreen state re-declares both, and diagram-viewer.css loads after this
|
|
362
|
+
sheet on both pages, so the overlay still paints.) */
|
|
363
|
+
.primer-figure .dgv, figure.diagram .dgv {
|
|
364
|
+
background: none;
|
|
365
|
+
border: 0;
|
|
366
|
+
border-radius: var(--radius-sm);
|
|
367
|
+
}
|
|
368
|
+
.primer-figure figcaption, figure.diagram figcaption {
|
|
369
|
+
margin-top: 14px;
|
|
370
|
+
max-width: var(--measure);
|
|
371
|
+
font-size: 13.5px;
|
|
372
|
+
line-height: 1.55;
|
|
373
|
+
color: var(--ink-faint);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/* ---- 6. the states before the document ----------------------------------
|
|
377
|
+
Each is the same card the article is, so the page never changes shape as it
|
|
378
|
+
resolves — the skeleton is the article's silhouette, not a spinner. */
|
|
379
|
+
|
|
380
|
+
.primer-note, .primer-skeleton { padding: var(--room-pad); }
|
|
381
|
+
.primer-note__label {
|
|
382
|
+
margin: 0 0 14px;
|
|
383
|
+
font-family: var(--label-face);
|
|
384
|
+
font-size: var(--label-size);
|
|
385
|
+
letter-spacing: var(--label-space);
|
|
386
|
+
text-transform: var(--label-case);
|
|
387
|
+
color: var(--ink-faint);
|
|
388
|
+
}
|
|
389
|
+
.primer-note--error .primer-note__label { color: var(--danger); }
|
|
390
|
+
.primer-note__body { margin: 0 0 var(--sp-lg); max-width: var(--measure); color: var(--ink-soft); }
|
|
391
|
+
.primer-note__body:last-child { margin-bottom: 0; }
|
|
392
|
+
.primer-note__acts { display: flex; flex-wrap: wrap; gap: var(--sp-xs); margin: 0; }
|
|
393
|
+
|
|
394
|
+
.primer-sk {
|
|
395
|
+
display: block;
|
|
396
|
+
height: 10px;
|
|
397
|
+
border-radius: 4px;
|
|
398
|
+
background: var(--skeleton);
|
|
399
|
+
}
|
|
400
|
+
.primer-skeleton__h { height: 28px; width: 58%; margin-bottom: var(--sp-lg); }
|
|
401
|
+
.primer-skeleton__p { margin-bottom: var(--sp-lg); max-width: var(--measure); }
|
|
402
|
+
.primer-skeleton__p .primer-sk { margin-bottom: 15px; }
|
|
403
|
+
.primer-skeleton__p .primer-sk:nth-child(2) { width: 96%; }
|
|
404
|
+
.primer-skeleton__p .primer-sk:nth-child(3) { width: 99%; }
|
|
405
|
+
.primer-skeleton__p .primer-sk:nth-child(4) { width: 84%; }
|
|
406
|
+
.primer-skeleton__p .primer-sk:last-child { width: 46%; margin-bottom: 0; }
|
|
407
|
+
.primer-skeleton__rule {
|
|
408
|
+
height: var(--line);
|
|
409
|
+
margin: var(--sp-xl) 0 var(--sp-lg);
|
|
410
|
+
background: var(--rule-soft);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/* ---- 7. the room's one breakpoint ---------------------------------------
|
|
414
|
+
760px, NOT the shell's 640: it is the width primer.js's matchMedia mirrors
|
|
415
|
+
and tests/hall_audit.mjs pins exactly. Narrowing it "for consistency" would
|
|
416
|
+
silently reopen the 641-760px band the table's scrollport exists to cover. */
|
|
417
|
+
@media (max-width: 760px) {
|
|
418
|
+
body.room {
|
|
419
|
+
--room-gap: 0px;
|
|
420
|
+
--room-pad: 20px;
|
|
421
|
+
--room-size: 16.5px;
|
|
422
|
+
--room-lead: 1.7;
|
|
423
|
+
--room-h2: 24px;
|
|
424
|
+
}
|
|
425
|
+
.primer-layout { grid-template-columns: minmax(0, 1fr); }
|
|
426
|
+
.primer-toc { position: static; margin-bottom: var(--sp-sm); }
|
|
427
|
+
.primer-toc__toggle { display: flex; }
|
|
428
|
+
.primer-toc__inner { display: none; margin-top: 8px; }
|
|
429
|
+
.primer-toc.is-open .primer-toc__inner { display: block; }
|
|
430
|
+
/* A markdown table's column count is fixed by its source, so its min-content
|
|
431
|
+
width outruns a phone (measured: 79px of page overflow on /drachmae). Give
|
|
432
|
+
the table its own horizontal scroller instead of letting it drag the page
|
|
433
|
+
sideways. `display: block` is what makes the table box a scrollport; the
|
|
434
|
+
rows still lay out through the anonymous table box inside it. */
|
|
435
|
+
.primer-article table {
|
|
436
|
+
display: block;
|
|
437
|
+
width: max-content;
|
|
438
|
+
max-width: 100%;
|
|
439
|
+
overflow-x: auto;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
@@ -173,6 +173,11 @@
|
|
|
173
173
|
--sidebar-w: var(--sidebar-w-rail);
|
|
174
174
|
--rail-open: 246px;
|
|
175
175
|
--content-max: 1120px;
|
|
176
|
+
/* the READING ceiling (task 1003306). A reading room is narrower than a
|
|
177
|
+
working surface: past ~1010px the article card is more empty ground than
|
|
178
|
+
page and reads as a void, so the room's head and its two columns share one
|
|
179
|
+
cap rather than each carrying a literal. */
|
|
180
|
+
--room-max: 1010px;
|
|
176
181
|
/* the RIGHT rail — the room a page reserves beside its main column for a
|
|
177
182
|
fixed side panel (the ideas composer's meter). Named here so the reserve
|
|
178
183
|
and the panel are measured from one value; see `.app-content--railed`. */
|
|
@@ -206,12 +211,18 @@
|
|
|
206
211
|
--shadow-pop: 0 18px 40px rgba(0, 0, 0, .28);
|
|
207
212
|
|
|
208
213
|
/* ---- z ladder — content overlays (rank tips z-50, modals z-50, toast z-100,
|
|
209
|
-
copy-toast z-1000, deeplink z-2000
|
|
210
|
-
|
|
214
|
+
copy-toast z-1000, deeplink z-2000) must beat the chrome; the mobile drawer
|
|
215
|
+
sits above chrome but below dialogs. The two ends belong to the reading
|
|
216
|
+
rooms and were hand-written numbers until task 1003306 named them: the
|
|
217
|
+
reading hairline sits UNDER the topbar so it reads as the article's
|
|
218
|
+
progress and not as app chrome, and the diagram's fullscreen canvas is the
|
|
219
|
+
top of the whole ladder because it covers the shell entirely. ---- */
|
|
220
|
+
--z-progress: 25;
|
|
211
221
|
--z-topbar: 30;
|
|
212
222
|
--z-sidebar: 40;
|
|
213
223
|
--z-scrim: 140;
|
|
214
224
|
--z-drawer: 150;
|
|
225
|
+
--z-diagram-full: 9999;
|
|
215
226
|
|
|
216
227
|
/* ---- the hall's own plate: the declared seam, deferred by the owner
|
|
217
228
|
("decide after the shell lands", 2026-08-30). The hall's plate was
|
|
@@ -1270,6 +1281,53 @@ main:focus { outline: none; }
|
|
|
1270
1281
|
}
|
|
1271
1282
|
.page-head--board .page-head__sub { font-size: 14px; max-width: var(--measure); }
|
|
1272
1283
|
|
|
1284
|
+
/* The READING-ROOM page head (task 1003306, mock docs/design/mocks/hall/reading/v3.html).
|
|
1285
|
+
The board's head is quiet BECAUSE the board is a working surface and the page's
|
|
1286
|
+
name is the least interesting thing on it. A reading room is the opposite: the
|
|
1287
|
+
document IS the page, so its name is the largest thing in the first viewport,
|
|
1288
|
+
lowercase in the display face over the ground, with the label voice spent on a
|
|
1289
|
+
one-word eyebrow above it. Two voices, one per archetype — the divergence is
|
|
1290
|
+
the owner's pick, not drift.
|
|
1291
|
+
The sub takes --measure because it is body prose. The h1 does NOT: --measure is
|
|
1292
|
+
the BODY measure, and spending it on a display line caps it near 950px and lets
|
|
1293
|
+
the title run the column's width (tests/hall_record_world.mjs §8). A heading's
|
|
1294
|
+
cap is the room's own --room-max, which is a layout ceiling, not a measure.
|
|
1295
|
+
The modifier carries the VOICE only. The room's WIDTH belongs to room.css,
|
|
1296
|
+
which caps the head and the column it heads from one value — so a page that
|
|
1297
|
+
takes the voice without loading the archetype (Ranks) keeps the shell's width
|
|
1298
|
+
for both, and never ends up with a 1010px head over 1120px cards. */
|
|
1299
|
+
.page-head--room { padding: var(--sp-xl) 0 var(--sp-lg); margin: 0; }
|
|
1300
|
+
.page-head--room .page-head__eyebrow {
|
|
1301
|
+
margin: 0 0 14px;
|
|
1302
|
+
font-family: var(--label-face);
|
|
1303
|
+
font-size: var(--label-size);
|
|
1304
|
+
font-weight: 400;
|
|
1305
|
+
letter-spacing: var(--label-space);
|
|
1306
|
+
text-transform: var(--label-case);
|
|
1307
|
+
color: var(--ink-faint);
|
|
1308
|
+
}
|
|
1309
|
+
.page-head--room .page-head__h {
|
|
1310
|
+
margin: 0;
|
|
1311
|
+
font-family: var(--font-display);
|
|
1312
|
+
font-weight: 300;
|
|
1313
|
+
font-size: clamp(34px, 4.6vw, 58px);
|
|
1314
|
+
line-height: 1.02;
|
|
1315
|
+
letter-spacing: -0.042em;
|
|
1316
|
+
text-transform: lowercase;
|
|
1317
|
+
color: var(--ink);
|
|
1318
|
+
text-shadow: var(--type-halo);
|
|
1319
|
+
}
|
|
1320
|
+
.page-head--room .page-head__sub {
|
|
1321
|
+
margin: var(--sp-md) 0 0;
|
|
1322
|
+
max-width: var(--measure);
|
|
1323
|
+
font-size: 16px;
|
|
1324
|
+
color: var(--ink-soft);
|
|
1325
|
+
}
|
|
1326
|
+
@media (max-width: 760px) {
|
|
1327
|
+
.page-head--room { padding-top: var(--sp-lg); }
|
|
1328
|
+
.page-head--room .page-head__h { font-size: 34px; }
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1273
1331
|
.hall-nav {
|
|
1274
1332
|
position: sticky;
|
|
1275
1333
|
top: var(--topbar-h);
|
|
@@ -2345,7 +2403,17 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
|
|
|
2345
2403
|
.task__body { grid-column: 1 / -1; }
|
|
2346
2404
|
}
|
|
2347
2405
|
|
|
2348
|
-
/* ---------- ranks page ----------
|
|
2406
|
+
/* ---------- ranks page ----------
|
|
2407
|
+
Re-skinned into the chrome world by task 1003306 (goal 1000081). Ranks is a
|
|
2408
|
+
reading room by archetype — a document about the ladder — so it takes the
|
|
2409
|
+
room's page head (.page-head--room) and the room's voice on its labels, but
|
|
2410
|
+
not room.css: it has no article, no table of contents and no figures, and a
|
|
2411
|
+
sheet loaded for one max-width is a request spent on nothing.
|
|
2412
|
+
The rank card is `.scroll--quiet`'s level expressed as a list row: a tone one
|
|
2413
|
+
step further from the ground than the panel it sits in, with the edge
|
|
2414
|
+
reserved as transparent so a modifier can draw one without the base having
|
|
2415
|
+
to. The compat aliases are retired here; the badges above still spend them,
|
|
2416
|
+
because they render on every page in the hall and belong to 1003308. */
|
|
2349
2417
|
|
|
2350
2418
|
.ranks-standing {
|
|
2351
2419
|
display: grid;
|
|
@@ -2354,47 +2422,51 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
|
|
|
2354
2422
|
align-items: center;
|
|
2355
2423
|
}
|
|
2356
2424
|
.ranks-standing__badge { display: flex; }
|
|
2357
|
-
.ranks-standing__title { font-weight:
|
|
2358
|
-
.ranks-standing__blurb { grid-column: 1 / -1; font-size: 13.5px; color: var(--ink-soft); }
|
|
2425
|
+
.ranks-standing__title { font-family: var(--font-display); font-weight: 300; font-size: 19px; letter-spacing: -0.02em; }
|
|
2426
|
+
.ranks-standing__blurb { grid-column: 1 / -1; font-size: 13.5px; color: var(--ink-soft); max-width: var(--measure); }
|
|
2359
2427
|
.ranks-standing__next { grid-column: 1 / -1; font-size: 13px; color: var(--ink-faint); }
|
|
2360
2428
|
@media (max-width: 540px) { .ranks-standing { grid-template-columns: minmax(0, 1fr); } }
|
|
2361
2429
|
|
|
2362
2430
|
.ranks-ladder { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
|
|
2363
2431
|
.rank-card {
|
|
2364
|
-
background: var(--
|
|
2365
|
-
border:
|
|
2432
|
+
background: var(--glass);
|
|
2433
|
+
border: var(--line) solid transparent;
|
|
2366
2434
|
border-radius: var(--radius);
|
|
2367
|
-
padding:
|
|
2435
|
+
padding: var(--sp-sm) 16px;
|
|
2368
2436
|
}
|
|
2369
|
-
|
|
2370
|
-
.rank-card--
|
|
2437
|
+
/* the reader's own rung is the one warm thing on the ladder */
|
|
2438
|
+
.rank-card--current { background: var(--accent-tint); border-color: color-mix(in srgb, var(--accent) 45%, transparent); }
|
|
2439
|
+
.rank-card--next { border-style: dashed; border-color: var(--rule); }
|
|
2371
2440
|
.rank-card--sealed { opacity: 0.7; }
|
|
2372
2441
|
.rank-card--placeholder { color: var(--ink-faint); }
|
|
2373
2442
|
.rank-card__head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
|
|
2374
|
-
.rank-card__title { font-weight:
|
|
2443
|
+
.rank-card__title { font-family: var(--font-display); font-weight: 400; font-size: 16px; letter-spacing: -0.02em; }
|
|
2375
2444
|
.rank-card__status {
|
|
2376
2445
|
margin-left: auto;
|
|
2377
|
-
font-
|
|
2378
|
-
font-
|
|
2379
|
-
|
|
2380
|
-
|
|
2446
|
+
font-family: var(--label-face);
|
|
2447
|
+
font-size: var(--label-size);
|
|
2448
|
+
font-weight: 400;
|
|
2449
|
+
letter-spacing: var(--label-space);
|
|
2450
|
+
text-transform: var(--label-case);
|
|
2381
2451
|
}
|
|
2382
|
-
.rank-card__status--current { color: var(--accent-
|
|
2452
|
+
.rank-card__status--current { color: var(--accent-ink); }
|
|
2383
2453
|
.rank-card__status--next { color: var(--info); }
|
|
2384
2454
|
.rank-card__status--sealed { color: var(--ink-faint); }
|
|
2385
|
-
.rank-card__blurb { font-size: 13px; color: var(--ink-soft); margin: 6px 0; }
|
|
2455
|
+
.rank-card__blurb { font-size: 13px; color: var(--ink-soft); margin: 6px 0; max-width: var(--measure); }
|
|
2386
2456
|
.rank-card__blurb--sealed { font-style: italic; }
|
|
2387
2457
|
.rank-card__unlocks-label {
|
|
2388
|
-
font-
|
|
2389
|
-
font-
|
|
2390
|
-
|
|
2391
|
-
letter-spacing:
|
|
2458
|
+
font-family: var(--label-face);
|
|
2459
|
+
font-size: var(--label-size);
|
|
2460
|
+
font-weight: 400;
|
|
2461
|
+
letter-spacing: var(--label-space);
|
|
2462
|
+
text-transform: var(--label-case);
|
|
2392
2463
|
color: var(--ink-faint);
|
|
2393
|
-
margin:
|
|
2464
|
+
margin: 10px 0 4px;
|
|
2394
2465
|
}
|
|
2395
|
-
.rank-card__list { margin: 0; padding-left: 18px; font-size: 13px; color: var(--ink-soft); }
|
|
2466
|
+
.rank-card__list { margin: 0; padding-left: 18px; font-size: 13px; color: var(--ink-soft); max-width: var(--measure); }
|
|
2396
2467
|
.rank-card__list li { margin: 2px 0; }
|
|
2397
|
-
.
|
|
2468
|
+
.rank-card__list li::marker { color: var(--ink-faint); }
|
|
2469
|
+
.ranks-rise__body { font-size: 13.5px; max-width: var(--measure); }
|
|
2398
2470
|
.ranks-rise__body p { margin: 8px 0; }
|
|
2399
2471
|
|
|
2400
2472
|
/* ---------- toast + copy toast + deep-link overlay ---------- */
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.451",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@bongos/core",
|
|
9
|
-
"version": "1.19.
|
|
9
|
+
"version": "1.19.451",
|
|
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.
|
|
3
|
+
"version": "1.19.451",
|
|
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",
|