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
@@ -15,6 +15,12 @@
15
15
  import { useEffect, useMemo, useRef, useState } from 'react';
16
16
  import { forceCollide, forceLink, forceManyBody, forceSimulation, forceX, forceY } from 'd3';
17
17
  import { useCompanyScores, ScorePicker } from './CompanyScores';
18
+ import PeopleMap from './PeopleMap';
19
+ import { TierGrid } from './FilterPanel';
20
+ import { MapLook, useLivePhysics, HeatDefs, HeatGlow, PHYSICS_OFF } from './MapControls';
21
+ import { makeGrid, shows, gridCounts } from '../../lib/tier-grid';
22
+ import { heatBy, heatColour } from '../../lib/galaxy-lab';
23
+ import { companyStrength } from '../../lib/map-heat';
18
24
  import {
19
25
  buildCompanyIndex, companyLinks, companyOf, getSeniority, industryOf, industryByKey,
20
26
  INDUSTRIES, UNKNOWN_INDUSTRY, waysInto, isSenior,
@@ -25,13 +31,13 @@ const LINE = '1px solid rgba(255,255,255,0.1)';
25
31
  const MAX_BUBBLES = 140;
26
32
  const ALL_INDUSTRIES = [...INDUSTRIES, UNKNOWN_INDUSTRY];
27
33
 
28
- function jitter(text) {
34
+ export function jitter(text) {
29
35
  let h = 2166136261;
30
36
  for (let i = 0; i < text.length; i++) h = Math.imul(h ^ text.charCodeAt(i), 16777619);
31
37
  return ((h >>> 0) % 1000) / 1000;
32
38
  }
33
39
 
34
- function Seg({ value, onChange, options }) {
40
+ export function Seg({ value, onChange, options }) {
35
41
  return (
36
42
  <div style={{ display: 'flex', borderRadius: 7, overflow: 'hidden', border: LINE }}>
37
43
  {options.map(([v, label]) => (
@@ -44,7 +50,7 @@ function Seg({ value, onChange, options }) {
44
50
  );
45
51
  }
46
52
 
47
- function useSize(ref) {
53
+ export function useSize(ref) {
48
54
  const [size, setSize] = useState({ w: 0, h: 0 });
49
55
  useEffect(() => {
50
56
  const el = ref.current;
@@ -61,22 +67,73 @@ function useSize(ref) {
61
67
  return size;
62
68
  }
63
69
 
64
- /** Does this person pass the filters? */
70
+ /**
71
+ * The left panel, as on the map page (app/components/FilterPanel.js): a
72
+ * Filters tab at the edge until opened, then a column the map makes room for.
73
+ * Paths' filters, and the ways to read the map, live here (Blake, 2026-10-02:
74
+ * "incorporate the filter with maybe ways to read the data more").
75
+ */
76
+ export function SidePanel({ open, onToggle, children }) {
77
+ if (!open) {
78
+ return (
79
+ <button type="button" onClick={onToggle} style={{
80
+ position: 'fixed', left: 16, top: 140, zIndex: 30, cursor: 'pointer', height: 36, borderRadius: 18, padding: '0 14px 0 10px',
81
+ display: 'flex', alignItems: 'center', gap: 6, background: 'rgba(52,152,219,0.15)', border: '2px solid rgba(52,152,219,0.5)',
82
+ color: '#3498DB', fontWeight: 700, boxShadow: '0 0 12px rgba(52,152,219,0.3)', backdropFilter: 'blur(8px)',
83
+ }}>
84
+ <span style={{ fontSize: 18 }}>›</span><span style={{ fontSize: 11, fontWeight: 600 }}>Filters</span>
85
+ </button>
86
+ );
87
+ }
88
+ return (
89
+ <aside style={{
90
+ width: 300, flexShrink: 0, height: '100%', overflowY: 'auto', boxSizing: 'border-box', padding: '16px 14px',
91
+ borderRight: '1px solid rgba(52,152,219,0.15)', background: 'rgba(10,15,30,0.65)', fontSize: 13,
92
+ }}>
93
+ <button type="button" onClick={onToggle} style={{
94
+ display: 'flex', alignItems: 'center', gap: 6, width: '100%', marginBottom: 14, padding: '6px 12px', borderRadius: 6, cursor: 'pointer',
95
+ background: 'rgba(255,255,255,0.06)', border: '1px solid rgba(255,255,255,0.1)', color: '#aaa', fontSize: 12, fontWeight: 600,
96
+ }}><span style={{ fontSize: 16 }}>›</span> Close</button>
97
+ {children}
98
+ </aside>
99
+ );
100
+ }
101
+
102
+ export const panelHeading = { fontSize: 9, fontWeight: 700, color: '#555', letterSpacing: 1, margin: '14px 0 6px', textTransform: 'uppercase' };
103
+
104
+ /** Does this person pass the filters? Tier and degree from the grid, as in Network Circle. */
65
105
  function passes(p, f) {
66
- if (f.degree !== 'all' && String(p.degree) !== f.degree) return false;
106
+ if (f.grid && !shows(f.grid, p.tier, Number(p.degree) || 1)) return false;
67
107
  if (f.seniority === 'senior' && !isSenior(p.headline)) return false;
68
108
  if (f.seniority === 'csuite' && getSeniority(p.headline).level < 6) return false;
69
- if (f.tier === 'SA' && p.tier !== 'S' && p.tier !== 'A') return false;
70
109
  return true;
71
110
  }
72
111
 
73
- export default function PathsAnalyzer({ d1 = [], d2 = [], d3 = [], tab = 'map', onOpenCompany }) {
74
- const [filters, setFilters] = useState({ degree: 'all', seniority: 'all', tier: 'all' });
112
+ /** What the map's bubbles are: companies, or your connections (Paths → People). An easy switch at the top of the panel. */
113
+ function ShowSwitch({ show, onShow }) {
114
+ return (
115
+ <div style={{ marginBottom: 6 }}>
116
+ <div style={{ ...panelHeading, marginTop: 0 }}>Bubbles are</div>
117
+ <Seg value={show} onChange={onShow} options={[['companies', 'Companies'], ['people', 'People']]} />
118
+ </div>
119
+ );
120
+ }
121
+
122
+ export default function PathsAnalyzer({ d1 = [], d2 = [], d3 = [], initialShow = 'companies', onOpenCompany }) {
123
+ const [show, setShow] = useState(initialShow);
124
+ const [filters, setFilters] = useState(() => ({ seniority: 'all', grid: makeGrid([1, 2, 3]) }));
125
+ const [colourBy, setColourBy] = useState('sector');
126
+ const [physics, setPhysics] = useState(PHYSICS_OFF);
75
127
  const [hidden, setHidden] = useState(() => new Set()); // industries toggled off
76
128
  const [query, setQuery] = useState('');
77
129
  const [focus, setFocus] = useState(null); // { kind: 'company'|'industry', key }
130
+ const [panelOpen, setPanelOpen] = useState(true);
131
+ // Ways to read the map: what a bubble's size means, and which names show.
132
+ const [sizeBy, setSizeBy] = useState('people'); // 'people' | 'sa' | 'known'
133
+ const [labels, setLabels] = useState('top'); // 'top' | 'all' | 'none'
78
134
 
79
135
  const rows = useMemo(() => [...d1, ...d2, ...d3], [d1, d2, d3]);
136
+ const counts = useMemo(() => gridCounts({ 1: d1, 2: d2, 3: d3 }), [d1, d2, d3]);
80
137
  const index = useMemo(() => buildCompanyIndex(rows), [rows]);
81
138
  const links = useMemo(() => companyLinks(d1, d2), [d1, d2]);
82
139
 
@@ -115,44 +172,65 @@ export default function PathsAnalyzer({ d1 = [], d2 = [], d3 = [], tab = 'map',
115
172
  const panel = focus?.kind === 'company' ? index.get(focus.key)
116
173
  : focus?.kind === 'industry' ? industries.find((i) => i.key === focus.key) : null;
117
174
 
175
+ const look = (heatHint) => (
176
+ <MapLook colourBy={colourBy} onColourBy={setColourBy} physics={physics} onPhysics={setPhysics} heatHint={heatHint} />
177
+ );
178
+
179
+ // People: the same map with your connections as the bubbles (app/components/PeopleMap.js),
180
+ // with the same switch, colours and physics.
181
+ if (show === 'people') {
182
+ return (
183
+ <PeopleMap d1={d1} d2={d2} top={<ShowSwitch show={show} onShow={setShow} />}
184
+ colourBy={colourBy} physics={physics}
185
+ look={look('How strong each cluster is, person for person (S counts 3, A 2, the rest 1): the hotter, the stronger. Size is still how big it is.')} />
186
+ );
187
+ }
188
+
118
189
  return (
119
190
  <div style={{ display: 'flex', flex: 1, minHeight: 0 }}>
120
- <div style={{ flex: 1, minWidth: 0, display: 'flex', flexDirection: 'column' }}>
121
- <Filters filters={filters} setFilters={setFilters} query={query} setQuery={setQuery}
191
+ <SidePanel open={panelOpen} onToggle={() => setPanelOpen((o) => !o)}>
192
+ <ShowSwitch show={show} onShow={setShow} />
193
+ <Filters filters={filters} setFilters={setFilters} counts={counts} query={query} setQuery={setQuery}
122
194
  industries={industries} hidden={hidden} setHidden={setHidden}
123
195
  onIndustry={(key) => setFocus({ kind: 'industry', key })} />
124
- {tab === 'map' ? (
125
- <CompanyMap companies={companies} links={links} focus={focus}
126
- onCompany={(name) => setFocus({ kind: 'company', key: name })}
127
- onIndustry={(key) => setFocus({ kind: 'industry', key })}
128
- onClear={() => setFocus(null)} />
129
- ) : (
130
- <IndustryCards industries={industries} index={index} d1={d1} d2={d2}
131
- onIndustry={(key) => setFocus({ kind: 'industry', key })}
132
- onCompany={(name) => setFocus({ kind: 'company', key: name })} />
133
- )}
196
+ <div style={panelHeading}>Read the map</div>
197
+ <div style={{ fontSize: 11, color: '#8b9a9a', marginBottom: 4 }}>Bubble size</div>
198
+ <Seg value={sizeBy} onChange={setSizeBy} options={[['people', 'Your people'], ['sa', 'S & A there'], ['known', 'You know']]} />
199
+ <div style={{ fontSize: 11, color: '#8b9a9a', margin: '10px 0 4px' }}>Names</div>
200
+ <Seg value={labels} onChange={setLabels} options={[['top', 'Biggest'], ['all', 'All'], ['none', 'None']]} />
201
+ {look('How strong your people at each company are: the average power score of the five strongest. The hotter, the stronger; size is still how many.')}
202
+ </SidePanel>
203
+ {/* Room at the top for the notch's Map / Companies, so it never covers a label */}
204
+ <div style={{ flex: 1, minWidth: 0, display: 'flex', flexDirection: 'column', paddingTop: 40, boxSizing: 'border-box' }}>
205
+ <CompanyMap companies={companies} links={links} focus={focus} sizeBy={sizeBy} labels={labels}
206
+ colourBy={colourBy} physics={physics}
207
+ onCompany={(name) => setFocus({ kind: 'company', key: name })}
208
+ onIndustry={(key) => setFocus({ kind: 'industry', key })}
209
+ onClear={() => setFocus(null)} />
134
210
  </div>
135
211
  {panel && (
136
212
  <AnalyzerPanel focus={focus} data={panel} index={index} links={links} d1={d1} d2={d2}
137
213
  filters={filters} onClose={() => setFocus(null)}
138
214
  onCompany={(name) => setFocus({ kind: 'company', key: name })}
215
+ onIndustry={(key) => setFocus({ kind: 'industry', key })}
139
216
  onOpenCompany={onOpenCompany} />
140
217
  )}
141
218
  </div>
142
219
  );
143
220
  }
144
221
 
145
- function Filters({ filters, setFilters, query, setQuery, industries, hidden, setHidden, onIndustry }) {
222
+ function Filters({ filters, setFilters, counts, query, setQuery, industries, hidden, setHidden, onIndustry }) {
146
223
  const set = (k, v) => setFilters((f) => ({ ...f, [k]: v }));
147
224
  return (
148
- <div style={{ padding: '10px 16px', borderBottom: LINE, display: 'flex', flexDirection: 'column', gap: 8 }}>
149
- <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', alignItems: 'center' }}>
150
- <input value={query} onChange={(e) => setQuery(e.target.value)} placeholder="Find a company"
151
- style={{ padding: '6px 10px', borderRadius: 7, border: LINE, background: 'rgba(255,255,255,0.05)', color: '#fff', fontSize: 13, minWidth: 170 }} />
152
- <Seg value={filters.degree} onChange={(v) => set('degree', v)} options={[['all', 'All degrees'], ['1', '1st'], ['2', '2nd'], ['3', '3rd']]} />
153
- <Seg value={filters.seniority} onChange={(v) => set('seniority', v)} options={[['all', 'Any level'], ['senior', 'Director+'], ['csuite', 'C-suite']]} />
154
- <Seg value={filters.tier} onChange={(v) => set('tier', v)} options={[['all', 'All tiers'], ['SA', 'S & A only']]} />
155
- </div>
225
+ <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
226
+ <div style={panelHeading}>Filter</div>
227
+ <input value={query} onChange={(e) => setQuery(e.target.value)} placeholder="Find a company"
228
+ style={{ padding: '6px 10px', borderRadius: 7, border: LINE, background: 'rgba(255,255,255,0.05)', color: '#fff', fontSize: 13, width: '100%', boxSizing: 'border-box' }} />
229
+ {/* The same tiers × degrees as Network Circle (Blake, 2026-10-02) */}
230
+ <TierGrid grid={filters.grid} counts={counts} onChange={(g) => set('grid', g)} mode="paths" />
231
+ <div style={{ fontSize: 11, color: '#8b9a9a', marginTop: -10 }}>Level</div>
232
+ <Seg value={filters.seniority} onChange={(v) => set('seniority', v)} options={[['all', 'Any level'], ['senior', 'Director+'], ['csuite', 'C-suite']]} />
233
+ <div style={panelHeading}>Industries</div>
156
234
  <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
157
235
  {industries.map((i) => {
158
236
  const off = hidden.has(i.key);
@@ -168,13 +246,13 @@ function Filters({ filters, setFilters, query, setQuery, industries, hidden, set
168
246
  </span>
169
247
  );
170
248
  })}
171
- <span style={{ fontSize: 11, color: '#667', alignSelf: 'center' }}>industries inferred from companies and headlines</span>
249
+ <span style={{ fontSize: 11, color: '#667', alignSelf: 'center' }}>Inferred from companies and headlines. ● hides one; its name opens it.</span>
172
250
  </div>
173
251
  </div>
174
252
  );
175
253
  }
176
254
 
177
- function CompanyMap({ companies, links, focus, onCompany, onIndustry, onClear }) {
255
+ function CompanyMap({ companies, links, focus, onCompany, onIndustry, onClear, sizeBy = 'people', labels: names = 'top', colourBy = 'sector', physics = PHYSICS_OFF }) {
178
256
  const wrap = useRef(null);
179
257
  const { w, h } = useSize(wrap);
180
258
  const [hover, setHover] = useState(null);
@@ -191,17 +269,22 @@ function CompanyMap({ companies, links, focus, onCompany, onIndustry, onClear })
191
269
  return [k, { x: Math.cos(a) * R, y: Math.sin(a) * R }];
192
270
  }));
193
271
  const nodes = shown.map((c) => ({
194
- id: c.name, co: c, r: 4 + Math.sqrt(c.shown.length) * 3.4,
272
+ id: c.name, co: c,
273
+ // Size: your people there, the S and A among them, or the ones you already know.
274
+ r: 4 + Math.sqrt(sizeBy === 'sa' ? c.shown.filter((p) => p.tier === 'S' || p.tier === 'A').length : sizeBy === 'known' ? c.d1 : c.shown.length) * (sizeBy === 'people' ? 3.4 : 5),
195
275
  // A fixed jitter from the name, so the same network always lays out the same.
196
276
  x: anchor.get(c.industry.key).x + (jitter(c.name) - 0.5) * 40, y: anchor.get(c.industry.key).y + (jitter(c.name + '#') - 0.5) * 40,
277
+ // Where its industry sits, for live physics (MapControls.js).
278
+ ax: anchor.get(c.industry.key).x, ay: anchor.get(c.industry.key).y,
197
279
  }));
198
- const edges = links.filter((l) => names.has(l.a) && names.has(l.b)).map((l) => ({ source: l.a, target: l.b, weight: l.weight, via: l.via.size }));
280
+ const edges = links.filter((l) => names.has(l.a) && names.has(l.b))
281
+ .map((l) => ({ source: l.a, target: l.b, weight: l.weight, via: l.via.size, k: Math.min(0.25, 0.03 * l.weight) }));
199
282
  const sim = forceSimulation(nodes)
200
283
  .force('x', forceX((d) => anchor.get(d.co.industry.key).x).strength(0.12))
201
284
  .force('y', forceY((d) => anchor.get(d.co.industry.key).y).strength(0.12))
202
285
  .force('collide', forceCollide((d) => d.r + 3))
203
286
  .force('charge', forceManyBody().strength(-25))
204
- .force('link', forceLink(edges).id((d) => d.id).strength((e) => Math.min(0.25, 0.03 * e.weight)).distance(60))
287
+ .force('link', forceLink(edges).id((d) => d.id).strength((e) => e.k).distance(60))
205
288
  .stop();
206
289
  for (let i = 0; i < 320; i++) sim.tick();
207
290
  const xs = nodes.flatMap((n) => [n.x - n.r, n.x + n.r]);
@@ -232,7 +315,14 @@ function CompanyMap({ companies, links, focus, onCompany, onIndustry, onClear })
232
315
  // cluster's label never lands on it.
233
316
  box.h += Math.max(60, box.h * 0.1);
234
317
  return { nodes, edges, box, labels, cut: Math.max(0, companies.length - shown.length) };
235
- }, [companies, links]);
318
+ }, [companies, links, sizeBy]);
319
+ const { drag, clicked } = useLivePhysics(layout, physics);
320
+ // Heat: how strong your people at each company are, ranked among the bubbles shown.
321
+ const heat = useMemo(() => {
322
+ const strength = new Map(layout.nodes.map((n) => [n.id, companyStrength(n.co.shown)]));
323
+ return heatBy(layout.nodes, (n) => strength.get(n.id));
324
+ }, [layout]);
325
+ const hot = colourBy === 'heat';
236
326
 
237
327
  const active = hover || (focus?.kind === 'company' ? focus.key : null);
238
328
  const activeInd = focus?.kind === 'industry' ? focus.key : null;
@@ -245,12 +335,14 @@ function CompanyMap({ companies, links, focus, onCompany, onIndustry, onClear })
245
335
  }
246
336
  return s;
247
337
  }, [active, layout]);
248
- const labelled = useMemo(() => new Set(layout.nodes.slice(0, 28).map((n) => n.id)), [layout]);
338
+ const labelled = useMemo(() => new Set(names === 'none' ? [] : (names === 'all' ? layout.nodes : [...layout.nodes].sort((a, b) => b.r - a.r).slice(0, 28)).map((n) => n.id)), [layout, names]);
249
339
 
250
340
  return (
251
341
  <div ref={wrap} style={{ flex: 1, minHeight: 360, position: 'relative' }} onClick={onClear}>
252
342
  {w > 0 && (
253
- <svg width={w} height={h} viewBox={`${layout.box.x} ${layout.box.y} ${layout.box.w} ${layout.box.h}`} style={{ display: 'block' }}>
343
+ <svg width={w} height={h} viewBox={`${layout.box.x} ${layout.box.y} ${layout.box.w} ${layout.box.h}`} style={{ display: 'block', touchAction: drag ? 'none' : undefined }}>
344
+ {hot && <HeatDefs id="coheat" />}
345
+ {hot && <HeatGlow id="coheat" nodes={layout.nodes} heat={heat} />}
254
346
  <g>
255
347
  {layout.edges.map((e, i) => {
256
348
  const on = active && (e.source.id === active || e.target.id === active);
@@ -272,12 +364,13 @@ function CompanyMap({ companies, links, focus, onCompany, onIndustry, onClear })
272
364
  const dim = (neighbours && !neighbours.has(n.id)) || (activeInd && n.co.industry.key !== activeInd);
273
365
  const sel = focus?.kind === 'company' && focus.key === n.id;
274
366
  return (
275
- <g key={n.id} transform={`translate(${n.x},${n.y})`} style={{ cursor: 'pointer' }}
367
+ <g key={n.id} transform={`translate(${n.x},${n.y})`} style={{ cursor: drag ? 'grab' : 'pointer' }}
276
368
  opacity={dim ? 0.18 : 1}
277
369
  onMouseEnter={() => setHover(n.id)} onMouseLeave={() => setHover(null)}
278
- onClick={(ev) => { ev.stopPropagation(); onCompany(n.id); }}>
370
+ onPointerDown={drag ? (ev) => drag(ev, n) : undefined}
371
+ onClick={(ev) => { ev.stopPropagation(); if (clicked()) onCompany(n.id); }}>
279
372
  <title>{`${n.co.name} · ${n.co.industry.label} (inferred)\n${n.co.d1} you know · ${n.co.d2} reachable${n.co.d3 ? ` · ${n.co.d3} further` : ''}`}</title>
280
- <circle r={n.r} fill={n.co.industry.color} fillOpacity={0.75}
373
+ <circle r={n.r} fill={hot ? heatColour(heat(n)) : n.co.industry.color} fillOpacity={hot ? 0.9 : 0.75}
281
374
  stroke={sel ? '#fff' : n.co.S ? TIER.S : 'rgba(0,0,0,0.35)'} strokeWidth={sel ? 2.5 : n.co.S ? 1.5 : 0.6} />
282
375
  {/* the share you already know, as an inner disc */}
283
376
  {n.co.d1 > 0 && <circle r={n.r * Math.sqrt(n.co.d1 / Math.max(1, n.co.people.length))} fill="#fff" fillOpacity={0.35} />}
@@ -290,9 +383,9 @@ function CompanyMap({ companies, links, focus, onCompany, onIndustry, onClear })
290
383
  </svg>
291
384
  )}
292
385
  <div style={{ position: 'absolute', left: 12, bottom: 10, fontSize: 11, color: '#778', lineHeight: 1.6, pointerEvents: 'none' }}>
293
- Bubble = a company, sized by your people there; white centre = the share you already know; gold ring = an S-tier person inside.<br />
386
+ Bubble = a company, sized by your people there; {hot ? 'colour = how strong they are, cold to white hot' : 'colour = its industry'}; white centre = the share you already know; gold ring = an S-tier person inside.<br />
294
387
  A line = one of your connections at one company knows people at the other.
295
- {layout.cut ? ` Showing the ${MAX_BUBBLES} largest; ${layout.cut} smaller companies are in Industries.` : ''}
388
+ {layout.cut ? ` Showing the ${MAX_BUBBLES} largest; ${layout.cut} smaller companies are in Companies.` : ''}
296
389
  </div>
297
390
  </div>
298
391
  );
@@ -306,69 +399,6 @@ function Bar({ parts, total }) {
306
399
  );
307
400
  }
308
401
 
309
- function IndustryCards({ industries, index, d1, d2, onIndustry, onCompany }) {
310
- const bridgesInto = useMemo(() => {
311
- const byId = new Map(d1.map((c) => [c.id, c]));
312
- const out = new Map();
313
- for (const r of d2) {
314
- const co = companyOf(r);
315
- const ind = co ? index.get(co)?.industry.key : industryOf(null, r.headline).key;
316
- if (!ind) continue;
317
- const m = out.get(ind) || new Map();
318
- m.set(r.source_connection_id, (m.get(r.source_connection_id) || 0) + 1);
319
- out.set(ind, m);
320
- }
321
- const best = new Map();
322
- for (const [ind, m] of out) {
323
- const [id, n] = [...m.entries()].sort((a, b) => b[1] - a[1])[0] || [];
324
- if (byId.get(id)) best.set(ind, { bridge: byId.get(id), n });
325
- }
326
- return best;
327
- }, [index, d1, d2]);
328
-
329
- return (
330
- <div style={{ flex: 1, overflow: 'auto', padding: 16 }}>
331
- <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(280px, 1fr))', gap: 12 }}>
332
- {industries.map((i) => {
333
- const d1n = i.people.filter((p) => p.degree === 1).length;
334
- const d2n = i.people.filter((p) => p.degree === 2).length;
335
- const senior = i.people.filter((p) => isSenior(p.headline)).length;
336
- const S = i.people.filter((p) => p.tier === 'S').length;
337
- const topCos = [...i.companies.entries()].sort((a, b) => b[1] - a[1]).slice(0, 3);
338
- const way = bridgesInto.get(i.key);
339
- return (
340
- <div key={i.key} onClick={() => onIndustry(i.key)} style={{ padding: 14, borderRadius: 10, border: LINE, borderTop: `3px solid ${i.color}`, background: 'rgba(255,255,255,0.03)', cursor: 'pointer' }}>
341
- <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
342
- <b style={{ fontSize: 14, color: i.color }}>{i.label}</b>
343
- <span style={{ fontSize: 20, fontWeight: 800 }}>{i.people.length}</span>
344
- </div>
345
- <div style={{ fontSize: 11.5, color: '#8b9a9a', margin: '4px 0 6px' }}>
346
- {d1n} you know · {d2n} reachable · {i.companies.size} companies · {senior} director+ · {S} S-tier
347
- </div>
348
- <Bar total={i.people.length} parts={[[d1n, '#00ff88'], [d2n, '#FF6B35']]} />
349
- {topCos.length > 0 && (
350
- <div style={{ marginTop: 8, display: 'flex', gap: 6, flexWrap: 'wrap' }}>
351
- {topCos.map(([name, n]) => (
352
- <button key={name} onClick={(e) => { e.stopPropagation(); onCompany(name); }}
353
- style={{ padding: '2px 8px', borderRadius: 10, border: LINE, background: 'rgba(255,255,255,0.05)', color: '#dfe6e9', fontSize: 11, cursor: 'pointer' }}>
354
- {name} <span style={{ color: '#778' }}>{n}</span>
355
- </button>
356
- ))}
357
- </div>
358
- )}
359
- {way && (
360
- <div style={{ marginTop: 8, fontSize: 11.5, color: '#aab7b7' }}>
361
- Best way in: <b style={{ color: TIER[way.bridge.tier] || '#ccc' }}>{way.bridge.name}</b> knows {way.n} here
362
- </div>
363
- )}
364
- </div>
365
- );
366
- })}
367
- </div>
368
- </div>
369
- );
370
- }
371
-
372
402
  function PersonLine({ p, note }) {
373
403
  return (
374
404
  <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '5px 0', fontSize: 12.5 }}>
@@ -381,7 +411,7 @@ function PersonLine({ p, note }) {
381
411
  );
382
412
  }
383
413
 
384
- function AnalyzerPanel({ focus, data, index, links, d1, d2, filters, onClose, onCompany, onOpenCompany }) {
414
+ function AnalyzerPanel({ focus, data, index, links, d1, d2, filters, onClose, onCompany, onIndustry, onOpenCompany }) {
385
415
  const isCompany = focus.kind === 'company';
386
416
  const people = (isCompany ? data.people : data.people).filter((p) => passes(p, filters));
387
417
  const levels = useMemo(() => {
@@ -410,9 +440,16 @@ function AnalyzerPanel({ focus, data, index, links, d1, d2, filters, onClose, on
410
440
  <button onClick={onClose} style={{ background: 'none', border: 'none', color: '#888', cursor: 'pointer', fontSize: 12, padding: 0 }}>✕ Close</button>
411
441
  <div style={{ fontSize: 10, letterSpacing: 1, color: '#8b9a9a', marginTop: 8 }}>{isCompany ? 'COMPANY' : 'INDUSTRY'} ANALYZER</div>
412
442
  <h2 style={{ margin: '4px 0 6px', fontSize: 20 }}>{isCompany ? data.name : data.label}</h2>
413
- <span style={{ fontSize: 11, padding: '2px 8px', borderRadius: 10, background: `${industry.color}22`, color: industry.color }}>
414
- {industry.label}{isCompany ? ' · inferred' : ''}
415
- </span>
443
+ {/* A company's industry opens that industry here (Blake, 2026-10-02: industries live in the side card, not a tab). */}
444
+ {isCompany && onIndustry ? (
445
+ <button type="button" onClick={() => onIndustry(industry.key)} title={`Open ${industry.label}: everyone there and its top companies`} style={{
446
+ fontSize: 11, padding: '2px 8px', borderRadius: 10, border: 'none', cursor: 'pointer', background: `${industry.color}22`, color: industry.color,
447
+ }}>{industry.label} · inferred →</button>
448
+ ) : (
449
+ <span style={{ fontSize: 11, padding: '2px 8px', borderRadius: 10, background: `${industry.color}22`, color: industry.color }}>
450
+ {industry.label}{isCompany ? ' · inferred' : ''}
451
+ </span>
452
+ )}
416
453
  {isCompany && <CompanyScoreLine name={data.name} />}
417
454
 
418
455
  <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 8, margin: '14px 0' }}>
@@ -505,7 +542,7 @@ function Section({ title, children }) {
505
542
  }
506
543
 
507
544
  // The company's score in people's power, where it comes from, and a control
508
- // to set it (the Scores tab has every company).
545
+ // to set it (Settings → Scores has every company).
509
546
  function CompanyScoreLine({ name }) {
510
547
  const { companies, setScore } = useCompanyScores();
511
548
  const c = companies?.find((x) => x.name === name);