@bongos/core 1.25.5 → 1.25.7

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 (46) hide show
  1. package/.bongos-core.json +69 -49
  2. package/clients/bongos-client/README.md +1 -1
  3. package/clients/bongos-client/bongos-client.global.js +2 -0
  4. package/clients/bongos-client/index.cjs +2 -0
  5. package/clients/bongos-client/index.d.ts +4 -1
  6. package/clients/bongos-client/index.mjs +2 -0
  7. package/docs/api/openapi.json +56 -2
  8. package/docs/api-reference.md +4 -3
  9. package/docs/copy-inventory.md +20 -19
  10. package/docs/copy-registry.json +32 -23
  11. package/docs/module-api-changelog.md +2 -0
  12. package/docs/page-readings.json +49 -52
  13. package/modules/hall-ui/public/shell-game.js +132 -5
  14. package/modules/hall-ui/public/style.css +59 -0
  15. package/modules/hall-ui/public/visor.css +11 -0
  16. package/modules/hall-ui/public/visor.js +14 -5
  17. package/modules/hall-ui/public/welcome-boot.js +27 -11
  18. package/modules/hall-ui/records/game-menu.md +22 -0
  19. package/modules/hall-ui/records/game-mode.md +2 -2
  20. package/modules/hall-ui/records/options-menu.md +1 -1
  21. package/modules/hall-ui/records/start-screen.md +12 -2
  22. package/modules/hall-ui/records/visor.md +4 -0
  23. package/modules/onboarding/genesis-home.js +35 -1
  24. package/modules/onboarding/routes/onboarding.js +7 -2
  25. package/modules/provisioning/catalog-bridge.js +3 -0
  26. package/modules/provisioning/paid-shape-gate.js +3 -1
  27. package/modules/provisioning/provisioning.js +3 -3
  28. package/modules/provisioning/routes/provisioning.js +7 -4
  29. package/modules/provisioning/test-project.js +65 -0
  30. package/modules/ui-design/public/brand.html +1 -1
  31. package/package-lock.json +2 -2
  32. package/package.json +1 -1
  33. package/release-notes.json +25 -0
  34. package/scripts/bongos/government-walk.js +2 -2
  35. package/src/branding.js +7 -0
  36. package/src/module-api.js +1 -1
  37. package/tests/currency_label.mjs +3 -1
  38. package/tests/hall_game_menu.mjs +195 -0
  39. package/tests/hall_options_menu.mjs +4 -1
  40. package/tests/hall_start_screen.mjs +62 -8
  41. package/tests/hall_visor.mjs +40 -5
  42. package/tests/provision_settings_apply.mjs +2 -1
  43. package/tests/provisioning_paid_shape_gate.mjs +16 -0
  44. package/tests/provisioning_settings_env.mjs +2 -2
  45. package/tests/test_project.mjs +122 -0
  46. package/tests/wizard_demo.mjs +25 -4
@@ -51,7 +51,7 @@
51
51
  <ul class="ref-list" role="list"><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--ok)" aria-hidden="true"></span><code class="ref-name">--ok</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#187444</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#4ade80</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--ok-weak)" aria-hidden="true"></span><code class="ref-name">--ok-weak</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, #187444 12%, var(--bg-card))</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, #4ade80 14%, var(--bg-card))</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--warn)" aria-hidden="true"></span><code class="ref-name">--warn</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#895c00</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#fbbf24</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--warn-weak)" aria-hidden="true"></span><code class="ref-name">--warn-weak</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, #895c00 14%, var(--bg-card))</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, #fbbf24 14%, var(--bg-card))</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--danger)" aria-hidden="true"></span><code class="ref-name">--danger</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#b42318</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#f87171</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--danger-weak)" aria-hidden="true"></span><code class="ref-name">--danger-weak</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, #b42318 10%, var(--bg-card))</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, #f87171 14%, var(--bg-card))</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--info)" aria-hidden="true"></span><code class="ref-name">--info</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--sea) 86%, #000000)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--sea) 80%, #ffffff)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--info-weak)" aria-hidden="true"></span><code class="ref-name">--info-weak</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--info) 9%, var(--bg-card))</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--info) 14%, var(--bg-card))</code></span></li></ul>
52
52
  <h3 class="ref-sub">Derived colours</h3>
53
53
  <p class="ref-note">Mixed from the thirteen, never typed as a new colour. Black and white with alpha appear only as a scrim, a shadow or glass.</p>
54
- <ul class="ref-list" role="list"><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--glass)" aria-hidden="true"></span><code class="ref-name">--glass</code><span class="ref-val"><span class="ref-val__k">light</span> <code>rgba(23, 24, 26, .05)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>rgba(200, 241, 247, .1)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--glass-strong)" aria-hidden="true"></span><code class="ref-name">--glass-strong</code><span class="ref-val"><span class="ref-val__k">light</span> <code>rgba(23, 24, 26, .08)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>rgba(200, 241, 247, .16)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--glass-edge)" aria-hidden="true"></span><code class="ref-name">--glass-edge</code><span class="ref-val"><span class="ref-val__k">light</span> <code>rgba(23, 24, 26, .12)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>rgba(200, 241, 247, .2)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--void)" aria-hidden="true"></span><code class="ref-name">--void</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#050508</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#050d16</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--void-ink)" aria-hidden="true"></span><code class="ref-name">--void-ink</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#ffffff</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>var(--ink)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--void-edge)" aria-hidden="true"></span><code class="ref-name">--void-edge</code><span class="ref-val"><span class="ref-val__k">light</span> <code>rgba(23, 24, 26, .12)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>rgba(200, 241, 247, .4)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--skeleton)" aria-hidden="true"></span><code class="ref-name">--skeleton</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--ink) 10%, var(--bg-card))</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--ink) 10%, var(--bg-card))</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--accent-ink)" aria-hidden="true"></span><code class="ref-name">--accent-ink</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--accent) 45%, #240e00)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>var(--accent)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--accent-lift)" aria-hidden="true"></span><code class="ref-name">--accent-lift</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--accent) 58%, #ffffff)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--accent) 58%, #ffffff)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--accent-tint)" aria-hidden="true"></span><code class="ref-name">--accent-tint</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--accent) 30%, #fffdf9)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--accent) 22%, #050d16)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--accent-on)" aria-hidden="true"></span><code class="ref-name">--accent-on</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#2a1305</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#2a1305</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--focus)" aria-hidden="true"></span><code class="ref-name">--focus</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--accent-deep) 82%, #3a1400)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>var(--accent)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--scrim)" aria-hidden="true"></span><code class="ref-name">--scrim</code><span class="ref-val"><span class="ref-val__k">light</span> <code>rgba(0, 0, 0, .55)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>rgba(0, 0, 0, .55)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--surface-2)" aria-hidden="true"></span><code class="ref-name">--surface-2</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--ink) 5%, var(--bg-card))</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--ink) 6%, var(--bg-card))</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--night-glass)" aria-hidden="true"></span><code class="ref-name">--night-glass</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--bg) 72%, transparent)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--bg) 72%, transparent)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--night-plate)" aria-hidden="true"></span><code class="ref-name">--night-plate</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--bg) 88%, transparent)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--bg) 88%, transparent)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-top)" aria-hidden="true"></span><code class="ref-name">--sky-night-top</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#02060c</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#02060c</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-mid)" aria-hidden="true"></span><code class="ref-name">--sky-night-mid</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#07121f</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#07121f</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-cloud)" aria-hidden="true"></span><code class="ref-name">--sky-night-cloud</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#456780</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#456780</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-cloud-shade)" aria-hidden="true"></span><code class="ref-name">--sky-night-cloud-shade</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#1a3348</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#1a3348</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-roof)" aria-hidden="true"></span><code class="ref-name">--sky-night-roof</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#2a475e</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#2a475e</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-lit)" aria-hidden="true"></span><code class="ref-name">--sky-night-lit</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#10263a</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#10263a</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-shade)" aria-hidden="true"></span><code class="ref-name">--sky-night-shade</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#081522</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#081522</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-base)" aria-hidden="true"></span><code class="ref-name">--sky-night-base</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#3c5d75</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#3c5d75</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-lamp)" aria-hidden="true"></span><code class="ref-name">--sky-night-lamp</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#ffe9c9</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#ffe9c9</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-line)" aria-hidden="true"></span><code class="ref-name">--sky-night-line</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#8fb3c8</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#8fb3c8</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-top)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-top</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#050d16</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#050d16</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-mid)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-mid</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#17334a</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#17334a</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-cloud)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-cloud</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#fbe3c8</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#fbe3c8</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-cloud-shade)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-cloud-shade</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#b08e8c</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#b08e8c</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-roof)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-roof</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#a9c0cc</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#a9c0cc</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-lit)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-lit</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#3f5b70</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#3f5b70</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-shade)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-shade</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#1f3a50</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#1f3a50</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-base)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-base</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#f0c9ab</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#f0c9ab</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-lamp)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-lamp</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#ffe2c4</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#ffe2c4</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-line)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-line</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#2f4b61</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#2f4b61</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-top)" aria-hidden="true"></span><code class="ref-name">--sky-midday-top</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#1d5687</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#1d5687</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-mid)" aria-hidden="true"></span><code class="ref-name">--sky-midday-mid</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#4a90c2</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#4a90c2</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-cloud)" aria-hidden="true"></span><code class="ref-name">--sky-midday-cloud</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#fff6dc</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#fff6dc</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-cloud-shade)" aria-hidden="true"></span><code class="ref-name">--sky-midday-cloud-shade</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#e8d2a8</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#e8d2a8</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-roof)" aria-hidden="true"></span><code class="ref-name">--sky-midday-roof</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#fff3d4</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#fff3d4</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-lit)" aria-hidden="true"></span><code class="ref-name">--sky-midday-lit</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#dcc79c</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#dcc79c</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-shade)" aria-hidden="true"></span><code class="ref-name">--sky-midday-shade</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#7f93a8</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#7f93a8</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-base)" aria-hidden="true"></span><code class="ref-name">--sky-midday-base</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#ffe6b3</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#ffe6b3</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-lamp)" aria-hidden="true"></span><code class="ref-name">--sky-midday-lamp</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#fff6dc</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#fff6dc</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-line)" aria-hidden="true"></span><code class="ref-name">--sky-midday-line</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#2f679a</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#2f679a</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-top)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-top</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#0a0f24</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#0a0f24</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-mid)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-mid</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#2a2552</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#2a2552</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-cloud)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-cloud</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#ffc79a</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#ffc79a</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-cloud-shade)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-cloud-shade</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#a8748a</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#a8748a</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-roof)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-roof</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#c7a3b0</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#c7a3b0</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-lit)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-lit</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#4a4470</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#4a4470</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-shade)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-shade</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#231f44</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#231f44</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-base)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-base</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#f6b596</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#f6b596</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-lamp)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-lamp</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#ffe2c4</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#ffe2c4</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-line)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-line</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#302b55</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#302b55</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-now-haze)" aria-hidden="true"></span><code class="ref-name">--sky-now-haze</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--sky-now-mid) 55%, var(--sky-now-cloud))</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--sky-now-mid) 55%, var(--sky-now-cloud))</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-now-glow)" aria-hidden="true"></span><code class="ref-name">--sky-now-glow</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--sky-now-lamp) calc(var(--sky-now-windows) * 100%), transparent)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--sky-now-lamp) calc(var(--sky-now-windows) * 100%), transparent)</code></span></li></ul>
54
+ <ul class="ref-list" role="list"><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--glass)" aria-hidden="true"></span><code class="ref-name">--glass</code><span class="ref-val"><span class="ref-val__k">light</span> <code>rgba(23, 24, 26, .05)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>rgba(200, 241, 247, .1)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--glass-strong)" aria-hidden="true"></span><code class="ref-name">--glass-strong</code><span class="ref-val"><span class="ref-val__k">light</span> <code>rgba(23, 24, 26, .08)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>rgba(200, 241, 247, .16)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--glass-edge)" aria-hidden="true"></span><code class="ref-name">--glass-edge</code><span class="ref-val"><span class="ref-val__k">light</span> <code>rgba(23, 24, 26, .12)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>rgba(200, 241, 247, .2)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--void)" aria-hidden="true"></span><code class="ref-name">--void</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#050508</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#050d16</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--void-ink)" aria-hidden="true"></span><code class="ref-name">--void-ink</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#ffffff</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>var(--ink)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--void-edge)" aria-hidden="true"></span><code class="ref-name">--void-edge</code><span class="ref-val"><span class="ref-val__k">light</span> <code>rgba(23, 24, 26, .12)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>rgba(200, 241, 247, .4)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--skeleton)" aria-hidden="true"></span><code class="ref-name">--skeleton</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--ink) 10%, var(--bg-card))</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--ink) 10%, var(--bg-card))</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--accent-ink)" aria-hidden="true"></span><code class="ref-name">--accent-ink</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--accent) 45%, #240e00)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>var(--accent)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--accent-lift)" aria-hidden="true"></span><code class="ref-name">--accent-lift</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--accent) 58%, #ffffff)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--accent) 58%, #ffffff)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--accent-tint)" aria-hidden="true"></span><code class="ref-name">--accent-tint</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--accent) 30%, #fffdf9)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--accent) 22%, #050d16)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--accent-on)" aria-hidden="true"></span><code class="ref-name">--accent-on</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#2a1305</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#2a1305</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--focus)" aria-hidden="true"></span><code class="ref-name">--focus</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--accent-deep) 82%, #3a1400)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>var(--accent)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--scrim)" aria-hidden="true"></span><code class="ref-name">--scrim</code><span class="ref-val"><span class="ref-val__k">light</span> <code>rgba(0, 0, 0, .55)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>rgba(0, 0, 0, .55)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--surface-2)" aria-hidden="true"></span><code class="ref-name">--surface-2</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--ink) 5%, var(--bg-card))</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--ink) 6%, var(--bg-card))</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--night-glass)" aria-hidden="true"></span><code class="ref-name">--night-glass</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--bg) 72%, transparent)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--bg) 72%, transparent)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--night-plate)" aria-hidden="true"></span><code class="ref-name">--night-plate</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--bg) 88%, transparent)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--bg) 88%, transparent)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--smoke)" aria-hidden="true"></span><code class="ref-name">--smoke</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--bg) 62%, transparent)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--bg) 62%, transparent)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-top)" aria-hidden="true"></span><code class="ref-name">--sky-night-top</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#02060c</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#02060c</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-mid)" aria-hidden="true"></span><code class="ref-name">--sky-night-mid</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#07121f</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#07121f</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-cloud)" aria-hidden="true"></span><code class="ref-name">--sky-night-cloud</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#456780</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#456780</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-cloud-shade)" aria-hidden="true"></span><code class="ref-name">--sky-night-cloud-shade</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#1a3348</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#1a3348</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-roof)" aria-hidden="true"></span><code class="ref-name">--sky-night-roof</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#2a475e</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#2a475e</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-lit)" aria-hidden="true"></span><code class="ref-name">--sky-night-lit</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#10263a</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#10263a</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-shade)" aria-hidden="true"></span><code class="ref-name">--sky-night-shade</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#081522</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#081522</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-base)" aria-hidden="true"></span><code class="ref-name">--sky-night-base</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#3c5d75</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#3c5d75</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-lamp)" aria-hidden="true"></span><code class="ref-name">--sky-night-lamp</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#ffe9c9</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#ffe9c9</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-line)" aria-hidden="true"></span><code class="ref-name">--sky-night-line</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#8fb3c8</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#8fb3c8</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-top)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-top</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#050d16</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#050d16</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-mid)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-mid</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#17334a</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#17334a</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-cloud)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-cloud</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#fbe3c8</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#fbe3c8</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-cloud-shade)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-cloud-shade</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#b08e8c</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#b08e8c</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-roof)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-roof</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#a9c0cc</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#a9c0cc</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-lit)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-lit</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#3f5b70</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#3f5b70</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-shade)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-shade</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#1f3a50</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#1f3a50</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-base)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-base</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#f0c9ab</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#f0c9ab</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-lamp)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-lamp</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#ffe2c4</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#ffe2c4</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-line)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-line</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#2f4b61</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#2f4b61</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-top)" aria-hidden="true"></span><code class="ref-name">--sky-midday-top</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#1d5687</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#1d5687</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-mid)" aria-hidden="true"></span><code class="ref-name">--sky-midday-mid</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#4a90c2</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#4a90c2</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-cloud)" aria-hidden="true"></span><code class="ref-name">--sky-midday-cloud</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#fff6dc</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#fff6dc</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-cloud-shade)" aria-hidden="true"></span><code class="ref-name">--sky-midday-cloud-shade</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#e8d2a8</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#e8d2a8</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-roof)" aria-hidden="true"></span><code class="ref-name">--sky-midday-roof</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#fff3d4</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#fff3d4</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-lit)" aria-hidden="true"></span><code class="ref-name">--sky-midday-lit</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#dcc79c</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#dcc79c</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-shade)" aria-hidden="true"></span><code class="ref-name">--sky-midday-shade</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#7f93a8</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#7f93a8</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-base)" aria-hidden="true"></span><code class="ref-name">--sky-midday-base</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#ffe6b3</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#ffe6b3</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-lamp)" aria-hidden="true"></span><code class="ref-name">--sky-midday-lamp</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#fff6dc</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#fff6dc</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-line)" aria-hidden="true"></span><code class="ref-name">--sky-midday-line</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#2f679a</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#2f679a</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-top)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-top</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#0a0f24</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#0a0f24</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-mid)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-mid</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#2a2552</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#2a2552</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-cloud)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-cloud</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#ffc79a</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#ffc79a</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-cloud-shade)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-cloud-shade</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#a8748a</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#a8748a</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-roof)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-roof</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#c7a3b0</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#c7a3b0</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-lit)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-lit</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#4a4470</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#4a4470</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-shade)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-shade</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#231f44</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#231f44</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-base)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-base</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#f6b596</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#f6b596</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-lamp)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-lamp</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#ffe2c4</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#ffe2c4</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-line)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-line</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#302b55</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#302b55</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-now-haze)" aria-hidden="true"></span><code class="ref-name">--sky-now-haze</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--sky-now-mid) 55%, var(--sky-now-cloud))</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--sky-now-mid) 55%, var(--sky-now-cloud))</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-now-glow)" aria-hidden="true"></span><code class="ref-name">--sky-now-glow</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--sky-now-lamp) calc(var(--sky-now-windows) * 100%), transparent)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--sky-now-lamp) calc(var(--sky-now-windows) * 100%), transparent)</code></span></li></ul>
55
55
  </section>
56
56
  <section class="scroll ref-sec" id="ref-type" aria-labelledby="ref-type-h">
57
57
  <h2 class="scroll__h" id="ref-type-h">Type</h2>
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.25.5",
3
+ "version": "1.25.7",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.25.5",
9
+ "version": "1.25.7",
10
10
  "license": "AGPL-3.0-or-later",
11
11
  "dependencies": {
12
12
  "express": "^4.21.2",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.25.5",
3
+ "version": "1.25.7",
4
4
  "description": "Cloud Bongos — the AI-first build platform core (GDS + platform surfaces + module system), installed as a versioned dependency (ADR 0108).",
5
5
  "license": "AGPL-3.0-or-later",
6
6
  "main": "src/platform-server.js",
@@ -11728,5 +11728,30 @@
11728
11728
  "id": "1004150",
11729
11729
  "text": "The fleet view can now show which projects get automatic patch upgrades, and the nightly upgrade run says so out loud when it has nothing to do."
11730
11730
  }
11731
+ ],
11732
+ "1.25.7": [
11733
+ {
11734
+ "id": "1005252",
11735
+ "text": "In game mode the visor's labels now sit on smoked glass that blurs whatever is behind them, so a busy scene, or a screenshot of the hall being reviewed, no longer looks like a second visor."
11736
+ },
11737
+ {
11738
+ "id": "1005251",
11739
+ "text": "In game mode, Escape now only ever closes things; it no longer opens the options menu. Also fixed the visor's keys going dead after Options had been opened once."
11740
+ },
11741
+ {
11742
+ "text": "Escape opens the game menu (owner 2026-11-13, task 1005250 wins); keep the closed-dialog key test (task 1005251)"
11743
+ },
11744
+ {
11745
+ "id": "1005250",
11746
+ "text": "Game mode now has a game menu on Escape: players can open options, change character, log out or quit the game from one place."
11747
+ },
11748
+ {
11749
+ "id": "1005036",
11750
+ "text": "An archon can now create a test project: a project marked for trying features that are not finished. It stays off the public map, does not use up anyone's one free hosted project, and is the only kind where the guided setup ca"
11751
+ },
11752
+ {
11753
+ "id": "1005219",
11754
+ "text": "Opening the builders' hall now starts on the Game or Classic choice. Signed out, your pick takes you to sign in and then straight to that menu."
11755
+ }
11731
11756
  ]
11732
11757
  }
@@ -610,8 +610,8 @@ async function runWalk() {
610
610
  const instanceRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'government-walk-'));
611
611
  process.env.BONGOS_INSTANCE_ROOT = instanceRoot;
612
612
  delete process.env.DATABASE_URL; // the walk never touches a real database
613
- // The modules' info lines (a fence switched, a budget set) would bury the table.
614
- if (!process.env.LOG_LEVEL) process.env.LOG_LEVEL = 'warn';
613
+ process.env.BONGOS_TEST_PROJECT = 'on'; // a TEST project: only one starts genesis by hand (task 1005036)
614
+ if (!process.env.LOG_LEVEL) process.env.LOG_LEVEL = 'warn'; // info lines would bury the table
615
615
 
616
616
  const req = (rel) => require(path.join(ROOT, rel));
617
617
  const api = req('src/module-api.js');
package/src/branding.js CHANGED
@@ -94,6 +94,9 @@ const ENV_OVERRIDES = [
94
94
  ['NIGHT_TINT', ['project', 'nightTint']],
95
95
  ['LOOK_ACCENT', ['project', 'lookAccent']],
96
96
  ['LOGO_URL', ['project', 'logoUrl']],
97
+ // 'on' only on a TEST project (task 1005036, modules/provisioning/test-project.js): the hall labels itself
98
+ // and the not-yet-live feature switches open. Empty on every other project.
99
+ ['TEST_PROJECT', ['project', 'test']],
97
100
  // The birth marker (task 1004506): set by the platform only on a project created
98
101
  // through the startup flow, so a project made before that never has it (spec D8).
99
102
  // FOUNDING_BIRTH is when the platform made the row; DEMO_PEOPLE / DEMO_HOURS are the
@@ -258,6 +261,10 @@ function clientBranding(b = branding()) {
258
261
  mark: b.identity?.company?.mark || '',
259
262
  },
260
263
  },
264
+ // A TEST project (task 1005036, modules/provisioning/test-project.js): the hall labels itself and the
265
+ // not-yet-live feature switches open. Beside `project`, not in it: that block is the settings the
266
+ // platform pushes, key for key, and this is a mark, not a setting.
267
+ testProject: b.project?.test === 'on',
261
268
  currency: {
262
269
  label: b.currency?.label || 'credits',
263
270
  symbol: b.currency?.symbol || '',
package/src/module-api.js CHANGED
@@ -81,7 +81,7 @@ const { sleep } = require('./sleep');
81
81
  // MAJOR (see allowBoxScope below): passes the request through untouched.
82
82
  function deprecatedNoopMiddleware(_req, _res, next) { next(); }
83
83
 
84
- const CORE_VERSION = '1.25.5'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
84
+ const CORE_VERSION = '1.25.7'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
85
85
 
86
86
  // A namespaced logger so a module's log lines are attributable + consistent.
87
87
  // Usage: const log = api.logger('discord'); log.info('mounted');
@@ -84,7 +84,9 @@ test('clientBranding is a SMALL allow-list — no server-only field leaks to the
84
84
  // had been failing since that landed (task 1002470).
85
85
  // `project` joined the allow-list in task 1003140: the per-project policy is public
86
86
  // by nature and is the settings read-back a manage page needs (see clientBranding).
87
- assert.deepEqual(Object.keys(projected).sort(), ['copy', 'currency', 'identity', 'project', 'rankLabels', 'reward', 'theme']);
87
+ assert.deepEqual(Object.keys(projected).sort(), ['copy', 'currency', 'identity', 'project', 'rankLabels', 'reward', 'testProject', 'theme']);
88
+ // `testProject` joined in task 1005036: the platform's test-project mark ('on' or
89
+ // not), public by nature: the hall labels itself and opens its not-yet-live switches.
88
90
  // `artistGate` joined in task 1003575 (ADR 0241) — the project's artist strictness,
89
91
  // public for the same read-back reason as its neighbours. Its companion stamp
90
92
  // (artistGateSince) deliberately does NOT: that is platform bookkeeping the server
@@ -0,0 +1,195 @@
1
+ // tests/hall_game_menu.mjs — the game menu (task 1005250).
2
+ //
3
+ // WHY. Game mode has no sidebar, so a player could neither sign out nor quit. The game menu is
4
+ // the one way to do both, so a menu that draws but whose rows do nothing, or an Escape that
5
+ // still opens the options straight away, would leave the player locked in again. This RUNS the
6
+ // real shell-game.js, hall-dialog.js and visor.js in a real browser over a stand-in place
7
+ // (skipped where there is no browser) and presses what a player presses.
8
+ //
9
+ // Run: node tests/hall_game_menu.mjs
10
+ import assert from 'node:assert/strict';
11
+ import { test, after } from 'node:test';
12
+ import { createRequire } from 'node:module';
13
+ import fs from 'node:fs';
14
+ import path from 'node:path';
15
+ import { fileURLToPath } from 'node:url';
16
+
17
+ const require = createRequire(import.meta.url);
18
+ const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
19
+ const HALL = path.join(ROOT, 'modules', 'hall-ui', 'public');
20
+
21
+ const lib = require(path.join(ROOT, 'modules', 'ui-design', 'kit', 'lib.js'));
22
+ let browser = null;
23
+ try { browser = await lib.launchBrowser(); } catch (e) { if (!(e instanceof lib.NoBrowserError)) throw e; }
24
+ after(() => browser && browser.close());
25
+ const skip = !browser && 'no system Edge or Chrome';
26
+
27
+ const ORIGIN = 'http://hall.test';
28
+ const TYPES = { '.js': 'text/javascript', '.css': 'text/css', '.png': 'image/png', '.svg': 'image/svg+xml' };
29
+ // The stand-in place: a character (with or without "change character"), a scene for the visor,
30
+ // and a listener where shell.js's sign-out sits (a click on a link to the logout address).
31
+ const SCENE = (character) => `<script>
32
+ window.signedOut = 0; window.changed = 0; window.closeCalls = 0;
33
+ window.close = function () { window.closeCalls++; }; // a browser keeps a tab it did not open
34
+ document.addEventListener('click', function (e) {
35
+ var a = e.target.closest && e.target.closest('a');
36
+ if (a && /\\/auth\\/logout\\/?$/.test(a.getAttribute('href') || '')) { e.preventDefault(); window.signedOut++; }
37
+ });
38
+ window.OTBCraftMode = { character() { return 'artisan'; }, current() { return null; }, me() { return { builder: { total_credits: 5 } }; },
39
+ spriteSrc() { return ''; }, openTool() {}${character ? ', changeCharacter() { window.changed++; }' : ''} };
40
+ window.__visorScene = { name: 'test', place: 'Test city', actions: [], keys: [] };
41
+ </script>`;
42
+ const PAGE = (game, character) => `<!doctype html><html data-theme="dark" data-faces="helm"${game ? ' data-game="on"' : ''}><head><meta charset="utf-8">
43
+ <link rel="stylesheet" href="/builders/style.css"><link rel="stylesheet" href="/builders/visor.css"></head>
44
+ <body data-page="city"><main id="place"><button id="in-place">a button in the place</button></main>${SCENE(character)}
45
+ <script src="/builders/hall-dialog.js"></script><script src="/builders/shell-game.js"></script><script src="/builders/visor.js"></script></body></html>`;
46
+
47
+ async function open({ game = true, character = true, width = 1280, height = 800 } = {}) {
48
+ const ctx = await browser.newContext({ viewport: { width, height } });
49
+ await ctx.route(ORIGIN + '/**', (route) => {
50
+ const u = new URL(route.request().url());
51
+ const p = u.pathname;
52
+ if (p === '/city') return route.fulfill({ contentType: 'text/html', body: PAGE(game, character) });
53
+ if (p === '/settings') return route.fulfill({ contentType: 'text/html', body: '<!doctype html><title>options</title>' });
54
+ const f = p.startsWith('/modules/') ? path.join(ROOT, p) : path.join(HALL, p.replace(/^\/builders\//, ''));
55
+ if ((p.startsWith('/builders/') || p.startsWith('/modules/')) && TYPES[path.extname(p)] && fs.existsSync(f)) return route.fulfill({ contentType: TYPES[path.extname(p)], body: fs.readFileSync(f) });
56
+ if (p.startsWith('/api/')) return route.fulfill({ status: 401, contentType: 'application/json', body: '{}' });
57
+ return route.fulfill({ status: 404, body: '' });
58
+ });
59
+ const page = await ctx.newPage();
60
+ const errors = [];
61
+ page.on('pageerror', (e) => errors.push(String(e.message)));
62
+ await page.addInitScript((g) => { try { localStorage.setItem('hall-game', g ? 'on' : 'off'); window.OTB = { escapeHtml: (s) => String(s) }; } catch (_) { /* none */ } }, game);
63
+ await page.goto(ORIGIN + '/city');
64
+ await page.waitForFunction(() => !!window.OTBVisor && !!window.OTBShellGame);
65
+ return { ctx, page, errors };
66
+ }
67
+ const menuUp = (page) => page.evaluate(() => !!window.OTBGameMenu && window.OTBGameMenu.isOpen());
68
+ const optionsUp = (page) => page.evaluate(() => window.OTBOptionsOverlay.isOpen());
69
+ async function escape(page) { await page.keyboard.press('Escape'); await page.waitForTimeout(40); }
70
+
71
+ test('Escape in a game place opens the game menu, not the options; Escape again returns to the game', { skip }, async () => {
72
+ const { ctx, page, errors } = await open();
73
+ await escape(page);
74
+ assert.equal(await menuUp(page), true);
75
+ assert.equal(await optionsUp(page), false, 'the options stay shut until asked for');
76
+ const m = await page.evaluate(() => ({
77
+ title: document.querySelector('.game-menu__title').textContent,
78
+ rows: [...document.querySelectorAll('.game-menu__item')].map((r) => r.textContent),
79
+ shown: getComputedStyle(document.querySelector('.game-menu')).display,
80
+ modal: document.querySelector('.game-menu__box').getAttribute('aria-modal'),
81
+ focusIn: document.querySelector('.game-menu').contains(document.activeElement),
82
+ }));
83
+ assert.deepEqual(m, { title: 'Game menu', rows: ['Options', 'Change character', 'Log out', 'Exit game', 'Return to game'], shown: 'grid', modal: 'true', focusIn: true });
84
+ // the arrows walk the rows and wrap
85
+ await page.keyboard.press('ArrowUp');
86
+ assert.equal(await page.evaluate(() => document.activeElement.textContent), 'Return to game');
87
+ await page.keyboard.press('ArrowDown');
88
+ assert.equal(await page.evaluate(() => document.activeElement.textContent), 'Options');
89
+ await escape(page);
90
+ assert.equal(await menuUp(page), false, 'the second Escape shuts it');
91
+ assert.equal(await page.evaluate(() => getComputedStyle(document.querySelector('.game-menu')).display), 'none');
92
+ assert.deepEqual(errors, []);
93
+ await ctx.close();
94
+ });
95
+
96
+ test('Return to game shuts the menu; Options opens the options window in its place', { skip }, async () => {
97
+ const { ctx, page, errors } = await open();
98
+ await escape(page);
99
+ await page.click('[data-gm="return"]');
100
+ assert.equal(await menuUp(page), false);
101
+ await escape(page);
102
+ await page.click('[data-gm="options"]');
103
+ assert.equal(await menuUp(page), false, 'one window at a time');
104
+ assert.equal(await optionsUp(page), true);
105
+ assert.equal(await page.evaluate(() => document.querySelector('.opt-window__frame').getAttribute('src')), '/settings?embed=1', 'the one options menu, framed');
106
+ // (in the hall the framed menu hands its Escape up; this stand-in frame has no script, so press it on the window)
107
+ await page.evaluate(() => document.querySelector('.opt-window__box').focus());
108
+ await escape(page);
109
+ assert.equal(await optionsUp(page), false, 'Escape shuts the options');
110
+ assert.equal(await menuUp(page), false, 'and lands in the game, not back on the menu');
111
+ assert.deepEqual(errors, []);
112
+ await ctx.close();
113
+ });
114
+
115
+ test('Log out is a link to the sign-out address, so the shell signs the player out', { skip }, async () => {
116
+ const { ctx, page, errors } = await open();
117
+ await escape(page);
118
+ assert.equal(await page.evaluate(() => document.querySelector('[data-gm="logout"]').getAttribute('href')), '/api/bongos/auth/logout');
119
+ await page.click('[data-gm="logout"]');
120
+ assert.equal(await page.evaluate(() => window.signedOut), 1, 'the click reached the sign-out listener, once');
121
+ assert.equal(await page.evaluate(() => document.querySelector('.game-menu__note').textContent), 'Logging out');
122
+ // the real listener: shell.js turns exactly such a click into the POST and the bounce home
123
+ const shell = fs.readFileSync(path.join(HALL, 'shell.js'), 'utf8');
124
+ assert.match(shell, /if \(\/\\\/auth\\\/logout\\\/\?\$\/\.test\(a\.getAttribute\('href'\) \|\| ''\)\) \{\s*e\.preventDefault\(\);\s*doLogout\(\);/);
125
+ assert.deepEqual(errors, []);
126
+ await ctx.close();
127
+ });
128
+
129
+ test('Exit game closes the tab, and says so when the browser keeps it', { skip }, async () => {
130
+ const { ctx, page, errors } = await open();
131
+ await escape(page);
132
+ assert.equal(await page.evaluate(() => document.querySelector('.game-menu__note').hidden), true, 'no note until there is something to say');
133
+ await page.click('[data-gm="exit"]');
134
+ assert.equal(await page.evaluate(() => window.closeCalls), 1, 'it asked the browser to close the tab');
135
+ await page.waitForFunction(() => !document.querySelector('.game-menu__note').hidden);
136
+ assert.equal(await page.evaluate(() => document.querySelector('.game-menu__note').textContent), 'Your browser kept this tab open. Close it to quit.');
137
+ // Exit, then shut and reopen at once: the pending check must not speak into the new opening
138
+ await escape(page); await escape(page);
139
+ await page.click('[data-gm="exit"]');
140
+ await page.keyboard.press('Escape'); await page.keyboard.press('Escape');
141
+ await page.waitForTimeout(450);
142
+ assert.equal(await menuUp(page), true);
143
+ assert.equal(await page.evaluate(() => document.querySelector('.game-menu__note').hidden), true, 'a stale Exit check stays quiet');
144
+ // a fresh opening starts with no note
145
+ await escape(page); await escape(page);
146
+ assert.equal(await page.evaluate(() => document.querySelector('.game-menu__note').hidden), true);
147
+ assert.deepEqual(errors, []);
148
+ await ctx.close();
149
+ });
150
+
151
+ test('Change character hands over to the character\'s own flow, and is absent where there is none', { skip }, async () => {
152
+ const { ctx, page } = await open();
153
+ await escape(page);
154
+ await page.click('[data-gm="character"]');
155
+ assert.deepEqual(await page.evaluate(() => [window.changed, window.OTBGameMenu.isOpen()]), [1, false]);
156
+ await ctx.close();
157
+ const bare = await open({ character: false });
158
+ await escape(bare.page);
159
+ assert.deepEqual(await bare.page.$$eval('.game-menu__item', (r) => r.map((x) => x.textContent)), ['Options', 'Log out', 'Exit game', 'Return to game']);
160
+ await bare.ctx.close();
161
+ });
162
+
163
+ test('the visor opens it: its own key, and the Actions sheet\'s last row; its keys work again afterwards', { skip }, async () => {
164
+ const { ctx, page, errors } = await open();
165
+ assert.equal(await page.$('.visor__hint--options'), null, 'Escape is on the glass nowhere (task 1005248)');
166
+ await page.keyboard.press('m');
167
+ assert.equal(await menuUp(page), true, 'the game menu key');
168
+ assert.equal(await optionsUp(page), false);
169
+ await page.click('[data-gm="return"]');
170
+ await page.keyboard.press('a');
171
+ assert.equal(await page.evaluate(() => OTBVisor.isOpen()), true, 'a shut menu does not hold the visor\'s keys');
172
+ await page.click('.visor__sheet [data-game-menu]');
173
+ assert.deepEqual(await page.evaluate(() => [window.OTBGameMenu.isOpen(), OTBVisor.isOpen()]), [true, false], 'the sheet\'s Game menu row opens it and folds the sheet');
174
+ // while the menu is up, the place behind is not reachable by a letter key
175
+ await page.keyboard.press('a');
176
+ assert.equal(await page.evaluate(() => OTBVisor.isOpen()), false);
177
+ assert.deepEqual(errors, []);
178
+ await ctx.close();
179
+ });
180
+
181
+ test('the menu holds at a phone width, and classic mode has no game menu', { skip }, async () => {
182
+ const phone = await open({ width: 390, height: 780 });
183
+ await escape(phone.page);
184
+ const box = await phone.page.evaluate(() => { const r = document.querySelector('.game-menu__box').getBoundingClientRect(); return { l: r.left, r: r.right, t: r.top, b: r.bottom, sw: document.documentElement.scrollWidth }; });
185
+ assert.ok(box.l >= 16 && box.r <= 374 && box.t >= 0 && box.b <= 780, 'the whole menu is on the screen');
186
+ assert.equal(box.sw, 390, 'the page does not scroll sideways');
187
+ const small = await phone.page.$$eval('.game-menu__item', (r) => r.filter((x) => x.getBoundingClientRect().height < 24).length);
188
+ assert.equal(small, 0, 'every row is a full target');
189
+ await phone.ctx.close();
190
+ const classic = await open({ game: false });
191
+ await escape(classic.page);
192
+ assert.equal(await menuUp(classic.page), false, 'outside game mode Escape is the shell\'s, as before');
193
+ assert.equal(await classic.page.evaluate(() => document.querySelector('.game-menu')), null);
194
+ await classic.ctx.close();
195
+ });
@@ -241,6 +241,9 @@ test('GAME MODE: on the menu itself the last Escape closes it; outside game mode
241
241
  assert.deepEqual(off.assigned, [], 'outside game mode the press stays the shell\'s');
242
242
  });
243
243
 
244
+ // Since task 1005250 the last Escape opens the GAME MENU, whose Options row opens this window
245
+ // (tests/hall_game_menu.mjs presses both in a real browser). This stub page can draw no game
246
+ // menu, so the press falls through to the window itself, which is what is tested here.
244
247
  test('GAME MODE: away from the menu, Escape opens the options as a window over the place, and Escape again shuts it', () => {
245
248
  const city = bootGame({ game: true, framed: false, path: '/city', dom: true });
246
249
  city.press('Escape');
@@ -301,6 +304,6 @@ test('every pop-up that closes on Escape spends the press, so the menu never ope
301
304
  test('the start screen\'s Options is the menu, and its first tip says what Escape does now', () => {
302
305
  const src = read('shell-game.js');
303
306
  assert.match(src, /\{ id: 'options', label: 'Options', href: '\/settings' \}/, 'Options opens the one options menu');
304
- assert.match(src, /'Escape opens the options menu, where every setting lives\.'/);
307
+ assert.match(src, /'Escape opens the game menu: options, log out and exit\.'/, 'task 1005250: Escape is the game menu\'s');
305
308
  assert.doesNotMatch(src, /Escape brings the navigation back/, 'no tip promises what Escape no longer does');
306
309
  });
@@ -23,17 +23,20 @@ const read = (f) => fs.readFileSync(path.join(HALL, f), 'utf8');
23
23
  const CITY = fs.readFileSync(path.join(ROOT, 'scripts', 'hall-preview', 'fixtures', 'home__city.json'), 'utf8');
24
24
 
25
25
  // ---------- in a vm: the pure parts and the welcome's hand-off ----------
26
- function sandbox({ store = {}, game = true } = {}) {
27
- const started = [], asked = [];
26
+ function sandbox({ store = {}, session = {}, game = true } = {}) {
27
+ const started = [], asked = [], went = [];
28
28
  const window = {
29
- location: { search: '', pathname: '/', hash: '' },
29
+ location: { search: '', pathname: '/', hash: '', assign: (h) => went.push(h) },
30
30
  __BRANDING__: { identity: { worldName: 'Harbor' } },
31
31
  localStorage: {
32
32
  getItem: (k) => (k in store ? store[k] : null),
33
33
  setItem: (k, v) => { store[k] = String(v); },
34
34
  removeItem: (k) => { delete store[k]; },
35
35
  },
36
- sessionStorage: { getItem: () => null, setItem() {} },
36
+ sessionStorage: {
37
+ getItem: (k) => (k in session ? session[k] : null),
38
+ setItem: (k, v) => { session[k] = String(v); },
39
+ },
37
40
  OTBCraftMode: { markAsked: () => asked.push('marked'), onAccess: (a, b) => asked.push(['picker', a.authed, b.id]) },
38
41
  };
39
42
  const document = { documentElement: { dataset: {}, classList: { add() {}, remove() {} } }, addEventListener() {} };
@@ -44,7 +47,7 @@ function sandbox({ store = {}, game = true } = {}) {
44
47
  window.OTBShellGame.start = (o) => { started.push(o); return true; };
45
48
  }
46
49
  vm.runInContext(read('welcome-boot.js'), box, { filename: 'welcome-boot.js' });
47
- return { window, store, started, asked };
50
+ return { window, store, session, started, asked, went };
48
51
  }
49
52
 
50
53
  test('the menu is Start, Options, Achievements, Extras, Quit, in that order', () => {
@@ -105,10 +108,27 @@ test('a fresh sign-in is handed to the start screen with the still, and the craf
105
108
  assert.deepEqual(s.asked, [['picker', true, 7]], 'the picker is asked once the world is showing');
106
109
  });
107
110
 
108
- test('a visit that is not a fresh sign-in keeps the welcome, and a hall without shell-game.js greets a sign-in as before', () => {
109
- const daily = sandbox();
111
+ test('every visit to Home opens on Game or Classic, signed in or not (task 1005219)', () => {
112
+ const visit = sandbox();
113
+ assert.equal(visit.window.OTBWelcome.onAccess({ authed: true }, { id: 7 }), true);
114
+ assert.deepEqual([visit.started.length, visit.asked], [1, []], 'a new visit, signed in, is the chooser, not the welcome');
115
+ const deep = sandbox();
116
+ deep.window.location.pathname = '/goals';
117
+ assert.equal(deep.window.OTBWelcome.onAccess({ authed: true }, { id: 7 }), true);
118
+ assert.equal(deep.started.length, 0, 'only Home asks; a page deeper in keeps the day\'s welcome');
119
+ const out = sandbox();
120
+ assert.equal(out.window.OTBWelcome.onAccess({ authed: false }, null), true);
121
+ assert.equal(out.started.length, 1, 'signed out, the chooser stands in for the painted welcome');
122
+ assert.equal(typeof out.started[0].signIn, 'function', 'and a pick goes on to sign in');
123
+ out.started[0].signIn();
124
+ assert.deepEqual([out.went, out.store['hall-welcome-signin']], [['/api/bongos/auth/web/start'], '1'],
125
+ 'to GitHub, remembered as a sign-in so the return opens the picked menu');
126
+ });
127
+
128
+ test('within one visit, Home asks once; the day\'s welcome stays for a later page, and a hall without shell-game.js greets a sign-in as before', () => {
129
+ const daily = sandbox({ session: { 'hall-chooser-seen': '1' } });
110
130
  assert.equal(daily.window.OTBWelcome.onAccess({ authed: true }, { id: 7 }), true);
111
- assert.deepEqual([daily.started.length, daily.asked], [0, ['marked']], 'the day\'s first visit is the welcome\'s');
131
+ assert.deepEqual([daily.started.length, daily.asked], [0, ['marked']], 'asked already this visit: the day\'s first visit is the welcome\'s');
112
132
  const bare = sandbox({ store: { 'hall-welcome-signin': '1' }, game: false });
113
133
  assert.equal(bare.window.OTBWelcome.onAccess({ authed: true }, { id: 7 }), true);
114
134
  assert.deepEqual(bare.asked, ['marked']);
@@ -286,6 +306,40 @@ test('choosing Classic at sign-in closes the screen, leaves game mode off, and s
286
306
  await ctx.close();
287
307
  });
288
308
 
309
+ // task 1005219: the hall's front opens on the chooser signed out; the pick goes to sign-in and the
310
+ // return opens that menu without asking again — the start screen for Game, the plain hall for Classic.
311
+ test('signed out, a pick goes to sign-in, and the return opens the picked menu without asking again', { skip }, async () => {
312
+ for (const pick of ['game', 'classic']) {
313
+ const ctx = await hall();
314
+ await ctx.route(ORIGIN + '/api/bongos/auth/web/start', (route) => route.fulfill({ contentType: 'text/html', body: 'github' }));
315
+ const page = await ctx.newPage();
316
+ await page.goto(ORIGIN + '/');
317
+ await page.waitForFunction(() => !!window.OTBShell && !!window.OTBWelcome && !!window.OTBShellGame);
318
+ await page.evaluate(() => window.OTBShell.applyAccess({ authed: false }));
319
+ await page.waitForSelector('#game-start');
320
+ assert.equal((await state(page)).welcome, false, 'the chooser, not the painted welcome');
321
+ await Promise.all([page.waitForURL(ORIGIN + '/api/bongos/auth/web/start'), page.click(`[data-gs="view-${pick}"]`)]);
322
+ assert.deepEqual(await page.evaluate(() => [localStorage.getItem('hall-view-pending'), localStorage.getItem('hall-welcome-signin')]), [pick, '1']);
323
+
324
+ // back from GitHub, signed in
325
+ await page.goto(ORIGIN + '/');
326
+ await page.waitForFunction(() => !!window.OTBShell && !!window.OTBWelcome && !!window.OTBShellGame);
327
+ await page.evaluate(() => { const me = { authed: true, rank: 'metic', builder: { id: 7, display_name: 'Ada', github_login: 'ada' } }; window.OTBShell.applyAccess(me); window.OTBShell.applyAccess(me); });
328
+ await page.evaluate(() => new Promise((r) => setTimeout(r, 100)));
329
+ const s = await state(page);
330
+ if (pick === 'game') {
331
+ assert.equal(s.start, true, 'Game: the start screen');
332
+ assert.equal(await page.isVisible('#gs-items'), true, 'on its menu');
333
+ assert.equal(await page.isVisible('#gs-views'), false, 'not asked again');
334
+ assert.equal(s.game, 'on');
335
+ } else {
336
+ assert.deepEqual([s.start, s.welcome, s.game], [false, false, null], 'Classic: the hall, no screen, game mode off');
337
+ }
338
+ assert.equal(await page.evaluate(() => localStorage.getItem('hall-view-pending')), null, 'the pick is spent');
339
+ await ctx.close();
340
+ }
341
+ });
342
+
289
343
  test('on a phone the panel is the whole width, nothing scrolls sideways and every choice clears the floor (task 1005192)', { skip }, async () => {
290
344
  for (const [w, h] of [[390, 844], [320, 700]]) {
291
345
  const ctx = await hall({ viewport: { width: w, height: h } });