@bongos/core 1.21.113 → 1.21.114

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 (260) hide show
  1. package/.bongos-core.json +603 -183
  2. package/.claude/skills/ask-for-help/SKILL.md +1 -1
  3. package/.claude/skills/bongos-feedback/SKILL.md +1 -1
  4. package/.claude/skills/builder-sequence/SKILL.md +1 -1
  5. package/.claude/skills/builder-ship/SKILL.md +1 -0
  6. package/GOVERNMENT.md +128 -11
  7. package/clients/bongos-client/README.md +1 -1
  8. package/clients/bongos-client/bongos-client.global.js +28 -0
  9. package/clients/bongos-client/index.cjs +28 -0
  10. package/clients/bongos-client/index.d.ts +45 -2
  11. package/clients/bongos-client/index.mjs +28 -0
  12. package/docs/adr/0372-an-ask-is-stored-per-docket-matter-and-the-server-refuses-slop.md +33 -0
  13. package/docs/adr/0373-an-ai-session-files-a-blocker-with-an-ask.md +31 -0
  14. package/docs/adr/0374-a-building-lead-is-a-held-position-appointed-by-a-people-matter.md +30 -0
  15. package/docs/adr/0375-who-may-build-without-a-vote-comes-from-the-form-of-government.md +38 -0
  16. package/docs/adr/0376-every-ask-is-routed-to-a-real-seat-on-the-server.md +30 -0
  17. package/docs/adr/0377-governance-is-a-held-position-read-on-me.md +24 -0
  18. package/docs/adr/0378-a-leads-build-outs-are-rows-built-at-once-or-by-a-passed-vote.md +33 -0
  19. package/docs/adr/0379-the-treasury-is-pots-per-goal-a-reserve-and-borrowing-over-real-spend.md +32 -0
  20. package/docs/adr/0380-a-strictness-preset-is-a-bundle-of-laws-switched-by-one-laws-vote.md +26 -0
  21. package/docs/adr/README.md +10 -1
  22. package/docs/api/openapi.json +989 -87
  23. package/docs/api-reference.md +18 -4
  24. package/docs/copy-inventory.md +343 -262
  25. package/docs/copy-registry.json +1223 -426
  26. package/docs/file-map.md +2 -1
  27. package/docs/module-api-changelog.md +2 -0
  28. package/docs/packs/engineer.md +2 -1
  29. package/docs/page-inventory.json +91 -6
  30. package/docs/page-readings.json +5017 -4458
  31. package/modules/builder-settings/law-locks.js +202 -0
  32. package/modules/builder-settings/routes/settings.js +66 -6
  33. package/modules/builder-settings/settings.js +7 -0
  34. package/modules/discord/ship-broadcast.js +22 -13
  35. package/modules/government/asks-db.js +54 -0
  36. package/modules/government/asks.js +269 -0
  37. package/modules/government/board-idea-reads.js +68 -0
  38. package/modules/government/board.js +21 -57
  39. package/modules/government/build-rights.js +148 -0
  40. package/modules/government/buildouts.js +160 -0
  41. package/modules/government/counts.js +81 -0
  42. package/modules/government/db.js +242 -0
  43. package/modules/government/decision-board.js +234 -8
  44. package/modules/government/decision-rules.js +2 -0
  45. package/modules/government/docket.js +114 -6
  46. package/modules/government/law-board.js +131 -0
  47. package/modules/government/laws.js +241 -0
  48. package/modules/government/leads.js +170 -0
  49. package/modules/government/migrations/government_027_laws.sql +143 -0
  50. package/modules/government/migrations/government_028_asks.sql +57 -0
  51. package/modules/government/migrations/government_029_leads.sql +135 -0
  52. package/modules/government/migrations/government_030_buildouts.sql +111 -0
  53. package/modules/government/migrations/government_031_treasury.sql +107 -0
  54. package/modules/government/module.json +2 -1
  55. package/modules/government/pollers/treasury-borrow.js +62 -0
  56. package/modules/government/positions.js +107 -0
  57. package/modules/government/presets.js +149 -0
  58. package/modules/government/routes/government.js +425 -2
  59. package/modules/government/routing.js +154 -0
  60. package/modules/government/treasury-db.js +166 -0
  61. package/modules/government/treasury.js +241 -0
  62. package/modules/hall-ui/public/atlas.html +2 -2
  63. package/modules/hall-ui/public/blockers.html +2 -2
  64. package/modules/hall-ui/public/board-room.html +2 -2
  65. package/modules/hall-ui/public/board-room.js +2 -0
  66. package/modules/hall-ui/public/city-draw.js +604 -11
  67. package/modules/hall-ui/public/city.css +157 -1
  68. package/modules/hall-ui/public/city.html +37 -7
  69. package/modules/hall-ui/public/city.js +441 -21
  70. package/modules/hall-ui/public/city.states.json +110 -5
  71. package/modules/hall-ui/public/collab.html +2 -2
  72. package/modules/hall-ui/public/commands.html +2 -2
  73. package/modules/hall-ui/public/copy-desk.html +2 -2
  74. package/modules/hall-ui/public/craft-mode.js +112 -29
  75. package/modules/hall-ui/public/deploy.html +2 -2
  76. package/modules/hall-ui/public/diagram-viewer.css +12 -0
  77. package/modules/hall-ui/public/diagram-viewer.js +4 -0
  78. package/modules/hall-ui/public/diagrams.html +2 -2
  79. package/modules/hall-ui/public/drachmae.html +2 -2
  80. package/modules/hall-ui/public/fleet.html +2 -2
  81. package/modules/hall-ui/public/gate.html +2 -2
  82. package/modules/hall-ui/public/goal-map.html +2 -2
  83. package/modules/hall-ui/public/goals.html +2 -2
  84. package/modules/hall-ui/public/gov-feeds.js +141 -0
  85. package/modules/hall-ui/public/gov-living.js +1002 -0
  86. package/modules/hall-ui/public/gov-positions.js +97 -0
  87. package/modules/hall-ui/public/government.html +2 -2
  88. package/modules/hall-ui/public/hall-render.js +3 -0
  89. package/modules/hall-ui/public/idea.html +2 -2
  90. package/modules/hall-ui/public/ideas.html +2 -2
  91. package/modules/hall-ui/public/index.html +3 -3
  92. package/modules/hall-ui/public/modules.html +2 -2
  93. package/modules/hall-ui/public/my-agents.css +334 -0
  94. package/modules/hall-ui/public/my-agents.html +72 -0
  95. package/modules/hall-ui/public/my-agents.js +603 -0
  96. package/modules/hall-ui/public/my-agents.states.json +37 -0
  97. package/modules/hall-ui/public/primer.html +2 -2
  98. package/modules/hall-ui/public/profile-connections.js +40 -28
  99. package/modules/hall-ui/public/profile.html +2 -2
  100. package/modules/hall-ui/public/project-settings.html +2 -2
  101. package/modules/hall-ui/public/ranks.html +2 -2
  102. package/modules/hall-ui/public/roadmap.html +2 -2
  103. package/modules/hall-ui/public/room.css +8 -0
  104. package/modules/hall-ui/public/roster.html +2 -2
  105. package/modules/hall-ui/public/sessions.html +2 -2
  106. package/modules/hall-ui/public/settings.html +2 -2
  107. package/modules/hall-ui/public/shell.js +116 -16
  108. package/modules/hall-ui/public/street-card.js +18 -1
  109. package/modules/hall-ui/public/street-deck.css +299 -0
  110. package/modules/hall-ui/public/street-deck.js +1145 -0
  111. package/modules/hall-ui/public/street-depth.js +712 -0
  112. package/modules/hall-ui/public/street-desk.js +5 -2
  113. package/modules/hall-ui/public/street-draw.js +109 -16
  114. package/modules/hall-ui/public/street-inside.js +137 -22
  115. package/modules/hall-ui/public/street-office.js +705 -0
  116. package/modules/hall-ui/public/street.css +161 -11
  117. package/modules/hall-ui/public/street.html +41 -11
  118. package/modules/hall-ui/public/street.js +78 -66
  119. package/modules/hall-ui/public/street.states.json +129 -21
  120. package/modules/hall-ui/public/studio.html +2 -2
  121. package/modules/hall-ui/public/style.css +5 -1
  122. package/modules/hall-ui/public/task.html +2 -2
  123. package/modules/hall-ui/public/thinking.html +2 -2
  124. package/modules/hall-ui/public/tweak-editor.html +2 -2
  125. package/modules/hall-ui/public/watch.html +2 -2
  126. package/modules/hall-ui/public/watch.js +14 -1
  127. package/modules/hall-ui/public/work.html +2 -2
  128. package/modules/hall-ui/records/living-city.md +57 -0
  129. package/modules/hall-ui/records/my-agents.md +21 -0
  130. package/modules/hall-ui/records/oversight-family.md +1 -0
  131. package/modules/hall-ui/records/profile-connections.md +10 -0
  132. package/modules/hall-ui/records/reading-rooms.md +2 -0
  133. package/modules/ideas/routes/blockers.js +92 -3
  134. package/modules/lifecycle/module.json +2 -1
  135. package/modules/lifecycle/moving.js +17 -1
  136. package/modules/lifecycle/routes/moving.js +6 -0
  137. package/modules/lifecycle/routes/project-settings.js +23 -0
  138. package/modules/onboarding/approval-broadcast.js +8 -0
  139. package/modules/onboarding/routes/access-requests.js +16 -6
  140. package/modules/platform-identity/connections.js +13 -2
  141. package/modules/platform-identity/routes/connections.js +7 -1
  142. package/modules/public-landing/public/account-private.states.json +2 -2
  143. package/modules/public-landing/public/account.html +65 -5
  144. package/modules/public-landing/public/account.states.json +3 -3
  145. package/modules/public-landing/public/assets/world/r2-bongos-chrome-b.jpg.json +1 -1
  146. package/modules/public-landing/public/assets/world/r2-bongos-chrome-b.webp +0 -0
  147. package/modules/public-landing/public/assets/world/r2-bongos-chrome-b.webp.json +13 -0
  148. package/modules/public-landing/public/assets/world/r2-chrome-blob-one.jpg.json +1 -1
  149. package/modules/public-landing/public/assets/world/r2-chrome-blob-one.webp +0 -0
  150. package/modules/public-landing/public/assets/world/r2-chrome-blob-one.webp.json +13 -0
  151. package/modules/public-landing/public/assets/world/r2-chrome-blobs-set.jpg.json +1 -1
  152. package/modules/public-landing/public/assets/world/r2-chrome-blobs-set.webp +0 -0
  153. package/modules/public-landing/public/assets/world/r2-chrome-blobs-set.webp.json +13 -0
  154. package/modules/public-landing/public/assets/world.css +4 -4
  155. package/modules/public-landing/public/connections-empty.states.json +14 -0
  156. package/modules/public-landing/public/connections-inactive.states.json +14 -0
  157. package/modules/public-landing/public/connections.html +450 -0
  158. package/modules/public-landing/public/connections.probes.json +414 -0
  159. package/modules/public-landing/public/connections.states.json +17 -0
  160. package/modules/public-landing/public/contact.html +2 -2
  161. package/modules/public-landing/public/guild.html +2 -2
  162. package/modules/public-landing/public/index.html +2 -2
  163. package/modules/public-landing/public/invitations.html +2 -2
  164. package/modules/public-landing/public/privacy.html +2 -2
  165. package/modules/public-landing/public/projects.html +2 -2
  166. package/modules/public-landing/public/projects.probes.json +6 -2
  167. package/modules/public-landing/public/terms.html +2 -2
  168. package/modules/ui-design/kit/fixtures/connections-empty.json +12 -0
  169. package/modules/ui-design/kit/fixtures/connections-inactive.json +7 -0
  170. package/modules/ui-design/kit/fixtures/connections.json +22 -0
  171. package/modules/ui-design/kit/serve.js +95 -0
  172. package/package-lock.json +2 -2
  173. package/package.json +1 -1
  174. package/release-notes.json +122 -0
  175. package/scripts/discord/README.md +8 -5
  176. package/scripts/discord/post.js +12 -1
  177. package/scripts/gds/artifact-audit.js +20 -3
  178. package/scripts/gds/ask.js +164 -0
  179. package/scripts/gds/autobongos-verify.js +21 -2
  180. package/scripts/gds/government-walk.js +638 -4
  181. package/scripts/gds/pulse.js +9 -6
  182. package/scripts/gds/ship-escalation.js +22 -3
  183. package/scripts/gds/ship-finish.js +5 -4
  184. package/scripts/gds/ship-merge-gate.js +18 -6
  185. package/scripts/hall-preview/README.md +41 -1
  186. package/scripts/hall-preview/pref-writes.js +140 -0
  187. package/scripts/hall-preview/refresh-fixtures.js +101 -7
  188. package/scripts/hall-preview/scrub-identity.js +366 -7
  189. package/scripts/hall-preview/server.js +27 -1
  190. package/scripts/render-diagrams.sh +4 -2
  191. package/src/bongos/auth-idp.js +6 -1
  192. package/src/bongos/project-settings.js +41 -0
  193. package/src/bongos/route-rank-check.js +27 -0
  194. package/src/bongos/routes/me.js +68 -7
  195. package/src/bongos/serve-internal.js +5 -1
  196. package/src/module-api.js +7 -1
  197. package/src/platform-server.js +10 -0
  198. package/tests/application_lifecycle.mjs +47 -5
  199. package/tests/conductor_main_e2e.mjs +21 -0
  200. package/tests/connections_api.mjs +18 -0
  201. package/tests/craft_mode_nav.mjs +5 -3
  202. package/tests/craft_mode_tallies.mjs +52 -16
  203. package/tests/discord_approvals.mjs +11 -0
  204. package/tests/discord_channels.mjs +20 -0
  205. package/tests/fixtures/gov-seated.mjs +64 -0
  206. package/tests/fixtures/government-ask-cards.json +1284 -0
  207. package/tests/government_act_alone_buildings.mjs +1 -0
  208. package/tests/government_agent_asks.mjs +322 -0
  209. package/tests/government_asks.mjs +408 -0
  210. package/tests/government_build_rights.mjs +253 -0
  211. package/tests/government_buildouts.mjs +382 -0
  212. package/tests/government_counts.mjs +143 -0
  213. package/tests/government_decision_rules.mjs +5 -1
  214. package/tests/government_laws.mjs +488 -0
  215. package/tests/government_laws_session.mjs +321 -0
  216. package/tests/government_leads.mjs +375 -0
  217. package/tests/government_positions.mjs +127 -0
  218. package/tests/government_presets.mjs +215 -0
  219. package/tests/government_routes.mjs +8 -1
  220. package/tests/government_routing.mjs +118 -0
  221. package/tests/government_seed.mjs +5 -0
  222. package/tests/government_treasury.mjs +394 -0
  223. package/tests/governor_docket.mjs +26 -2
  224. package/tests/hall_buildouts.mjs +208 -0
  225. package/tests/hall_city.mjs +14 -6
  226. package/tests/hall_city_living.mjs +617 -0
  227. package/tests/hall_gov_counts.mjs +336 -0
  228. package/tests/hall_gov_living.mjs +636 -0
  229. package/tests/hall_gov_real_site.mjs +655 -0
  230. package/tests/hall_matter_card.mjs +6 -1
  231. package/tests/hall_my_agents.mjs +481 -0
  232. package/tests/hall_nav.mjs +107 -4
  233. package/tests/hall_page_gate_map.mjs +4 -0
  234. package/tests/hall_preview_governor_fixtures.mjs +30 -3
  235. package/tests/hall_preview_scrub.mjs +59 -1
  236. package/tests/hall_preview_security.mjs +169 -0
  237. package/tests/hall_reading_world.mjs +44 -0
  238. package/tests/hall_roster_world.mjs +6 -2
  239. package/tests/hall_street.mjs +18 -2
  240. package/tests/hall_street_amend.mjs +1 -1
  241. package/tests/hall_street_deck.mjs +609 -0
  242. package/tests/hall_street_depth.mjs +559 -0
  243. package/tests/hall_street_desk.mjs +1 -1
  244. package/tests/hall_street_inside.mjs +29 -5
  245. package/tests/hall_tweak_editor.mjs +4 -1
  246. package/tests/hub_account_page.mjs +94 -3
  247. package/tests/hub_connections_page.mjs +507 -0
  248. package/tests/hub_invite_badge.mjs +1 -1
  249. package/tests/idp_device_exchange.mjs +18 -0
  250. package/tests/landing_legal_pages.mjs +8 -5
  251. package/tests/landing_page.mjs +23 -4
  252. package/tests/nav_permission_atoms.mjs +4 -1
  253. package/tests/profile_connections_ui.mjs +88 -25
  254. package/tests/projects_hub.mjs +15 -0
  255. package/tests/render_check.mjs +2 -2
  256. package/tests/ship_broadcast_routing.mjs +57 -16
  257. package/tests/ship_broadcast_server.mjs +40 -7
  258. package/tests/ship_merge_gate.mjs +19 -0
  259. package/tests/ui_design_kit.mjs +2 -2
  260. package/tests/watch_applications_queue.mjs +23 -0
@@ -18,6 +18,20 @@ body[data-page="city"] {
18
18
  --city-glow: none;
19
19
  --city-crate: color-mix(in srgb, var(--ink) 7%, transparent);
20
20
  --city-crate-edge: color-mix(in srgb, var(--ink) 55%, transparent);
21
+ /* THE LIVING CITY (task 1004685). Paper cannot glow, so in light every glow
22
+ is an ink wash and a lit window is ink-filled; the dark twins below turn
23
+ the same names into light in the black. Salmon (the accent) is spent only
24
+ on what waits on the viewer: its windows, its pins and their age rings. */
25
+ --city-win-lit: color-mix(in srgb, var(--ink) 58%, transparent);
26
+ --city-shaft: color-mix(in srgb, var(--ink) 8%, transparent);
27
+ --city-shaft-ring: color-mix(in srgb, var(--ink) 34%, transparent);
28
+ --city-pod-hi: color-mix(in srgb, var(--ink) 62%, var(--bg));
29
+ --city-pod-lo: var(--ink);
30
+ --city-lane: color-mix(in srgb, var(--ink) 32%, transparent);
31
+ --city-conduit: color-mix(in srgb, var(--sea) 62%, transparent);
32
+ --city-hover: brightness(.96);
33
+ --city-crane: color-mix(in srgb, var(--ink) 62%, transparent);
34
+ --city-ghost-edge: color-mix(in srgb, var(--sea) 72%, transparent);
21
35
  /* the hall's ground plate and its dark veil (style.css body::before/::after) are
22
36
  the hall chrome's; the city is its own ground, so both are off here */
23
37
  --plate: none;
@@ -32,11 +46,31 @@ body[data-page="city"] {
32
46
  html[data-theme="dark"] body[data-page="city"] {
33
47
  --city-contact: none;
34
48
  --city-glow: 0 0 18px color-mix(in srgb, var(--accent) 50%, transparent);
49
+ --city-win-lit: color-mix(in srgb, var(--ink) 40%, transparent);
50
+ --city-shaft: color-mix(in srgb, var(--ink) 14%, transparent);
51
+ --city-shaft-ring: color-mix(in srgb, var(--ink) 48%, transparent);
52
+ --city-pod-hi: var(--ink);
53
+ --city-pod-lo: color-mix(in srgb, var(--ink) 42%, var(--bg));
54
+ --city-lane: color-mix(in srgb, var(--ink) 28%, transparent);
55
+ --city-conduit: color-mix(in srgb, var(--sea) 78%, transparent);
56
+ --city-hover: brightness(1.4);
57
+ --city-crane: color-mix(in srgb, var(--ink) 70%, transparent);
58
+ --city-ghost-edge: color-mix(in srgb, var(--sea) 55%, var(--ink));
35
59
  }
36
60
  @media (prefers-color-scheme: dark) {
37
61
  html:not([data-theme]) body[data-page="city"] {
38
62
  --city-contact: none;
39
63
  --city-glow: 0 0 18px color-mix(in srgb, var(--accent) 50%, transparent);
64
+ --city-win-lit: color-mix(in srgb, var(--ink) 40%, transparent);
65
+ --city-shaft: color-mix(in srgb, var(--ink) 14%, transparent);
66
+ --city-shaft-ring: color-mix(in srgb, var(--ink) 48%, transparent);
67
+ --city-pod-hi: var(--ink);
68
+ --city-pod-lo: color-mix(in srgb, var(--ink) 42%, var(--bg));
69
+ --city-lane: color-mix(in srgb, var(--ink) 28%, transparent);
70
+ --city-conduit: color-mix(in srgb, var(--sea) 78%, transparent);
71
+ --city-hover: brightness(1.4);
72
+ --city-crane: color-mix(in srgb, var(--ink) 70%, transparent);
73
+ --city-ghost-edge: color-mix(in srgb, var(--sea) 55%, var(--ink));
40
74
  }
41
75
  }
42
76
  html:has(body[data-page="city"]) { height: 100%; }
@@ -74,7 +108,8 @@ html[data-fullscreen="on"] .city-top { right: 184px; }
74
108
 
75
109
  /* parcels: crates riding the ring road on offset-path */
76
110
  .city-parcel { position: absolute; left: 0; top: 0; width: 9px; height: 7px; margin: -4px 0 0 -5px; box-sizing: border-box; border-radius: 2px; background: var(--city-crate); border: 1px solid var(--city-crate-edge); offset-rotate: 0deg; }
77
- .city-parcel--out { background: var(--accent); border-color: var(--accent); }
111
+ /* work leaving through Release is live, not yours to answer: ink, not salmon (task 1004685) */
112
+ .city-parcel--out { background: var(--ink-soft); border-color: var(--ink-soft); }
78
113
 
79
114
  /* pins: orange and pulsing waits on you; ink and bobbing is moving; grey is settled */
80
115
  .city-pin { position: absolute; width: 30px; height: 52px; display: flex; flex-direction: column; align-items: center; }
@@ -110,6 +145,100 @@ html[data-fullscreen="on"] .city-top { right: 184px; }
110
145
  .city-door { bottom: 40px; padding: 0 16px; }
111
146
  }
112
147
 
148
+ /* ======================================================================
149
+ THE LIVING CITY (task 1004685): three levels, each with one meaning.
150
+ ====================================================================== */
151
+
152
+ /* ground: the spend conduit, in the reserve blue; the trunk's width is the
153
+ real spend rate, a spur's its pot's share; a dry pot's spur is starved */
154
+ .city-conduit { fill: none; stroke: var(--city-conduit); stroke-linecap: round; stroke-linejoin: round; }
155
+ .city-conduit--dry { stroke: color-mix(in srgb, var(--sea) 50%, transparent); }
156
+
157
+ /* civic: windows. Ink for how busy a building is; salmon only for what waits on you */
158
+ .city-win--lit { fill: var(--city-win-lit); }
159
+ .city-win--you { fill: var(--accent); }
160
+ /* the council's tally over a ghost annex: a dot per seat, filled as they vote */
161
+ .city-tally--yes { fill: var(--ink); }
162
+ .city-tally--no { fill: var(--ink-faint); }
163
+ .city-tally--open { fill: none; stroke: var(--ink-soft); stroke-width: 1; }
164
+
165
+ /* sky: one dotted lane per building-to-district route, one chrome pod per agent;
166
+ a dry pot's reserve-borrow beacon */
167
+ .city-lane { fill: none; stroke: var(--city-lane); stroke-width: 2; stroke-dasharray: 0.1 7; stroke-linecap: round; }
168
+ .city-beacon { fill: var(--sea); stroke: none; }
169
+ .city-beacon--stem { fill: none; stroke: var(--sea); }
170
+ .city-beacon--ring { fill: none; stroke: color-mix(in srgb, var(--sea) 60%, transparent); }
171
+ .city-sky, .city-hits { position: absolute; left: 0; top: 0; width: 1440px; height: 900px; pointer-events: none; }
172
+ .city-pod { position: absolute; left: 0; top: 0; width: 11px; height: 5px; margin: -2.5px 0 0 -5.5px; box-sizing: border-box; border-radius: 999px; background: linear-gradient(180deg, var(--city-pod-hi), var(--city-pod-lo)); box-shadow: 0 0 0 1px color-mix(in srgb, var(--bg) 55%, transparent); offset-rotate: auto; offset-distance: var(--pod-at, 30%); }
173
+
174
+ .city-lane__more { position: absolute; transform: translate(-50%, -150%); font-size: 10.5px; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--ink-soft); }
175
+
176
+ /* an open sitting: a light shaft from the roof, a ring rising slowly through it */
177
+ .city-shaft { position: absolute; width: 30px; margin-left: -15px; overflow: hidden; background: linear-gradient(to top, var(--city-shaft), transparent); -webkit-mask-image: linear-gradient(to top, #000 0%, #000 50%, transparent 100%); mask-image: linear-gradient(to top, #000 0%, #000 50%, transparent 100%); }
178
+ .city-shaft__ring { position: absolute; left: 0; right: 0; bottom: 0; height: 10px; margin-bottom: -5px; box-sizing: border-box; border-radius: 50%; border: 1px solid var(--city-shaft-ring); transform: translateY(-34px); }
179
+
180
+ /* each building's Lead, or "owner" where it has none (GET /government/leads) */
181
+ .city-plate { position: absolute; transform: translateY(-50%); height: 18px; padding: 0 8px; box-sizing: border-box; border-radius: 999px; border: 1px solid var(--rule-soft); background: color-mix(in srgb, var(--bg) 78%, transparent); font-family: var(--font-body); font-size: 11px; font-weight: 500; line-height: 16px; white-space: nowrap; color: var(--ink-soft); }
182
+ .city-plate--owner { border-style: dashed; color: var(--ink-faint); visibility: hidden; }
183
+ /* "owner" is the absence of a Lead: it shows only while its building is pointed
184
+ at, focused or open (city.js), so the seated Leads read at a glance */
185
+ .city-plate--owner.city-plate--shown { visibility: visible; }
186
+
187
+ /* construction reads at a glance, the street's family: a solid lattice crane and
188
+ a firmer scaffold over the live site; the ghost annex a crisp dashed glass */
189
+ .city-crane path, .city-jib path { stroke: var(--city-crane); stroke-width: 1.3; }
190
+ .city-scaffold path { stroke: var(--city-crane); stroke-width: 1.1; }
191
+ .city-ghost path { stroke: var(--city-ghost-edge); stroke-width: 1.2; }
192
+
193
+ /* the building you tap. A pointer finds it by its own painted faces (the one in
194
+ front wins, as the eye sees it), its pin or its plate; the button over its
195
+ core is the keyboard's and the screen reader's way in, and where the card is
196
+ placed beside. */
197
+ .city-blds g[data-civic] { pointer-events: visiblePainted; cursor: pointer; }
198
+ .city-blds g[data-civic]:hover { filter: var(--city-hover); }
199
+ .city-pin__head, .city-plate { pointer-events: auto; cursor: pointer; }
200
+ .city-hit { position: absolute; margin: 0; padding: 0; border: 0; border-radius: 14px; background: transparent; pointer-events: none; }
201
+ .city-hit:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
202
+
203
+ /* the pins' age ring: how long the oldest ask on you has waited, full at two weeks */
204
+ .city-pin__age { position: absolute; left: -6px; top: -6px; width: calc(100% + 12px); height: calc(100% + 12px); transform: rotate(-90deg); overflow: visible; }
205
+ .city-pin__age-track { fill: none; stroke: color-mix(in srgb, var(--accent) 24%, transparent); stroke-width: 2; }
206
+ .city-pin__age-arc { fill: none; stroke: var(--accent); stroke-width: 2; stroke-linecap: round; }
207
+
208
+ /* the gate plaque: the government at a glance, one number and two words a tile */
209
+ .city-plaque { position: absolute; left: 32px; top: 62px; z-index: 3; display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 20px; max-width: calc(100% - 64px); }
210
+ .city-plaque[hidden] { display: none; }
211
+ .city-plaque__tile { display: inline-flex; align-items: baseline; gap: 7px; }
212
+ .city-plaque__figure { font-size: 22px; font-weight: 300; letter-spacing: -0.03em; line-height: 1.1; font-variant-numeric: tabular-nums; color: var(--ink); }
213
+ .city-plaque__words { font-family: var(--label-face); font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-faint); }
214
+ .city-plaque__tile[data-key="you"] .city-plaque__figure { color: var(--accent-deep); }
215
+
216
+ /* the card a building opens in place, in the desk line: who, one fact, its count, two doors */
217
+ /* the building's card (task 1004702): a glass panel beside the building, the
218
+ glass and its tokens street-deck.css's (the ask inside is the deck's card) */
219
+ .city-card { position: absolute; left: 50%; top: 96px; z-index: 8; width: min(432px, calc(100% - 32px)); max-height: calc(100% - 80px); overflow-y: auto; box-sizing: border-box; display: flex; flex-direction: column; gap: 16px; padding: 22px 24px 18px; border-radius: 28px; color: var(--ink); }
220
+ .city-card[hidden] { display: none; }
221
+ .city-card__head { display: flex; flex-direction: column; gap: 4px; }
222
+ .city-card__top { display: flex; align-items: center; gap: 10px; }
223
+ .city-card__name { flex: 1; min-width: 0; margin: 0; font-size: 24px; font-weight: 400; letter-spacing: -0.02em; }
224
+ .city-card__close { flex: none; display: inline-flex; background: none; border: 0; padding: 0; min-width: 24px; min-height: 24px; cursor: pointer; }
225
+ .city-card__f { margin: 0; font-size: 14px; line-height: 1.45; color: var(--ink-soft); }
226
+ .city-card__count--you { color: var(--you-ink); }
227
+ .city-card__said { margin: -4px 0 0; font-size: 13.5px; line-height: 1.45; color: var(--ink-soft); }
228
+ .city-card__close:focus-visible, .city-card__go:focus-visible, .city-card__enter:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
229
+ .city-card__acts { display: flex; align-items: center; gap: 14px; }
230
+ .city-card__go { display: inline-flex; align-items: center; height: 46px; padding: 0 22px; box-sizing: border-box; border-radius: 999px; font-size: 15px; text-decoration: none; background: var(--ink); color: var(--bg); }
231
+ .city-card__enter { display: inline-flex; align-items: center; min-height: 24px; font-size: 15px; color: var(--ink); text-decoration: underline; text-underline-offset: 4px; text-decoration-color: color-mix(in srgb, var(--ink) 35%, transparent); }
232
+ .city-spot { z-index: 7; }
233
+
234
+ @media (max-width: 640px) {
235
+ /* the plates are in the card on a phone; the card is a sheet along the foot */
236
+ .city-plate { display: none; }
237
+ .city-card { left: 12px !important; right: 12px; top: auto !important; bottom: 12px; width: auto; max-height: 72%; overflow-y: auto; }
238
+ .city-plaque { left: 16px; max-width: calc(100% - 32px); gap: 2px 14px; }
239
+ .city-plaque__figure { font-size: 18px; }
240
+ }
241
+
113
242
  /* the prototype's motion, verbatim */
114
243
  @keyframes city-ring { 0% { transform: scale(.8); opacity: .9; } 100% { transform: scale(2.3); opacity: 0; } }
115
244
  @keyframes city-zoom { from { opacity: 0; transform: scale(.97); } to { opacity: 1; transform: none; } }
@@ -122,6 +251,33 @@ html[data-fullscreen="on"] .city-top { right: 184px; }
122
251
  .city-pin__ring { animation: city-ring 2.8s cubic-bezier(.2,.7,.3,1) infinite; }
123
252
  .city-parcel { animation-name: city-travel; animation-timing-function: linear; animation-iteration-count: infinite; }
124
253
 
254
+ /* THE LIVING CITY's motion (task 1004685). It only says "this is live": data
255
+ is in count, size, position and colour, never in speed or a blink, so every
256
+ lane runs the same period and every loop is 20s or longer. Pods ride
257
+ offset-distance (the traffic exception the parcels already hold); the rest
258
+ is transform alone. Each moving part's still frame is set on the part
259
+ itself (--pod-at, --rise, --climb-at), so the Kill Switch leaves a whole
260
+ composition: the pods standing on their lanes at fixed spacing, the
261
+ scaffold at its share built, the rings at the foot of their shafts. */
262
+ @keyframes city-fly { from { offset-distance: 0%; } to { offset-distance: 100%; } }
263
+ @keyframes city-rise { 0% { transform: scaleY(.04); } 72%, 100% { transform: scaleY(1); } }
264
+ @keyframes city-climb { from { transform: translateY(0); } to { transform: translateY(var(--climb, -40px)); } }
265
+ @keyframes city-swing { from { transform: rotate(-9deg); } to { transform: rotate(11deg); } }
266
+ @keyframes city-shaft { from { transform: translateY(0); } to { transform: translateY(-140px); } }
267
+ @keyframes city-plug { from { transform: scaleY(0); } to { transform: none; } }
268
+ @keyframes city-plug-in { from { transform: scale(0); } to { transform: none; } }
269
+ .city-pod { animation: city-fly 26s linear infinite alternate; }
270
+ .city-rise { transform-box: fill-box; transform-origin: 50% 100%; transform: scaleY(var(--rise, 1)); animation: city-rise 24s cubic-bezier(.2,.7,.3,1) infinite; }
271
+ .city-climb { transform: translateY(var(--climb-at, 0px)); animation: city-climb 26s ease-in-out infinite alternate; }
272
+ .city-jib { transform-box: view-box; transform-origin: var(--pivot, 0 0); animation: city-swing 28s ease-in-out infinite alternate; }
273
+ .city-shaft__ring { animation: city-shaft 22s linear infinite; }
274
+ /* government adds structure: a capsule plugs in on the world's arrive curve, the
275
+ shape first, then its windows; once, on the first drawing (city.js marks the
276
+ stage data-drawn so a redraw does not replay it) */
277
+ .city-plug { transform-box: fill-box; transform-origin: 50% 100%; animation: city-plug 700ms cubic-bezier(.16,1,.3,1) both; animation-delay: calc(500ms + var(--i, 0) * 160ms); }
278
+ .city-plug--detail { transform-origin: 50% 50%; animation-name: city-plug-in; animation-delay: calc(900ms + var(--i, 0) * 160ms); }
279
+ .city-stage[data-drawn] .city-plug { animation: none; }
280
+
125
281
  /* The Kill Switch: under reduced motion nothing moves. The rest frame is the
126
282
  whole city with its pins standing still; the parcels, which only mean
127
283
  something while they travel, are left out of it. */
@@ -12,7 +12,9 @@
12
12
  (tests/hall_tokens.mjs: no hall page hardcodes a web-font stylesheet).
13
13
  The prototype carried its own Google Fonts link for the same two faces. -->
14
14
  <link rel="stylesheet" href="/builders/style.css?v=2026-07-02-shell1">
15
- <link rel="stylesheet" href="/builders/city.css?v=2026-10-04-pins1">
15
+ <link rel="stylesheet" href="/builders/city.css?v=2026-10-13-glass1">
16
+ <!-- the ask card in the glass language, shared with the street's deck (task 1004702) -->
17
+ <link rel="stylesheet" href="/builders/street-deck.css?v=2026-10-13-glass1">
16
18
  </head>
17
19
  <!-- THE GOVERNOR CITY, HOME (task 1004524, goal 1000125, R02). The home view
18
20
  of docs/design/mocks/governor-city/Street.dc.html (homeView and the home
@@ -43,7 +45,19 @@
43
45
 
44
46
  The page is gated on board.vote.cast (src/bongos/serve-internal.js), the
45
47
  same atom the docket read checks, so whoever reaches the city can read
46
- what it draws. -->
48
+ what it draws.
49
+
50
+ THE LIVING CITY (task 1004685, a prototype parked for the owner). The
51
+ same drawing in three levels: the ground (the goal districts, hazed by
52
+ depth, and the spend conduit), the civic quarter (each building a core
53
+ whose capsule floors are its Lead, committee rooms and built floors, its windows
54
+ ink for activity and salmon for what waits on you, a live build site or a
55
+ ghost annex on a vote, a light shaft over an open sitting) and the sky
56
+ (one pod per agent at work, on a lane to its goal's district). The plaque
57
+ under the wordmark is the government at a glance; a building opens its
58
+ card in place (who holds it, one fact, its count, two doors); the door is
59
+ "decide N in a row". gov-living.js is the model under it, all of it real
60
+ reads (task 1004717: the prototype overlay and its key are gone). -->
47
61
  <body data-page="city" data-page-title="The city" class="city" data-fullscreen-switch>
48
62
 
49
63
  <div class="app">
@@ -59,22 +73,28 @@
59
73
  <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" aria-hidden="true"><path id="cityModeIcon" d=""></path></svg>
60
74
  </button>
61
75
  </div>
76
+ <div class="city-plaque" id="cityPlaque" aria-label="The government at a glance" hidden></div>
62
77
 
63
78
  <div class="city-frame" id="cityFrame">
64
- <div class="city-stage" id="cityStage" role="img" aria-label="The governor city">
79
+ <div class="city-stage" id="cityStage" role="group" aria-label="The governor city">
65
80
  <div class="city-zoom">
66
81
  <div class="city-drift">
67
82
  <svg class="city-svg" id="citySvg" width="1440" height="900" viewBox="0 0 1440 900" aria-hidden="true" focusable="false">
68
83
  <g id="cityFlat"></g>
69
84
  <g id="cityBlds" class="city-blds"></g>
85
+ <g id="citySkyLanes" class="city-sky-lanes"></g>
70
86
  </svg>
71
87
  <div class="city-parcels" id="cityParcels" aria-hidden="true"></div>
88
+ <div class="city-sky" id="citySky" aria-hidden="true"></div>
72
89
  <div class="city-pins" id="cityPins" aria-hidden="true"></div>
90
+ <div class="city-hits" id="cityHits"></div>
73
91
  </div>
74
92
  </div>
75
93
  </div>
76
94
  </div>
77
95
 
96
+ <div class="city-card" id="cityCard" role="dialog" aria-label="A building" hidden></div>
97
+
78
98
  <div class="city-door">
79
99
  <a class="city-start" id="cityStart" href="/builders/street" aria-label="Start governing: enter the street view">start governing</a>
80
100
  <h1 class="city-line" id="cityLine" aria-live="polite">reading the docket</h1>
@@ -84,10 +104,20 @@
84
104
  </div>
85
105
 
86
106
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
87
- <script src="/builders/craft-mode.js?v=2026-10-08-city-tab"></script>
88
- <script src="/builders/shell.js?v=2026-10-08-glyph-fix"></script>
107
+ <script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
108
+ <script src="/builders/shell.js?v=2026-10-10-hall-keys1"></script>
89
109
  <script src="/builders/palette.js" defer></script>
90
- <script src="/builders/city-draw.js?v=2026-10-04-pins1"></script>
91
- <script src="/builders/city.js?v=2026-10-04-pins1"></script>
110
+ <script src="/builders/gov-living.js?v=2026-10-09-positions1"></script>
111
+ <script src="/builders/gov-feeds.js?v=2026-10-09-living3"></script>
112
+ <script src="/builders/city-draw.js?v=2026-10-09-living3"></script>
113
+ <!-- a building's card answers its first ask in place through the deck's own
114
+ route (task 1004702): the desk rows (street-desk.js over the street's kit)
115
+ and the deck's card and sender (street-deck.js) -->
116
+ <script src="/builders/street-draw.js?v=2026-10-09-living3"></script>
117
+ <script src="/builders/street-card.js?v=2026-10-04-record1"></script>
118
+ <script src="/builders/street-inside.js?v=2026-10-09-living3"></script>
119
+ <script src="/builders/street-desk.js?v=2026-10-04-record1"></script>
120
+ <script src="/builders/street-deck.js?v=2026-10-13-glass1"></script>
121
+ <script src="/builders/city.js?v=2026-10-13-glass1"></script>
92
122
  </body>
93
123
  </html>