@bongos/core 1.18.3 → 1.18.19

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 (471) hide show
  1. package/.bongos-core.json +1576 -286
  2. package/.claude/skills/builder-box/SKILL.md +6 -0
  3. package/.claude/skills/builder-sequence/SKILL.md +97 -0
  4. package/.claude/skills/builder-ship/SKILL.md +8 -2
  5. package/.claude/skills/builder-start/SKILL.md +11 -0
  6. package/.claude/skills/builder-sync/SKILL.md +41 -0
  7. package/.claude/skills/fix-task/SKILL.md +64 -0
  8. package/.claude/skills/goal-create/SKILL.md +158 -0
  9. package/.claude/skills/goal-review/SKILL.md +3 -1
  10. package/.claude/skills/idea-triage/SKILL.md +14 -8
  11. package/.claude/skills/merge-mode/SKILL.md +2 -2
  12. package/.claude/skills/new-project/SKILL.md +1 -0
  13. package/.claude/skills/planning-session/SKILL.md +45 -18
  14. package/.env.local.example +4 -3
  15. package/README.md +4 -2
  16. package/bin/bongos.js +1 -0
  17. package/clients/bongos-client/README.md +2 -2
  18. package/clients/bongos-client/bongos-client.global.js +82 -18
  19. package/clients/bongos-client/index.cjs +82 -18
  20. package/clients/bongos-client/index.d.ts +131 -29
  21. package/clients/bongos-client/index.mjs +82 -18
  22. package/config/branding.neutral.json +6 -1
  23. package/config/governance.neutral.json +21 -0
  24. package/docs/adr/0043-git-ssh-trust-boundary-and-rank-floor-on-permission-paths.md +24 -0
  25. package/docs/adr/0090-metic-task-authoring.md +1 -1
  26. package/docs/adr/0144-devbox-rehome-onto-cloudbongos-plane.md +41 -0
  27. package/docs/adr/0144-federated-single-logout-backchannel.md +42 -0
  28. package/docs/adr/0145-devbox-app-branding-driven-module.md +44 -0
  29. package/docs/adr/0145-free-hosted-project-tier-isolation-and-domain-separation.md +62 -0
  30. package/docs/adr/0146-configurable-reward-mode-cost-plus-only.md +53 -0
  31. package/docs/adr/0147-standalone-live-docs-regen.md +39 -0
  32. package/docs/adr/0148-task-scoped-box-source-access.md +48 -0
  33. package/docs/adr/0149-bongos-dev-local-launcher.md +57 -0
  34. package/docs/adr/0150-box-first-boot-bringup-vendored-instances.md +68 -0
  35. package/docs/adr/0151-governance-permissions-as-atom-ranks-as-roles.md +229 -0
  36. package/docs/adr/0152-landing-gate-served-by-the-core-app.md +92 -0
  37. package/docs/adr/0152-metic-task-abandonment.md +67 -0
  38. package/docs/adr/0153-sequential-chain-runner.md +51 -0
  39. package/docs/adr/0154-goal-owner-criterion-authoring.md +86 -0
  40. package/docs/adr/README.md +10 -0
  41. package/docs/api/openapi.json +843 -17
  42. package/docs/api-reference.md +23 -10
  43. package/docs/architecture.md +4 -2
  44. package/docs/branding-contract.md +3 -1
  45. package/docs/canonical-permissions.md +21 -8
  46. package/docs/file-map.md +8 -0
  47. package/docs/onboarding/diagrams/01-task-lifecycle.mmd +2 -2
  48. package/docs/onboarding/diagrams/02-rank-ladder.mmd +3 -1
  49. package/docs/onboarding/diagrams/05-versioning.mmd +1 -3
  50. package/docs/onboarding/diagrams/assertions.json +4 -7
  51. package/docs/onboarding/drachmae-and-karma.md +3 -3
  52. package/docs/onboarding/primer.md +17 -16
  53. package/docs/onboarding/slash-commands.md +124 -0
  54. package/docs/recipes/builder-box-lifecycle.md +23 -0
  55. package/docs/recipes/devbox-app-release.md +14 -4
  56. package/docs/recipes/instance-first-run.md +16 -0
  57. package/docs/recipes/local-dev.md +81 -0
  58. package/docs/recipes/ops-gotchas.md +19 -1
  59. package/docs/recipes/overnight-builder.md +1 -1
  60. package/docs/recipes/parallel-goal-waves.md +174 -0
  61. package/docs/recipes/ship-and-regrade.md +2 -2
  62. package/docs/recipes/standalone-live-docs.md +48 -0
  63. package/docs/recipes/work-on-a-task-from-your-dev-box.md +108 -0
  64. package/migrations/003_pms.sql +6 -7
  65. package/migrations/006_pms_v2.sql +3 -31
  66. package/migrations/core_193_task_needs_rebase.sql +28 -0
  67. package/migrations/core_194_confirmed_backlog_clawback.sql +63 -0
  68. package/migrations/core_195_idea_triage_provenance.sql +57 -0
  69. package/migrations/core_196_session_reward_topup.sql +69 -0
  70. package/modules/autonomy/pollers/routine-timers.js +9 -8
  71. package/modules/builder-settings/wandering-prefs.js +61 -18
  72. package/modules/dev-box/app/README.md +73 -0
  73. package/modules/dev-box/app/assets/tray/mac-alertTemplate.png +0 -0
  74. package/modules/dev-box/app/assets/tray/mac-alertTemplate@2x.png +0 -0
  75. package/modules/dev-box/app/assets/tray/mac-busyTemplate.png +0 -0
  76. package/modules/dev-box/app/assets/tray/mac-busyTemplate@2x.png +0 -0
  77. package/modules/dev-box/app/assets/tray/mac-offTemplate.png +0 -0
  78. package/modules/dev-box/app/assets/tray/mac-offTemplate@2x.png +0 -0
  79. package/modules/dev-box/app/assets/tray/mac-onTemplate.png +0 -0
  80. package/modules/dev-box/app/assets/tray/mac-onTemplate@2x.png +0 -0
  81. package/modules/dev-box/app/assets/tray/win-alert.png +0 -0
  82. package/modules/dev-box/app/assets/tray/win-busy.png +0 -0
  83. package/modules/dev-box/app/assets/tray/win-off.png +0 -0
  84. package/modules/dev-box/app/assets/tray/win-on.png +0 -0
  85. package/modules/dev-box/app/build-resources/dmg-background.png +0 -0
  86. package/modules/dev-box/app/build-resources/dmg-background@2x.png +0 -0
  87. package/modules/dev-box/app/build-resources/icon.png +0 -0
  88. package/modules/dev-box/app/electron-builder.tmpl.yml +95 -0
  89. package/modules/dev-box/app/electron-builder.yml +95 -0
  90. package/modules/dev-box/app/package-lock.json +5291 -0
  91. package/modules/dev-box/app/package.json +30 -0
  92. package/modules/dev-box/app/renderer/app.js +319 -0
  93. package/modules/dev-box/app/renderer/index.html +45 -0
  94. package/modules/dev-box/app/renderer/styles.css +246 -0
  95. package/modules/dev-box/app/renderer/theme.generated.css +16 -0
  96. package/modules/dev-box/app/scripts/apply-dmg-backdrop.sh +82 -0
  97. package/modules/dev-box/app/scripts/dmgbuild-settings.py +39 -0
  98. package/modules/dev-box/app/scripts/gen-brand.js +138 -0
  99. package/modules/dev-box/app/scripts/gen-dmg-backdrop.py +323 -0
  100. package/modules/dev-box/app/scripts/gen-icons.js +286 -0
  101. package/modules/dev-box/app/scripts/vendor-client.js +23 -0
  102. package/modules/dev-box/app/src/box-controller.js +287 -0
  103. package/modules/dev-box/app/src/brand.generated.json +13 -0
  104. package/modules/dev-box/app/src/brand.js +16 -0
  105. package/modules/dev-box/app/src/config.js +19 -0
  106. package/modules/dev-box/app/src/gds-client.js +90 -0
  107. package/modules/dev-box/app/src/main.js +610 -0
  108. package/modules/dev-box/app/src/pairing.js +57 -0
  109. package/modules/dev-box/app/src/preload.js +29 -0
  110. package/modules/dev-box/app/src/session-store.js +58 -0
  111. package/modules/dev-box/app/src/ssh-setup.js +569 -0
  112. package/modules/dev-box/app/src/task-picker.js +70 -0
  113. package/modules/dev-box/app/src/tray.js +99 -0
  114. package/modules/dev-box/app/src/updater.js +55 -0
  115. package/modules/dev-box/app/src/vendor/bongos-client.cjs +698 -0
  116. package/modules/dev-box/app/test/unit.mjs +526 -0
  117. package/modules/dev-box/box-access.js +121 -4
  118. package/modules/dev-box/boxes.js +20 -0
  119. package/modules/dev-box/module.json +1 -1
  120. package/modules/dev-box/routes/box.js +87 -3
  121. package/modules/economy/credits.js +116 -25
  122. package/modules/economy/reward.js +8 -0
  123. package/modules/economy/streak.js +2 -1
  124. package/modules/governance/CLAUDE.md +15 -0
  125. package/modules/governance/catalog.js +419 -0
  126. package/modules/governance/config.js +174 -0
  127. package/modules/governance/db.js +125 -0
  128. package/modules/governance/migrations/governance_001_tables.sql +81 -0
  129. package/modules/governance/migrations/governance_002_seed_and_backfill.sql +103 -0
  130. package/modules/governance/migrations/governance_003_task_abandon_metic.sql +28 -0
  131. package/modules/governance/migrations/governance_004_criterion_create.sql +39 -0
  132. package/modules/governance/migrations/governance_005_resync_builder_rank_roles.sql +56 -0
  133. package/modules/governance/module.json +10 -0
  134. package/modules/governance/protected-surfaces.js +88 -0
  135. package/modules/governance/protected-surfaces.json +80 -0
  136. package/modules/governance/rank-roles.js +83 -0
  137. package/modules/governance/resolver.js +221 -0
  138. package/modules/governance/routes/governance.js +89 -0
  139. package/modules/governance/routes/role-sync.js +49 -0
  140. package/modules/governance/session-scopes.js +127 -0
  141. package/modules/governance/session-scopes.json +38 -0
  142. package/modules/hall-ui/public/atlas.css +117 -0
  143. package/modules/hall-ui/public/atlas.html +3 -114
  144. package/modules/hall-ui/public/brand-apply.js +34 -6
  145. package/modules/hall-ui/public/builders.js +187 -219
  146. package/modules/hall-ui/public/diagrams.html +2 -0
  147. package/modules/hall-ui/public/dom-utils.js +27 -0
  148. package/modules/hall-ui/public/drachmae.html +2 -0
  149. package/modules/hall-ui/public/drachmae.js +54 -1
  150. package/modules/hall-ui/public/gate.css +98 -0
  151. package/modules/hall-ui/public/gate.html +3 -95
  152. package/modules/hall-ui/public/goal-inbox.js +4 -1
  153. package/modules/hall-ui/public/goals-page.js +626 -114
  154. package/modules/hall-ui/public/goals.css +79 -1
  155. package/modules/hall-ui/public/goals.html +38 -11
  156. package/modules/hall-ui/public/hall-widgets.js +62 -52
  157. package/modules/hall-ui/public/harbor.css +123 -0
  158. package/modules/hall-ui/public/harbor.html +3 -120
  159. package/modules/hall-ui/public/index.html +11 -4
  160. package/modules/hall-ui/public/instances-panel.js +4 -1
  161. package/modules/hall-ui/public/modules.css +63 -0
  162. package/modules/hall-ui/public/modules.html +3 -60
  163. package/modules/hall-ui/public/new-project-wizard.js +7 -3
  164. package/modules/hall-ui/public/not-ready.html +2 -0
  165. package/modules/hall-ui/public/pair.css +73 -0
  166. package/modules/hall-ui/public/pair.html +3 -70
  167. package/modules/hall-ui/public/palette.js +302 -0
  168. package/modules/hall-ui/public/primer.css +13 -0
  169. package/modules/hall-ui/public/primer.html +2 -0
  170. package/modules/hall-ui/public/profile.html +2 -0
  171. package/modules/hall-ui/public/ranks.html +2 -0
  172. package/modules/hall-ui/public/roadmap.css +179 -0
  173. package/modules/hall-ui/public/roadmap.html +9 -172
  174. package/modules/hall-ui/public/roadmap.js +329 -316
  175. package/modules/hall-ui/public/sessions.css +16 -0
  176. package/modules/hall-ui/public/sessions.html +3 -13
  177. package/modules/hall-ui/public/settings.html +2 -0
  178. package/modules/hall-ui/public/settings.js +4 -4
  179. package/modules/hall-ui/public/shell.js +143 -18
  180. package/modules/hall-ui/public/style.css +231 -39
  181. package/modules/hall-ui/public/task-detail.js +347 -26
  182. package/modules/hall-ui/public/task.html +6 -1
  183. package/modules/hall-ui/public/watch.html +2 -0
  184. package/modules/hall-ui/public/work.html +8 -6
  185. package/modules/hall-ui/public/work.js +1 -1
  186. package/modules/ideas/inbox.js +61 -11
  187. package/modules/ideas/routes/inbox.js +23 -0
  188. package/modules/lifecycle/claim-eligibility.js +72 -0
  189. package/modules/lifecycle/db.js +519 -139
  190. package/modules/lifecycle/done-when.js +18 -3
  191. package/modules/lifecycle/github-push.js +19 -2
  192. package/modules/lifecycle/goal-advisory.js +114 -0
  193. package/modules/lifecycle/goal-authz.js +62 -0
  194. package/modules/lifecycle/lifecycle.js +9 -0
  195. package/modules/lifecycle/publish-reconciler.js +109 -6
  196. package/modules/lifecycle/routes/claims.js +68 -23
  197. package/modules/lifecycle/routes/done-when.js +110 -15
  198. package/modules/lifecycle/routes/goals.js +8 -38
  199. package/modules/lifecycle/routes/tasks.js +38 -6
  200. package/modules/lifecycle/ship-card.js +6 -0
  201. package/modules/onboarding/onboarding-state.js +1 -1
  202. package/modules/platform-identity/CLAUDE.md +15 -0
  203. package/modules/platform-identity/hub-device.js +147 -0
  204. package/modules/platform-identity/hub-keys.js +151 -0
  205. package/modules/platform-identity/migrations/platform_identity_001_tables.sql +114 -0
  206. package/modules/platform-identity/migrations/platform_identity_002_client_origin_index.sql +18 -0
  207. package/modules/platform-identity/migrations/platform_identity_003_project_memberships.sql +42 -0
  208. package/modules/platform-identity/migrations/platform_identity_004_projects.sql +44 -0
  209. package/modules/platform-identity/migrations/platform_identity_005_builder_activity.sql +42 -0
  210. package/modules/platform-identity/module.json +18 -0
  211. package/modules/platform-identity/platform-identity.js +531 -0
  212. package/modules/platform-identity/pollers/code-sweep.js +43 -0
  213. package/modules/platform-identity/routes/my-projects.js +140 -0
  214. package/modules/platform-identity/routes/projects.js +107 -0
  215. package/modules/platform-identity/routes/scouting.js +35 -0
  216. package/modules/platform-identity/routes/sso.js +402 -0
  217. package/modules/platform-identity/tests/platform-identity.mjs +388 -0
  218. package/modules/platform-identity/ui/.gitkeep +0 -0
  219. package/modules/security/routes/reports.js +10 -0
  220. package/modules/sessions/db.js +166 -21
  221. package/modules/sessions/module.json +1 -1
  222. package/modules/sessions/pollers/session-reward-reconcile.js +78 -0
  223. package/modules/sessions/routes/sessions.js +33 -0
  224. package/package-lock.json +2 -2
  225. package/package.json +1 -1
  226. package/public-landing/assets/anim/idle/frame_00.webp +0 -0
  227. package/public-landing/assets/anim/idle/frame_01.webp +0 -0
  228. package/public-landing/assets/anim/idle/frame_02.webp +0 -0
  229. package/public-landing/assets/anim/idle/frame_03.webp +0 -0
  230. package/public-landing/assets/anim/idle/frame_04.webp +0 -0
  231. package/public-landing/assets/anim/idle/frame_05.webp +0 -0
  232. package/public-landing/assets/anim/idle/frame_06.webp +0 -0
  233. package/public-landing/assets/anim/idle/frame_07.webp +0 -0
  234. package/public-landing/assets/anim/idle/frame_08.webp +0 -0
  235. package/public-landing/assets/anim/idle/frame_09.webp +0 -0
  236. package/public-landing/assets/anim/idle/frame_10.webp +0 -0
  237. package/public-landing/assets/anim/idle/frame_11.webp +0 -0
  238. package/public-landing/assets/anim/idle/frame_12.webp +0 -0
  239. package/public-landing/assets/anim/idle/frame_13.webp +0 -0
  240. package/public-landing/assets/anim/idle/frame_14.webp +0 -0
  241. package/public-landing/assets/anim/idle/frame_15.webp +0 -0
  242. package/public-landing/assets/anim/idle/frame_16.webp +0 -0
  243. package/public-landing/assets/anim/idle/frame_17.webp +0 -0
  244. package/public-landing/assets/anim/idle/frame_18.webp +0 -0
  245. package/public-landing/assets/anim/idle/frame_19.webp +0 -0
  246. package/public-landing/assets/anim/idle/frame_20.webp +0 -0
  247. package/public-landing/assets/anim/idle/frame_21.webp +0 -0
  248. package/public-landing/assets/anim/idle/frame_22.webp +0 -0
  249. package/public-landing/assets/anim/idle/frame_23.webp +0 -0
  250. package/public-landing/assets/anim/idle/frame_24.webp +0 -0
  251. package/public-landing/assets/anim/idle/frame_25.webp +0 -0
  252. package/public-landing/assets/anim/idle/frame_26.webp +0 -0
  253. package/public-landing/assets/anim/idle/frame_27.webp +0 -0
  254. package/public-landing/assets/anim/idle/frame_28.webp +0 -0
  255. package/public-landing/assets/anim/idle/frame_29.webp +0 -0
  256. package/public-landing/assets/anim/idle/frame_30.webp +0 -0
  257. package/public-landing/assets/anim/idle/frame_31.webp +0 -0
  258. package/public-landing/assets/anim/idle/frame_32.webp +0 -0
  259. package/public-landing/assets/anim/idle/frame_33.webp +0 -0
  260. package/public-landing/assets/anim/idle/frame_34.webp +0 -0
  261. package/public-landing/assets/anim/idle/frame_35.webp +0 -0
  262. package/public-landing/assets/anim/idle/frame_36.webp +0 -0
  263. package/public-landing/assets/anim/idle/frame_37.webp +0 -0
  264. package/public-landing/assets/anim/idle/frame_38.webp +0 -0
  265. package/public-landing/assets/anim/idle/frame_39.webp +0 -0
  266. package/public-landing/assets/anim/idle/frame_40.webp +0 -0
  267. package/public-landing/assets/anim/idle/frame_41.webp +0 -0
  268. package/public-landing/assets/anim/idle/frame_42.webp +0 -0
  269. package/public-landing/assets/anim/idle/frame_43.webp +0 -0
  270. package/public-landing/create.html +51 -58
  271. package/public-landing/gate/README.md +137 -0
  272. package/public-landing/gate/dispmaps/bar.png +0 -0
  273. package/public-landing/gate/dispmaps/flat.png +0 -0
  274. package/public-landing/gate/dispmaps/key.png +0 -0
  275. package/public-landing/gate/index.html +587 -0
  276. package/public-landing/gate/previews/cloud-bongos.jpg +0 -0
  277. package/public-landing/gate/previews/off-the-boats.jpg +0 -0
  278. package/public-landing/gate/space.css +799 -0
  279. package/public-landing/gate/space.js +1826 -0
  280. package/public-landing/gate/sprites/enter.png +0 -0
  281. package/public-landing/gate/sprites/search.png +0 -0
  282. package/public-landing/gate/sprites/terminal-blank.png +0 -0
  283. package/public-landing/gate/sprites/tile.png +0 -0
  284. package/public-landing/world/assets/clouds/cloud-island-large.png +0 -0
  285. package/public-landing/world/assets/clouds/cloud-puff.png +0 -0
  286. package/public-landing/world/assets/creatures/creature-whale-cargo.png +0 -0
  287. package/public-landing/world/assets/creatures/creature-whale-glide.png +0 -0
  288. package/public-landing/world/assets/plates/plate-clouds-near.png +0 -0
  289. package/public-landing/world/assets/plates/scene-establishing.png +0 -0
  290. package/scripts/gds/abandon.js +6 -4
  291. package/scripts/gds/api.js +10 -5
  292. package/scripts/gds/api.ps1 +26 -0
  293. package/scripts/gds/api.sh +6 -0
  294. package/scripts/gds/audit-ships.js +7 -1
  295. package/scripts/gds/backfill-sessions.js +78 -18
  296. package/scripts/gds/backup.js +23 -1
  297. package/scripts/gds/box-connect-lib.js +124 -31
  298. package/scripts/gds/box-sync.js +66 -0
  299. package/scripts/gds/box.js +225 -53
  300. package/scripts/gds/cf-tunnel.js +145 -6
  301. package/scripts/gds/claim.js +34 -3
  302. package/scripts/gds/cli-lib.js +161 -27
  303. package/scripts/gds/code.js +6 -2
  304. package/scripts/gds/deploy-divergence.js +209 -0
  305. package/scripts/gds/dev-lib.js +309 -0
  306. package/scripts/gds/dev.js +322 -0
  307. package/scripts/gds/doctor.js +90 -61
  308. package/scripts/gds/fetch-art-key.js +1 -1
  309. package/scripts/gds/fetch-sound-prefs.js +2 -2
  310. package/scripts/gds/fitness.js +228 -12
  311. package/scripts/gds/gds-db-backup.service +16 -1
  312. package/scripts/gds/gds-db-offsite.service +9 -1
  313. package/scripts/gds/gen-api-client.js +1 -1
  314. package/scripts/gds/gen-api-docs.js +36 -14
  315. package/scripts/gds/gen-diagrams.js +45 -28
  316. package/scripts/gds/gen-file-map.js +2 -1
  317. package/scripts/gds/gen-freshness.js +32 -0
  318. package/scripts/gds/gen-repo-map.js +3 -2
  319. package/scripts/gds/gen-session-index.js +14 -5
  320. package/scripts/gds/hooks/pre-push.js +2 -2
  321. package/scripts/gds/init.js +60 -3
  322. package/scripts/gds/install-git-hooks.js +1 -1
  323. package/scripts/gds/key-card.js +15 -6
  324. package/scripts/gds/key-status.js +1 -1
  325. package/scripts/gds/linkify-refs.js +35 -9
  326. package/scripts/gds/login.js +16 -1
  327. package/scripts/gds/paste-token.js +7 -1
  328. package/scripts/gds/preflight.js +126 -0
  329. package/scripts/gds/provision.js +123 -12
  330. package/scripts/gds/publish-manifest.js +7 -1
  331. package/scripts/gds/reauth.js +7 -3
  332. package/scripts/gds/regen-instance-docs.js +47 -0
  333. package/scripts/gds/run-unit-tests.js +4 -2
  334. package/scripts/gds/seed-bongos-v1-seo-tasks.js +104 -0
  335. package/scripts/gds/seed-bv1-profiles-tasks.js +126 -0
  336. package/scripts/gds/sequence.js +425 -0
  337. package/scripts/gds/session-cost.js +10 -1
  338. package/scripts/gds/setup.js +31 -5
  339. package/scripts/gds/shell.js +5 -3
  340. package/scripts/gds/ship.js +319 -29
  341. package/scripts/gds/smoke-gds.js +139 -8
  342. package/scripts/gds/start.js +171 -22
  343. package/scripts/gds/status.js +1 -1
  344. package/scripts/gds/triage.js +10 -9
  345. package/scripts/gds/upgrade.js +124 -2
  346. package/scripts/migrate.sh +99 -14
  347. package/scripts/status-mirror-sync.js +114 -84
  348. package/src/bongos/api-errors.js +1 -0
  349. package/src/bongos/auth.js +447 -102
  350. package/src/bongos/db-kernel.js +27 -0
  351. package/src/bongos/db.js +39 -0
  352. package/src/bongos/module-scope-map.js +27 -1
  353. package/src/bongos/permission-path-check.js +136 -102
  354. package/src/bongos/repo-info.js +47 -11
  355. package/src/bongos/route-rank-check.js +429 -46
  356. package/src/bongos/routes/_helpers.js +12 -1
  357. package/src/bongos/routes/auth.js +219 -2
  358. package/src/bongos/routes/backup.js +58 -2
  359. package/src/bongos/routes/me.js +35 -1
  360. package/src/bongos/serve-internal.js +84 -15
  361. package/src/branding.js +32 -0
  362. package/src/instance-config.js +30 -0
  363. package/src/module-api.js +124 -1
  364. package/src/platform-server.js +86 -9
  365. package/tests/abandon_task.mjs +59 -3
  366. package/tests/api_cli_flags.mjs +53 -0
  367. package/tests/auth_page_gate.mjs +13 -0
  368. package/tests/backfill_sessions.mjs +127 -1
  369. package/tests/backup_cli.mjs +54 -0
  370. package/tests/bongos_box_connect.mjs +77 -0
  371. package/tests/box_access.mjs +130 -1
  372. package/tests/box_credential.mjs +125 -0
  373. package/tests/box_host_keys.mjs +24 -0
  374. package/tests/box_infra_resolve.mjs +149 -0
  375. package/tests/box_scope_session.mjs +6 -2
  376. package/tests/box_sync.mjs +55 -0
  377. package/tests/box_task_scope.mjs +99 -0
  378. package/tests/branding.mjs +12 -0
  379. package/tests/cf_ruleset_preflight.mjs +142 -0
  380. package/tests/cf_tunnel.mjs +37 -0
  381. package/tests/claim_gate_rebase.mjs +98 -0
  382. package/tests/clawback_confirmed_backlog.mjs +103 -0
  383. package/tests/cli_lib_formatters.mjs +20 -0
  384. package/tests/confirm_attribution.mjs +30 -46
  385. package/tests/credit_grant.mjs +198 -10
  386. package/tests/criterion_authoring_gate.mjs +272 -0
  387. package/tests/criterion_progress.mjs +33 -1
  388. package/tests/dev_lib.mjs +253 -0
  389. package/tests/devbox_artifact_gate.mjs +75 -0
  390. package/tests/devbox_dmg_backdrop.mjs +137 -0
  391. package/tests/devbox_icons.mjs +304 -0
  392. package/tests/devbox_installer_brand.mjs +232 -0
  393. package/tests/devbox_key_register.mjs +234 -0
  394. package/tests/docs_openapi_route.mjs +110 -0
  395. package/tests/doctor_hooks.mjs +141 -0
  396. package/tests/extract_json.mjs +140 -0
  397. package/tests/fitness.mjs +89 -0
  398. package/tests/gen_freshness.mjs +96 -0
  399. package/tests/goal_advisory.mjs +251 -0
  400. package/tests/goal_criterion_confirm_ui.mjs +269 -0
  401. package/tests/goal_routes.mjs +59 -4
  402. package/tests/goal_tier.mjs +12 -3
  403. package/tests/governance_catalog.mjs +129 -0
  404. package/tests/governance_claim_eligibility.mjs +262 -0
  405. package/tests/governance_config.mjs +187 -0
  406. package/tests/governance_ownership_scope.mjs +410 -0
  407. package/tests/governance_page_gates.mjs +324 -0
  408. package/tests/governance_parity.mjs +336 -0
  409. package/tests/governance_principals.mjs +232 -0
  410. package/tests/governance_protected_surfaces.mjs +208 -0
  411. package/tests/governance_require_permission.mjs +223 -0
  412. package/tests/governance_resolver.mjs +84 -0
  413. package/tests/governance_role_sync.mjs +231 -0
  414. package/tests/governance_seed.mjs +127 -0
  415. package/tests/governance_session_scope.mjs +434 -0
  416. package/tests/governance_vanilla_boot.mjs +203 -0
  417. package/tests/grade_attribution.mjs +7 -7
  418. package/tests/hall_audit.mjs +223 -0
  419. package/tests/hall_nav.mjs +191 -0
  420. package/tests/hall_palette.mjs +206 -0
  421. package/tests/hall_signout.mjs +124 -0
  422. package/tests/hook_user_agents.mjs +10 -0
  423. package/tests/idea_triage.mjs +162 -0
  424. package/tests/idp_device_exchange.mjs +93 -0
  425. package/tests/init.mjs +51 -0
  426. package/tests/instance_config.mjs +65 -0
  427. package/tests/instance_mismatch_guard.mjs +23 -6
  428. package/tests/instance_release_config.mjs +104 -0
  429. package/tests/linkify_refs.mjs +15 -2
  430. package/tests/migrate_root_resolution.mjs +124 -1
  431. package/tests/module_contributions.mjs +55 -0
  432. package/tests/module_loader.mjs +10 -5
  433. package/tests/module_scope_active_claims.mjs +94 -0
  434. package/tests/needs_rebase.mjs +92 -0
  435. package/tests/one_active_claim_per_session.mjs +76 -0
  436. package/tests/override_attribution.mjs +10 -8
  437. package/tests/override_request_ownership.mjs +8 -4
  438. package/tests/parse_cookie_decode.mjs +42 -0
  439. package/tests/pay_on_land.mjs +129 -0
  440. package/tests/platform_boot.mjs +100 -1
  441. package/tests/post_login_landing.mjs +42 -0
  442. package/tests/preflight_checks.mjs +72 -0
  443. package/tests/provision.mjs +132 -7
  444. package/tests/publish_branch_route.mjs +53 -0
  445. package/tests/publish_reconciler.mjs +187 -2
  446. package/tests/repo_info_binding.mjs +248 -0
  447. package/tests/reward_gate.mjs +11 -2
  448. package/tests/reward_mode_cost_plus_only.mjs +116 -0
  449. package/tests/reward_mode_surfacing.mjs +168 -0
  450. package/tests/route_permission_check.mjs +301 -0
  451. package/tests/route_rank_check.mjs +254 -12
  452. package/tests/route_validation.mjs +30 -0
  453. package/tests/sequence.mjs +267 -0
  454. package/tests/session_digest.mjs +44 -0
  455. package/tests/session_index.mjs +18 -6
  456. package/tests/session_records.mjs +39 -1
  457. package/tests/session_reward_on_land.mjs +381 -0
  458. package/tests/session_reward_reconcile.mjs +229 -0
  459. package/tests/ship_api_client_pathspec.mjs +100 -0
  460. package/tests/ship_base_flag.mjs +93 -0
  461. package/tests/ship_ci_deploy.mjs +80 -3
  462. package/tests/ship_upstream_deletion.mjs +57 -0
  463. package/tests/smoke_target.mjs +233 -0
  464. package/tests/start_env_guard.mjs +87 -0
  465. package/tests/start_rebase_warning.mjs +103 -0
  466. package/tests/status_mirror_sync.mjs +122 -0
  467. package/tests/stop_refcheck.mjs +19 -1
  468. package/tests/task_goal_link.mjs +15 -6
  469. package/tests/upgrade.mjs +139 -0
  470. package/tests/web_admission_status.mjs +162 -0
  471. package/tests/write_validation_gaps.mjs +110 -0
@@ -65,6 +65,28 @@
65
65
  --z-drawer: 150;
66
66
  }
67
67
 
68
+ /* ---------- spacing scale (task 2179) ----------
69
+ Four steps, deliberately matching the values the sheet had already converged
70
+ on (a census found 6/10/16/20 dominant), so this NAMES the existing rhythm
71
+ rather than restyling the hall. It governs the three things that decide
72
+ density — card padding, card gap, section gap — and is not a mandate to
73
+ rewrite every inset; chip and control padding stay as authored.
74
+
75
+ Kept in its OWN block rather than added to :root above: :root is the
76
+ pack-driven theming contract an instance overrides, and the program's audit
77
+ requires it unchanged. Spacing is structure, not theme.
78
+
79
+ 1 6px tight — inside a row or chip
80
+ 2 10px default gap between siblings
81
+ 3 16px comfortable — secondary card padding
82
+ 4 20px card padding, card gap, section gap */
83
+ :root {
84
+ --space-1: 6px;
85
+ --space-2: 10px;
86
+ --space-3: 16px;
87
+ --space-4: 20px;
88
+ }
89
+
68
90
  /* ---------- dark theme ----------
69
91
  Only the NEUTRALS flip; the instance pack's accent/sea/terracotta + fonts
70
92
  survive, and every derived token (color-mix on these vars) re-derives
@@ -212,8 +234,7 @@ button { font-family: var(--font-body); }
212
234
  flex-direction: column;
213
235
  background: var(--surface);
214
236
  border-right: 1px solid var(--border);
215
- overflow-y: auto;
216
- overflow-x: hidden;
237
+ overflow: hidden;
217
238
  }
218
239
 
219
240
  .app-sidebar__brand {
@@ -253,6 +274,19 @@ button { font-family: var(--font-body); }
253
274
  display: flex;
254
275
  flex-direction: column;
255
276
  gap: 2px;
277
+ /* task 1002446: the nav list is the scroller, not the whole sidebar. The
278
+ brand and foot were already flex-shrink:0 — the intent was always that they
279
+ stay put — but with overflow on .app-sidebar they scrolled away with
280
+ everything else, so the 2175 nav groups pushed "Sign out" 27px under a
281
+ 844px-tall window. Scrolling the list instead pins sign-out for good,
282
+ however many groups a later task adds. `min-height: 0` is what lets a flex
283
+ child shrink below its content and actually scroll; the explicit
284
+ `overflow-x: hidden` keeps the clip .app-sidebar used to provide, since
285
+ `overflow-y: auto` alone would promote the x axis to auto and give the
286
+ collapsed rail a stray sideways scrollbar. */
287
+ min-height: 0;
288
+ overflow-y: auto;
289
+ overflow-x: hidden;
256
290
  }
257
291
  .nav-group { display: flex; flex-direction: column; gap: 2px; }
258
292
  .nav-group + .nav-group { margin-top: 14px; }
@@ -358,6 +392,7 @@ button { font-family: var(--font-body); }
358
392
  }
359
393
  .shell-user__rank { font-size: 11.5px; color: var(--ink-faint); }
360
394
  .shell-signin,
395
+ .shell-home,
361
396
  .shell-signout {
362
397
  display: flex;
363
398
  align-items: center;
@@ -369,12 +404,14 @@ button { font-family: var(--font-body); }
369
404
  font-weight: 500;
370
405
  color: var(--ink-soft);
371
406
  }
407
+ .shell-home { text-decoration: none; }
372
408
  .shell-signin {
373
409
  justify-content: center;
374
410
  background: var(--accent);
375
411
  color: #fff;
376
412
  }
377
413
  .shell-signin:hover { background: var(--accent-deep); color: #fff; text-decoration: none; }
414
+ .shell-home:hover,
378
415
  .shell-signout:hover { background: var(--surface-2); color: var(--ink); text-decoration: none; }
379
416
 
380
417
  .app-body {
@@ -487,11 +524,11 @@ button { font-family: var(--font-body); }
487
524
  flex: 1;
488
525
  }
489
526
 
490
- .app-views .view > .view-zone + .view-zone { margin-top: 20px; }
527
+ .app-views .view > .view-zone + .view-zone { margin-top: var(--space-4); }
491
528
  .view-zone--band {
492
529
  display: grid;
493
530
  grid-template-columns: 1fr 1fr;
494
- gap: 20px;
531
+ gap: var(--space-4);
495
532
  align-items: start;
496
533
  }
497
534
  .view-zone--band > .scroll { margin: 0; }
@@ -527,7 +564,7 @@ button { font-family: var(--font-body); }
527
564
  .nav-item__label,
528
565
  .nav-group__head,
529
566
  .shell-user__meta { display: none; }
530
- .nav-item, .shell-signout { justify-content: center; padding: 0; }
567
+ .nav-item, .shell-home, .shell-signout { justify-content: center; padding: 0; }
531
568
  .nav-item--active::before { left: -6px; }
532
569
  .shell-user { justify-content: center; padding: 2px 0; }
533
570
  .shell-signin { font-size: 0; padding: 0; height: 34px; }
@@ -544,7 +581,7 @@ button { font-family: var(--font-body); }
544
581
  html.drawer-open .app-sidebar { transform: translateX(0); box-shadow: var(--shadow-pop); }
545
582
  .app-body { margin-left: 0; }
546
583
  .brand-mark__name, .nav-item__label, .nav-group__head, .shell-user__meta { display: block; }
547
- .nav-item, .shell-signout { justify-content: flex-start; padding: 0 10px; }
584
+ .nav-item, .shell-home, .shell-signout { justify-content: flex-start; padding: 0 10px; }
548
585
  .shell-user { justify-content: flex-start; }
549
586
  .shell-signin { font-size: 13.5px; padding: 0 10px; }
550
587
  .shell-signin::after { content: none; }
@@ -564,12 +601,17 @@ button { font-family: var(--font-body); }
564
601
 
565
602
  /* ---------- cards (the .scroll legacy name is load-bearing) ---------- */
566
603
 
604
+ /* The three sanctioned card levels (task 2179). Anything that looks like a card
605
+ is one of these — a fourth variant is a design decision, not a local override:
606
+ .scroll primary — the default surface for a section
607
+ .scroll--quiet secondary — a card INSIDE a card, or supporting detail
608
+ .scroll--bare none — layout-only, for stat rows and grids */
567
609
  .scroll {
568
610
  background: var(--surface);
569
611
  border: 1px solid var(--border);
570
612
  border-radius: var(--radius);
571
- padding: 20px;
572
- margin: 0 0 20px;
613
+ padding: var(--space-4);
614
+ margin: 0 0 var(--space-4);
573
615
  /* anchor jumps must clear the 56px sticky top bar */
574
616
  scroll-margin-top: calc(var(--topbar-h) + 16px);
575
617
  }
@@ -580,6 +622,16 @@ button { font-family: var(--font-body); }
580
622
  border-radius: 0;
581
623
  padding: 0;
582
624
  }
625
+ /* Secondary level: recedes against a primary card via surface-2 and a quieter,
626
+ smaller header. Use for supporting detail — not to fit more onto Home. */
627
+ .scroll--quiet {
628
+ background: var(--surface-2);
629
+ padding: var(--space-3);
630
+ }
631
+ .scroll--quiet > .scroll__h {
632
+ font-size: 13.5px;
633
+ color: var(--ink-soft);
634
+ }
583
635
 
584
636
  .scroll__h {
585
637
  margin: 0 0 6px;
@@ -680,6 +732,12 @@ button { font-family: var(--font-body); }
680
732
  .rail-link:hover { background: var(--surface-2); color: var(--ink); text-decoration: none; }
681
733
  .rail-link--active { background: var(--accent-weak); color: var(--accent-text); }
682
734
 
735
+ /* task 2174: a Standing rail section — the scroll-spy anchor holding one or
736
+ more cards. The extra air between groups is what makes the grouping legible
737
+ without adding a second level of headings above the cards' own. */
738
+ .standing-group + .standing-group { margin-top: 16px; }
739
+ .standing-group:last-child > .scroll:last-child { margin-bottom: 0; }
740
+
683
741
  @media (max-width: 768px) {
684
742
  .standing-layout { grid-template-columns: minmax(0, 1fr); }
685
743
  .section-rail {
@@ -843,6 +901,25 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
843
901
  .ledger th.ledger__sortable[aria-sort="ascending"]::after { content: " ↑"; }
844
902
  .ledger th.ledger__sortable[aria-sort="descending"]::after { content: " ↓"; }
845
903
 
904
+ /* task 1002446: a ledger's column count is fixed by its data, so its min-content
905
+ width outruns a phone and drags the whole page sideways — measured at 390w:
906
+ leaderboard 218px, Standing's ships table 19px, Home's recent-work 8px. (The
907
+ .rank-tip fix in the same task is what exposed these; its 62px used to swamp
908
+ them.) The strip goes on the ledger's PARENT, not on the ledger. Making the
909
+ table itself `display: block` does turn it into a scroller, but it also re-wraps
910
+ its rows in an anonymous table box that is shrink-to-fit, so any ledger NARROWER
911
+ than its card stops short of the card's right edge — measured at 390w on
912
+ /profile, #works-table's rows rendered 240px inside a 329px card, which is every
913
+ empty state in the hall. Left a table, it keeps `width: 100%` (fills) and lets
914
+ min-content push past the card, which is what the card then scrolls — the same
915
+ strip treatment .section-rail / .kit-tabs already use. Sticky headers go with
916
+ it: sticky would otherwise resolve against the new scrollport instead of the
917
+ window, so it is switched off rather than left silently broken. */
918
+ @media (max-width: 640px) {
919
+ :has(> .ledger) { overflow-x: auto; }
920
+ .ledger th { position: static; }
921
+ }
922
+
846
923
  /* ---------- filters / pager / buttons ---------- */
847
924
 
848
925
  .filters {
@@ -989,7 +1066,7 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
989
1066
  .profile__karma-label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--ink-faint); }
990
1067
  .profile__placeholder { color: var(--ink-faint); font-size: 13.5px; }
991
1068
 
992
- .profile__budget, .profile__needs {
1069
+ .profile__budget, .profile__needs, .profile__rebase {
993
1070
  grid-column: 1 / -1;
994
1071
  border-radius: var(--radius-sm);
995
1072
  padding: 10px 14px;
@@ -1001,6 +1078,8 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
1001
1078
  .profile__needs--action { background: var(--warn-weak); color: var(--warn); border-color: color-mix(in srgb, var(--warn) 25%, transparent); }
1002
1079
  .profile__needs--covered { background: var(--ok-weak); color: var(--ok); border-color: color-mix(in srgb, var(--ok) 22%, transparent); }
1003
1080
  .profile__needs-act { font-weight: 600; white-space: nowrap; }
1081
+ /* ADR 0120 part 5: owed-rebase gate banner — danger-tinted (it blocks new claims). */
1082
+ .profile__rebase { background: var(--danger-weak); color: var(--danger); border-color: color-mix(in srgb, var(--danger) 25%, transparent); }
1004
1083
 
1005
1084
  .disc-pref { margin-right: 4px; }
1006
1085
 
@@ -1063,6 +1142,18 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
1063
1142
  .rank-tip__list li { margin: 2px 0; }
1064
1143
  .rank-tip__more { margin: 6px 0 0; color: var(--ink-faint); }
1065
1144
 
1145
+ /* The tip is 240px anchored to the badge's LEFT edge, and the badge sits partway
1146
+ across the identity band — so under ~640px it reaches past the viewport and
1147
+ drags the whole page into sideways scroll. `visibility: hidden` still occupies
1148
+ layout, so that happened on every hall page at phone width with nothing even
1149
+ visible (measured: 62px of phantom scroll at 390w). Below the breakpoint where
1150
+ .profile already reflows, drop it: it is a hover popover, and a touch on the
1151
+ badge follows .rank-badge-stretch to /ranks — the full ladder the tip's own
1152
+ footer points at. The badge keeps its aria-label, so the rank is still named. */
1153
+ @media (max-width: 640px) {
1154
+ .rank-tip { display: none; }
1155
+ }
1156
+
1066
1157
  /* ---------- karma / acclaim ---------- */
1067
1158
 
1068
1159
  .karma-badge__trend { font-variant-numeric: tabular-nums; }
@@ -1586,35 +1677,6 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
1586
1677
  .ranks-rise__body { font-size: 13.5px; }
1587
1678
  .ranks-rise__body p { margin: 8px 0; }
1588
1679
 
1589
- /* ---------- security / roster / admin leftovers ---------- */
1590
-
1591
- .sev-badge {
1592
- display: inline-flex;
1593
- align-items: center;
1594
- height: 20px;
1595
- padding: 0 9px;
1596
- border-radius: 999px;
1597
- font-size: 11.5px;
1598
- font-weight: 600;
1599
- }
1600
- .sev-low { background: var(--surface-2); color: var(--ink-soft); }
1601
- .sev-medium { background: var(--info-weak); color: var(--info); }
1602
- .sev-high { background: var(--warn-weak); color: var(--warn); }
1603
- .sev-critical { background: var(--danger-weak); color: var(--danger); }
1604
-
1605
- .security-audit-details summary { cursor: pointer; font-weight: 600; font-size: 13.5px; }
1606
- .override__rationale { font-size: 12.5px; color: var(--ink-soft); }
1607
-
1608
- .roster__stale { color: var(--warn); }
1609
- .roster__inactive { color: var(--ink-faint); }
1610
- .roster__self { font-weight: 600; }
1611
- #roster-table td:last-child { white-space: nowrap; }
1612
- #roster-table td:last-child button { margin-left: 6px; }
1613
-
1614
- .skill-prefs__select { min-width: 160px; }
1615
- .skill-prefs__default { color: var(--ink-faint); }
1616
- .voices__select { min-width: 160px; }
1617
-
1618
1680
  /* ---------- toast + copy toast + deep-link overlay ---------- */
1619
1681
 
1620
1682
  .toast {
@@ -1718,7 +1780,9 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
1718
1780
  overflow-y: auto;
1719
1781
  }
1720
1782
  .td-touches { font-size: 12.5px; color: var(--ink-faint); word-break: break-word; margin: 0 0 12px; }
1721
- .td-section-h { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-faint); margin: 0 0 4px; }
1783
+ /* Shared small-caps label: overlay section heads and triage form-field labels. */
1784
+ .td-section-h, .td-field > span { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-faint); }
1785
+ .td-section-h { margin: 0 0 4px; }
1722
1786
  .td-deps { margin: 0 0 12px; }
1723
1787
  .td-dep-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 3px; }
1724
1788
  .td-dep { font-size: 13px; color: var(--accent-text); text-decoration: none; }
@@ -1741,6 +1805,30 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
1741
1805
  .td-btn:disabled { opacity: 0.6; cursor: default; }
1742
1806
  .td-action-note { flex-basis: 100%; font-size: 12.5px; color: var(--warn); margin: 4px 0 0; }
1743
1807
 
1808
+ /* Idea triage inside the record overlay (task 1002447). A two-column grid so
1809
+ promote's five fields fit the panel without scrolling; --wide spans both. */
1810
+ .td-form { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 10px; margin: 14px 0 0; }
1811
+ .td-field { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
1812
+ .td-field--wide { grid-column: 1 / -1; }
1813
+ .td-field input, .td-field select {
1814
+ font: inherit;
1815
+ font-size: 13px;
1816
+ padding: 5px 8px;
1817
+ border: 1px solid var(--border-strong);
1818
+ border-radius: var(--radius-sm);
1819
+ background: var(--surface);
1820
+ color: var(--ink);
1821
+ min-width: 0;
1822
+ max-width: 100%;
1823
+ }
1824
+ .td-form .td-actions, .td-form-hint, .td-form .td-action-note { grid-column: 1 / -1; }
1825
+ .td-form .td-actions { margin: 4px 0 0; }
1826
+ .td-form-hint { font-size: 12.5px; color: var(--ink-soft); margin: 0; }
1827
+
1828
+ @media (max-width: 460px) {
1829
+ .td-form { grid-template-columns: 1fr; }
1830
+ }
1831
+
1744
1832
  /* ---------- misc shared bits ---------- */
1745
1833
 
1746
1834
  .vgoal { border: 1px solid var(--border); border-radius: var(--radius); }
@@ -1945,3 +2033,107 @@ a.stat-tile:hover {
1945
2033
  .next-up__title:hover { color: var(--accent-text); }
1946
2034
  .next-up__meta { font-size: 12px; color: var(--ink-faint); font-variant-numeric: tabular-nums; }
1947
2035
  .next-up__foot { margin: 0 0 14px; font-size: 13px; }
2036
+
2037
+ /* ---------- jump palette (task 2178) ----------
2038
+ The top-bar slot + the Ctrl/Cmd-K overlay. Styled from existing tokens only —
2039
+ no new theme vars, so dark mode follows the neutral flip for free. The overlay
2040
+ mirrors .deeplink-card's posture (fixed scrim + centred panel, z above the
2041
+ drawer) so the two modal surfaces read as one system. */
2042
+ .topbar-jump {
2043
+ display: inline-flex;
2044
+ align-items: center;
2045
+ gap: 8px;
2046
+ height: 32px;
2047
+ padding: 0 10px;
2048
+ border: 1px solid var(--border);
2049
+ border-radius: var(--radius-sm);
2050
+ background: var(--surface);
2051
+ color: var(--ink-faint);
2052
+ font: inherit;
2053
+ font-size: 13px;
2054
+ cursor: pointer;
2055
+ min-width: 0;
2056
+ }
2057
+ .topbar-jump:hover { color: var(--ink-soft); border-color: var(--ink-faint); }
2058
+ .topbar-jump svg { width: 15px; height: 15px; flex-shrink: 0; }
2059
+ .topbar-jump__label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
2060
+ .topbar-jump__kbd {
2061
+ font-family: inherit;
2062
+ font-size: 11px;
2063
+ color: var(--ink-faint);
2064
+ border: 1px solid var(--border);
2065
+ border-radius: 4px;
2066
+ padding: 1px 5px;
2067
+ white-space: nowrap;
2068
+ }
2069
+
2070
+ .palette { position: fixed; inset: 0; z-index: 2100; }
2071
+ .palette__scrim { position: absolute; inset: 0; background: color-mix(in srgb, var(--ink) 45%, transparent); }
2072
+ .palette__panel {
2073
+ position: relative;
2074
+ margin: 10vh auto 0;
2075
+ max-width: 560px;
2076
+ width: calc(100% - 32px);
2077
+ background: var(--surface);
2078
+ border: 1px solid var(--border);
2079
+ border-radius: var(--radius);
2080
+ box-shadow: var(--shadow-pop);
2081
+ overflow: hidden;
2082
+ }
2083
+ .palette__input {
2084
+ width: 100%;
2085
+ box-sizing: border-box;
2086
+ border: none;
2087
+ border-bottom: 1px solid var(--border);
2088
+ background: transparent;
2089
+ color: var(--ink);
2090
+ font: inherit;
2091
+ font-size: 15px;
2092
+ padding: 14px 16px;
2093
+ outline: none;
2094
+ }
2095
+ .palette__input::placeholder { color: var(--ink-faint); }
2096
+ .palette__list {
2097
+ list-style: none;
2098
+ margin: 0;
2099
+ padding: 6px;
2100
+ max-height: 50vh;
2101
+ overflow-y: auto;
2102
+ }
2103
+ .palette__item {
2104
+ display: flex;
2105
+ align-items: baseline;
2106
+ gap: 10px;
2107
+ padding: 8px 10px;
2108
+ border-radius: var(--radius-sm);
2109
+ cursor: pointer;
2110
+ }
2111
+ .palette__item--active { background: var(--accent-weak); }
2112
+ .palette__group {
2113
+ font-size: 11px;
2114
+ letter-spacing: 0.04em;
2115
+ text-transform: uppercase;
2116
+ color: var(--ink-faint);
2117
+ flex-shrink: 0;
2118
+ min-width: 68px;
2119
+ }
2120
+ .palette__label { font-size: 13.5px; color: var(--ink); }
2121
+ .palette__item--active .palette__label { color: var(--accent-text); font-weight: 600; }
2122
+ .palette__hint, .palette__empty { font-size: 12px; color: var(--ink-faint); }
2123
+ .palette__empty { padding: 14px 12px; line-height: 1.6; }
2124
+ .palette__empty kbd {
2125
+ font-family: inherit;
2126
+ border: 1px solid var(--border);
2127
+ border-radius: 4px;
2128
+ padding: 0 4px;
2129
+ }
2130
+ html.palette-open { overflow: hidden; }
2131
+
2132
+ @media (max-width: 768px) {
2133
+ /* The slot keeps its icon as an affordance; the label + hint would crowd the
2134
+ title on a phone. Ctrl/Cmd-K still opens it on a keyboard. */
2135
+ .topbar-jump__label, .topbar-jump__kbd { display: none; }
2136
+ .topbar-jump { padding: 0 8px; }
2137
+ .palette__panel { margin-top: 6vh; }
2138
+ .palette__group { min-width: 56px; }
2139
+ }