six-degrees 0.6.0 → 0.8.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 (609) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-path-routes-manifest.json +4 -0
  3. package/.next/standalone/.next/build-manifest.json +3 -3
  4. package/.next/standalone/.next/prerender-manifest.json +42 -14
  5. package/.next/standalone/.next/routes-manifest.json +24 -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 +1 -1
  12. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  13. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  14. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  15. package/.next/standalone/.next/server/app/_not-found.rsc +26 -18
  16. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +26 -18
  17. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +25 -16
  18. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  19. package/.next/standalone/.next/server/app/api/admin-delete/route.js +2 -2
  20. package/.next/standalone/.next/server/app/api/admin-delete/route.js.nft.json +1 -1
  21. package/.next/standalone/.next/server/app/api/admin-update/route.js +2 -2
  22. package/.next/standalone/.next/server/app/api/admin-update/route.js.nft.json +1 -1
  23. package/.next/standalone/.next/server/app/api/bridges/route.js +2 -2
  24. package/.next/standalone/.next/server/app/api/bridges/route.js.nft.json +1 -1
  25. package/.next/standalone/.next/server/app/api/bulk-import/route.js +2 -2
  26. package/.next/standalone/.next/server/app/api/bulk-import/route.js.nft.json +1 -1
  27. package/.next/standalone/.next/server/app/api/company-scores/legacy/route.js +3 -3
  28. package/.next/standalone/.next/server/app/api/company-scores/legacy/route.js.nft.json +1 -1
  29. package/.next/standalone/.next/server/app/api/company-scores/route.js +3 -3
  30. package/.next/standalone/.next/server/app/api/company-scores/route.js.nft.json +1 -1
  31. package/.next/standalone/.next/server/app/api/connections/route.js +2 -2
  32. package/.next/standalone/.next/server/app/api/connections/route.js.nft.json +1 -1
  33. package/.next/standalone/.next/server/app/api/data/backup/route/app-paths-manifest.json +3 -0
  34. package/.next/standalone/.next/server/app/api/data/backup/route/build-manifest.json +12 -0
  35. package/.next/standalone/.next/server/app/api/data/backup/route/server-reference-manifest.json +4 -0
  36. package/.next/standalone/.next/server/app/api/data/backup/route.js +7 -0
  37. package/.next/standalone/.next/server/app/api/data/backup/route.js.map +5 -0
  38. package/.next/standalone/.next/server/app/api/data/backup/route.js.nft.json +1 -0
  39. package/.next/standalone/.next/server/app/api/data/backup/route_client-reference-manifest.js +3 -0
  40. package/.next/standalone/.next/server/app/api/data/csv/route/app-paths-manifest.json +3 -0
  41. package/.next/standalone/.next/server/app/api/data/csv/route/build-manifest.json +12 -0
  42. package/.next/standalone/.next/server/app/api/data/csv/route/server-reference-manifest.json +4 -0
  43. package/.next/standalone/.next/server/app/api/data/csv/route.js +8 -0
  44. package/.next/standalone/.next/server/app/api/data/csv/route.js.map +5 -0
  45. package/.next/standalone/.next/server/app/api/data/csv/route.js.nft.json +1 -0
  46. package/.next/standalone/.next/server/app/api/data/csv/route_client-reference-manifest.js +3 -0
  47. package/.next/standalone/.next/server/app/api/data/export/route.js +1 -1
  48. package/.next/standalone/.next/server/app/api/data/export/route.js.nft.json +1 -1
  49. package/.next/standalone/.next/server/app/api/data/import/route.js +1 -1
  50. package/.next/standalone/.next/server/app/api/data/import/route.js.nft.json +1 -1
  51. package/.next/standalone/.next/server/app/api/data/restart/route.js +1 -1
  52. package/.next/standalone/.next/server/app/api/data/restart/route.js.nft.json +1 -1
  53. package/.next/standalone/.next/server/app/api/data/restore/route/app-paths-manifest.json +3 -0
  54. package/.next/standalone/.next/server/app/api/data/restore/route/build-manifest.json +12 -0
  55. package/.next/standalone/.next/server/app/api/data/restore/route/server-reference-manifest.json +4 -0
  56. package/.next/standalone/.next/server/app/api/data/restore/route.js +7 -0
  57. package/.next/standalone/.next/server/app/api/data/restore/route.js.map +5 -0
  58. package/.next/standalone/.next/server/app/api/data/restore/route.js.nft.json +1 -0
  59. package/.next/standalone/.next/server/app/api/data/restore/route_client-reference-manifest.js +3 -0
  60. package/.next/standalone/.next/server/app/api/data/reveal/route.js +1 -1
  61. package/.next/standalone/.next/server/app/api/data/reveal/route.js.nft.json +1 -1
  62. package/.next/standalone/.next/server/app/api/data/route.js +1 -1
  63. package/.next/standalone/.next/server/app/api/data/route.js.nft.json +1 -1
  64. package/.next/standalone/.next/server/app/api/delete-cluster/route.js +2 -2
  65. package/.next/standalone/.next/server/app/api/delete-cluster/route.js.nft.json +1 -1
  66. package/.next/standalone/.next/server/app/api/ingest/route.js +2 -2
  67. package/.next/standalone/.next/server/app/api/ingest/route.js.nft.json +1 -1
  68. package/.next/standalone/.next/server/app/api/network/route.js +2 -2
  69. package/.next/standalone/.next/server/app/api/network/route.js.nft.json +1 -1
  70. package/.next/standalone/.next/server/app/api/notifications/route.js +2 -2
  71. package/.next/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  72. package/.next/standalone/.next/server/app/api/outreach/route.js +3 -3
  73. package/.next/standalone/.next/server/app/api/outreach/route.js.nft.json +1 -1
  74. package/.next/standalone/.next/server/app/api/queue/route.js +2 -2
  75. package/.next/standalone/.next/server/app/api/queue/route.js.nft.json +1 -1
  76. package/.next/standalone/.next/server/app/api/scraper/route.js +5 -3
  77. package/.next/standalone/.next/server/app/api/scraper/route.js.nft.json +1 -1
  78. package/.next/standalone/.next/server/app/api/settings/route.js +3 -3
  79. package/.next/standalone/.next/server/app/api/settings/route.js.nft.json +1 -1
  80. package/.next/standalone/.next/server/app/api/settings/sector-preview/route.js +3 -3
  81. package/.next/standalone/.next/server/app/api/settings/sector-preview/route.js.nft.json +1 -1
  82. package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route.js +3 -3
  83. package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route.js.nft.json +1 -1
  84. package/.next/standalone/.next/server/app/api/setup-profile/route.js +2 -2
  85. package/.next/standalone/.next/server/app/api/setup-profile/route.js.nft.json +1 -1
  86. package/.next/standalone/.next/server/app/api/social/crm/route.js +1 -1
  87. package/.next/standalone/.next/server/app/api/social/crm/route.js.nft.json +1 -1
  88. package/.next/standalone/.next/server/app/api/social/messages/route.js +1 -1
  89. package/.next/standalone/.next/server/app/api/social/messages/route.js.nft.json +1 -1
  90. package/.next/standalone/.next/server/app/api/social/route.js +2 -2
  91. package/.next/standalone/.next/server/app/api/social/route.js.nft.json +1 -1
  92. package/.next/standalone/.next/server/app/api/unlock/route.js +2 -2
  93. package/.next/standalone/.next/server/app/api/unlock/route.js.nft.json +1 -1
  94. package/.next/standalone/.next/server/app/api/update/route.js.nft.json +1 -1
  95. package/.next/standalone/.next/server/app/api/update-images/route.js +2 -2
  96. package/.next/standalone/.next/server/app/api/update-images/route.js.nft.json +1 -1
  97. package/.next/standalone/.next/server/app/api/users/route.js +2 -2
  98. package/.next/standalone/.next/server/app/api/users/route.js.nft.json +1 -1
  99. package/.next/standalone/.next/server/app/avatars/[file]/route.js +1 -1
  100. package/.next/standalone/.next/server/app/avatars/[file]/route.js.nft.json +1 -1
  101. package/.next/standalone/.next/server/app/import/page.js +1 -1
  102. package/.next/standalone/.next/server/app/import/page.js.nft.json +1 -1
  103. package/.next/standalone/.next/server/app/import/page_client-reference-manifest.js +1 -1
  104. package/.next/standalone/.next/server/app/import.html +1 -1
  105. package/.next/standalone/.next/server/app/import.rsc +32 -24
  106. package/.next/standalone/.next/server/app/import.segments/_full.segment.rsc +32 -24
  107. package/.next/standalone/.next/server/app/import.segments/_tree.segment.rsc +2 -2
  108. package/.next/standalone/.next/server/app/import.segments/import/__PAGE__.segment.rsc +23 -18
  109. package/.next/standalone/.next/server/app/index.html +1 -1
  110. package/.next/standalone/.next/server/app/index.rsc +29 -22
  111. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +20 -15
  112. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +29 -22
  113. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  114. package/.next/standalone/.next/server/app/insights/page/app-paths-manifest.json +3 -0
  115. package/.next/standalone/.next/server/app/insights/page/build-manifest.json +20 -0
  116. package/.next/standalone/.next/server/app/insights/page/next-font-manifest.json +11 -0
  117. package/.next/standalone/.next/server/app/insights/page/react-loadable-manifest.json +1 -0
  118. package/.next/standalone/.next/server/app/insights/page/server-reference-manifest.json +4 -0
  119. package/.next/standalone/.next/server/app/insights/page.js +13 -0
  120. package/.next/standalone/.next/server/app/insights/page.js.map +5 -0
  121. package/.next/standalone/.next/server/app/insights/page.js.nft.json +1 -0
  122. package/.next/standalone/.next/server/app/insights/page_client-reference-manifest.js +3 -0
  123. package/.next/standalone/.next/server/app/insights.html +1 -0
  124. package/.next/standalone/.next/server/app/insights.meta +26 -0
  125. package/.next/standalone/.next/server/app/insights.rsc +35 -0
  126. package/.next/standalone/.next/server/app/insights.segments/_full.segment.rsc +35 -0
  127. package/.next/standalone/.next/server/app/insights.segments/_tree.segment.rsc +4 -0
  128. package/.next/standalone/.next/server/app/insights.segments/insights/__PAGE__.segment.rsc +33 -0
  129. package/.next/standalone/.next/server/app/launch/page.js +1 -1
  130. package/.next/standalone/.next/server/app/launch/page.js.nft.json +1 -1
  131. package/.next/standalone/.next/server/app/launch/page_client-reference-manifest.js +1 -1
  132. package/.next/standalone/.next/server/app/launch.html +2 -2
  133. package/.next/standalone/.next/server/app/launch.rsc +32 -24
  134. package/.next/standalone/.next/server/app/launch.segments/_full.segment.rsc +32 -24
  135. package/.next/standalone/.next/server/app/launch.segments/_tree.segment.rsc +2 -2
  136. package/.next/standalone/.next/server/app/launch.segments/launch/__PAGE__.segment.rsc +23 -18
  137. package/.next/standalone/.next/server/app/page.js +1 -1
  138. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  139. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  140. package/.next/standalone/.next/server/app/paths/page.js +1 -1
  141. package/.next/standalone/.next/server/app/paths/page.js.nft.json +1 -1
  142. package/.next/standalone/.next/server/app/paths/page_client-reference-manifest.js +1 -1
  143. package/.next/standalone/.next/server/app/paths.html +1 -1
  144. package/.next/standalone/.next/server/app/paths.rsc +32 -24
  145. package/.next/standalone/.next/server/app/paths.segments/_full.segment.rsc +32 -24
  146. package/.next/standalone/.next/server/app/paths.segments/_tree.segment.rsc +2 -2
  147. package/.next/standalone/.next/server/app/paths.segments/paths/__PAGE__.segment.rsc +21 -18
  148. package/.next/standalone/.next/server/app/profile/page.js +1 -1
  149. package/.next/standalone/.next/server/app/profile/page.js.nft.json +1 -1
  150. package/.next/standalone/.next/server/app/profile/page_client-reference-manifest.js +1 -1
  151. package/.next/standalone/.next/server/app/profile.html +1 -1
  152. package/.next/standalone/.next/server/app/profile.rsc +32 -24
  153. package/.next/standalone/.next/server/app/profile.segments/_full.segment.rsc +32 -24
  154. package/.next/standalone/.next/server/app/profile.segments/_tree.segment.rsc +2 -2
  155. package/.next/standalone/.next/server/app/profile.segments/profile/__PAGE__.segment.rsc +23 -18
  156. package/.next/standalone/.next/server/app/queue/page.js +1 -1
  157. package/.next/standalone/.next/server/app/queue/page.js.nft.json +1 -1
  158. package/.next/standalone/.next/server/app/queue/page_client-reference-manifest.js +1 -1
  159. package/.next/standalone/.next/server/app/queue.html +1 -1
  160. package/.next/standalone/.next/server/app/queue.rsc +32 -24
  161. package/.next/standalone/.next/server/app/queue.segments/_full.segment.rsc +32 -24
  162. package/.next/standalone/.next/server/app/queue.segments/_tree.segment.rsc +2 -2
  163. package/.next/standalone/.next/server/app/queue.segments/queue/__PAGE__.segment.rsc +21 -18
  164. package/.next/standalone/.next/server/app/scores/page.js +1 -1
  165. package/.next/standalone/.next/server/app/scores/page.js.nft.json +1 -1
  166. package/.next/standalone/.next/server/app/scores/page_client-reference-manifest.js +1 -1
  167. package/.next/standalone/.next/server/app/scores.html +1 -1
  168. package/.next/standalone/.next/server/app/scores.rsc +32 -24
  169. package/.next/standalone/.next/server/app/scores.segments/_full.segment.rsc +32 -24
  170. package/.next/standalone/.next/server/app/scores.segments/_tree.segment.rsc +2 -2
  171. package/.next/standalone/.next/server/app/scores.segments/scores/__PAGE__.segment.rsc +23 -18
  172. package/.next/standalone/.next/server/app/settings/page.js +1 -1
  173. package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
  174. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  175. package/.next/standalone/.next/server/app/settings.html +1 -1
  176. package/.next/standalone/.next/server/app/settings.rsc +32 -24
  177. package/.next/standalone/.next/server/app/settings.segments/_full.segment.rsc +32 -24
  178. package/.next/standalone/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
  179. package/.next/standalone/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +20 -18
  180. package/.next/standalone/.next/server/app/setup/page.js +1 -1
  181. package/.next/standalone/.next/server/app/setup/page.js.nft.json +1 -1
  182. package/.next/standalone/.next/server/app/setup/page_client-reference-manifest.js +1 -1
  183. package/.next/standalone/.next/server/app/setup.html +1 -1
  184. package/.next/standalone/.next/server/app/setup.rsc +32 -24
  185. package/.next/standalone/.next/server/app/setup.segments/_full.segment.rsc +32 -24
  186. package/.next/standalone/.next/server/app/setup.segments/_tree.segment.rsc +2 -2
  187. package/.next/standalone/.next/server/app/setup.segments/setup/__PAGE__.segment.rsc +21 -18
  188. package/.next/standalone/.next/server/app/social/page.js +1 -1
  189. package/.next/standalone/.next/server/app/social/page.js.nft.json +1 -1
  190. package/.next/standalone/.next/server/app/social/page_client-reference-manifest.js +1 -1
  191. package/.next/standalone/.next/server/app/social.html +1 -1
  192. package/.next/standalone/.next/server/app/social.rsc +32 -24
  193. package/.next/standalone/.next/server/app/social.segments/_full.segment.rsc +32 -24
  194. package/.next/standalone/.next/server/app/social.segments/_tree.segment.rsc +2 -2
  195. package/.next/standalone/.next/server/app/social.segments/social/__PAGE__.segment.rsc +23 -18
  196. package/.next/standalone/.next/server/app-paths-manifest.json +4 -0
  197. package/.next/standalone/.next/server/chunks/[root-of-the-server]__00la_y0._.js +1 -1
  198. package/.next/standalone/.next/server/chunks/[root-of-the-server]__05_3-22._.js +1 -1
  199. package/.next/standalone/.next/server/chunks/[root-of-the-server]__066rab1._.js +7 -0
  200. package/.next/standalone/.next/server/chunks/[root-of-the-server]__07t47cm._.js +1 -1
  201. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0cj5jqc._.js +1 -1
  202. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0e0fei3._.js +1 -1
  203. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0fooke1._.js +7 -0
  204. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ljnyho._.js +1 -1
  205. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o5-tcg._.js +1 -1
  206. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0qrnous._.js +1 -1
  207. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__15wc9e-._.js → [root-of-the-server]__0r-0t-9._.js} +2 -2
  208. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ra6xyg._.js +15 -0
  209. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__20rwfdw._.js → [root-of-the-server]__0rcpjad._.js} +6 -3
  210. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0t3v1a1._.js +1 -1
  211. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0t6y79e._.js +7 -0
  212. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0wmexuc._.js +1 -1
  213. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0x29muh._.js +7 -0
  214. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0xu34sz._.js +1 -1
  215. package/.next/standalone/.next/server/chunks/[root-of-the-server]__133knx1._.js +1 -1
  216. package/.next/standalone/.next/server/chunks/[root-of-the-server]__15-17hl._.js +1 -1
  217. package/.next/standalone/.next/server/chunks/[root-of-the-server]__19b7mig._.js +1 -1
  218. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1a_6x37._.js +8 -0
  219. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1an_8pa._.js +7 -0
  220. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1bbcwub._.js +1 -1
  221. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1ducpz2._.js +3 -0
  222. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1eris29._.js +1 -1
  223. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1gjo_cq._.js +1 -1
  224. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1qcm08_._.js +1 -1
  225. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1tir0vc._.js +1 -1
  226. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1w25q0m._.js +1 -1
  227. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1xhyinn._.js +3 -0
  228. package/.next/standalone/.next/server/chunks/_072jl0y._.js +1 -1
  229. package/.next/standalone/.next/server/chunks/_0lw8_i0._.js +1 -1
  230. package/.next/standalone/.next/server/chunks/_0sqqpzb._.js +3 -0
  231. package/.next/standalone/.next/server/chunks/_1_fynia._.js +7 -7
  232. package/.next/standalone/.next/server/chunks/_1fn30_l._.js +1 -1
  233. package/.next/standalone/.next/server/chunks/_1itd1o_._.js +1 -1
  234. package/.next/standalone/.next/server/chunks/_1iwkh8t._.js +1 -1
  235. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_data_backup_route_actions_0zoj04p.js +3 -0
  236. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_data_csv_route_actions_0l6m7lg.js +3 -0
  237. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_data_restore_route_actions_0-b05bv.js +3 -0
  238. package/.next/standalone/.next/server/chunks/lib_02iz_9q._.js +4 -0
  239. package/.next/standalone/.next/server/chunks/lib_05agvk3._.js +4 -0
  240. package/.next/standalone/.next/server/chunks/lib_0v84u66._.js +4 -0
  241. package/.next/standalone/.next/server/chunks/lib_db-client_0_dch35.js +174 -0
  242. package/.next/standalone/.next/server/chunks/lib_linkedin-export_12imqxg.js +1 -1
  243. package/.next/standalone/.next/server/chunks/lib_rpc_00nndai.js +3 -0
  244. package/.next/standalone/.next/server/chunks/lib_rpc_03ibb-x.js +3 -0
  245. package/.next/standalone/.next/server/chunks/lib_rpc_03ri3ji.js +3 -0
  246. package/.next/standalone/.next/server/chunks/lib_rpc_078ce48.js +3 -0
  247. package/.next/standalone/.next/server/chunks/lib_rpc_0a69mgr.js +3 -0
  248. package/.next/standalone/.next/server/chunks/lib_rpc_0c9d9ti.js +7 -0
  249. package/.next/standalone/.next/server/chunks/lib_rpc_0cej3t8.js +3 -0
  250. package/.next/standalone/.next/server/chunks/lib_rpc_0cmh4g6.js +3 -0
  251. package/.next/standalone/.next/server/chunks/lib_rpc_0nx2_pc.js +3 -0
  252. package/.next/standalone/.next/server/chunks/lib_rpc_0r79-w1.js +3 -0
  253. package/.next/standalone/.next/server/chunks/lib_rpc_0t552z6.js +3 -0
  254. package/.next/standalone/.next/server/chunks/lib_rpc_0yx8ynd.js +3 -0
  255. package/.next/standalone/.next/server/chunks/lib_rpc_12p-o9-.js +3 -0
  256. package/.next/standalone/.next/server/chunks/lib_rpc_1466dnb.js +3 -0
  257. package/.next/standalone/.next/server/chunks/lib_rpc_1sryxv6.js +3 -0
  258. package/.next/standalone/.next/server/chunks/lib_rpc_1trn-x5.js +3 -0
  259. package/.next/standalone/.next/server/chunks/lib_rpc_1ygu_mv.js +3 -0
  260. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0egamyq._.js +3 -0
  261. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qd8pzm._.js +3 -0
  262. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0qdeuyo._.js → [root-of-the-server]__1-012q1._.js} +2 -2
  263. package/.next/standalone/.next/server/chunks/ssr/_04am_h8._.js +3 -0
  264. package/.next/standalone/.next/server/chunks/ssr/_06rgzfh._.js +3 -0
  265. package/.next/standalone/.next/server/chunks/ssr/_07zb7lu._.js +3 -0
  266. package/.next/standalone/.next/server/chunks/ssr/_0_79idq._.js +3 -0
  267. package/.next/standalone/.next/server/chunks/ssr/_0gds903._.js +3 -0
  268. package/.next/standalone/.next/server/chunks/ssr/_0hb-dhy._.js +3 -0
  269. package/.next/standalone/.next/server/chunks/ssr/_0klqt9z._.js +3 -0
  270. package/.next/standalone/.next/server/chunks/ssr/_14jak5s._.js +7 -0
  271. package/.next/standalone/.next/server/chunks/ssr/_14nxd3q._.js +3 -0
  272. package/.next/standalone/.next/server/chunks/ssr/_1cj2yog._.js +3 -0
  273. package/.next/standalone/.next/server/chunks/ssr/_1fm1ih_._.js +2 -2
  274. package/.next/standalone/.next/server/chunks/ssr/_1hdqw0-._.js +7 -0
  275. package/.next/standalone/.next/server/chunks/ssr/_1k2nmbw._.js +2 -2
  276. package/.next/standalone/.next/server/chunks/ssr/_1r62six._.js +7 -0
  277. package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_insights_page_actions_0-0tf75.js +3 -0
  278. package/.next/standalone/.next/server/chunks/ssr/app_141w189._.js +1 -1
  279. package/.next/standalone/.next/server/chunks/ssr/app_components_0uuff77._.js +25 -2
  280. package/.next/standalone/.next/server/chunks/ssr/app_components_1j3q-h5._.js +25 -2
  281. package/.next/standalone/.next/server/chunks/ssr/app_components_CompanyScores_1g0mytz.js +1 -1
  282. package/.next/standalone/.next/server/chunks/ssr/app_components_settings_SectorPicker_1c-29qw.js +1 -1
  283. package/.next/standalone/.next/server/chunks/ssr/app_components_ui_0pdmz2z.js +3 -0
  284. package/.next/standalone/.next/server/chunks/ssr/app_import_page_1fmu6_l.js +1 -1
  285. package/.next/standalone/.next/server/chunks/ssr/app_insights_page_1d_chja.js +3 -0
  286. package/.next/standalone/.next/server/chunks/ssr/app_launch_page_19t0dyd.js +1 -1
  287. package/.next/standalone/.next/server/chunks/ssr/app_page_1fazqbf.js +26 -14
  288. package/.next/standalone/.next/server/chunks/ssr/app_paths_page_1ol90m7.js +2 -2
  289. package/.next/standalone/.next/server/chunks/ssr/app_profile_page_0u3-l5y.js +1 -1
  290. package/.next/standalone/.next/server/chunks/ssr/app_queue_page_0c6znd6.js +11 -11
  291. package/.next/standalone/.next/server/chunks/ssr/app_settings_page_1f8mjj_.js +1 -1
  292. package/.next/standalone/.next/server/chunks/ssr/app_setup_page_1-282zx.js +12 -13
  293. package/.next/standalone/.next/server/chunks/ssr/app_social_page_0h7zxda.js +1 -1
  294. package/.next/standalone/.next/server/chunks/ssr/{lib_1c4ieuw._.js → lib_csv_1ttiu_h.js} +2 -2
  295. package/.next/standalone/.next/server/chunks/ssr/lib_galaxy-lab_108_lu-.js +1 -1
  296. package/.next/standalone/.next/server/chunks/ssr/lib_separation_1305zsx.js +3 -0
  297. package/.next/standalone/.next/server/edge/chunks/[root-of-the-server]__0pco7a6._.js +1 -1
  298. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  299. package/.next/standalone/.next/server/middleware-manifest.json +5 -5
  300. package/.next/standalone/.next/server/next-font-manifest.js +1 -1
  301. package/.next/standalone/.next/server/next-font-manifest.json +4 -0
  302. package/.next/standalone/.next/server/pages/404.html +1 -1
  303. package/.next/standalone/.next/server/pages/500.html +1 -1
  304. package/.next/standalone/.next/server/prefetch-hints.json +14 -0
  305. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  306. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  307. package/.next/standalone/.next/static/chunks/02wnf8dkxegxg.js +34 -0
  308. package/.next/standalone/.next/static/chunks/03-_esd2x_yk6.js +1 -0
  309. package/.next/standalone/.next/static/chunks/03-demj2iy-0p.js +44 -0
  310. package/.next/standalone/.next/static/chunks/0838_s6w-i_ik.js +1 -0
  311. package/.next/standalone/.next/static/chunks/0_1r-3csplxnj.js +1 -0
  312. package/.next/standalone/.next/static/chunks/0ka4prpk3w9wn.js +34 -0
  313. package/.next/standalone/.next/static/chunks/0kscsqnvfq3-r.js +1 -0
  314. package/.next/standalone/.next/static/chunks/0s_xxwp7z88vv.js +1 -0
  315. package/.next/standalone/.next/static/chunks/1-nnl8amfm4yh.js +57 -0
  316. package/.next/standalone/.next/static/chunks/112mv-com-mqa.js +21 -0
  317. package/.next/standalone/.next/static/chunks/1bkt_hhjzvbh8.js +1 -0
  318. package/.next/standalone/.next/static/chunks/1cmphb3kh2ers.css +3 -0
  319. package/.next/standalone/.next/static/chunks/1d8yv3k_atka7.js +1 -0
  320. package/.next/standalone/.next/static/chunks/{0ws7zy0w57ufi.js → 1eyajb9ntzlrl.js} +1 -1
  321. package/.next/standalone/.next/static/chunks/1z9lb-dbcg4aa.js +1 -0
  322. package/.next/standalone/.next/static/chunks/23hc51oa4vkhc.js +5 -0
  323. package/.next/standalone/.next/static/chunks/27n8k9wxlz5-7.js +1 -0
  324. package/.next/standalone/.next/static/chunks/2q9i7pcxcnph1.js +7 -0
  325. package/.next/standalone/.next/static/chunks/2w-y83mjlpnse.js +1 -0
  326. package/.next/standalone/.next/static/chunks/2ws1xf293j-tm.js +5 -0
  327. package/.next/standalone/.next/static/chunks/2z1-q0_vunbql.js +2 -0
  328. package/.next/standalone/.next/static/chunks/34g73qhayuevu.js +1 -0
  329. package/.next/standalone/.next/static/chunks/3cqn-r-y5rrw1.js +5 -0
  330. package/.next/standalone/.next/static/chunks/3opgg1efrx8q6.js +1 -0
  331. package/.next/standalone/.next/static/chunks/3p51fpxxi4d5y.js +34 -0
  332. package/.next/standalone/.next/static/chunks/3y40z6of3r9py.js +1 -0
  333. package/.next/standalone/.next/static/chunks/403dpflln8ah5.js +1 -0
  334. package/.next/standalone/.next/static/chunks/43pg2sursiypz.js +1 -0
  335. package/.next/standalone/CHANGELOG.md +203 -0
  336. package/.next/standalone/README.md +96 -50
  337. package/.next/standalone/SECURITY.md +25 -11
  338. package/.next/standalone/app/api/data/backup/route.js +25 -0
  339. package/.next/standalone/app/api/data/csv/route.js +74 -0
  340. package/.next/standalone/app/api/data/export/route.js +1 -1
  341. package/.next/standalone/app/api/data/restore/route.js +48 -0
  342. package/.next/standalone/app/api/data/reveal/route.js +19 -6
  343. package/.next/standalone/app/api/data/route.js +15 -4
  344. package/.next/standalone/app/api/ingest/route.js +1 -1
  345. package/.next/standalone/app/api/outreach/route.js +13 -73
  346. package/.next/standalone/app/api/queue/route.js +1 -1
  347. package/.next/standalone/app/api/scraper/route.js +217 -36
  348. package/.next/standalone/app/api/social/crm/route.js +2 -1
  349. package/.next/standalone/app/components/AppHeader.js +41 -21
  350. package/.next/standalone/app/components/AppTabs.js +12 -8
  351. package/.next/standalone/app/components/AutoConnect.js +286 -0
  352. package/.next/standalone/app/components/AutoScanButton.js +2 -2
  353. package/.next/standalone/app/components/Avatar.js +1 -1
  354. package/.next/standalone/app/components/ChainView.js +258 -113
  355. package/.next/standalone/app/components/CirclePanel.js +16 -16
  356. package/.next/standalone/app/components/ClusterSpinner.js +64 -0
  357. package/.next/standalone/app/components/CompanyScores.js +20 -20
  358. package/.next/standalone/app/components/EmptyState.js +39 -18
  359. package/.next/standalone/app/components/FieldStep.js +15 -13
  360. package/.next/standalone/app/components/FilterPanel.js +25 -18
  361. package/.next/standalone/app/components/ForceGraph.js +49 -14
  362. package/.next/standalone/app/components/GalaxyLab.js +33 -33
  363. package/.next/standalone/app/components/GridView.js +18 -18
  364. package/.next/standalone/app/components/LegacyScoresCard.js +10 -11
  365. package/.next/standalone/app/components/LinkedInLimits.js +57 -27
  366. package/.next/standalone/app/components/LiquidGlass.js +99 -0
  367. package/.next/standalone/app/components/ListView.js +20 -20
  368. package/.next/standalone/app/components/MapControls.js +5 -5
  369. package/.next/standalone/app/components/MappingProgress.js +16 -16
  370. package/.next/standalone/app/components/NoteDetail.js +13 -13
  371. package/.next/standalone/app/components/OnboardingGate.js +4 -4
  372. package/.next/standalone/app/components/OutlinkQuest.js +56 -35
  373. package/.next/standalone/app/components/PathsAnalyzer.js +37 -36
  374. package/.next/standalone/app/components/PeopleMap.js +21 -21
  375. package/.next/standalone/app/components/RingsView.js +11 -11
  376. package/.next/standalone/app/components/ScanRadar.js +84 -39
  377. package/.next/standalone/app/components/ScanStatusBar.js +40 -21
  378. package/.next/standalone/app/components/ScanTrail.js +21 -8
  379. package/.next/standalone/app/components/SeparationView.js +172 -124
  380. package/.next/standalone/app/components/Sidebar.js +308 -199
  381. package/.next/standalone/app/components/StaleServerBanner.js +4 -4
  382. package/.next/standalone/app/components/TheirCircle.js +26 -26
  383. package/.next/standalone/app/components/ThemeDefs.js +42 -0
  384. package/.next/standalone/app/components/ThemeLoader.js +20 -1
  385. package/.next/standalone/app/components/UpdatePanel.js +22 -22
  386. package/.next/standalone/app/components/UserProvider.js +22 -15
  387. package/.next/standalone/app/components/insights/Boards.js +275 -0
  388. package/.next/standalone/app/components/insights/PeopleView.js +266 -0
  389. package/.next/standalone/app/components/insights/Rail.js +156 -0
  390. package/.next/standalone/app/components/insights/Report.js +382 -0
  391. package/.next/standalone/app/components/insights/parts.js +239 -0
  392. package/.next/standalone/app/components/settings/AppearanceSection.js +47 -24
  393. package/.next/standalone/app/components/settings/DataSection.js +276 -109
  394. package/.next/standalone/app/components/settings/NetworkHealthSection.js +13 -13
  395. package/.next/standalone/app/components/settings/SectorPicker.js +12 -12
  396. package/.next/standalone/app/components/settings/SectorSection.js +13 -14
  397. package/.next/standalone/app/components/settings/TierSection.js +9 -9
  398. package/.next/standalone/app/components/settings/TitleSection.js +11 -11
  399. package/.next/standalone/app/components/settings/UsageSection.js +360 -0
  400. package/.next/standalone/app/components/ui.js +8 -8
  401. package/.next/standalone/app/globals.css +161 -5
  402. package/.next/standalone/app/import/page.js +94 -38
  403. package/.next/standalone/app/insights/page.js +220 -0
  404. package/.next/standalone/app/launch/page.js +5 -5
  405. package/.next/standalone/app/layout.js +6 -2
  406. package/.next/standalone/app/page.js +53 -53
  407. package/.next/standalone/app/paths/page.js +63 -63
  408. package/.next/standalone/app/profile/page.js +58 -58
  409. package/.next/standalone/app/queue/page.js +84 -72
  410. package/.next/standalone/app/scores/page.js +2 -2
  411. package/.next/standalone/app/settings/page.js +16 -13
  412. package/.next/standalone/app/setup/page.js +236 -133
  413. package/.next/standalone/app/social/Crm.js +63 -62
  414. package/.next/standalone/app/social/SocialHub.js +22 -22
  415. package/.next/standalone/app/social/Thread.js +7 -7
  416. package/.next/standalone/app/social/page.js +2 -2
  417. package/.next/standalone/lib/auto-connect.js +145 -0
  418. package/.next/standalone/lib/backups.js +458 -0
  419. package/.next/standalone/lib/chain-layout.js +32 -0
  420. package/.next/standalone/lib/companies.js +1 -1
  421. package/.next/standalone/lib/csv-store.js +131 -0
  422. package/.next/standalone/lib/csv.js +137 -39
  423. package/.next/standalone/lib/data-folder.js +19 -3
  424. package/.next/standalone/lib/data-import.js +5 -2
  425. package/.next/standalone/lib/db-client.js +78 -20
  426. package/.next/standalone/lib/demo.js +5 -4
  427. package/.next/standalone/lib/galaxy-export.js +9 -2
  428. package/.next/standalone/lib/galaxy-lab.js +19 -5
  429. package/.next/standalone/lib/galaxy-layouts.js +43 -0
  430. package/.next/standalone/lib/gate.js +10 -4
  431. package/.next/standalone/lib/in-progress.js +46 -0
  432. package/.next/standalone/lib/ingest.js +1 -1
  433. package/.next/standalone/lib/insights-board.js +613 -0
  434. package/.next/standalone/lib/linkedin-limits.js +240 -14
  435. package/.next/standalone/lib/liquid-glass.js +59 -0
  436. package/.next/standalone/lib/notifications.js +13 -0
  437. package/.next/standalone/lib/requests-client.js +10 -0
  438. package/.next/standalone/lib/requests.js +124 -0
  439. package/.next/standalone/lib/scan-pace.js +11 -0
  440. package/.next/standalone/lib/scan-progress.js +20 -0
  441. package/.next/standalone/lib/scan-risk.js +44 -0
  442. package/.next/standalone/lib/scan-state.js +1 -0
  443. package/.next/standalone/lib/scanner-setup.js +97 -15
  444. package/.next/standalone/lib/scraper-client.js +35 -8
  445. package/.next/standalone/lib/search-risk.js +7 -3
  446. package/.next/standalone/lib/settings-client.js +5 -3
  447. package/.next/standalone/lib/settings.js +13 -0
  448. package/.next/standalone/lib/social-store.js +3 -2
  449. package/.next/standalone/lib/synced-setting.js +46 -0
  450. package/.next/standalone/lib/theme-store.js +42 -10
  451. package/.next/standalone/lib/themes.js +111 -21
  452. package/.next/standalone/lib/usage.js +200 -0
  453. package/.next/standalone/package-lock.json +2 -2
  454. package/.next/standalone/package.json +1 -1
  455. package/.next/standalone/scripts/scrape.py +595 -11
  456. package/.next/static/chunks/02wnf8dkxegxg.js +34 -0
  457. package/.next/static/chunks/03-_esd2x_yk6.js +1 -0
  458. package/.next/static/chunks/03-demj2iy-0p.js +44 -0
  459. package/.next/static/chunks/0838_s6w-i_ik.js +1 -0
  460. package/.next/static/chunks/0_1r-3csplxnj.js +1 -0
  461. package/.next/static/chunks/0ka4prpk3w9wn.js +34 -0
  462. package/.next/static/chunks/0kscsqnvfq3-r.js +1 -0
  463. package/.next/static/chunks/0s_xxwp7z88vv.js +1 -0
  464. package/.next/static/chunks/1-nnl8amfm4yh.js +57 -0
  465. package/.next/static/chunks/112mv-com-mqa.js +21 -0
  466. package/.next/static/chunks/1bkt_hhjzvbh8.js +1 -0
  467. package/.next/static/chunks/1cmphb3kh2ers.css +3 -0
  468. package/.next/static/chunks/1d8yv3k_atka7.js +1 -0
  469. package/.next/static/chunks/{0ws7zy0w57ufi.js → 1eyajb9ntzlrl.js} +1 -1
  470. package/.next/static/chunks/1z9lb-dbcg4aa.js +1 -0
  471. package/.next/static/chunks/23hc51oa4vkhc.js +5 -0
  472. package/.next/static/chunks/27n8k9wxlz5-7.js +1 -0
  473. package/.next/static/chunks/2q9i7pcxcnph1.js +7 -0
  474. package/.next/static/chunks/2w-y83mjlpnse.js +1 -0
  475. package/.next/static/chunks/2ws1xf293j-tm.js +5 -0
  476. package/.next/static/chunks/2z1-q0_vunbql.js +2 -0
  477. package/.next/static/chunks/34g73qhayuevu.js +1 -0
  478. package/.next/static/chunks/3cqn-r-y5rrw1.js +5 -0
  479. package/.next/static/chunks/3opgg1efrx8q6.js +1 -0
  480. package/.next/static/chunks/3p51fpxxi4d5y.js +34 -0
  481. package/.next/static/chunks/3y40z6of3r9py.js +1 -0
  482. package/.next/static/chunks/403dpflln8ah5.js +1 -0
  483. package/.next/static/chunks/43pg2sursiypz.js +1 -0
  484. package/CHANGELOG.md +203 -0
  485. package/README.md +96 -50
  486. package/SECURITY.md +25 -11
  487. package/lib/auto-connect.js +145 -0
  488. package/lib/backups.js +458 -0
  489. package/lib/chain-layout.js +32 -0
  490. package/lib/companies.js +1 -1
  491. package/lib/csv-store.js +131 -0
  492. package/lib/csv.js +137 -39
  493. package/lib/data-folder.js +19 -3
  494. package/lib/data-import.js +5 -2
  495. package/lib/db-client.js +78 -20
  496. package/lib/demo.js +5 -4
  497. package/lib/galaxy-export.js +9 -2
  498. package/lib/galaxy-lab.js +19 -5
  499. package/lib/galaxy-layouts.js +43 -0
  500. package/lib/gate.js +10 -4
  501. package/lib/in-progress.js +46 -0
  502. package/lib/ingest.js +1 -1
  503. package/lib/insights-board.js +613 -0
  504. package/lib/linkedin-limits.js +240 -14
  505. package/lib/liquid-glass.js +59 -0
  506. package/lib/notifications.js +13 -0
  507. package/lib/requests-client.js +10 -0
  508. package/lib/requests.js +124 -0
  509. package/lib/scan-pace.js +11 -0
  510. package/lib/scan-progress.js +20 -0
  511. package/lib/scan-risk.js +44 -0
  512. package/lib/scan-state.js +1 -0
  513. package/lib/scanner-setup.js +97 -15
  514. package/lib/scraper-client.js +35 -8
  515. package/lib/search-risk.js +7 -3
  516. package/lib/settings-client.js +5 -3
  517. package/lib/settings.js +13 -0
  518. package/lib/social-store.js +3 -2
  519. package/lib/synced-setting.js +46 -0
  520. package/lib/theme-store.js +42 -10
  521. package/lib/themes.js +111 -21
  522. package/lib/usage.js +200 -0
  523. package/package.json +1 -1
  524. package/scripts/scrape.py +595 -11
  525. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0-rnla2._.js +0 -3
  526. package/.next/standalone/.next/server/chunks/[root-of-the-server]__13dx4sd._.js +0 -8
  527. package/.next/standalone/.next/server/chunks/[root-of-the-server]__14ou7j5._.js +0 -3
  528. package/.next/standalone/.next/server/chunks/[root-of-the-server]__16iu0hv._.js +0 -3
  529. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1kbl21f._.js +0 -3
  530. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1rphsdk._.js +0 -3
  531. package/.next/standalone/.next/server/chunks/_02twlca._.js +0 -10
  532. package/.next/standalone/.next/server/chunks/lib_0851sk0._.js +0 -8
  533. package/.next/standalone/.next/server/chunks/lib_1q7p2ro._.js +0 -8
  534. package/.next/standalone/.next/server/chunks/lib_1r6l86l._.js +0 -8
  535. package/.next/standalone/.next/server/chunks/lib_db-client_15le7cw.js +0 -174
  536. package/.next/standalone/.next/server/chunks/lib_rpc_04s8mzr.js +0 -3
  537. package/.next/standalone/.next/server/chunks/lib_rpc_053z7as.js +0 -3
  538. package/.next/standalone/.next/server/chunks/lib_rpc_0b_-2te.js +0 -3
  539. package/.next/standalone/.next/server/chunks/lib_rpc_0dhbxdm.js +0 -3
  540. package/.next/standalone/.next/server/chunks/lib_rpc_0dxlk31.js +0 -3
  541. package/.next/standalone/.next/server/chunks/lib_rpc_0f8b-qc.js +0 -3
  542. package/.next/standalone/.next/server/chunks/lib_rpc_0pzie7_.js +0 -3
  543. package/.next/standalone/.next/server/chunks/lib_rpc_0r76fq_.js +0 -3
  544. package/.next/standalone/.next/server/chunks/lib_rpc_0ut7pjp.js +0 -3
  545. package/.next/standalone/.next/server/chunks/lib_rpc_15zyqaz.js +0 -3
  546. package/.next/standalone/.next/server/chunks/lib_rpc_18zpjtq.js +0 -3
  547. package/.next/standalone/.next/server/chunks/lib_rpc_1a8xkiz.js +0 -3
  548. package/.next/standalone/.next/server/chunks/lib_rpc_1e_55xo.js +0 -3
  549. package/.next/standalone/.next/server/chunks/lib_rpc_1oxfd1_.js +0 -3
  550. package/.next/standalone/.next/server/chunks/lib_rpc_1s0lod0.js +0 -3
  551. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__08oxiqh._.js +0 -3
  552. package/.next/standalone/.next/server/chunks/ssr/_03l7vge._.js +0 -3
  553. package/.next/standalone/.next/server/chunks/ssr/_08g31gm._.js +0 -3
  554. package/.next/standalone/.next/server/chunks/ssr/_0gk_ofx._.js +0 -3
  555. package/.next/standalone/.next/server/chunks/ssr/_0nwsf93._.js +0 -3
  556. package/.next/standalone/.next/server/chunks/ssr/_0vho1lb._.js +0 -3
  557. package/.next/standalone/.next/server/chunks/ssr/_1-658fq._.js +0 -3
  558. package/.next/standalone/.next/server/chunks/ssr/_1bc46kz._.js +0 -3
  559. package/.next/standalone/.next/server/chunks/ssr/_1f_n00p._.js +0 -3
  560. package/.next/standalone/.next/server/chunks/ssr/_2105jz8._.js +0 -3
  561. package/.next/standalone/.next/server/chunks/ssr/app_components_0t908t-._.js +0 -3
  562. package/.next/standalone/.next/static/chunks/02pq76u7y4v9-.js +0 -22
  563. package/.next/standalone/.next/static/chunks/0cmq0exd4d0h9.js +0 -1
  564. package/.next/standalone/.next/static/chunks/0i02yxppzds1o.js +0 -1
  565. package/.next/standalone/.next/static/chunks/0m_p4k-q2qh--.js +0 -1
  566. package/.next/standalone/.next/static/chunks/0oyslj62jkubd.js +0 -1
  567. package/.next/standalone/.next/static/chunks/0vo-l8hxneba6.css +0 -3
  568. package/.next/standalone/.next/static/chunks/0yh8z2tbrc5i_.js +0 -1
  569. package/.next/standalone/.next/static/chunks/17-rhp8sg4m1b.js +0 -44
  570. package/.next/standalone/.next/static/chunks/172e10mi-tpo_.js +0 -34
  571. package/.next/standalone/.next/static/chunks/1ei5vbe2uw6fl.js +0 -1
  572. package/.next/standalone/.next/static/chunks/1f7_pl_wq7lh3.js +0 -11
  573. package/.next/standalone/.next/static/chunks/1jzbe7zdx9vbj.js +0 -2
  574. package/.next/standalone/.next/static/chunks/1m3017gp790pw.js +0 -45
  575. package/.next/standalone/.next/static/chunks/1t20e8u0st7ep.js +0 -1
  576. package/.next/standalone/.next/static/chunks/2-ch9rm27eril.js +0 -11
  577. package/.next/standalone/.next/static/chunks/2ldv-v3s9yaif.js +0 -1
  578. package/.next/standalone/.next/static/chunks/3bp284gjf7dyq.js +0 -1
  579. package/.next/standalone/.next/static/chunks/3k1f6clbn3gj3.js +0 -7
  580. package/.next/standalone/.next/static/chunks/3l4t8je6iguzc.js +0 -1
  581. package/.next/standalone/.next/static/chunks/3tplzuc9jk-tl.js +0 -1
  582. package/.next/standalone/.next/static/chunks/42m0bqr8pbovz.js +0 -11
  583. package/.next/static/chunks/02pq76u7y4v9-.js +0 -22
  584. package/.next/static/chunks/0cmq0exd4d0h9.js +0 -1
  585. package/.next/static/chunks/0i02yxppzds1o.js +0 -1
  586. package/.next/static/chunks/0m_p4k-q2qh--.js +0 -1
  587. package/.next/static/chunks/0oyslj62jkubd.js +0 -1
  588. package/.next/static/chunks/0vo-l8hxneba6.css +0 -3
  589. package/.next/static/chunks/0yh8z2tbrc5i_.js +0 -1
  590. package/.next/static/chunks/17-rhp8sg4m1b.js +0 -44
  591. package/.next/static/chunks/172e10mi-tpo_.js +0 -34
  592. package/.next/static/chunks/1ei5vbe2uw6fl.js +0 -1
  593. package/.next/static/chunks/1f7_pl_wq7lh3.js +0 -11
  594. package/.next/static/chunks/1jzbe7zdx9vbj.js +0 -2
  595. package/.next/static/chunks/1m3017gp790pw.js +0 -45
  596. package/.next/static/chunks/1t20e8u0st7ep.js +0 -1
  597. package/.next/static/chunks/2-ch9rm27eril.js +0 -11
  598. package/.next/static/chunks/2ldv-v3s9yaif.js +0 -1
  599. package/.next/static/chunks/3bp284gjf7dyq.js +0 -1
  600. package/.next/static/chunks/3k1f6clbn3gj3.js +0 -7
  601. package/.next/static/chunks/3l4t8je6iguzc.js +0 -1
  602. package/.next/static/chunks/3tplzuc9jk-tl.js +0 -1
  603. package/.next/static/chunks/42m0bqr8pbovz.js +0 -11
  604. /package/.next/standalone/.next/static/{dQUvvVSXqbkEFC3-CNcwT → 3NCyJyAPDCEYsYTwF1Ieu}/_buildManifest.js +0 -0
  605. /package/.next/standalone/.next/static/{dQUvvVSXqbkEFC3-CNcwT → 3NCyJyAPDCEYsYTwF1Ieu}/_clientMiddlewareManifest.js +0 -0
  606. /package/.next/standalone/.next/static/{dQUvvVSXqbkEFC3-CNcwT → 3NCyJyAPDCEYsYTwF1Ieu}/_ssgManifest.js +0 -0
  607. /package/.next/static/{dQUvvVSXqbkEFC3-CNcwT → 3NCyJyAPDCEYsYTwF1Ieu}/_buildManifest.js +0 -0
  608. /package/.next/static/{dQUvvVSXqbkEFC3-CNcwT → 3NCyJyAPDCEYsYTwF1Ieu}/_clientMiddlewareManifest.js +0 -0
  609. /package/.next/static/{dQUvvVSXqbkEFC3-CNcwT → 3NCyJyAPDCEYsYTwF1Ieu}/_ssgManifest.js +0 -0
@@ -35,12 +35,15 @@ import { useRouter } from 'next/navigation';
35
35
  import { circleIndex, MAX_DEGREE } from '../../lib/circle';
36
36
  import { localPhoto } from '../../lib/photos';
37
37
  import { reachIndex, reachState, circleState, readyByCircle, circleScanCost, scanBars } from '../../lib/reach';
38
+ import { stoppedLine } from '../../lib/in-progress';
38
39
  import { reachSegments, RING } from '../../lib/dot-rings';
39
- import { ringLayout, chainTree, dotRadius, previewBand, tierBandLayout } from '../../lib/chain-layout';
40
+ import { ringLayout, chainTree, dotRadius, previewBand, tierBandLayout, circleActivity } from '../../lib/chain-layout';
41
+ import { noteCircle } from '../../lib/notifications';
42
+ import { useUser } from './UserProvider';
40
43
  import { redundancy } from '../../lib/brokerage';
41
44
  import { keyFor, score } from '../../lib/separation';
42
45
  import { hasRequest } from '../../lib/requests-client';
43
- import { watchScanner, scannerNow, isCircleScan } from '../../lib/scraper-client';
46
+ import { watchScanner, scannerNow, isCircleScan, beginScrape, scraperStatus, notReadyMessage, busyReason, resumePoint } from '../../lib/scraper-client';
44
47
  import useRequests from './useRequests';
45
48
  import { TIER_COLORS } from '../../lib/themes';
46
49
 
@@ -175,6 +178,17 @@ export default function ChainView({ connections, degree2 = [], onSelect, userNam
175
178
  const index = useMemo(() => circleIndex(all1, all2), [all1, all2]);
176
179
  const reach = useMemo(() => reachIndex(all1, all2, scanNotes), [all1, all2, scanNotes]);
177
180
  const readyCount = useMemo(() => readyByCircle(reach), [reach]);
181
+ // The notifications, by the circle each is about: the busiest circles go on the inner ring.
182
+ const { userId } = useUser();
183
+ const [notes, setNotes] = useState([]);
184
+ useEffect(() => {
185
+ if (!userId) return undefined;
186
+ let live = true;
187
+ fetch(`/api/notifications?userId=${encodeURIComponent(userId)}`).then((r) => r.json())
188
+ .then((d) => { if (live) setNotes((d.notifications || []).map((n) => ({ circle: noteCircle(n), seen: !!n.seen }))); })
189
+ .catch(() => {});
190
+ return () => { live = false; };
191
+ }, [userId]);
178
192
  const twoWays = useMemo(() => redundancy(fullDegree2 || degree2, fullDegree1 || connections), [fullDegree2, degree2, fullDegree1, connections]);
179
193
  const rowById = useMemo(() => {
180
194
  const m = new Map();
@@ -240,7 +254,12 @@ export default function ChainView({ connections, degree2 = [], onSelect, userNam
240
254
  }
241
255
  return withCircle.has(b.unlocked_from_bridge_id);
242
256
  };
243
- const roots = bridges.filter((b) => !linked(b));
257
+ // The inner ring holds the circles with the most going on (lib/chain-layout.js
258
+ // circleActivity): notifications about them, people in them ready to scan,
259
+ // clusters formed from them since. The biggest first among the rest.
260
+ const activity = circleActivity(bridges, { notes, ready: readyCount, chained });
261
+ const roots = bridges.filter((b) => !linked(b))
262
+ .sort((a, b) => activity.get(b.id).score - activity.get(a.id).score);
244
263
  // Bridges round you: one ring while they fit, more once there are many, each
245
264
  // ring far enough from the last for the names under it.
246
265
  const bridgeLayout = ringLayout(roots.length, {
@@ -248,7 +267,7 @@ export default function ChainView({ connections, degree2 = [], onSelect, userNam
248
267
  });
249
268
  const bridgePos = roots.map((b, i) => {
250
269
  const p = bridgeLayout.points[i];
251
- return { ...b, x: cx + p.x, y: cy + p.y, angle: p.angle, clusterSize: (bridgeMap[b.id] || []).length, chains: chained.get(b.id) || 0 };
270
+ return { ...b, x: cx + p.x, y: cy + p.y, angle: p.angle, clusterSize: (bridgeMap[b.id] || []).length, chains: chained.get(b.id) || 0, activity: activity.get(b.id) };
252
271
  });
253
272
  // More than one ring: the counts under each name wait for a hover.
254
273
  const crowded = bridgeLayout.rings.length > 1;
@@ -339,8 +358,8 @@ export default function ChainView({ connections, degree2 = [], onSelect, userNam
339
358
 
340
359
  {/* Their circle, previewed on hover, in a wedge that grows rows as it fills */}
341
360
  {hovBridge && (
342
- <CirclePreview bridge={hovBridge} members={membersOf(hovBridge, index)} reach={reach}
343
- cx={cx} cy={cy} maxR={maxR} still={still} band={band} />
361
+ <CirclePreview key={hovBridge.id} bridge={hovBridge} members={membersOf(hovBridge, index)} reach={reach}
362
+ cx={cx} cy={cy} maxR={maxR} still={still} band={band} circleOf={(id) => bridgeMap[id] || []} />
344
363
  )}
345
364
 
346
365
  {/* Bridge nodes — hover to preview their circle, click to open it */}
@@ -357,7 +376,7 @@ export default function ChainView({ connections, degree2 = [], onSelect, userNam
357
376
  style={{ cursor: 'pointer' }}>
358
377
  <title>{bridgeTitle(b, ready, scanBars(b, reach))}</title>
359
378
  {/* Glow */}
360
- <circle cx={b.x} cy={b.y} r={isHov ? 21 : 18} fill={`${TIER_COLORS[b.tier]}${isHov ? '14' : '08'}`} />
379
+ <circle className="sd-dot" cx={b.x} cy={b.y} r={isHov ? 21 : 18} fill={`${TIER_COLORS[b.tier]}${isHov ? '14' : '08'}`} />
361
380
  {/* The ring, tight on the dot: one bar for each person you added through
362
381
  this circle. Orange: scanned since, with a cluster of their own.
363
382
  Green: ready for a scan. Nobody yet: one faint line. */}
@@ -371,9 +390,9 @@ export default function ChainView({ connections, degree2 = [], onSelect, userNam
371
390
  ))}
372
391
  </g>
373
392
  {/* Node */}
374
- <circle cx={b.x} cy={b.y} r={isHov ? 13 : 11}
393
+ <circle className="sd-dot" cx={b.x} cy={b.y} r={isHov ? 13 : 11}
375
394
  fill={localPhoto(b.profile_image_url) ? '#1a1a2e' : TIER_COLORS[b.tier]}
376
- stroke={isHov ? '#fff' : TIER_COLORS[b.tier]}
395
+ stroke={isHov ? 'var(--sd-fg-1, #fff)' : TIER_COLORS[b.tier]}
377
396
  strokeWidth={isHov ? 2.5 : 2} />
378
397
  {/* Photo */}
379
398
  {localPhoto(b.profile_image_url) && (
@@ -384,22 +403,30 @@ export default function ChainView({ connections, degree2 = [], onSelect, userNam
384
403
  </>
385
404
  )}
386
405
  {!localPhoto(b.profile_image_url) && (
387
- <text x={b.x} y={b.y + 4} textAnchor="middle" fill={b.tier === 'S' ? '#000' : '#fff'}
406
+ <text x={b.x} y={b.y + 4} textAnchor="middle" fill={b.tier === 'S' ? '#000' : 'var(--sd-fg-1, #fff)'}
388
407
  fontSize={11} fontWeight={700}>{b.name?.charAt(0)}</text>
389
408
  )}
390
- {/* How many in their circle are waiting for a scan: a small outlined number, top right */}
391
- {ready > 0 && (
392
- <g pointerEvents="none">
393
- <circle cx={b.x + 14} cy={b.y - 14} r={6} fill="var(--sd-bg)" stroke={GREEN} strokeWidth={1.2} />
394
- <text x={b.x + 14} y={b.y - 11.4} textAnchor="middle" fill={GREEN} fontSize={ready > 9 ? 6 : 7} fontWeight={800}>{ready > 99 ? '99+' : ready}</text>
395
- </g>
396
- )}
409
+ {/* The circle's notifications, top right (Blake, 2026-10-02: "the circle degree
410
+ outline on the top right with the number of notifications for that cluster"):
411
+ new notifications about it and the people in it ready to scan. Gold when
412
+ there's news, green when it's only people ready. */}
413
+ {(() => {
414
+ const news = (b.activity?.unread || 0) + ready;
415
+ if (!news) return null;
416
+ const tone = b.activity?.unread ? 'var(--sd-gold, #FFD700)' : 'var(--sd-green, #00ff88)'; // deeper on a light look
417
+ return (
418
+ <g pointerEvents="none">
419
+ <circle cx={b.x + 14} cy={b.y - 14} r={6} fill="var(--sd-bg)" stroke={tone} strokeWidth={1.2} />
420
+ <text x={b.x + 14} y={b.y - 11.4} textAnchor="middle" fill={tone} fontSize={news > 9 ? 6 : 7} fontWeight={800}>{news > 99 ? '99+' : news}</text>
421
+ </g>
422
+ );
423
+ })()}
397
424
  {/* Name + count */}
398
- <text x={b.x} y={b.y + (isHov ? 24 : 22)} textAnchor="middle" fill="#fff" fontSize={9} fontWeight={600}>
425
+ <text x={b.x} y={b.y + (isHov ? 24 : 22)} textAnchor="middle" fill="var(--sd-fg-1, #fff)" fontSize={9} fontWeight={600}>
399
426
  {b.name?.split(' ')[0]}
400
427
  </text>
401
428
  {(!crowded || isHov) && (
402
- <text x={b.x} y={b.y + (isHov ? 34 : 32)} textAnchor="middle" fill={isHov ? '#bbb' : '#888'} fontSize={7}>
429
+ <text x={b.x} y={b.y + (isHov ? 34 : 32)} textAnchor="middle" fill={isHov ? 'var(--sd-fg-2, #bbb)' : 'var(--sd-fg-3, #888)'} fontSize={7}>
403
430
  {b.clusterSize} · {sCount > 0 ? sCount + 'S ' : ''}{aCount > 0 ? aCount + 'A' : ''}
404
431
  </text>
405
432
  )}
@@ -409,7 +436,7 @@ export default function ChainView({ connections, degree2 = [], onSelect, userNam
409
436
 
410
437
  {/* Center: YOU */}
411
438
  <circle cx={cx} cy={cy} r={22} fill="var(--sd-bg)" stroke="#FFD700" strokeWidth={3} />
412
- <text x={cx} y={cy + 4} textAnchor="middle" fill="#FFD700" fontSize={11} fontWeight={800}>
439
+ <text x={cx} y={cy + 4} textAnchor="middle" fill="var(--sd-gold, #FFD700)" fontSize={11} fontWeight={800}>
413
440
  {userName?.split(' ')[0] || 'YOU'}
414
441
  </text>
415
442
  </g>
@@ -422,41 +449,35 @@ export default function ChainView({ connections, degree2 = [], onSelect, userNam
422
449
  onOut={() => setZoom(z => Math.max(0.4, (z ?? homeZoom) - 0.3))}
423
450
  />
424
451
 
425
- {/* Depth tracker */}
426
- <div style={{
427
- position: 'absolute', bottom: 16, left: 12,
428
- background: 'rgba(0,0,0,0.75)', borderRadius: 10, padding: '10px 14px',
429
- backdropFilter: 'blur(12px)', border: '1px solid rgba(255,255,255,0.06)',
430
- maxWidth: 'calc(100vw - 80px)',
431
- }}>
432
- <div style={{ fontSize: 9, fontWeight: 700, color: '#666', letterSpacing: 1.5, marginBottom: 8 }}>DEGREES OF SEPARATION</div>
433
- <div style={{ display: 'flex', gap: 8 }}>
434
- {[1, 2, 3, 4, 5, 6].map(d => (
435
- <div key={d} style={{ textAlign: 'center' }}>
436
- <div style={{
437
- width: 28, height: 28, borderRadius: '50%', fontSize: 11, fontWeight: 800,
438
- display: 'flex', alignItems: 'center', justifyContent: 'center',
439
- background: d <= 2 ? DEGREE_COLORS[d] : 'rgba(255,255,255,0.04)',
440
- color: d <= 2 ? '#000' : '#333',
441
- border: d <= 2 ? 'none' : '1px solid rgba(255,255,255,0.08)',
442
- boxShadow: d <= 2 ? `0 0 6px ${DEGREE_COLORS[d]}30` : 'none',
443
- }}>D{d}</div>
444
- <div style={{ fontSize: 7, color: d <= 2 ? '#aaa' : '#333', marginTop: 3 }}>
445
- {d === 1 ? connections.length : d === 2 ? totalD2 : '—'}
446
- </div>
452
+ {/* Depth tracker: just the dots, no box (Blake, 2026-10-03: the box grew with
453
+ a theme's font and stopped fitting; "just have the dots there instead so
454
+ its more clean looking"). What they add up to is the tooltip. */}
455
+ <div
456
+ title={[
457
+ `${roots.length} bridges${bridges.length > roots.length ? ` + ${bridges.length - roots.length} along their chains` : ''} · ${d2S} S + ${d2A} A at 2nd degree`,
458
+ twoWays > 0 ? `${Math.round(twoWays * 100)}% of your 2nd degree you reach two or more ways` : null,
459
+ 'The inner ring: the circles with the most going on (notifications, people ready to scan, clusters formed since)',
460
+ 'Click a bridge to open their circle, then anyone in it to open theirs',
461
+ ].filter(Boolean).join('\n')}
462
+ style={{ position: 'absolute', bottom: 16, left: 16, display: 'flex', alignItems: 'flex-end', gap: 12 }}>
463
+ {[1, 2, 3, 4, 5, 6].map((d) => {
464
+ const lit = d <= 2;
465
+ const n = d === 1 ? connections.length : d === 2 ? totalD2 : null;
466
+ return (
467
+ <div key={d} title={lit ? `${d === 1 ? '1st degree: your bridges' : '2nd degree: the people in their circles'} (${n.toLocaleString('en-US')})` : `${d}th degree: further along a chain, as your scans reach it`}
468
+ style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4 }}>
469
+ <span className={lit ? 'sd-dot-html' : undefined} style={{
470
+ width: 11, height: 11, borderRadius: '50%',
471
+ background: lit ? DEGREE_COLORS[d] : 'transparent',
472
+ border: lit ? 'none' : '1px solid rgba(var(--sd-ink, 255, 255, 255), 0.22)',
473
+ boxShadow: lit ? `0 0 8px ${DEGREE_COLORS[d]}80` : 'none',
474
+ }} />
475
+ <span style={{ fontSize: 9.5, fontWeight: 700, color: lit ? 'var(--sd-fg-2, #c8cdd8)' : 'var(--sd-fg-5, #556)', fontVariantNumeric: 'tabular-nums', textShadow: HALO_TEXT }}>
476
+ {lit ? n.toLocaleString('en-US') : `D${d}`}
477
+ </span>
447
478
  </div>
448
- ))}
449
- </div>
450
- <div style={{ fontSize: 9, color: '#555', marginTop: 8 }}>
451
- {roots.length} bridges{bridges.length > roots.length ? ` + ${bridges.length - roots.length} along their chains` : ''} · {d2S} S + {d2A} A at 2nd degree
452
- </div>
453
- {twoWays > 0 && (
454
- <div style={{ fontSize: 9, color: '#555', marginTop: 4 }}
455
- title="The share of everyone you reach through a circle that more than one of your connections reaches">
456
- {Math.round(twoWays * 100)}% of your 2nd degree you reach two or more ways
457
- </div>
458
- )}
459
- <div style={{ fontSize: 8, color: '#444', marginTop: 4 }}>Click a bridge to open their circle, then anyone in it to open theirs</div>
479
+ );
480
+ })}
460
481
  </div>
461
482
  </div>
462
483
  );
@@ -465,6 +486,8 @@ export default function ChainView({ connections, degree2 = [], onSelect, userNam
465
486
  /** What a bridge's ring and number mean, in words, for its tooltip. */
466
487
  function bridgeTitle(b, ready, bars) {
467
488
  const parts = [];
489
+ const notes = b.activity?.notes || 0;
490
+ if (notes) parts.push(`${notes} notification${notes === 1 ? '' : 's'} about their circle${b.activity.unread ? `, ${b.activity.unread} new` : ''}`);
468
491
  if (ready) parts.push(`${ready} in ${firstName(b)}’s circle ${ready === 1 ? 'is' : 'are'} ready for a scan`);
469
492
  if (b.chains) parts.push(`${b.chains} scanned since, with ${b.chains === 1 ? 'a cluster' : 'clusters'} of their own`);
470
493
  if (bars != null) parts.push(bars === 5 ? 'their whole list is scanned' : `about ${bars * 20}% of their list is scanned`);
@@ -472,7 +495,34 @@ function bridgeTitle(b, ready, bars) {
472
495
  }
473
496
 
474
497
  /** A bridge's circle on hover: the people you reached through it first, then their S, A and B. */
475
- function CirclePreview({ bridge, members, reach, cx, cy, maxR, still, band }) {
498
+ // The preview grows out of the bridge when you hover it (Blake, 2026-10-03: "the
499
+ // d2,3,4 clusters emerging out of the circle in the preview to show the grow but
500
+ // make it quick and snappy"): their circle's people shoot out to their places,
501
+ // then anyone among them whose own circle is scanned sprouts it (3rd degree),
502
+ // then theirs (4th). Under half a second in all; still with Reduce Motion.
503
+ const PREVIEW_CSS = `
504
+ @keyframes pvEmerge { from { transform: translate(var(--fx), var(--fy)) scale(0.2); opacity: 0; } 55% { opacity: 1; } to { transform: none; opacity: 1; } }
505
+ @keyframes pvFade { from { opacity: 0; } }
506
+ .pv-dot { transform-box: fill-box; transform-origin: center; animation: pvEmerge .24s cubic-bezier(.2,.9,.3,1.25) both; animation-delay: var(--d, 0ms); }
507
+ .pv-d3 { animation-duration: .22s; animation-delay: calc(150ms + var(--d, 0ms)); }
508
+ .pv-d4 { animation-duration: .2s; animation-delay: calc(270ms + var(--d, 0ms)); }
509
+ .pv-line { animation: pvFade .3s ease-out both; animation-delay: var(--d, 0ms); }
510
+ @media (prefers-reduced-motion: reduce) { .pv-dot, .pv-line { animation: none; } }
511
+ `;
512
+ const SPROUT = 14; // the most of a circle's own circle drawn round them
513
+ const SPROUT_4 = 8;
514
+
515
+ /** Where someone's own circle sprouts round their dot: an arc facing away from the middle. */
516
+ function sprout(n, x, y, cx, cy, r) {
517
+ const out = Math.atan2(y - cy, x - cx);
518
+ const spread = Math.min(Math.PI * 1.1, 0.5 + n * 0.16);
519
+ return Array.from({ length: n }, (_, i) => {
520
+ const a = out - spread / 2 + (n === 1 ? spread / 2 : (i * spread) / (n - 1));
521
+ return { x: x + Math.cos(a) * r, y: y + Math.sin(a) * r };
522
+ });
523
+ }
524
+
525
+ function CirclePreview({ bridge, members, reach, cx, cy, maxR, still, band, circleOf = () => [] }) {
476
526
  const shown = members.filter((m) => m.degree === 1 || m.tier === 'S' || m.tier === 'A' || m.tier === 'B');
477
527
  // Beyond every ring of bridges (lib/chain-layout.js previewBand).
478
528
  const { inner, outer } = band;
@@ -480,8 +530,12 @@ function CirclePreview({ bridge, members, reach, cx, cy, maxR, still, band }) {
480
530
  const layout = ringLayout(shown.length, {
481
531
  inner, outer, spacing: 11, minSpacing: 3.5, start: bridge.angle - sweep / 2, sweep,
482
532
  });
533
+ // Spread the start of each dot over a tenth of a second, wherever it sits.
534
+ const stagger = (j) => `${Math.round((j / Math.max(1, shown.length)) * 110)}ms`;
535
+ const from = (x, y, ox, oy) => ({ '--fx': `${(ox - x).toFixed(1)}px`, '--fy': `${(oy - y).toFixed(1)}px` });
483
536
  return (
484
537
  <g>
538
+ <style>{PREVIEW_CSS}</style>
485
539
  <circle cx={cx} cy={cy} r={inner} fill="none" stroke={`${DEGREE_COLORS[2]}06`} strokeWidth={1} />
486
540
  {shown.map((d2, j) => {
487
541
  const p = layout.points[j];
@@ -490,21 +544,44 @@ function CirclePreview({ bridge, members, reach, cx, cy, maxR, still, band }) {
490
544
  const state = reachState(d2, reach);
491
545
  const nr = Math.min(dotRadius(layout.spacing, d2.tier), 5) * (state ? 1.3 : 1);
492
546
  const color = state === 'hidden' ? HIDDEN : TIER_COLORS[d2.tier] || '#555';
547
+ // Their own circle, if it's scanned: the 3rd degree, and inside it the 4th.
548
+ const own = d2.degree === 1 ? circleOf(d2.id) : [];
549
+ const third = own.slice(0, SPROUT);
550
+ const thirdAt = sprout(third.length, x2, y2, cx, cy, nr + 9);
493
551
  return (
494
552
  <g key={'pv-' + d2.id}>
495
553
  {(state || shown.length <= 40) && (
496
- <line x1={bridge.x} y1={bridge.y} x2={x2} y2={y2}
554
+ <line className="pv-line" style={{ '--d': stagger(j) }} x1={bridge.x} y1={bridge.y} x2={x2} y2={y2}
497
555
  stroke={state ? GREEN : color} strokeWidth={0.5} strokeOpacity={state ? 0.35 : 0.15} />
498
556
  )}
499
- {state === 'ready' && <Halo x={x2} y={y2} r={nr * 2.3} still={still} />}
500
- <circle cx={x2} cy={y2} r={nr}
501
- fill={color} fillOpacity={state ? 0.95 : 0.45}
502
- stroke={state && state !== 'hidden' ? GREEN : color} strokeWidth={state ? 1 : 0.5} strokeOpacity={state ? 1 : 0.25} />
503
- {(d2.tier === 'S' || state) && shown.length <= 60 && (
504
- <text x={x2} y={y2 + nr + 9} textAnchor="middle" fill={state && state !== 'hidden' ? GREEN : '#aaa'} fontSize={7}>
505
- {firstName(d2)}
506
- </text>
507
- )}
557
+ <g className="pv-dot" style={{ '--d': stagger(j), ...from(x2, y2, bridge.x, bridge.y) }}>
558
+ {state === 'ready' && <Halo x={x2} y={y2} r={nr * 2.3} still={still} />}
559
+ <circle className="sd-dot" cx={x2} cy={y2} r={nr}
560
+ fill={color} fillOpacity={state ? 0.95 : 0.45}
561
+ stroke={state && state !== 'hidden' ? GREEN : color} strokeWidth={state ? 1 : 0.5} strokeOpacity={state ? 1 : 0.25} />
562
+ {(d2.tier === 'S' || state) && shown.length <= 60 && (
563
+ <text x={x2} y={y2 + nr + 9} textAnchor="middle" fill={state && state !== 'hidden' ? GREEN : 'var(--sd-fg-3, #aaa)'} fontSize={7}>
564
+ {firstName(d2)}
565
+ </text>
566
+ )}
567
+ </g>
568
+ {third.map((k, i) => {
569
+ const t = thirdAt[i];
570
+ const fourth = k.degree === 1 ? circleOf(k.id).slice(0, SPROUT_4) : [];
571
+ const fourthAt = sprout(fourth.length, t.x, t.y, x2, y2, 6);
572
+ return (
573
+ <g key={'p3-' + k.id}>
574
+ <line className="pv-line" style={{ '--d': `calc(150ms + ${stagger(j)})` }} x1={x2} y1={y2} x2={t.x} y2={t.y}
575
+ stroke={TIER_COLORS[k.tier] || '#555'} strokeWidth={0.4} strokeOpacity={0.3} />
576
+ <circle className="pv-dot pv-d3" style={{ '--d': `${i * 8}ms`, ...from(t.x, t.y, x2, y2) }}
577
+ cx={t.x} cy={t.y} r={1.8} fill={TIER_COLORS[k.tier] || '#555'} fillOpacity={0.85} />
578
+ {fourth.map((f, q) => (
579
+ <circle key={'p4-' + f.id} className="pv-dot pv-d4" style={{ '--d': `${q * 6}ms`, ...from(fourthAt[q].x, fourthAt[q].y, t.x, t.y) }}
580
+ cx={fourthAt[q].x} cy={fourthAt[q].y} r={1.1} fill={TIER_COLORS[f.tier] || '#555'} fillOpacity={0.75} />
581
+ ))}
582
+ </g>
583
+ );
584
+ })}
508
585
  </g>
509
586
  );
510
587
  })}
@@ -527,7 +604,7 @@ function Lock({ x, y, s }) {
527
604
  return (
528
605
  <g transform={`translate(${x} ${y}) scale(${s})`} pointerEvents="none">
529
606
  <path d="M-1.9 -0.6 V-1.8 A1.9 1.9 0 0 1 1.9 -1.8 V-0.6" fill="none" stroke="#d6d6de" strokeWidth={0.9} />
530
- <rect x={-2.6} y={-0.7} width={5.2} height={3.9} rx={0.8} fill="#d6d6de" />
607
+ <rect x={-2.6} y={-0.7} width={5.2} height={3.9} rx={0.8} fill="var(--sd-fg-2, #d6d6de)" />
531
608
  </g>
532
609
  );
533
610
  }
@@ -535,7 +612,7 @@ function Lock({ x, y, s }) {
535
612
  function ZoomButtons({ onIn, onReset, onOut }) {
536
613
  const round = (dim) => ({
537
614
  width: 32, height: 32, borderRadius: '50%', border: 'none', cursor: 'pointer',
538
- background: dim ? 'rgba(255,255,255,0.06)' : 'rgba(255,255,255,0.1)', color: dim ? '#666' : '#fff',
615
+ background: dim ? 'rgba(var(--sd-ink, 255, 255, 255), 0.06)' : 'rgba(var(--sd-ink, 255, 255, 255), 0.1)', color: dim ? 'var(--sd-fg-4, #666)' : 'var(--sd-fg-1, #fff)',
539
616
  fontSize: dim ? 10 : 18, fontWeight: 700,
540
617
  display: 'flex', alignItems: 'center', justifyContent: 'center', backdropFilter: 'blur(8px)',
541
618
  });
@@ -683,7 +760,7 @@ function CircleFocus({ trail, index, reach, dims, requests, scanningId, still, c
683
760
  <circle cx={p.x} cy={p.y} r={r * 1.2} fill="none" stroke={color} strokeWidth={Math.max(0.6, r * 0.45)}
684
761
  strokeDasharray={`${Math.max(0.8, r * 0.55)} ${Math.max(0.6, r * 0.45)}`} />
685
762
  ) : (
686
- <circle cx={p.x} cy={p.y} r={r} fill={color} fillOpacity={f.reached ? 1 : 0.85}
763
+ <circle className="sd-dot" cx={p.x} cy={p.y} r={r} fill={color} fillOpacity={f.reached ? 1 : 0.85}
687
764
  stroke={f.reached && f.reached !== 'hidden' ? GREEN : 'none'} strokeWidth={f.reached ? Math.max(0.8, r * 0.3) : 0} />
688
765
  )}
689
766
  {f.reached === 'hidden' && <Lock x={p.x} y={p.y - r * 0.1} s={r / 4.2} />}
@@ -692,7 +769,7 @@ function CircleFocus({ trail, index, reach, dims, requests, scanningId, still, c
692
769
  )}
693
770
  {(f.reached || (roomy && row.tier === 'S')) && (
694
771
  <text x={p.x} y={above ? p.y - r - 4 / k : p.y + r + 10 / k} textAnchor="middle" fontSize={8.5 / k} fontWeight={f.reached ? 700 : 400}
695
- fill={f.reached === 'hidden' ? '#999' : f.reached ? GREEN : '#aaa'} pointerEvents="none"
772
+ fill={f.reached === 'hidden' ? 'var(--sd-fg-3, #999)' : f.reached ? GREEN : 'var(--sd-fg-3, #aaa)'} pointerEvents="none"
696
773
  stroke="var(--sd-bg)" strokeWidth={2.4 / k} paintOrder="stroke">
697
774
  {firstName(row)}
698
775
  </text>
@@ -794,7 +871,7 @@ function CircleFocus({ trail, index, reach, dims, requests, scanningId, still, c
794
871
  {/* A faint band behind each tier's dots, in its colour */}
795
872
  {layout.bands.map((band) => (
796
873
  <circle key={band.tier} r={(band.inner + band.outer) / 2} fill="none"
797
- stroke={TIER_COLORS[band.tier] || '#555'} strokeOpacity={0.07}
874
+ stroke={TIER_COLORS[band.tier] || 'var(--sd-fg-5, #555)'} strokeOpacity={0.07}
798
875
  strokeWidth={Math.max(1 / k, band.outer - band.inner + layout.spacing)} pointerEvents="none" />
799
876
  ))}
800
877
  {dots}
@@ -813,17 +890,17 @@ function CircleFocus({ trail, index, reach, dims, requests, scanningId, still, c
813
890
  <circle r={c.radius} fill="var(--sd-bg)" fillOpacity={0.9} stroke={color} strokeOpacity={lit ? 0.7 : 0.25} strokeWidth={1 / k} />
814
891
  {/* Their people, each joined to the middle of the cluster */}
815
892
  {clusterPaths(c).map(([tier, { spokes }]) => (
816
- <path key={'s' + tier} d={spokes} fill="none" stroke={TIER_COLORS[tier] || '#555'}
893
+ <path key={'s' + tier} d={spokes} fill="none" stroke={TIER_COLORS[tier] || 'var(--sd-fg-5, #555)'}
817
894
  strokeWidth={0.7} strokeOpacity={lit ? 0.6 : 0.38} />
818
895
  ))}
819
896
  {clusterPaths(c).map(([tier, { dots: d }]) => (
820
- <path key={tier} d={d} fill={TIER_COLORS[tier] || '#555'} fillOpacity={lit ? 1 : 0.9} />
897
+ <path className="sd-dot" key={tier} d={d} fill={TIER_COLORS[tier] || 'var(--sd-fg-5, #555)'} fillOpacity={lit ? 1 : 0.9} />
821
898
  ))}
822
- <circle r={LINK_HUB} fill={color} stroke={hovLink === j ? '#fff' : 'var(--sd-bg)'} strokeWidth={1.5} />
899
+ <circle className="sd-dot" r={LINK_HUB} fill={color} stroke={hovLink === j ? 'var(--sd-fg-1, #fff)' : 'var(--sd-bg)'} strokeWidth={1.5} />
823
900
  {row.id === scanningId && (
824
901
  <circle r={c.radius + 4} fill="none" stroke={DEGREE_COLORS[3]} strokeWidth={1 / k} strokeDasharray={`${3 / k} ${2 / k}`} />
825
902
  )}
826
- <text y={c.radius + 12 / k} textAnchor="middle" fill="#fff" fontSize={10 / k} fontWeight={700}
903
+ <text y={c.radius + 12 / k} textAnchor="middle" fill="var(--sd-fg-1, #fff)" fontSize={10 / k} fontWeight={700}
827
904
  stroke="var(--sd-bg)" strokeWidth={2.4 / k} paintOrder="stroke">{firstName(row)}’s circle</text>
828
905
  <text y={c.radius + 23 / k} textAnchor="middle" fill={color} fontSize={8 / k}
829
906
  stroke="var(--sd-bg)" strokeWidth={2.4 / k} paintOrder="stroke">
@@ -856,7 +933,7 @@ function CircleFocus({ trail, index, reach, dims, requests, scanningId, still, c
856
933
  {seg(o, o.r + 1, p, LINK_HUB + 1, 'b')}
857
934
  {/* Their own dot inside the cluster they were met through */}
858
935
  {o.inCluster && (
859
- <circle cx={o.x} cy={o.y} r={o.r} fill={TIER_COLORS[link.row.tier] || '#555'} stroke={GREEN} strokeWidth={1.4} />
936
+ <circle className="sd-dot" cx={o.x} cy={o.y} r={o.r} fill={TIER_COLORS[link.row.tier] || 'var(--sd-fg-5, #555)'} stroke={GREEN} strokeWidth={1.4} />
860
937
  )}
861
938
  </g>
862
939
  );
@@ -864,25 +941,25 @@ function CircleFocus({ trail, index, reach, dims, requests, scanningId, still, c
864
941
  {/* The one under the pointer, on top */}
865
942
  {hp && (
866
943
  <>
867
- <line x1={0} y1={0} x2={hp.x} y2={hp.y} stroke={TIER_COLORS[hovered.tier] || '#888'} strokeWidth={1.6 / k} strokeOpacity={0.8} />
944
+ <line x1={0} y1={0} x2={hp.x} y2={hp.y} stroke={TIER_COLORS[hovered.tier] || 'var(--sd-fg-3, #888)'} strokeWidth={1.6 / k} strokeOpacity={0.8} />
868
945
  <circle cx={hp.x} cy={hp.y} r={dotRadius(layout.spacing, hovered.tier) * (facts[hover].reached ? 1.4 : 1) + 2 / k}
869
946
  fill="none" stroke="#fff" strokeWidth={1.6 / k} />
870
947
  </>
871
948
  )}
872
949
  {/* The person in the middle, with the halo if their own circle is ready to scan */}
873
950
  {reachState(person, reach) === 'ready' && <Halo x={0} y={0} r={40} still={still} />}
874
- <circle r={28} fill="var(--sd-bg)" stroke={TIER_COLORS[person.tier] || '#888'} strokeWidth={hover === 'center' ? 4 : 3} filter="url(#focusGlow)" />
951
+ <circle r={28} fill="var(--sd-bg)" stroke={TIER_COLORS[person.tier] || 'var(--sd-fg-3, #888)'} strokeWidth={hover === 'center' ? 4 : 3} filter="url(#focusGlow)" />
875
952
  {localPhoto(person.profile_image_url) ? (
876
953
  <>
877
954
  <clipPath id="focus-clip"><circle r={24} /></clipPath>
878
955
  <image href={localPhoto(person.profile_image_url)} x={-24} y={-24} width={48} height={48} clipPath="url(#focus-clip)" />
879
956
  </>
880
957
  ) : (
881
- <text y={5} textAnchor="middle" fill={TIER_COLORS[person.tier] || '#888'} fontSize={16} fontWeight={800}>
958
+ <text y={5} textAnchor="middle" fill={TIER_COLORS[person.tier] || 'var(--sd-fg-3, #888)'} fontSize={16} fontWeight={800}>
882
959
  {person.name?.charAt(0)}
883
960
  </text>
884
961
  )}
885
- <text y={40} textAnchor="middle" fill="#fff" fontSize={11} fontWeight={700} pointerEvents="none">{person.name}</text>
962
+ <text y={40} textAnchor="middle" fill="var(--sd-fg-1, #fff)" fontSize={11} fontWeight={700} pointerEvents="none">{person.name}</text>
886
963
  </g>
887
964
  {hovered && (
888
965
  <Tip x={cx + view.x + hp.x * k} y={cy + view.y + hp.y * k} w={dims.w}
@@ -908,28 +985,28 @@ function CircleFocus({ trail, index, reach, dims, requests, scanningId, still, c
908
985
  <div style={{ display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap', pointerEvents: 'auto' }}>
909
986
  <button type="button" onClick={() => onBack(depth - 1)} style={{
910
987
  padding: '8px 16px', borderRadius: 8, border: 'none', cursor: 'pointer',
911
- background: 'rgba(255,255,255,0.1)', color: '#ddd', fontSize: 12, fontWeight: 700,
988
+ background: 'rgba(var(--sd-ink, 255, 255, 255), 0.1)', color: 'var(--sd-fg-1, #ddd)', fontSize: 12, fontWeight: 700,
912
989
  }}>
913
990
  ← {depth === 1 ? 'All bridges' : `${firstName(trail[depth - 2])}’s circle`}
914
991
  </button>
915
- <nav aria-label="Trail" style={{ fontSize: 11, color: '#777', display: 'flex', gap: 6, flexWrap: 'wrap', alignItems: 'center' }}>
992
+ <nav aria-label="Trail" style={{ fontSize: 11, color: 'var(--sd-fg-4, #777)', display: 'flex', gap: 6, flexWrap: 'wrap', alignItems: 'center' }}>
916
993
  <button type="button" onClick={() => onBack(0)} style={crumb}>All bridges</button>
917
994
  {trail.map((row, i) => (
918
995
  <span key={row.id} style={{ display: 'inline-flex', gap: 6, alignItems: 'center' }}>
919
996
  <span aria-hidden="true">›</span>
920
997
  {i === depth - 1
921
- ? <span style={{ color: '#fff', fontWeight: 700 }}>{row.name}</span>
998
+ ? <span style={{ color: 'var(--sd-fg-1, #fff)', fontWeight: 700 }}>{row.name}</span>
922
999
  : <button type="button" onClick={() => onBack(i + 1)} style={crumb}>{row.name}</button>}
923
1000
  </span>
924
1001
  ))}
925
1002
  </nav>
926
1003
  </div>
927
- <div style={{ fontSize: 11, color: '#999' }}>
1004
+ <div style={{ fontSize: 11, color: 'var(--sd-fg-3, #999)' }}>
928
1005
  {firstName(person)}’s circle · {members.length.toLocaleString('en-US')} {members.length === 1 ? 'person' : 'people'}
929
1006
  {' · '}{ordinal(depth + 1)} degree{depth > 1 ? ', counted along this chain' : ''}
930
1007
  </div>
931
1008
  {scanningThem && members.length > 0 && (
932
- <div role="status" style={{ ...note, borderColor: 'rgba(52,152,219,0.4)', color: '#cfe6f7' }}>
1009
+ <div role="status" style={{ ...note, borderColor: 'rgba(52,152,219,0.4)', color: 'var(--sd-fg-1, #cfe6f7)' }}>
933
1010
  Scanning {firstName(person)}’s circle now. More people appear here as it saves, every 10 pages.
934
1011
  </div>
935
1012
  )}
@@ -940,30 +1017,23 @@ function CircleFocus({ trail, index, reach, dims, requests, scanningId, still, c
940
1017
  scanning={scanningThem} canScan={canScan} onSelect={onSelect} top={cy + 64} />
941
1018
  )}
942
1019
 
943
- {/* What's in this circle */}
1020
+ {/* What's in this circle: dots and counts, no box, as the depth tracker */}
944
1021
  {members.length > 0 && (
945
- <div style={{
946
- position: 'absolute', bottom: 20, left: 20, maxWidth: 'calc(100% - 110px)',
947
- background: 'rgba(0,0,0,0.75)', borderRadius: 10, padding: '10px 14px',
948
- backdropFilter: 'blur(8px)', fontSize: 10, color: '#888', lineHeight: 1.6,
949
- }}>
950
- <div style={{ fontSize: 9, fontWeight: 700, color: '#666', letterSpacing: 1, marginBottom: 6 }}>IN THIS CIRCLE</div>
1022
+ <div title={`Click anyone for their circle${ready > 0 && canScan ? ', or someone ready to scan theirs' : ''} · drag to move · scroll to zoom`}
1023
+ style={{
1024
+ position: 'absolute', bottom: 18, left: 18, maxWidth: 'calc(100% - 110px)',
1025
+ display: 'flex', flexWrap: 'wrap', alignItems: 'center', gap: '6px 14px',
1026
+ fontSize: 10.5, color: 'var(--sd-fg-3, #aab)', textShadow: HALO_TEXT,
1027
+ }}>
951
1028
  {byTier.map(([t, n]) => (
952
- <div key={t} style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
953
- <div style={{ width: 6, height: 6, borderRadius: '50%', background: TIER_COLORS[t] }} />
954
- <span style={{ color: TIER_COLORS[t], fontWeight: 600, width: 40 }}>{t}-Tier</span>
955
- <span>{n.toLocaleString('en-US')}</span>
956
- </div>
1029
+ <span key={t} style={{ display: 'inline-flex', alignItems: 'center', gap: 5 }}>
1030
+ <span className="sd-dot-html" style={{ width: 8, height: 8, borderRadius: '50%', background: TIER_COLORS[t], boxShadow: `0 0 6px ${TIER_COLORS[t]}66` }} />
1031
+ <span style={{ color: TIER_COLORS[t], fontWeight: 700 }}>{t}</span>
1032
+ <span style={{ fontVariantNumeric: 'tabular-nums' }}>{n.toLocaleString('en-US')}</span>
1033
+ </span>
957
1034
  ))}
958
- {(added > 0 || asked > 0) && (
959
- <div style={{ marginTop: 6 }}>
960
- {added > 0 && <div><span style={{ color: GREEN }}>● </span>you added {added}{ready ? `, ${ready} ready to scan` : ''}{hidden ? `, ${hidden} hidden` : ''}</div>}
961
- {asked > 0 && <div><span style={{ color: '#FFD700' }}>◌ </span>{asked} {asked === 1 ? 'request' : 'requests'} out</div>}
962
- </div>
963
- )}
964
- <div style={{ marginTop: 6, color: '#555' }}>
965
- Click anyone for their circle{ready > 0 && canScan ? ', or someone ready to scan theirs' : ''} · drag to move · scroll to zoom
966
- </div>
1035
+ {added > 0 && <span><span style={{ color: GREEN }}>●</span> you added {added}{ready ? `, ${ready} ready to scan` : ''}{hidden ? `, ${hidden} hidden` : ''}</span>}
1036
+ {asked > 0 && <span><span style={{ color: 'var(--sd-gold, #FFD700)' }}>◌</span> {asked} {asked === 1 ? 'request' : 'requests'} out</span>}
967
1037
  </div>
968
1038
  )}
969
1039
 
@@ -972,6 +1042,9 @@ function CircleFocus({ trail, index, reach, dims, requests, scanningId, still, c
972
1042
  );
973
1043
  }
974
1044
 
1045
+ // Words over the map without a box: a soft halo in the theme's background (lib/themes.js).
1046
+ const HALO_TEXT = '0 0 3px var(--sd-bg), 0 0 6px var(--sd-bg), 0 0 1px var(--sd-bg)';
1047
+
975
1048
  // A link's cluster draws at most this many of their people; the count beside it is the whole circle.
976
1049
  const LINK_DOTS = 290;
977
1050
  // The middle of a cluster, where its first ring starts, and a link's own dot inside one.
@@ -1019,10 +1092,10 @@ function Tip({ x, y, w, lines, accent }) {
1019
1092
  const top = Math.max(6, y - height - 12);
1020
1093
  return (
1021
1094
  <g pointerEvents="none">
1022
- <rect x={left} y={top} width={width} height={height} rx={6} fill="rgba(0,0,0,0.92)" stroke={accent || '#555'} strokeWidth={0.6} />
1095
+ <rect x={left} y={top} width={width} height={height} rx={6} fill="var(--sd-surface, rgba(0,0,0,0.92))" stroke={accent || 'var(--sd-fg-5, #555)'} strokeWidth={0.6} />
1023
1096
  {lines.map((line, i) => (
1024
1097
  <text key={i} x={left + width / 2} y={top + 16 + i * 12} textAnchor="middle"
1025
- fill={i === 0 ? '#fff' : i === 2 ? accent || '#aaa' : '#999'} fontSize={i === 0 ? 10.5 : 9} fontWeight={i === 0 ? 700 : 400}>
1098
+ fill={i === 0 ? 'var(--sd-fg-1, #fff)' : i === 2 ? accent || 'var(--sd-fg-3, #aaa)' : 'var(--sd-fg-3, #999)'} fontSize={i === 0 ? 10.5 : 9} fontWeight={i === 0 ? 700 : 400}>
1026
1099
  {line}
1027
1100
  </text>
1028
1101
  ))}
@@ -1039,6 +1112,17 @@ function EmptyCircle({ person, depth, reach, requests, scanning, canScan, onSele
1039
1112
  const next = ordinal(depth + 1);
1040
1113
  const yours = person.degree === 1;
1041
1114
  const state = yours ? circleState(person, reach) : null;
1115
+ // Read partway with nothing saved yet (everyone on those pages was already
1116
+ // yours): that isn't a list that has been read, so it says it stopped, with
1117
+ // the card's Resume (Blake, 2026-10-03: "the ones they stopped and would like
1118
+ // to resume"). Where it stopped is the card's own answer, asked of the server
1119
+ // (GET /api/scraper?resume=<id>): the map's scan notes don't say how far a
1120
+ // list got. Undefined while it's asked.
1121
+ const stopped = useStoppedAt(state === 'scanned' && !scanning ? person.id : null);
1122
+ // Why Resume didn't start, kept here: a start greys this to "Scanning…" for a
1123
+ // moment even when it's refused, and the button's own state would go with it.
1124
+ const [problem, setProblem] = useState(null);
1125
+ if (state === 'scanned' && !scanning && stopped === undefined) return null; // never "has been read" by mistake
1042
1126
  const cost = circleScanCost();
1043
1127
  let title;
1044
1128
  let body;
@@ -1046,6 +1130,10 @@ function EmptyCircle({ person, depth, reach, requests, scanning, canScan, onSele
1046
1130
  if (scanning) {
1047
1131
  title = `Scanning ${first}’s circle now`;
1048
1132
  body = 'Their people appear here as the scan saves them, every 10 pages.';
1133
+ } else if (stopped) {
1134
+ title = `${first}’s scan stopped partway`;
1135
+ body = `${stoppedLine(stopped)}. Everyone on those pages was already one of your connections, so nobody new is here yet. Resume carries on from page ${stopped.nextPage}.`;
1136
+ if (canScan) action = <ResumeHere person={person} stopped={stopped} problem={problem} setProblem={setProblem} />;
1049
1137
  } else if (state === 'hidden') {
1050
1138
  title = `${first} keeps their connections hidden`;
1051
1139
  body = 'LinkedIn doesn’t show their list, so there is no circle to scan.';
@@ -1059,7 +1147,7 @@ function EmptyCircle({ person, depth, reach, requests, scanning, canScan, onSele
1059
1147
  action = (
1060
1148
  <>
1061
1149
  <Link href={scanPageFor(person)} style={primary}>Scan {first}’s circle →</Link>
1062
- <div style={{ fontSize: 10.5, color: '#888', marginTop: 8 }}>
1150
+ <div style={{ fontSize: 10.5, color: 'var(--sd-fg-3, #888)', marginTop: 8 }}>
1063
1151
  {cost.profileViews} profile view, then one LinkedIn search per page of their list (up to {cost.searches}, about {cost.minutes} min).
1064
1152
  It starts only once you confirm it on the Scan page.
1065
1153
  </div>
@@ -1077,21 +1165,78 @@ function EmptyCircle({ person, depth, reach, requests, scanning, canScan, onSele
1077
1165
  return (
1078
1166
  <div role="status" style={{
1079
1167
  position: 'absolute', left: '50%', top, transform: 'translateX(-50%)', width: 'min(360px, calc(100% - 32px))',
1080
- background: 'color-mix(in srgb, var(--sd-bg) 94%, transparent)', border: `1px solid ${state === 'hidden' ? 'rgba(255,255,255,0.12)' : 'rgba(0,255,136,0.25)'}`,
1168
+ background: 'color-mix(in srgb, var(--sd-bg) 94%, transparent)', border: `1px solid ${state === 'hidden' ? 'rgba(var(--sd-ink, 255, 255, 255), 0.12)' : stopped && !scanning ? 'rgba(255,215,0,0.4)' : 'rgba(0,255,136,0.25)'}`,
1081
1169
  borderRadius: 12, padding: '14px 16px', textAlign: 'center',
1082
1170
  }}>
1083
- <div style={{ fontSize: 13, fontWeight: 800, color: state === 'hidden' ? '#aaa' : '#fff', marginBottom: 6 }}>
1171
+ <div style={{ fontSize: 13, fontWeight: 800, color: state === 'hidden' ? 'var(--sd-fg-3, #aaa)' : 'var(--sd-fg-1, #fff)', marginBottom: 6 }}>
1084
1172
  {state === 'hidden' && <span aria-hidden="true">🔒 </span>}{title}
1085
1173
  </div>
1086
- <div style={{ fontSize: 11.5, color: '#9aa', lineHeight: 1.55, marginBottom: action ? 12 : 0 }}>{body}</div>
1174
+ <div style={{ fontSize: 11.5, color: 'var(--sd-fg-3, #9aa)', lineHeight: 1.55, marginBottom: action ? 12 : 0 }}>{body}</div>
1087
1175
  {action}
1088
1176
  </div>
1089
1177
  );
1090
1178
  }
1091
1179
 
1180
+ /**
1181
+ * Where Resume would carry on with one of your connections ({ nextPage,
1182
+ * pagesRead }), null when there's nothing to carry on with, undefined while
1183
+ * it's asked; and never asked for null. Asked again whenever `id` comes back,
1184
+ * as it does when a scan of theirs ends.
1185
+ */
1186
+ function useStoppedAt(id) {
1187
+ const [got, setGot] = useState({ id: null, resume: undefined });
1188
+ useEffect(() => {
1189
+ if (!id) return undefined;
1190
+ let live = true;
1191
+ resumePoint(id).then((r) => { if (live) setGot({ id, resume: r }); }, () => { if (live) setGot({ id, resume: null }); });
1192
+ return () => { live = false; };
1193
+ }, [id]);
1194
+ if (!id) return null;
1195
+ return got.id === id ? got.resume : undefined;
1196
+ }
1197
+
1198
+ /**
1199
+ * Resume for a circle that stopped partway, from the map: what the card's
1200
+ * Resume does (Sidebar.js CreateClusterCard), the same check first, carrying on
1201
+ * from the page it stopped at, never page 1 again. Once it starts, the empty
1202
+ * circle says it's being scanned. Greyed out, saying why, while another scan runs.
1203
+ */
1204
+ function ResumeHere({ person, stopped, problem, setProblem }) {
1205
+ const busy = useSyncExternalStore(watchScanner, () => busyReason(scannerNow()), () => null);
1206
+ const [checking, setChecking] = useState(false);
1207
+ async function go() {
1208
+ setProblem(null);
1209
+ setChecking(true);
1210
+ const blocked = notReadyMessage(await scraperStatus().catch(() => null));
1211
+ setChecking(false);
1212
+ if (blocked) {
1213
+ setProblem(`${blocked} Open the Scan page to finish setting the scanner up.`);
1214
+ return;
1215
+ }
1216
+ try {
1217
+ await beginScrape('resume', { id: person.id });
1218
+ } catch (e) {
1219
+ setProblem(e.message || 'Could not start the scan.');
1220
+ }
1221
+ }
1222
+ const off = Boolean(busy) || checking;
1223
+ return (
1224
+ <>
1225
+ <button type="button" onClick={go} disabled={off} style={{
1226
+ ...primary, border: 'none', cursor: off ? 'not-allowed' : 'pointer', opacity: off ? 0.45 : 1,
1227
+ }}>Resume from page {stopped.nextPage}</button>
1228
+ {(busy || problem) && (
1229
+ <div style={{ fontSize: 10.5, color: problem ? '#ff8080' : 'var(--sd-fg-3, #888)', marginTop: 8 }}>
1230
+ {problem || `${busy}. One scan at a time: this one can start when it finishes.`}
1231
+ </div>
1232
+ )}
1233
+ </>
1234
+ );
1235
+ }
1236
+
1092
1237
  const crumb = { background: 'none', border: 'none', color: '#8fb8d6', fontSize: 11, fontWeight: 600, cursor: 'pointer', padding: 0 };
1093
1238
  const note = {
1094
- fontSize: 11, padding: '6px 10px', borderRadius: 8, border: '1px solid', background: 'rgba(0,0,0,0.6)', pointerEvents: 'auto',
1239
+ fontSize: 11, padding: '6px 10px', borderRadius: 8, border: '1px solid', background: 'rgba(var(--sd-shade, 0, 0, 0), 0.6)', pointerEvents: 'auto',
1095
1240
  };
1096
1241
  const primary = {
1097
1242
  display: 'inline-block', padding: '9px 16px', borderRadius: 8, textDecoration: 'none', fontSize: 12.5, fontWeight: 800,
@@ -1099,5 +1244,5 @@ const primary = {
1099
1244
  };
1100
1245
  const secondary = {
1101
1246
  padding: '8px 14px', borderRadius: 8, cursor: 'pointer', fontSize: 12, fontWeight: 700,
1102
- border: '1px solid rgba(255,255,255,0.18)', background: 'rgba(255,255,255,0.06)', color: '#ddd',
1247
+ border: '1px solid rgba(var(--sd-ink, 255, 255, 255), 0.18)', background: 'rgba(var(--sd-ink, 255, 255, 255), 0.06)', color: 'var(--sd-fg-1, #ddd)',
1103
1248
  };