@bongos/core 1.19.413 → 1.19.415
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 +190 -40
- package/docs/adr/0204-the-apex-is-dark-only.md +36 -0
- package/docs/adr/README.md +1 -0
- package/docs/copy-inventory.md +310 -312
- package/docs/copy-registry.json +394 -412
- package/docs/design/landing-page-direction-v2.md +2 -0
- package/docs/design/mocks/hub/assets/r3-space-deepfield-half.jpg +0 -0
- package/docs/design/mocks/hub/assets/r3-space-deepfield-half.jpg.json +13 -0
- package/docs/design/mocks/hub/assets/r3-space-dust-half.jpg +0 -0
- package/docs/design/mocks/hub/assets/r3-space-dust-half.jpg.json +13 -0
- package/docs/design/mocks/hub/assets/r3-space-nebula-half.jpg +0 -0
- package/docs/design/mocks/hub/assets/r3-space-nebula-half.jpg.json +13 -0
- package/docs/design/mocks/hub/assets/r3-space-starfield-half.jpg +0 -0
- package/docs/design/mocks/hub/assets/r3-space-starfield-half.jpg.json +13 -0
- package/docs/design/mocks/hub/planets.html +127 -3
- package/docs/design/projects-hub-direction-v2.md +14 -0
- package/docs/module-api-changelog.md +4 -0
- package/docs/recipes/ui-look-before-you-ship.md +4 -1
- package/modules/platform-identity/migrations/platform_identity_013_project_template_materials.sql +31 -0
- package/modules/platform-identity/platform-identity.js +18 -5
- package/modules/platform-identity/routes/projects.js +3 -2
- package/modules/platform-identity/tests/platform-identity.mjs +23 -12
- package/modules/ui-design/kit/fixtures/featured.json +1 -1
- package/modules/ui-design/kit/lib.js +3 -1
- package/modules/ui-design/kit/render.js +5 -4
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/public-landing/assets/cosmos.css +50 -18
- package/public-landing/assets/world/r3-frost-bead-cut.webp +0 -0
- package/public-landing/assets/world/r3-frost-bead-cut.webp.json +15 -0
- package/public-landing/assets/world/r3-frost-blob-cut.webp +0 -0
- package/public-landing/assets/world/r3-frost-blob-cut.webp.json +15 -0
- package/public-landing/assets/world/r3-frost-pair-cut.webp +0 -0
- package/public-landing/assets/world/r3-frost-pair-cut.webp.json +15 -0
- package/public-landing/assets/world/r3-gold-bead-cut.webp +0 -0
- package/public-landing/assets/world/r3-gold-bead-cut.webp.json +15 -0
- package/public-landing/assets/world/r3-gold-blob-cut.webp +0 -0
- package/public-landing/assets/world/r3-gold-blob-cut.webp.json +15 -0
- package/public-landing/assets/world/r3-gold-pair-cut.webp +0 -0
- package/public-landing/assets/world/r3-gold-pair-cut.webp.json +15 -0
- package/public-landing/assets/world/r3-obsidian-bead-cut.webp +0 -0
- package/public-landing/assets/world/r3-obsidian-bead-cut.webp.json +15 -0
- package/public-landing/assets/world/r3-obsidian-blob-cut.webp +0 -0
- package/public-landing/assets/world/r3-obsidian-blob-cut.webp.json +15 -0
- package/public-landing/assets/world/r3-obsidian-pair-cut.webp +0 -0
- package/public-landing/assets/world/r3-obsidian-pair-cut.webp.json +15 -0
- package/public-landing/assets/world/r3-space-nebula.jpg +0 -0
- package/public-landing/assets/world/r3-space-nebula.jpg.json +13 -0
- package/public-landing/contact.html +2 -6
- package/public-landing/index.html +5 -44
- package/public-landing/index.states.json +3 -2
- package/public-landing/privacy.html +2 -6
- package/public-landing/projects.html +27 -55
- package/public-landing/projects.probes.json +0 -3
- package/public-landing/projects.states.json +4 -3
- package/public-landing/terms.html +2 -6
- package/scripts/gds/worktree.js +11 -0
- package/src/module-api.js +1 -1
- package/tests/landing_legal_pages.mjs +10 -0
- package/tests/landing_page.mjs +16 -19
- package/tests/projects_hub.mjs +69 -19
- package/tests/projects_hub_pre_uat.mjs +4 -3
- package/tests/ui_design_kit.mjs +10 -0
|
@@ -60,6 +60,8 @@ What the pick settles: the settled constraint (dark-first with a real, tested li
|
|
|
60
60
|
|
|
61
61
|
**2026-08-28, the second note (task 1003334).** Seeing the before/after of task 1003333, the owner found the chrome bongo pair sitting on the top-right sweeping form did not fit ("the random bongos on the blobs background"). Offered three treatments (remove it from the hero; keep it off the blob on plain black or paper; phones only), the owner picked **remove it from the hero**. The pair is no longer a hero object: `.mark`, its arrival and its tokens leave; it stays as the closing figure, the second project orb and the bar's mark. The sweeping form stays as a bare backdrop. Under 900 the masthead is the big blob alone, with the words keeping the 56vw the pair used to hold above them.
|
|
62
62
|
|
|
63
|
+
**2026-08-28, the third note — dark only (task 1003336, [ADR 0204](../adr/<redacted>.md)).** Reviewing the planets (task 1003319) with both grounds in front of them, the owner took option 4 of §5 after all, widened to the whole apex: "only black or only white is a bit bland, frankly I am leaning towards only dark mode for this page and keep the dark/light mode to be solely for the builder hall … we could invest into a cool space themed backdrop for the blobs." Built: `data-mode="dark"` fixed on `<html>` of every apex page, the pre-paint script and the persisted `cb-color-mode` gone, the moon/sun glyph and its wiring out of both bars, the kit rendering dark only. What the 2026-08-27 pick settled about light — the cutouts on paper under a contact shadow, the toggle staying on the landing — no longer describes the apex; the cutouts remain the closing figure and the planets' masks. The light tier of `world.css` stays until its own removal. The space backdrop is the next task (1003337).
|
|
64
|
+
|
|
63
65
|
## 7. Shot list: real imagery still owed
|
|
64
66
|
|
|
65
67
|
No version left a placeholder slot: every image on the three pages is a real plate (the round-2 chrome set, the single blob, the two bongo pairs, the two new blob cutouts) or the real Verro Labs medallion, and the proof is the ledger rendered as page content, so no hall or hub capture is used. What the build will still owe:
|
|
Binary file
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"kind": "backdrop",
|
|
3
|
+
"model": "nano_banana_2 (requested as nano_banana_pro; the catalog served nano_banana_2)",
|
|
4
|
+
"aspect_ratio": "16:9",
|
|
5
|
+
"resolution": "2k",
|
|
6
|
+
"generated": "2026-08-29T15:37Z",
|
|
7
|
+
"round": 3,
|
|
8
|
+
"task": 1003337,
|
|
9
|
+
"prompt": "Deep-space photograph on a pure black ground: almost entirely black with a barely-there violet-to-blue gradient in the upper left corner and a handful of pin-sharp stars, maximal emptiness, no nebula, no planets, no ground plane, no horizon, no lens flare, no text, no watermark. Pure black everywhere but the faint corner.",
|
|
10
|
+
"source": ".impeccable/mocks/world-assets/r3-space-deepfield.jpg",
|
|
11
|
+
"encoded": "ffmpeg JPEG -q:v 5 at 1376px (the sheet's candidate; docs/ is served raw by the kit's stub)",
|
|
12
|
+
"use": "docs/design/mocks/hub/planets.html ?state=backdrops"
|
|
13
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"kind": "backdrop",
|
|
3
|
+
"model": "nano_banana_2 (requested as nano_banana_pro; the catalog served nano_banana_2)",
|
|
4
|
+
"aspect_ratio": "16:9",
|
|
5
|
+
"resolution": "2k",
|
|
6
|
+
"generated": "2026-08-29T15:37Z",
|
|
7
|
+
"round": 3,
|
|
8
|
+
"task": 1003337,
|
|
9
|
+
"prompt": "Deep-space photograph on a pure black ground: thin drifting cosmic dust filaments in bronze and cool blue crossing the frame diagonally, sparse pin-sharp stars, one soft distant glow low right, generous empty black, no planets, no ground plane, no horizon, no lens flare, no text, no watermark. Pure black dominates.",
|
|
10
|
+
"source": ".impeccable/mocks/world-assets/r3-space-dust.jpg",
|
|
11
|
+
"encoded": "ffmpeg JPEG -q:v 5 at 1376px (the sheet's candidate; docs/ is served raw by the kit's stub)",
|
|
12
|
+
"use": "docs/design/mocks/hub/planets.html ?state=backdrops"
|
|
13
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"kind": "backdrop",
|
|
3
|
+
"model": "nano_banana_2 (requested as nano_banana_pro; the catalog served nano_banana_2)",
|
|
4
|
+
"aspect_ratio": "16:9",
|
|
5
|
+
"resolution": "2k",
|
|
6
|
+
"generated": "2026-08-29T15:37Z",
|
|
7
|
+
"round": 3,
|
|
8
|
+
"task": 1003337,
|
|
9
|
+
"prompt": "Deep-space photograph on a pure black ground: a faint wide nebula wash in muted violet and deep blue with a soft bronze warmth along one edge, very sparse pin-sharp stars of varied brightness and size, gentle depth, most of the frame near-black, nothing else, no planets, no ground plane, no horizon, no lens flare, no text, no watermark. Pure black dominates.",
|
|
10
|
+
"source": ".impeccable/mocks/world-assets/r3-space-nebula.jpg",
|
|
11
|
+
"encoded": "ffmpeg JPEG -q:v 5 at 1376px (the sheet's candidate; docs/ is served raw by the kit's stub)",
|
|
12
|
+
"use": "docs/design/mocks/hub/planets.html ?state=backdrops"
|
|
13
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"kind": "backdrop",
|
|
3
|
+
"model": "nano_banana_2 (requested as nano_banana_pro; the catalog served nano_banana_2)",
|
|
4
|
+
"aspect_ratio": "16:9",
|
|
5
|
+
"resolution": "2k",
|
|
6
|
+
"generated": "2026-08-29T15:37Z",
|
|
7
|
+
"round": 3,
|
|
8
|
+
"task": 1003337,
|
|
9
|
+
"prompt": "Deep-space photograph on a pure black ground: a fine field of pin-sharp stars in three depths (a few bright, many mid, a faint dust of tiny ones), a barely visible cool haze band drifting across the lower third, no nebula colour, no planets, no ground plane, no horizon, no lens flare, no text, no watermark. Pure black dominates.",
|
|
10
|
+
"source": ".impeccable/mocks/world-assets/r3-space-starfield.jpg",
|
|
11
|
+
"encoded": "ffmpeg JPEG -q:v 5 at 1376px (the sheet's candidate; docs/ is served raw by the kit's stub)",
|
|
12
|
+
"use": "docs/design/mocks/hub/planets.html ?state=backdrops"
|
|
13
|
+
}
|
|
@@ -126,7 +126,32 @@ body{
|
|
|
126
126
|
section[data-state]{display:none;}
|
|
127
127
|
body[data-state="sheet"] section[data-state="sheet"],
|
|
128
128
|
body[data-state="void"] section[data-state="void"],
|
|
129
|
-
body[data-state="grid"] section[data-state="grid"]
|
|
129
|
+
body[data-state="grid"] section[data-state="grid"],
|
|
130
|
+
body[data-state="backdrops"] section[data-state="backdrops"],
|
|
131
|
+
body[data-state="materials"] section[data-state="materials"]{display:block;}
|
|
132
|
+
/* round 3 (task 1003337): the materials' crops, byte-equal to cosmos.css (patch-checked), on
|
|
133
|
+
the generic attribute pair so the sheet's .planet and the field's .worldOrb share them;
|
|
134
|
+
the candidate backdrops as the field's ground (half-size copies, served raw from docs/) */
|
|
135
|
+
[data-style="plain"]{--tpl-ink:transparent;--tpl-blend:normal;}
|
|
136
|
+
[data-material="frost"][data-shape="blob"]{--tpl-src:var(--plate-frost-blob-cut);--tpl-ar:1.25629;--tpl-zoom:1.46135;--tpl-px:-.22359;--tpl-py:-.34269;}
|
|
137
|
+
[data-material="frost"][data-shape="pair"]{--tpl-src:var(--plate-frost-pair-cut);--tpl-ar:1.91273;--tpl-zoom:1.09673;--tpl-px:-.04837;--tpl-py:-.28669;}
|
|
138
|
+
[data-material="frost"][data-shape="bead"]{--tpl-src:var(--plate-frost-bead-cut);--tpl-ar:.98831;--tpl-zoom:1.49678;--tpl-px:-.22976;--tpl-py:-.23769;}
|
|
139
|
+
[data-material="gold"][data-shape="blob"]{--tpl-src:var(--plate-gold-blob-cut);--tpl-ar:.91864;--tpl-zoom:1.31406;--tpl-px:-.1477;--tpl-py:-.11629;}
|
|
140
|
+
[data-material="gold"][data-shape="pair"]{--tpl-src:var(--plate-gold-pair-cut);--tpl-ar:1.86206;--tpl-zoom:1.08625;--tpl-px:-.04367;--tpl-py:-.28123;}
|
|
141
|
+
[data-material="gold"][data-shape="bead"]{--tpl-src:var(--plate-gold-bead-cut);--tpl-ar:1.00479;--tpl-zoom:1.08272;--tpl-px:-.04244;--tpl-py:-.04244;}
|
|
142
|
+
[data-material="obsidian"][data-shape="blob"]{--tpl-src:var(--plate-obsidian-blob-cut);--tpl-ar:.794;--tpl-zoom:1.55448;--tpl-px:-.2697;--tpl-py:-.15965;}
|
|
143
|
+
[data-material="obsidian"][data-shape="pair"]{--tpl-src:var(--plate-obsidian-pair-cut);--tpl-ar:2.23705;--tpl-zoom:1.0248;--tpl-px:-.01015;--tpl-py:-.30191;}
|
|
144
|
+
[data-material="obsidian"][data-shape="bead"]{--tpl-src:var(--plate-obsidian-bead-cut);--tpl-ar:1.0027;--tpl-zoom:1.34698;--tpl-px:-.17053;--tpl-py:-.17255;}
|
|
145
|
+
.mock .field[data-backdrop] .ground{background:var(--sky-bg) var(--cand) center/cover no-repeat;}
|
|
146
|
+
.mock .field[data-backdrop="nebula"]{--cand:url(assets/r3-space-nebula-half.jpg);}
|
|
147
|
+
.mock .field[data-backdrop="starfield"]{--cand:url(assets/r3-space-starfield-half.jpg);}
|
|
148
|
+
.mock .field[data-backdrop="dust"]{--cand:url(assets/r3-space-dust-half.jpg);}
|
|
149
|
+
.mock .field[data-backdrop="deepfield"]{--cand:url(assets/r3-space-deepfield-half.jpg);}
|
|
150
|
+
.mock section[data-state="backdrops"] .field{height:min(62vh,640px);}
|
|
151
|
+
.mock section[data-state="backdrops"] .rowLabel{padding:22px var(--gutter) 10px;}
|
|
152
|
+
.matrix.walk{grid-template-columns:repeat(12,1fr);}
|
|
153
|
+
.sheet .cell .nm{white-space:normal;text-align:center;line-height:1.35;max-width:100%;}
|
|
154
|
+
@media (max-width:900px){.matrix.walk{grid-template-columns:repeat(3,1fr);}}
|
|
130
155
|
.vh{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;}
|
|
131
156
|
.skip{position:absolute;left:12px;top:-60px;background:var(--bg-card);color:var(--ink);padding:11px 18px;border-radius:999px;}
|
|
132
157
|
.skip:focus{top:12px;}
|
|
@@ -139,6 +164,8 @@ body[data-state="grid"] section[data-state="grid"]{display:block;}
|
|
|
139
164
|
?state=sheet the nine templates at the five accents, and the blend candidates
|
|
140
165
|
?state=void field treatment A: the void — nothing drawn, the objects carry the depth
|
|
141
166
|
?state=grid field treatment B: the sheet — one hairline grid inside the camera
|
|
167
|
+
?state=backdrops round 3 (task 1003337): the four rendered space candidates as the field's ground
|
|
168
|
+
?state=materials round 3: the twelve-step walk, then frost / gold / obsidian at the five accents
|
|
142
169
|
?mode=dark|light
|
|
143
170
|
-->
|
|
144
171
|
<a class="skip" href="#main">Skip to content</a>
|
|
@@ -189,14 +216,73 @@ body[data-state="grid"] section[data-state="grid"]{display:block;}
|
|
|
189
216
|
<div class="hintbar"><span><kbd>drag</kbd> pan</span><span><kbd>scroll</kbd> zoom</span><span><kbd>click a project</kbd> open it</span></div>
|
|
190
217
|
</div></div>
|
|
191
218
|
</section>
|
|
219
|
+
|
|
220
|
+
<section data-state="backdrops">
|
|
221
|
+
<div class="rowLabel">the nebula wash: a faint violet-and-bronze wash, sparse stars (the builder's recommendation; shipped as --field-plate)</div>
|
|
222
|
+
<div class="fieldWrap"><div class="field" data-backdrop="nebula">
|
|
223
|
+
<div class="ground"></div>
|
|
224
|
+
<div class="skyCam">
|
|
225
|
+
<a class="worldOrb" href="#" data-rel="owner" data-shape="pair" data-material="chrome" data-style="chrome" style="--acc:var(--accent);--d:140px;left:50%;top:44%"><span class="badge">yours</span><span class="disc"></span><span class="nm">Cloud Bongos</span><span class="sub">this platform</span></a>
|
|
226
|
+
<a class="worldOrb" href="#" data-rel="none" data-shape="blob" data-material="frost" data-style="wash" style="--acc:var(--terracotta);--d:92px;left:22%;top:30%"><span class="disc"></span><span class="nm">Demo</span></a>
|
|
227
|
+
<a class="worldOrb" href="#" data-rel="builder" data-shape="bead" data-material="gold" data-style="tint" style="--acc:var(--gold-soft);--d:75px;left:78%;top:66%"><span class="badge">you build here</span><span class="disc"></span><span class="nm">Off the Boats</span></a>
|
|
228
|
+
<a class="worldOrb" href="#" data-rel="builder" data-shape="pair" data-material="obsidian" data-style="tint" style="--acc:var(--sea);--d:70px;left:33%;top:74%"><span class="badge">you build here</span><span class="disc"></span><span class="nm">Emersonian Circles</span></a>
|
|
229
|
+
<a class="worldOrb" href="#" data-rel="none" data-shape="bead" data-material="chrome" data-style="chrome" style="--acc:var(--sun-lit);--d:80px;left:70%;top:26%"><span class="disc"></span><span class="nm">Mercury</span></a>
|
|
230
|
+
</div>
|
|
231
|
+
<div class="hintbar"><span><kbd>drag</kbd> pan</span><span><kbd>scroll</kbd> zoom</span><span><kbd>click a project</kbd> open it</span></div>
|
|
232
|
+
</div></div>
|
|
233
|
+
<div class="rowLabel">the starfield: three depths of pin-sharp stars, a cool haze band</div>
|
|
234
|
+
<div class="fieldWrap"><div class="field" data-backdrop="starfield">
|
|
235
|
+
<div class="ground"></div>
|
|
236
|
+
<div class="skyCam">
|
|
237
|
+
<a class="worldOrb" href="#" data-rel="owner" data-shape="pair" data-material="chrome" data-style="chrome" style="--acc:var(--accent);--d:140px;left:50%;top:44%"><span class="badge">yours</span><span class="disc"></span><span class="nm">Cloud Bongos</span><span class="sub">this platform</span></a>
|
|
238
|
+
<a class="worldOrb" href="#" data-rel="none" data-shape="blob" data-material="frost" data-style="wash" style="--acc:var(--terracotta);--d:92px;left:22%;top:30%"><span class="disc"></span><span class="nm">Demo</span></a>
|
|
239
|
+
<a class="worldOrb" href="#" data-rel="builder" data-shape="bead" data-material="gold" data-style="tint" style="--acc:var(--gold-soft);--d:75px;left:78%;top:66%"><span class="badge">you build here</span><span class="disc"></span><span class="nm">Off the Boats</span></a>
|
|
240
|
+
<a class="worldOrb" href="#" data-rel="builder" data-shape="pair" data-material="obsidian" data-style="tint" style="--acc:var(--sea);--d:70px;left:33%;top:74%"><span class="badge">you build here</span><span class="disc"></span><span class="nm">Emersonian Circles</span></a>
|
|
241
|
+
<a class="worldOrb" href="#" data-rel="none" data-shape="bead" data-material="chrome" data-style="chrome" style="--acc:var(--sun-lit);--d:80px;left:70%;top:26%"><span class="disc"></span><span class="nm">Mercury</span></a>
|
|
242
|
+
</div>
|
|
243
|
+
<div class="hintbar"><span><kbd>drag</kbd> pan</span><span><kbd>scroll</kbd> zoom</span><span><kbd>click a project</kbd> open it</span></div>
|
|
244
|
+
</div></div>
|
|
245
|
+
<div class="rowLabel">the dust: bronze-and-blue filaments, one distant glow</div>
|
|
246
|
+
<div class="fieldWrap"><div class="field" data-backdrop="dust">
|
|
247
|
+
<div class="ground"></div>
|
|
248
|
+
<div class="skyCam">
|
|
249
|
+
<a class="worldOrb" href="#" data-rel="owner" data-shape="pair" data-material="chrome" data-style="chrome" style="--acc:var(--accent);--d:140px;left:50%;top:44%"><span class="badge">yours</span><span class="disc"></span><span class="nm">Cloud Bongos</span><span class="sub">this platform</span></a>
|
|
250
|
+
<a class="worldOrb" href="#" data-rel="none" data-shape="blob" data-material="frost" data-style="wash" style="--acc:var(--terracotta);--d:92px;left:22%;top:30%"><span class="disc"></span><span class="nm">Demo</span></a>
|
|
251
|
+
<a class="worldOrb" href="#" data-rel="builder" data-shape="bead" data-material="gold" data-style="tint" style="--acc:var(--gold-soft);--d:75px;left:78%;top:66%"><span class="badge">you build here</span><span class="disc"></span><span class="nm">Off the Boats</span></a>
|
|
252
|
+
<a class="worldOrb" href="#" data-rel="builder" data-shape="pair" data-material="obsidian" data-style="tint" style="--acc:var(--sea);--d:70px;left:33%;top:74%"><span class="badge">you build here</span><span class="disc"></span><span class="nm">Emersonian Circles</span></a>
|
|
253
|
+
<a class="worldOrb" href="#" data-rel="none" data-shape="bead" data-material="chrome" data-style="chrome" style="--acc:var(--sun-lit);--d:80px;left:70%;top:26%"><span class="disc"></span><span class="nm">Mercury</span></a>
|
|
254
|
+
</div>
|
|
255
|
+
<div class="hintbar"><span><kbd>drag</kbd> pan</span><span><kbd>scroll</kbd> zoom</span><span><kbd>click a project</kbd> open it</span></div>
|
|
256
|
+
</div></div>
|
|
257
|
+
<div class="rowLabel">the deep field: near-empty, a violet corner</div>
|
|
258
|
+
<div class="fieldWrap"><div class="field" data-backdrop="deepfield">
|
|
259
|
+
<div class="ground"></div>
|
|
260
|
+
<div class="skyCam">
|
|
261
|
+
<a class="worldOrb" href="#" data-rel="owner" data-shape="pair" data-material="chrome" data-style="chrome" style="--acc:var(--accent);--d:140px;left:50%;top:44%"><span class="badge">yours</span><span class="disc"></span><span class="nm">Cloud Bongos</span><span class="sub">this platform</span></a>
|
|
262
|
+
<a class="worldOrb" href="#" data-rel="none" data-shape="blob" data-material="frost" data-style="wash" style="--acc:var(--terracotta);--d:92px;left:22%;top:30%"><span class="disc"></span><span class="nm">Demo</span></a>
|
|
263
|
+
<a class="worldOrb" href="#" data-rel="builder" data-shape="bead" data-material="gold" data-style="tint" style="--acc:var(--gold-soft);--d:75px;left:78%;top:66%"><span class="badge">you build here</span><span class="disc"></span><span class="nm">Off the Boats</span></a>
|
|
264
|
+
<a class="worldOrb" href="#" data-rel="builder" data-shape="pair" data-material="obsidian" data-style="tint" style="--acc:var(--sea);--d:70px;left:33%;top:74%"><span class="badge">you build here</span><span class="disc"></span><span class="nm">Emersonian Circles</span></a>
|
|
265
|
+
<a class="worldOrb" href="#" data-rel="none" data-shape="bead" data-material="chrome" data-style="chrome" style="--acc:var(--sun-lit);--d:80px;left:70%;top:26%"><span class="disc"></span><span class="nm">Mercury</span></a>
|
|
266
|
+
</div>
|
|
267
|
+
<div class="hintbar"><span><kbd>drag</kbd> pan</span><span><kbd>scroll</kbd> zoom</span><span><kbd>click a project</kbd> open it</span></div>
|
|
268
|
+
</div></div>
|
|
269
|
+
</section>
|
|
270
|
+
|
|
271
|
+
<section data-state="materials" class="sheet">
|
|
272
|
+
<h2>Three materials, five accents</h2>
|
|
273
|
+
<p>Round 3: the same three whole objects rendered in frosted glass, brushed gold and polished obsidian, cut out and cropped from their own alpha, on the same masked colour layer. A template is now shape, material and style; the walk changes all three each step.</p>
|
|
274
|
+
<div class="rowLabel">the walk, twelve steps (the hub's default order)</div>
|
|
275
|
+
<div class="matrix walk" id="walk"></div>
|
|
276
|
+
<div id="matrix2"></div>
|
|
277
|
+
</section>
|
|
192
278
|
</main>
|
|
193
|
-
<footer class="foot">A composition sheet for
|
|
279
|
+
<footer class="foot">A composition sheet for tasks 1003319 and 1003337. Nothing here is served.</footer>
|
|
194
280
|
<script>
|
|
195
281
|
/* The mock's state contract: read ?state= once, apply one state (sheet | void | grid). The
|
|
196
282
|
matrix is built with createElement + textContent. No motion in script. */
|
|
197
283
|
(function () {
|
|
198
284
|
var state = new URLSearchParams(location.search || location.hash.slice(1) || (window.__Q || '')).get('state') || 'sheet';
|
|
199
|
-
if (
|
|
285
|
+
if (['sheet', 'void', 'grid', 'backdrops', 'materials'].indexOf(state) === -1) state = 'sheet';
|
|
200
286
|
document.body.setAttribute('data-state', state);
|
|
201
287
|
var ACCENTS = [['sea', 'var(--sea)'], ['terracotta', 'var(--terracotta)'], ['gold-soft', 'var(--gold-soft)'], ['sun-lit', 'var(--sun-lit)'], ['accent', 'var(--accent)']];
|
|
202
288
|
var TEMPLATES = ['blob-tint', 'pair-wash', 'bead-chrome', 'blob-wash', 'pair-chrome', 'bead-tint', 'blob-chrome', 'pair-tint', 'bead-wash'];
|
|
@@ -226,6 +312,44 @@ body[data-state="grid"] section[data-state="grid"]{display:block;}
|
|
|
226
312
|
});
|
|
227
313
|
host.appendChild(row);
|
|
228
314
|
});
|
|
315
|
+
/* round 3: the walk and the materials matrix, the same cell grammar */
|
|
316
|
+
var WALK = ['blob-tint', 'pair-gold-wash', 'bead-obsidian-plain', 'blob-frost-wash', 'pair-chrome', 'bead-gold-tint', 'blob-obsidian-wash', 'pair-frost-tint', 'bead-wash', 'blob-gold-plain', 'pair-obsidian-tint', 'bead-frost-wash'];
|
|
317
|
+
function cellFor(t, acc) {
|
|
318
|
+
var parts = t.split('-'), shape = parts[0], material = parts.length === 3 ? parts[1] : 'chrome', style = parts[parts.length - 1];
|
|
319
|
+
var cell = document.createElement('div');
|
|
320
|
+
cell.className = 'cell';
|
|
321
|
+
var p = document.createElement('span');
|
|
322
|
+
p.className = 'planet';
|
|
323
|
+
p.setAttribute('data-shape', shape);
|
|
324
|
+
p.setAttribute('data-material', material);
|
|
325
|
+
p.setAttribute('data-style', style);
|
|
326
|
+
p.style.setProperty('--acc', acc);
|
|
327
|
+
var n = document.createElement('span');
|
|
328
|
+
n.className = 'nm';
|
|
329
|
+
n.textContent = t;
|
|
330
|
+
cell.appendChild(p);
|
|
331
|
+
cell.appendChild(n);
|
|
332
|
+
return cell;
|
|
333
|
+
}
|
|
334
|
+
var walkHost = document.getElementById('walk');
|
|
335
|
+
if (walkHost) WALK.forEach(function (t, i) { walkHost.appendChild(cellFor(t, ACCENTS[i % ACCENTS.length][1])); });
|
|
336
|
+
var host2 = document.getElementById('matrix2');
|
|
337
|
+
if (host2) {
|
|
338
|
+
['frost', 'gold', 'obsidian'].forEach(function (m) {
|
|
339
|
+
ACCENTS.forEach(function (a) {
|
|
340
|
+
var label = document.createElement('div');
|
|
341
|
+
label.className = 'rowLabel';
|
|
342
|
+
label.textContent = m + ', the ' + a[0] + ' accent';
|
|
343
|
+
host2.appendChild(label);
|
|
344
|
+
var row = document.createElement('div');
|
|
345
|
+
row.className = 'matrix';
|
|
346
|
+
['blob', 'pair', 'bead'].forEach(function (s) {
|
|
347
|
+
['tint', 'wash', 'plain'].forEach(function (y) { row.appendChild(cellFor(s + '-' + m + '-' + y, a[1])); });
|
|
348
|
+
});
|
|
349
|
+
host2.appendChild(row);
|
|
350
|
+
});
|
|
351
|
+
});
|
|
352
|
+
}
|
|
229
353
|
})();
|
|
230
354
|
</script>
|
|
231
355
|
</body>
|
|
@@ -170,3 +170,17 @@ Three mastheads, rendered dark and light at 1440 / 390 / 320 (ALL CLEAN) and mea
|
|
|
170
170
|
**What was built.** In `cosmos.css` the orb's disc is a masked colour layer over a cutout (`.disc::before`: the plate as both background and mask, `background-blend-mode` by style), sized `--d` by the object's own aspect; `[data-shape]` carries the three crops, `[data-style]` the three blends; the relationship ring is a circle behind the object (a mask clips a box-shadow away), the search spotlight an accent drop-shadow on the disc's filter after the contact shadow (dark's `--orb-shadow` is `opacity(1)`, a no-op, so the two compose). The starfield, its 3.2s twinkle, the 74px gravity grid and `--star-display` are gone; the labels, the badge, the hint and the hover card moved onto the world's type (hairline pill, label face, no accent on a fact, no shadow). In `projects.html` `ORB_TEMPLATES` walks beside `ORB_ACCENTS` in `assignAccents` (consecutive positions change shape and style; nine against five repeat every forty-five projects), `templateOf()` prefers a curated name, an owned-only entry walks by its slug, the orb carries `data-template` / `data-shape` / `data-style`, the physics measures the disc's own height, and the slot widths grew a quarter (a cutout's silhouette reads smaller than a filled disc of the same box). The platform's own orb is the pair in chrome. On the catalog side migration `<redacted>` adds the nullable `template` column with its nine-value CHECK, `upsertProject` carries it COALESCE-preserved, `POST /projects` validates it against `PROJECT_TEMPLATES`, and the public `/projects/featured` projection returns it. The kit's fixture gives Example a curated `bead-wash` and the `in-map` state reads it back off the orb.
|
|
171
171
|
|
|
172
172
|
**Not done, on purpose:** no owner-facing picker — a template is set through the curation route today, the way `featured` is; whether a project's owner chooses their own planet from the manage view is the owner's call. The manage view's small `.orb` spheres keep their old look (the scope named the sky's `a.worldOrb` only).
|
|
173
|
+
|
|
174
|
+
## 12. Dark only (task 1003336)
|
|
175
|
+
|
|
176
|
+
**Date:** 2026-08-28 (decided), 2026-08-29 (built) · the owner's call on the planets review (§11): the apex renders dark only and the light/dark switch is the builders' hall's alone — [ADR 0204](../adr/<redacted>.md). On `/projects`: `data-mode="dark"` is fixed on `<html>`, the pre-paint script is gone, the `#modeToggle` glyph and its `resolvedMode` / `paintModeToggle` wiring leave the bar (Projects, then the chip), the `.modeBtn` rules and the icon-swap twins leave `cosmos.css`, the mode-toggle probe leaves `projects.probes.json`, and `projects.states.json` declares `"modes": ["dark"]` so the kit renders the hub's twelve states at three widths in one mode (48 shots, ALL CLEAN; probes 31/31). The light tier of `cosmos.css` stays until its own removal. Why first: the space backdrop for the field (task 1003337) is a black-ground plate; one mode is what lets the field commit to it.
|
|
177
|
+
|
|
178
|
+
## 13. The space and the materials (task 1003337)
|
|
179
|
+
|
|
180
|
+
**Date:** 2026-08-29 · the owner's ask on the planets review (§11): "use higgsfield for some further ideas colors, styles, and inspiration … we could invest into a cool space themed backdrop for the blobs", and the pick of the FULL material round the same day.
|
|
181
|
+
|
|
182
|
+
**The round.** Higgsfield (`nano_banana_pro`, served as `nano_banana_2`, 2k; 15 generations + 9 cutouts, ~37 credits): four text-free deep-space plates on pure black (`r3-space-nebula` — a faint violet-and-bronze wash with sparse stars; `-starfield` — three depths of pin-sharp stars and a cool haze band; `-dust` — bronze-and-blue filaments with one distant glow; `-deepfield` — near-empty with a violet corner), and the world's three whole objects in three new materials — **frosted glass**, **brushed gold**, **polished obsidian** — one whole object per 1:1 plate (the first frost blob ran off the frame and was retaken), each cut out with `remove_background` and its alpha verified with ffmpeg (min 0, max 255). The sheet: `docs/design/mocks/hub/planets.html` gains `?state=backdrops` (the four candidates as the field with the real orbs over them) and `?state=materials` (the twelve-step walk, then every material at the five accents).
|
|
183
|
+
|
|
184
|
+
**What was built.** The template grammar grows from shape × style to shape × **material** × style: `<shape>-<style>` stays the chrome material's name (nine rows keep their meaning), `<shape>-<material>-<style>` names a new material with style `tint` / `wash` / `plain` — thirty-six names in migration `<redacted>`, `PROJECT_TEMPLATES` (every valid name, the `POST /projects` enum) and `PROJECT_TEMPLATE_WALK` (the hub's twelve-step default, each step changing shape, material and style — `ORB_WALK` in `projects.html`, `ORB_TEMPLATES` the full set). `cosmos.css` carries a plate token per material × shape, a two-attribute crop rule per plate measured from the cutout's alpha box (pinned by `tests/projects_hub.mjs`, which recomputes every rule from the boxes), and `[data-style="plain"]`. The orb carries `data-material` beside `data-shape` and `data-style`. The field's ground is `--field-plate` at `cover` under the page ground, drifting 2–3% over 90 s by transform (dead under reduced motion) — one token, so the pick is one line.
|
|
185
|
+
|
|
186
|
+
**The pick, open.** The owner was not in the session, so the backdrop shipped on the builder's recommendation — the nebula wash (its violet and bronze are the chrome's own colours; the dust plate's glow competes with the orbs; the starfield is plain; the deepfield's corner is heavier than asked) — with the other three beside it in `.impeccable/mocks/world-assets/` and on the sheet. Swapping is one token (`--field-plate`) plus a copy into `assets/world/`. The materials are not a pick: they ship as templates, and a curated `template` chooses one per project.
|
|
@@ -1263,5 +1263,9 @@ is load-bearing: the script throws rather than guess if it is missing, and
|
|
|
1263
1263
|
landed since 1.19.411 with no explicit bump. run 33259357678. (task 1002620)
|
|
1264
1264
|
1.19.413 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
1265
1265
|
landed since 1.19.412 with no explicit bump. run 33259477562. (task 1002620)
|
|
1266
|
+
1.19.414 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
1267
|
+
landed since 1.19.413 with no explicit bump. run 33260596712. (task 1002620)
|
|
1268
|
+
1.19.415 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
1269
|
+
landed since 1.19.414 with no explicit bump. run 33262322596. (task 1002620)
|
|
1266
1270
|
---------------------------------------------------------------------------
|
|
1267
1271
|
```
|
|
@@ -56,7 +56,8 @@ Then a state's own `expect` (a band open, a dialog present, a field's value, a c
|
|
|
56
56
|
{
|
|
57
57
|
"page": "/projects",
|
|
58
58
|
"surface": "public-landing",
|
|
59
|
-
"
|
|
59
|
+
"modes": ["dark"],
|
|
60
|
+
"modeQuery": false,
|
|
60
61
|
"ignoreRequests": ["/api/(gds|bongos)/me$", "/my-projects"],
|
|
61
62
|
"ignoreConsole": ["\\b401\\b"],
|
|
62
63
|
"ignoreControls": [".skip", ".vh"],
|
|
@@ -69,6 +70,8 @@ Then a state's own `expect` (a band open, a dialog present, a field's value, a c
|
|
|
69
70
|
}
|
|
70
71
|
```
|
|
71
72
|
|
|
73
|
+
`modes` names the modes the page renders (default both). A page that pins one mode — the apex pins `data-mode="dark"` on `<html>` since task 1003336 — declares it here so a plain `--page` render never walks a mode the page cannot show; `--modes` on the command line still overrides. `modeQuery: false` says no query walks a mode.
|
|
74
|
+
|
|
72
75
|
Actions: `click`, `focus`, `press`, `fill`, `wait`, `clickAt x y`, `clickIfVisible`, `dispatchClick`, `check`, `back`, `forward`. Expectations: `expanded`, `dialog`, `visible[]`, `hidden[]`, `open`, `closed`, `activeId`, `activeText`, `expandedIds[]`, `param{}`, `attr[[sel,name,value]]`, `text[[sel,value]]`, `href[[sel,value]]`, `count[[sel,n]]`, `value[[sel,v]]`, `hasClass[[sel,class,bool]]`, `checked`, `noOverflow`, `top[[sel,px]]` (an element's viewport top — assert it closed, open a band, assert it again: the proof an overlay did not push the page). The kit validates the file before it opens a browser and names every problem.
|
|
73
76
|
|
|
74
77
|
The worked examples: `public-landing/projects.states.json` (the hub's thirteen), `public-landing/index.states.json` (the landing's four), `modules/hall-ui/public/ranks.states.json` (a second surface under its own prefix — it renders **red**, deliberately: the hall predates the 24px floor and Ranks has no `<h1>`, and the states file declares the shell's un-fixtured feeds rather than hiding the findings; idea 1000863 carries them).
|
package/modules/platform-identity/migrations/platform_identity_013_project_template_materials.sql
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
-- platform_identity_013_project_template_materials.sql — the planet templates grow from
|
|
2
|
+
-- shape × style to shape × MATERIAL × style (task 1003337).
|
|
3
|
+
--
|
|
4
|
+
-- Round 3 rendered the world's three whole objects (blob / pair / bead) in three new
|
|
5
|
+
-- materials — frosted glass, brushed gold, polished obsidian — beside the first round's
|
|
6
|
+
-- chrome. A template name is `<shape>-<style>` for chrome (the first round's names, kept
|
|
7
|
+
-- verbatim so every stored row stays valid) or `<shape>-<material>-<style>` for a new
|
|
8
|
+
-- material, where style is tint / wash / plain (plain = the material as rendered; the
|
|
9
|
+
-- chrome material's plain is spelled `chrome`). Thirty-six names; the hub's default walk
|
|
10
|
+
-- (PROJECT_TEMPLATE_WALK) uses twelve of them, each step changing shape, material and style.
|
|
11
|
+
--
|
|
12
|
+
-- Additive + platform_identity_-namespaced (ADR 0083 §5): the CHECK from migration 012 is
|
|
13
|
+
-- re-stated with the wider set; the column, its nullability and the curation route are
|
|
14
|
+
-- unchanged. Idempotent: safe to re-run.
|
|
15
|
+
|
|
16
|
+
BEGIN;
|
|
17
|
+
|
|
18
|
+
ALTER TABLE platform_identity_projects DROP CONSTRAINT IF EXISTS platform_identity_projects_template_check;
|
|
19
|
+
ALTER TABLE platform_identity_projects ADD CONSTRAINT platform_identity_projects_template_check
|
|
20
|
+
CHECK (template IS NULL OR template IN (
|
|
21
|
+
-- chrome, the first round (migration 012), names kept verbatim
|
|
22
|
+
'blob-tint', 'blob-wash', 'blob-chrome',
|
|
23
|
+
'pair-tint', 'pair-wash', 'pair-chrome',
|
|
24
|
+
'bead-tint', 'bead-wash', 'bead-chrome',
|
|
25
|
+
-- the materials round
|
|
26
|
+
'blob-frost-tint', 'blob-frost-wash', 'blob-frost-plain', 'blob-gold-tint', 'blob-gold-wash', 'blob-gold-plain', 'blob-obsidian-tint', 'blob-obsidian-wash', 'blob-obsidian-plain',
|
|
27
|
+
'pair-frost-tint', 'pair-frost-wash', 'pair-frost-plain', 'pair-gold-tint', 'pair-gold-wash', 'pair-gold-plain', 'pair-obsidian-tint', 'pair-obsidian-wash', 'pair-obsidian-plain',
|
|
28
|
+
'bead-frost-tint', 'bead-frost-wash', 'bead-frost-plain', 'bead-gold-tint', 'bead-gold-wash', 'bead-gold-plain', 'bead-obsidian-tint', 'bead-obsidian-wash', 'bead-obsidian-plain'
|
|
29
|
+
));
|
|
30
|
+
|
|
31
|
+
COMMIT;
|
|
@@ -234,11 +234,21 @@ async function getClientByOrigin(origin, { pool = defaultPool } = {}) {
|
|
|
234
234
|
// provisioning's copy on its own instances table).
|
|
235
235
|
const PROJECT_TYPES = ['game', 'research', 'business', 'non-profit', 'not-sure'];
|
|
236
236
|
|
|
237
|
-
// The sky's planet templates (task 1003319):
|
|
238
|
-
// whole
|
|
239
|
-
//
|
|
240
|
-
//
|
|
241
|
-
|
|
237
|
+
// The sky's planet templates (task 1003319; the materials, task 1003337): SHAPE (blob / pair /
|
|
238
|
+
// bead, the world's three whole objects) × MATERIAL (chrome — the first round, named by omission
|
|
239
|
+
// — frost / gold / obsidian) × STYLE (how the accent lands: tint / wash / plain; the chrome
|
|
240
|
+
// material's plain is spelled `chrome`, the first round's name, so stored rows stay valid).
|
|
241
|
+
// PROJECT_TEMPLATES is EVERY valid name (the DB CHECK, migrations 012 + 013; the POST /projects
|
|
242
|
+
// enum); PROJECT_TEMPLATE_WALK is the hub's deterministic default order — consecutive positions
|
|
243
|
+
// change shape, material AND style. A CATALOG field curated through POST /projects; null = the
|
|
244
|
+
// walk. Mirrored by ORB_TEMPLATES / ORB_WALK in projects.html.
|
|
245
|
+
const PROJECT_SHAPES = ['blob', 'pair', 'bead'];
|
|
246
|
+
const PROJECT_MATERIALS = ['frost', 'gold', 'obsidian'];
|
|
247
|
+
const PROJECT_TEMPLATES = [
|
|
248
|
+
...PROJECT_SHAPES.flatMap((s) => ['tint', 'wash', 'chrome'].map((y) => `${s}-${y}`)),
|
|
249
|
+
...PROJECT_SHAPES.flatMap((s) => PROJECT_MATERIALS.flatMap((m) => ['tint', 'wash', 'plain'].map((y) => `${s}-${m}-${y}`))),
|
|
250
|
+
];
|
|
251
|
+
const PROJECT_TEMPLATE_WALK = ['blob-tint', 'pair-gold-wash', 'bead-obsidian-plain', 'blob-frost-wash', 'pair-chrome', 'bead-gold-tint', 'blob-obsidian-wash', 'pair-frost-tint', 'bead-wash', 'blob-gold-plain', 'pair-obsidian-tint', 'bead-frost-wash'];
|
|
242
252
|
|
|
243
253
|
// The stored JOIN DOOR (ADR 0182 D1, task 1002323). Three values, and ALL THREE ARE
|
|
244
254
|
// VISIBLE: `private` is visible-but-closed (the `goals.visibility` meaning, ADR 0112),
|
|
@@ -1357,6 +1367,9 @@ module.exports = {
|
|
|
1357
1367
|
upsertProject,
|
|
1358
1368
|
PROJECT_TYPES,
|
|
1359
1369
|
PROJECT_TEMPLATES,
|
|
1370
|
+
PROJECT_TEMPLATE_WALK,
|
|
1371
|
+
PROJECT_MATERIALS,
|
|
1372
|
+
PROJECT_SHAPES,
|
|
1360
1373
|
getProject,
|
|
1361
1374
|
listFeaturedProjects,
|
|
1362
1375
|
listAllProjects,
|
|
@@ -48,8 +48,9 @@ module.exports = function projectsRoutes() {
|
|
|
48
48
|
description: { type: 'string', maxLength: 2000 },
|
|
49
49
|
art_url: { type: 'string', maxLength: 2048 },
|
|
50
50
|
type: { type: 'string', enum: [...pi.PROJECT_TYPES] },
|
|
51
|
-
// The planet template (task 1003319): the shape and
|
|
52
|
-
// project's orb in. Curated here, never self-reported; absent
|
|
51
|
+
// The planet template (task 1003319; materials, task 1003337): the shape, material and
|
|
52
|
+
// style the sky cuts this project's orb in. Curated here, never self-reported; absent
|
|
53
|
+
// means the hub's walk.
|
|
53
54
|
template: { type: 'string', enum: [...pi.PROJECT_TEMPLATES] },
|
|
54
55
|
})) return;
|
|
55
56
|
try {
|
|
@@ -235,19 +235,30 @@ await ta('upsertProject carries the planet template, COALESCE-preserved; an unkn
|
|
|
235
235
|
const pool2 = mockPool([{ rows: [{ id: '2' }] }]);
|
|
236
236
|
await P.upsertProject({ origin: 'https://q', name: 'Q', template: 'saucer-neon' }, { pool: pool2 });
|
|
237
237
|
assert.ok(!pool2.calls[0].params.includes('saucer-neon'), 'unknown templates never reach the SQL');
|
|
238
|
-
// the vocabulary: the world's three whole objects ×
|
|
239
|
-
//
|
|
240
|
-
|
|
241
|
-
assert.
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
238
|
+
// the vocabulary: the world's three whole objects × four materials (chrome named by
|
|
239
|
+
// omission) × the three ways the accent lands — every valid name (the CHECK's set)
|
|
240
|
+
const RE = /^(blob|pair|bead)-(tint|wash|chrome|(frost|gold|obsidian)-(tint|wash|plain))$/;
|
|
241
|
+
assert.deepEqual(P.PROJECT_SHAPES, ['blob', 'pair', 'bead']);
|
|
242
|
+
assert.deepEqual(P.PROJECT_MATERIALS, ['frost', 'gold', 'obsidian']);
|
|
243
|
+
assert.equal(P.PROJECT_TEMPLATES.length, 36);
|
|
244
|
+
assert.equal(new Set(P.PROJECT_TEMPLATES).size, 36, 'thirty-six distinct templates');
|
|
245
|
+
for (const t of P.PROJECT_TEMPLATES) assert.match(t, RE);
|
|
246
|
+
for (const t of ['blob-tint', 'pair-wash', 'bead-chrome', 'blob-wash', 'pair-chrome', 'bead-tint', 'blob-chrome', 'pair-tint', 'bead-wash']) assert.ok(P.PROJECT_TEMPLATES.includes(t), `the first round's ${t} stays valid`);
|
|
247
|
+
// the walk: twelve of them, consecutive positions (wrapping) change shape, material AND style
|
|
248
|
+
const parts = (t) => { const p = t.split('-'); return p.length === 3 ? p : [p[0], 'chrome', p[1]]; };
|
|
249
|
+
assert.equal(P.PROJECT_TEMPLATE_WALK.length, 12);
|
|
250
|
+
assert.equal(new Set(P.PROJECT_TEMPLATE_WALK).size, 12, 'twelve distinct walk positions');
|
|
251
|
+
for (let i = 0; i < P.PROJECT_TEMPLATE_WALK.length; i++) {
|
|
252
|
+
const [s0, m0, y0] = parts(P.PROJECT_TEMPLATE_WALK[(i + 11) % 12]);
|
|
253
|
+
const [s1, m1, y1] = parts(P.PROJECT_TEMPLATE_WALK[i]);
|
|
254
|
+
assert.ok(s0 !== s1 && m0 !== m1 && y0 !== y1, `walk step ${i} changes shape, material and style`);
|
|
255
|
+
assert.ok(P.PROJECT_TEMPLATES.includes(P.PROJECT_TEMPLATE_WALK[i]), 'every walk position is a valid name');
|
|
247
256
|
}
|
|
248
|
-
//
|
|
249
|
-
const mig = readFileSync(new URL('../migrations/
|
|
250
|
-
for (const t of P.PROJECT_TEMPLATES) assert.ok(mig.includes(`'${t}'`), `migration
|
|
257
|
+
// migration 013 pins the same thirty-six (012 named the first nine)
|
|
258
|
+
const mig = readFileSync(new URL('../migrations/platform_identity_013_project_template_materials.sql', import.meta.url), 'utf8');
|
|
259
|
+
for (const t of P.PROJECT_TEMPLATES) assert.ok(mig.includes(`'${t}'`), `migration 013 names ${t}`);
|
|
260
|
+
const mig12 = readFileSync(new URL('../migrations/platform_identity_012_project_template.sql', import.meta.url), 'utf8');
|
|
261
|
+
for (const t of P.PROJECT_TEMPLATES.slice(0, 9)) assert.ok(mig12.includes(`'${t}'`), `migration 012 named ${t}`);
|
|
251
262
|
// and the public projection carries it, so the sky can read a curated choice
|
|
252
263
|
const pool3 = mockPool([{ rows: [] }]);
|
|
253
264
|
await P.listFeaturedProjects({ pool: pool3 });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"projects":[{"origin":"https://amazonprimea.com","name":"Off the Boats","tagline":"A singular shop, and a broader videogame in a persistent ancient Greek world that collides with modern day commerce & products.","art_url":"/assets/world/r2-chrome-blob-one.jpg","type":"game","template":"bead-wash","created_at":"2026-07-15T22:12:57.732Z","builders":11,"tags":["art-pipeline","character-anim","demo","game"],"owner":"lars589","owner_avatar":"https://avatars.githubusercontent.com/u/283020391?v=4","faces":["https://avatars.githubusercontent.com/u/283020391?v=4","https://avatars.githubusercontent.com/u/64553469?v=4","https://avatars.githubusercontent.com/u/290184380?v=4","https://avatars.githubusercontent.com/u/295990394?v=4","https://avatars.githubusercontent.com/u/35337514?v=4"],"shipped_30d":0,"shipped_30d_capped":false,"hall_origin":"https://builders.amazonprimea.com"},{"origin":"https://demo.cloudbongos.com","name":"Demo","tagline":"A live demo instance on Cloud Bongos.","art_url":null,"type":null,"template":
|
|
1
|
+
{"projects":[{"origin":"https://amazonprimea.com","name":"Off the Boats","tagline":"A singular shop, and a broader videogame in a persistent ancient Greek world that collides with modern day commerce & products.","art_url":"/assets/world/r2-chrome-blob-one.jpg","type":"game","template":"bead-wash","created_at":"2026-07-15T22:12:57.732Z","builders":11,"tags":["art-pipeline","character-anim","demo","game"],"owner":"lars589","owner_avatar":"https://avatars.githubusercontent.com/u/283020391?v=4","faces":["https://avatars.githubusercontent.com/u/283020391?v=4","https://avatars.githubusercontent.com/u/64553469?v=4","https://avatars.githubusercontent.com/u/290184380?v=4","https://avatars.githubusercontent.com/u/295990394?v=4","https://avatars.githubusercontent.com/u/35337514?v=4"],"shipped_30d":0,"shipped_30d_capped":false,"hall_origin":"https://builders.amazonprimea.com"},{"origin":"https://demo.cloudbongos.com","name":"Demo","tagline":"A live demo instance on Cloud Bongos.","art_url":null,"type":null,"template":"pair-gold-wash","created_at":"2026-07-14T19:16:38.160Z","builders":null,"tags":null,"owner":null,"owner_avatar":null,"faces":null,"shipped_30d":null,"shipped_30d_capped":null,"hall_origin":null},{"origin":"https://emersonian-circles.cloudbongos.com","name":"Emersonian Circles","tagline":"An independent project built on Cloud Bongos.","art_url":null,"type":null,"template":null,"created_at":"2026-07-25T02:21:55.641Z","builders":1,"tags":[],"owner":"lars589","owner_avatar":"https://avatars.githubusercontent.com/u/283020391?v=4","faces":[],"shipped_30d":30,"shipped_30d_capped":true,"hall_origin":null}]}
|
|
@@ -235,7 +235,8 @@ function reducedMotionProblems({ running = [], frames = 0 } = {}) {
|
|
|
235
235
|
|
|
236
236
|
// ── the states file ───────────────────────────────────────────────────────────
|
|
237
237
|
// { "page": "/projects", "surface"?: "public-landing", "stub"?: { prefix?, child? },
|
|
238
|
-
// "
|
|
238
|
+
// "modes"?: ["dark" | "light", …] (the modes the page renders; default both — a page that pins
|
|
239
|
+
// one mode declares it here), "modeQuery"?: "mode" | false, "ignoreRequests"?: [regex strings], "ignoreConsole"?: [...],
|
|
239
240
|
// "ignoreControls"?: [selectors], "states": { name: { url?, auth?, actions?, expect? } },
|
|
240
241
|
// "reducedMotion"?: { auth?, url?, actions? } }
|
|
241
242
|
function validateStatesFile(json) {
|
|
@@ -245,6 +246,7 @@ function validateStatesFile(json) {
|
|
|
245
246
|
if (json.surface !== undefined && typeof json.surface !== 'string') errors.push('surface: a string (a checkout dir or a module key)');
|
|
246
247
|
errors.push(...validateStub(json.stub, 'stub'));
|
|
247
248
|
if (json.modeQuery !== undefined && json.modeQuery !== false && typeof json.modeQuery !== 'string') errors.push('modeQuery: the query param the page reads for its colour mode (default "mode"), or false');
|
|
249
|
+
if (json.modes !== undefined && !(Array.isArray(json.modes) && json.modes.length && json.modes.every((m) => MODES.includes(m)))) errors.push('modes: a non-empty array of "dark" | "light" — the modes the page renders (default both); a page that pins one mode declares it here');
|
|
248
250
|
for (const k of ['ignoreRequests', 'ignoreConsole', 'ignoreControls']) if (json[k] !== undefined && !(Array.isArray(json[k]) && json[k].every((s) => typeof s === 'string'))) errors.push(`${k}: an array of strings`);
|
|
249
251
|
const states = json.states;
|
|
250
252
|
if (!states || typeof states !== 'object' || Array.isArray(states) || !Object.keys(states).length) errors.push('states: required — a non-empty object of name → { url?, auth?, actions?, expect? }');
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
// render.js — render a page's states and audit every render against the platform
|
|
4
4
|
// floors (task 1003320, ADR 0197). The states live in a JSON file BESIDE the
|
|
5
5
|
// surface (<dir>/<page>.states.json: name → url + actions + expectations); each
|
|
6
|
-
// is rendered
|
|
7
|
-
//
|
|
8
|
-
//
|
|
6
|
+
// is rendered at 1440x900 / 390x844 / 320x700 in the modes the states file names
|
|
7
|
+
// (`"modes"`; both by default — the apex pins dark, task 1003336; `--modes` overrides)
|
|
8
|
+
// through two stubs this file starts itself (signed out, signed in), then a
|
|
9
|
+
// reduced-motion pass per mode. Writes the shots + a JSON report; exits non-zero on any problem.
|
|
9
10
|
//
|
|
10
11
|
// node modules/ui-design/kit/render.js --page /projects (public-landing/projects.states.json)
|
|
11
12
|
// node modules/ui-design/kit/render.js --page /builders/ranks --surface hall-ui
|
|
@@ -65,7 +66,7 @@ async function main() {
|
|
|
65
66
|
const args = process.argv.slice(2);
|
|
66
67
|
if (lib.hasFlag(args, '--help')) usage('');
|
|
67
68
|
const { file, json, surface } = locate(args);
|
|
68
|
-
const modes = lib.listArg(args, '--modes', [...lib.MODES]).filter((m) => lib.MODES.includes(m));
|
|
69
|
+
const modes = lib.listArg(args, '--modes', json.modes || [...lib.MODES]).filter((m) => lib.MODES.includes(m));
|
|
69
70
|
const sizes = lib.listArg(args, '--sizes', Object.keys(lib.SIZES)).map(Number).filter((w) => lib.SIZES[w]);
|
|
70
71
|
const only = lib.listArg(args, '--only', null);
|
|
71
72
|
const names = Object.keys(json.states).filter((n) => !only || only.includes(n));
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.415",
|
|
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.415",
|
|
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.415",
|
|
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",
|