@bongos/core 1.19.726 → 1.19.727

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (226) hide show
  1. package/.bongos-core.json +176 -491
  2. package/.devcontainer/Dockerfile +1 -1
  3. package/.devcontainer/devcontainer.json +2 -2
  4. package/.devcontainer/healthcheck.sh +1 -1
  5. package/.devcontainer/init-firewall.sh +1 -1
  6. package/.devcontainer/post-create.sh +2 -2
  7. package/.env.local.example +1 -1
  8. package/Dockerfile +1 -1
  9. package/docs/copy-inventory.md +1 -1
  10. package/docs/copy-registry.json +9 -9
  11. package/docs/module-api-changelog.md +2 -0
  12. package/docs/recipes/devbox-app-release.md +4 -4
  13. package/modules/dev-box/app/scripts/dmgbuild-settings.py +5 -5
  14. package/modules/dev-box/app/scripts/gen-brand.js +1 -1
  15. package/modules/dev-box/app/src/brand.js +1 -1
  16. package/modules/dev-box/app/test/unit.mjs +16 -16
  17. package/modules/dev-box/box-access.js +1 -1
  18. package/modules/dev-box/routes/box.js +1 -1
  19. package/modules/discord/discord-approvals.js +1 -1
  20. package/modules/grading/grader-model.js +1 -1
  21. package/modules/grading/grader-prompt.js +1 -1
  22. package/modules/grading/grader-workers/quality.js +1 -1
  23. package/modules/hall-ui/module.json +1 -1
  24. package/modules/hall-ui/public/brand-apply.js +1 -1
  25. package/modules/hall-ui/public/shell.js +1 -1
  26. package/modules/hall-ui/public/work.js +1 -1
  27. package/modules/lifecycle/conflict-resolve.js +1 -1
  28. package/modules/lifecycle/db-analytics.js +1 -1
  29. package/modules/lifecycle/routes/analytics.js +1 -1
  30. package/modules/onboarding/approval-broadcast.js +1 -1
  31. package/modules/onboarding/onboarding.js +1 -1
  32. package/modules/provisioning/tests/liveness.mjs +1 -1
  33. package/modules/public-landing/public/index.html +1 -1
  34. package/modules/public-landing/public/projects-floor.states.json +2 -2
  35. package/modules/public-landing/public/projects.probes.json +4 -4
  36. package/modules/public-landing/public/projects.states.json +2 -2
  37. package/modules/status-ui/module.json +1 -1
  38. package/modules/status-ui/public/status.js +4 -4
  39. package/modules/status-ui/public/style.css +1 -1
  40. package/modules/ui-design/kit/fixtures/cost-summary.json +1 -1
  41. package/modules/ui-design/kit/fixtures/featured-hub.json +1 -1
  42. package/modules/ui-design/kit/fixtures/featured.json +1 -1
  43. package/modules/ui-design/kit/fixtures/leaderboard.json +1 -1
  44. package/modules/ui-design/kit/fixtures/my-projects.json +1 -1
  45. package/modules/ui-design/kit/fixtures/progress.json +1 -1
  46. package/modules/ui-design/kit/fixtures/recent-shipped.json +1 -1
  47. package/package-lock.json +2 -2
  48. package/package.json +1 -1
  49. package/scripts/cron/style_guide_audit.sh +1 -1
  50. package/scripts/discord/lib.js +1 -1
  51. package/scripts/discord/post.js +1 -1
  52. package/scripts/gds/audit-authorship.sh +1 -1
  53. package/scripts/gds/audit-replay.sh +29 -2
  54. package/scripts/gds/audit-ships.js +1 -1
  55. package/scripts/gds/backfill-sessions.js +2 -2
  56. package/scripts/gds/cf-tunnel.js +4 -4
  57. package/scripts/gds/claude-materialize.js +2 -2
  58. package/scripts/gds/cli-lib.js +6 -6
  59. package/scripts/gds/cutover-codemod.js +1 -1
  60. package/scripts/gds/dev-lib.js +2 -2
  61. package/scripts/gds/diagnose-achievements.js +2 -2
  62. package/scripts/gds/fitness-checks-identity.js +6 -4
  63. package/scripts/gds/gen-diagrams.js +1 -1
  64. package/scripts/gds/leak-scan-allowlist.js +293 -0
  65. package/scripts/gds/learning-capture.js +1 -1
  66. package/scripts/gds/linkify-refs.js +2 -2
  67. package/scripts/gds/local-preview-lib.js +1 -1
  68. package/scripts/gds/mirror-lineage-check.js +1 -1
  69. package/scripts/gds/mirror-redact.js +17 -2
  70. package/scripts/gds/newcomer-floor.templates.json +1 -1
  71. package/scripts/gds/package-core.js +18 -1
  72. package/scripts/gds/paste-token.js +1 -1
  73. package/scripts/gds/provision-units.js +2 -2
  74. package/scripts/gds/publish-manifest.js +15 -0
  75. package/scripts/gds/repo-metrics.js +1 -1
  76. package/scripts/gds/sandbox-stage.js +1 -1
  77. package/scripts/gds/seed-bongos-coreB-tranche1-tasks.js +1 -1
  78. package/scripts/gds/seed-bongos-coreB-tranche2-tasks.js +1 -1
  79. package/scripts/gds/seed-bongos-goal-hierarchy-tasks.js +1 -1
  80. package/scripts/gds/seed-bongos-tasks.js +2 -2
  81. package/scripts/gds/seed-gds-v4-tasks.js +1 -1
  82. package/scripts/gds/seed-medusa-tasks.js +10 -10
  83. package/scripts/gds/seed-module-upstreaming.js +1 -1
  84. package/scripts/gds/seed-productization-tasks.js +6 -6
  85. package/scripts/gds/seed-provisioning-tasks.js +2 -2
  86. package/scripts/gds/seed-staging.sh +19 -6
  87. package/scripts/gds/ship-deploy-target.js +1 -1
  88. package/scripts/gds/ship-flow.js +1 -1
  89. package/scripts/gds/smoke-gds.js +1 -1
  90. package/scripts/status-probe.mjs +2 -2
  91. package/src/bongos/auth-discord.js +2 -2
  92. package/src/bongos/live-channel.js +1 -1
  93. package/src/bongos/pool.js +1 -1
  94. package/src/bongos/routes/auth.js +11 -11
  95. package/src/bongos/routes/security.js +1 -1
  96. package/src/bongos/routes.js +1 -1
  97. package/src/branding.js +1 -1
  98. package/src/devbox-downloads.js +1 -1
  99. package/src/instance-config.js +2 -2
  100. package/src/module-api.js +1 -1
  101. package/src/module-loader/provenance.js +2 -2
  102. package/tests/art_stage.mjs +2 -2
  103. package/tests/auth_anthropic_identity.mjs +1 -1
  104. package/tests/auth_duplicate_cookie.mjs +1 -1
  105. package/tests/auth_error_brand.mjs +1 -1
  106. package/tests/auth_inactive_builder.mjs +1 -1
  107. package/tests/backup_cli.mjs +4 -4
  108. package/tests/bongos_box_connect.mjs +2 -2
  109. package/tests/bongos_downloads.mjs +2 -2
  110. package/tests/bongos_login.mjs +5 -5
  111. package/tests/box_connect_e2e.mjs +2 -2
  112. package/tests/box_dns_repoint.mjs +10 -10
  113. package/tests/box_host_keys.mjs +1 -1
  114. package/tests/box_onboard.mjs +9 -9
  115. package/tests/box_scope_session.mjs +1 -1
  116. package/tests/box_terminal_ssrf.mjs +7 -7
  117. package/tests/boxes.mjs +9 -9
  118. package/tests/branding.mjs +2 -2
  119. package/tests/bump_version.mjs +2 -2
  120. package/tests/cf_tunnel.mjs +40 -40
  121. package/tests/cli_token_reissue.mjs +7 -7
  122. package/tests/cloud_bongos_pack.mjs +1 -1
  123. package/tests/currency_label.mjs +8 -8
  124. package/tests/dev_lib.mjs +4 -4
  125. package/tests/devbox_dmg_backdrop.mjs +1 -1
  126. package/tests/devbox_downloads.mjs +2 -2
  127. package/tests/devbox_icons.mjs +1 -1
  128. package/tests/discord_approvals.mjs +1 -1
  129. package/tests/discord_oauth.mjs +2 -2
  130. package/tests/executed_closure.mjs +6 -1
  131. package/tests/first_admin_bootstrap.mjs +1 -1
  132. package/tests/gate_approvals.mjs +5 -5
  133. package/tests/grade_aggregates_unavailable.mjs +1 -1
  134. package/tests/hook_user_agents.mjs +2 -2
  135. package/tests/init.mjs +6 -6
  136. package/tests/instance_config.mjs +1 -1
  137. package/tests/instance_manifest.mjs +5 -5
  138. package/tests/instance_mismatch_guard.mjs +13 -13
  139. package/tests/leak_scan_allowlist.mjs +94 -0
  140. package/tests/migrate_root_resolution.mjs +4 -4
  141. package/tests/mirror_redact.mjs +28 -4
  142. package/tests/module_catalog.mjs +5 -5
  143. package/tests/module_submissions.mjs +3 -3
  144. package/tests/package_core.mjs +1 -1
  145. package/tests/parallel-load.mjs +6 -6
  146. package/tests/projects_hub.mjs +2 -2
  147. package/tests/provision.mjs +50 -50
  148. package/tests/provisioning_github_app_routes.mjs +1 -1
  149. package/tests/provisioning_onboard_mode.mjs +2 -2
  150. package/tests/publish_reconciler.mjs +4 -4
  151. package/tests/sandbox_stage.mjs +1 -1
  152. package/tests/scrubber_corpus.mjs +3 -3
  153. package/tests/search_isolation.mjs +1 -1
  154. package/tests/session_records.mjs +1 -1
  155. package/tests/ship_card.mjs +6 -6
  156. package/tests/ship_ci_deploy.mjs +1 -1
  157. package/tests/single_host_hall.mjs +9 -9
  158. package/tests/smoke_preflight.mjs +1 -1
  159. package/tests/smoke_target.mjs +1 -1
  160. package/tests/status-probe.mjs +1 -1
  161. package/tests/status_mirror_sync.mjs +1 -1
  162. package/docs/adr/0004-amazonprimea-name-and-trademark-acceptance.md +0 -45
  163. package/docs/design/mocks/_schemes.css +0 -604
  164. package/docs/design/mocks/component-sheet.html +0 -428
  165. package/docs/design/mocks/hall/_tokens.css +0 -370
  166. package/docs/design/mocks/hall/board/v1.html +0 -846
  167. package/docs/design/mocks/hall/board/v2.html +0 -858
  168. package/docs/design/mocks/hall/board/v3.html +0 -884
  169. package/docs/design/mocks/hall/goals/v1.html +0 -1212
  170. package/docs/design/mocks/hall/goals/v2.html +0 -1192
  171. package/docs/design/mocks/hall/goals/v3.html +0 -1205
  172. package/docs/design/mocks/hall/hall-sheet.html +0 -244
  173. package/docs/design/mocks/hall/reading/v1.html +0 -1125
  174. package/docs/design/mocks/hall/reading/v2.html +0 -1177
  175. package/docs/design/mocks/hall/reading/v3.html +0 -1150
  176. package/docs/design/mocks/hall/settings/v1.html +0 -1238
  177. package/docs/design/mocks/hall/settings/v2.html +0 -1235
  178. package/docs/design/mocks/hall/settings/v3.html +0 -1299
  179. package/docs/design/mocks/hall/task/v1.html +0 -633
  180. package/docs/design/mocks/hall/task/v2.html +0 -646
  181. package/docs/design/mocks/hall/task/v3.html +0 -647
  182. package/docs/design/mocks/hub/assets/r3-space-deepfield-half.jpg +0 -0
  183. package/docs/design/mocks/hub/assets/r3-space-deepfield-half.jpg.json +0 -13
  184. package/docs/design/mocks/hub/assets/r3-space-dust-half.jpg +0 -0
  185. package/docs/design/mocks/hub/assets/r3-space-dust-half.jpg.json +0 -13
  186. package/docs/design/mocks/hub/assets/r3-space-nebula-half.jpg +0 -0
  187. package/docs/design/mocks/hub/assets/r3-space-nebula-half.jpg.json +0 -13
  188. package/docs/design/mocks/hub/assets/r3-space-starfield-half.jpg +0 -0
  189. package/docs/design/mocks/hub/assets/r3-space-starfield-half.jpg.json +0 -13
  190. package/docs/design/mocks/hub/hub-sheet.html +0 -192
  191. package/docs/design/mocks/hub/mine.html +0 -465
  192. package/docs/design/mocks/hub/picker.html +0 -421
  193. package/docs/design/mocks/hub/planets.html +0 -356
  194. package/docs/design/mocks/hub/v1.html +0 -1209
  195. package/docs/design/mocks/hub/v2.html +0 -1257
  196. package/docs/design/mocks/hub/v3.html +0 -1496
  197. package/docs/design/mocks/hub/wizard.html +0 -421
  198. package/docs/design/mocks/landing/landing-sheet.html +0 -131
  199. package/docs/design/mocks/landing/v1.html +0 -956
  200. package/docs/design/mocks/landing/v2.html +0 -708
  201. package/docs/design/mocks/landing/v3.html +0 -911
  202. package/docs/design/mocks/landing-page-mock.html +0 -687
  203. package/docs/design/mocks/landing-palettes.html +0 -103
  204. package/docs/design/mocks/projects-hub-mock.html +0 -991
  205. package/docs/design/mocks/projects-hub-variants.html +0 -146
  206. package/docs/design/mocks/projects-page-mock.html +0 -167
  207. package/docs/design/mocks/world/blue-hud/_tokens.css +0 -246
  208. package/docs/design/mocks/world/blue-hud/hall.html +0 -595
  209. package/docs/design/mocks/world/blue-hud/landing.html +0 -424
  210. package/docs/design/mocks/world/blue-hud/status.html +0 -410
  211. package/docs/design/mocks/world/chrome-blobs/_tokens.css +0 -479
  212. package/docs/design/mocks/world/chrome-blobs/hall.html +0 -553
  213. package/docs/design/mocks/world/chrome-blobs/landing-b.html +0 -581
  214. package/docs/design/mocks/world/chrome-blobs/landing.html +0 -328
  215. package/docs/design/mocks/world/chrome-blobs/status.html +0 -416
  216. package/docs/design/mocks/world/natgeo-editorial/_tokens.css +0 -377
  217. package/docs/design/mocks/world/natgeo-editorial/hall.html +0 -649
  218. package/docs/design/mocks/world/natgeo-editorial/landing-b.html +0 -743
  219. package/docs/design/mocks/world/natgeo-editorial/landing.html +0 -475
  220. package/docs/design/mocks/world/natgeo-editorial/status.html +0 -437
  221. package/docs/design/mocks/world/organic-cards/_tokens.css +0 -462
  222. package/docs/design/mocks/world/organic-cards/hall.html +0 -625
  223. package/docs/design/mocks/world/organic-cards/landing-b.html +0 -736
  224. package/docs/design/mocks/world/organic-cards/landing.html +0 -420
  225. package/docs/design/mocks/world/organic-cards/status.html +0 -458
  226. package/docs/design/mocks/world/world-sheet.html +0 -156
@@ -1,1209 +0,0 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="utf-8">
5
- <script>
6
- (function(){try{var q=new URLSearchParams(location.search || location.hash.slice(1) || (window.__Q || '')).get('mode');var m=(q==='light'||q==='dark')?q:localStorage.getItem('cb-color-mode');if(m==='light'||m==='dark')document.documentElement.setAttribute('data-mode',m);}catch(e){}})();
7
- </script>
8
- <meta name="viewport" content="width=device-width,initial-scale=1">
9
- <title>The shelf, hub v1</title>
10
- <link rel="icon" href="data:,">
11
- <link rel="preconnect" href="https://fonts.googleapis.com">
12
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
13
- <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400&family=Manrope:wght@300;400;500;600&display=swap">
14
- <link rel="stylesheet" href="../../../../modules/public-landing/public/assets/cosmos.css">
15
- <style>
16
- /* ═══════════════ v1 "the shelf" — the page tier ═══════════════════════════
17
- cosmos.css above carries the fifteen contract tokens, the sky, the orbs, the
18
- hover card, the toolbar, the table, the mine list and the footer. What lands
19
- here is the world's DERIVED tier (DESIGN.md's recipes, its names) declared on
20
- `body` — never :root, which the branding pack owns — plus this version's own
21
- chrome: the shelf, its two menus, its search, and the poster card.
22
- --line, --ok, --warn and --err are cosmos's on this page and are not touched. */
23
- *{box-sizing:border-box}
24
- body{
25
- /* geometry */
26
- --gutter:26px; --gutter-narrow:20px;
27
- --radius:16px; --radius-sm:10px; --radius-pill:999px; --top-h:72px;
28
- --r-card:16px; /* cosmos's own .projCard hook */
29
- --search-row-h:0px;
30
- /* glass + the void (translucent ink over paper in light, white over black in dark) */
31
- --void-glass:color-mix(in srgb, var(--ink) 5%, transparent);
32
- --void-glass-strong:color-mix(in srgb, var(--ink) 9%, transparent);
33
- --void-glass-edge:color-mix(in srgb, var(--ink) 12%, transparent);
34
- --void-pill:rgba(0,0,0,.5);
35
- --glass:color-mix(in srgb, var(--ink) 5%, transparent);
36
- --glass-strong:color-mix(in srgb, var(--ink) 8%, transparent);
37
- --glass-edge:color-mix(in srgb, var(--ink) 12%, transparent);
38
- --glass-blur:0px;
39
- /* the shelf and the pills that sit on it */
40
- --shelf-bg:var(--bg-frame);
41
- --shelf-edge:var(--rule-soft);
42
- --pill-bg:color-mix(in srgb, var(--bg) 88%, transparent);
43
- --pill-bg-hi:color-mix(in srgb, var(--bg-card) 94%, transparent);
44
- --pill-edge:var(--rule-soft);
45
- --panel-bg:var(--bg-card);
46
- --door-ground:color-mix(in srgb, var(--bg-card) 93%, transparent);
47
- --door-edge:var(--rule);
48
- /* accent behaviours + the lit mark (the current view is the live one) */
49
- --accent-lift:color-mix(in srgb, var(--accent) 58%, #ffffff);
50
- --accent-glow:0 0 0 0 transparent;
51
- --mark-lit:var(--accent-deep);
52
- --focus:var(--accent-deep);
53
- /* the label face flips: mono on paper, the body face on black */
54
- --label-face:var(--font-mono); --label-size:11px; --label-space:.12em;
55
- --sun-display:none; --moon-display:block;
56
- font-family:var(--font-body);
57
- }
58
- :root[data-mode="dark"] body{
59
- --void-glass:color-mix(in srgb, var(--ink) 7.5%, transparent);
60
- --void-glass-strong:color-mix(in srgb, var(--ink) 14%, transparent);
61
- --void-glass-edge:color-mix(in srgb, var(--ink) 11%, transparent);
62
- --glass:color-mix(in srgb, var(--ink) 11%, transparent);
63
- --glass-strong:color-mix(in srgb, var(--ink) 17%, transparent);
64
- --glass-edge:color-mix(in srgb, var(--ink) 13%, transparent);
65
- --glass-blur:18px;
66
- --pill-bg:var(--void-glass);
67
- --pill-bg-hi:var(--void-glass-strong);
68
- --pill-edge:var(--void-glass-edge);
69
- --panel-bg:color-mix(in srgb, var(--bg-card) 88%, transparent);
70
- --door-ground:var(--void-pill);
71
- --door-edge:var(--void-glass-edge);
72
- --accent-glow:0 8px 28px color-mix(in srgb, var(--accent) 38%, transparent);
73
- --mark-lit:var(--accent);
74
- --focus:var(--accent);
75
- --label-face:var(--font-body); --label-size:11.5px; --label-space:.1em;
76
- --sun-display:block; --moon-display:none;
77
- }
78
- @media (prefers-color-scheme: dark){
79
- :root:not([data-mode="light"]) body{
80
- --void-glass:color-mix(in srgb, var(--ink) 7.5%, transparent);
81
- --void-glass-strong:color-mix(in srgb, var(--ink) 14%, transparent);
82
- --void-glass-edge:color-mix(in srgb, var(--ink) 11%, transparent);
83
- --glass:color-mix(in srgb, var(--ink) 11%, transparent);
84
- --glass-strong:color-mix(in srgb, var(--ink) 17%, transparent);
85
- --glass-edge:color-mix(in srgb, var(--ink) 13%, transparent);
86
- --glass-blur:18px;
87
- --pill-bg:var(--void-glass);
88
- --pill-bg-hi:var(--void-glass-strong);
89
- --pill-edge:var(--void-glass-edge);
90
- --panel-bg:color-mix(in srgb, var(--bg-card) 88%, transparent);
91
- --door-ground:var(--void-pill);
92
- --door-edge:var(--void-glass-edge);
93
- --accent-glow:0 8px 28px color-mix(in srgb, var(--accent) 38%, transparent);
94
- --mark-lit:var(--accent);
95
- --focus:var(--accent);
96
- --label-face:var(--font-body); --label-size:11.5px; --label-space:.1em;
97
- --sun-display:block; --moon-display:none;
98
- }
99
- }
100
-
101
- /* ---------- browser surfaces: the parts nobody draws still carry the world -- */
102
- ::selection{background:var(--accent);color:var(--accent-on)}
103
- :focus-visible,.is-focus,.searchPill:focus-within{outline:2px solid var(--focus);
104
- outline-offset:3px;box-shadow:0 0 0 8px var(--bg)}
105
- a{color:inherit;text-decoration:none}
106
- .lbl{font-family:var(--label-face);font-size:var(--label-size);letter-spacing:var(--label-space);
107
- text-transform:uppercase}
108
- .num{font-variant-numeric:tabular-nums}
109
-
110
- .skip{position:absolute;left:-9999px;top:0;z-index:99;display:inline-flex;align-items:center;
111
- min-height:24px;padding:11px 18px;border-radius:var(--radius-pill);background:var(--bg-card);
112
- color:var(--ink);border:1px solid var(--rule);font-size:14px}
113
- .skip:focus{left:14px;top:14px}
114
-
115
- /* ═══════════════ THE SHELF ════════════════════════════════════════════════
116
- A real surface with its own ground and a bottom edge, 72px, not sticky. The
117
- landing's three pill groups sit ON it rather than floating over the sky, so
118
- the hub and the front door read as one product. */
119
- .bar{position:relative;z-index:50;height:var(--top-h);display:flex;align-items:center;
120
- padding:0 var(--gutter);background:var(--shelf-bg);border-bottom:1px solid var(--shelf-edge)}
121
- .barIn{display:flex;align-items:center;gap:12px;width:100%;min-width:0}
122
- .grpL{display:flex;align-items:center;gap:12px;min-width:0;flex:1 1 auto}
123
- .grpR{display:flex;align-items:center;gap:10px;flex:none;margin-left:auto}
124
-
125
- .cpill{display:inline-flex;align-items:center;justify-content:center;gap:9px;min-height:46px;
126
- padding:0 18px;border-radius:var(--radius-pill);background:var(--pill-bg);
127
- border:1px solid var(--pill-edge);backdrop-filter:blur(var(--glass-blur));
128
- -webkit-backdrop-filter:blur(var(--glass-blur));font-family:var(--font-body);font-size:15px;
129
- font-weight:400;color:var(--ink);cursor:pointer;white-space:nowrap;
130
- transition:background 240ms cubic-bezier(.2,.7,.3,1),color 200ms ease}
131
- .cpill:hover{background:var(--pill-bg-hi)}
132
- .markPill{padding:0 20px;gap:10px;background:var(--pill-bg-hi);letter-spacing:-.012em;flex:none}
133
- .markPill svg{width:23px;height:18px;display:block;flex:none}
134
- .markWord{white-space:nowrap}
135
-
136
- .searchPill{width:260px;padding:0 16px;gap:9px;cursor:text;justify-content:flex-start;
137
- transition:width 280ms cubic-bezier(.2,.7,.3,1),background 240ms cubic-bezier(.2,.7,.3,1)}
138
- .searchPill:focus-within,.searchPill.is-focus{width:340px;background:var(--pill-bg-hi)}
139
- .searchPill .mag{width:15px;height:15px;flex:none;fill:none;stroke:var(--ink-faint);stroke-width:2;
140
- stroke-linecap:round}
141
- .searchPill input{flex:1 1 auto;min-width:0;min-height:24px;align-self:stretch;border:0;
142
- background:none;outline:none;font-family:var(--font-body);font-size:14px;color:var(--ink)}
143
- .searchPill input::placeholder{color:var(--ink-faint)}
144
- /* the ring belongs to the pill a visitor sees as the control, so the field
145
- itself paints neither an outline nor the halo that would go with it */
146
- .searchPill input:focus,.searchPill input:focus-visible{outline:none;box-shadow:none}
147
- .searchPill .count{flex:none;color:var(--ink-faint);white-space:nowrap;text-transform:none;
148
- letter-spacing:.02em}
149
- .bar[data-view="mine"] .searchPill,.bar[data-view="new"] .searchPill{display:none}
150
-
151
- .mode-toggle{width:46px;min-width:46px;padding:0}
152
- .mode-toggle svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.4;
153
- stroke-linecap:round;stroke-linejoin:round}
154
- .sun{display:var(--sun-display)}
155
- .moon{display:var(--moon-display)}
156
-
157
- .crt{width:11px;height:11px;flex:none;fill:none;stroke:currentColor;stroke-width:1.5;
158
- stroke-linecap:round;stroke-linejoin:round;color:var(--ink-faint);
159
- transition:transform 220ms cubic-bezier(.2,.7,.3,1)}
160
- [aria-expanded="true"] .crt{transform:rotate(180deg)}
161
-
162
- .signin{background:color-mix(in srgb, var(--ink) 92%, var(--bg));color:var(--bg);
163
- border-color:transparent;text-transform:lowercase;font-weight:500;padding:0 26px}
164
- .signin:hover{background:var(--ink);color:var(--bg)}
165
- .chipPill{padding:0 12px 0 9px;gap:8px}
166
- .chipPill img{width:26px;height:26px;border-radius:var(--radius-pill);object-fit:cover;flex:none}
167
- .whoName{max-width:14ch;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
168
- .cpill.trigger{text-transform:lowercase;padding:0 16px}
169
- .bar[data-auth="out"] .idChip{display:none}
170
- .bar[data-auth="in"] .signin{display:none}
171
-
172
- /* ---------- the menu: a card panel under a chrome trigger ------------------ */
173
- .menu{position:relative;flex:none}
174
- .menuPanel{position:absolute;top:calc(100% + 8px);right:0;width:240px;padding:6px;margin:0;
175
- list-style:none;background:var(--panel-bg);border:1px solid var(--rule);
176
- border-radius:var(--radius);backdrop-filter:blur(var(--glass-blur));
177
- -webkit-backdrop-filter:blur(var(--glass-blur));z-index:60;
178
- animation:menuIn 220ms cubic-bezier(.16,1,.3,1) both}
179
- @keyframes menuIn{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
180
- .menuPanel li{list-style:none}
181
- .menuPanel a{display:flex;align-items:center;gap:10px;min-height:44px;padding:0 14px;
182
- border-radius:var(--radius-sm);color:var(--ink-soft);font-size:15px;text-transform:lowercase;
183
- transition:background 200ms cubic-bezier(.2,.7,.3,1),color 200ms ease}
184
- .menuPanel a:hover,.menuPanel a.is-hover{background:var(--glass);color:var(--ink)}
185
- .menuPanel a[aria-current="page"]{color:var(--ink)}
186
- .menuPanel .dot{width:6px;height:6px;border-radius:50%;background:transparent;flex:none}
187
- .menuPanel a[aria-current="page"] .dot{background:var(--mark-lit)}
188
- .menuId{display:flex;align-items:center;gap:9px;padding:8px 14px 10px;color:var(--ink-faint)}
189
- .menuId img{width:24px;height:24px;border-radius:50%;object-fit:cover;flex:none}
190
- .menuRule{height:1px;margin:6px 8px;background:var(--rule-soft);list-style:none}
191
-
192
- /* ═══════════════ the carried page, re-aligned to the shelf ════════════════ */
193
- .toolbar{padding:16px var(--gutter)}
194
- .tbl th button{display:inline-flex;align-items:center;min-height:24px}
195
- .hallGlyph{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;
196
- margin-right:8px;vertical-align:middle;border-radius:50%;border:1px solid var(--rule-soft);
197
- color:var(--ink-soft);transition:color 200ms ease,border-color 200ms ease}
198
- .hallGlyph:hover{color:var(--ink);border-color:var(--rule)}
199
- .hallGlyph svg{width:17px;height:17px;fill:none;stroke:currentColor;stroke-width:1.4;
200
- stroke-linecap:round;stroke-linejoin:round}
201
- .search input{min-height:24px}
202
- /* the table on a phone: cosmos already drops Runs and Type at 780; Status goes
203
- with them, because a catalog row's chip says the same thing on every row and
204
- the name is what a phone came for. Nothing scrolls sideways. */
205
- @media (max-width:780px){
206
- .tbl .colStatus{display:none}
207
- .tbl td,.tbl th{padding:12px 10px}
208
- .tbl th{font-size:10.5px;letter-spacing:.4px}
209
- .tbl .ptitle{font-size:14px}
210
- .tbl .pname{gap:8px}
211
- .tbl .btn.small{padding:8px 11px;font-size:12.5px}
212
- .hallGlyph{width:30px;height:30px;margin-right:6px}
213
- /* the row still has a floor: past it the panel scrolls inside itself, so the
214
- PAGE never scrolls sideways at any width */
215
- #sub-table-body{overflow-x:auto}
216
- .tbl{min-width:330px}
217
- }
218
- .foot a,.finePrint a{display:inline-block;padding:3px 0;min-height:24px}
219
- #view-mine .hero h2,#view-new h2{font-family:var(--font-display);font-weight:300;
220
- font-size:clamp(26px,3.1vw,42px);line-height:1.06;letter-spacing:-.035em;color:var(--ink);
221
- margin:0 0 8px}
222
- .panel{display:none}
223
- .panel.on{display:block}
224
- .createSplit{grid-template-columns:1fr}
225
- .wizField{display:block;margin-bottom:18px}
226
- .wizField>span{display:block;font-size:13.5px;font-weight:500;color:var(--ink-soft);margin-bottom:7px}
227
- #view-new input[type=text]{width:100%;font-family:var(--font-body);font-size:17px;color:var(--ink);
228
- background:var(--bg-card);border:1px solid var(--rule);border-radius:var(--radius);
229
- padding:13px 16px}
230
- #view-new input[type=text]::placeholder{color:var(--ink-faint)}
231
- .hint{font-size:13px;color:var(--ink-faint);margin-top:7px;min-height:18px}
232
- .nav{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:26px}
233
- .btn.big{width:100%;justify-content:center;font-size:17px;padding:16px 30px}
234
-
235
- /* ═══════════════ THE POSTER CARD ══════════════════════════════════════════
236
- A stack, top to bottom: art, disc, name, tagline, relationship, faces,
237
- figures, facts, doors. Every region is a DIRECT child (the C6 slice rule),
238
- so no region is wrapped in a block container. */
239
- .projCard{position:relative;width:min(560px,100%);background:var(--bg-card);
240
- border:1px solid var(--rule);border-radius:var(--r-card);box-shadow:none;
241
- padding:0 0 22px;text-align:left;overflow:hidden}
242
- .projCard .cardX{position:absolute;top:12px;right:12px;width:36px;height:36px;border-radius:50%;
243
- border:1px solid var(--glass-edge);background:var(--door-ground);color:var(--ink);
244
- display:inline-flex;align-items:center;justify-content:center;cursor:pointer;font-size:0;
245
- backdrop-filter:blur(var(--glass-blur));-webkit-backdrop-filter:blur(var(--glass-blur))}
246
- .projCard .cardX svg{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:1.6;
247
- stroke-linecap:round}
248
- /* the plate is a capture of the landing, so a plain cover crop puts the
249
- landing's own headline, its CTA and its callouts inside a poster that then
250
- repeats them. The view box takes the chrome instead: the lower-left blob at
251
- exactly 5:2, no type in it. object-position is the fallback framing for a
252
- browser without object-view-box, set below the headline. */
253
- .cardArt{display:block;width:100%;aspect-ratio:5/2;object-fit:cover;object-position:50% 88%;
254
- object-view-box:inset(60% 45.4% .3% 2.5%)}
255
- .projCard .cardDot{display:block;position:relative;z-index:1;width:48px;height:48px;
256
- border-radius:50%;box-shadow:none;background:var(--acc,var(--accent));
257
- border:4px solid var(--bg-card);margin:-24px 0 0 var(--gutter)}
258
- .projCard[data-art="off"] .cardArt{display:none}
259
- .projCard[data-art="off"] .cardDot{width:54px;height:54px;margin:26px 0 0 var(--gutter)}
260
- .projCard[data-art="off"] .cardX{border-color:var(--rule);background:transparent}
261
- .cardName{font-family:var(--font-display);font-weight:300;font-size:clamp(24px,2.4vw,28px);
262
- line-height:1.2;letter-spacing:-.03em;color:var(--ink);margin:14px var(--gutter) 0}
263
- .projCard .cardTag{font-size:15px;line-height:1.5;color:var(--ink-soft);
264
- margin:8px var(--gutter) 0;max-width:46ch}
265
- .projCard .cardRel{display:inline-flex;align-items:center;min-height:26px;padding:0 12px;
266
- margin:14px var(--gutter) 0;border-radius:var(--radius-pill);background:var(--glass);
267
- border:1px solid var(--glass-edge);color:var(--ink-soft);font-family:var(--label-face);
268
- font-size:var(--label-size);letter-spacing:var(--label-space);font-weight:400;
269
- text-transform:uppercase}
270
- .faces{display:flex;align-items:center;margin:18px var(--gutter) 0}
271
- .faces img{width:28px;height:28px;border-radius:50%;object-fit:cover;
272
- border:2px solid var(--bg-card);margin-left:-8px}
273
- .faces img:first-child{margin-left:0}
274
- .faces .more{display:inline-flex;align-items:center;justify-content:center;min-width:28px;
275
- height:28px;padding:0 7px;margin-left:-8px;border-radius:var(--radius-pill);
276
- border:2px solid var(--bg-card);background:var(--glass-strong);color:var(--ink-soft)}
277
- .figs{display:grid;grid-template-columns:1fr 1fr;margin:20px var(--gutter) 0;padding-top:18px;
278
- border-top:1px solid var(--rule-soft)}
279
- .fig{display:block;text-align:center}
280
- .figN{display:block;font-family:var(--font-display);font-weight:300;font-size:34px;line-height:1;
281
- letter-spacing:-.035em;color:var(--ink)}
282
- .figL{display:block;margin-top:8px;color:var(--ink-faint)}
283
- .projCard[data-figs="one"] .figs{grid-template-columns:1fr}
284
- .projCard[data-figs="one"] .figShip{display:none}
285
- .projCard[data-figs="none"] .figs{display:none}
286
- .projCard .cardMeta{display:grid;grid-template-columns:auto 1fr;margin:18px var(--gutter) 0;
287
- gap:0;text-align:left}
288
- .projCard[data-facts="off"] .cardMeta{display:none}
289
- /* both cells stretch to the row, so the two border-tops are ONE hairline
290
- across the card; the selectors match cosmos's own weight so the declared
291
- --label-face actually paints instead of cosmos's mono */
292
- .projCard .cardMeta dt{grid-column:1;display:flex;align-items:center;align-self:stretch;
293
- padding:11px 0;border-top:1px solid var(--rule-soft);
294
- font-family:var(--label-face);font-size:var(--label-size);letter-spacing:var(--label-space);
295
- font-weight:400;text-transform:uppercase;color:var(--ink-faint);white-space:nowrap}
296
- .projCard .cardMeta dd{grid-column:2;display:flex;align-items:center;justify-content:flex-end;
297
- align-self:stretch;padding:11px 0;border-top:1px solid var(--rule-soft);text-align:right;
298
- font-family:var(--font-body);font-size:14px;font-weight:400;color:var(--ink);
299
- font-variant-numeric:tabular-nums}
300
- .projCard .cardMeta [hidden]{display:none}
301
- .cardMeta .ownerAv{width:18px;height:18px;border-radius:50%;vertical-align:-4px;margin-right:7px}
302
- .projCard .cardActions{display:flex;gap:6px;justify-content:center;margin:22px var(--gutter) 0;
303
- padding:7px;border-radius:var(--radius-pill);background:var(--door-ground);
304
- border:1px solid var(--door-edge)}
305
- .door{display:inline-flex;align-items:center;justify-content:center;flex:1 1 auto;min-height:48px;
306
- padding:0 26px;border-radius:var(--radius-pill);font-size:15px;text-transform:lowercase;
307
- white-space:nowrap;transition:background 240ms cubic-bezier(.2,.7,.3,1),color 200ms ease}
308
- .doorGo{background:var(--accent);color:var(--accent-on);box-shadow:var(--accent-glow)}
309
- .doorGo:hover{background:var(--accent-lift)}
310
- .doorGo:focus-visible{box-shadow:var(--accent-glow),0 0 0 8px var(--bg)}
311
- .doorAlt{background:transparent;color:var(--ink)}
312
- .doorAlt:hover{background:var(--glass-strong)}
313
- .projCard[data-hall="off"] .doorAlt{display:none}
314
- .projCard[data-faces="off"] .faces{display:none}
315
- /* the poster is 758px tall; a 625px laptop window would centre it and put both
316
- the door and the close button off-screen, and a fixed scrim has nowhere to
317
- scroll. Past the threshold the scrim starts the card at the top and scrolls. */
318
- @media (max-height:820px){
319
- .cardScrim{align-items:flex-start;overflow-y:auto}
320
- }
321
-
322
- /* ═══════════════ the state contract ═══════════════════════════════════════ */
323
- [data-state] #view-map,[data-state] #view-mine,[data-state] #view-new{display:none}
324
- body[data-view="map"] #view-map,body[data-view="table"] #view-map{display:block}
325
- body[data-view="mine"] #view-mine{display:block}
326
- body[data-view="new"] #view-new{display:block}
327
- #sub-table-body{display:none}
328
- body[data-view="table"] #sub-sky-body{display:none}
329
- body[data-view="table"] #sub-table-body{display:block}
330
- .bmenu .menu{display:flex;flex-direction:column;align-items:flex-end;gap:8px}
331
- .bmenu .bframe.left .menu{align-items:flex-start}
332
- [data-auth="out"] .switch{display:none}
333
- [data-auth="out"] #selfPill{display:none}
334
- body[data-auth="out"] #panel-name{display:none}
335
- body[data-auth="out"] #panel-gate{display:block}
336
- body[data-auth="in"] #panel-gate{display:none}
337
-
338
- /* the boards: the same components, the same CSS, laid out for comparison. The
339
- page's own surfaces are direct children of body, so the child combinator
340
- hides them without touching a clone; the sky goes with them, because a board
341
- is read on the page ground and a fixed layer paints over unpositioned type. */
342
- #boards{display:none;padding:26px 0 60px}
343
- body:not([data-board="none"]) #boards{display:block}
344
- body:not([data-board="none"])>.skip,
345
- body:not([data-board="none"])>header,
346
- body:not([data-board="none"])>main,
347
- body:not([data-board="none"])>.foot,
348
- body:not([data-board="none"])>.sky{display:none}
349
- .board{max-width:1200px;margin:0 auto;padding:0 var(--gutter)}
350
- .brow{margin-bottom:22px}
351
- .blabel{display:block;position:relative;margin-bottom:8px;font-family:var(--label-face);
352
- font-size:var(--label-size);letter-spacing:var(--label-space);text-transform:uppercase;
353
- color:var(--ink-faint)}
354
- .bframe{position:relative;min-height:240px;border:1px solid var(--rule-soft);
355
- border-radius:var(--radius);overflow:hidden}
356
- .bframe .bar{border-radius:0}
357
- .bgrid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:26px}
358
- .bcell{min-width:0}
359
- .bmenu{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:26px}
360
- .bmenu .bframe{min-height:250px;padding:14px;display:flex;justify-content:flex-end;
361
- align-items:flex-start;background:var(--shelf-bg)}
362
- .bmenu .bframe.left{justify-content:flex-start}
363
- .bmenu .menuPanel{position:static;width:240px}
364
-
365
- /* ═══════════════ 900 and under: one row, and the search takes a second lip ═ */
366
- @media (max-width:900px){
367
- body{--top-h:60px;--gutter:var(--gutter-narrow);--search-row-h:56px}
368
- .bar{padding:0 14px}
369
- .barIn{gap:6px}
370
- .cpill{min-height:42px;font-size:13.5px;padding:0 12px}
371
- .markPill{padding:0 12px;gap:0}
372
- .markWord{display:none}
373
- .grpR{gap:6px}
374
- .mode-toggle{width:42px;min-width:42px}
375
- .signin{padding:0 14px}
376
- .whoName{display:none}
377
- .chipPill{padding:0 10px}
378
- .chipPill img{width:22px;height:22px}
379
- /* the search does not hide behind an icon: a search you cannot see on the one
380
- view it filters is a search nobody finds. It steps down onto a second lip of
381
- the same shelf, full width, and the map begins below it. */
382
- .searchPill{position:absolute;left:0;right:0;top:100%;width:auto;height:var(--search-row-h);
383
- border-radius:0;border:0;border-bottom:1px solid var(--shelf-edge);background:var(--shelf-bg);
384
- padding:0 14px}
385
- .searchPill:focus-within,.searchPill.is-focus{width:auto;background:var(--shelf-bg)}
386
- .bar[data-view="map"]~.menu .menuPanel{top:calc(100% + 8px)}
387
- body[data-view="map"] main,body[data-view="table"] main{padding-top:var(--search-row-h)}
388
- .menu{position:static}
389
- .menuPanel{left:0;right:0;width:auto;border-radius:0 0 var(--radius) var(--radius);
390
- border-top:0;top:calc(100% + var(--search-row-h))}
391
- .bar[data-view="mine"] .menuPanel,.bar[data-view="new"] .menuPanel{top:100%}
392
- .bgrid,.bmenu{grid-template-columns:minmax(0,1fr)}
393
- }
394
- @media (max-width:420px){
395
- .cpill{padding:0 10px}
396
- .cpill.trigger{padding:0 12px}
397
- }
398
- </style>
399
- </head>
400
- <body>
401
- <!--
402
- THESIS. The hub's chrome is the landing's chrome, set down on a real shelf. Nothing on this page
403
- invents a control: the mark pill, the glass pill, the ink sign-in door and the door bar all come
404
- from the front door, and the only new thing is the ground they stand on. Triggers are chrome, so
405
- they stay in the pill grammar people already learned at the apex; panels and the project card are
406
- cards, because a menu and a poster are things you read, not things you look through. The version's
407
- bet is continuity: a visitor who came from cloudbongos.com should not notice they changed page.
408
-
409
- THE BAR. Ground --bg-frame, one 1px --rule-soft bottom edge, 72px tall, 26px gutters, not sticky;
410
- the sky begins under it. LEFT: the mark pill (bongo-pair glyph + Cloud Bongos, glass-strong, the
411
- way home) then the search as a 46px glass pill, 260px at rest, 340px on focus, with the count at
412
- its right end (4 projects at rest, 1 of 4 filtered). The pill is the control: it takes the whole
413
- 46px as a click target and wears the two-tone ring on focus, sharing the :focus-visible
414
- declaration, while the field inside it paints nothing of its own. The search hides on mine and new. RIGHT: the
415
- Projects pill with a caret, the 46px mode toggle, then the identity slot: the landing's inverted
416
- ink sign-in door signed out, or the chip pill (26px avatar, login, caret) signed in, which IS the
417
- profile trigger. No Home, no hall pill, no nav row, no Docs. Controls lowercase by CSS, as the
418
- landing's are; the copy strings are unchanged.
419
-
420
- THE MENU. A card, not glass: --bg-card ground, 16px radius, 1px --rule edge, backdrop blur in dark
421
- only (the blur token is 0px on paper), 240px wide, hung 8px under its trigger and right-aligned to
422
- it. Items are 44px lowercase rows, --ink-soft rising to --ink on a --glass hover ground. The
423
- current view is the live one, so it takes the accent: a 6px --mark-lit dot at the row's left plus
424
- --ink ink and aria-current="page". Signed out the menu still holds all three, and Your projects
425
- points at sign-in. The profile panel opens the same way from the chip, over a non-interactive
426
- identity row, with a hairline and an empty slot where Settings will go. One authored move: rise 6px
427
- and fade, 220ms, exponential ease-out. Escape closes and hands focus back; a click outside closes;
428
- arrows walk the items.
429
-
430
- THE CARD. min(560px,100%), a stack of six regions, all direct children of the card. 1 ART: a
431
- full-bleed 5:2 banner, cover, clipped by the card's own 16px radius, framed by object-view-box on
432
- the plate's lower-left chrome so the poster carries material rather than a shrunken copy of the
433
- landing with its own headline, CTA and callouts inside it. 2 the DISC survives and moves:
434
- 48px, ringed 4px in the card ground, half over the banner's lower-left corner, so the colour a
435
- visitor learned in the sky is the first thing on the poster; with no art it keeps the same beat at
436
- the top of the card and grows back to 54px, on the poster's left axis rather than centred, because
437
- this card reads down one edge. 3 NAME at the title scale (Manrope 300, 28px, -0.03em), TAGLINE, and the RELATIONSHIP as a
438
- glass pill, not an accent one, because a relationship is neither pressable nor live. 4 FACES: five
439
- 28px avatars overlapping -8px, each ringed in the card ground, then a +N chip. 5 FIGURES: a centred
440
- two-up band over a hairline, tabular 34px numbers over mono labels; one null centres the survivor,
441
- both null take the band away. 6 FACTS as hairline ledger rows, one continuous rule each,
442
- label left in the label face, value right and tabular: four rows where Type is real (Off the
443
- Boats: Game) and three where it pair-hides (the platform's feed carries no type). Then the ACTIONS: the landing's door bar, a glass tray holding Open site
444
- in the accent and Builders' hall as the secondary door, one door wide when there is no hall entry.
445
-
446
- LIGHT. The shelf is paper on paper: --bg-frame over --bg, told apart by its edge alone, with the
447
- pills as near-opaque --bg tints and no blur (the glass token is 0px there). The panel and the card
448
- are --bg-card on that paper with --rule hairlines. Nothing black lands on a light page: the scrim
449
- stays cosmos's black wash because it is a scrim, and the disc, the accent door and the lit dot are
450
- the only colour in either mode.
451
-
452
- 390. The bar holds one row: the wordmark folds away, the glyph stays, the pills tighten to 42px and
453
- the toggle to 42px. The search does not hide behind an icon; it steps down onto a second lip of the
454
- same shelf, full width under the bar, and the map starts below it. Both menus drop to full-width
455
- panels under that lip, square at the top so they read as the shelf continuing downward.
456
-
457
- BEYOND THE SKIN
458
- 1 (finding) One project, two builder counts: the table row reports 13 (every leaderboard row) and
459
- the poster reports 9 (rows with credits above zero). Pick one definition before the figure ships.
460
- No test pins either value; the element that carries it is pinned, see item 17.
461
- 2 (consequence, given 3) The nav row leaves the bar, so the map gains its height back and the
462
- toolbar re-aligns from cosmos's clamp(16px,4vw,34px) to the bar's 26px gutter. Collision:
463
- projects_hub_pre_uat.mjs:203 pins the cosmos rule .shell .navrow{position:absolute;...} inside
464
- @media (min-width:1080px) and BREAKS if .navrow leaves cosmos; keep the rule or retarget.
465
- projects_hub.mjs:42-43 stays green while the menu items keep href="?view=map" data-nav="map"
466
- adjacent. Runtime :5307 querySelector('[data-nav="mine"]') stays singular here.
467
- 3 (given 6) Home is gone and the mark is home. Collision: projects_hub.mjs:40 (the Home regex)
468
- BREAKS hard; :46 and :48 (dataset.nav === 'home') go dead. The mark already announces itself as
469
- home (projects_hub_pre_uat.mjs:486), so the retarget is the wordmark.
470
- 4 (consequence, given 2) The self-typing wordmark gives way to the landing's static mark pill, so
471
- both surfaces carry one logo. Collision: projects_hub.mjs:116-134 (the markLeft/markPrefix/caret/
472
- markWord literal), :400-434 (typeMark, HOLD, HOLD_HOME) and landing_page.mjs's twin assertion all
473
- BREAK, and cosmos's .shell .mark #markPrefix / .shell .caret rules go unused.
474
- 5 (proposal) #mapCount moves inside the search pill and reads 4 projects at rest, 1 of 4 filtered,
475
- so the count sits where the filtering happens. Collision: projects_hub.mjs:389,393 pins the
476
- shown = list.length + (selfShown ? 1 : 0) wiring, which is untouched; keep
477
- .mineBar .search .count{display:none;} in cosmos (projects_hub_pre_uat.mjs:207).
478
- 6 (proposal) The relationship pill loses the accent. Today .cardRel and .tbl .pill are both
479
- --accent-soft on --accent-deep; the One Warm Thing Rule reserves the accent for the pressable and
480
- the live, so on the poster it becomes a glass pill. The table's twin is carried verbatim here and
481
- is still warm, which is what the two side by side are for. Collision: cosmos_token_contrast.mjs
482
- PAIRS carries .cardRel and .tbl .pill rows that would then measure a pairing nothing uses;
483
- retarget them to the glass pair.
484
- 7 (proposal) Runs becomes the address on the poster and keeps the module list in the table only.
485
- Runs today is tagsHtml(p.tags), which reads as a list of parts where a poster wants a place.
486
- Collision: projects_hub.mjs:586-602 pins cardFact('cardRuns', Array.isArray(p.tags) ? ...) and
487
- BREAKS; the thead's >Runs< (:518-526) is untouched.
488
- 8 (consequence) The em dash is the hub's "we could not ask" mark in four table cells, and the
489
- world bans it in visible copy. This mock uses a middot, and a catalog row's status chip says
490
- not checked rather than a bullet and a dash. Collision: projects_hub.mjs:564-580 pins
491
- p.builders == null ? '-' as an em dash and tagsHtml returning one; :493-500 already bans the dash
492
- inside the card slice, so today the ban and the tests disagree.
493
- 9 (consequence) The hub ships four h1s, one per view. This mock keeps The project map and demotes
494
- Your projects, Start a project and Create a project to h2 at the world's headline scale.
495
- Collision: projects_hub_pre_uat.mjs pins the view-map h1 literal (safe) and the
496
- h1[tabindex="-1"]:focus:not(:focus-visible) rule, which retargets to h2.
497
- 10 (consequence, given 7) The hall glyph rides inside the existing .colGo cell instead of taking a
498
- seventh column, so projects_hub.mjs:531-535 (td counts must match header, #selfRow and the
499
- template) stays green.
500
- 11 (finding, given 7 vs the state contract) The contract asks for the glyph on Off the Boats as
501
- well; given 7's address rule removes it, because its hall is amazonprimea.com/builders, the same
502
- address as its site. Built to the given, flagged here. Architecture: no feed carries a hall
503
- address today (HUB-TESTS A3 row 3), so the rule needs a new field on /projects/featured before
504
- either version can ship it.
505
- 12 (proposal) About (goal 1000063) belongs as a fourth item in the Projects menu, under a hairline
506
- below New project: the menu is now the page's only navigation, and About is a destination rather
507
- than a view. No collision today.
508
- 13 (proposal) The card grows from 420px to 560px and drops --shadow-card. The world has no shadow
509
- vocabulary for UI, and a poster with a banner needs the width. Collision: none pinned; the
510
- cosmos.css:717-745 numbers change.
511
- 14 (proposal) The mine view's empty state keeps cosmos's 2px dashed --line box, which is a
512
- container in a world made of hairlines; propose a hairline and space instead. No collision.
513
- 15 (consequence) Under 780 the table already drops Runs and Type; Status has to follow, or a row
514
- that says anything more than a punctuation mark overflows a phone. No test pins the breakpoint
515
- list, so this is free; cosmos.css:685 is where it lands.
516
- 16 (consequence, given 1) A grounded bar retires the top wash that compensates for controls over a
517
- sky. The hub never had one (cosmos's .sky is flat), but the landing's --sky-topscrim should go
518
- when the landing adopts the shelf. No collision.
519
- 17 (consequence, given 8) The Builders fact becomes a FIGURE, so id="cardBuilders" leaves the card.
520
- Collision: projects_hub.mjs:496-498 requires the cardScrim slice to contain id="cardBuilders"
521
- beside cardRuns / cardOwner / cardListed, and :586-602 pins the cardFact('cardBuilders', ...)
522
- call site; both BREAK. The retarget is to move the assertion onto the figure (#figBuilders) or to
523
- keep a hidden dt/dd pair carrying the id. This is the card's hardest-pinned assertion; without
524
- naming it the build task inherits a red test it did not choose.
525
- 18 (consequence, given 8) The poster is 758px tall against today's 308px, so a 1366x625 or
526
- 1024x600 window centres it and puts the Open site door and the close button past both edges of a
527
- fixed scrim with nowhere to scroll. cosmos.css:717 .cardScrim needs a max-height threshold that
528
- flips it to align-items:flex-start with overflow-y:auto; this mock carries the rule at 820px. No
529
- test pins the scrim's alignment.
530
-
531
- DATA. Real, fetched 2026-08-27. Builder jaxri with the real avatar. Catalog: Off the Boats, Demo,
532
- Emersonian Circles as /projects/featured returns them, plus the apex self row; the orbs carry the
533
- inline styles the live page computes (accent by origin order, --d and left/top from ORB_SLOTS),
534
- placed statically. Poster (platform): builders 9 (apex leaderboard rows with credits above zero),
535
- shipped in 30 days 30+ (the feed caps at 30 and all 30 are inside the window), faces jaxri,
536
- lars589, IAMMASTERQUA, scootermack, LarsCode and +4, owner lars589, listed Jul 14, 2026 (the Demo
537
- row's date, since the synthesized self row has none). Its banner is the landing's own social card,
538
- public-landing/assets/world/og-card.jpg, a real 1200x630 capture of the built landing, framed 5:2
539
- on its lower-left chrome (object-view-box inset(60% 45.4% .3% 2.5%), the one region of the plate
540
- that carries no type; object-position 50% 88% is the fallback where object-view-box is unsupported):
541
- the platform has no art_url, and this is the only sense in which it has art. Poster (member): Off
542
- the Boats, art null, faces lars589, kingaonline, IAMMASTERQUA, scootermack, LarsCode and +8,
543
- builders 13, shipped in 30 days 0 (a real zero, rendered), no hall entry because its hall is at the
544
- same address as its site. Membership is illustrative: jaxri is shown as a builder of both projects
545
- so the Owner fact stays visible, which is what makes the poster's ledger legible. The table keeps
546
- today's counts and semantics verbatim, which is why item 1 above exists. Hall links are written as
547
- https://builders.cloudbongos.com because a mock is served without the {{buildersOrigin}} pass.
548
- Carried copy that held an em dash is normalised to a colon or a comma, per the world's ban.
549
- The wizard's bongo-pair cell is not carried: it needs page-local --skin-* literals, which this
550
- world's token rule forbids, so the create rail runs one column wide.
551
-
552
- TOKENS declared on body, by DESIGN.md's recipes and its names: --gutter --gutter-narrow --radius
553
- --radius-sm --radius-pill --top-h --r-card --search-row-h --void-glass --void-glass-strong
554
- --void-glass-edge --void-pill --glass --glass-strong --glass-edge --glass-blur --shelf-bg
555
- --shelf-edge --pill-bg --pill-bg-hi --pill-edge --panel-bg --door-ground --door-edge --accent-lift
556
- --accent-glow --mark-lit --focus --label-face --label-size --label-space --sun-display
557
- --moon-display. Two dark twin blocks, byte-identical, at (0,2,0). --line (a hairline colour here,
558
- not a width), --ok, --warn and --err keep cosmos's meaning and are not redeclared; --accent-on,
559
- --accent-deep, --accent-soft, --ctl-line and the fifteen contract tokens are taken from cosmos.
560
- -->
561
-
562
- <div class="sky" aria-hidden="true">
563
- <span class="star" style="top:2%;left:12%;width:2px;height:2px;"></span>
564
- <span class="star" style="top:5%;left:28%;width:1.5px;height:1.5px;animation-delay:.7s;"></span>
565
- <span class="star" style="top:3%;left:47%;width:2px;height:2px;animation-delay:1.4s;"></span>
566
- <span class="star" style="top:8%;left:63%;width:1.5px;height:1.5px;animation-delay:.3s;"></span>
567
- <span class="star" style="top:4%;left:78%;width:2.5px;height:2.5px;animation-delay:2s;"></span>
568
- <span class="star" style="top:10%;left:88%;width:1.5px;height:1.5px;animation-delay:1s;"></span>
569
- <span class="star" style="top:14%;left:20%;width:1.5px;height:1.5px;animation-delay:1.8s;"></span>
570
- <span class="star" style="top:22%;left:55%;width:2px;height:2px;animation-delay:.5s;"></span>
571
- <span class="star" style="top:34%;left:36%;width:1.5px;height:1.5px;animation-delay:2.4s;"></span>
572
- <span class="star" style="top:30%;left:78%;width:1.5px;height:1.5px;animation-delay:1.2s;"></span>
573
- <span class="star" style="top:48%;left:8%;width:2px;height:2px;animation-delay:.9s;"></span>
574
- <span class="star" style="top:55%;left:90%;width:1.5px;height:1.5px;animation-delay:1.6s;"></span>
575
- <span class="star" style="top:68%;left:24%;width:1.5px;height:1.5px;animation-delay:2.1s;"></span>
576
- <span class="star" style="top:76%;left:64%;width:2px;height:2px;animation-delay:.4s;"></span>
577
- <span class="star" style="top:88%;left:42%;width:1.5px;height:1.5px;animation-delay:1.9s;"></span>
578
- </div>
579
-
580
- <a class="skip" href="#hubMain">Skip to content</a>
581
-
582
- <header class="bar" id="topBar" data-auth="in" data-view="map">
583
- <div class="barIn">
584
- <div class="grpL">
585
- <a class="cpill markPill" href="/" aria-label="Cloud Bongos">
586
- <svg viewBox="0 0 26 20" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.4"
587
- stroke-linecap="round" stroke-linejoin="round">
588
- <ellipse cx="8.4" cy="5.6" rx="6.6" ry="2.9"/>
589
- <path d="M1.8 5.6v6.6a6.6 2.9 0 0 0 13.2 0V5.6"/>
590
- <ellipse cx="19.6" cy="8.4" rx="4.7" ry="2.1"/>
591
- <path d="M14.9 8.4v4.6a4.7 2.1 0 0 0 9.4 0V8.4"/>
592
- </svg>
593
- <span class="markWord" data-brand-product-inline>Cloud Bongos</span>
594
- </a>
595
- <div class="cpill searchPill" id="searchPill">
596
- <svg class="mag" viewBox="0 0 24 24" aria-hidden="true"><circle cx="11" cy="11" r="7"/><path d="M20 20l-3.5-3.5"/></svg>
597
- <label class="vh" for="mapQ">Search projects</label>
598
- <input type="text" id="mapQ" placeholder="Find a project">
599
- <span class="count lbl num" id="mapCount">4 projects</span>
600
- </div>
601
- </div>
602
-
603
- <div class="grpR">
604
- <div class="menu">
605
- <button type="button" class="cpill trigger" id="projTrigger" aria-expanded="false" aria-controls="projMenu">
606
- Projects
607
- <svg class="crt" viewBox="0 0 20 20" aria-hidden="true"><path d="m5.6 8 4.4 4.4L14.4 8"/></svg>
608
- </button>
609
- <ul class="menuPanel" id="projMenu" hidden>
610
- <li><a href="?view=map" data-nav="map" aria-current="page"><span class="dot" aria-hidden="true"></span>Map</a></li>
611
- <li><a href="?view=mine" data-nav="mine" id="menuMine"><span class="dot" aria-hidden="true"></span>Your projects</a></li>
612
- <li><a href="?view=new" data-nav="new"><span class="dot" aria-hidden="true"></span>New project</a></li>
613
- </ul>
614
- </div>
615
-
616
- <button type="button" class="cpill mode-toggle" id="modeToggle" aria-label="Toggle light or dark">
617
- <svg class="moon" viewBox="0 0 20 20" aria-hidden="true">
618
- <path d="M16.2 12.4A6.8 6.8 0 0 1 7.6 3.8a6.8 6.8 0 1 0 8.6 8.6z"/>
619
- </svg>
620
- <svg class="sun" viewBox="0 0 20 20" aria-hidden="true">
621
- <circle cx="10" cy="10" r="3.9"/>
622
- <path d="M10 1.6v2.1M10 16.3v2.1M1.6 10h2.1M16.3 10h2.1M4.1 4.1l1.5 1.5M14.4 14.4l1.5 1.5M15.9 4.1l-1.5 1.5M5.6 14.4l-1.5 1.5"/>
623
- </svg>
624
- </button>
625
-
626
- <a class="cpill signin" href="/api/bongos/auth/web/start?return=/projects">Sign in</a>
627
-
628
- <div class="menu idChip">
629
- <button type="button" class="cpill chipPill" id="profTrigger" aria-expanded="false" aria-controls="profMenu" aria-label="Account, jaxri">
630
- <img src="https://avatars.githubusercontent.com/u/64553469?v=4" alt="">
631
- <span class="whoName">jaxri</span>
632
- <svg class="crt" viewBox="0 0 20 20" aria-hidden="true"><path d="m5.6 8 4.4 4.4L14.4 8"/></svg>
633
- </button>
634
- <ul class="menuPanel" id="profMenu" hidden>
635
- <li class="menuId"><img src="https://avatars.githubusercontent.com/u/64553469?v=4" alt=""><span>jaxri</span></li>
636
- <li><a href="https://builders.cloudbongos.com/my-projects"><span class="dot" aria-hidden="true"></span>My projects</a></li>
637
- <!-- the deferred Settings slot lives here; nothing is rendered until it exists -->
638
- <li class="menuRule" aria-hidden="true"></li>
639
- <li><a href="/api/bongos/auth/logout"><span class="dot" aria-hidden="true"></span>Sign out</a></li>
640
- </ul>
641
- </div>
642
- </div>
643
- </div>
644
- </header>
645
-
646
- <main id="hubMain">
647
- <section id="view-map">
648
- <h1 class="vh">The project map</h1>
649
- <div class="toolbar">
650
- <div class="seg" role="group" aria-label="Map display">
651
- <button type="button" id="sub-sky" aria-pressed="true">Sky</button>
652
- <button type="button" id="sub-table" aria-pressed="false">Table</button>
653
- </div>
654
-
655
- <label class="switch" title="Show only projects you own or build on">
656
- <input type="checkbox" id="onlyMine"><span class="track"></span> Only mine
657
- </label>
658
- </div>
659
-
660
- <div class="fieldWrap" id="sub-sky-body">
661
- <div class="field" id="orbField">
662
- <div class="ground"></div>
663
- <div class="stars" id="mapStars" aria-hidden="true"></div>
664
- <div class="skyCam" id="skyCam">
665
- <!--apex-only:start-->
666
- <a class="worldOrb" id="selfOrb" href="/" data-rel="builder" style="--acc:var(--accent);--d:122px;left:50%;top:44%">
667
- <span class="badge">you build here</span>
668
- <span class="disc"></span>
669
- <span class="nm" data-brand-product-inline>Cloud Bongos</span>
670
- <span class="sub">this platform</span>
671
- </a>
672
- <!--apex-only:end-->
673
- <a class="worldOrb" data-generated data-rel="none" href="https://demo.cloudbongos.com" target="_blank" rel="noopener" style="--acc:var(--terracotta);--d:74px;left:22%;top:30%">
674
- <span class="disc"></span>
675
- <span class="nm">Demo</span>
676
- </a>
677
- <a class="worldOrb" data-generated data-rel="none" href="https://emersonian-circles.cloudbongos.com" target="_blank" rel="noopener" style="--acc:var(--gold-soft);--d:60px;left:78%;top:66%">
678
- <span class="disc"></span>
679
- <span class="nm">Emersonian Circles</span>
680
- </a>
681
- <a class="worldOrb" data-generated data-rel="builder" href="https://amazonprimea.com" target="_blank" rel="noopener" style="--acc:var(--sea);--d:56px;left:33%;top:74%">
682
- <span class="badge">you build here</span>
683
- <span class="disc"></span>
684
- <span class="nm">Off the Boats</span>
685
- </a>
686
- </div>
687
- <div class="fieldEmpty">
688
- <p id="emptyMsg">You don’t own or build on anything here yet.</p>
689
- <span class="sub">Turn the filter off to see what everyone else is building, or start your own.</span>
690
- <a class="btn small" href="?view=new" data-nav-to="new">Start a project</a>
691
- </div>
692
- <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>
693
- <div class="hoverCard" id="hoverCard" hidden aria-hidden="true"></div>
694
- </div>
695
- </div>
696
-
697
- <div class="wrap viewWrap" id="sub-table-body">
698
- <table class="tbl">
699
- <thead>
700
- <tr>
701
- <th class="colName" data-sort="name" aria-sort="ascending"><button type="button" class="thSort">Project</button></th>
702
- <th class="colType">Type</th>
703
- <th class="right" data-sort="builders"><button type="button" class="thSort">Builders</button></th>
704
- <th class="colTags">Runs</th>
705
- <th class="right colStatus">Status</th>
706
- <th class="colGo"></th>
707
- </tr>
708
- </thead>
709
- <tbody id="mapRows">
710
- <!--apex-only:start-->
711
- <tr id="selfRow">
712
- <td class="colName"><span class="pname"><span class="pdot" style="--acc:var(--accent)"></span>
713
- <span><span class="ptitle" data-brand-product-inline>Cloud Bongos</span><span id="selfPill"><span class="pill">you build here</span></span><br>
714
- <span class="ptag">this platform</span></span></span></td>
715
- <td class="colType">·</td>
716
- <td class="right num" id="selfBuilders">13</td>
717
- <td class="colTags" id="selfTags">·</td>
718
- <td class="right colStatus"><span class="chip calm"><span class="cdot"></span>not checked</span></td>
719
- <td class="colGo"><a class="hallGlyph" href="https://builders.cloudbongos.com" target="_blank" rel="noopener" aria-label="Builders' hall"><svg viewBox="0 0 20 20" aria-hidden="true"><path d="M10 2.6 2.6 6.1h14.8L10 2.6Z"/><path d="M4.8 8.2v6.2M8.3 8.2v6.2M11.7 8.2v6.2M15.2 8.2v6.2"/><path d="M2.9 16.7h14.2"/></svg></a><a class="btn small ghost" href="/">Open →</a></td>
720
- </tr>
721
- <!--apex-only:end-->
722
- <tr data-generated>
723
- <td class="colName"><span class="pname"><span class="pdot" style="--acc:var(--terracotta)"></span>
724
- <span><span class="ptitle">Demo</span><br>
725
- <span class="ptag">A live demo instance on Cloud Bongos.</span></span></span></td>
726
- <td class="colType">·</td>
727
- <td class="right num">1</td>
728
- <td class="colTags">core</td>
729
- <td class="right colStatus"><span class="chip calm"><span class="cdot"></span>not checked</span></td>
730
- <td class="colGo"><a class="btn small ghost" href="https://demo.cloudbongos.com" target="_blank" rel="noopener">Open →</a></td>
731
- </tr>
732
- <tr data-generated>
733
- <td class="colName"><span class="pname"><span class="pdot" style="--acc:var(--gold-soft)"></span>
734
- <span><span class="ptitle">Emersonian Circles</span><br>
735
- <span class="ptag">An independent project built on Cloud Bongos.</span></span></span></td>
736
- <td class="colType">·</td>
737
- <td class="right num">1</td>
738
- <td class="colTags">core</td>
739
- <td class="right colStatus"><span class="chip calm"><span class="cdot"></span>not checked</span></td>
740
- <td class="colGo"><a class="btn small ghost" href="https://emersonian-circles.cloudbongos.com" target="_blank" rel="noopener">Open →</a></td>
741
- </tr>
742
- <tr data-generated>
743
- <td class="colName"><span class="pname"><span class="pdot" style="--acc:var(--sea)"></span>
744
- <span><span class="ptitle">Off the Boats</span><span class="pill">you build here</span><br>
745
- <span class="ptag">A singular shop, and a broader videogame in a persistent ancient Greek world that collides with modern day commerce &amp; products.</span></span></span></td>
746
- <td class="colType"><span class="typeTag">Game</span></td>
747
- <td class="right num">11</td>
748
- <td class="colTags"><span class="tags"><span>art-pipeline</span> <span>character-anim</span> <span>demo</span> <span>+1</span></span></td>
749
- <td class="right colStatus"><span class="chip calm"><span class="cdot"></span>not checked</span></td>
750
- <td class="colGo"><a class="btn small ghost" href="https://amazonprimea.com" target="_blank" rel="noopener">Open →</a></td>
751
- </tr>
752
- </tbody>
753
- </table>
754
- <p class="finePrint" style="text-align:center">Sort by Project or Builders.</p>
755
- </div>
756
-
757
- <div class="cardScrim" id="cardScrim" hidden>
758
- <div class="projCard" id="projCard" role="dialog" aria-modal="true" aria-labelledby="cardName" data-art="on" data-faces="on" data-figs="two" data-facts="on" data-hall="on" style="--acc:var(--accent)">
759
- <button type="button" class="cardX" id="cardClose" aria-label="Close"><svg viewBox="0 0 20 20" aria-hidden="true"><path d="M5.4 5.4l9.2 9.2M14.6 5.4l-9.2 9.2"/></svg></button>
760
- <img class="cardArt" id="cardArt" src="../../../../modules/public-landing/public/assets/world/og-card.jpg" alt="">
761
- <span class="cardDot" id="cardDot"></span>
762
- <h2 class="cardName" id="cardName">Cloud Bongos</h2>
763
- <p class="cardTag" id="cardTag">Building Digitally, as simple as Bongos.</p>
764
- <p class="cardRel lbl" id="cardRel">you build here</p>
765
- <p class="faces" id="cardFaces"><img id="face1" src="https://avatars.githubusercontent.com/u/64553469?v=4" alt="jaxri"><img id="face2" src="https://avatars.githubusercontent.com/u/283020391?v=4" alt="lars589"><img id="face3" src="https://avatars.githubusercontent.com/u/290184380?v=4" alt="IAMMASTERQUA"><img id="face4" src="https://avatars.githubusercontent.com/u/295990394?v=4" alt="scootermack"><img id="face5" src="https://avatars.githubusercontent.com/u/35337514?v=4" alt="LarsCode"><span class="more lbl num" id="faceMore">+4</span></p>
766
- <p class="figs" id="cardFigs"><span class="fig"><span class="figN num" id="figBuilders">9</span><span class="figL lbl">builders</span></span><span class="fig figShip"><span class="figN num" id="figShipped">30+</span><span class="figL lbl">shipped in 30 days</span></span></p>
767
- <dl class="cardMeta" id="cardMeta">
768
- <dt id="cardTypeL" hidden>Type</dt><dd id="cardType" hidden></dd>
769
- <dt id="cardRunsL">Runs</dt><dd id="cardRuns">cloudbongos.com</dd>
770
- <dt id="cardOwnerL">Owner</dt><dd id="cardOwner"><img class="ownerAv" id="ownerAv" src="https://avatars.githubusercontent.com/u/283020391?v=4" alt=""><span id="ownerName">lars589</span></dd>
771
- <dt id="cardListedL">Listed</dt><dd id="cardListed">Jul 14, 2026</dd>
772
- </dl>
773
- <div class="cardActions" id="cardActions"><a class="door doorGo" id="doorGo" href="https://cloudbongos.com">Open site</a><a class="door doorAlt" id="doorAlt" href="https://builders.cloudbongos.com" target="_blank" rel="noopener">Builders' hall</a></div>
774
- </div>
775
- </div>
776
- </section>
777
-
778
- <section id="view-mine">
779
- <div class="wrap viewWrap">
780
- <div class="hero" style="padding-left:0;padding-right:0">
781
- <h2>Your projects</h2>
782
- <p class="lede">Every project you own: what it is, whether it is answering, and the controls that matter.
783
- Each card says what the platform <b>last verified</b>, and when.</p>
784
- </div>
785
-
786
- <div class="card">
787
- <section id="mine">
788
- <div class="mineBar" id="mineBar">
789
- <div class="search">
790
- <svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="11" cy="11" r="7"/><path d="M20 20l-3.5-3.5"/></svg>
791
- <input type="text" id="mineQ" placeholder="Search your projects by name, repo or address…" aria-label="Search your projects">
792
- <span class="count" id="mineCount"></span>
793
- </div>
794
- <div class="filters" role="group" aria-label="Filter by state">
795
- <button type="button" data-f="all" aria-controls="projectsList" aria-pressed="true">All <span class="n">0</span></button>
796
- <button type="button" data-f="live" aria-controls="projectsList" aria-pressed="false">Live <span class="n">0</span></button>
797
- <button type="button" data-f="attention" aria-controls="projectsList" aria-pressed="false">Needs you <span class="n">0</span></button>
798
- <button type="button" data-f="working" aria-controls="projectsList" aria-pressed="false">Working <span class="n">0</span></button>
799
- <button type="button" data-f="gone" aria-controls="projectsList" aria-pressed="false">Torn down <span class="n">0</span></button>
800
- </div>
801
- </div>
802
-
803
- <section class="empty" id="empty">
804
- <p>You don't own any projects yet. Name one, pick a home for its code, and it gets an address of its own in this sky.</p>
805
- <a class="btn" href="?view=new" data-nav-to="new">Create your first project</a>
806
- </section>
807
- <ul class="projects" id="projectsList"></ul>
808
- <p class="finePrint">Buttons here ask the platform to act; each card reports only what was verified, and when. A standup keeps going even with this tab closed.</p>
809
- </section>
810
- </div>
811
- </div>
812
- </section>
813
-
814
- <section id="view-new">
815
- <div class="wrap viewWrap">
816
- <div class="card">
817
- <ol class="steps" aria-label="Creation steps">
818
- <li class="now" data-step="1" aria-current="step"><span class="snum">1</span><span class="slbl">Name</span></li>
819
- <li data-step="2"><span class="snum">2</span><span class="slbl">Type</span></li>
820
- <li data-step="3"><span class="snum">3</span><span class="slbl">Home</span></li>
821
- <li data-step="4"><span class="snum">4</span><span class="slbl">Address</span></li>
822
- <li data-step="5"><span class="snum">5</span><span class="slbl">Create</span></li>
823
- </ol>
824
-
825
- <div class="createSplit">
826
- <div>
827
- <section class="panel" id="panel-gate" aria-labelledby="gate-h">
828
- <h2 id="gate-h">Create a project</h2>
829
- <p class="lede">Your own <strong data-brand-product-inline>Cloud Bongos</strong> project: its own repository, its own home on the web, and a hall of AI builders who do the building. You set the direction; agents lay down the code. Sign in with GitHub so the project belongs to <em>you</em> from the very first beat.</p>
830
- <a class="btn big" id="wizSignin" href="/api/bongos/auth/web/start?return=/projects%3Fview%3Dnew&amp;repos=1">
831
- <svg class="gh" viewBox="0 0 16 16" aria-hidden="true" width="17" height="17"><path fill="currentColor" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27s1.36.09 2 .27c1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8z"/></svg>
832
- Sign in with GitHub
833
- </a>
834
- <p class="finePrint" id="wizScopeNote">Signing in asks GitHub for repository access. GitHub words this as access to <em>all</em> your repositories; that is the only permission it offers that can write to a private repo. We use it to create (or read) the one repo your project lives in and push its starting files. Nothing else is touched.</p>
835
- <p class="finePrint">Free while we find our feet. Your project’s repo and server are yours,
836
- <span data-brand-product-inline>Cloud Bongos</span> is <a href="https://www.gnu.org/licenses/agpl-3.0.html" target="_blank" rel="noopener">open source (AGPL-3.0)</a>
837
- and capture-resistant by design.</p>
838
- </section>
839
-
840
- <section class="panel on" id="panel-name" aria-labelledby="name-h">
841
- <h2 id="name-h">Start a project</h2>
842
- <p class="lede">Your own project: its own repository, its own home on the web, and a hall of AI builders
843
- who do the building. You set the direction; agents lay down the code.</p>
844
- <form id="newForm" data-next="2">
845
- <label class="wizField"><span>Project name</span>
846
- <input type="text" id="newName" placeholder="What should it be called?" autocomplete="off" maxlength="80" aria-label="Project name">
847
- <div class="hint" id="h-name">&nbsp;</div>
848
- </label>
849
- <div class="nav">
850
- <span></span>
851
- <button type="submit" class="btn">Continue →</button>
852
- </div>
853
- </form>
854
- <p class="finePrint">Free while we find our feet. Your project’s repo and server are yours,
855
- <span data-brand-product-inline>Cloud Bongos</span> is <a href="https://www.gnu.org/licenses/agpl-3.0.html" target="_blank" rel="noopener">open source (AGPL-3.0)</a>
856
- and capture-resistant by design.</p>
857
- </section>
858
- </div>
859
- </div>
860
- </div>
861
- </div>
862
- </section>
863
- </main>
864
-
865
- <footer class="foot"><!--apex-only:start--><span>A non-profit, capture-resistant commons. </span><!--apex-only:end-->Built by agents, on <span data-brand-product-inline>Cloud&nbsp;Bongos</span>. <a href="https://www.gnu.org/licenses/agpl-3.0.html" target="_blank" rel="noopener">Open source (AGPL-3.0)</a>.<nav class="footNav" aria-label="Site"><a href="/privacy">Privacy</a><a href="/terms">Terms</a><a href="/contact">Contact</a></nav></footer>
866
-
867
- <div id="boards">
868
- <div class="board" id="boardBar" hidden></div>
869
- <div class="board" id="boardCard" hidden></div>
870
- <div class="board" id="boardMenu" hidden></div>
871
- </div>
872
-
873
- <script>
874
- /* The state contract. One state per load, read once from ?state=; the default is
875
- in-map. Every state is markup that already exists: the script sets attributes,
876
- textContent and src, and clones the real components for the three boards, so a
877
- board can never drift from the surface it is comparing. No motion is authored
878
- here (the one menu move is CSS), and nothing is built from a string. */
879
- (function () {
880
- var STATES = {
881
- 'out-map': { auth: 'out', view: 'map' },
882
- 'in-map': { auth: 'in', view: 'map' },
883
- 'in-map-projects': { auth: 'in', view: 'map', open: 'projects' },
884
- 'in-map-profile': { auth: 'in', view: 'map', open: 'profile' },
885
- 'in-map-focus': { auth: 'in', view: 'map', open: 'projects', focus: 'item2' },
886
- 'in-map-search': { auth: 'in', view: 'map', q: 'emer', count: '1 of 4' },
887
- 'in-mine': { auth: 'in', view: 'mine' },
888
- 'in-new': { auth: 'in', view: 'new' },
889
- 'out-new': { auth: 'out', view: 'new' },
890
- 'in-table': { auth: 'in', view: 'table' },
891
- 'card': { auth: 'in', view: 'map', card: 'platform' },
892
- 'card-member': { auth: 'in', view: 'map', card: 'otb' },
893
- 'card-noart': { auth: 'in', view: 'map', card: 'platform', art: 'off' },
894
- 'card-nofaces': { auth: 'in', view: 'map', card: 'platform', faces: 'off' },
895
- 'card-onefig': { auth: 'in', view: 'map', card: 'platform', figs: 'one' },
896
- 'card-nofig': { auth: 'in', view: 'map', card: 'platform', figs: 'none' },
897
- 'card-floor': { auth: 'in', view: 'map', card: 'platform', art: 'off', faces: 'off', figs: 'none', facts: 'off', hall: 'off' },
898
- 'board-bar': { auth: 'in', view: 'map', board: 'bar' },
899
- 'board-card': { auth: 'in', view: 'map', board: 'card' },
900
- 'board-menu': { auth: 'in', view: 'map', board: 'menu' }
901
- };
902
-
903
- var AV = 'https://avatars.githubusercontent.com/u/';
904
- var PLATFORM = {
905
- acc: 'var(--accent)', name: 'Cloud Bongos', tag: 'Building Digitally, as simple as Bongos.',
906
- rel: 'you build here', art: '../../../../modules/public-landing/public/assets/world/og-card.jpg',
907
- faces: [[AV + '64553469?v=4', 'jaxri'], [AV + '283020391?v=4', 'lars589'], [AV + '290184380?v=4', 'IAMMASTERQUA'],
908
- [AV + '295990394?v=4', 'scootermack'], [AV + '35337514?v=4', 'LarsCode']],
909
- type: null, more: '+4', builders: '9', shipped: '30+', runs: 'cloudbongos.com',
910
- owner: 'lars589', ownerAv: AV + '283020391?v=4', listed: 'Jul 14, 2026',
911
- site: 'https://cloudbongos.com', hall: 'on'
912
- };
913
- var OTB = {
914
- acc: 'var(--sea)', name: 'Off the Boats',
915
- tag: 'A singular shop, and a broader videogame in a persistent ancient Greek world that collides with modern day commerce & products.',
916
- rel: 'you build here', art: null,
917
- faces: [[AV + '283020391?v=4', 'lars589'], [AV + '293641659?v=4', 'kingaonline'], [AV + '290184380?v=4', 'IAMMASTERQUA'],
918
- [AV + '295990394?v=4', 'scootermack'], [AV + '35337514?v=4', 'LarsCode']],
919
- type: 'Game', more: '+8', builders: '13', shipped: '0', runs: 'amazonprimea.com',
920
- owner: 'lars589', ownerAv: AV + '283020391?v=4', listed: 'Jul 15, 2026',
921
- site: 'https://amazonprimea.com', hall: 'off'
922
- };
923
- var PROJECTS = { platform: PLATFORM, otb: OTB };
924
-
925
- var $ = function (id) { return document.getElementById(id); };
926
- var body = document.body;
927
- var params = new URLSearchParams(location.search || location.hash.slice(1) || (window.__Q || ''));
928
- var name = params.get('state');
929
- var st = Object.prototype.hasOwnProperty.call(STATES, name) ? name : 'in-map';
930
- var s = STATES[st];
931
-
932
- /* ---- the bar: its own state, so a cloned bar on a board carries its own ---- */
933
- function setBar(bar, opt) {
934
- bar.setAttribute('data-auth', opt.auth);
935
- bar.setAttribute('data-view', opt.view === 'table' ? 'map' : opt.view);
936
- var triggers = bar.querySelectorAll('[aria-expanded]');
937
- for (var i = 0; i < triggers.length; i++) {
938
- var t = triggers[i];
939
- var which = t.className.indexOf('chipPill') > -1 ? 'profile' : 'projects';
940
- var isOpen = opt.open === which;
941
- t.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
942
- var panel = bar.querySelector('#' + t.getAttribute('aria-controls')) ||
943
- document.getElementById(t.getAttribute('aria-controls'));
944
- if (panel) panel.hidden = !isOpen;
945
- t.classList.remove('is-focus');
946
- }
947
- var cur = opt.view === 'table' ? 'map' : opt.view;
948
- var navs = bar.querySelectorAll('[data-nav]');
949
- for (var v = 0; v < navs.length; v++) {
950
- if (navs[v].getAttribute('data-nav') === cur) navs[v].setAttribute('aria-current', 'page');
951
- else navs[v].removeAttribute('aria-current');
952
- }
953
- var mine = bar.querySelector('[data-nav="mine"]');
954
- if (mine) mine.setAttribute('href', opt.auth === 'out'
955
- ? '/api/bongos/auth/web/start?return=/projects%3Fview%3Dmine' : '?view=mine');
956
- var q = bar.querySelector('input[type="text"]');
957
- if (q) q.value = opt.q || '';
958
- var count = bar.querySelector('.count');
959
- if (count) count.textContent = opt.count || '4 projects';
960
- var pill = bar.querySelector('.searchPill');
961
- if (pill) pill.classList.toggle('is-focus', !!opt.q);
962
- if (opt.focus === 'item2') {
963
- var pt = bar.querySelector('.trigger');
964
- var pp = pt ? document.getElementById(pt.getAttribute('aria-controls')) : null;
965
- if (pp) { var links = pp.querySelectorAll('a'); if (links[1]) links[1].classList.add('is-focus'); }
966
- var chip = bar.querySelector('.chipPill');
967
- if (chip) chip.classList.add('is-focus');
968
- }
969
- }
970
-
971
- /* ---- the card: one component, seven rungs of the ladder ---- */
972
- function setCard(card, key, opt) {
973
- var d = PROJECTS[key] || PLATFORM;
974
- var art = opt.art === 'off' || !d.art ? 'off' : 'on';
975
- card.setAttribute('data-art', art);
976
- card.setAttribute('data-faces', opt.faces === 'off' ? 'off' : 'on');
977
- card.setAttribute('data-figs', opt.figs || 'two');
978
- card.setAttribute('data-facts', opt.facts === 'off' ? 'off' : 'on');
979
- card.setAttribute('data-hall', opt.hall === 'off' ? 'off' : d.hall);
980
- card.style.setProperty('--acc', d.acc);
981
- if (art === 'on') card.querySelector('.cardArt').setAttribute('src', d.art);
982
- card.querySelector('.cardName').textContent = d.name;
983
- card.querySelector('.cardTag').textContent = d.tag;
984
- card.querySelector('.cardRel').textContent = d.rel;
985
- var faces = card.querySelectorAll('.faces img');
986
- for (var i = 0; i < faces.length; i++) {
987
- faces[i].setAttribute('src', d.faces[i][0]);
988
- faces[i].setAttribute('alt', d.faces[i][1]);
989
- }
990
- card.querySelector('.faces .more').textContent = d.more;
991
- card.querySelectorAll('.figN')[0].textContent = d.builders;
992
- card.querySelectorAll('.figN')[1].textContent = d.shipped;
993
- var dts = card.querySelectorAll('.cardMeta dt');
994
- var dds = card.querySelectorAll('.cardMeta dd');
995
- dts[0].hidden = !d.type; dds[0].hidden = !d.type;
996
- dds[0].textContent = d.type || '';
997
- card.querySelectorAll('.cardMeta dd')[1].textContent = d.runs;
998
- card.querySelector('.ownerAv').setAttribute('src', d.ownerAv);
999
- card.querySelectorAll('.cardMeta dd')[2].lastChild.textContent = d.owner;
1000
- card.querySelectorAll('.cardMeta dd')[3].textContent = d.listed;
1001
- card.querySelector('.doorGo').setAttribute('href', d.site);
1002
- }
1003
-
1004
- /* ---- apply the state ---- */
1005
- body.setAttribute('data-state', st);
1006
- body.setAttribute('data-auth', s.auth);
1007
- body.setAttribute('data-view', s.view);
1008
- body.setAttribute('data-board', s.board || 'none');
1009
- setBar($('topBar'), s);
1010
- if (s.auth === 'out') {
1011
- /* relationship is a signed-in fact: no badge and no owned ring for a
1012
- visitor the page cannot even name */
1013
- var orbs = document.querySelectorAll('.worldOrb');
1014
- for (var o = 0; o < orbs.length; o++) {
1015
- orbs[o].setAttribute('data-rel', 'none');
1016
- var bdg = orbs[o].querySelector('.badge');
1017
- if (bdg) bdg.parentNode.removeChild(bdg);
1018
- }
1019
- var sp = $('selfPill');
1020
- if (sp) sp.textContent = '';
1021
- }
1022
- $('cardScrim').hidden = !s.card;
1023
- if (s.card) setCard($('projCard'), s.card, s);
1024
- if (s.view === 'table') {
1025
- $('sub-sky').setAttribute('aria-pressed', 'false');
1026
- $('sub-table').setAttribute('aria-pressed', 'true');
1027
- }
1028
- if (st === 'in-map-search') $('mapQ').focus();
1029
- if (st === 'in-map-focus') {
1030
- var second = $('projMenu').querySelectorAll('a')[1];
1031
- if (second) second.focus();
1032
- }
1033
-
1034
- /* ---- the disclosure pattern, for the real bar ---- */
1035
- function wire(triggerId, panelId) {
1036
- var t = $(triggerId), p = $(panelId);
1037
- function close(back) { t.setAttribute('aria-expanded', 'false'); p.hidden = true; if (back) t.focus(); }
1038
- function open() {
1039
- t.setAttribute('aria-expanded', 'true'); p.hidden = false;
1040
- var other = triggerId === 'projTrigger' ? 'profMenu' : 'projMenu';
1041
- var otherT = triggerId === 'projTrigger' ? 'profTrigger' : 'projTrigger';
1042
- $(other).hidden = true; $(otherT).setAttribute('aria-expanded', 'false');
1043
- }
1044
- t.addEventListener('click', function () {
1045
- if (t.getAttribute('aria-expanded') === 'true') close(false); else open();
1046
- });
1047
- p.addEventListener('keydown', function (ev) {
1048
- var links = p.querySelectorAll('a');
1049
- var at = Array.prototype.indexOf.call(links, document.activeElement);
1050
- if (ev.key === 'ArrowDown' && at > -1 && links[at + 1]) { ev.preventDefault(); links[at + 1].focus(); }
1051
- if (ev.key === 'ArrowUp' && at > 0) { ev.preventDefault(); links[at - 1].focus(); }
1052
- });
1053
- document.addEventListener('keydown', function (ev) {
1054
- if (ev.key === 'Escape' && t.getAttribute('aria-expanded') === 'true') close(true);
1055
- });
1056
- document.addEventListener('click', function (ev) {
1057
- if (t.getAttribute('aria-expanded') !== 'true') return;
1058
- if (t.contains(ev.target) || p.contains(ev.target)) return;
1059
- close(false);
1060
- });
1061
- }
1062
- /* the pill advertises cursor:text across 260x46; a click anywhere on it
1063
- lands on the field, so the drawn affordance and the target are one */
1064
- document.addEventListener('pointerdown', function (ev) {
1065
- var t = ev.target;
1066
- var pill = t && t.closest ? t.closest('.searchPill') : null;
1067
- if (!pill) return;
1068
- var inp = pill.querySelector('input');
1069
- if (inp && t !== inp) { ev.preventDefault(); inp.focus(); }
1070
- });
1071
-
1072
- wire('projTrigger', 'projMenu');
1073
- wire('profTrigger', 'profMenu');
1074
- $('cardClose').addEventListener('click', function () { $('cardScrim').hidden = true; });
1075
- $('cardScrim').addEventListener('click', function (ev) {
1076
- if (ev.target === $('cardScrim')) $('cardScrim').hidden = true;
1077
- });
1078
-
1079
- /* ---- the boards: clones of the real components, never a second copy in markup -- */
1080
- var uid = 0;
1081
- function reid(root) {
1082
- var map = {}, i, a;
1083
- var nodes = root.querySelectorAll('[id]');
1084
- if (root.id) { map[root.id] = root.id + '-b' + uid; root.id = map[root.id]; }
1085
- for (i = 0; i < nodes.length; i++) { var old = nodes[i].id; map[old] = old + '-b' + uid; nodes[i].id = map[old]; }
1086
- var refs = root.querySelectorAll('[aria-controls],[aria-labelledby],[for]');
1087
- for (i = 0; i < refs.length; i++) {
1088
- var names = ['aria-controls', 'aria-labelledby', 'for'];
1089
- for (a = 0; a < names.length; a++) {
1090
- var v = refs[i].getAttribute(names[a]);
1091
- if (v && map[v]) refs[i].setAttribute(names[a], map[v]);
1092
- }
1093
- }
1094
- uid++;
1095
- return root;
1096
- }
1097
- function row(into, label, node, frameClass) {
1098
- var wrap = document.createElement('div');
1099
- wrap.className = 'brow';
1100
- var lab = document.createElement('span');
1101
- lab.className = 'blabel';
1102
- lab.textContent = label;
1103
- var frame = document.createElement('div');
1104
- frame.className = frameClass || 'bframe';
1105
- frame.appendChild(node);
1106
- wrap.appendChild(lab);
1107
- wrap.appendChild(frame);
1108
- into.appendChild(wrap);
1109
- return frame;
1110
- }
1111
-
1112
- if (s.board === 'bar') {
1113
- var board = $('boardBar');
1114
- board.hidden = false;
1115
- var rows = ['out-map', 'in-map', 'in-map-projects', 'in-map-profile', 'in-map-focus', 'in-map-search', 'in-mine', 'in-new'];
1116
- for (var r = 0; r < rows.length; r++) {
1117
- var conf = STATES[rows[r]];
1118
- var bar = reid($('topBar').cloneNode(true));
1119
- var frame = row(board, rows[r], bar);
1120
- /* the frame carries the row's own auth, so a cloned toolbar hides the
1121
- Only mine switch exactly where the real signed-out page hides it */
1122
- frame.setAttribute('data-auth', conf.auth);
1123
- setBar(bar, conf);
1124
- if (conf.view === 'map') frame.appendChild(reid(document.querySelector('.toolbar').cloneNode(true)));
1125
- }
1126
- }
1127
- if (s.board === 'card') {
1128
- var cboard = $('boardCard');
1129
- cboard.hidden = false;
1130
- var grid = document.createElement('div');
1131
- grid.className = 'bgrid';
1132
- cboard.appendChild(grid);
1133
- var rungs = [['card', 'platform', {}], ['card-member', 'otb', {}], ['card-noart', 'platform', { art: 'off' }],
1134
- ['card-nofaces', 'platform', { faces: 'off' }], ['card-onefig', 'platform', { figs: 'one' }],
1135
- ['card-nofig', 'platform', { figs: 'none' }],
1136
- ['card-floor', 'platform', { art: 'off', faces: 'off', figs: 'none', facts: 'off', hall: 'off' }]];
1137
- for (var c = 0; c < rungs.length; c++) {
1138
- var cell = document.createElement('div');
1139
- cell.className = 'bcell';
1140
- grid.appendChild(cell);
1141
- var card = reid($('projCard').cloneNode(true));
1142
- card.removeAttribute('role');
1143
- card.removeAttribute('aria-modal');
1144
- card.removeAttribute('aria-labelledby');
1145
- var x = card.querySelector('.cardX');
1146
- if (x) x.parentNode.removeChild(x);
1147
- var lab2 = document.createElement('span');
1148
- lab2.className = 'blabel';
1149
- lab2.textContent = rungs[c][0];
1150
- cell.appendChild(lab2);
1151
- cell.appendChild(card);
1152
- setCard(card, rungs[c][1], rungs[c][2]);
1153
- }
1154
- }
1155
- if (s.board === 'menu') {
1156
- var mboard = $('boardMenu');
1157
- mboard.hidden = false;
1158
- var mgrid = document.createElement('div');
1159
- mgrid.className = 'bmenu';
1160
- mboard.appendChild(mgrid);
1161
- var cells = [
1162
- ['trigger, closed', 'proj', 'closed'],
1163
- ['panel, open', 'proj', 'open'],
1164
- ['panel, keyboard focus', 'proj', 'focus'],
1165
- ['panel, hover', 'proj', 'hover'],
1166
- ['profile panel, open', 'prof', 'open'],
1167
- ['search, at rest', 'search', 'rest'],
1168
- ['search, focused', 'search', 'focus'],
1169
- ['search, with a value', 'search', 'value']
1170
- ];
1171
- for (var m = 0; m < cells.length; m++) {
1172
- var kind = cells[m][1], mode = cells[m][2];
1173
- var node;
1174
- if (kind === 'search') {
1175
- node = reid($('searchPill').cloneNode(true));
1176
- if (mode === 'focus') node.classList.add('is-focus');
1177
- if (mode === 'value') {
1178
- node.classList.add('is-focus');
1179
- node.querySelector('input').value = 'emer';
1180
- node.querySelector('.count').textContent = '1 of 4';
1181
- }
1182
- } else {
1183
- var src = kind === 'proj' ? $('projTrigger').closest('.menu') : $('profTrigger').closest('.menu');
1184
- node = reid(src.cloneNode(true));
1185
- var trig = node.querySelector('[aria-expanded]');
1186
- var pan = node.querySelector('.menuPanel');
1187
- var isOpen = mode !== 'closed';
1188
- trig.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
1189
- pan.hidden = !isOpen;
1190
- if (mode === 'focus') pan.querySelectorAll('a')[1].classList.add('is-focus');
1191
- if (mode === 'hover') pan.querySelectorAll('a')[0].classList.add('is-hover');
1192
- }
1193
- var mcell = document.createElement('div');
1194
- mcell.className = 'bcell';
1195
- var mlab = document.createElement('span');
1196
- mlab.className = 'blabel';
1197
- mlab.textContent = cells[m][0];
1198
- var mframe = document.createElement('div');
1199
- mframe.className = 'bframe' + (kind === 'search' ? ' left' : '');
1200
- mframe.appendChild(node);
1201
- mcell.appendChild(mlab);
1202
- mcell.appendChild(mframe);
1203
- mgrid.appendChild(mcell);
1204
- }
1205
- }
1206
- })();
1207
- </script>
1208
- </body>
1209
- </html>