six-degrees 0.4.10 → 0.5.0

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 (414) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-path-routes-manifest.json +1 -0
  3. package/.next/standalone/.next/build-manifest.json +3 -3
  4. package/.next/standalone/.next/prerender-manifest.json +9 -9
  5. package/.next/standalone/.next/routes-manifest.json +6 -0
  6. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  7. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  8. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  9. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  10. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  11. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  12. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  13. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  14. package/.next/standalone/.next/server/app/_not-found.rsc +13 -13
  15. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +13 -13
  16. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +12 -12
  17. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  18. package/.next/standalone/.next/server/app/api/admin-delete/route.js +1 -1
  19. package/.next/standalone/.next/server/app/api/admin-delete/route.js.nft.json +1 -1
  20. package/.next/standalone/.next/server/app/api/admin-update/route.js +1 -1
  21. package/.next/standalone/.next/server/app/api/admin-update/route.js.nft.json +1 -1
  22. package/.next/standalone/.next/server/app/api/bridges/route.js +1 -1
  23. package/.next/standalone/.next/server/app/api/bridges/route.js.nft.json +1 -1
  24. package/.next/standalone/.next/server/app/api/bulk-import/route.js +1 -1
  25. package/.next/standalone/.next/server/app/api/bulk-import/route.js.nft.json +1 -1
  26. package/.next/standalone/.next/server/app/api/company-scores/legacy/route.js +1 -1
  27. package/.next/standalone/.next/server/app/api/company-scores/legacy/route.js.nft.json +1 -1
  28. package/.next/standalone/.next/server/app/api/company-scores/route.js +1 -1
  29. package/.next/standalone/.next/server/app/api/company-scores/route.js.nft.json +1 -1
  30. package/.next/standalone/.next/server/app/api/connections/route.js +1 -1
  31. package/.next/standalone/.next/server/app/api/connections/route.js.nft.json +1 -1
  32. package/.next/standalone/.next/server/app/api/data/export/route.js.nft.json +1 -1
  33. package/.next/standalone/.next/server/app/api/data/import/route.js.nft.json +1 -1
  34. package/.next/standalone/.next/server/app/api/data/restart/route.js.nft.json +1 -1
  35. package/.next/standalone/.next/server/app/api/data/reveal/route.js.nft.json +1 -1
  36. package/.next/standalone/.next/server/app/api/data/route.js.nft.json +1 -1
  37. package/.next/standalone/.next/server/app/api/delete-cluster/route.js +1 -1
  38. package/.next/standalone/.next/server/app/api/delete-cluster/route.js.nft.json +1 -1
  39. package/.next/standalone/.next/server/app/api/ingest/route.js +1 -1
  40. package/.next/standalone/.next/server/app/api/ingest/route.js.nft.json +1 -1
  41. package/.next/standalone/.next/server/app/api/network/route.js +1 -1
  42. package/.next/standalone/.next/server/app/api/network/route.js.nft.json +1 -1
  43. package/.next/standalone/.next/server/app/api/notifications/route.js +1 -1
  44. package/.next/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  45. package/.next/standalone/.next/server/app/api/outreach/route.js +1 -1
  46. package/.next/standalone/.next/server/app/api/outreach/route.js.nft.json +1 -1
  47. package/.next/standalone/.next/server/app/api/queue/route.js +1 -1
  48. package/.next/standalone/.next/server/app/api/queue/route.js.nft.json +1 -1
  49. package/.next/standalone/.next/server/app/api/scraper/route.js +3 -2
  50. package/.next/standalone/.next/server/app/api/scraper/route.js.nft.json +1 -1
  51. package/.next/standalone/.next/server/app/api/settings/route.js +1 -1
  52. package/.next/standalone/.next/server/app/api/settings/route.js.nft.json +1 -1
  53. package/.next/standalone/.next/server/app/api/settings/sector-preview/route.js +1 -1
  54. package/.next/standalone/.next/server/app/api/settings/sector-preview/route.js.nft.json +1 -1
  55. package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route.js +1 -1
  56. package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route.js.nft.json +1 -1
  57. package/.next/standalone/.next/server/app/api/setup-profile/route.js +1 -1
  58. package/.next/standalone/.next/server/app/api/setup-profile/route.js.nft.json +1 -1
  59. package/.next/standalone/.next/server/app/api/social/crm/route/app-paths-manifest.json +3 -0
  60. package/.next/standalone/.next/server/app/api/social/crm/route/build-manifest.json +12 -0
  61. package/.next/standalone/.next/server/app/api/social/crm/route/server-reference-manifest.json +4 -0
  62. package/.next/standalone/.next/server/app/api/social/crm/route.js +10 -0
  63. package/.next/standalone/.next/server/app/api/social/crm/route.js.map +5 -0
  64. package/.next/standalone/.next/server/app/api/social/crm/route.js.nft.json +1 -0
  65. package/.next/standalone/.next/server/app/api/social/crm/route_client-reference-manifest.js +3 -0
  66. package/.next/standalone/.next/server/app/api/social/messages/route.js +4 -3
  67. package/.next/standalone/.next/server/app/api/social/messages/route.js.nft.json +1 -1
  68. package/.next/standalone/.next/server/app/api/social/route.js +4 -3
  69. package/.next/standalone/.next/server/app/api/social/route.js.nft.json +1 -1
  70. package/.next/standalone/.next/server/app/api/unlock/route.js +1 -1
  71. package/.next/standalone/.next/server/app/api/unlock/route.js.nft.json +1 -1
  72. package/.next/standalone/.next/server/app/api/update/route.js.nft.json +1 -1
  73. package/.next/standalone/.next/server/app/api/update-images/route.js +1 -1
  74. package/.next/standalone/.next/server/app/api/update-images/route.js.nft.json +1 -1
  75. package/.next/standalone/.next/server/app/api/users/route.js +1 -1
  76. package/.next/standalone/.next/server/app/api/users/route.js.nft.json +1 -1
  77. package/.next/standalone/.next/server/app/avatars/[file]/route.js.nft.json +1 -1
  78. package/.next/standalone/.next/server/app/import/page.js.nft.json +1 -1
  79. package/.next/standalone/.next/server/app/import/page_client-reference-manifest.js +1 -1
  80. package/.next/standalone/.next/server/app/import.html +1 -1
  81. package/.next/standalone/.next/server/app/import.rsc +15 -15
  82. package/.next/standalone/.next/server/app/import.segments/_full.segment.rsc +15 -15
  83. package/.next/standalone/.next/server/app/import.segments/_tree.segment.rsc +2 -2
  84. package/.next/standalone/.next/server/app/import.segments/import/__PAGE__.segment.rsc +14 -14
  85. package/.next/standalone/.next/server/app/index.html +1 -1
  86. package/.next/standalone/.next/server/app/index.rsc +15 -15
  87. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +14 -14
  88. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
  89. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  90. package/.next/standalone/.next/server/app/launch/page.js.nft.json +1 -1
  91. package/.next/standalone/.next/server/app/launch/page_client-reference-manifest.js +1 -1
  92. package/.next/standalone/.next/server/app/launch.html +2 -2
  93. package/.next/standalone/.next/server/app/launch.rsc +15 -15
  94. package/.next/standalone/.next/server/app/launch.segments/_full.segment.rsc +15 -15
  95. package/.next/standalone/.next/server/app/launch.segments/_tree.segment.rsc +2 -2
  96. package/.next/standalone/.next/server/app/launch.segments/launch/__PAGE__.segment.rsc +14 -14
  97. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  98. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  99. package/.next/standalone/.next/server/app/paths/page.js.nft.json +1 -1
  100. package/.next/standalone/.next/server/app/paths/page_client-reference-manifest.js +1 -1
  101. package/.next/standalone/.next/server/app/paths.html +1 -1
  102. package/.next/standalone/.next/server/app/paths.rsc +15 -15
  103. package/.next/standalone/.next/server/app/paths.segments/_full.segment.rsc +15 -15
  104. package/.next/standalone/.next/server/app/paths.segments/_tree.segment.rsc +2 -2
  105. package/.next/standalone/.next/server/app/paths.segments/paths/__PAGE__.segment.rsc +14 -14
  106. package/.next/standalone/.next/server/app/profile/page.js.nft.json +1 -1
  107. package/.next/standalone/.next/server/app/profile/page_client-reference-manifest.js +1 -1
  108. package/.next/standalone/.next/server/app/profile.html +1 -1
  109. package/.next/standalone/.next/server/app/profile.rsc +15 -15
  110. package/.next/standalone/.next/server/app/profile.segments/_full.segment.rsc +15 -15
  111. package/.next/standalone/.next/server/app/profile.segments/_tree.segment.rsc +2 -2
  112. package/.next/standalone/.next/server/app/profile.segments/profile/__PAGE__.segment.rsc +14 -14
  113. package/.next/standalone/.next/server/app/queue/page.js.nft.json +1 -1
  114. package/.next/standalone/.next/server/app/queue/page_client-reference-manifest.js +1 -1
  115. package/.next/standalone/.next/server/app/queue.html +1 -1
  116. package/.next/standalone/.next/server/app/queue.rsc +15 -15
  117. package/.next/standalone/.next/server/app/queue.segments/_full.segment.rsc +15 -15
  118. package/.next/standalone/.next/server/app/queue.segments/_tree.segment.rsc +2 -2
  119. package/.next/standalone/.next/server/app/queue.segments/queue/__PAGE__.segment.rsc +14 -14
  120. package/.next/standalone/.next/server/app/scores/page.js.nft.json +1 -1
  121. package/.next/standalone/.next/server/app/scores/page_client-reference-manifest.js +1 -1
  122. package/.next/standalone/.next/server/app/scores.html +1 -1
  123. package/.next/standalone/.next/server/app/scores.rsc +15 -15
  124. package/.next/standalone/.next/server/app/scores.segments/_full.segment.rsc +15 -15
  125. package/.next/standalone/.next/server/app/scores.segments/_tree.segment.rsc +2 -2
  126. package/.next/standalone/.next/server/app/scores.segments/scores/__PAGE__.segment.rsc +14 -14
  127. package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
  128. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  129. package/.next/standalone/.next/server/app/settings.html +1 -1
  130. package/.next/standalone/.next/server/app/settings.rsc +15 -15
  131. package/.next/standalone/.next/server/app/settings.segments/_full.segment.rsc +15 -15
  132. package/.next/standalone/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
  133. package/.next/standalone/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +14 -14
  134. package/.next/standalone/.next/server/app/setup/page.js.nft.json +1 -1
  135. package/.next/standalone/.next/server/app/setup/page_client-reference-manifest.js +1 -1
  136. package/.next/standalone/.next/server/app/setup.html +1 -1
  137. package/.next/standalone/.next/server/app/setup.rsc +15 -15
  138. package/.next/standalone/.next/server/app/setup.segments/_full.segment.rsc +15 -15
  139. package/.next/standalone/.next/server/app/setup.segments/_tree.segment.rsc +2 -2
  140. package/.next/standalone/.next/server/app/setup.segments/setup/__PAGE__.segment.rsc +14 -14
  141. package/.next/standalone/.next/server/app/social/page.js.nft.json +1 -1
  142. package/.next/standalone/.next/server/app/social/page_client-reference-manifest.js +1 -1
  143. package/.next/standalone/.next/server/app/social.html +1 -1
  144. package/.next/standalone/.next/server/app/social.rsc +15 -15
  145. package/.next/standalone/.next/server/app/social.segments/_full.segment.rsc +15 -15
  146. package/.next/standalone/.next/server/app/social.segments/_tree.segment.rsc +2 -2
  147. package/.next/standalone/.next/server/app/social.segments/social/__PAGE__.segment.rsc +14 -14
  148. package/.next/standalone/.next/server/app-paths-manifest.json +1 -0
  149. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0bat8nx._.js → [root-of-the-server]__05_3-22._.js} +2 -2
  150. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0t3v1a1._.js +1 -1
  151. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__06mi9k2._.js → [root-of-the-server]__13dx4sd._.js} +7 -2
  152. package/.next/standalone/.next/server/chunks/[root-of-the-server]__15wc9e-._.js +3 -0
  153. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1kbl21f._.js +1 -1
  154. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1tir0vc._.js +8 -0
  155. package/.next/standalone/.next/server/chunks/[root-of-the-server]__20rwfdw._.js +8 -0
  156. package/.next/standalone/.next/server/chunks/_072jl0y._.js +1 -1
  157. package/.next/standalone/.next/server/chunks/_0ea9qwy._.js +1 -1
  158. package/.next/standalone/.next/server/chunks/_1_fynia._.js +7 -7
  159. package/.next/standalone/.next/server/chunks/_1itd1o_._.js +1 -1
  160. package/.next/standalone/.next/server/chunks/_1iwkh8t._.js +1 -1
  161. package/.next/standalone/.next/server/chunks/_1oqfuh8._.js +3 -0
  162. package/.next/standalone/.next/server/chunks/_1xh07bp._.js +1 -1
  163. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_social_crm_route_actions_0d1aflv.js +3 -0
  164. package/.next/standalone/.next/server/chunks/lib_0851sk0._.js +8 -0
  165. package/.next/standalone/.next/server/chunks/lib_1q7p2ro._.js +8 -0
  166. package/.next/standalone/.next/server/chunks/lib_1r6l86l._.js +8 -0
  167. package/.next/standalone/.next/server/chunks/lib_db-client_15le7cw.js +8 -8
  168. package/.next/standalone/.next/server/chunks/lib_linkedin-export_12imqxg.js +3 -0
  169. package/.next/standalone/.next/server/chunks/lib_rpc_04s8mzr.js +3 -0
  170. package/.next/standalone/.next/server/chunks/lib_rpc_053z7as.js +3 -0
  171. package/.next/standalone/.next/server/chunks/lib_rpc_0b_-2te.js +3 -0
  172. package/.next/standalone/.next/server/chunks/lib_rpc_0dhbxdm.js +3 -0
  173. package/.next/standalone/.next/server/chunks/lib_rpc_0dxlk31.js +3 -0
  174. package/.next/standalone/.next/server/chunks/lib_rpc_0f8b-qc.js +3 -0
  175. package/.next/standalone/.next/server/chunks/lib_rpc_0pzie7_.js +3 -0
  176. package/.next/standalone/.next/server/chunks/lib_rpc_0r76fq_.js +3 -0
  177. package/.next/standalone/.next/server/chunks/lib_rpc_0ut7pjp.js +3 -0
  178. package/.next/standalone/.next/server/chunks/lib_rpc_15zyqaz.js +3 -0
  179. package/.next/standalone/.next/server/chunks/lib_rpc_18zpjtq.js +3 -0
  180. package/.next/standalone/.next/server/chunks/lib_rpc_1a8xkiz.js +3 -0
  181. package/.next/standalone/.next/server/chunks/lib_rpc_1e_55xo.js +3 -0
  182. package/.next/standalone/.next/server/chunks/lib_rpc_1oxfd1_.js +3 -0
  183. package/.next/standalone/.next/server/chunks/lib_rpc_1s0lod0.js +3 -0
  184. package/.next/standalone/.next/server/chunks/lib_scoring_1-e4ur0.js +1 -1
  185. package/.next/standalone/.next/server/chunks/ssr/_01kacen._.js +3 -0
  186. package/.next/standalone/.next/server/chunks/ssr/_03l7vge._.js +3 -0
  187. package/.next/standalone/.next/server/chunks/ssr/{_1ap1tu_._.js → _0gtv9jb._.js} +2 -2
  188. package/.next/standalone/.next/server/chunks/ssr/_0jdkqgi._.js +3 -0
  189. package/.next/standalone/.next/server/chunks/ssr/_0xi-fbs._.js +3 -0
  190. package/.next/standalone/.next/server/chunks/ssr/_0xmwmfv._.js +3 -0
  191. package/.next/standalone/.next/server/chunks/ssr/_1-b9hj7._.js +9 -0
  192. package/.next/standalone/.next/server/chunks/ssr/_112ewem._.js +3 -0
  193. package/.next/standalone/.next/server/chunks/ssr/_16ab63q._.js +3 -0
  194. package/.next/standalone/.next/server/chunks/ssr/_1fxm0-s._.js +3 -0
  195. package/.next/standalone/.next/server/chunks/ssr/_1ra1d3r._.js +9 -0
  196. package/.next/standalone/.next/server/chunks/ssr/app_141w189._.js +3 -0
  197. package/.next/standalone/.next/server/chunks/ssr/app_page_1fazqbf.js +22 -10
  198. package/.next/standalone/.next/server/chunks/ssr/app_paths_page_1ol90m7.js +2 -2
  199. package/.next/standalone/.next/server/chunks/ssr/app_profile_page_0u3-l5y.js +1 -1
  200. package/.next/standalone/.next/server/chunks/ssr/app_queue_page_0c6znd6.js +6 -5
  201. package/.next/standalone/.next/server/chunks/ssr/app_settings_page_1f8mjj_.js +1 -1
  202. package/.next/standalone/.next/server/chunks/ssr/app_setup_page_1-282zx.js +19 -3
  203. package/.next/standalone/.next/server/chunks/ssr/app_social_page_0h7zxda.js +1 -1
  204. package/.next/standalone/.next/server/chunks/ssr/lib_0i8v-s3._.js +1 -1
  205. package/.next/standalone/.next/server/chunks/ssr/lib_13rapwj._.js +3 -0
  206. package/.next/standalone/.next/server/chunks/ssr/lib_galaxy-lab_108_lu-.js +3 -0
  207. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  208. package/.next/standalone/.next/server/middleware-manifest.json +5 -5
  209. package/.next/standalone/.next/server/pages/404.html +1 -1
  210. package/.next/standalone/.next/server/pages/500.html +1 -1
  211. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  212. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  213. package/.next/standalone/.next/static/chunks/03bziijw5srol.js +1 -0
  214. package/.next/standalone/.next/static/chunks/0bgq8wmopl_ig.js +7 -0
  215. package/.next/standalone/.next/static/chunks/0ezus6p2eb-vg.js +1 -0
  216. package/.next/standalone/.next/static/chunks/0g_fy2034bp0x.js +34 -0
  217. package/.next/standalone/.next/static/chunks/0q5dru4q6gxl5.js +22 -0
  218. package/.next/standalone/.next/static/chunks/0w-byiwb2zax8.js +2 -0
  219. package/.next/standalone/.next/static/chunks/1g7jcovdejc9-.js +1 -0
  220. package/.next/standalone/.next/static/chunks/1i51yylxdzht1.js +1 -0
  221. package/.next/{static/chunks/1xptlvtcz6654.css → standalone/.next/static/chunks/1x_ysly42-teq.css} +1 -1
  222. package/.next/standalone/.next/static/chunks/1zf8swaasjf1e.js +43 -0
  223. package/.next/standalone/.next/static/chunks/2rqtpccruavf2.js +1 -0
  224. package/.next/standalone/.next/static/chunks/2wgz9ietkqqe6.js +1 -0
  225. package/.next/standalone/.next/static/chunks/30x3oq_st7a5r.js +1 -0
  226. package/.next/standalone/.next/static/chunks/355ryio1b7sm1.js +1 -0
  227. package/.next/standalone/.next/static/chunks/3ap5hgma7n0o7.js +1 -0
  228. package/.next/standalone/.next/static/chunks/3fci6qi39-1n5.js +1 -0
  229. package/.next/standalone/.next/static/chunks/{24tvdun1cb3g1.js → 3sowbvbaj1s6n.js} +1 -1
  230. package/.next/standalone/CHANGELOG.md +235 -0
  231. package/.next/standalone/app/api/data/export/route.js +2 -1
  232. package/.next/standalone/app/api/ingest/route.js +40 -1
  233. package/.next/standalone/app/api/scraper/route.js +12 -2
  234. package/.next/standalone/app/api/settings/sector-preview/route.js +2 -1
  235. package/.next/standalone/app/api/social/crm/route.js +37 -0
  236. package/.next/standalone/app/api/social/messages/route.js +44 -8
  237. package/.next/standalone/app/api/social/route.js +80 -22
  238. package/.next/standalone/app/components/AppTabs.js +59 -0
  239. package/.next/standalone/app/components/ChainView.js +303 -89
  240. package/.next/standalone/app/components/CirclePanel.js +162 -0
  241. package/.next/standalone/app/components/CompanyScores.js +2 -2
  242. package/.next/standalone/app/components/FieldStep.js +4 -4
  243. package/.next/standalone/app/components/FilterPanel.js +121 -183
  244. package/.next/standalone/app/components/ForceGraph.js +41 -3
  245. package/.next/standalone/app/components/GalaxyLab.js +26 -31
  246. package/.next/standalone/app/components/LegacyScoresCard.js +2 -2
  247. package/.next/standalone/app/components/MapControls.js +154 -0
  248. package/.next/standalone/app/components/NoteDetail.js +118 -0
  249. package/.next/standalone/app/components/PathsAnalyzer.js +147 -110
  250. package/.next/standalone/app/components/PeopleMap.js +308 -0
  251. package/.next/standalone/app/components/ScanRadar.js +129 -0
  252. package/.next/standalone/app/components/ScanStatusBar.js +72 -27
  253. package/.next/standalone/app/components/SeparationView.js +626 -118
  254. package/.next/standalone/app/components/Sidebar.js +28 -2
  255. package/.next/standalone/app/components/settings/DataSection.js +12 -3
  256. package/.next/standalone/app/components/settings/NetworkHealthSection.js +1 -1
  257. package/.next/standalone/app/components/settings/SectorSection.js +2 -2
  258. package/.next/standalone/app/components/settings/TierSection.js +1 -1
  259. package/.next/standalone/app/components/settings/TitleSection.js +149 -0
  260. package/.next/standalone/app/components/views.js +15 -14
  261. package/.next/standalone/app/globals.css +11 -0
  262. package/.next/standalone/app/page.js +89 -156
  263. package/.next/standalone/app/paths/page.js +39 -27
  264. package/.next/standalone/app/profile/page.js +33 -5
  265. package/.next/standalone/app/queue/page.js +56 -34
  266. package/.next/standalone/app/scores/page.js +16 -66
  267. package/.next/standalone/app/settings/page.js +27 -13
  268. package/.next/standalone/app/setup/page.js +298 -205
  269. package/.next/standalone/app/social/Crm.js +683 -0
  270. package/.next/standalone/app/social/SocialHub.js +374 -0
  271. package/.next/standalone/app/social/Thread.js +90 -0
  272. package/.next/standalone/app/social/page.js +10 -351
  273. package/.next/standalone/lib/chain-layout.js +105 -35
  274. package/.next/standalone/lib/data-export.js +10 -4
  275. package/.next/standalone/lib/data-folder.js +9 -0
  276. package/.next/standalone/lib/data-import.js +13 -3
  277. package/.next/standalone/lib/degrees.js +0 -6
  278. package/.next/standalone/lib/dot-rings.js +25 -0
  279. package/.next/standalone/lib/galaxy-lab.js +65 -6
  280. package/.next/standalone/lib/ingest.js +2 -0
  281. package/.next/standalone/lib/island.js +40 -0
  282. package/.next/standalone/lib/linkedin-export.js +267 -46
  283. package/.next/standalone/lib/linkedin-limits.js +6 -2
  284. package/.next/standalone/lib/map-heat.js +20 -0
  285. package/.next/standalone/lib/network-health.js +1 -1
  286. package/.next/standalone/lib/notifications.js +121 -0
  287. package/.next/standalone/lib/people-map.js +82 -0
  288. package/.next/standalone/lib/rarity.js +45 -3
  289. package/.next/standalone/lib/reach.js +7 -6
  290. package/.next/standalone/lib/rpc.js +15 -4
  291. package/.next/standalone/lib/scan-pace.js +46 -0
  292. package/.next/standalone/lib/scoring.js +39 -8
  293. package/.next/standalone/lib/scraper-client.js +19 -6
  294. package/.next/standalone/lib/sector-focus.js +4 -4
  295. package/.next/standalone/lib/separation.js +137 -10
  296. package/.next/standalone/lib/settings-effects.js +20 -11
  297. package/.next/standalone/lib/settings.js +3 -0
  298. package/.next/standalone/lib/social-crm.js +415 -0
  299. package/.next/standalone/lib/social-store.js +13 -6
  300. package/.next/standalone/lib/tier-grid.js +99 -0
  301. package/.next/standalone/lib/title-ranking.js +83 -0
  302. package/.next/standalone/package-lock.json +2 -2
  303. package/.next/standalone/package.json +1 -1
  304. package/.next/standalone/scripts/scrape.py +177 -35
  305. package/.next/static/chunks/03bziijw5srol.js +1 -0
  306. package/.next/static/chunks/0bgq8wmopl_ig.js +7 -0
  307. package/.next/static/chunks/0ezus6p2eb-vg.js +1 -0
  308. package/.next/static/chunks/0g_fy2034bp0x.js +34 -0
  309. package/.next/static/chunks/0q5dru4q6gxl5.js +22 -0
  310. package/.next/static/chunks/0w-byiwb2zax8.js +2 -0
  311. package/.next/static/chunks/1g7jcovdejc9-.js +1 -0
  312. package/.next/static/chunks/1i51yylxdzht1.js +1 -0
  313. package/.next/{standalone/.next/static/chunks/1xptlvtcz6654.css → static/chunks/1x_ysly42-teq.css} +1 -1
  314. package/.next/static/chunks/1zf8swaasjf1e.js +43 -0
  315. package/.next/static/chunks/2rqtpccruavf2.js +1 -0
  316. package/.next/static/chunks/2wgz9ietkqqe6.js +1 -0
  317. package/.next/static/chunks/30x3oq_st7a5r.js +1 -0
  318. package/.next/static/chunks/355ryio1b7sm1.js +1 -0
  319. package/.next/static/chunks/3ap5hgma7n0o7.js +1 -0
  320. package/.next/static/chunks/3fci6qi39-1n5.js +1 -0
  321. package/.next/static/chunks/{24tvdun1cb3g1.js → 3sowbvbaj1s6n.js} +1 -1
  322. package/CHANGELOG.md +235 -0
  323. package/lib/chain-layout.js +105 -35
  324. package/lib/data-export.js +10 -4
  325. package/lib/data-folder.js +9 -0
  326. package/lib/data-import.js +13 -3
  327. package/lib/degrees.js +0 -6
  328. package/lib/dot-rings.js +25 -0
  329. package/lib/galaxy-lab.js +65 -6
  330. package/lib/ingest.js +2 -0
  331. package/lib/island.js +40 -0
  332. package/lib/linkedin-export.js +267 -46
  333. package/lib/linkedin-limits.js +6 -2
  334. package/lib/map-heat.js +20 -0
  335. package/lib/network-health.js +1 -1
  336. package/lib/notifications.js +121 -0
  337. package/lib/people-map.js +82 -0
  338. package/lib/rarity.js +45 -3
  339. package/lib/reach.js +7 -6
  340. package/lib/rpc.js +15 -4
  341. package/lib/scan-pace.js +46 -0
  342. package/lib/scoring.js +39 -8
  343. package/lib/scraper-client.js +19 -6
  344. package/lib/sector-focus.js +4 -4
  345. package/lib/separation.js +137 -10
  346. package/lib/settings-effects.js +20 -11
  347. package/lib/settings.js +3 -0
  348. package/lib/social-crm.js +415 -0
  349. package/lib/social-store.js +13 -6
  350. package/lib/tier-grid.js +99 -0
  351. package/lib/title-ranking.js +83 -0
  352. package/package.json +1 -1
  353. package/scripts/scrape.py +177 -35
  354. package/.next/standalone/.next/server/chunks/[root-of-the-server]__08f5awg._.js +0 -8
  355. package/.next/standalone/.next/server/chunks/[root-of-the-server]__17hjtzl._.js +0 -8
  356. package/.next/standalone/.next/server/chunks/[root-of-the-server]__20tmem7._.js +0 -3
  357. package/.next/standalone/.next/server/chunks/lib_18cr1gi._.js +0 -8
  358. package/.next/standalone/.next/server/chunks/lib_rpc_03i8xef.js +0 -3
  359. package/.next/standalone/.next/server/chunks/lib_rpc_08fc3rp.js +0 -3
  360. package/.next/standalone/.next/server/chunks/lib_rpc_08r2t_q.js +0 -3
  361. package/.next/standalone/.next/server/chunks/lib_rpc_0btpv1t.js +0 -3
  362. package/.next/standalone/.next/server/chunks/lib_rpc_0c9d9ti.js +0 -8
  363. package/.next/standalone/.next/server/chunks/lib_rpc_0cm2ev3.js +0 -3
  364. package/.next/standalone/.next/server/chunks/lib_rpc_0iovswz.js +0 -3
  365. package/.next/standalone/.next/server/chunks/lib_rpc_0is8flp.js +0 -3
  366. package/.next/standalone/.next/server/chunks/lib_rpc_0v8ajtd.js +0 -3
  367. package/.next/standalone/.next/server/chunks/lib_rpc_0xgmvvt.js +0 -3
  368. package/.next/standalone/.next/server/chunks/lib_rpc_144mzbf.js +0 -3
  369. package/.next/standalone/.next/server/chunks/lib_rpc_1bggi0n.js +0 -3
  370. package/.next/standalone/.next/server/chunks/lib_rpc_1dkcu9f.js +0 -3
  371. package/.next/standalone/.next/server/chunks/lib_rpc_1o0jb6w.js +0 -3
  372. package/.next/standalone/.next/server/chunks/ssr/_0c_y09g._.js +0 -3
  373. package/.next/standalone/.next/server/chunks/ssr/_0ezj4e0._.js +0 -3
  374. package/.next/standalone/.next/server/chunks/ssr/_0j4-lc3._.js +0 -3
  375. package/.next/standalone/.next/server/chunks/ssr/_0l8cxmo._.js +0 -3
  376. package/.next/standalone/.next/server/chunks/ssr/_0xkur4p._.js +0 -3
  377. package/.next/standalone/.next/server/chunks/ssr/_14iv_zy._.js +0 -3
  378. package/.next/standalone/.next/server/chunks/ssr/_15x6q32._.js +0 -3
  379. package/.next/standalone/.next/server/chunks/ssr/_1errbuf._.js +0 -3
  380. package/.next/standalone/.next/server/chunks/ssr/_212xw8q._.js +0 -3
  381. package/.next/standalone/.next/server/chunks/ssr/app_components_19c2d9c._.js +0 -3
  382. package/.next/standalone/.next/server/chunks/ssr/app_scores_page_09wepvv.js +0 -3
  383. package/.next/standalone/.next/static/chunks/07dyt47mp4s9-.js +0 -1
  384. package/.next/standalone/.next/static/chunks/0a5iadnmt9u9k.js +0 -1
  385. package/.next/standalone/.next/static/chunks/160wjb73ddwqd.js +0 -6
  386. package/.next/standalone/.next/static/chunks/1c_n0973t07l0.js +0 -2
  387. package/.next/standalone/.next/static/chunks/1e1n0kkz-psdb.js +0 -1
  388. package/.next/standalone/.next/static/chunks/206rm6j42gl_a.js +0 -1
  389. package/.next/standalone/.next/static/chunks/236f0jtp68j_h.js +0 -1
  390. package/.next/standalone/.next/static/chunks/2coxzjm_k6ilr.js +0 -1
  391. package/.next/standalone/.next/static/chunks/2kfhc58df2xyo.js +0 -1
  392. package/.next/standalone/.next/static/chunks/2pw6_osz1n_te.js +0 -1
  393. package/.next/standalone/.next/static/chunks/39hr8d-b2ibtw.js +0 -31
  394. package/.next/standalone/.next/static/chunks/3zw8bv7-mc4n6.js +0 -33
  395. package/.next/standalone/app/components/OrbitGraph.js +0 -737
  396. package/.next/standalone/app/social/Conversations.js +0 -246
  397. package/.next/static/chunks/07dyt47mp4s9-.js +0 -1
  398. package/.next/static/chunks/0a5iadnmt9u9k.js +0 -1
  399. package/.next/static/chunks/160wjb73ddwqd.js +0 -6
  400. package/.next/static/chunks/1c_n0973t07l0.js +0 -2
  401. package/.next/static/chunks/1e1n0kkz-psdb.js +0 -1
  402. package/.next/static/chunks/206rm6j42gl_a.js +0 -1
  403. package/.next/static/chunks/236f0jtp68j_h.js +0 -1
  404. package/.next/static/chunks/2coxzjm_k6ilr.js +0 -1
  405. package/.next/static/chunks/2kfhc58df2xyo.js +0 -1
  406. package/.next/static/chunks/2pw6_osz1n_te.js +0 -1
  407. package/.next/static/chunks/39hr8d-b2ibtw.js +0 -31
  408. package/.next/static/chunks/3zw8bv7-mc4n6.js +0 -33
  409. /package/.next/standalone/.next/static/{7zWJnSkfSoRhRsqY6ZKtD → I-cj79yE2IZ8taX2dZGp3}/_buildManifest.js +0 -0
  410. /package/.next/standalone/.next/static/{7zWJnSkfSoRhRsqY6ZKtD → I-cj79yE2IZ8taX2dZGp3}/_clientMiddlewareManifest.js +0 -0
  411. /package/.next/standalone/.next/static/{7zWJnSkfSoRhRsqY6ZKtD → I-cj79yE2IZ8taX2dZGp3}/_ssgManifest.js +0 -0
  412. /package/.next/static/{7zWJnSkfSoRhRsqY6ZKtD → I-cj79yE2IZ8taX2dZGp3}/_buildManifest.js +0 -0
  413. /package/.next/static/{7zWJnSkfSoRhRsqY6ZKtD → I-cj79yE2IZ8taX2dZGp3}/_clientMiddlewareManifest.js +0 -0
  414. /package/.next/static/{7zWJnSkfSoRhRsqY6ZKtD → I-cj79yE2IZ8taX2dZGp3}/_ssgManifest.js +0 -0
@@ -31,7 +31,7 @@ import { runningNow } from './scan-state.js';
31
31
  import { durable } from './durable.js';
32
32
  import { budgetFileProblem, mergeBudgetFiles } from './linkedin-limits.js';
33
33
  import {
34
- AVATAR_FILE, TRAVELLING_FILES, NETWORK_FILES, BUDGET_FILES, PENDING_DIR, IMPORT_BACKUP_PREFIX,
34
+ AVATAR_FILE, TRAVELLING_FILES, NETWORK_FILES, BUDGET_FILES, SOCIAL_FILE, PENDING_DIR, IMPORT_BACKUP_PREFIX,
35
35
  sweepLeftovers, namesInFolder,
36
36
  } from './data-folder.js';
37
37
  import {
@@ -158,10 +158,11 @@ export async function receiveUpload(body, file, { declared }) {
158
158
  return received;
159
159
  }
160
160
 
161
- /** 'photo', 'file' (one of the scanner's travelling files), or null for anything an export never carries. */
161
+ /** 'photo', 'file' (one of the scanner's travelling files), 'social', or null for anything an export never carries. */
162
162
  export function exportedFileKind(rel) {
163
163
  if (typeof rel !== 'string') return null;
164
164
  if (TRAVELLING_FILES.includes(rel)) return 'file';
165
+ if (SOCIAL_FILE.test(rel)) return 'social';
165
166
  // The same pattern the /avatars route serves: no folders, no dots but the
166
167
  // extension, so no path can climb out of avatars/.
167
168
  if (rel.startsWith('avatars/') && AVATAR_FILE.test(rel.slice('avatars/'.length))) return 'photo';
@@ -421,7 +422,7 @@ export function stageImport(upload, {
421
422
  throw new ImportError(`“${shortName(rel)}” inside this file is damaged, so nothing was imported.`);
422
423
  }
423
424
  writeFileSync(path.join(filesDir, rel), row.bytes, { flag: 'wx' });
424
- if (kind === 'file') scannerFiles.push(path.join(filesDir, rel));
425
+ if (kind === 'file' || kind === 'social') scannerFiles.push(path.join(filesDir, rel));
425
426
  }
426
427
  } finally {
427
428
  db.close();
@@ -731,6 +732,14 @@ export function applyPendingImport({ dir, dbFile, now = new Date(), copyDatabase
731
732
  keptFolder();
732
733
  move(from, path.join(keptFiles, name));
733
734
  }
735
+ // This computer's Social files step aside only when the copy brings its
736
+ // own; a copy made without them leaves them where they are.
737
+ if (namesInFolder(path.join(pending, 'files')).some((n) => SOCIAL_FILE.test(n))) {
738
+ for (const name of namesInFolder(dir).filter((n) => SOCIAL_FILE.test(n))) {
739
+ keptFolder();
740
+ move(path.join(dir, name), path.join(keptFiles, name));
741
+ }
742
+ }
734
743
  for (const name of BUDGET_FILES) {
735
744
  const from = path.join(dir, name);
736
745
  if (!exists(from) || !lstatSync(from).isFile()) continue;
@@ -786,6 +795,7 @@ export function applyPendingImport({ dir, dbFile, now = new Date(), copyDatabase
786
795
  const from = path.join(files, name);
787
796
  if (exists(from)) move(from, path.join(dir, name));
788
797
  }
798
+ for (const name of namesInFolder(files).filter((n) => SOCIAL_FILE.test(n))) move(path.join(files, name), path.join(dir, name));
789
799
  mergeBudgetFiles({ dir, from: files });
790
800
  durable.syncFolder(dir);
791
801
  step('done');
@@ -22,9 +22,3 @@ export function peopleByDegree(degree1 = [], degree2 = [], degree3 = []) {
22
22
  };
23
23
  return { 1: take(degree1, 1), 2: take(degree2, 2), 3: take(degree3, 3) };
24
24
  }
25
-
26
- export function tierCountsOf(rows = []) {
27
- const counts = {};
28
- for (const row of rows) counts[row.tier] = (counts[row.tier] || 0) + 1;
29
- return counts;
30
- }
@@ -18,4 +18,29 @@ export function ringSegments(r) {
18
18
  });
19
19
  }
20
20
 
21
+ /**
22
+ * The ring round a bridge in Bridge Chains (Blake, 2026-10-02: "the bars on the
23
+ * ring should signify how many dots in the clusters are ready to be scanned
24
+ * and new clusters formed"). One bar for each person you added through that
25
+ * circle: the ones scanned since, with a cluster of their own (`formed`),
26
+ * then the ones waiting for a scan (`ready`). Past `max` bars the two kinds
27
+ * share them in proportion, each keeping at least one.
28
+ *
29
+ * @returns {{ d: string, kind: 'formed' | 'ready' }[]}
30
+ */
31
+ export function reachSegments(r, { formed = 0, ready = 0 } = {}, max = 12) {
32
+ const total = Math.max(0, formed) + Math.max(0, ready);
33
+ if (!total) return [];
34
+ const n = Math.min(total, max);
35
+ let nFormed = formed > 0 ? Math.max(1, Math.round((n * formed) / total)) : 0;
36
+ if (ready > 0 && nFormed >= n) nFormed = n - 1;
37
+ const gap = n === 1 ? 0.5 : Math.min(GAP, ((2 * Math.PI) / n) * 0.35);
38
+ const span = (2 * Math.PI) / n - gap;
39
+ const p = (a) => `${(r * Math.cos(a)).toFixed(2)} ${(r * Math.sin(a)).toFixed(2)}`;
40
+ return Array.from({ length: n }, (_, i) => {
41
+ const a0 = -Math.PI / 2 + gap / 2 + i * (span + gap);
42
+ return { kind: i < nFormed ? 'formed' : 'ready', d: `M${p(a0)} A${r} ${r} 0 ${span > Math.PI ? 1 : 0} 1 ${p(a0 + span)}` };
43
+ });
44
+ }
45
+
21
46
  export const RING = { filled: '#1abc9c', empty: 'rgba(255,255,255,0.16)', badge: '#7F77DD' };
@@ -7,7 +7,7 @@
7
7
  // which isn't. Both follow useSyncExternalStore's rules: a snapshot only changes
8
8
  // when something in it does.
9
9
 
10
- import { keyFor } from './separation.js';
10
+ import { keyFor, score } from './separation.js';
11
11
  import { warmthOf } from './linkedin-export.js';
12
12
 
13
13
  const KEY = 'six-degrees-galaxy-lab';
@@ -15,7 +15,7 @@ const LAYOUTS_KEY = 'six-degrees-galaxy-layouts';
15
15
 
16
16
  /** The layout as it has always been. Every slider is a multiple of today's value, or 0 for off. */
17
17
  export const LAB_DEFAULTS = Object.freeze({
18
- on: false, // the lab is on: without it, the Galaxy ignores everything below
18
+ on: true, // always: the sliders are the Galaxy's own controls now (it was an experimental switch)
19
19
  gravity: 0, // a pull on every dot towards you, in the middle
20
20
  rings: 1, // how hard each tier (or degree) holds its ring; 0 lets it find its own shape
21
21
  push: 15, // how hard dots push each other apart
@@ -25,11 +25,12 @@ export const LAB_DEFAULTS = Object.freeze({
25
25
  lines: 1,
26
26
  sizeBy: 'power', // 'power' (power score) or 'reach' (how many hang off them)
27
27
  names: 'key', // 'key' (you, S tier, catalysts) or 'all' (all your connections)
28
- branch: true, // hovering a dot lights up its branch and dims the rest
29
- colourBy: 'tier', // 'tier', 'degree', 'company' or 'warmth' (from the Social tab)
28
+ branch: false, // hovering a dot lights up its branch and dims the rest: off to start (Blake, 2026-10-02: it glitched)
29
+ colourBy: 'tier', // 'tier', 'heat' (power as a thermal map), 'degree', 'company' or 'warmth' (from the Social tab)
30
30
  speed: 15, // a replay's length, in seconds
31
31
  loop: false, // start the replay again when it ends
32
32
  labels: true, // names on the Galaxy at all: the Filter panel's switch, honoured with the lab off too
33
+ v: 2, // which defaults a saved setting was made under (2: the branch starts off)
33
34
  });
34
35
 
35
36
  /** The slider settings a saved layout keeps (not whether the lab is on, nor the names switch). */
@@ -38,13 +39,33 @@ const LAYOUT_KEYS = ['gravity', 'rings', 'push', 'pull', 'distance', 'dotSize',
38
39
  /** Let the layout find its own shape: no rings, each connection's circle bunched round them. */
39
40
  export const CLUSTERS = Object.freeze({ gravity: 0.25, rings: 0, push: 25, pull: 2.5, distance: 0.35, sizeBy: 'reach' });
40
41
 
42
+ /**
43
+ * Orbit, the old view, as a layout of the Galaxy (Blake, 2026-10-02: "add that as a
44
+ * visual option instead so the person can interact with it"): every tier held hard
45
+ * on its orbit, and each connection's circle drawn in close behind them. It's still
46
+ * the Galaxy, so dragging and every slider work on it.
47
+ */
48
+ export const ORBIT = Object.freeze({ gravity: 0, rings: 3, push: 6, pull: 4, distance: 0.22, sizeBy: 'power' });
49
+
50
+ /** Which layout the sliders are set to: 'rings', 'clusters', 'orbit', or null for your own. */
51
+ export function layoutOf(lab) {
52
+ const is = (preset) => Object.entries(preset).every(([k, v]) => lab[k] === v);
53
+ if (['gravity', 'rings', 'push', 'pull', 'distance'].every((k) => lab[k] === LAB_DEFAULTS[k])) return 'rings';
54
+ if (is(CLUSTERS)) return 'clusters';
55
+ if (is(ORBIT)) return 'orbit';
56
+ return null;
57
+ }
58
+
41
59
  const listeners = new Set();
42
60
  let cache = null;
43
61
 
44
62
  function read() {
45
63
  try {
46
64
  const raw = JSON.parse(localStorage.getItem(KEY) || 'null');
47
- return raw && typeof raw === 'object' ? { ...LAB_DEFAULTS, ...raw } : LAB_DEFAULTS;
65
+ // `on` was a switch once; a setting saved back then mustn't turn the sliders off.
66
+ // Saved before v2, the branch light-up was on by default; it starts off now.
67
+ if (!raw || typeof raw !== 'object') return LAB_DEFAULTS;
68
+ return { ...LAB_DEFAULTS, ...raw, ...(raw.v === LAB_DEFAULTS.v ? {} : { branch: false }), v: LAB_DEFAULTS.v, on: true };
48
69
  } catch { return LAB_DEFAULTS; }
49
70
  }
50
71
 
@@ -54,7 +75,7 @@ export function labNow() {
54
75
  }
55
76
 
56
77
  export function setLab(patch) {
57
- cache = patch === null ? { ...LAB_DEFAULTS, on: labNow().on, labels: labNow().labels } : { ...labNow(), ...patch };
78
+ cache = patch === null ? { ...LAB_DEFAULTS, labels: labNow().labels } : { ...labNow(), ...patch, on: true };
58
79
  try { localStorage.setItem(KEY, JSON.stringify(cache)); } catch {}
59
80
  listeners.forEach((f) => f());
60
81
  }
@@ -249,6 +270,36 @@ const DEGREE_COLOURS = { 1: '#4FC3F7', 2: '#BA68C8', 3: '#FFB74D' };
249
270
  const COMPANY_COLOURS = ['#FF6B6B', '#4ECDC4', '#FFD93D', '#A29BFE', '#00B894', '#FD79A8', '#74B9FF', '#E17055'];
250
271
  const WARMTH_COLOURS = { warm: '#FF7043', cool: '#4FC3F7', dormant: '#8D6E63', never: '#546E7A' };
251
272
  const OTHER = '#4a5568';
273
+
274
+ // Heat (Blake, 2026-10-02: "a thermal visual of power based on the dots"): a
275
+ // thermal camera's colours, cold violet through red and orange to white hot.
276
+ const HEAT_STOPS = ['#2b1b6b', '#6a1b9a', '#c2185b', '#f4511e', '#ffb300', '#fff3b0'];
277
+
278
+ /** The thermal colour at `t` (0 cold … 1 hottest). */
279
+ export function heatColour(t) {
280
+ const x = Math.max(0, Math.min(1, Number(t) || 0)) * (HEAT_STOPS.length - 1);
281
+ const i = Math.min(HEAT_STOPS.length - 2, Math.floor(x));
282
+ const f = x - i;
283
+ const a = HEAT_STOPS[i], b = HEAT_STOPS[i + 1];
284
+ const mix = (k) => Math.round(parseInt(a.slice(k, k + 2), 16) * (1 - f) + parseInt(b.slice(k, k + 2), 16) * f);
285
+ return `#${[1, 3, 5].map((k) => mix(k).toString(16).padStart(2, '0')).join('')}`;
286
+ }
287
+
288
+ /**
289
+ * Everyone's heat, 0 to 1: where their power score ranks among the people shown,
290
+ * so the colours spread across whoever is on screen (a network of mostly B tier
291
+ * still has its hot spots). Equal scores share a heat.
292
+ */
293
+ export function heatOf(people = []) {
294
+ return heatBy(people, score);
295
+ }
296
+
297
+ /** The same for anything with a value: each one's heat, 0 to 1, from where its value ranks. */
298
+ export function heatBy(items = [], valueOf = () => 0) {
299
+ const values = [...new Set(items.map(valueOf))].sort((a, b) => a - b);
300
+ const at = new Map(values.map((v, i) => [v, values.length > 1 ? i / (values.length - 1) : 1]));
301
+ return (d) => at.get(valueOf(d)) ?? 0;
302
+ }
252
303
  const companyKey = (c) => String(c || '').trim().toLowerCase();
253
304
 
254
305
  /**
@@ -280,6 +331,14 @@ export function colourScheme(mode, people, tierColors, social) {
280
331
  legend: [...top.map(([, c], i) => [c.name, COMPANY_COLOURS[i]]), ['Other', OTHER]],
281
332
  };
282
333
  }
334
+ if (mode === 'heat') {
335
+ const heat = heatOf(people);
336
+ return {
337
+ of: (d) => heatColour(heat(d)),
338
+ heat,
339
+ legend: [['Cold', heatColour(0.1)], ['Warm', heatColour(0.45)], ['Hot', heatColour(0.75)], ['Hottest', heatColour(1)]],
340
+ };
341
+ }
283
342
  if (mode === 'warmth' && social) {
284
343
  return {
285
344
  of: (d) => ((d.degree || 1) === 1 ? WARMTH_COLOURS[warmthOf(social.merged.get(keyFor(d)), social.asOf)] : '#2d3748'),
@@ -103,6 +103,8 @@ export function refreshNotifications({ added = [], checked = 0, tierOf = () => n
103
103
  out.push({
104
104
  user_id, type: 'new_elite_connection', title: `High-value connection: ${r.name}`,
105
105
  message: r.headline?.substring(0, 60), icon: '👑',
106
+ // Who it is, so the notification can open them (lib/notifications.js noteSubject).
107
+ data: { profileUrl: r.profile_url },
106
108
  });
107
109
  }
108
110
  return out;
@@ -34,3 +34,43 @@ export function clearActivity(id) {
34
34
  activities = activities.filter((x) => x.id !== id);
35
35
  listeners.forEach((f) => f());
36
36
  }
37
+
38
+ // The notch's buttons: the views of the page you're on (Bridge Chains,
39
+ // Separation…), or any page's own sub-tabs. A page sets them while it's on
40
+ // screen and clears them when it leaves; the notch draws them under the header's
41
+ // tabs (Blake, 2026-10-02: "the notch… under the ui buttons at top so then we
42
+ // can use that for button selection too").
43
+ //
44
+ // setNotchTabs({ items: [{ key, label, icon?, title? }], current, onPick })
45
+ // setNotchTabs(null)
46
+ const tabListeners = new Set();
47
+ let notchTabs = null;
48
+
49
+ export const notchTabsNow = () => notchTabs;
50
+ export const noNotchTabs = () => null;
51
+
52
+ export function watchNotchTabs(f) {
53
+ tabListeners.add(f);
54
+ return () => tabListeners.delete(f);
55
+ }
56
+
57
+ // Whether the notch is on screen at all (tabs, a scan, or another job), so a
58
+ // page with a heading at the top can leave room for it only when it's there.
59
+ const shownListeners = new Set();
60
+ let notchShown = false;
61
+ export const notchShownNow = () => notchShown;
62
+ export const noNotch = () => false;
63
+ export function watchNotchShown(f) {
64
+ shownListeners.add(f);
65
+ return () => shownListeners.delete(f);
66
+ }
67
+ export function setNotchShown(shown) {
68
+ if (notchShown === Boolean(shown)) return;
69
+ notchShown = Boolean(shown);
70
+ shownListeners.forEach((f) => f());
71
+ }
72
+
73
+ export function setNotchTabs(tabs) {
74
+ notchTabs = tabs && Array.isArray(tabs.items) && tabs.items.length > 1 ? tabs : null;
75
+ tabListeners.forEach((f) => f());
76
+ }