@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,1496 +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>Cloud Bongos projects, v3 the glass strip</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
- /* ══ v3 THE GLASS STRIP. Page tier only. cosmos.css owns the fifteen contract
17
- tokens, the sky, the orbs, the hover card, the toolbar, the table, the
18
- mine list and the footer. Nothing here declares :root. ══ */
19
-
20
- /* ---- the world's derived tier lives on body; light is the opening state ---- */
21
- *{box-sizing:border-box}
22
- body{
23
- --void-glass:color-mix(in srgb, var(--ink) 5%, transparent);
24
- --void-glass-strong:color-mix(in srgb, var(--ink) 9%, transparent);
25
- --void-pill:rgba(0,0,0,.5);
26
- --glass:color-mix(in srgb, var(--ink) 5%, transparent);
27
- --glass-strong:color-mix(in srgb, var(--ink) 8%, transparent);
28
- --glass-edge:color-mix(in srgb, var(--ink) 12%, transparent);
29
- --glass-blur:0px;
30
- --panel-bg:var(--bg-card);
31
- --art-matte:color-mix(in srgb, var(--bg-card) 45%, transparent);
32
- --door-bg:var(--glass);
33
- --accent-lift:color-mix(in srgb, var(--accent) 58%, #ffffff);
34
- --accent-tint:color-mix(in srgb, var(--accent) 30%, #ffffff);
35
- --accent-on:color-mix(in srgb, var(--accent) 18%, #000000);
36
- --accent-glow:0 0 0 0 transparent;
37
- --focus:var(--accent-deep);
38
- --type-halo:none;
39
- --label-face:var(--font-mono);
40
- --label-size:11px;
41
- --label-space:.12em;
42
- --radius:16px;
43
- --radius-sm:10px;
44
- --radius-pill:999px;
45
- --top-h:64px;
46
- }
47
- :root[data-mode="dark"] body{
48
- --void-glass:color-mix(in srgb, var(--ink) 7.5%, transparent);
49
- --void-glass-strong:color-mix(in srgb, var(--ink) 14%, transparent);
50
- --glass:color-mix(in srgb, var(--ink) 11%, transparent);
51
- --glass-strong:color-mix(in srgb, var(--ink) 17%, transparent);
52
- --glass-edge:color-mix(in srgb, var(--ink) 13%, transparent);
53
- --glass-blur:18px;
54
- --panel-bg:color-mix(in srgb, var(--bg-card) 92%, transparent);
55
- --art-matte:transparent;
56
- --accent-tint:color-mix(in srgb, var(--accent) 22%, #000000);
57
- --accent-glow:0 8px 28px color-mix(in srgb, var(--accent) 38%, transparent);
58
- --focus:var(--accent);
59
- --type-halo:0 2px 18px rgba(0,0,0,.94), 0 0 54px rgba(0,0,0,.72);
60
- --label-face:var(--font-body);
61
- --label-size:11.5px;
62
- --label-space:.1em;
63
- }
64
- :root[data-mode="dark"] .sun{display:block}
65
- :root[data-mode="dark"] .moon{display:none}
66
- @media (prefers-color-scheme: dark){
67
- :root:not([data-mode="light"]) body{
68
- --void-glass:color-mix(in srgb, var(--ink) 7.5%, transparent);
69
- --void-glass-strong:color-mix(in srgb, var(--ink) 14%, transparent);
70
- --glass:color-mix(in srgb, var(--ink) 11%, transparent);
71
- --glass-strong:color-mix(in srgb, var(--ink) 17%, transparent);
72
- --glass-edge:color-mix(in srgb, var(--ink) 13%, transparent);
73
- --glass-blur:18px;
74
- --panel-bg:color-mix(in srgb, var(--bg-card) 92%, transparent);
75
- --art-matte:transparent;
76
- --accent-tint:color-mix(in srgb, var(--accent) 22%, #000000);
77
- --accent-glow:0 8px 28px color-mix(in srgb, var(--accent) 38%, transparent);
78
- --focus:var(--accent);
79
- --type-halo:0 2px 18px rgba(0,0,0,.94), 0 0 54px rgba(0,0,0,.72);
80
- --label-face:var(--font-body);
81
- --label-size:11.5px;
82
- --label-space:.1em;
83
- }
84
- :root:not([data-mode="light"]) .sun{display:block}
85
- :root:not([data-mode="light"]) .moon{display:none}
86
- }
87
- @media (max-width:900px){ body{--top-h:56px} }
88
-
89
- /* ---- shared: icons, focus, the skip door ---- */
90
- .ic{width:17px;height:17px;flex:none;fill:none;stroke:currentColor;stroke-width:1.4;
91
- stroke-linecap:round;stroke-linejoin:round}
92
- .sprite{position:absolute;width:1px;height:1px;overflow:hidden}
93
- .sun{display:none}
94
- :focus-visible,.is-focus,.find:focus-within .findBox{outline:2px solid var(--focus);outline-offset:3px;
95
- box-shadow:0 0 0 8px var(--bg);border-radius:var(--radius-sm)}
96
- /* the field IS the pill, so the ring hangs on the pill and keeps its shape */
97
- .find:focus-within .findBox,.findBox.is-focus{border-radius:var(--radius-pill)}
98
- /* V3-10: the strip's controls run the plate's full height, so their ring turns
99
- inward. Same two tones, drawn inside the segment, never clipped by the top
100
- edge of the viewport. */
101
- .gstrip .mark:focus-visible,.gstrip .sgm:focus-visible,.gstrip .sgm.is-focus{
102
- outline-offset:-5px;box-shadow:inset 0 0 0 5px var(--bg);border-radius:0}
103
- .skip{position:absolute;left:-9999px;top:0;z-index:100;text-decoration:none}
104
- .skip:focus{left:12px;top:12px;display:inline-flex;align-items:center;min-height:24px;
105
- padding:11px 18px;border-radius:var(--radius-pill);background:var(--bg-card);
106
- border:1px solid var(--rule);color:var(--ink);font-size:14px}
107
- .lbl{font-family:var(--label-face);font-size:var(--label-size);letter-spacing:var(--label-space);
108
- text-transform:uppercase;color:var(--ink-faint)}
109
- .foot a,.finePrint a,.lede a{display:inline-block;padding:5px 3px}
110
- .btn{box-shadow:var(--accent-glow);}
111
- .btn:hover{box-shadow:var(--accent-glow);}
112
- .btn:focus-visible,.btn.is-focus{box-shadow:var(--accent-glow),0 0 0 8px var(--bg)}
113
- .btn.ghost:focus-visible,.btn.ghost.is-focus{box-shadow:0 0 0 8px var(--bg)}
114
- .tbl th .thSort{display:inline-flex;align-items:center;min-height:24px}
115
- .mineBar .search input{min-height:26px}
116
- .hero h2{font-family:var(--font-display);font-weight:300;font-size:clamp(26px,3.1vw,42px);
117
- line-height:1.06;letter-spacing:-.035em;color:var(--ink);text-shadow:var(--type-halo);
118
- margin-bottom:8px}
119
-
120
- /* ══ THE STRIP ═══════════════════════════════════════════════════════════
121
- One continuous glass plate laid over the sky: its own ground, one 1px
122
- bottom edge running the full width, and internal hairlines that belong to
123
- the plate rather than to floating pills. Not sticky, not fixed. The sky
124
- starts at the top of the page and the strip sits on it. ── */
125
- .gstrip{position:relative;z-index:40;display:flex;align-items:stretch;height:var(--top-h);
126
- background:var(--void-glass);
127
- backdrop-filter:blur(var(--glass-blur));-webkit-backdrop-filter:blur(var(--glass-blur));
128
- border-bottom:1px solid var(--glass-edge)}
129
- .gstrip .mark{flex:none;display:flex;align-items:center;gap:11px;padding:0 22px;
130
- color:var(--ink);font-size:17px;font-weight:500;letter-spacing:-.015em;white-space:nowrap;
131
- text-decoration:none;text-shadow:var(--type-halo)}
132
- .gstrip .mark .ic{width:23px;height:18px}
133
- .gstrip .find{flex:1 1 0;min-width:62px;display:flex;align-items:center;padding:0 18px;
134
- border-left:1px solid var(--glass-edge)}
135
- .findBox{position:relative;display:flex;align-items:center;gap:10px;width:100%;max-width:300px;
136
- height:44px;padding:0 13px;border-radius:var(--radius-pill);background:transparent;color:var(--ink-soft);
137
- transition:background .22s cubic-bezier(.2,.7,.3,1),max-width .22s cubic-bezier(.2,.7,.3,1)}
138
- .find:focus-within .findBox,.find.is-open .findBox{background:var(--glass-strong);max-width:340px}
139
- .findBox input{flex:1 1 0;min-width:0;height:100%;background:none;border:none;
140
- font-family:var(--font-mono);font-size:13px;color:var(--ink);text-overflow:ellipsis}
141
- .findBox input:focus-visible{outline:none;box-shadow:none}
142
- .findBox input::placeholder{color:var(--ink-soft)}
143
- .findBox .count{flex:none;font-family:var(--label-face);font-size:var(--label-size);
144
- letter-spacing:var(--label-space);color:var(--ink-soft);white-space:nowrap;
145
- font-variant-numeric:tabular-nums}
146
- .sgmWrap{position:relative;flex:none;display:flex}
147
- .sgm{flex:none;display:inline-flex;align-items:center;justify-content:center;gap:8px;
148
- min-width:44px;padding:0 18px;cursor:pointer;background:transparent;
149
- border:none;border-left:1px solid var(--glass-edge);color:var(--ink-soft);
150
- font-family:inherit;font-size:15px;text-transform:lowercase;white-space:nowrap;
151
- text-decoration:none;text-shadow:var(--type-halo);
152
- transition:background .2s cubic-bezier(.2,.7,.3,1),color .2s ease}
153
- .sgm:hover,.sgm.is-hover{background:var(--glass);color:var(--ink)}
154
- .sgm[aria-expanded="true"]{background:var(--glass-strong);color:var(--ink)}
155
- .sgm .cr{width:12px;height:12px}
156
- .sgm-mode{width:56px;padding:0}
157
- .sgm-mode .ic{width:18px;height:18px}
158
- .sgm-id img{width:26px;height:26px;border-radius:50%;object-fit:cover;flex:none}
159
- .sgm-id .who-name{font-size:15px;text-transform:none;color:var(--ink)}
160
- .idSlot{flex:none;display:flex;align-items:center;padding:0 14px;
161
- border-left:1px solid var(--glass-edge)}
162
- .signin{display:inline-flex;align-items:center;height:44px;padding:0 24px;
163
- border-radius:var(--radius-pill);text-decoration:none;text-transform:lowercase;font-weight:500;
164
- font-size:15px;background:color-mix(in srgb, var(--ink) 92%, var(--bg));color:var(--bg);
165
- transition:background .2s cubic-bezier(.2,.7,.3,1)}
166
- .signin:hover{background:var(--ink)}
167
-
168
- /* ---- the panels hang from the strip's bottom edge ---- */
169
- .menu{position:absolute;top:100%;z-index:50;width:252px;margin:0;padding:6px;list-style:none;
170
- background:var(--panel-bg);
171
- backdrop-filter:blur(var(--glass-blur));-webkit-backdrop-filter:blur(var(--glass-blur));
172
- border:1px solid var(--glass-edge);border-top:none;
173
- border-radius:0 0 var(--radius) var(--radius);
174
- animation:menuIn .22s cubic-bezier(.16,1,.3,1) both}
175
- .menu--projects{left:0}
176
- .menu--profile{right:0}
177
- .menu li{list-style:none}
178
- .menu a{position:relative;display:flex;align-items:center;min-height:44px;padding:0 14px;
179
- border-radius:var(--radius-sm);color:var(--ink-soft);font-size:15px;text-transform:lowercase;
180
- text-decoration:none;transition:background .2s cubic-bezier(.2,.7,.3,1),color .2s ease}
181
- .menu a:hover,.menu a.is-hover{background:var(--glass);color:var(--ink)}
182
- .menu a[aria-current="page"]{color:var(--ink)}
183
- .menu a[aria-current="page"]::before{content:"";position:absolute;left:0;top:50%;
184
- width:2px;height:20px;margin-top:-10px;background:var(--accent);border-radius:1px}
185
- .menu .who-row{display:flex;align-items:center;gap:10px;min-height:40px;padding:0 14px;
186
- border-bottom:1px solid var(--rule-soft);margin-bottom:6px}
187
- .menu .who-row img{width:26px;height:26px;border-radius:50%;object-fit:cover}
188
- .menu .who-row span{font-size:14px;color:var(--ink)}
189
- .menu .slot{display:block;height:6px}
190
- @keyframes menuIn{from{translate:0 6px;opacity:0}to{translate:0 0;opacity:1}}
191
-
192
- @media (max-width:900px){
193
- .gstrip .mark{padding:0 12px;gap:0}
194
- .mark-word{display:none}
195
- .gstrip .find{padding:0 10px;min-width:0}
196
- .findBox{padding:0 10px;gap:8px;max-width:420px}
197
- .sgm{padding:0 12px;gap:6px;font-size:14px}
198
- .sgm-mode{width:48px}
199
- .sgm-id .who-name{display:none}
200
- .sgm-id img{width:24px;height:24px}
201
- .idSlot{padding:0 10px}
202
- .sgmWrap{position:static}
203
- /* full width, so the panel now hangs over the toolbar rather than over the
204
- sky: it takes an opaque card ground in both modes, or the controls beneath
205
- read through it as menu items */
206
- .menu{left:8px;right:8px;width:auto;background:var(--bg-card);
207
- backdrop-filter:none;-webkit-backdrop-filter:none}
208
- .signin{padding:0 16px;height:44px}
209
- }
210
- /* V3-15. Under 560 the plate cannot hold a field that can read its own name
211
- (14 characters of the placeholder want 109px; the row has about 40), so the
212
- search takes the brief's other option: a 44px magnifier cut into the plate,
213
- opening a full-width field welded to the strip's bottom edge, the same panel
214
- material the menus use. The count comes back in that row. */
215
- @media (max-width:560px){
216
- .gstrip .find{padding:0 6px}
217
- .findBox{width:44px;max-width:44px;height:44px;padding:0;justify-content:center;
218
- background:var(--glass)}
219
- .findBox .ic{position:absolute;left:50%;top:50%;translate:-50% -50%}
220
- .findBox input{flex:0 0 24px;width:24px;min-width:24px}
221
- .findBox input::placeholder{color:transparent}
222
- .findBox .count{display:none}
223
- .find.is-open,.find:focus-within{position:absolute;left:0;right:0;top:100%;z-index:50;
224
- padding:8px 10px;background:var(--bg-card);border-left:none;
225
- border-bottom:1px solid var(--glass-edge);border-radius:0 0 var(--radius) var(--radius)}
226
- .find.is-open .findBox,.find:focus-within .findBox{width:auto;max-width:none;flex:1 1 auto;
227
- justify-content:flex-start;padding:0 13px;background:var(--glass-strong)}
228
- .find.is-open .findBox .ic,.find:focus-within .findBox .ic{position:static;translate:none}
229
- .find.is-open .findBox input,.find:focus-within .findBox input{flex:1 1 0;width:auto;min-width:0}
230
- .find.is-open .findBox input::placeholder,
231
- .find:focus-within .findBox input::placeholder{color:var(--ink-soft)}
232
- .find.is-open .findBox .count,.find:focus-within .findBox .count{display:inline}
233
- }
234
- /* 320: the plate keeps one row, so the segments give their padding back to the
235
- field rather than the field disappearing */
236
- @media (max-width:380px){
237
- .gstrip .mark{padding:0 8px;min-width:44px;justify-content:center}
238
- .gstrip .find{padding:0 4px}
239
- .sgm{padding:0 8px;gap:5px;font-size:13px}
240
- .sgm-mode{width:44px;min-width:44px}
241
- .sgm-id img{width:22px;height:22px}
242
- .idSlot{padding:0 8px}
243
- .signin{padding:0 12px;height:44px;font-size:13px}
244
- }
245
- /* under 560 the plate keeps the field rather than the count: a 48px tally would
246
- take the whole of a 320px row's search */
247
- @media (min-width:561px){ body[data-state="in-map-search"] .findBox .count{display:inline} }
248
-
249
- /* ══ THE POSTER CARD, "the room" ════════════════════════════════════════ */
250
- .cardScrim{position:fixed;inset:0;z-index:60;display:flex;align-items:center;justify-content:center;
251
- padding:24px;background:rgba(0,0,0,.55);
252
- backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px)}
253
- .ladderCell{display:contents}
254
- .ladderCell .boardLbl{display:none}
255
- .projCard{position:relative;width:min(560px,100%);max-height:calc(100vh - 48px);
256
- overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain;
257
- text-align:left;background:var(--bg-card);border:1px solid var(--rule);
258
- border-radius:var(--radius);box-shadow:none;padding:0;
259
- --art-h:224px;--nm-top:88px;--tg-top:56px;--nm-size:26px;--tg-size:13.5px;
260
- --scr-a:92px;--scr-b:132px;--scr-c:176px}
261
- /* the open move has to out-rank cosmos's own .cardScrim:not([hidden]) .projCard
262
- rule, and its keyframes must not share a name with it */
263
- .cardScrim:not([hidden]) .projCard{animation:cardInV3 .26s cubic-bezier(.16,1,.3,1) both}
264
- @keyframes cardInV3{from{translate:0 8px;opacity:0}to{translate:0 0;opacity:1}}
265
- /* a narrow card cannot hold the disc, the relationship and the faces on one
266
- shelf, so the relationship drops into the body and the shelf keeps the two
267
- things it has to show */
268
- /* in flow and sticky, not absolute: the card scrolls inside the scrim on a short phone and the
269
- way out must stay in view; the negative bottom margin keeps it a net-zero row over the art */
270
- .projCard .cardX{position:sticky;top:14px;z-index:4;width:34px;height:34px;
271
- margin:14px 14px -48px auto;
272
- cursor:pointer;display:flex;align-items:center;justify-content:center;border-radius:50%;
273
- background:color-mix(in srgb, var(--bg-card) 92%, transparent);
274
- border:1px solid var(--glass-edge);color:var(--ink);
275
- transition:background .2s cubic-bezier(.2,.7,.3,1)}
276
- .projCard .cardX:hover{background:var(--bg-card);color:var(--ink)}
277
- /* The banner. 5:2, object-fit:cover, plus an object-view-box that crops the
278
- plate to its chrome: the og-card is a capture of the landing, and a plain
279
- cover crop puts the landing's own headline behind a card that then prints the
280
- same words. The view box is the source rectangle x 620..1200, y 222..454 of
281
- 1200x630, which is 2.5:1, sits below the headline's descenders and is all
282
- sculpture. A browser without object-view-box falls back to the plain cover. */
283
- .projCard .cardArt{display:block;width:100%;aspect-ratio:5 / 2;object-fit:cover;
284
- object-view-box:inset(35.24% 0% 27.94% 51.67%);margin:0 0 44px}
285
- .projCard .artScrim{position:absolute;left:0;right:0;top:0;height:var(--art-h);pointer-events:none;
286
- background:linear-gradient(to top,
287
- var(--bg-card) 0,
288
- var(--bg-card) var(--scr-a),
289
- color-mix(in srgb, var(--bg-card) 55%, transparent) var(--scr-b),
290
- transparent var(--scr-c)),
291
- linear-gradient(var(--art-matte),var(--art-matte))}
292
- .projCard .cardDot{position:absolute;z-index:3;left:26px;top:calc(var(--art-h) - 27px);
293
- display:block;margin:0;box-shadow:none;
294
- width:46px;height:46px;border-radius:50%;border:4px solid var(--bg-card);
295
- background:radial-gradient(circle at 34% 28%,
296
- color-mix(in srgb, var(--acc,var(--accent)) 22%, #ffffff) 0%,
297
- var(--acc,var(--accent)) 42%,
298
- color-mix(in srgb, var(--acc,var(--accent)) 72%, #000000) 100%)}
299
- .projCard .cardName{position:absolute;z-index:2;left:26px;right:26px;
300
- top:calc(var(--art-h) - var(--nm-top));
301
- margin:0;font-family:var(--font-display);font-weight:300;font-size:var(--nm-size);
302
- line-height:1.1;letter-spacing:-.03em;color:var(--ink)}
303
- .projCard .cardTag{position:absolute;z-index:2;left:26px;right:26px;
304
- top:calc(var(--art-h) - var(--tg-top));
305
- margin:0;font-weight:400;font-size:var(--tg-size);line-height:1.45;color:var(--ink-soft)}
306
- .projCard .faces{position:absolute;z-index:3;right:26px;top:calc(var(--art-h) - 16px);
307
- display:flex;align-items:center;margin:0}
308
- .projCard .faces img{width:28px;height:28px;border-radius:50%;object-fit:cover;
309
- border:2px solid var(--bg-card);margin-left:-8px}
310
- .projCard .faces img:first-child{margin-left:0}
311
- .projCard .faces .more{margin-left:7px;height:28px;display:inline-flex;align-items:center;
312
- padding:0 9px;border-radius:var(--radius-pill);background:var(--bg-card);
313
- border:1px solid var(--rule-soft);font-family:var(--label-face);font-size:11px;
314
- color:var(--ink-soft);font-variant-numeric:tabular-nums}
315
- /* the shelf: the disc, the relationship and the faces share one line ACROSS the
316
- banner's lower edge, so the card's body starts clear of all three */
317
- .projCard .cardRel{position:absolute;z-index:3;left:96px;top:calc(var(--art-h) - 14px);
318
- display:inline-block;margin:0;padding:5px 11px;
319
- border-radius:var(--radius-pill);border:1px solid var(--rule);background:transparent;
320
- font-family:var(--label-face);font-size:var(--label-size);letter-spacing:var(--label-space);
321
- text-transform:uppercase;color:var(--ink-soft)}
322
- .projCard .cardMeta{display:grid;grid-template-columns:1fr auto;gap:0;
323
- margin:0;padding:0 26px;text-align:left}
324
- .projCard .cardMeta dt{grid-column:1;padding:13px 14px 13px 0;align-self:stretch;
325
- display:flex;align-items:center;border-top:1px solid var(--rule-soft);
326
- font-family:var(--label-face);font-size:var(--label-size);letter-spacing:var(--label-space);
327
- text-transform:uppercase;color:var(--ink-faint)}
328
- .projCard .cardMeta dd{grid-column:2;margin:0;padding:13px 0;align-self:stretch;
329
- display:flex;align-items:center;justify-content:flex-end;text-align:right;
330
- border-top:1px solid var(--rule-soft);font-size:14.5px;font-weight:500;color:var(--ink);
331
- font-variant-numeric:tabular-nums}
332
- .projCard .cardMeta dd.fig{font-family:var(--font-display);font-weight:300;font-size:30px;
333
- line-height:1;letter-spacing:-.035em;padding:11px 0}
334
- .projCard .cardMeta dd img{width:17px;height:17px;border-radius:50%;object-fit:cover;
335
- vertical-align:-4px;margin-right:7px}
336
- .projCard .doorbar{display:flex;justify-content:center;gap:7px;margin:22px 26px 26px;padding:7px;
337
- border-radius:var(--radius-pill);background:var(--door-bg);border:1px solid var(--glass-edge)}
338
- .projCard .door{flex:1 1 0;display:inline-flex;align-items:center;justify-content:center;
339
- min-height:46px;padding:0 18px;border-radius:var(--radius-pill);text-decoration:none;
340
- text-transform:lowercase;font-size:15px;color:var(--ink);white-space:nowrap;
341
- transition:background .22s cubic-bezier(.2,.7,.3,1),color .2s ease}
342
- .projCard .door:hover{background:var(--glass-strong)}
343
- .projCard .door--go{background:var(--accent);color:var(--accent-on);box-shadow:var(--accent-glow);}
344
- .projCard .door--go:hover{background:var(--accent-lift);color:var(--accent-on)}
345
- .projCard .door--go:focus-visible,.projCard .door--go.is-focus{
346
- box-shadow:var(--accent-glow),0 0 0 8px var(--bg)}
347
- /* two doors stay equal halves, as the door pill asks; a lone door takes the
348
- world's own pill width rather than the whole bar, so the emptiest rung of the
349
- ladder does not carry the loudest accent field on the page */
350
- .projCard .door:only-child{flex:0 1 auto;padding:0 30px}
351
- /* and the tray around a lone door goes: one pill standing alone, not a pill inside an empty ring */
352
- .projCard .doorbar:has(> .door:only-child){padding:0;background:none;border-color:transparent}
353
-
354
- /* the ladder's no-art rung: the banner and its scrim leave, the head block
355
- centres and the disc renders where it does today */
356
- .projCard.noart{text-align:center;padding-top:30px}
357
- .projCard.noart .cardArt,.projCard.noart .artScrim{display:none}
358
- .projCard.noart .cardDot{position:static;z-index:auto;width:54px;height:54px;
359
- border:none;margin:0 auto}
360
- .projCard.noart .cardName{position:static;left:auto;right:auto;top:auto;
361
- margin:16px 26px 0;font-size:26px}
362
- .projCard.noart .cardTag{position:static;left:auto;right:auto;top:auto;
363
- margin:7px 26px 0;font-size:14px}
364
- .projCard.noart .faces{position:static;top:auto;right:auto;justify-content:center;
365
- margin:18px 26px 0}
366
- .projCard.noart .cardRel{position:static;left:auto;top:auto;margin:16px 26px 0}
367
- .projCard.noart .cardMeta{margin-top:22px}
368
- @media (max-width:608px){
369
- .projCard{--art-h:calc((100vw - 48px) / 2.5);--nm-top:70px;--tg-top:44px;
370
- --nm-size:21px;--tg-size:12.5px;--scr-a:76px;--scr-b:104px;--scr-c:136px}
371
- .projCard .cardArt{margin-bottom:34px}
372
- .projCard .cardRel{position:static;left:auto;top:auto;margin:14px 26px 0}
373
- }
374
-
375
- /* ══ BOARDS ═════════════════════════════════════════════════════════════ */
376
- .board{position:relative;z-index:1;padding:26px 26px 40px}
377
- .boardLbl{display:block;margin-bottom:9px;font-family:var(--label-face);font-size:var(--label-size);
378
- letter-spacing:var(--label-space);text-transform:uppercase;color:var(--ink-faint)}
379
- .boardRow{margin-bottom:30px}
380
- .boardFrame{position:relative;border:1px solid var(--rule-soft);border-radius:var(--radius);
381
- overflow:hidden;background:var(--bg)}
382
- .boardFrame .gstrip{z-index:2}
383
- .boardFrame .under{height:164px}
384
- .boardGrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(310px,1fr));
385
- gap:28px;align-items:start}
386
- .boardGrid .cell{min-width:0}
387
- body[data-state="board-card"] .cardScrim{position:relative;z-index:1;display:grid;padding:26px 26px 40px;
388
- grid-template-columns:repeat(auto-fill,320px);gap:30px 28px;align-items:start;
389
- justify-content:center;background:none;backdrop-filter:none;-webkit-backdrop-filter:none}
390
- body[data-state="board-card"] .ladderCell{display:block;min-width:0}
391
- body[data-state="board-card"] .ladderCell .boardLbl{display:block}
392
- body[data-state="board-card"] .projCard{width:320px;max-height:none;animation:none;
393
- --art-h:128px;--nm-top:70px;--tg-top:44px;--nm-size:21px;--tg-size:12.5px;
394
- --scr-a:76px;--scr-b:104px;--scr-c:136px}
395
- body[data-state="board-card"] .projCard .cardArt{margin-bottom:34px}
396
- body[data-state="board-card"] .projCard .cardRel{position:static;left:auto;top:auto;
397
- margin:14px 26px 0}
398
- body[data-state="board-card"] .projCard .cardX{display:none}
399
- body[data-state="board-card"] .cardScrim:not([hidden]) .projCard{animation:none}
400
-
401
- /* ══ VIEW SWITCHING (the state contract) ════════════════════════════════ */
402
- #view-map,#view-mine,#view-new,#board-bar,#board-menu{display:none}
403
- body[data-view="map"] #view-map,
404
- body[data-view="table"] #view-map{display:block}
405
- body[data-view="mine"] #view-mine{display:block}
406
- body[data-view="new"] #view-new{display:block}
407
- body[data-state="board-bar"] #board-bar{display:block}
408
- body[data-state="board-menu"] #board-menu{display:block}
409
- body[data-view="map"] #sub-table-body{display:none}
410
- body[data-view="table"] #sub-sky-body{display:none}
411
- /* the table is 491px of nowrap cells: it scrolls inside its own panel rather
412
- than off the page, which is what body[overflow-x:hidden] does to it today */
413
- body[data-view="table"] #sub-table-body{display:block;overflow-x:auto}
414
- body[data-view="table"] #sub-sky{background:transparent;color:var(--glass-ink)}
415
- body[data-view="table"] #sub-table{background:var(--accent);color:var(--accent-on)}
416
- body[data-view="mine"] .find,body[data-view="new"] .find{display:none}
417
- body[data-auth="out"] .switch{display:none}
418
- body[data-auth="out"] header .sgm-id,body[data-auth="in"] header .idSlot{display:none}
419
- /* with the search gone, the segments take the plate's right end */
420
- body[data-view="mine"] .find + .sgmWrap,
421
- body[data-view="new"] .find + .sgmWrap{margin-left:auto}
422
- body[data-view="board"] header.gstrip,
423
- body[data-view="board"] #view-mine,
424
- body[data-view="board"] #view-new,
425
- body[data-view="board"] .foot{display:none}
426
- body[data-state="board-bar"] #view-map,
427
- body[data-state="board-menu"] #view-map{display:none}
428
- body[data-state="board-card"] #view-map{display:block}
429
- body[data-state="board-card"] #view-map > :not(#cardScrim){display:none}
430
- body[data-auth="out"] #gate{display:block}
431
- body[data-auth="out"] #mine{display:none}
432
- body[data-auth="in"] #gate{display:none}
433
- body[data-auth="in"] #mine{display:block}
434
- .panel{display:none}
435
- body[data-state="out-new"] #panel-gate{display:block}
436
- body[data-state="in-new"] #panel-name{display:block}
437
-
438
- /* the new view keeps its own field vocabulary, drawn with control tokens */
439
- .wizField{display:block;margin-bottom:18px}
440
- .wizField>span{display:block;font-size:13.5px;font-weight:700;color:var(--ink-soft);
441
- margin-bottom:7px;letter-spacing:.2px}
442
- #view-new input[type=text]{width:100%;padding:12px 16px;border-radius:var(--radius);
443
- border:1.5px solid var(--ctl-line);background:var(--bg-card);color:var(--ink);
444
- font-family:var(--font-body);font-size:15.5px}
445
- #view-new .hint{min-height:18px;font-size:12.5px;color:var(--ink-faint);margin-top:7px}
446
- #view-new .nav{display:flex;justify-content:space-between;align-items:center;gap:12px;margin-top:6px}
447
- #view-mine .hero,#view-new .hero{max-width:none}
448
-
449
- /* the hall entry on a table row rides in the existing go cell, so the row
450
- keeps its six columns */
451
- .hallGo{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;
452
- margin-right:8px;border-radius:var(--radius-pill);vertical-align:middle;
453
- border:1px solid var(--rule);color:var(--ink-soft);text-decoration:none;
454
- transition:background .2s cubic-bezier(.2,.7,.3,1),color .2s ease}
455
- .hallGo:hover{background:var(--glass);color:var(--ink)}
456
- </style>
457
- </head>
458
- <body>
459
- <!--
460
- v3 "THE GLASS STRIP" for /projects. Mock only. Nothing here edits a build file.
461
-
462
- THESIS The hub's chrome should be one surface, not a row of objects standing on
463
- one. So the bar is a single continuous plate of glass laid over the sky: one
464
- ground, one bottom edge, and every control cut INTO it as a segment rather than
465
- set on it as a pill. The sky reads through the plate (that is the material) but
466
- the plate is unmistakably a thing, because it has a tint, an edge and internal
467
- hairlines that meet that edge. The card answers the strip: where the strip is a
468
- plate you look through, the card is a room you look into, and the art recedes
469
- into the card ground rather than sitting in a frame on it.
470
-
471
- BAR Ground var(--void-glass) with backdrop blur var(--glass-blur), closed by a
472
- 1px var(--glass-edge) bottom edge. 64px at desktop, 56px under 900, never
473
- sticky, sitting at the very top of the page (the hub has no sky top scrim to
474
- retire; cosmos paints one flat --sky-bg from the bar to the footer, so nothing
475
- was removed). LEFT: the bongo-pair glyph plus the product name, then a hairline,
476
- then the search fused into the plate, no field chrome at rest, a magnifier and
477
- "Find a project" in --ink-soft; on focus a --glass-strong inset pill grows from
478
- 300px to 340px around the glyph, the field and the count. The pill is 44px, is
479
- the field's whole target (a press anywhere on it takes the caret), and is what
480
- the two-tone focus ring hangs on, so the ring reads on the thing the eye calls
481
- the field rather than on the 24px input inside it. The count is --ink-soft, not
482
- --ink-faint: the strip tints its own ground, and ink-faint has no headroom left
483
- to spend once it does. RIGHT: three segments,
484
- each opened by a 1px var(--glass-edge) hairline, "Projects" with a caret, the
485
- mode toggle, then the identity (the landing's inverted ink door signed out, the
486
- avatar + login + caret chip signed in). The open segment fills --glass-strong,
487
- which is how the plate says which panel is hanging off it.
488
- HOW THE GIVEN IS SATISFIED Given 1 asks for a real surface with its own ground
489
- and a bottom edge, not floating controls over the sky. The strip has exactly
490
- one ground (a tint, blurred in dark), exactly one bottom edge that runs the full
491
- width uninterrupted, and no control inside it carries a ground of its own at
492
- rest. Every hairline inside the plate terminates on that bottom edge, so the
493
- segments read as cuts in one plate rather than as separate objects. The one
494
- exception is the sign-in door, which is a solid ink pill because it is the one
495
- thing on the bar that is both pressable and primary.
496
-
497
- MENU A panel of the card voice hanging from the strip's bottom edge: ground
498
- var(--panel-bg) (--bg-card at 92% in dark under an 18px blur, plain --bg-card on
499
- paper), 1px var(--glass-edge), no top border and no top radius so it is welded
500
- to the strip, 16px on the bottom two corners, 252px wide, aligned to its
501
- segment's own edge. Items are 44px lowercase rows, --ink-soft rising to --ink.
502
- The current view is marked twice: its ink goes to --ink and a 2px accent bar
503
- sits at its left edge, the lifecycle rail's lit-step grammar. It carries
504
- aria-current="page", and the mark FOLLOWS the view the page is on (Table is a
505
- sub-mode of the Map destination, so it marks Map), because the accent lights the
506
- live thing and the live thing is where you are standing. Under 900 the panel
507
- drops to the strip's full width, which puts it over the toolbar rather than over
508
- the sky, so there it takes an opaque --bg-card ground in both modes; nothing
509
- behind a menu may be readable as a menu item. Opening is one authored move, a
510
- 6px rise and fade over 220ms on cubic-bezier(.16,1,.3,1); dead under reduced
511
- motion. The card's own open move is 260ms on the same curve, declared on
512
- .cardScrim:not([hidden]) .projCard under its own keyframe name so cosmos's
513
- 160px/ease-out rule of the same name cannot out-rank it.
514
-
515
- CARD Six regions, reordered by the thesis. 1 the 5:2 banner, a real image, top
516
- corners taken from the card, cropped by an object-view-box to the plate's own
517
- sculpture (see DATA). 2 the name at the title scale and the tagline sit ON the
518
- banner's lower third, over a scrim that is a vertical gradient of var(--bg-card)
519
- itself, so it is card black in dark and paper in light and never a black panel
520
- on a light page; the art dissolves upward into the card instead of ending at a
521
- rule. 3 THE SHELF: the accent disc straddles the banner's lower edge at the
522
- left, ringed 4px in the card ground and carrying the sky orb's own radial gloss
523
- so the card's disc and the orb are one object; the relationship sits beside it
524
- as a hairline label, not an accent pill, because a relationship is a fact and
525
- not a control; the faces straddle the same edge at the right. All three sit on
526
- one line across the boundary, and the card's body starts clear of them. 4 and 5
527
- the two figures and the four facts are ONE hairline ledger, label left in
528
- --label-face, value right and tabular, with builders and shipped in 30 days as
529
- the first two rows at the figure scale, so a number is read in the same column
530
- as a fact rather than in a band of its own. 6 the actions are a full-width door
531
- bar: the accent primary and the hall entry as its quiet twin, equal halves of
532
- the bar as the door pill asks. A LONE door does not stretch: it takes the
533
- world's own 30px pill padding and centres, so the ladder's emptiest rungs do not
534
- carry the largest accent field on the page. The card scrolls inside itself when
535
- the viewport is shorter than the rung (card-member is 728px at 390), so the
536
- primary door is never clipped away. With no art the banner and the scrim leave,
537
- the head block centres, and the disc renders at 54px where it does today. Nothing in the card is nested: every region is a direct
538
- child, so the C6 slice that ends at the first adjacent pair of closing wrappers
539
- still reaches cardListed.
540
-
541
- LIGHT The strip is a 5% ink tint on paper with the blur token at 0px, so light
542
- glass is a tint and not a frost, and the bottom hairline does the separating.
543
- The panel is paper (plain --bg-card) with the same hairline. The card is
544
- --bg-card on paper, hairlines only, no shadow anywhere. The banner takes a
545
- light-only paper matte, --art-matte (45% --bg-card, transparent in dark), laid
546
- under the scrim: the og-card is a capture of a black page, and without the matte
547
- its unlit half lands on paper as the black panel the world forbids. The scrim
548
- resolves to paper,
549
- measured over the real og-card art with a pixel probe (screenshot the card with
550
- the glyphs hidden, read every ground pixel under the two text boxes, take the
551
- worst): the name lands on rgb(251,249,252) in light at 16.97:1 and rgb(16,16,18)
552
- in dark at 19.01:1; the tagline 7.00:1 and 10.45:1. The name block sits entirely
553
- inside the scrim's opaque run in both modes and at both widths, so the sampled
554
- ground IS --bg-card and never a black panel on paper.
555
-
556
- 390 The strip stays one row and one plate down to 320. The wordmark folds to
557
- the glyph, and under 560 the search takes the brief's other option: it collapses
558
- to a 44px magnifier cut into the plate, and a press opens the field full width
559
- on the strip's bottom edge, on the same --bg-card panel the menus hang from,
560
- with the count back inside it. A compact field was measured and rejected: the
561
- placeholder wants 109px of the row and the row can spare about 40, so at 390 and
562
- 320 it read "Fin..." and "Fi...", which is worse than a glyph. The mark, the
563
- toggle, the segments and the sign-in door all hold 44px down to 320. The panels
564
- drop to the full width of the strip, still welded to its bottom edge. The card
565
- keeps its 5:2 crop and scales the name block to 21px.
566
-
567
- BEYOND THE SKIN
568
- - given Projects becomes a right-group dropdown; the nav row leaves the bar.
569
- COLLISION projects_hub_pre_uat.mjs:203 pins the cosmos rule
570
- ".shell .navrow{position:absolute;left:50%;top:50%;...}"; deleting .navrow
571
- from cosmos.css kills that test. Retarget it, or keep an unused .navrow rule.
572
- projects_hub.mjs:42-43 is SAFE if the menu items keep
573
- href="?view=map" data-nav="map" as adjacent attributes, which they do here.
574
- - given Home is removed; the logo is home. COLLISION projects_hub.mjs:40 (the
575
- Home link regex) and :46,:48 (the dataset.nav === 'home' guards) break hard.
576
- - given the hall pill leaves the bar. COLLISION landing_page.mjs:214,217,220
577
- and projects_hub.mjs:105 all read data-link-hall href="{{buildersOrigin}}" in
578
- the hub and collapse. ARCHITECTURE no feed carries a per-project hall address,
579
- so "only where the hall address differs" needs a new field on
580
- /projects/featured or /my-projects; it cannot be a {{token}}.
581
- - given the map search moves into the bar and hides off the map. SAFE.
582
- - consequence the toolbar is now two controls, Sky | Table and Only mine. The
583
- count element (#mapCount) travels with the search into the strip, because a
584
- count belongs to the field that produces it; at rest it reads "4 projects" and
585
- under a query "1 of 4".
586
- - consequence the nav row's height returns to the sky: the bar loses one of
587
- today's three desktop rows and all three of today's mobile ones, so the sky at
588
- 390 starts about 244px higher than it does now.
589
- - consequence the relationship pill loses the accent. It states a fact and is
590
- not pressable, so under the One Warm Thing Rule it becomes a hairline pill in
591
- the label face. The accent on this page is spent only on the primary door, the
592
- current view in the Projects menu, the owned-orb ring cosmos already draws,
593
- and the focus ring.
594
- - proposal the hall glyph rides INSIDE the existing .colGo cell beside
595
- "Open ->", rather than as a seventh column. That keeps the row at six <td>s,
596
- so projects_hub.mjs:531-535 (header/selfRow/template td parity) never fires.
597
- - consequence the table glyph and the card's hall entry obey ONE rule, the
598
- address gate of given 7: the glyph shows on the platform's own row (its hall
599
- is builders.cloudbongos.com) and NOT on Off the Boats, whose hall is at
600
- amazonprimea.com/builders, the same address as its site. Member-gating alone
601
- would have put a glyph on a row whose card correctly has no door.
602
- - proposal the table view scrolls sideways inside its own panel under about
603
- 500px. Its cells are nowrap and it measures 491px, and today the page simply
604
- hides the overflow with cosmos's body{overflow-x:hidden}, which means Status
605
- and Open are unreachable on a phone. One CSS line on #sub-table-body fixes it
606
- and nothing else changes. No test collision.
607
- - proposal the unknown mark in the table becomes a middot rather than an em
608
- dash, so the hub obeys the same no-dash rule the card already obeys.
609
- COLLISION projects_hub.mjs:564-580 pins p.builders == null ? '-' (em dash) and
610
- tagsHtml returning an em dash.
611
- - proposal "Runs" is the label the hub gives a project's module list. The
612
- brief's data reads runs = cloudbongos.com, so this mock renders Runs as the
613
- address in both cards. If that is the intent, COLLISION projects_hub.mjs:
614
- 586-602 pins cardFact('cardRuns', Array.isArray(p.tags) ? tagsHtml(p.tags)...)
615
- and would need retargeting; if it is not, Runs stays the tag list and the
616
- address is already carried by the primary door.
617
- - proposal a project's art_url is a photograph the platform did not author, and
618
- a dark one reads on paper as the black panel the world otherwise forbids. This
619
- mock now takes the second of the two options it framed: in light the banner
620
- carries a 45% paper matte (--art-matte, transparent in dark), so no rung of
621
- the ladder puts a black lid on a light card. The owner should say whether the
622
- matte stays at 45%, goes further, or is dropped in favour of asking projects
623
- for graded art; it is the only place light mode takes an image it did not
624
- grade.
625
- - proposal the card grows to 640px on desktop. The room earns it: the ledger
626
- runs to eight rows on a full project and the banner is the composition.
627
- - proposal the hover card takes the panel's ground (--panel-bg plus the same
628
- hairline and blur) instead of --bg-card with --shadow-card, so the one thing
629
- that floats over the sky and the one thing that hangs off the strip are the
630
- same material. This world has no shadow vocabulary for UI.
631
- - proposal the strip's search finds by tag as well as by name, since the tags
632
- are already in the catalog row and the table already shows them.
633
- - proposal About (goal 1000063) becomes a fourth item in the Projects menu,
634
- under a hairline below New project, because it is a destination of this
635
- surface and not of the bar.
636
- - proposal the wizard's bongo pair still carries a marigold ceramic ramp of
637
- literal hexes (projects.html:72-75). In this world it takes the --chrome-* and
638
- --skin-* ramp from DESIGN.md's sidecar. It is elided from this mock rather
639
- than reproduced, because the mock's rule set forbids a literal in the page
640
- sheet; nothing else about the new view changed.
641
- - proposal the mine view's empty state is drawn today with a 2px dashed
642
- var(--line) box. Hairlines, not containers: one top rule and the sentence.
643
-
644
- DATA Real, fetched 2026-08-27. Signed-in builder jaxri. The sky's four orbs
645
- carry the live catalog's own accents and slots: Demo terracotta at 22/30 d74,
646
- Emersonian Circles gold-soft at 78/66 d60, Off the Boats sea at 33/74 d56, the
647
- platform accent at 50/44 d122; the accents come from assignAccents() sorting the
648
- catalog by origin, the slots from ORB_SLOTS in name order. The card figures are
649
- the apex leaderboard's 9 builders with credits above zero and the 30-row feed cap
650
- rendered as 30+; Off the Boats is 13 builders and a real 0 shipped in 30 days
651
- (its newest ship is 2026-06-30). Faces are real GitHub avatars. Listed dates are
652
- the catalog's created_at (Jul 14 2026 for the platform, taken from the Demo row
653
- as the brief allows; Jul 15 2026 for Off the Boats). ART the platform has no
654
- art_url in the feed, so the banner uses the landing's own social card,
655
- public-landing/assets/world/og-card.jpg, a real 1200x630 capture of the built
656
- landing. It is object-fit:cover at 5:2 as the brief asks, with one deviation
657
- stated here: a plain cover crop of a 1200x630 plate into a 2.5:1 box shows the
658
- FULL WIDTH of the landing, headline included, so the card would print "Building
659
- Digitally, as simple as Bongos." twice, once as art and once as its own tagline.
660
- An object-view-box narrows the source to x 620..1200, y 222..454, which is 2.5:1
661
- and is all sculpture, and the fallback for a browser without it is the plain
662
- cover crop. No other image is invented and no pixel is retouched.
663
- MEMBERSHIP is illustrative: jaxri is treated as a builder on both the platform
664
- and Off the Boats so the member-only affordances can be seen; the live page
665
- would read archon on the apex and show "yours". The static self orb is carried
666
- verbatim from projects.html, which is why it wears no badge here.
667
-
668
- TOKENS Declared on body (never :root), with the dark twin written twice
669
- byte-identical: --void-glass, --void-glass-strong, --void-pill, --glass,
670
- --glass-strong, --glass-edge, --glass-blur, --panel-bg, --door-bg,
671
- --art-matte, --accent-lift, --accent-tint, --accent-on, --accent-glow, --focus,
672
- --type-halo, --label-face, --label-size, --label-space, --radius, --radius-sm, --radius-pill,
673
- --top-h. Every one is a var() or a color-mix() of the fifteen contract tokens;
674
- the only literals are pure black and pure white with alpha. The glass family is
675
- expressed as color-mix(in srgb, var(--ink) N%, transparent) rather than
676
- world.css's rgba pairs, so one recipe gives ink-on-paper in light and
677
- white-on-black in dark. --focus takes var(--accent-deep) in light and
678
- var(--accent) in dark rather than world.css's mix with a literal. --font-mono,
679
- --line, --ok, --warn and --err are cosmos.css's on this page and are not
680
- redeclared: --line is a hairline COLOUR here, not a width, and ok/warn/err are
681
- the hub's fixed verification vocabulary.
682
- -->
683
-
684
- <svg class="sprite" aria-hidden="true" focusable="false">
685
- <symbol id="i-bongos" viewBox="0 0 26 20"><ellipse cx="8.4" cy="5.6" rx="6.6" ry="2.9"/><path d="M1.8 5.6v6.6a6.6 2.9 0 0 0 13.2 0V5.6"/><ellipse cx="19.6" cy="8.4" rx="4.7" ry="2.1"/><path d="M14.9 8.4v4.6a4.7 2.1 0 0 0 9.4 0V8.4"/></symbol>
686
- <symbol id="i-search" viewBox="0 0 20 20"><circle cx="9" cy="9" r="5.6"/><path d="M13.2 13.2 17 17"/></symbol>
687
- <symbol id="i-caret" viewBox="0 0 20 20"><path d="m5.6 8 4.4 4.4L14.4 8"/></symbol>
688
- <symbol id="i-moon" viewBox="0 0 20 20"><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"/></symbol>
689
- <symbol id="i-sun" viewBox="0 0 20 20"><circle cx="10" cy="10" r="3.9"/><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"/></symbol>
690
- <symbol id="i-hall" viewBox="0 0 20 20"><path d="M2.6 7.6 10 3.4l7.4 4.2"/><path d="M4.8 9v5.4M8.3 9v5.4M11.7 9v5.4M15.2 9v5.4"/><path d="M3 16.4h14"/></symbol>
691
- <symbol id="i-close" viewBox="0 0 20 20"><path d="M5.8 5.8l8.4 8.4M14.2 5.8l-8.4 8.4"/></symbol>
692
- </svg>
693
-
694
- <div class="sky" aria-hidden="true">
695
- <span class="star" style="top:2%;left:12%;width:2px;height:2px;"></span>
696
- <span class="star" style="top:5%;left:28%;width:1.5px;height:1.5px;animation-delay:.7s;"></span>
697
- <span class="star" style="top:3%;left:47%;width:2px;height:2px;animation-delay:1.4s;"></span>
698
- <span class="star" style="top:8%;left:63%;width:1.5px;height:1.5px;animation-delay:.3s;"></span>
699
- <span class="star" style="top:4%;left:78%;width:2.5px;height:2.5px;animation-delay:2s;"></span>
700
- <span class="star" style="top:10%;left:88%;width:1.5px;height:1.5px;animation-delay:1s;"></span>
701
- <span class="star" style="top:14%;left:20%;width:1.5px;height:1.5px;animation-delay:1.8s;"></span>
702
- <span class="star" style="top:22%;left:55%;width:2px;height:2px;animation-delay:.5s;"></span>
703
- <span class="star" style="top:34%;left:36%;width:1.5px;height:1.5px;animation-delay:2.4s;"></span>
704
- <span class="star" style="top:30%;left:78%;width:1.5px;height:1.5px;animation-delay:1.2s;"></span>
705
- <span class="star" style="top:48%;left:8%;width:2px;height:2px;animation-delay:.9s;"></span>
706
- <span class="star" style="top:55%;left:90%;width:1.5px;height:1.5px;animation-delay:1.6s;"></span>
707
- <span class="star" style="top:68%;left:24%;width:1.5px;height:1.5px;animation-delay:2.1s;"></span>
708
- <span class="star" style="top:76%;left:64%;width:2px;height:2px;animation-delay:.4s;"></span>
709
- <span class="star" style="top:88%;left:42%;width:1.5px;height:1.5px;animation-delay:1.9s;"></span>
710
- </div>
711
-
712
- <a class="skip" href="#hubMain">Skip to content</a>
713
-
714
- <header class="gstrip">
715
- <a class="mark" href="/" aria-label="Cloud Bongos, home">
716
- <svg class="ic" aria-hidden="true"><use href="#i-bongos"></use></svg>
717
- <span class="mark-word">Cloud Bongos</span>
718
- </a>
719
-
720
- <div class="find" id="find">
721
- <span class="findBox">
722
- <svg class="ic" aria-hidden="true"><use href="#i-search"></use></svg>
723
- <label class="vh" for="mapQ">Search projects</label>
724
- <input type="text" id="mapQ" placeholder="Find a project">
725
- <span class="count" id="mapCount">4 projects</span>
726
- </span>
727
- </div>
728
-
729
- <span class="sgmWrap">
730
- <button type="button" class="sgm" id="projTrigger" aria-expanded="false" aria-controls="projMenu">Projects<svg class="ic cr" aria-hidden="true"><use href="#i-caret"></use></svg></button>
731
- <ul class="menu menu--projects" id="projMenu" hidden>
732
- <li><a href="?view=map" data-nav="map" aria-current="page">Map</a></li>
733
- <li><a href="?view=mine" data-nav="mine" id="menuMine">Your projects</a></li>
734
- <li><a href="?view=new" data-nav="new">New project</a></li>
735
- </ul>
736
- </span>
737
-
738
- <button type="button" class="sgm sgm-mode" id="modeToggle" aria-label="Toggle light or dark">
739
- <svg class="ic moon" aria-hidden="true"><use href="#i-moon"></use></svg>
740
- <svg class="ic sun" aria-hidden="true"><use href="#i-sun"></use></svg>
741
- </button>
742
-
743
- <span class="idSlot"><a class="signin" href="/api/bongos/auth/web/start?return=/projects">Sign in</a></span>
744
-
745
- <span class="sgmWrap">
746
- <button type="button" class="sgm sgm-id" id="profTrigger" aria-expanded="false" aria-controls="profMenu" aria-label="Account, jaxri">
747
- <img src="https://avatars.githubusercontent.com/u/64553469?v=4" alt="">
748
- <span class="who-name">jaxri</span>
749
- <svg class="ic cr" aria-hidden="true"><use href="#i-caret"></use></svg>
750
- </button>
751
- <ul class="menu menu--profile" id="profMenu" hidden>
752
- <li class="who-row"><img src="https://avatars.githubusercontent.com/u/64553469?v=4" alt=""><span>jaxri</span></li>
753
- <li><a href="https://builders.cloudbongos.com/my-projects">My projects</a></li>
754
- <li class="slot"></li>
755
- <li><a href="/api/bongos/auth/logout">Sign out</a></li>
756
- </ul>
757
- </span>
758
- </header>
759
-
760
- <main id="hubMain">
761
-
762
- <section id="view-map">
763
- <h1 class="vh">The project map</h1>
764
-
765
- <div class="toolbar">
766
- <div class="seg" role="group" aria-label="Map display">
767
- <button type="button" id="sub-sky" aria-pressed="true">Sky</button>
768
- <button type="button" id="sub-table" aria-pressed="false">Table</button>
769
- </div>
770
-
771
- <label class="switch" title="Show only projects you own or build on">
772
- <input type="checkbox" id="onlyMine"><span class="track"></span> Only mine
773
- </label>
774
- </div>
775
-
776
- <div class="fieldWrap" id="sub-sky-body">
777
- <div class="field" id="orbField">
778
- <div class="ground"></div>
779
- <div class="stars" id="mapStars" aria-hidden="true"></div>
780
- <div class="skyCam" id="skyCam">
781
- <!--apex-only:start-->
782
- <a class="worldOrb" id="selfOrb" href="/" style="--acc:var(--accent);--d:122px;left:50%;top:44%">
783
- <span class="disc"></span>
784
- <span class="nm" data-brand-product-inline>Cloud Bongos</span>
785
- <span class="sub">this platform</span>
786
- </a>
787
- <!--apex-only:end-->
788
- <a class="worldOrb" data-generated data-rel="none" href="https://demo.cloudbongos.com" target="_blank" rel="noopener" title="A live demo instance on Cloud Bongos." style="--acc:var(--terracotta);--d:74px;left:22%;top:30%">
789
- <span class="disc"></span>
790
- <span class="nm">Demo</span>
791
- </a>
792
- <a class="worldOrb" data-generated data-rel="none" href="https://emersonian-circles.cloudbongos.com" target="_blank" rel="noopener" title="An independent project built on Cloud Bongos." style="--acc:var(--gold-soft);--d:60px;left:78%;top:66%">
793
- <span class="disc"></span>
794
- <span class="nm">Emersonian Circles</span>
795
- </a>
796
- <a class="worldOrb" data-generated data-rel="builder" href="https://amazonprimea.com" target="_blank" rel="noopener" title="A singular shop, and a broader videogame in a persistent ancient Greek world that collides with modern day commerce &amp; products." style="--acc:var(--sea);--d:56px;left:33%;top:74%">
797
- <span class="badge">you build here</span>
798
- <span class="disc"></span>
799
- <span class="nm">Off the Boats</span>
800
- </a>
801
- </div>
802
- <div class="fieldEmpty">
803
- <p id="emptyMsg">You don’t own or build on anything here yet.</p>
804
- <span class="sub">Turn the filter off to see what everyone else is building, or start your own.</span>
805
- <a class="btn small" href="?view=new" data-nav-to="new">Start a project</a>
806
- </div>
807
- <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>
808
- <div class="hoverCard" id="hoverCard" hidden aria-hidden="true"></div>
809
- </div>
810
- </div>
811
-
812
- <div class="wrap viewWrap" id="sub-table-body" hidden>
813
- <table class="tbl">
814
- <thead>
815
- <tr>
816
- <th class="colName" data-sort="name" aria-sort="ascending"><button type="button" class="thSort">Project</button></th>
817
- <th class="colType">Type</th>
818
- <th class="right" data-sort="builders"><button type="button" class="thSort">Builders</button></th>
819
- <th class="colTags">Runs</th>
820
- <th class="right colStatus">Status</th>
821
- <th class="colGo"></th>
822
- </tr>
823
- </thead>
824
- <tbody id="mapRows">
825
- <!--apex-only:start-->
826
- <tr id="selfRow">
827
- <td class="colName"><span class="pname"><span class="pdot" style="--acc:var(--accent)"></span>
828
- <span><span class="ptitle" data-brand-product-inline>Cloud Bongos</span><span id="selfPill"><span class="pill">you build here</span></span><br>
829
- <span class="ptag">this platform</span></span></span></td>
830
- <td class="colType">·</td>
831
- <td class="right num" id="selfBuilders">13</td>
832
- <td class="colTags" id="selfTags">·</td>
833
- <td class="right colStatus"><span class="chip calm"><span class="cdot"></span>·</span></td>
834
- <td class="colGo"><a class="hallGo" href="https://builders.cloudbongos.com" aria-label="Builders' hall"><svg class="ic" aria-hidden="true"><use href="#i-hall"></use></svg></a><a class="btn small ghost" href="/">Open →</a></td>
835
- </tr>
836
- <!--apex-only:end-->
837
- <tr data-generated>
838
- <td class="colName"><span class="pname"><span class="pdot" style="--acc:var(--terracotta)"></span>
839
- <span><span class="ptitle">Demo</span><br>
840
- <span class="ptag">A live demo instance on Cloud Bongos.</span></span></span></td>
841
- <td class="colType">·</td>
842
- <td class="right num">1</td>
843
- <td class="colTags"><span class="tags"><span>core</span></span></td>
844
- <td class="right colStatus"><span class="chip calm"><span class="cdot"></span>·</span></td>
845
- <td class="colGo"><a class="btn small ghost" href="https://demo.cloudbongos.com" target="_blank" rel="noopener">Open →</a></td>
846
- </tr>
847
- <tr data-generated>
848
- <td class="colName"><span class="pname"><span class="pdot" style="--acc:var(--gold-soft)"></span>
849
- <span><span class="ptitle">Emersonian Circles</span><br>
850
- <span class="ptag">An independent project built on Cloud Bongos.</span></span></span></td>
851
- <td class="colType">·</td>
852
- <td class="right num">1</td>
853
- <td class="colTags"><span class="tags"><span>core</span></span></td>
854
- <td class="right colStatus"><span class="chip calm"><span class="cdot"></span>·</span></td>
855
- <td class="colGo"><a class="btn small ghost" href="https://emersonian-circles.cloudbongos.com" target="_blank" rel="noopener">Open →</a></td>
856
- </tr>
857
- <tr data-generated>
858
- <td class="colName"><span class="pname"><span class="pdot" style="--acc:var(--sea)"></span>
859
- <span><span class="ptitle">Off the Boats</span><span class="pill">you build here</span><br>
860
- <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>
861
- <td class="colType"><span class="typeTag">Game</span></td>
862
- <td class="right num">11</td>
863
- <td class="colTags"><span class="tags"><span>art-pipeline</span><span>character-anim</span><span>demo</span><span>+1</span></span></td>
864
- <td class="right colStatus"><span class="chip calm"><span class="cdot"></span>·</span></td>
865
- <td class="colGo"><a class="btn small ghost" href="https://amazonprimea.com" target="_blank" rel="noopener">Open →</a></td>
866
- </tr>
867
- </tbody>
868
- </table>
869
- <p class="finePrint" style="text-align:center">Sort by Project or Builders.</p>
870
- </div>
871
-
872
- <div class="cardScrim" id="cardScrim" hidden>
873
-
874
- <!-- 1 · card : the platform, everything present -->
875
- <div class="ladderCell" data-card="card"><span class="boardLbl">card</span>
876
- <div class="projCard" id="projCard" role="dialog" aria-modal="true" aria-labelledby="cardName" style="--acc:var(--accent)">
877
- <button type="button" class="cardX" id="cardClose" aria-label="Close"><svg class="ic" aria-hidden="true"><use href="#i-close"></use></svg></button>
878
- <img class="cardArt" src="../../../../modules/public-landing/public/assets/world/og-card.jpg" alt="">
879
- <span class="artScrim" aria-hidden="true"></span>
880
- <span class="cardDot" id="cardDot"></span>
881
- <h3 class="cardName" id="cardName">Cloud Bongos</h3>
882
- <p class="cardTag" id="cardTag">Building Digitally, as simple as Bongos.</p>
883
- <p class="faces">
884
- <img src="https://avatars.githubusercontent.com/u/64553469?v=4" alt="jaxri">
885
- <img src="https://avatars.githubusercontent.com/u/283020391?v=4" alt="lars589">
886
- <img src="https://avatars.githubusercontent.com/u/290184380?v=4" alt="IAMMASTERQUA">
887
- <img src="https://avatars.githubusercontent.com/u/295990394?v=4" alt="scootermack">
888
- <img src="https://avatars.githubusercontent.com/u/35337514?v=4" alt="LarsCode">
889
- <span class="more">+4</span>
890
- </p>
891
- <p class="cardRel" id="cardRel">you build here</p>
892
- <dl class="cardMeta" id="cardMeta">
893
- <dt>builders</dt><dd class="fig">9</dd>
894
- <dt>shipped in 30 days</dt><dd class="fig">30+</dd>
895
- <dt id="cardTypeL" hidden>Type</dt><dd id="cardType" hidden></dd>
896
- <dt>Runs</dt><dd id="cardRuns">cloudbongos.com</dd>
897
- <dt>Owner</dt><dd id="cardOwner"><img src="https://avatars.githubusercontent.com/u/283020391?v=4" alt="">lars589</dd>
898
- <dt>Listed</dt><dd id="cardListed">Jul 14, 2026</dd>
899
- </dl>
900
- <div class="doorbar">
901
- <a class="door door--go" href="/">Open site</a>
902
- <a class="door door--hall" href="https://builders.cloudbongos.com">Builders' hall</a>
903
- </div>
904
- </div></div>
905
-
906
- <!-- 2 · card-member : Off the Boats. art null, a real zero, and NO hall
907
- entry, because its hall is at amazonprimea.com/builders, the same
908
- address as its site. -->
909
- <div class="ladderCell" data-card="card-member" hidden><span class="boardLbl">card-member</span>
910
- <div class="projCard noart" style="--acc:var(--sea)">
911
- <button type="button" class="cardX" aria-label="Close"><svg class="ic" aria-hidden="true"><use href="#i-close"></use></svg></button>
912
- <span class="cardDot"></span>
913
- <h3 class="cardName" id="cardName-member">Off the Boats</h3>
914
- <p class="cardTag">A singular shop, and a broader videogame in a persistent ancient Greek world that collides with modern day commerce &amp; products.</p>
915
- <p class="faces">
916
- <img src="https://avatars.githubusercontent.com/u/283020391?v=4" alt="lars589">
917
- <img src="https://avatars.githubusercontent.com/u/293641659?v=4" alt="kingaonline">
918
- <img src="https://avatars.githubusercontent.com/u/290184380?v=4" alt="IAMMASTERQUA">
919
- <img src="https://avatars.githubusercontent.com/u/295990394?v=4" alt="scootermack">
920
- <img src="https://avatars.githubusercontent.com/u/35337514?v=4" alt="LarsCode">
921
- <span class="more">+8</span>
922
- </p>
923
- <p class="cardRel">you build here</p>
924
- <dl class="cardMeta">
925
- <dt>builders</dt><dd class="fig">13</dd>
926
- <dt>shipped in 30 days</dt><dd class="fig">0</dd>
927
- <dt>Type</dt><dd>Game</dd>
928
- <dt>Runs</dt><dd>amazonprimea.com</dd>
929
- <dt>Owner</dt><dd><img src="https://avatars.githubusercontent.com/u/283020391?v=4" alt="">lars589</dd>
930
- <dt>Listed</dt><dd>Jul 15, 2026</dd>
931
- </dl>
932
- <div class="doorbar">
933
- <a class="door door--go" href="https://amazonprimea.com" target="_blank" rel="noopener">Open site</a>
934
- </div>
935
- </div></div>
936
-
937
- <!-- 3 · card-noart : the platform with art_url null -->
938
- <div class="ladderCell" data-card="card-noart" hidden><span class="boardLbl">card-noart</span>
939
- <div class="projCard noart" style="--acc:var(--accent)">
940
- <button type="button" class="cardX" aria-label="Close"><svg class="ic" aria-hidden="true"><use href="#i-close"></use></svg></button>
941
- <span class="cardDot"></span>
942
- <h3 class="cardName" id="cardName-noart">Cloud Bongos</h3>
943
- <p class="cardTag">Building Digitally, as simple as Bongos.</p>
944
- <p class="faces">
945
- <img src="https://avatars.githubusercontent.com/u/64553469?v=4" alt="jaxri">
946
- <img src="https://avatars.githubusercontent.com/u/283020391?v=4" alt="lars589">
947
- <img src="https://avatars.githubusercontent.com/u/290184380?v=4" alt="IAMMASTERQUA">
948
- <img src="https://avatars.githubusercontent.com/u/295990394?v=4" alt="scootermack">
949
- <img src="https://avatars.githubusercontent.com/u/35337514?v=4" alt="LarsCode">
950
- <span class="more">+4</span>
951
- </p>
952
- <p class="cardRel">you build here</p>
953
- <dl class="cardMeta">
954
- <dt>builders</dt><dd class="fig">9</dd>
955
- <dt>shipped in 30 days</dt><dd class="fig">30+</dd>
956
- <dt>Runs</dt><dd>cloudbongos.com</dd>
957
- <dt>Owner</dt><dd><img src="https://avatars.githubusercontent.com/u/283020391?v=4" alt="">lars589</dd>
958
- <dt>Listed</dt><dd>Jul 14, 2026</dd>
959
- </dl>
960
- <div class="doorbar">
961
- <a class="door door--go" href="/">Open site</a>
962
- <a class="door door--hall" href="https://builders.cloudbongos.com">Builders' hall</a>
963
- </div>
964
- </div></div>
965
-
966
- <!-- 4 · card-nofaces : the faces row is gone, not empty -->
967
- <div class="ladderCell" data-card="card-nofaces" hidden><span class="boardLbl">card-nofaces</span>
968
- <div class="projCard" style="--acc:var(--accent)">
969
- <button type="button" class="cardX" aria-label="Close"><svg class="ic" aria-hidden="true"><use href="#i-close"></use></svg></button>
970
- <img class="cardArt" src="../../../../modules/public-landing/public/assets/world/og-card.jpg" alt="">
971
- <span class="artScrim" aria-hidden="true"></span>
972
- <span class="cardDot"></span>
973
- <h3 class="cardName" id="cardName-nofaces">Cloud Bongos</h3>
974
- <p class="cardTag">Building Digitally, as simple as Bongos.</p>
975
- <p class="cardRel">you build here</p>
976
- <dl class="cardMeta">
977
- <dt>builders</dt><dd class="fig">9</dd>
978
- <dt>shipped in 30 days</dt><dd class="fig">30+</dd>
979
- <dt>Runs</dt><dd>cloudbongos.com</dd>
980
- <dt>Owner</dt><dd><img src="https://avatars.githubusercontent.com/u/283020391?v=4" alt="">lars589</dd>
981
- <dt>Listed</dt><dd>Jul 14, 2026</dd>
982
- </dl>
983
- <div class="doorbar">
984
- <a class="door door--go" href="/">Open site</a>
985
- <a class="door door--hall" href="https://builders.cloudbongos.com">Builders' hall</a>
986
- </div>
987
- </div></div>
988
-
989
- <!-- 5 · card-onefig : shipped in 30 days is null, builders stands alone -->
990
- <div class="ladderCell" data-card="card-onefig" hidden><span class="boardLbl">card-onefig</span>
991
- <div class="projCard" style="--acc:var(--accent)">
992
- <button type="button" class="cardX" aria-label="Close"><svg class="ic" aria-hidden="true"><use href="#i-close"></use></svg></button>
993
- <img class="cardArt" src="../../../../modules/public-landing/public/assets/world/og-card.jpg" alt="">
994
- <span class="artScrim" aria-hidden="true"></span>
995
- <span class="cardDot"></span>
996
- <h3 class="cardName" id="cardName-onefig">Cloud Bongos</h3>
997
- <p class="cardTag">Building Digitally, as simple as Bongos.</p>
998
- <p class="faces">
999
- <img src="https://avatars.githubusercontent.com/u/64553469?v=4" alt="jaxri">
1000
- <img src="https://avatars.githubusercontent.com/u/283020391?v=4" alt="lars589">
1001
- <img src="https://avatars.githubusercontent.com/u/290184380?v=4" alt="IAMMASTERQUA">
1002
- <img src="https://avatars.githubusercontent.com/u/295990394?v=4" alt="scootermack">
1003
- <img src="https://avatars.githubusercontent.com/u/35337514?v=4" alt="LarsCode">
1004
- <span class="more">+4</span>
1005
- </p>
1006
- <p class="cardRel">you build here</p>
1007
- <dl class="cardMeta">
1008
- <dt>builders</dt><dd class="fig">9</dd>
1009
- <dt>Runs</dt><dd>cloudbongos.com</dd>
1010
- <dt>Owner</dt><dd><img src="https://avatars.githubusercontent.com/u/283020391?v=4" alt="">lars589</dd>
1011
- <dt>Listed</dt><dd>Jul 14, 2026</dd>
1012
- </dl>
1013
- <div class="doorbar">
1014
- <a class="door door--go" href="/">Open site</a>
1015
- <a class="door door--hall" href="https://builders.cloudbongos.com">Builders' hall</a>
1016
- </div>
1017
- </div></div>
1018
-
1019
- <!-- 6 · card-nofig : both figures null, the two figure rows leave -->
1020
- <div class="ladderCell" data-card="card-nofig" hidden><span class="boardLbl">card-nofig</span>
1021
- <div class="projCard" style="--acc:var(--accent)">
1022
- <button type="button" class="cardX" aria-label="Close"><svg class="ic" aria-hidden="true"><use href="#i-close"></use></svg></button>
1023
- <img class="cardArt" src="../../../../modules/public-landing/public/assets/world/og-card.jpg" alt="">
1024
- <span class="artScrim" aria-hidden="true"></span>
1025
- <span class="cardDot"></span>
1026
- <h3 class="cardName" id="cardName-nofig">Cloud Bongos</h3>
1027
- <p class="cardTag">Building Digitally, as simple as Bongos.</p>
1028
- <p class="faces">
1029
- <img src="https://avatars.githubusercontent.com/u/64553469?v=4" alt="jaxri">
1030
- <img src="https://avatars.githubusercontent.com/u/283020391?v=4" alt="lars589">
1031
- <img src="https://avatars.githubusercontent.com/u/290184380?v=4" alt="IAMMASTERQUA">
1032
- <img src="https://avatars.githubusercontent.com/u/295990394?v=4" alt="scootermack">
1033
- <img src="https://avatars.githubusercontent.com/u/35337514?v=4" alt="LarsCode">
1034
- <span class="more">+4</span>
1035
- </p>
1036
- <p class="cardRel">you build here</p>
1037
- <dl class="cardMeta">
1038
- <dt>Runs</dt><dd>cloudbongos.com</dd>
1039
- <dt>Owner</dt><dd><img src="https://avatars.githubusercontent.com/u/283020391?v=4" alt="">lars589</dd>
1040
- <dt>Listed</dt><dd>Jul 14, 2026</dd>
1041
- </dl>
1042
- <div class="doorbar">
1043
- <a class="door door--go" href="/">Open site</a>
1044
- <a class="door door--hall" href="https://builders.cloudbongos.com">Builders' hall</a>
1045
- </div>
1046
- </div></div>
1047
-
1048
- <!-- 7 · card-floor : today's card, in the world's skin -->
1049
- <div class="ladderCell" data-card="card-floor" hidden><span class="boardLbl">card-floor</span>
1050
- <div class="projCard noart" style="--acc:var(--accent)">
1051
- <button type="button" class="cardX" aria-label="Close"><svg class="ic" aria-hidden="true"><use href="#i-close"></use></svg></button>
1052
- <span class="cardDot"></span>
1053
- <h3 class="cardName" id="cardName-floor">Cloud Bongos</h3>
1054
- <p class="cardTag">Building Digitally, as simple as Bongos.</p>
1055
- <p class="cardRel">you build here</p>
1056
- <div class="doorbar">
1057
- <a class="door door--go" href="/">Open site</a>
1058
- </div>
1059
- </div></div>
1060
-
1061
- </div>
1062
- </section>
1063
-
1064
- <section id="view-mine">
1065
- <div class="wrap viewWrap">
1066
- <div class="hero" style="padding-left:0;padding-right:0">
1067
- <h2>Your projects</h2>
1068
- <p class="lede">Every project you own: what it is, whether it is answering, and the controls that
1069
- matter. Each card says what the platform <b>last verified</b>, and when.</p>
1070
- </div>
1071
-
1072
- <div class="card">
1073
- <section id="gate" hidden>
1074
- <p class="lede">Every project you own, in one place: its live status, its address, and the controls that matter. Sign in with GitHub to see yours.</p>
1075
- <a class="btn" id="signin" href="/api/bongos/auth/web/start?return=/projects%3Fview%3Dmine">
1076
- <svg class="gh" viewBox="0 0 16 16" aria-hidden="true"><path 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>
1077
- Sign in with GitHub
1078
- </a>
1079
- <div class="alert" id="gateAlert" role="alert"></div>
1080
- </section>
1081
-
1082
- <section id="mine">
1083
- <div class="mineBar" id="mineBar">
1084
- <div class="search">
1085
- <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>
1086
- <input type="text" id="mineQ" placeholder="Search your projects by name, repo or address…" aria-label="Search your projects">
1087
- <span class="count" id="mineCount"></span>
1088
- </div>
1089
- <div class="filters" role="group" aria-label="Filter by state">
1090
- <button type="button" data-f="all" aria-controls="projectsList" aria-pressed="true">All <span class="n">0</span></button>
1091
- <button type="button" data-f="live" aria-controls="projectsList" aria-pressed="false">Live <span class="n">0</span></button>
1092
- <button type="button" data-f="attention" aria-controls="projectsList" aria-pressed="false">Needs you <span class="n">0</span></button>
1093
- <button type="button" data-f="working" aria-controls="projectsList" aria-pressed="false">Working <span class="n">0</span></button>
1094
- <button type="button" data-f="gone" aria-controls="projectsList" aria-pressed="false">Torn down <span class="n">0</span></button>
1095
- </div>
1096
- </div>
1097
-
1098
- <section class="empty" id="empty">
1099
- <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>
1100
- <a class="btn" href="?view=new" data-nav-to="new">Create your first project</a>
1101
- </section>
1102
- <ul class="projects" id="projectsList"></ul>
1103
- <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>
1104
- </section>
1105
- </div>
1106
- </div>
1107
- </section>
1108
-
1109
- <section id="view-new">
1110
- <div class="wrap viewWrap">
1111
- <div class="card">
1112
- <ol class="steps" aria-label="Creation steps">
1113
- <li class="now" data-step="1" aria-current="step"><span class="snum">1</span><span class="slbl">Name</span></li>
1114
- <li data-step="2"><span class="snum">2</span><span class="slbl">Type</span></li>
1115
- <li data-step="3"><span class="snum">3</span><span class="slbl">Home</span></li>
1116
- <li data-step="4"><span class="snum">4</span><span class="slbl">Address</span></li>
1117
- <li data-step="5"><span class="snum">5</span><span class="slbl">Create</span></li>
1118
- </ol>
1119
-
1120
- <div class="createSplit">
1121
- <div>
1122
- <section class="panel" id="panel-gate" aria-labelledby="gate-h">
1123
- <h2 id="gate-h">Create a project</h2>
1124
- <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>
1125
- <a class="btn big" id="wizSignin" href="/api/bongos/auth/web/start?return=/projects%3Fview%3Dnew&amp;repos=1">
1126
- <svg class="gh" viewBox="0 0 16 16" aria-hidden="true"><path 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>
1127
- Sign in with GitHub
1128
- </a>
1129
- <p class="finePrint" id="wizScopeNote">Signing in asks GitHub for repository access. GitHub words this as access to <em>all</em> your repositories, 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>
1130
- </section>
1131
-
1132
- <section class="panel" id="panel-name" aria-labelledby="name-h">
1133
- <h2 id="name-h">Start a project</h2>
1134
- <p class="lede">Your own project: its own repository, its own home on the web, and a hall of AI builders
1135
- who do the building. You set the direction; agents lay down the code.</p>
1136
- <form id="newForm" data-next="2">
1137
- <label class="wizField"><span>Project name</span>
1138
- <input type="text" id="newName" placeholder="What should it be called?" autocomplete="off" maxlength="80" aria-label="Project name">
1139
- <div class="hint" id="h-name">&nbsp;</div>
1140
- </label>
1141
- <div class="nav">
1142
- <span></span>
1143
- <button type="submit" class="btn">Continue →</button>
1144
- </div>
1145
- </form>
1146
- <p class="finePrint">Free while we find our feet. Your project’s repo and server are yours;
1147
- <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>
1148
- and capture-resistant by design.</p>
1149
- </section>
1150
- </div>
1151
- </div>
1152
- </div>
1153
- </div>
1154
- </section>
1155
-
1156
- <!-- ══ BOARD · THE BAR, every state of the strip stacked ══════════════════ -->
1157
- <section id="board-bar" class="board">
1158
- <div class="boardRow"><span class="boardLbl">out-map</span>
1159
- <div class="boardFrame">
1160
- <div class="gstrip">
1161
- <a class="mark" href="/" aria-label="Cloud Bongos, home"><svg class="ic" aria-hidden="true"><use href="#i-bongos"></use></svg><span class="mark-word">Cloud Bongos</span></a>
1162
- <div class="find"><span class="findBox"><svg class="ic" aria-hidden="true"><use href="#i-search"></use></svg><input type="text" placeholder="Find a project" aria-label="Search projects"><span class="count">4 projects</span></span></div>
1163
- <span class="sgmWrap"><button type="button" class="sgm" aria-expanded="false" aria-controls="bm1">Projects<svg class="ic cr" aria-hidden="true"><use href="#i-caret"></use></svg></button></span>
1164
- <button type="button" class="sgm sgm-mode" aria-label="Toggle light or dark"><svg class="ic moon" aria-hidden="true"><use href="#i-moon"></use></svg><svg class="ic sun" aria-hidden="true"><use href="#i-sun"></use></svg></button>
1165
- <span class="idSlot"><a class="signin" href="/api/bongos/auth/web/start?return=/projects">Sign in</a></span>
1166
- </div>
1167
- <div class="under"><div class="toolbar"><div class="seg" role="group" aria-label="Map display"><button type="button" aria-pressed="true">Sky</button><button type="button" aria-pressed="false">Table</button></div></div></div>
1168
- </div>
1169
- </div>
1170
-
1171
- <div class="boardRow"><span class="boardLbl">in-map</span>
1172
- <div class="boardFrame">
1173
- <div class="gstrip">
1174
- <a class="mark" href="/" aria-label="Cloud Bongos, home"><svg class="ic" aria-hidden="true"><use href="#i-bongos"></use></svg><span class="mark-word">Cloud Bongos</span></a>
1175
- <div class="find"><span class="findBox"><svg class="ic" aria-hidden="true"><use href="#i-search"></use></svg><input type="text" placeholder="Find a project" aria-label="Search projects"><span class="count">4 projects</span></span></div>
1176
- <span class="sgmWrap"><button type="button" class="sgm" aria-expanded="false" aria-controls="bm2">Projects<svg class="ic cr" aria-hidden="true"><use href="#i-caret"></use></svg></button></span>
1177
- <button type="button" class="sgm sgm-mode" aria-label="Toggle light or dark"><svg class="ic moon" aria-hidden="true"><use href="#i-moon"></use></svg><svg class="ic sun" aria-hidden="true"><use href="#i-sun"></use></svg></button>
1178
- <span class="sgmWrap"><button type="button" class="sgm sgm-id" aria-expanded="false" aria-controls="bp2" aria-label="Account, jaxri"><img src="https://avatars.githubusercontent.com/u/64553469?v=4" alt=""><span class="who-name">jaxri</span><svg class="ic cr" aria-hidden="true"><use href="#i-caret"></use></svg></button></span>
1179
- </div>
1180
- <div class="under"><div class="toolbar"><div class="seg" role="group" aria-label="Map display"><button type="button" aria-pressed="true">Sky</button><button type="button" aria-pressed="false">Table</button></div><label class="switch" title="Show only projects you own or build on"><input type="checkbox"><span class="track"></span> Only mine</label></div></div>
1181
- </div>
1182
- </div>
1183
-
1184
- <div class="boardRow"><span class="boardLbl">in-map-projects</span>
1185
- <div class="boardFrame">
1186
- <div class="gstrip">
1187
- <a class="mark" href="/" aria-label="Cloud Bongos, home"><svg class="ic" aria-hidden="true"><use href="#i-bongos"></use></svg><span class="mark-word">Cloud Bongos</span></a>
1188
- <div class="find"><span class="findBox"><svg class="ic" aria-hidden="true"><use href="#i-search"></use></svg><input type="text" placeholder="Find a project" aria-label="Search projects"><span class="count">4 projects</span></span></div>
1189
- <span class="sgmWrap"><button type="button" class="sgm" aria-expanded="true" aria-controls="bm3">Projects<svg class="ic cr" aria-hidden="true"><use href="#i-caret"></use></svg></button>
1190
- <ul class="menu menu--projects" id="bm3">
1191
- <li><a href="?view=map" aria-current="page">Map</a></li>
1192
- <li><a href="?view=mine">Your projects</a></li>
1193
- <li><a href="?view=new">New project</a></li>
1194
- </ul>
1195
- </span>
1196
- <button type="button" class="sgm sgm-mode" aria-label="Toggle light or dark"><svg class="ic moon" aria-hidden="true"><use href="#i-moon"></use></svg><svg class="ic sun" aria-hidden="true"><use href="#i-sun"></use></svg></button>
1197
- <span class="sgmWrap"><button type="button" class="sgm sgm-id" aria-expanded="false" aria-controls="bp3" aria-label="Account, jaxri"><img src="https://avatars.githubusercontent.com/u/64553469?v=4" alt=""><span class="who-name">jaxri</span><svg class="ic cr" aria-hidden="true"><use href="#i-caret"></use></svg></button></span>
1198
- </div>
1199
- <div class="under"><div class="toolbar"><div class="seg" role="group" aria-label="Map display"><button type="button" aria-pressed="true">Sky</button><button type="button" aria-pressed="false">Table</button></div><label class="switch" title="Show only projects you own or build on"><input type="checkbox"><span class="track"></span> Only mine</label></div></div>
1200
- </div>
1201
- </div>
1202
-
1203
- <div class="boardRow"><span class="boardLbl">in-map-profile</span>
1204
- <div class="boardFrame">
1205
- <div class="gstrip">
1206
- <a class="mark" href="/" aria-label="Cloud Bongos, home"><svg class="ic" aria-hidden="true"><use href="#i-bongos"></use></svg><span class="mark-word">Cloud Bongos</span></a>
1207
- <div class="find"><span class="findBox"><svg class="ic" aria-hidden="true"><use href="#i-search"></use></svg><input type="text" placeholder="Find a project" aria-label="Search projects"><span class="count">4 projects</span></span></div>
1208
- <span class="sgmWrap"><button type="button" class="sgm" aria-expanded="false" aria-controls="bm4">Projects<svg class="ic cr" aria-hidden="true"><use href="#i-caret"></use></svg></button></span>
1209
- <button type="button" class="sgm sgm-mode" aria-label="Toggle light or dark"><svg class="ic moon" aria-hidden="true"><use href="#i-moon"></use></svg><svg class="ic sun" aria-hidden="true"><use href="#i-sun"></use></svg></button>
1210
- <span class="sgmWrap"><button type="button" class="sgm sgm-id" aria-expanded="true" aria-controls="bp4" aria-label="Account, jaxri"><img src="https://avatars.githubusercontent.com/u/64553469?v=4" alt=""><span class="who-name">jaxri</span><svg class="ic cr" aria-hidden="true"><use href="#i-caret"></use></svg></button>
1211
- <ul class="menu menu--profile" id="bp4">
1212
- <li class="who-row"><img src="https://avatars.githubusercontent.com/u/64553469?v=4" alt=""><span>jaxri</span></li>
1213
- <li><a href="https://builders.cloudbongos.com/my-projects">My projects</a></li>
1214
- <li class="slot"></li>
1215
- <li><a href="/api/bongos/auth/logout">Sign out</a></li>
1216
- </ul>
1217
- </span>
1218
- </div>
1219
- <div class="under"><div class="toolbar"><div class="seg" role="group" aria-label="Map display"><button type="button" aria-pressed="true">Sky</button><button type="button" aria-pressed="false">Table</button></div><label class="switch" title="Show only projects you own or build on"><input type="checkbox"><span class="track"></span> Only mine</label></div></div>
1220
- </div>
1221
- </div>
1222
-
1223
- <div class="boardRow"><span class="boardLbl">in-map-focus</span>
1224
- <div class="boardFrame">
1225
- <div class="gstrip">
1226
- <a class="mark" href="/" aria-label="Cloud Bongos, home"><svg class="ic" aria-hidden="true"><use href="#i-bongos"></use></svg><span class="mark-word">Cloud Bongos</span></a>
1227
- <div class="find"><span class="findBox"><svg class="ic" aria-hidden="true"><use href="#i-search"></use></svg><input type="text" placeholder="Find a project" aria-label="Search projects"><span class="count">4 projects</span></span></div>
1228
- <span class="sgmWrap"><button type="button" class="sgm" aria-expanded="true" aria-controls="bm5">Projects<svg class="ic cr" aria-hidden="true"><use href="#i-caret"></use></svg></button>
1229
- <ul class="menu menu--projects" id="bm5">
1230
- <li><a href="?view=map" aria-current="page">Map</a></li>
1231
- <li><a href="?view=mine" class="is-focus">Your projects</a></li>
1232
- <li><a href="?view=new">New project</a></li>
1233
- </ul>
1234
- </span>
1235
- <button type="button" class="sgm sgm-mode" aria-label="Toggle light or dark"><svg class="ic moon" aria-hidden="true"><use href="#i-moon"></use></svg><svg class="ic sun" aria-hidden="true"><use href="#i-sun"></use></svg></button>
1236
- <span class="sgmWrap"><button type="button" class="sgm sgm-id is-focus" aria-expanded="false" aria-controls="bp5" aria-label="Account, jaxri"><img src="https://avatars.githubusercontent.com/u/64553469?v=4" alt=""><span class="who-name">jaxri</span><svg class="ic cr" aria-hidden="true"><use href="#i-caret"></use></svg></button></span>
1237
- </div>
1238
- <div class="under"><div class="toolbar"><div class="seg" role="group" aria-label="Map display"><button type="button" aria-pressed="true">Sky</button><button type="button" aria-pressed="false">Table</button></div><label class="switch" title="Show only projects you own or build on"><input type="checkbox"><span class="track"></span> Only mine</label></div></div>
1239
- </div>
1240
- </div>
1241
-
1242
- <div class="boardRow"><span class="boardLbl">in-map-search</span>
1243
- <div class="boardFrame">
1244
- <div class="gstrip">
1245
- <a class="mark" href="/" aria-label="Cloud Bongos, home"><svg class="ic" aria-hidden="true"><use href="#i-bongos"></use></svg><span class="mark-word">Cloud Bongos</span></a>
1246
- <div class="find is-open"><span class="findBox"><svg class="ic" aria-hidden="true"><use href="#i-search"></use></svg><input type="text" value="emer" placeholder="Find a project" aria-label="Search projects"><span class="count">1 of 4</span></span></div>
1247
- <span class="sgmWrap"><button type="button" class="sgm" aria-expanded="false" aria-controls="bm6">Projects<svg class="ic cr" aria-hidden="true"><use href="#i-caret"></use></svg></button></span>
1248
- <button type="button" class="sgm sgm-mode" aria-label="Toggle light or dark"><svg class="ic moon" aria-hidden="true"><use href="#i-moon"></use></svg><svg class="ic sun" aria-hidden="true"><use href="#i-sun"></use></svg></button>
1249
- <span class="sgmWrap"><button type="button" class="sgm sgm-id" aria-expanded="false" aria-controls="bp6" aria-label="Account, jaxri"><img src="https://avatars.githubusercontent.com/u/64553469?v=4" alt=""><span class="who-name">jaxri</span><svg class="ic cr" aria-hidden="true"><use href="#i-caret"></use></svg></button></span>
1250
- </div>
1251
- <div class="under"><div class="toolbar"><div class="seg" role="group" aria-label="Map display"><button type="button" aria-pressed="true">Sky</button><button type="button" aria-pressed="false">Table</button></div><label class="switch" title="Show only projects you own or build on"><input type="checkbox"><span class="track"></span> Only mine</label></div></div>
1252
- </div>
1253
- </div>
1254
-
1255
- <div class="boardRow"><span class="boardLbl">in-mine</span>
1256
- <div class="boardFrame">
1257
- <div class="gstrip">
1258
- <a class="mark" href="/" aria-label="Cloud Bongos, home"><svg class="ic" aria-hidden="true"><use href="#i-bongos"></use></svg><span class="mark-word">Cloud Bongos</span></a>
1259
- <span class="sgmWrap" style="margin-left:auto"><button type="button" class="sgm" aria-expanded="false" aria-controls="bm7">Projects<svg class="ic cr" aria-hidden="true"><use href="#i-caret"></use></svg></button></span>
1260
- <button type="button" class="sgm sgm-mode" aria-label="Toggle light or dark"><svg class="ic moon" aria-hidden="true"><use href="#i-moon"></use></svg><svg class="ic sun" aria-hidden="true"><use href="#i-sun"></use></svg></button>
1261
- <span class="sgmWrap"><button type="button" class="sgm sgm-id" aria-expanded="false" aria-controls="bp7" aria-label="Account, jaxri"><img src="https://avatars.githubusercontent.com/u/64553469?v=4" alt=""><span class="who-name">jaxri</span><svg class="ic cr" aria-hidden="true"><use href="#i-caret"></use></svg></button></span>
1262
- </div>
1263
- <div class="under"><div class="wrap"><p class="lbl" style="padding:22px 0 0">the strip drops the search on a view it cannot filter</p></div></div>
1264
- </div>
1265
- </div>
1266
-
1267
- <div class="boardRow"><span class="boardLbl">in-new</span>
1268
- <div class="boardFrame">
1269
- <div class="gstrip">
1270
- <a class="mark" href="/" aria-label="Cloud Bongos, home"><svg class="ic" aria-hidden="true"><use href="#i-bongos"></use></svg><span class="mark-word">Cloud Bongos</span></a>
1271
- <span class="sgmWrap" style="margin-left:auto"><button type="button" class="sgm" aria-expanded="false" aria-controls="bm8">Projects<svg class="ic cr" aria-hidden="true"><use href="#i-caret"></use></svg></button></span>
1272
- <button type="button" class="sgm sgm-mode" aria-label="Toggle light or dark"><svg class="ic moon" aria-hidden="true"><use href="#i-moon"></use></svg><svg class="ic sun" aria-hidden="true"><use href="#i-sun"></use></svg></button>
1273
- <span class="sgmWrap"><button type="button" class="sgm sgm-id" aria-expanded="false" aria-controls="bp8" aria-label="Account, jaxri"><img src="https://avatars.githubusercontent.com/u/64553469?v=4" alt=""><span class="who-name">jaxri</span><svg class="ic cr" aria-hidden="true"><use href="#i-caret"></use></svg></button></span>
1274
- </div>
1275
- <div class="under"><div class="wrap"><p class="lbl" style="padding:22px 0 0">the create rail sits under the same plate</p></div></div>
1276
- </div>
1277
- </div>
1278
- </section>
1279
-
1280
- <!-- ══ BOARD · THE MENU AND THE SEARCH, component by component ═══════════ -->
1281
- <section id="board-menu" class="board">
1282
- <div class="boardGrid">
1283
- <div class="cell"><span class="boardLbl">trigger, closed</span>
1284
- <div class="boardFrame"><div class="gstrip" style="justify-content:flex-end">
1285
- <span class="sgmWrap"><button type="button" class="sgm" aria-expanded="false" aria-controls="cm1">Projects<svg class="ic cr" aria-hidden="true"><use href="#i-caret"></use></svg></button></span>
1286
- </div><div class="under" style="height:34px"></div></div>
1287
- </div>
1288
- <div class="cell"><span class="boardLbl">panel, open</span>
1289
- <div class="boardFrame"><div class="gstrip" style="justify-content:flex-end">
1290
- <span class="sgmWrap"><button type="button" class="sgm" aria-expanded="true" aria-controls="cm2">Projects<svg class="ic cr" aria-hidden="true"><use href="#i-caret"></use></svg></button>
1291
- <ul class="menu menu--profile" id="cm2">
1292
- <li><a href="?view=map" aria-current="page">Map</a></li>
1293
- <li><a href="?view=mine">Your projects</a></li>
1294
- <li><a href="?view=new">New project</a></li>
1295
- </ul>
1296
- </span>
1297
- </div><div class="under" style="height:172px"></div></div>
1298
- </div>
1299
- <div class="cell"><span class="boardLbl">item, keyboard focus</span>
1300
- <div class="boardFrame"><div class="gstrip" style="justify-content:flex-end">
1301
- <span class="sgmWrap"><button type="button" class="sgm" aria-expanded="true" aria-controls="cm3">Projects<svg class="ic cr" aria-hidden="true"><use href="#i-caret"></use></svg></button>
1302
- <ul class="menu menu--profile" id="cm3">
1303
- <li><a href="?view=map" aria-current="page">Map</a></li>
1304
- <li><a href="?view=mine" class="is-focus">Your projects</a></li>
1305
- <li><a href="?view=new">New project</a></li>
1306
- </ul>
1307
- </span>
1308
- </div><div class="under" style="height:172px"></div></div>
1309
- </div>
1310
- <div class="cell"><span class="boardLbl">item, hover</span>
1311
- <div class="boardFrame"><div class="gstrip" style="justify-content:flex-end">
1312
- <span class="sgmWrap"><button type="button" class="sgm" aria-expanded="true" aria-controls="cm4">Projects<svg class="ic cr" aria-hidden="true"><use href="#i-caret"></use></svg></button>
1313
- <ul class="menu menu--profile" id="cm4">
1314
- <li><a href="?view=map" aria-current="page">Map</a></li>
1315
- <li><a href="?view=mine">Your projects</a></li>
1316
- <li><a href="?view=new" class="is-hover">New project</a></li>
1317
- </ul>
1318
- </span>
1319
- </div><div class="under" style="height:172px"></div></div>
1320
- </div>
1321
- <div class="cell"><span class="boardLbl">profile panel, open</span>
1322
- <div class="boardFrame"><div class="gstrip" style="justify-content:flex-end">
1323
- <span class="sgmWrap"><button type="button" class="sgm sgm-id" aria-expanded="true" aria-controls="cm5" aria-label="Account, jaxri"><img src="https://avatars.githubusercontent.com/u/64553469?v=4" alt=""><span class="who-name">jaxri</span><svg class="ic cr" aria-hidden="true"><use href="#i-caret"></use></svg></button>
1324
- <ul class="menu menu--profile" id="cm5">
1325
- <li class="who-row"><img src="https://avatars.githubusercontent.com/u/64553469?v=4" alt=""><span>jaxri</span></li>
1326
- <li><a href="https://builders.cloudbongos.com/my-projects">My projects</a></li>
1327
- <li class="slot"></li>
1328
- <li><a href="/api/bongos/auth/logout">Sign out</a></li>
1329
- </ul>
1330
- </span>
1331
- </div><div class="under" style="height:186px"></div></div>
1332
- </div>
1333
- <div class="cell"><span class="boardLbl">search, at rest</span>
1334
- <div class="boardFrame"><div class="gstrip">
1335
- <div class="find"><span class="findBox"><svg class="ic" aria-hidden="true"><use href="#i-search"></use></svg><input type="text" placeholder="Find a project" aria-label="Search projects"><span class="count">4 projects</span></span></div>
1336
- </div><div class="under" style="height:34px"></div></div>
1337
- </div>
1338
- <div class="cell"><span class="boardLbl">search, focused</span>
1339
- <div class="boardFrame"><div class="gstrip">
1340
- <div class="find is-open"><span class="findBox is-focus"><svg class="ic" aria-hidden="true"><use href="#i-search"></use></svg><input type="text" placeholder="Find a project" aria-label="Search projects"><span class="count">4 projects</span></span></div>
1341
- </div><div class="under" style="height:34px"></div></div>
1342
- </div>
1343
- <div class="cell"><span class="boardLbl">search, carrying a query</span>
1344
- <div class="boardFrame"><div class="gstrip">
1345
- <div class="find is-open"><span class="findBox"><svg class="ic" aria-hidden="true"><use href="#i-search"></use></svg><input type="text" value="emer" placeholder="Find a project" aria-label="Search projects"><span class="count">1 of 4</span></span></div>
1346
- </div><div class="under" style="height:34px"></div></div>
1347
- </div>
1348
- </div>
1349
- </section>
1350
-
1351
- </main>
1352
-
1353
- <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>
1354
-
1355
- <script>
1356
- /* The state contract. One read of ?state= on load; everything else is a class
1357
- or an attribute. No motion is authored here (the world forbids JS motion),
1358
- and nothing is built from strings. */
1359
- (function () {
1360
- 'use strict';
1361
- var STATES = ['out-map', 'in-map', 'in-map-projects', 'in-map-profile', 'in-map-focus',
1362
- 'in-map-search', 'in-mine', 'in-new', 'out-new', 'in-table', 'card', 'card-member',
1363
- 'card-noart', 'card-nofaces', 'card-onefig', 'card-nofig', 'card-floor',
1364
- 'board-bar', 'board-card', 'board-menu'];
1365
- var $ = function (id) { return document.getElementById(id); };
1366
- var q = null;
1367
- try { q = new URLSearchParams(location.search || location.hash.slice(1) || (window.__Q || '')).get('state'); } catch (e) { q = null; }
1368
- var state = STATES.indexOf(q) > -1 ? q : 'in-map';
1369
- var body = document.body;
1370
- var view = 'map';
1371
- if (state === 'in-mine') view = 'mine';
1372
- else if (state === 'in-new' || state === 'out-new') view = 'new';
1373
- else if (state === 'in-table') view = 'table';
1374
- else if (state.indexOf('board-') === 0) view = 'board';
1375
- body.setAttribute('data-state', state);
1376
- body.setAttribute('data-view', view);
1377
- body.setAttribute('data-auth', state.indexOf('out-') === 0 ? 'out' : 'in');
1378
-
1379
- /* the table ships hidden, as it does today; the state contract un-hides it */
1380
- if (view === 'table') $('sub-table-body').hidden = false;
1381
-
1382
- /* signed out, Your projects is a door to sign-in, the way today's nav row is */
1383
- if (state.indexOf('out-') === 0) {
1384
- $('menuMine').setAttribute('href', '/api/bongos/auth/web/start?return=/projects%3Fview%3Dmine');
1385
- }
1386
-
1387
- var projTrigger = $('projTrigger'), projMenu = $('projMenu');
1388
- var profTrigger = $('profTrigger'), profMenu = $('profMenu');
1389
-
1390
- function open(trigger, panel, on) {
1391
- trigger.setAttribute('aria-expanded', on ? 'true' : 'false');
1392
- panel.hidden = !on;
1393
- }
1394
- function closeAll() { open(projTrigger, projMenu, false); open(profTrigger, profMenu, false); }
1395
-
1396
- /* the mark is the accent, and the accent lights the LIVE thing: it follows
1397
- the view the page is on. Table is a sub-mode of the Map destination. */
1398
- var CURRENT = { map: 'map', table: 'map', mine: 'mine', 'new': 'new' };
1399
- var navLinks = projMenu.querySelectorAll('a');
1400
- for (var k = 0; k < navLinks.length; k++) {
1401
- if (navLinks[k].getAttribute('data-nav') === CURRENT[view]) navLinks[k].setAttribute('aria-current', 'page');
1402
- else navLinks[k].removeAttribute('aria-current');
1403
- }
1404
-
1405
- if (state === 'in-map-projects' || state === 'in-map-focus') open(projTrigger, projMenu, true);
1406
- if (state === 'in-map-profile') open(profTrigger, profMenu, true);
1407
- if (state === 'in-map-focus') {
1408
- projMenu.querySelectorAll('a')[1].classList.add('is-focus');
1409
- profTrigger.classList.add('is-focus');
1410
- }
1411
- if (state === 'in-map-search') {
1412
- var f = $('mapQ');
1413
- f.value = 'emer';
1414
- $('mapCount').textContent = '1 of 4';
1415
- $('find').classList.add('is-open');
1416
- f.focus();
1417
- }
1418
-
1419
- /* the card ladder: seven real cards, one shown per card state, all seven on
1420
- the board. role="dialog" travels to whichever one the state opens. */
1421
- var cells = document.querySelectorAll('.ladderCell');
1422
- if (state.indexOf('card') === 0 || state === 'board-card') {
1423
- $('cardScrim').hidden = false;
1424
- var i, cell, card;
1425
- for (i = 0; i < cells.length; i++) {
1426
- cell = cells[i];
1427
- card = cell.querySelector('.projCard');
1428
- var mine = state === 'board-card' || cell.getAttribute('data-card') === state;
1429
- cell.hidden = !mine;
1430
- if (mine && state !== 'board-card') {
1431
- card.setAttribute('role', 'dialog');
1432
- card.setAttribute('aria-modal', 'true');
1433
- card.setAttribute('aria-labelledby', card.querySelector('.cardName').id);
1434
- } else {
1435
- card.removeAttribute('role');
1436
- card.removeAttribute('aria-modal');
1437
- card.removeAttribute('aria-labelledby');
1438
- }
1439
- }
1440
- }
1441
-
1442
- /* the disclosure pattern, live: click toggles, Escape closes and hands focus
1443
- back, a click outside closes, the arrows walk the items. */
1444
- function wire(trigger, panel) {
1445
- trigger.addEventListener('click', function () {
1446
- var on = trigger.getAttribute('aria-expanded') === 'true';
1447
- closeAll();
1448
- if (!on) { open(trigger, panel, true); }
1449
- });
1450
- panel.addEventListener('keydown', function (ev) {
1451
- if (ev.key !== 'ArrowDown' && ev.key !== 'ArrowUp') return;
1452
- var items = [].slice.call(panel.querySelectorAll('a'));
1453
- var at = items.indexOf(document.activeElement);
1454
- var next = ev.key === 'ArrowDown' ? at + 1 : at - 1;
1455
- if (next < 0) next = items.length - 1;
1456
- if (next >= items.length) next = 0;
1457
- ev.preventDefault();
1458
- items[next].focus();
1459
- });
1460
- }
1461
- wire(projTrigger, projMenu);
1462
- wire(profTrigger, profMenu);
1463
-
1464
- document.addEventListener('keydown', function (ev) {
1465
- if (ev.key !== 'Escape') return;
1466
- if (projTrigger.getAttribute('aria-expanded') === 'true') { closeAll(); projTrigger.focus(); return; }
1467
- if (profTrigger.getAttribute('aria-expanded') === 'true') { closeAll(); profTrigger.focus(); }
1468
- });
1469
- document.addEventListener('click', function (ev) {
1470
- if (ev.target.closest && ev.target.closest('.sgmWrap')) return;
1471
- closeAll();
1472
- });
1473
-
1474
- /* the whole pill is the field's target, not the 24px input inside it; under
1475
- 560 the same press opens the full-width field on the strip's bottom edge */
1476
- var findWrap = $('find'), findPill = findWrap.querySelector('.findBox'), mapQ = $('mapQ');
1477
- findPill.addEventListener('mousedown', function (ev) {
1478
- if (ev.target === mapQ) return;
1479
- ev.preventDefault();
1480
- findWrap.classList.add('is-open');
1481
- mapQ.focus();
1482
- });
1483
- mapQ.addEventListener('blur', function () { if (!mapQ.value) findWrap.classList.remove('is-open'); });
1484
-
1485
- /* the mode toggle is real, so the mock can be flipped by hand */
1486
- $('modeToggle').addEventListener('click', function () {
1487
- var now = document.documentElement.getAttribute('data-mode');
1488
- if (!now) now = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
1489
- var next = now === 'dark' ? 'light' : 'dark';
1490
- document.documentElement.setAttribute('data-mode', next);
1491
- try { localStorage.setItem('cb-color-mode', next); } catch (e) { /* private mode */ }
1492
- });
1493
- })();
1494
- </script>
1495
- </body>
1496
- </html>