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
@@ -14,9 +14,11 @@ import { reachIndex, reachState, circleState, readyToScan, circleScanCost } from
14
14
  import { exclusiveReach, bridgeOverlap } from '../../lib/brokerage';
15
15
  import { profileInsights } from '../../lib/insights';
16
16
  import Avatar from './Avatar';
17
+ import NoteDetail from './NoteDetail';
18
+ import CirclePanel from './CirclePanel';
17
19
  import { localPhoto } from '../../lib/photos';
18
20
 
19
- export default function Sidebar({ selected, stats, tierColors, connections, degree2 = [], mode, collapsed, filter, pending = [], onToggle, onSelect, onSwitchMode, onFocusNode, onMarkSent, onUndoPending, scanNotes, csvSource = null, onOpenCircle, onShowInSeparation }) {
21
+ export default function Sidebar({ selected, stats, tierColors, connections, degree2 = [], mode, collapsed, filter, pending = [], onToggle, onSelect, onSwitchMode, onFocusNode, onMarkSent, onUndoPending, scanNotes, csvSource = null, onOpenCircle, onShowInSeparation, note = null, onCloseNote, circle = null }) {
20
22
  const isDegreesMode = mode === 'degrees';
21
23
  // 'sample' or 'csv' while the sample or a CSV import is open in this window,
22
24
  // null for your own network. Only your own can be scanned: the scanner looks
@@ -53,6 +55,18 @@ export default function Sidebar({ selected, stats, tierColors, connections, degr
53
55
  const requests = useRequests();
54
56
  const isRequested = useCallback((row) => hasRequest(row, requests), [requests]);
55
57
 
58
+ // A notification someone clicked takes the panel over until they go back (app/components/NoteDetail.js).
59
+ if (note) {
60
+ return (
61
+ <SidebarWrapper collapsed={collapsed} onToggle={onToggle}>
62
+ <NoteDetail note={note} connections={connections} degree2={degree2} onBack={onCloseNote}
63
+ onSelect={(p) => { onCloseNote?.(); onSelect?.(p); }}
64
+ onOpenCircle={onOpenCircle ? (id) => { onCloseNote?.(); onOpenCircle(id); } : undefined}
65
+ onShowInSeparation={onShowInSeparation ? (preset) => { onCloseNote?.(); onShowInSeparation(preset); } : undefined} />
66
+ </SidebarWrapper>
67
+ );
68
+ }
69
+
56
70
  if (selected) {
57
71
  const isBridge = selected.degree === 1 && bridgeMap[selected.id];
58
72
  const bridgeConnections = bridgeMap[selected.id] || [];
@@ -494,6 +508,16 @@ export default function Sidebar({ selected, stats, tierColors, connections, degr
494
508
  );
495
509
  }
496
510
 
511
+ // A circle open in Bridge Chains: the panel is about whoever's circle you're in.
512
+ if (isDegreesMode && circle) {
513
+ return (
514
+ <SidebarWrapper collapsed={collapsed} onToggle={onToggle}>
515
+ <CirclePanel key={circle.id} person={circle} connections={connections} degree2={degree2} scanNotes={scanNotes}
516
+ tierColors={tierColors} onSelect={onSelect} onToggle={onToggle} canScan={canScan} />
517
+ </SidebarWrapper>
518
+ );
519
+ }
520
+
497
521
  if (isDegreesMode) {
498
522
  return (
499
523
  <SidebarWrapper collapsed={collapsed} onToggle={onToggle}>
@@ -1202,7 +1226,9 @@ function ScanLog({ title, log, small = false }) {
1202
1226
  padding: '10px', borderRadius: 8, background: 'rgba(155,89,182,0.1)', border: '1px solid rgba(155,89,182,0.3)',
1203
1227
  }}>
1204
1228
  <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 4 }}>
1205
- <div style={{ width: small ? 6 : 8, height: small ? 6 : 8, borderRadius: '50%', background: '#9B59B6', animation: 'pulse 1s infinite' }} />
1229
+ {/* Its own keyframes: the 'pulse' this named was never defined anywhere, so the dot sat still. */}
1230
+ <style>{'@keyframes scanlogPulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .35; transform: scale(.7); } } @media (prefers-reduced-motion: reduce) { .scanlog-dot { animation: none !important; } }'}</style>
1231
+ <div className="scanlog-dot" style={{ width: small ? 6 : 8, height: small ? 6 : 8, borderRadius: '50%', background: '#9B59B6', animation: 'scanlogPulse 1s ease-in-out infinite' }} />
1206
1232
  <span style={{ fontSize: 11, fontWeight: 600, color: '#9B59B6' }}>{title}</span>
1207
1233
  </div>
1208
1234
  <div style={{ fontFamily: 'monospace', fontSize: small ? 9 : 10, color: '#888', maxHeight: small ? 80 : 100, overflow: 'auto' }}>
@@ -79,6 +79,7 @@ export default function DataSection() {
79
79
  const [exportNote, setExportNote] = useState(null);
80
80
  const [importNote, setImportNote] = useState(null);
81
81
  const [photos, setPhotos] = useState(true);
82
+ const [social, setSocial] = useState(true);
82
83
  const [file, setFile] = useState(null);
83
84
  const [confirmed, setConfirmed] = useState(false);
84
85
  const [restarting, setRestarting] = useState(false);
@@ -137,7 +138,7 @@ export default function DataSection() {
137
138
  const res = await fetch('/api/data/export', {
138
139
  method: 'POST',
139
140
  headers: { 'Content-Type': 'application/json' },
140
- body: JSON.stringify({ photos }),
141
+ body: JSON.stringify({ photos, social }),
141
142
  });
142
143
  if (!res.ok) await answer(res, 'The copy could not be made.');
143
144
  const blob = await res.blob();
@@ -324,6 +325,13 @@ export default function DataSection() {
324
325
  They can’t be downloaded again without a new scan.
325
326
  </span>
326
327
  </label>
328
+ <label style={check}>
329
+ <input type="checkbox" checked={social} onChange={(e) => setSocial(e.target.checked)} style={{ marginTop: 3 }} />
330
+ <span>
331
+ Include the Social tab: its findings, your CRM notes, stages and follow-ups, and any messages you keep
332
+ there.
333
+ </span>
334
+ </label>
327
335
  <div style={row}>
328
336
  <Btn primary onClick={exportNow} disabled={!!busy || restarting || info.people === 0}>
329
337
  {busy === 'export' ? 'Saving…' : 'Save a copy of my network'}
@@ -334,8 +342,9 @@ export default function DataSection() {
334
342
  <Body style={small}>
335
343
  The copy holds the names, headlines and photos of the people in your network. Keep it private: don’t
336
344
  post it or share it, and delete it once it has been imported. A network opened from a LinkedIn CSV lives
337
- only in its browser tab, so it isn’t in the copy; import the CSV again on the new computer. The Social
338
- tab’s findings, and any messages you keep there, stay on this computer and aren’t in the copy either.
345
+ only in its browser tab, so it isn’t in the copy; import the CSV again on the new computer. With the
346
+ Social tab included, the copy also holds your CRM notes and any messages you keep, so it&rsquo;s as private
347
+ as your inbox.
339
348
  </Body>
340
349
 
341
350
  <h3 style={subhead}>Bring in a network from another computer</h3>
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
 
3
- // Network health on the Scores tab (lib/network-health.js): how much of your
3
+ // Network health, in Profile → Insights (lib/network-health.js; it was on the Scores tab): how much of your
4
4
  // 2nd degree you reach two or more ways, the effective size of your own
5
5
  // network from the ties scans have kept, and your top five connections by who
6
6
  // only they reach. Only your own numbers, never a percentile against others.
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
 
3
- // Scores → Your sector (app/scores; it was Settings → Your sector). Up to three sectors you work in: one of the twelve
3
+ // Settings → Scores → Your field (app/settings; it was a Scores tab of its own from 9/28 to 10/2). Up to three sectors you work in: one of the twelve
4
4
  // broad industries, or a narrower sector from the app's directory (Dental,
5
5
  // Real Estate, Software & SaaS…). Companies in them count for more when your
6
6
  // scanned network is scored, like setting their scores by hand on Paths →
@@ -78,7 +78,7 @@ export default function SectorSection({ onSaved } = {}) {
78
78
  return () => { off = true; clearTimeout(timer.current); };
79
79
  }, []);
80
80
 
81
- // Links to /scores#sector (the profile's card, the old /settings#sector) arrive
81
+ // Links to /settings#sector (the profile's card, the old /scores#sector) arrive
82
82
  // before this section has loaded, so the browser's own jump to it finds
83
83
  // nothing. Jump once it's here, then keep it in place while what loads above
84
84
  // it (Updates) pushes it down: the browser only holds steady what's already
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
 
3
- // Scores → Tiers (app/scores; it was Settings → Tiers). How the S to D rings are drawn: on your network's curve
3
+ // Settings → Scores → Tiers (app/settings; it was a Scores tab of its own from 9/28 to 10/2). How the S to D rings are drawn: on your network's curve
4
4
  // (your top 3% are S, and so on down), or on the fixed scale, the same lines
5
5
  // for everyone. The curve only lifts, so a network full of companies the
6
6
  // curated list knows keeps its tiers. The model is lib/scoring.js (CURVE,
@@ -0,0 +1,149 @@
1
+ 'use client';
2
+
3
+ // Settings → Scores → Titles (Blake, 2026-10-02): how much each kind of title
4
+ // counts, your way. Value founders, investors, or a role you're looking for
5
+ // (outbound, hiring: "find more in that role"), and everyone with it rises.
6
+ // Saving rescores everyone and says how many changed tier, as Tiers does.
7
+ // The setting and its presets are lib/title-ranking.js; scoring applies it
8
+ // (lib/scoring.js rankedPoints).
9
+
10
+ import { useEffect, useRef, useState } from 'react';
11
+ import { Section, Body, Status, Btn, LINE } from '../ui';
12
+ import { LEVELS } from '../../../lib/scoring';
13
+ import { RANKED_LEVELS, NO_RANKING, RANKING_PRESETS, MAX_ROLES, rankingFingerprint } from '../../../lib/title-ranking';
14
+ import { saveSettings } from '../../../lib/settings-client';
15
+
16
+ const POINTS = [10, 9.5, 9, 8.5, 8, 7.5, 7, 6.5, 6, 5.5, 5, 4.5, 4, 3, 2, 1, 0];
17
+ const plural = (n, one, many) => `${n.toLocaleString()} ${n === 1 ? one : many}`;
18
+ const select = {
19
+ padding: '5px 8px', borderRadius: 6, fontSize: 12.5, cursor: 'pointer',
20
+ border: LINE, background: 'rgba(0,0,0,0.3)', color: '#fff',
21
+ };
22
+
23
+ export default function TitleSection({ onSaved } = {}) {
24
+ const [saved, setSaved] = useState(null);
25
+ const [draft, setDraft] = useState(null);
26
+ const [role, setRole] = useState('');
27
+ const [rolePoints, setRolePoints] = useState(10);
28
+ const [saving, setSaving] = useState(false);
29
+ const [result, setResult] = useState(null);
30
+ const [loadError, setLoadError] = useState(null);
31
+ const roleBox = useRef(null);
32
+
33
+ useEffect(() => {
34
+ let off = false;
35
+ fetch('/api/settings')
36
+ .then((r) => r.json().then((d) => (r.ok ? d : Promise.reject(new Error(d.error || 'Could not load your title ranking.')))))
37
+ .then((d) => { if (!off) { const r = d.settings?.titleRanking || NO_RANKING; setSaved(r); setDraft(r); } })
38
+ .catch((e) => { if (!off) setLoadError(e.message); });
39
+ return () => { off = true; };
40
+ }, []);
41
+
42
+ if (!draft) return loadError ? <Status tone="bad">{loadError}</Status> : null;
43
+
44
+ const pointsOf = (key) => draft.points?.[key] ?? LEVELS[key].points;
45
+ const setPoints = (key, v) => {
46
+ const points = { ...draft.points };
47
+ if (v === LEVELS[key].points) delete points[key]; else points[key] = v;
48
+ setDraft({ ...draft, points });
49
+ setResult(null);
50
+ };
51
+ const addRole = () => {
52
+ const text = role.trim().toLowerCase().replace(/\s+/g, ' ');
53
+ if (text.length < 2) return;
54
+ const roles = [...draft.roles.filter((r) => r.text !== text), { text, points: rolePoints }];
55
+ setDraft({ ...draft, roles: roles.slice(-MAX_ROLES) });
56
+ setRole('');
57
+ setResult(null);
58
+ };
59
+ const dropRole = (text) => { setDraft({ ...draft, roles: draft.roles.filter((r) => r.text !== text) }); setResult(null); };
60
+ const preset = RANKING_PRESETS.find((p) => p.ranking && rankingFingerprint(p.ranking) === rankingFingerprint(draft))?.key ?? null;
61
+ const pick = (p) => {
62
+ setResult(null);
63
+ if (p.ranking) setDraft({ points: { ...p.ranking.points }, roles: [...p.ranking.roles] });
64
+ else roleBox.current?.focus();
65
+ };
66
+ const dirty = rankingFingerprint(draft) !== rankingFingerprint(saved);
67
+
68
+ async function save() {
69
+ setSaving(true);
70
+ setResult(null);
71
+ const { settings, effects, error } = await saveSettings({ titleRanking: draft });
72
+ if (settings) { setSaved(settings.titleRanking); setDraft(settings.titleRanking); }
73
+ if (error) setResult({ tone: 'bad', text: error });
74
+ else {
75
+ const e = effects?.titleRanking;
76
+ setResult({ tone: 'ok', text: e ? `Saved. ${plural(e.moved, 'person', 'people')} changed tier.` : 'Saved.' });
77
+ onSaved?.();
78
+ }
79
+ setSaving(false);
80
+ }
81
+
82
+ return (
83
+ <Section id="titles" title="Titles" intro="How much each kind of title counts towards someone's power, out of 10. Change it if you value some people more than the app does: founders, investors, or a role you're looking for.">
84
+ {/* Starting points */}
85
+ <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', marginBottom: 6 }}>
86
+ {RANKING_PRESETS.map((p) => (
87
+ <button key={p.key} type="button" onClick={() => pick(p)} aria-pressed={preset === p.key} title={p.note} style={{
88
+ padding: '6px 12px', borderRadius: 16, fontSize: 12.5, fontWeight: 650, cursor: 'pointer',
89
+ border: preset === p.key ? '1px solid rgba(155,89,182,0.7)' : LINE,
90
+ background: preset === p.key ? 'rgba(155,89,182,0.16)' : 'rgba(255,255,255,0.03)', color: preset === p.key ? '#fff' : '#bbb',
91
+ }}>{p.label}</button>
92
+ ))}
93
+ </div>
94
+ <Body style={{ marginBottom: 14 }}>
95
+ {RANKING_PRESETS.find((p) => p.key === preset)?.note || 'Your own ranking. Higher points rank higher; the company someone works at still weighs it.'}
96
+ </Body>
97
+
98
+ {/* The ladder */}
99
+ <div style={{ display: 'grid', gridTemplateColumns: '1fr auto auto', gap: '6px 12px', alignItems: 'center', maxWidth: 520 }}>
100
+ {RANKED_LEVELS.map((key) => {
101
+ const mine = draft.points?.[key] != null;
102
+ return [
103
+ <div key={`${key}-l`} style={{ fontSize: 13, color: mine ? '#fff' : '#ccc', fontWeight: mine ? 700 : 500 }}>{LEVELS[key].label}</div>,
104
+ <select key={`${key}-s`} aria-label={`Points for ${LEVELS[key].label}`} value={pointsOf(key)} onChange={(e) => setPoints(key, Number(e.target.value))}
105
+ style={{ ...select, borderColor: mine ? 'rgba(155,89,182,0.7)' : undefined }}>
106
+ {POINTS.map((p) => <option key={p} value={p}>{p}</option>)}
107
+ </select>,
108
+ <div key={`${key}-d`} style={{ fontSize: 11, color: '#667', minWidth: 70 }}>
109
+ {mine ? <button type="button" onClick={() => setPoints(key, LEVELS[key].points)} style={{ background: 'none', border: 'none', color: '#9b9bd0', cursor: 'pointer', fontSize: 11, padding: 0 }}>back to {LEVELS[key].points}</button> : 'as it comes'}
110
+ </div>,
111
+ ];
112
+ })}
113
+ </div>
114
+
115
+ {/* Roles you're looking for */}
116
+ <div style={{ marginTop: 18, fontSize: 13.5, fontWeight: 700, color: '#eee' }}>Roles you&rsquo;re looking for</div>
117
+ <Body style={{ margin: '4px 0 10px' }}>
118
+ Anyone whose title has these words counts what you give them, whatever their level: for outbound to one role, or hiring for it. &ldquo;Account executive&rdquo; at 10 puts every account executive you can reach near the top.
119
+ </Body>
120
+ <form onSubmit={(e) => { e.preventDefault(); addRole(); }} style={{ display: 'flex', gap: 8, flexWrap: 'wrap', alignItems: 'center' }}>
121
+ <input ref={roleBox} value={role} onChange={(e) => setRole(e.target.value)} placeholder="e.g. head of growth, recruiter, founder"
122
+ maxLength={60} style={{ flex: '1 1 220px', padding: '7px 10px', borderRadius: 6, fontSize: 13, border: LINE, background: 'rgba(0,0,0,0.3)', color: '#fff' }} />
123
+ <select aria-label="Points for this role" value={rolePoints} onChange={(e) => setRolePoints(Number(e.target.value))} style={select}>
124
+ {POINTS.map((p) => <option key={p} value={p}>{p}</option>)}
125
+ </select>
126
+ <Btn type="submit" disabled={role.trim().length < 2 || draft.roles.length >= MAX_ROLES}>Add</Btn>
127
+ </form>
128
+ {draft.roles.length > 0 && (
129
+ <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', marginTop: 10 }}>
130
+ {draft.roles.map((r) => (
131
+ <span key={r.text} style={{
132
+ display: 'inline-flex', alignItems: 'center', gap: 6, padding: '4px 6px 4px 11px', borderRadius: 14, fontSize: 12.5,
133
+ border: '1px solid rgba(155,89,182,0.5)', background: 'rgba(155,89,182,0.12)', color: '#eee',
134
+ }}>
135
+ {r.text} <b style={{ color: '#d2b4ff' }}>{r.points}</b>
136
+ <button type="button" onClick={() => dropRole(r.text)} aria-label={`Remove ${r.text}`} style={{ background: 'none', border: 'none', color: '#aaa', cursor: 'pointer', fontSize: 13 }}>✕</button>
137
+ </span>
138
+ ))}
139
+ </div>
140
+ )}
141
+
142
+ <div style={{ display: 'flex', gap: 10, alignItems: 'center', marginTop: 16 }}>
143
+ <Btn primary onClick={save} disabled={!dirty || saving}>{saving ? 'Rescoring…' : 'Save and rescore'}</Btn>
144
+ {dirty && <span style={{ fontSize: 12, color: '#999' }}>Not saved yet. Saving rescores everyone.</span>}
145
+ </div>
146
+ {result && <Status tone={result.tone}>{result.text}</Status>}
147
+ </Section>
148
+ );
149
+ }
@@ -11,7 +11,6 @@
11
11
  // the component and adding a row.
12
12
 
13
13
  import ForceGraph from './ForceGraph';
14
- import OrbitGraph from './OrbitGraph';
15
14
  import ChainView from './ChainView';
16
15
  import GridView from './GridView';
17
16
  import ListView from './ListView';
@@ -19,30 +18,32 @@ import RingsView from './RingsView';
19
18
  import SeparationView from './SeparationView';
20
19
 
21
20
  /**
22
- * `modes` — which top-level mode the view belongs in ('network', 'degrees').
21
+ * `modes` — which top-level tab the view belongs in ('network', 'degrees', 'separation').
23
22
  * `allDegree2` — give it every 2nd-degree row rather than the mode-filtered
24
- * set. Only Orbit wants this: it draws each bridge's circle in both modes and
25
- * narrows to the bridges on screen itself. Declared here rather than hidden
26
- * in a branch, because an exception you cannot see is one you break later.
23
+ * set. No view wants it now (Orbit did, before it became a Galaxy layout);
24
+ * declared here rather than hidden in a branch, because an exception you
25
+ * cannot see is one you break later.
27
26
  */
28
27
  export const VIEWS = {
29
28
  galaxy: { component: ForceGraph, modes: ['network'], label: 'Galaxy', icon: '🌌', desc: 'Force-directed layout' },
30
- orbit: { component: OrbitGraph, modes: ['degrees'], label: 'Orbit', icon: '🪐', desc: 'Tier orbits + circle dots; in Degrees, every mapped circle fanned out', allDegree2: true },
31
- separation: { component: SeparationView, modes: ['degrees'], label: 'Separation', icon: '🏆', desc: 'Every 2nd degree, ranked · every way in' },
32
- chain: { component: ChainView, modes: ['degrees'], label: 'Bridge Chains', icon: '🔗', desc: 'Degree paths' },
33
- rings: { component: RingsView, modes: ['network', 'degrees'], label: 'Pyramid', icon: '🔺', desc: 'Tier hierarchy' },
34
- list: { component: ListView, modes: ['network', 'degrees'], label: 'List', icon: '☰', desc: 'Ranked power list' },
29
+ // Orbit is a layout of the Galaxy now, in its Physics (Blake, 2026-10-02: "add that
30
+ // as a visual option instead so the person can interact with it"): lib/galaxy-lab.js ORBIT.
31
+ // Separation is a tab of its own (Blake, 2026-10-02), not a view inside Degrees.
32
+ separation: { component: SeparationView, modes: ['separation'], label: 'Separation', icon: '🏆', desc: 'Every 2nd degree, ranked · every way in' },
33
+ chain: { component: ChainView, modes: ['degrees'], label: 'Bridge Chains', icon: '🔗', desc: 'Your bridges, and the chains that lead on from them' },
34
+ // Pyramid and List left Network Circle (Blake, 2026-10-02: "the list and pyramid gone"): the
35
+ // Galaxy and its physics are what that tab is for. They stay in Degrees.
36
+ rings: { component: RingsView, modes: ['degrees'], label: 'Pyramid', icon: '🔺', desc: 'Tier hierarchy' },
37
+ list: { component: ListView, modes: ['degrees'], label: 'List', icon: '☰', desc: 'Ranked power list' },
35
38
  grid: { component: GridView, modes: ['network', 'degrees'], label: 'Grid', icon: '▦', desc: 'Cards' },
36
39
  };
37
40
 
38
41
  /**
39
42
  * The order they appear in the menu. Bridge Chains is the first Degrees view, so
40
43
  * it is also where resolveView lands when the chosen view isn't a Degrees one
41
- * (Galaxy, say, carried over from Network Circle); then Separation, then Orbit.
42
- * Orbit is a Degrees view only: in Network Circle it was slow and said nothing
43
- * the Galaxy doesn't (OrbitGraph still has that branch until Orbit is redrawn).
44
+ * (Galaxy, say, carried over from Network Circle); then Separation.
44
45
  */
45
- const ORDER = ['galaxy', 'chain', 'separation', 'orbit', 'rings', 'list'];
46
+ const ORDER = ['galaxy', 'chain', 'separation', 'rings', 'list'];
46
47
 
47
48
  export function viewsForMode(mode) {
48
49
  return ORDER
@@ -46,3 +46,14 @@ html:has([data-field-question]) {
46
46
  /* The notch's running dot (app/components/ScanStatusBar.js). */
47
47
  @keyframes notch-pulse { 50% { opacity: 0.35; } }
48
48
  @media (prefers-reduced-motion: no-preference) { .notch-pulse { animation: notch-pulse 1.6s ease-in-out infinite; } }
49
+
50
+ /* The Social tab's CRM (app/social/Crm.js): the list and the person side by
51
+ side, stacked on a phone. In Pipeline the board takes the whole width and
52
+ the person sits under it. */
53
+ .crm-grid { display: grid; grid-template-columns: minmax(280px, 400px) minmax(0, 1fr); gap: 10px; align-items: start; }
54
+ .crm-grid > .crm-wide { grid-column: 1 / -1; }
55
+ .crm-board { display: grid; grid-template-columns: repeat(6, minmax(150px, 1fr)); gap: 10px; padding: 10px; overflow-x: auto; }
56
+ @media (max-width: 760px) {
57
+ .crm-grid { grid-template-columns: minmax(0, 1fr); }
58
+ .crm-board { grid-template-columns: minmax(0, 1fr); }
59
+ }