@bongos/core 1.24.79 → 1.24.81

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 (413) hide show
  1. package/.bongos-core.json +554 -394
  2. package/.claude/skills/ask-for-help/SKILL.md +1 -1
  3. package/.claude/skills/builder-sequence/SKILL.md +1 -1
  4. package/.claude/skills/design/SKILL.md +1 -1
  5. package/.claude/skills/goal-create/SKILL.md +1 -1
  6. package/.claude/skills/planning-session/SKILL.md +1 -1
  7. package/clients/bongos-client/README.md +1 -1
  8. package/clients/bongos-client/bongos-client.global.js +8 -0
  9. package/clients/bongos-client/index.cjs +8 -0
  10. package/clients/bongos-client/index.d.ts +11 -0
  11. package/clients/bongos-client/index.mjs +8 -0
  12. package/docs/adr/0274-one-kernel-three-role-packs.md +2 -2
  13. package/docs/adr/0399-the-visor-is-glass-over-the-scene-and-owns-no-camera.md +91 -0
  14. package/docs/adr/0400-a-chain-reserves-work-and-each-sub-quest-is-still-claimed-alone.md +109 -0
  15. package/docs/adr/0401-one-options-menu-opens-every-settings-screen-in-a-frame.md +53 -0
  16. package/docs/adr/0402-helm-is-the-halls-look-and-the-hall-is-dark-only.md +142 -0
  17. package/docs/adr/README.md +4 -0
  18. package/docs/api/openapi.json +195 -3
  19. package/docs/api-reference.md +8 -4
  20. package/docs/architecture.md +7 -3
  21. package/docs/copy-inventory.md +393 -378
  22. package/docs/copy-registry.json +722 -578
  23. package/docs/design/characters/character-sprites-source.webp +0 -0
  24. package/docs/file-map.md +7 -8
  25. package/docs/module-api-changelog.md +4 -0
  26. package/docs/modules-contract.md +5 -0
  27. package/docs/onboarding/slash-commands.md +1 -1
  28. package/docs/packs/{engineer.md → artisan.md} +5 -5
  29. package/docs/packs/artist.md +50 -4
  30. package/docs/page-inventory.json +16 -7
  31. package/docs/page-readings.json +3184 -3338
  32. package/docs/{packs/ideator.md → recipes/ideation-playbook.md} +5 -48
  33. package/migrations/core_296_crafts_artisan_artist.sql +72 -0
  34. package/migrations/core_297_builder_character.sql +30 -0
  35. package/modules/copy-desk/proposals.js +1 -1
  36. package/modules/economy/credits-by-craft.js +29 -15
  37. package/modules/hall-ui/public/ai-studio.html +6 -4
  38. package/modules/hall-ui/public/ai-studio.states.json +1 -0
  39. package/modules/hall-ui/public/atlas.html +5 -5
  40. package/modules/hall-ui/public/atlas.js +3 -1
  41. package/modules/hall-ui/public/atlas.states.json +1 -0
  42. package/modules/hall-ui/public/blockers.html +5 -5
  43. package/modules/hall-ui/public/board-room.html +4 -4
  44. package/modules/hall-ui/public/board-room.states.json +1 -0
  45. package/modules/hall-ui/public/characters/artisan.png +0 -0
  46. package/modules/hall-ui/public/characters/artist.png +0 -0
  47. package/modules/hall-ui/public/characters/patron.png +0 -0
  48. package/modules/hall-ui/public/city.css +3 -4
  49. package/modules/hall-ui/public/city.html +9 -9
  50. package/modules/hall-ui/public/city.js +17 -56
  51. package/modules/hall-ui/public/city.states.json +7 -32
  52. package/modules/hall-ui/public/collab.html +4 -4
  53. package/modules/hall-ui/public/collab.states.json +1 -0
  54. package/modules/hall-ui/public/commands.html +4 -4
  55. package/modules/hall-ui/public/commands.states.json +1 -0
  56. package/modules/hall-ui/public/controls.css +63 -11
  57. package/modules/hall-ui/public/copy-desk.html +4 -4
  58. package/modules/hall-ui/public/copy-desk.states.json +1 -0
  59. package/modules/hall-ui/public/craft-mode.js +258 -64
  60. package/modules/hall-ui/public/deploy.html +4 -4
  61. package/modules/hall-ui/public/deploy.states.json +1 -0
  62. package/modules/hall-ui/public/diagram-viewer.js +2 -1
  63. package/modules/hall-ui/public/dom-utils.js +1 -1
  64. package/modules/hall-ui/public/goal-map.html +9 -6
  65. package/modules/hall-ui/public/goals.html +5 -5
  66. package/modules/hall-ui/public/goals.states.json +1 -0
  67. package/modules/hall-ui/public/government.html +4 -4
  68. package/modules/hall-ui/public/government.states.json +1 -0
  69. package/modules/hall-ui/public/hall-render.js +3 -1
  70. package/modules/hall-ui/public/home-city-draw.js +3 -3
  71. package/modules/hall-ui/public/home-city.css +4 -0
  72. package/modules/hall-ui/public/home-city.js +17 -9
  73. package/modules/hall-ui/public/home-gallery.js +8 -1
  74. package/modules/hall-ui/public/home-idea-box.css +2 -2
  75. package/modules/hall-ui/public/home-idea-box.js +3 -3
  76. package/modules/hall-ui/public/idea.html +5 -5
  77. package/modules/hall-ui/public/idea.states.json +1 -0
  78. package/modules/hall-ui/public/ideas.html +5 -5
  79. package/modules/hall-ui/public/ideas.states.json +1 -0
  80. package/modules/hall-ui/public/index-founding.states.json +1 -0
  81. package/modules/hall-ui/public/index-genesis-decide.states.json +1 -0
  82. package/modules/hall-ui/public/index-genesis-demo.states.json +1 -0
  83. package/modules/hall-ui/public/index-genesis.states.json +1 -0
  84. package/modules/hall-ui/public/index.html +11 -7
  85. package/modules/hall-ui/public/index.states.json +1 -0
  86. package/modules/hall-ui/public/market-watch-item.html +4 -4
  87. package/modules/hall-ui/public/market-watch-item.states.json +1 -0
  88. package/modules/hall-ui/public/market-watch-rules.html +4 -4
  89. package/modules/hall-ui/public/market-watch-rules.states.json +1 -0
  90. package/modules/hall-ui/public/market-watch.html +6 -9
  91. package/modules/hall-ui/public/market-watch.js +22 -45
  92. package/modules/hall-ui/public/market-watch.states.json +1 -0
  93. package/modules/hall-ui/public/modules.html +4 -4
  94. package/modules/hall-ui/public/modules.states.json +1 -0
  95. package/modules/hall-ui/public/money.html +4 -4
  96. package/modules/hall-ui/public/money.states.json +1 -0
  97. package/modules/hall-ui/public/my-agents.html +4 -4
  98. package/modules/hall-ui/public/my-agents.states.json +1 -0
  99. package/modules/hall-ui/public/options-menu.js +409 -0
  100. package/modules/hall-ui/public/paintbrush.js +3 -3
  101. package/modules/hall-ui/public/palette.js +11 -13
  102. package/modules/hall-ui/public/primer.html +5 -5
  103. package/modules/hall-ui/public/primer.states.json +1 -0
  104. package/modules/hall-ui/public/profile-crafts.js +1 -1
  105. package/modules/hall-ui/public/profile-roles.js +23 -19
  106. package/modules/hall-ui/public/profile.css +1 -1
  107. package/modules/hall-ui/public/profile.html +19 -18
  108. package/modules/hall-ui/public/profile.js +19 -18
  109. package/modules/hall-ui/public/profile.states.json +5 -4
  110. package/modules/hall-ui/public/project-settings.html +4 -4
  111. package/modules/hall-ui/public/roster.html +4 -4
  112. package/modules/hall-ui/public/roster.js +3 -3
  113. package/modules/hall-ui/public/roster.states.json +1 -0
  114. package/modules/hall-ui/public/settings.css +24 -4
  115. package/modules/hall-ui/public/settings.html +21 -17
  116. package/modules/hall-ui/public/settings.js +44 -44
  117. package/modules/hall-ui/public/settings.states.json +1 -0
  118. package/modules/hall-ui/public/shell-game.css +110 -0
  119. package/modules/hall-ui/public/shell-game.js +316 -3
  120. package/modules/hall-ui/public/shell.js +15 -66
  121. package/modules/hall-ui/public/sky-interaction.js +7 -0
  122. package/modules/hall-ui/public/speciality-tools.js +1 -2
  123. package/modules/hall-ui/public/street-card.states.json +1 -0
  124. package/modules/hall-ui/public/street-inside.js +3 -4
  125. package/modules/hall-ui/public/street.css +1 -5
  126. package/modules/hall-ui/public/street.html +6 -10
  127. package/modules/hall-ui/public/street.js +8 -59
  128. package/modules/hall-ui/public/street.states.json +7 -32
  129. package/modules/hall-ui/public/studio.html +5 -5
  130. package/modules/hall-ui/public/studio.states.json +1 -0
  131. package/modules/hall-ui/public/style.css +197 -112
  132. package/modules/hall-ui/public/task-detail.js +5 -4
  133. package/modules/hall-ui/public/task.html +5 -5
  134. package/modules/hall-ui/public/task.states.json +1 -0
  135. package/modules/hall-ui/public/thinking.css +10 -0
  136. package/modules/hall-ui/public/thinking.html +9 -6
  137. package/modules/hall-ui/public/thinking.states.json +1 -0
  138. package/modules/hall-ui/public/tweak-editor.html +5 -5
  139. package/modules/hall-ui/public/tweak-editor.js +5 -1
  140. package/modules/hall-ui/public/tweak-editor.states.json +1 -0
  141. package/modules/hall-ui/public/update-pill.js +91 -2
  142. package/modules/hall-ui/public/visor.css +80 -0
  143. package/modules/hall-ui/public/visor.js +316 -0
  144. package/modules/hall-ui/public/watch-repo-invite.js +159 -0
  145. package/modules/hall-ui/public/watch.html +6 -5
  146. package/modules/hall-ui/public/watch.js +17 -2
  147. package/modules/hall-ui/public/watch.states.json +1 -0
  148. package/modules/hall-ui/public/welcome-boot.js +15 -6
  149. package/modules/hall-ui/public/work-founding.states.json +1 -0
  150. package/modules/hall-ui/public/work.html +5 -5
  151. package/modules/hall-ui/public/work.states.json +1 -0
  152. package/modules/hall-ui/records/builders-roster.md +2 -2
  153. package/modules/hall-ui/records/craft-mode.md +13 -11
  154. package/modules/hall-ui/records/game-mode.md +2 -2
  155. package/modules/hall-ui/records/governor-street.md +1 -1
  156. package/modules/hall-ui/records/home-city.md +3 -1
  157. package/modules/hall-ui/records/market-watch-settings.md +2 -0
  158. package/modules/hall-ui/records/options-menu.md +15 -0
  159. package/modules/hall-ui/records/profile-roles.md +11 -11
  160. package/modules/hall-ui/records/sky.md +3 -3
  161. package/modules/hall-ui/records/start-screen.md +25 -0
  162. package/modules/hall-ui/records/tweak-editor.md +1 -1
  163. package/modules/hall-ui/records/update-pill.md +12 -0
  164. package/modules/hall-ui/records/visor.md +23 -0
  165. package/modules/hall-ui/records/welcome-tower.md +5 -5
  166. package/modules/hall-ui/specimens/components.states.json +2 -1
  167. package/modules/ideas/ideator-stats.js +3 -1
  168. package/modules/ideas/inbox.js +2 -2
  169. package/modules/lifecycle/activity.js +1 -1
  170. package/modules/lifecycle/cascade.js +4 -4
  171. package/modules/lifecycle/goal-spec-task.js +1 -1
  172. package/modules/lifecycle/help-requests.js +19 -15
  173. package/modules/lifecycle/kickoff-checklist.js +3 -3
  174. package/modules/lifecycle/kickoff-seed.js +1 -1
  175. package/modules/lifecycle/migrations/lifecycle_021_crafts_artisan_artist.sql +29 -0
  176. package/modules/lifecycle/mingle.js +4 -4
  177. package/modules/lifecycle/page-tweak-write.js +1 -1
  178. package/modules/lifecycle/routes/task-write-routes.js +3 -1
  179. package/modules/lifecycle/routes/tasks.js +3 -3
  180. package/modules/lifecycle/ship-card.js +2 -3
  181. package/modules/lifecycle/task-classifier.js +39 -29
  182. package/modules/lifecycle/tests/cascade.mjs +7 -7
  183. package/modules/onboarding/founding-mode.js +3 -0
  184. package/modules/onboarding/genesis-home.js +21 -1
  185. package/modules/onboarding/routes/onboarding.js +2 -0
  186. package/modules/page-notes/notes.js +3 -2
  187. package/modules/page-notes/split.js +1 -1
  188. package/modules/platform-identity/craft-rollup.js +35 -7
  189. package/modules/platform-identity/migrations/platform_identity_036_crafts_artisan_artist.sql +45 -0
  190. package/modules/platform-identity/platform-identity.js +2 -2
  191. package/modules/platform-identity/routes/community-leaderboard.js +2 -1
  192. package/modules/platform-identity/routes/community-search.js +2 -1
  193. package/modules/platform-identity/routes/sso.js +2 -1
  194. package/modules/platform-identity/tests/platform-identity.mjs +6 -6
  195. package/modules/public-landing/public/community.html +3 -5
  196. package/modules/public-landing/public/index.html +1 -1
  197. package/modules/public-landing/public/projects.html +1 -1
  198. package/modules/specialities/migrations/specialities_004_crafts_artisan_artist.sql +30 -0
  199. package/modules/specialities/routes/specialities.js +2 -2
  200. package/modules/status-ui/public/status.js +1 -1
  201. package/modules/ui-design/kit/fixtures/community-leaderboard.json +10 -10
  202. package/modules/ui-design/kit/fixtures/community-search.json +2 -2
  203. package/modules/ui-design/kit/fixtures/scouting-recruiter.json +1 -1
  204. package/modules/ui-design/public/brand.html +2 -2
  205. package/package-lock.json +2 -2
  206. package/package.json +1 -1
  207. package/release-notes.json +76 -0
  208. package/scripts/bongos/autobongos-loop.js +1 -1
  209. package/scripts/bongos/discipline-modes.json +7 -12
  210. package/scripts/bongos/fitness.js +1 -1
  211. package/scripts/bongos/gen-hall-sitemap.js +7 -7
  212. package/scripts/bongos/grade-smoke.js +2 -2
  213. package/scripts/bongos/init.js +2 -2
  214. package/scripts/bongos/newcomer-floor.config.json +1 -2
  215. package/scripts/bongos/newcomer-floor.js +4 -3
  216. package/scripts/bongos/newcomer-floor.templates.json +10 -12
  217. package/scripts/bongos/newcomer-floor.test.js +47 -38
  218. package/scripts/bongos/role-pack-guard.js +5 -4
  219. package/scripts/bongos/seed-tasks.example.json +3 -3
  220. package/scripts/bongos/setup.js +20 -107
  221. package/scripts/bongos/start.js +2 -2
  222. package/scripts/bongos/task.js +5 -4
  223. package/scripts/bongos/triage.js +1 -1
  224. package/scripts/bongos/worktree.js +16 -4
  225. package/scripts/hall-preview/README.md +2 -3
  226. package/scripts/setup-builder.js +6 -46
  227. package/src/bongos/auth-admission.js +8 -8
  228. package/src/bongos/craft-mode.js +2 -0
  229. package/src/bongos/db.js +39 -1
  230. package/src/bongos/github-repos.js +78 -0
  231. package/src/bongos/module-scope-map.js +22 -0
  232. package/src/bongos/role-stats.js +27 -11
  233. package/src/bongos/routes/github.js +100 -2
  234. package/src/bongos/routes/me.js +33 -0
  235. package/src/bongos/serve-internal.js +33 -11
  236. package/src/crafts.js +66 -0
  237. package/src/hall-helm.js +79 -0
  238. package/src/module-api.js +6 -1
  239. package/src/module-loader/manifest-schema.js +16 -0
  240. package/src/modules.js +2 -2
  241. package/src/role-responsibilities.js +6 -5
  242. package/tests/acclaim_feed_evidence_db.mjs +1 -1
  243. package/tests/activity_rollup_as_of.mjs +1 -1
  244. package/tests/api_alias_caller_ratchet.mjs +3 -3
  245. package/tests/application_lifecycle.mjs +1 -1
  246. package/tests/artist_review.mjs +1 -1
  247. package/tests/artist_review_goal.mjs +1 -1
  248. package/tests/blocker_hall_live_proof.mjs +1 -1
  249. package/tests/blocker_tasks_named_db.mjs +2 -2
  250. package/tests/canonical_profile_url.mjs +1 -1
  251. package/tests/cap_newcomer_tasks.mjs +13 -13
  252. package/tests/character_creation.mjs +294 -0
  253. package/tests/claim_gate_open_blocker.mjs +2 -2
  254. package/tests/claim_gate_rebase.mjs +6 -6
  255. package/tests/claude_materialize.mjs +1 -1
  256. package/tests/clawback_confirmed_backlog.mjs +3 -3
  257. package/tests/collab_page.mjs +8 -9
  258. package/tests/collab_self_settling.mjs +2 -2
  259. package/tests/community_leaderboard_route.mjs +13 -5
  260. package/tests/community_proof_db.mjs +3 -0
  261. package/tests/community_search_route.mjs +7 -6
  262. package/tests/conductor.mjs +1 -1
  263. package/tests/conductor_main_e2e.mjs +8 -8
  264. package/tests/copy_desk_flags_db.mjs +1 -1
  265. package/tests/copy_desk_page_approve.mjs +2 -2
  266. package/tests/copy_desk_page_claim.mjs +2 -2
  267. package/tests/copy_desk_page_next.mjs +1 -1
  268. package/tests/copy_desk_page_release.mjs +1 -1
  269. package/tests/copy_desk_page_submit.mjs +2 -2
  270. package/tests/core_258_box_session_claims_db.mjs +1 -1
  271. package/tests/craft_mode.mjs +48 -34
  272. package/tests/craft_mode_home.mjs +20 -20
  273. package/tests/craft_mode_looks.mjs +16 -15
  274. package/tests/craft_mode_nav.mjs +31 -29
  275. package/tests/craft_review_mode.mjs +46 -41
  276. package/tests/crafts_vocabulary.mjs +70 -0
  277. package/tests/cross_discipline_priority_direction.mjs +5 -5
  278. package/tests/design_reference.mjs +1 -1
  279. package/tests/fitness.mjs +7 -11
  280. package/tests/funded_project_pays_proof_db.mjs +1 -1
  281. package/tests/genesis_home.mjs +21 -1
  282. package/tests/github_chip.mjs +3 -3
  283. package/tests/github_repo_invite.mjs +379 -0
  284. package/tests/goal_criterion_confirm_ui.mjs +1 -1
  285. package/tests/goal_invite_consent.mjs +1 -1
  286. package/tests/goal_map_page.mjs +2 -2
  287. package/tests/goal_sort_staleness.mjs +1 -1
  288. package/tests/goal_spec_task.mjs +1 -1
  289. package/tests/goal_spec_task_db.mjs +3 -3
  290. package/tests/grade_engine.mjs +2 -2
  291. package/tests/grader_no_artifact.mjs +1 -1
  292. package/tests/grader_prompt_fencing.mjs +1 -1
  293. package/tests/grader_prompt_window_bound.mjs +1 -1
  294. package/tests/grader_reader_lens.mjs +2 -2
  295. package/tests/grader_severity_gate.mjs +1 -1
  296. package/tests/grader_unbacked_score.mjs +1 -1
  297. package/tests/hall_approval_queue.mjs +1 -1
  298. package/tests/hall_board_world.mjs +2 -2
  299. package/tests/hall_builders_page_pass.mjs +3 -2
  300. package/tests/hall_city.mjs +16 -30
  301. package/tests/hall_controls.mjs +52 -4
  302. package/tests/hall_fullscreen.mjs +27 -3
  303. package/tests/hall_helm.mjs +187 -0
  304. package/tests/hall_kit_charts.mjs +1 -1
  305. package/tests/hall_landing_boot.mjs +1 -1
  306. package/tests/hall_my_agents.mjs +16 -16
  307. package/tests/hall_nav.mjs +22 -15
  308. package/tests/hall_options_menu.mjs +247 -0
  309. package/tests/hall_oversight_world.mjs +1 -1
  310. package/tests/hall_palette.mjs +8 -9
  311. package/tests/hall_profile_world.mjs +3 -3
  312. package/tests/hall_record_world.mjs +6 -4
  313. package/tests/hall_settings_world.mjs +2 -1
  314. package/tests/hall_sitemap.mjs +6 -5
  315. package/tests/hall_start_screen.mjs +307 -0
  316. package/tests/hall_street.mjs +15 -28
  317. package/tests/hall_street_inside.mjs +17 -9
  318. package/tests/hall_studio_world.mjs +3 -3
  319. package/tests/hall_topbar_320.mjs +4 -2
  320. package/tests/hall_visor.mjs +224 -0
  321. package/tests/help_requests.mjs +47 -15
  322. package/tests/helpers.mjs +4 -4
  323. package/tests/home_city.mjs +6 -4
  324. package/tests/home_city_widget.mjs +33 -14
  325. package/tests/home_gallery_widget.mjs +4 -4
  326. package/tests/home_idea_box.mjs +6 -6
  327. package/tests/hub_community_page.mjs +3 -3
  328. package/tests/hub_craft_rollup.mjs +75 -36
  329. package/tests/hub_recent_ships.mjs +3 -2
  330. package/tests/idea_cascade.mjs +2 -2
  331. package/tests/idea_credit_streams_db.mjs +1 -1
  332. package/tests/idea_detail_page.mjs +1 -1
  333. package/tests/idea_ideate_full.mjs +5 -2
  334. package/tests/idea_spark_hall.mjs +1 -1
  335. package/tests/init.mjs +3 -3
  336. package/tests/instance_manifest.mjs +2 -2
  337. package/tests/kickoff_checklist.mjs +1 -1
  338. package/tests/leaderboard_roles.mjs +34 -25
  339. package/tests/lifecycle_claim_ladder_refs.mjs +55 -0
  340. package/tests/lightbulb.mjs +14 -10
  341. package/tests/main_discipline.mjs +8 -8
  342. package/tests/markdown_line_endings.mjs +1 -1
  343. package/tests/market_watch_pages.mjs +52 -74
  344. package/tests/me_streak_leaderboard_queries.mjs +3 -3
  345. package/tests/migration_allocation.mjs +1 -1
  346. package/tests/mingle.mjs +36 -21
  347. package/tests/module-scope-map.mjs +22 -2
  348. package/tests/module_api.mjs +1 -0
  349. package/tests/module_contributions.mjs +13 -13
  350. package/tests/module_manifest.mjs +29 -0
  351. package/tests/module_skills_hook.mjs +2 -2
  352. package/tests/modules.mjs +14 -7
  353. package/tests/nav_permission_atoms.mjs +2 -1
  354. package/tests/needs_rebase.mjs +1 -1
  355. package/tests/newcomer_restock.mjs +13 -13
  356. package/tests/page_notes_panel.mjs +22 -22
  357. package/tests/page_tweak_no_block.mjs +1 -1
  358. package/tests/paintbrush.mjs +7 -7
  359. package/tests/privacy_matrix.mjs +1 -0
  360. package/tests/profile_activity.mjs +20 -23
  361. package/tests/profile_earnings.mjs +1 -1
  362. package/tests/profile_nudge_prefs.mjs +4 -4
  363. package/tests/profile_role_headline.mjs +73 -46
  364. package/tests/profile_role_stats.mjs +55 -45
  365. package/tests/profile_rollup_consent.mjs +19 -6
  366. package/tests/profile_route.mjs +12 -12
  367. package/tests/profile_ui_cross_project.mjs +4 -4
  368. package/tests/project_invite_suggestions.mjs +2 -2
  369. package/tests/promote_goal_id.mjs +1 -1
  370. package/tests/publish_manifest.mjs +1 -1
  371. package/tests/rank_floor_wiring.mjs +1 -1
  372. package/tests/regrade_actual_minutes.mjs +1 -1
  373. package/tests/removal_proposal.mjs +2 -2
  374. package/tests/reward_gate.mjs +4 -4
  375. package/tests/reward_mode_cost_plus_only.mjs +1 -1
  376. package/tests/role_responsibilities.mjs +18 -12
  377. package/tests/role_stats_db.mjs +17 -16
  378. package/tests/scouting_rollup_fanout.mjs +5 -5
  379. package/tests/seed_tasks.mjs +5 -2
  380. package/tests/session_earnings_mirror_db.mjs +1 -1
  381. package/tests/session_reward_on_land_db.mjs +1 -1
  382. package/tests/session_reward_reconcile_db.mjs +2 -2
  383. package/tests/sessions_kit_pager.mjs +1 -1
  384. package/tests/settings_art_key_absent.mjs +2 -2
  385. package/tests/settings_main_role.mjs +21 -20
  386. package/tests/setup_flow.mjs +3 -3
  387. package/tests/setup_smoke.mjs +20 -0
  388. package/tests/ship_card.mjs +6 -6
  389. package/tests/specialities.mjs +16 -4
  390. package/tests/speciality_db_shape.mjs +6 -6
  391. package/tests/speciality_injection.mjs +17 -17
  392. package/tests/speciality_offer_ui.mjs +5 -5
  393. package/tests/speciality_offered.mjs +6 -5
  394. package/tests/speciality_session_skills.mjs +7 -7
  395. package/tests/speciality_skills.mjs +11 -11
  396. package/tests/speciality_walkthrough_ui.mjs +2 -2
  397. package/tests/sso_checkin_identity_spoof.mjs +2 -1
  398. package/tests/task_classifier_vocab.mjs +10 -0
  399. package/tests/task_cli.mjs +11 -3
  400. package/tests/task_criteria_unlink_db.mjs +2 -2
  401. package/tests/task_discipline_required.mjs +38 -16
  402. package/tests/task_goal_required.mjs +4 -4
  403. package/tests/task_needs_db.mjs +1 -1
  404. package/tests/tweak_replaces_artist_review.mjs +1 -1
  405. package/tests/update_pill.mjs +153 -2
  406. package/tests/upkeep_home.mjs +1 -1
  407. package/tests/v3_c1_options_proof.mjs +145 -0
  408. package/tests/visual_review.mjs +3 -3
  409. package/tests/watch_applications_queue.mjs +8 -5
  410. package/tests/watch_sealed_floor.mjs +3 -1
  411. package/tests/welcome_boot.mjs +12 -9
  412. package/tests/welcome_boot_browser.mjs +13 -13
  413. package/tests/worktree_helper.mjs +16 -1
@@ -3,15 +3,15 @@
3
3
  <head>
4
4
  <meta charset="utf-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <title>Settings — {{worldName}}</title>
7
- <meta name="description" content="Your preferences — connections, access keys, and sounds.">
6
+ <title>Options — {{worldName}}</title>
7
+ <meta name="description" content="Every setting in one menu: your account, your agents, keys and sound, and the project's own settings, modules and permissions.">
8
8
  <!-- the hub's origin, stamped server-side (task 1004259): the Profile and
9
9
  privacy row links to its account page. Empty on an instance with no hub. -->
10
10
  <meta name="hub-origin" content="{{hubOrigin}}">
11
11
  <link rel="icon" href="/modules/ui-design/public/brand/favicon.svg" type="image/svg+xml">
12
12
  <link rel="preconnect" href="https://fonts.googleapis.com">
13
13
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
14
- <link rel="stylesheet" href="/builders/style.css?v=2026-07-02-shell1">
14
+ <link rel="stylesheet" href="/builders/style.css?v=2026-11-11-helm">
15
15
  <!-- The PANEL archetype (task 1003308): the row, the switch, the field, the
16
16
  chip control and the family's voices, shared with profile and pair.
17
17
  settings.css then holds only what this page
@@ -21,7 +21,7 @@
21
21
  <!-- task 1005094: the device cards and their Run button in Your Autobongos runner. -->
22
22
  <link rel="stylesheet" href="/builders/runner-button.css">
23
23
  </head>
24
- <body data-page="settings" data-page-title="Settings">
24
+ <body data-page="settings" data-page-title="Options">
25
25
 
26
26
  <div class="app">
27
27
  <aside class="app-sidebar" id="app-sidebar" aria-label="Primary"></aside>
@@ -33,7 +33,7 @@
33
33
  room voice, because here the document is the page. The sub-line is
34
34
  settings.js's — "Your preferences, <name>." and the two failure states. -->
35
35
  <div class="page-head page-head--room page-head--panel">
36
- <h1 id="settings-h1" class="page-head__h">settings</h1>
36
+ <h1 id="settings-h1" class="page-head__h">options</h1>
37
37
  <p class="page-head__sub" id="settings-sub">Loading your preferences…</p>
38
38
  </div>
39
39
 
@@ -47,13 +47,15 @@
47
47
  <div class="row-end"><a class="pbtn pbtn--save" href="/api/bongos/auth/web/start">Sign in</a></div>
48
48
  </section>
49
49
 
50
- <!-- Grouped layout (task 1723 → kit, task 2172): the sections sit in six
51
- groups behind a left sub-nav rail built by OTBKit.makeSectionRail
52
- (switch mode). settings.js wires the rail + per-panel anchor deep
53
- links (/settings#cli, /settings#art-key, …); only the active group's
54
- sections display. -->
50
+ <!-- The ONE options menu (task 1005144, ADR 0401; before it task 1723 → 2172):
51
+ the rail is a search box over every setting, grouped. Settings' own
52
+ sections sit in groups here; the screens that used to be pages (My
53
+ agents, Project settings, Modules, Permissions, Market Watch) open in a
54
+ frame that options-menu.js appends to #settings-groups. Per-panel
55
+ anchors (/settings#cli, /settings#art-key, …) still land; only the
56
+ active group's sections display. -->
55
57
  <div class="settings-layout" id="settings-layout">
56
- <nav class="section-rail" id="settings-rail" aria-label="Settings sections"></nav>
58
+ <nav class="opt-rail" id="settings-rail" aria-label="Options"></nav>
57
59
 
58
60
  <div class="settings-groups" id="settings-groups" data-active="account">
59
61
  <!-- task 1005043: the panel loader, until settings.js has read who is viewing (hideLayout). -->
@@ -403,10 +405,10 @@
403
405
  <!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
404
406
  chrome exists before the page scripts run. -->
405
407
  <script src="/builders/dom-utils.js?v=2026-11-05-numbers"></script>
406
- <script src="/builders/shell-game.js?v=2026-11-09-game-mode"></script>
408
+ <script src="/builders/shell-game.js?v=2026-11-11-helm"></script>
407
409
  <script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
408
- <script src="/builders/craft-mode.js?v=2026-11-05-goals"></script>
409
- <script src="/builders/shell.js?v=2026-11-09-game-mode"></script>
410
+ <script src="/builders/craft-mode.js?v=2026-11-10-visor"></script>
411
+ <script src="/builders/shell.js?v=2026-11-11-helm"></script>
410
412
  <script src="/builders/hall-dialog.js"></script>
411
413
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
412
414
  <script src="/builders/palette.js" defer></script>
@@ -414,10 +416,12 @@
414
416
  <script src="/builders/hall-kit.js"></script>
415
417
  <!-- shared record overlay (#/idea|blocker/N) — every hall page carries it; this
416
418
  page was the one gap (task 2172). -->
417
- <script src="/builders/task-detail.js?v=2026-07-03-taskdetail"></script>
419
+ <script src="/builders/task-detail.js?v=2026-11-10-options"></script>
418
420
  <!-- task 1005044: the old deep links to the agent settings that moved to My agents -->
419
421
  <script src="/builders/settings-moved.js?v=2026-11-03-moved"></script>
420
- <script src="/builders/settings.js?v=2026-11-03-moved"></script>
422
+ <!-- task 1005144: the ONE options menu — the rail, its search, and the screens it opens in a frame. -->
423
+ <script src="/builders/options-menu.js?v=2026-11-10-options"></script>
424
+ <script src="/builders/settings.js?v=2026-11-10-options"></script>
421
425
  <!-- task 1003341: the Active sessions panel. Its own file rather than more of
422
426
  settings.js, which sits close to the 1500-line size ratchet. -->
423
427
  <script src="/builders/settings-sessions.js?v=2026-08-29-sessions"></script>
@@ -426,7 +430,7 @@
426
430
  <script src="/builders/settings-ai-keys.js?v=2026-10-28-ai-keys"></script>
427
431
  <!-- task 1004296: Settings → Software update. Own file on the same precedent. -->
428
432
  <!-- the Update pill's flow, which the panel's Update button runs in place (task 1005041) -->
429
- <script src="/builders/update-pill.js?v=2026-11-03-pill"></script>
433
+ <script src="/builders/update-pill.js?v=2026-11-10-options"></script>
430
434
  <script src="/builders/settings-software-update.js?v=2026-11-03-pill"></script>
431
435
  <!-- task 1004501: Settings → Your Autobongos runner. Own file on the same precedent. -->
432
436
  <!-- task 1005094: what a device's Run button says (pure; loaded before the panel). -->
@@ -937,14 +937,14 @@
937
937
  }
938
938
  }
939
939
 
940
- // ---- section rail (grouped sub-nav, task 1723 → kit, task 2172) -----------
940
+ // ---- the options menu's native groups (task 1723 → 2172 → 1005144) ---------
941
941
  //
942
- // The sections sit in six groups behind a left rail (#settings-rail), built by
943
- // OTBKit.makeSectionRail in switch mode — the idiom this page originated. CSS
944
- // shows only the active group (.settings-groups[data-active]); a section's own
945
- // [hidden] attribute still wins, so the per-section reveal logic above is
946
- // unchanged. Deep links activate their group first, so scrollIntoView lands on
947
- // a visible section.
942
+ // The sections sit in groups; the left rail (#settings-rail) is the ONE options
943
+ // menu now (options-menu.js, ADR 0401), which also opens the screens that used
944
+ // to be pages of their own. CSS shows only the active group
945
+ // (.settings-groups[data-active]); a section's own [hidden] attribute still
946
+ // wins, so the per-section reveal logic above is unchanged. Deep links activate
947
+ // their group first, so scrollIntoView lands on a visible section.
948
948
 
949
949
  const RAIL_ITEMS = [
950
950
  { id: 'account', label: 'Account' },
@@ -955,7 +955,6 @@
955
955
  { id: 'update', label: 'Software update' },
956
956
  ];
957
957
  const RAIL_GROUPS = RAIL_ITEMS.map((i) => i.id).concat('extensions');
958
- let rail = null;
959
958
 
960
959
  // task 2172 — stable per-panel anchors (/settings#cli, /settings#sounds, …)
961
960
  // so skills and docs can deep-link a panel without depending on internal
@@ -984,7 +983,6 @@
984
983
  const groups = document.getElementById('settings-groups');
985
984
  if (!groups) return;
986
985
  groups.dataset.active = group;
987
- rail?.activate(group);
988
986
  // A panel whose read is expensive loads when its group opens, not with the page.
989
987
  if (typeof CustomEvent === 'function') document.dispatchEvent(new CustomEvent('settings:group', { detail: { group } }));
990
988
  if (!opts || opts.scroll !== false) window.scrollTo({ top: 0 });
@@ -1001,45 +999,52 @@
1001
999
  return grouped ? { group: grouped.getAttribute('data-group'), el } : null;
1002
1000
  }
1003
1001
 
1004
- // Activate the hash's group; for a panel anchor also scroll the panel into
1005
- // view (rail highlight = the group). Runs on load, after data lands (late-
1006
- // revealed sections), and on hashchange.
1002
+ // One of Settings' own groups, opened by the options menu (options-menu.js); a
1003
+ // panel anchor (#cli) also scrolls its panel into view.
1004
+ function showNative(group, anchor, opts) {
1005
+ const t = anchor ? resolveHash(anchor) : null;
1006
+ activateGroup(t ? t.group : group, { scroll: false });
1007
+ if (t && t.el && (!opts || opts.scroll !== false)) t.el.scrollIntoView({ behavior: 'smooth', block: 'start' });
1008
+ else if (!t || !t.el) window.scrollTo({ top: 0 });
1009
+ }
1010
+
1011
+ // Land the address on its place. The menu reads ?open= and a menu entry's id
1012
+ // (#account, ?open=my-agents#talk); a panel anchor (#cli) is this page's.
1013
+ // Runs on load, after data lands (late-revealed sections), and on hashchange.
1007
1014
  function applyHash(opts) {
1015
+ if (leaveIfMoved()) return;
1016
+ const menu = window.OTBOptions;
1017
+ if (menu && menu.openFromUrl()) return;
1008
1018
  const t = resolveHash(window.location.hash);
1009
1019
  if (!t) return;
1010
- activateGroup(t.group, { scroll: false });
1011
- if (t.el && (!opts || opts.scroll !== false)) {
1012
- t.el.scrollIntoView({ behavior: 'smooth', block: 'start' });
1013
- } else if (!t.el) {
1014
- window.scrollTo({ top: 0 });
1015
- }
1020
+ if (menu) menu.activate(t.group, null, { url: false });
1021
+ showNative(t.group, t.el ? window.location.hash : null, opts);
1016
1022
  }
1017
1023
 
1018
1024
  // task 1005044 — a link to an agent setting that moved to My agents
1019
- // (settings-moved.js) goes on there; replace(), so Back does not bounce here.
1025
+ // (settings-moved.js) opens it in the menu, where My agents lives now (task 1005144).
1020
1026
  function leaveIfMoved() {
1021
1027
  const to = window.OTBSettingsMoved && window.OTBSettingsMoved.movedTarget(window.location.hash);
1022
- if (to) window.location.replace(to);
1023
- return !!to;
1028
+ if (!to) return false;
1029
+ const anchor = to.split('#')[1] || null;
1030
+ if (window.OTBOptions) window.OTBOptions.activate('my-agents', anchor);
1031
+ return true;
1024
1032
  }
1025
1033
 
1026
- function wireRail() {
1027
- const mount = document.getElementById('settings-rail');
1028
- if (!mount || !window.OTBKit) return;
1029
- rail = window.OTBKit.makeSectionRail({
1030
- mount,
1031
- items: RAIL_ITEMS,
1032
- mode: 'switch',
1033
- onSwitch: (key) => {
1034
- activateGroup(key);
1035
- // Reflect the group in the URL so the view is shareable; replaceState
1036
- // keeps Back for leaving the page, not retracing rail clicks.
1037
- history.replaceState(null, '', window.location.pathname + window.location.search + `#${key}`);
1038
- },
1034
+ // The options menu (task 1005144): settings.js hands it the viewer once /me answers.
1035
+ function wireMenu(builder, contributed) {
1036
+ const menu = window.OTBOptions;
1037
+ if (!menu) return;
1038
+ menu.mount({
1039
+ rail: document.getElementById('settings-rail'),
1040
+ groups: document.getElementById('settings-groups'),
1041
+ viewer: { authed: true, rank: builder && builder.rank },
1042
+ contributed,
1043
+ onNative: (id, anchor) => showNative(id, anchor),
1039
1044
  });
1040
- rail.activate('account');
1045
+ if (!menu.openFromUrl() && !resolveHash(window.location.hash)) menu.activate('account', null, { url: false });
1041
1046
  applyHash({ scroll: false });
1042
- window.addEventListener('hashchange', () => { if (!leaveIfMoved()) applyHash(); });
1047
+ window.addEventListener('hashchange', () => applyHash());
1043
1048
  }
1044
1049
 
1045
1050
  // Hide the rail + groups entirely while the not-signed-in gate is showing —
@@ -1104,13 +1109,10 @@
1104
1109
  // MODULE PANELS — render any Settings panels modules contributed via the
1105
1110
  // seam (BV1.R42). None today; ready for discord/art once they leave core.
1106
1111
  mountContributedPanels();
1107
- // Reveal the Extensions rail entry only when a module actually contributed:
1108
- // the kit rail re-renders from the item list, then re-marks the active group.
1112
+ // THE OPTIONS MENU (task 1005144): the rail is the one menu now. The Extensions
1113
+ // entry shows only when a module actually contributed a panel.
1109
1114
  const contributed = $('#contributed-panels');
1110
- if (rail && contributed && contributed.children.length > 0) {
1111
- rail.refresh([...RAIL_ITEMS, { id: 'extensions', label: 'Extensions' }]);
1112
- rail.activate($('#settings-groups')?.dataset.active || 'account');
1113
- }
1115
+ wireMenu(builder, !!(contributed && contributed.children.length > 0));
1114
1116
 
1115
1117
  // Sounds are switched off for now (task 1004554 — .claude/sounds/play.js's
1116
1118
  // SOUNDS_ON). The per-sound toggles (#786) and the per-event picker (task 582)
@@ -1129,7 +1131,5 @@
1129
1131
  applyHash();
1130
1132
  }
1131
1133
 
1132
- if (leaveIfMoved()) return;
1133
- wireRail();
1134
1134
  load();
1135
1135
  })();
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "_": "The hall's SETTINGS page through modules/ui-design/kit/render.js (task 1003308). Every panel on it is a form the page script fills from a dozen /me/* reads, so the floors run against the hall-preview harness rather than the kit's own stub:\n\n node scripts/hall-preview/server.js --port 4621 --fixture-me\n node modules/ui-design/kit/render.js --states modules/hall-ui/public/settings.states.json --base-in http://builders.localhost:4621 --base-out http://builders.localhost:4621\n\nOne group renders at a time behind the section rail, so each rail group is its own state. There is no `out` state on purpose: settings.js answers a 401 by navigating to the sign-in flow, and a state whose page navigates away measures the destination, not this page (the not-signed-in gate panel is the non-401 failure render, pinned statically in tests/hall_settings_world.mjs).",
3
3
  "page": "/settings",
4
+ "modes": ["dark"],
4
5
  "_storage": "The hall asks a first-visit question (the session mode picker, craft-mode.js) over every page; seeding \"already asked\" renders the page a returning builder sees (task 1005080).",
5
6
  "storage": { "session": { "hall-craft-asked": "1" } },
6
7
  "surface": "hall-ui",
@@ -0,0 +1,110 @@
1
+ /* shell-game.css — the game's start screen and load screen (task 1005143; shell-game.js start()),
2
+ in the Helm look (task 1005192, ADR 0402). Both stand over the welcome's painting. The start
3
+ screen is one full-height night panel on the left, closed left and right by an ice hairline:
4
+ the mark and the project's name in the name voice, the five choices as full-width rows, one
5
+ line at the foot. The load screen is the same panel language, centred: the week in the name
6
+ voice, one segment per week, the city, the tip. Colours, sizes, corners, spacing and the
7
+ panel's own measures are the hall tier's tokens (style.css); nothing here is typed in, and
8
+ there is no breakpoint: the panel is as wide as a phone and stands off the edge on a desk
9
+ (--helm-inset). Rules: modules/hall-ui/records/start-screen.md. */
10
+ html.gs-open { overflow: hidden; }
11
+ .gs {
12
+ position: fixed; inset: 0; z-index: var(--ds-z-modal, 160); overflow: auto;
13
+ display: flex; align-items: stretch; justify-content: flex-start;
14
+ padding: 0 0 0 var(--helm-inset);
15
+ background: var(--bg); color: var(--ink-soft); font-family: var(--font-body);
16
+ transition: opacity var(--ds-dur-slower) var(--ds-ease);
17
+ }
18
+ .gs--leaving { opacity: 0; pointer-events: none; }
19
+ .gs--load { align-items: center; justify-content: center; padding: var(--ds-space-lg) var(--ds-space-gutter-narrow); }
20
+
21
+ /* the still: the painting, covering the screen. The start screen leaves it bare (the panel is
22
+ its own ground); the load screen lays the scrim over it so the centred panel reads anywhere. */
23
+ .gs__art { position: absolute; inset: 0; }
24
+ .gs--load .gs__art::after { content: ""; position: absolute; inset: 0; background: var(--scrim); }
25
+ .gs__img { width: 100%; height: 100%; object-fit: cover; display: block; }
26
+
27
+ /* the two panels: night over the art, an ice hairline left and right, no corner, no shadow */
28
+ .gs__menu, .gs__load {
29
+ position: relative; box-sizing: border-box;
30
+ background: var(--night-glass);
31
+ border: 0 solid var(--rule); border-left-width: var(--line-strong); border-right-width: var(--line-strong);
32
+ }
33
+ .gs__menu[hidden], .gs__load[hidden] { display: none; }
34
+
35
+ /* the start screen: the mark and the name, the five choices, one line at the foot */
36
+ .gs__menu {
37
+ width: min(100%, var(--helm-panel-w)); min-height: 100%; flex: none;
38
+ display: flex; flex-direction: column; justify-content: space-between; gap: var(--ds-space-lg);
39
+ padding: var(--ds-space-xl) 0 var(--ds-space-lg);
40
+ }
41
+ .gs__top { display: flex; flex-direction: column; gap: var(--ds-space-xl); }
42
+ .gs__head { display: flex; flex-direction: column; gap: var(--ds-space-md); padding: 0 var(--ds-space-lg); }
43
+ .gs__mark { display: block; width: var(--helm-mark); height: var(--helm-mark); object-fit: contain; --mark-ink: var(--ink); }
44
+ .gs__title {
45
+ margin: 0; overflow-wrap: anywhere;
46
+ font-family: var(--name-face); font-size: var(--ds-text-headline); font-weight: var(--name-weight);
47
+ letter-spacing: var(--name-space-wide); text-transform: var(--name-case); line-height: 1.15;
48
+ color: var(--ink); text-shadow: var(--name-glow);
49
+ }
50
+ .gs__items { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
51
+ .gs__items[hidden] { display: none; }
52
+ .gs__item {
53
+ display: flex; align-items: center; justify-content: space-between; box-sizing: border-box;
54
+ width: 100%; min-height: var(--helm-row); padding: var(--ds-space-hair) var(--ds-space-lg);
55
+ background: transparent; color: var(--ink); border: 0; border-bottom: var(--line) solid var(--rule-soft);
56
+ font-family: var(--name-face); font-size: var(--ds-text-5xl); font-weight: 400;
57
+ letter-spacing: var(--name-space); text-transform: var(--name-case); text-align: left;
58
+ text-decoration: none; cursor: pointer;
59
+ transition: background-color var(--ds-dur-fast) var(--ds-ease);
60
+ }
61
+ .gs__items > li:last-child > .gs__item { border-bottom-color: transparent; }
62
+ .gs__item:hover { background: var(--glass); color: var(--ink); text-decoration: none; }
63
+ /* the ring sits inside the row: the focus colour on the edge, a band of the night inside it, so
64
+ one of the two reads on the accent bar as well as on the panel */
65
+ .gs__item:focus-visible { outline: 0; border-radius: var(--press-radius); box-shadow: var(--press-focus); }
66
+ /* Start is the one thing lit: the accent bar under its dark ink, with the key that takes it */
67
+ .gs__item[data-gs="start"] {
68
+ background: var(--accent); color: var(--accent-on); border-bottom-color: transparent;
69
+ font-weight: var(--name-weight-lit); box-shadow: var(--accent-glow);
70
+ }
71
+ .gs__item[data-gs="start"]:hover { background: var(--accent-lift); color: var(--accent-on); }
72
+ .gs__item[data-gs="start"]:focus-visible { box-shadow: var(--press-focus), var(--accent-glow); }
73
+ .gs__item[data-gs="start"]::after {
74
+ content: "Enter"; padding: 0 var(--ds-space-hair);
75
+ border: var(--line-strong) solid currentColor;
76
+ font-size: var(--ds-text-md); letter-spacing: var(--label-space);
77
+ }
78
+ /* Extras: three quieter rows, stepped in under the menu */
79
+ .gs__items--extras { border-top: var(--line) solid var(--rule-soft); }
80
+ .gs__item--extra {
81
+ min-height: var(--ds-space-xl); padding-left: var(--ds-space-xl);
82
+ font-size: var(--ds-text-xl); letter-spacing: var(--name-space-tight); color: var(--ink-soft);
83
+ }
84
+ /* the foot: one line said to you, over the strong hairline */
85
+ .gs__foot { padding: var(--ds-space-md) var(--ds-space-lg) 0; border-top: var(--line-strong) solid var(--rule); }
86
+ .gs__line, .gs__note { margin: 0; font-size: var(--ds-text-lg); line-height: 1.5; text-wrap: pretty; color: var(--ink-soft); }
87
+ .gs__note { margin-top: var(--ds-space-xs); color: var(--ink); }
88
+ .gs__note[hidden] { display: none; }
89
+
90
+ /* the load screen: the week it is showing, a segment per week, the city, and the tip under it */
91
+ .gs__load {
92
+ width: 100%; max-width: 44rem; padding: var(--ds-space-lg) var(--ds-space-md);
93
+ display: flex; flex-direction: column; gap: var(--ds-space-sm);
94
+ }
95
+ .gs__city { display: block; width: 100%; height: auto; max-height: 52vh; }
96
+ .gs__city[hidden], .gs__when[hidden], .gs__segs[hidden] { display: none; }
97
+ .gs__when {
98
+ margin: 0; color: var(--ink); font-variant-numeric: tabular-nums;
99
+ font-family: var(--name-face); font-size: var(--ds-text-xl); font-weight: var(--name-weight);
100
+ letter-spacing: var(--name-space); text-transform: var(--name-case);
101
+ }
102
+ .gs__tip {
103
+ margin: 0; padding-top: var(--ds-space-sm); border-top: var(--line) solid var(--rule-soft);
104
+ font-size: var(--ds-text-lg); line-height: 1.5; text-wrap: pretty; color: var(--ink-soft);
105
+ }
106
+ .gs__tip b {
107
+ display: block; margin-bottom: var(--ds-space-hair);
108
+ font-family: var(--name-face); font-size: var(--label-size); font-weight: var(--name-weight);
109
+ letter-spacing: var(--label-space); text-transform: var(--name-case); color: var(--ink);
110
+ }