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
@@ -6,21 +6,23 @@ import OnboardingGate from '../components/OnboardingGate';
6
6
  import Link from 'next/link';
7
7
  import { stopScrape, pickedPerson, scanRequest, HIDE_CHROME_KEY } from '../../lib/scraper-client';
8
8
  import { setupStep, askForField } from '../../lib/scanner-setup';
9
+ import { RISK_POINTS } from '../../lib/scan-risk';
9
10
  import { IS_DEMO } from '../../lib/demo';
10
11
  import { circleScanCost } from '../../lib/reach';
11
12
  import ScanRadar from '../components/ScanRadar';
12
13
  import AppHeader from '../components/AppHeader';
13
- import { paceOf } from '../../lib/scan-pace';
14
+ import { paceOf, durationText, firstCircleSeconds } from '../../lib/scan-pace';
14
15
  import { BudgetBox, CooldownBanner, PausedList } from '../components/LinkedInLimits';
15
16
  import FieldStep, { FieldAnswer } from '../components/FieldStep';
16
17
  import { TIER_COLORS as THEME_TIERS } from '../../lib/themes';
18
+ import ClusterSpinner from '../components/ClusterSpinner';
17
19
 
18
20
  // Everything here runs through /api/scraper. There is deliberately no second
19
21
  // server and no command to copy: the step where people gave up was starting a
20
22
  // Python server in a terminal they had not been told they needed.
21
23
 
22
24
  const BG = 'var(--sd-page)'; // clear: the theme shows through (lib/themes.js)
23
- const LINE = '1px solid rgba(255,255,255,0.1)';
25
+ const LINE = '1px solid rgba(var(--sd-ink, 255, 255, 255), 0.1)';
24
26
 
25
27
  const ACTION_LABELS = {
26
28
  photos: 'Saving profile photos to this computer',
@@ -33,6 +35,7 @@ const ACTION_LABELS = {
33
35
  'auto-bridge-retry': 'Mapping 2nd degree, hidden ones included',
34
36
  resume: 'Carrying on with one paused list',
35
37
  'resume-all': 'Carrying on with every paused list',
38
+ connect: 'Sending a connection request (Auto)',
36
39
  };
37
40
 
38
41
  export default function SetupPage() {
@@ -133,13 +136,32 @@ function SetupInner() {
133
136
  poll();
134
137
  }
135
138
 
136
- // The question is answered: the steps take its place, from the top, since
137
- // it may have been answered from far down the picker.
139
+ // The question is answered: a line takes its place, and the page goes back
140
+ // to the top, since it may have been answered from far down the picker.
138
141
  function answered(sectors) {
139
142
  setField({ sectors });
140
143
  window.scrollTo(0, 0);
141
144
  }
142
145
 
146
+ // "I understand": when, kept with your settings so it travels with a copy.
147
+ async function acceptRisk() {
148
+ setError(null);
149
+ setBusy(true);
150
+ try {
151
+ const r = await fetch('/api/settings', {
152
+ method: 'POST',
153
+ headers: { 'Content-Type': 'application/json' },
154
+ body: JSON.stringify({ settings: { scanRiskAccepted: new Date().toISOString() } }),
155
+ });
156
+ if (!r.ok) setError((await r.json().catch(() => null))?.error || 'Could not save that. Try again.');
157
+ } catch (e) {
158
+ setError(e.message);
159
+ } finally {
160
+ setBusy(false);
161
+ poll();
162
+ }
163
+ }
164
+
143
165
  async function run(action, extra = {}) {
144
166
  setError(null);
145
167
  setBusy(true);
@@ -168,9 +190,13 @@ function SetupInner() {
168
190
  // and a line of its own when the Python inside the app didn't work.
169
191
  const step1 = setupStep(s);
170
192
  const needsDeps = s && !c.dependencies;
171
- const needsChrome = s && !c.chrome;
193
+ // Step 1 says so and offers the download (lib/scanner-setup.js); nothing that opens LinkedIn can start.
194
+ const needsChrome = s && c.chrome === false;
172
195
  const notFound = s && !c.scriptsFound;
173
- const canScrape = s?.ready && !running;
196
+ // The one-time "I understand" before anything opens LinkedIn (lib/scan-risk.js);
197
+ // the server refuses without it too. Unknown (an older server) counts as given.
198
+ const riskOk = c.riskAccepted !== false;
199
+ const canScrape = s?.ready && !running && riskOk;
174
200
  // Anything that searches LinkedIn waits out a cooldown (TRAPS §35).
175
201
  const li = s?.linkedin;
176
202
  const cooling = Boolean(li?.cooldown);
@@ -183,9 +209,12 @@ function SetupInner() {
183
209
  const current = !s || !step1.done ? 1 : !c.signedIn ? 2 : mapped === 0 ? 3 : 4;
184
210
  // Each step: done, the one you're on (now), or still to come (next).
185
211
  const stateOf = (n, done) => (done && n !== current ? 'done' : n === current ? 'now' : n < current ? 'done' : 'next');
186
- // Your field, asked once before the first scan (lib/scanner-setup.js
187
- // askForField). The steps wait while that isn't known yet (null).
212
+ // Your field, asked once when your connections are in, before who they know
213
+ // (lib/scanner-setup.js askForField); left out while that isn't known (null).
188
214
  const askField = IS_DEMO || field ? false : askForField(s, settings);
215
+ // Step 4, honestly: the first circle shows in minutes, the rest takes days.
216
+ const pace = li?.limits?.pace;
217
+ const firstCircle = durationText(firstCircleSeconds(pace));
189
218
  // A run that ended badly, and the line that says why — the last thing it
190
219
  // printed before stopping. Shown as a box, not left for someone to find in the log.
191
220
  const failed = s && !running && s.exitCode != null && s.exitCode !== 0;
@@ -198,7 +227,7 @@ function SetupInner() {
198
227
 
199
228
  return (
200
229
  <div style={{
201
- minHeight: '100vh', background: BG, color: '#fff',
230
+ minHeight: '100vh', background: BG, color: 'var(--sd-fg-1, #fff)',
202
231
  fontFamily: 'var(--sd-font)',
203
232
  }}>
204
233
  {/* The same header as every page, Scan lit (Blake, 2026-10-02: continuity) */}
@@ -209,32 +238,37 @@ function SetupInner() {
209
238
  {/* What the scanner is, in one breath, and what it never does */}
210
239
  <div style={{
211
240
  padding: '26px 26px 22px', borderRadius: 16, marginBottom: 22, position: 'relative', overflow: 'hidden',
212
- background: 'radial-gradient(120% 140% at 0% 0%, rgba(0,255,136,0.10), rgba(52,152,219,0.06) 45%, rgba(255,255,255,0.02) 75%)',
241
+ background: 'radial-gradient(120% 140% at 0% 0%, rgba(0,255,136,0.10), rgba(52,152,219,0.06) 45%, rgba(var(--sd-ink, 255, 255, 255), 0.02) 75%)',
213
242
  border: '1px solid rgba(0,255,136,0.22)',
214
243
  }}>
215
- <div style={{ fontSize: 11, fontWeight: 800, letterSpacing: 1.6, color: '#00ff88' }}>YOUR SCANNER</div>
244
+ <div style={{ fontSize: 11, fontWeight: 800, letterSpacing: 1.6, color: 'var(--sd-green, #00ff88)' }}>YOUR SCANNER</div>
245
+ {/* Steps 1 to 3 draw the galaxy in minutes; step 4 is days of small rounds,
246
+ and saying "four steps" made it sound like one sitting. */}
216
247
  <h1 style={{ fontSize: 27, fontWeight: 800, margin: '6px 0 8px', lineHeight: 1.2 }}>
217
- {mapped > 0 ? 'Your network is mapped. Send the scanner further.' : 'Map your network in four steps.'}
248
+ {mapped > 0 ? 'Your network is mapped. Send the scanner further.' : <>
249
+ Your galaxy in three steps.
250
+ <span style={{ display: 'block', color: 'var(--sd-fg-2, #aab7c4)', fontSize: 20, fontWeight: 700, marginTop: 4 }}>
251
+ Who they know fills in over days.
252
+ </span>
253
+ </>}
218
254
  </h1>
219
- <div style={{ fontSize: 14.5, color: '#aab7c4', lineHeight: 1.6, maxWidth: 560 }}>
255
+ <div style={{ fontSize: 14.5, color: 'var(--sd-fg-2, #aab7c4)', lineHeight: 1.6, maxWidth: 560 }}>
220
256
  It works in your own Chrome on this Mac, slowly and in the open, and keeps everything here.
221
257
  You launch it; it does the reading; you watch it go.
222
258
  </div>
223
259
  <div style={{ display: 'flex', gap: '8px 18px', flexWrap: 'wrap', marginTop: 16 }}>
224
- {['Never posts or messages anyone', 'Never sees your password', 'Nothing leaves this Mac', 'Stops the moment you say'].map((t) => (
225
- <span key={t} style={{ fontSize: 12.5, color: '#cfe8dc', display: 'flex', alignItems: 'center', gap: 6 }}>
226
- <span style={{ color: '#00ff88', fontWeight: 900 }}>✓</span>{t}
260
+ {['Never posts or messages anyone; sends a request only when you press Auto', 'Never sees your password', 'Nothing leaves this Mac', 'Stops the moment you say'].map((t) => (
261
+ <span key={t} style={{ fontSize: 12.5, color: 'var(--sd-fg-1, #cfe8dc)', display: 'flex', alignItems: 'center', gap: 6 }}>
262
+ <span style={{ color: 'var(--sd-green, #00ff88)', fontWeight: 900 }}>✓</span>{t}
227
263
  </span>
228
264
  ))}
229
265
  </div>
230
266
  </div>
231
267
 
232
268
  {/* The first look at the scanner can take a while (it looks for Python): say so, never a blank page. */}
233
- {askField === null && <p style={{ color: '#778', fontSize: 13 }}>Checking your setup…</p>}
234
- {askField && <FieldStep onDone={answered} />}
235
- {field && <FieldAnswer sectors={field.sectors} />}
269
+ {!s && <p style={{ color: 'var(--sd-fg-4, #778)', fontSize: 13 }}>Checking your setup…</p>}
236
270
 
237
- {askField === false && <>
271
+ {s && <>
238
272
  {/* By id: the server finds them by their profile, since two connections can share a name. */}
239
273
  {pick?.person.id === pickId && (
240
274
  <ScanOne
@@ -252,7 +286,7 @@ function SetupInner() {
252
286
  {net.second > 0 && <>, plus {net.second.toLocaleString()} people in their circles</>}
253
287
  {net.third > 0 && <> and {net.third.toLocaleString()} from company scans</>}
254
288
  .{' '}
255
- <span style={{ color: '#9aa' }}>Your galaxy is ready.</span>
289
+ <span style={{ color: 'var(--sd-fg-3, #9aa)' }}>Your galaxy is ready.</span>
256
290
  </div>
257
291
  <Link href="/" style={{
258
292
  padding: '9px 18px', borderRadius: 7, fontSize: 13.5, fontWeight: 700,
@@ -263,6 +297,11 @@ function SetupInner() {
263
297
  </Box>
264
298
  )}
265
299
 
300
+ {/* Your field, once, now that there are people to rank with it (it used to
301
+ stand in front of step 1); then a line saying what it did. */}
302
+ {askField && <FieldStep onDone={answered} />}
303
+ {field && <FieldAnswer sectors={field.sectors} />}
304
+
266
305
  {/* Photos an older version kept as links to LinkedIn. The app shows
267
306
  only photos saved here (lib/photos.js), so until then those people
268
307
  show initials. Every scan saves them at its end; this is the way
@@ -272,14 +311,14 @@ function SetupInner() {
272
311
  <div style={{ display: 'flex', alignItems: 'center', gap: 14, flexWrap: 'wrap' }}>
273
312
  <div style={{ flex: 1, minWidth: 200 }}>
274
313
  <b>{s.photosWaiting.toLocaleString()} {s.photosWaiting === 1 ? 'photo isn’t' : 'photos aren’t'} saved on this computer yet.</b>{' '}
275
- <span style={{ color: '#9aa' }}>
314
+ <span style={{ color: 'var(--sd-fg-3, #9aa)' }}>
276
315
  An older version kept them as links to LinkedIn. The app doesn’t load
277
316
  photos from LinkedIn while you browse, so those people show initials until
278
317
  the photos are saved here: now, or at the end of your next scan. An expired
279
318
  link can’t be saved; that person’s photo comes back when they’re next scanned.
280
319
  </span>
281
320
  {s && !c.dependencies && (
282
- <div style={{ color: '#8b9a9a', fontSize: 12.5, marginTop: 6 }}>Set up the scanner first (step 1 below): it saves them.</div>
321
+ <div style={{ color: 'var(--sd-fg-3, #8b9a9a)', fontSize: 12.5, marginTop: 6 }}>Set up the scanner first (step 1 below): it saves them.</div>
283
322
  )}
284
323
  </div>
285
324
  <Btn onClick={() => run('photos')} disabled={busy || !c.dependencies}>Save photos</Btn>
@@ -292,31 +331,20 @@ function SetupInner() {
292
331
  <b>The last run stopped before it finished.</b>
293
332
  {failReason && (
294
333
  <div style={{
295
- marginTop: 6, color: '#e8c4c4', whiteSpace: 'pre-wrap',
334
+ marginTop: 6, color: 'var(--sd-fg-2, #e8c4c4)', whiteSpace: 'pre-wrap',
296
335
  fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace', fontSize: 12.5,
297
336
  }}>{failReason}</div>
298
337
  )}
299
- <div style={{ color: '#9aa', marginTop: 6 }}>The full log is below.</div>
338
+ <div style={{ color: 'var(--sd-fg-3, #9aa)', marginTop: 6 }}>The full log is below.</div>
300
339
  </Box>
301
340
  )}
302
341
 
303
342
  {notFound && (
304
343
  <Box tone="bad">
305
344
  <b>Can’t find the scanner files.</b><br />
306
- <span style={{ color: '#9aa' }}>
307
- Expected <code style={code}>scripts/scrape.py</code> next to the app. If you
308
- downloaded a zip, run the app from inside the project folder.
309
- </span>
310
- </Box>
311
- )}
312
-
313
- {needsChrome && (
314
- <Box tone="bad">
315
- <b>Google Chrome isn’t installed.</b><br />
316
- <span style={{ color: '#9aa' }}>
317
- The scanner drives your real Chrome. Install it from{' '}
318
- <a href="https://www.google.com/chrome/" target="_blank" rel="noreferrer"
319
- style={{ color: '#3498DB' }}>google.com/chrome</a>, then reload this page.
345
+ <span style={{ color: 'var(--sd-fg-3, #9aa)' }}>
346
+ This copy of Six Degrees is missing part of its scanner. Download it again from
347
+ sixdegreesapp.com and put the new copy in place of this one.
320
348
  </span>
321
349
  </Box>
322
350
  )}
@@ -333,22 +361,37 @@ function SetupInner() {
333
361
  displayed with the line following"): every step shown at once, down a line that turns
334
362
  green as each is done, the one you're on lit, one button each. Everything else waits
335
363
  in Fine-tune. ---- */}
364
+ {s && !riskOk && <RiskCard onAccept={acceptRisk} busy={busy} />}
365
+
336
366
  <div role="list" aria-label="Scanning, step by step" style={{ margin: '4px 0 8px' }}>
337
367
  <style>{JOURNEY_CSS}</style>
338
368
  <StepRow n={1} label="Get ready" state={stateOf(1, step1.done)}>
339
369
  <Mission title="Get your scanner ready" time="A minute or two, once" done={step1.done} body={s ? step1.text : 'Checking…'}
340
370
  launch={s && step1.button && (
341
371
  <Launch onClick={() => run(step1.button.action)} disabled={busy || running}>{step1.button.label}</Launch>
372
+ )}
373
+ // No Chrome: the way to get it. The step turns done by itself once
374
+ // it's installed, since the page keeps asking.
375
+ more={s && step1.chrome && (
376
+ <Launch href={step1.chrome.href} quiet={Boolean(step1.button)}>{step1.chrome.label}</Launch>
342
377
  )} />
343
378
  </StepRow>
344
379
  <StepRow n={2} label="Sign in" state={stateOf(2, !!c.signedIn)}>
345
380
  <Mission title="Sign in to LinkedIn, once" time="You do this part" done={!!c.signedIn}
346
381
  body={c.signedIn
347
382
  ? 'Signed in on this Mac. If LinkedIn ever asks for a security check, or a scan says you were signed out, open LinkedIn here and finish it by hand.'
348
- : 'A Chrome window opens. Sign in with your email and password there: the scanner never sees them. (“Continue with Google” can’t work in it, because Google blocks its sign-in in automated browsers.)'}
383
+ : <>
384
+ A Chrome window opens. Sign in with your email and password there: the scanner never sees them.
385
+ {/* TRAPS §12: Google and Apple block their sign-in in automated browsers, so the fix is a password. */}
386
+ <span style={{ display: 'block', marginTop: 6 }}>
387
+ Sign in to LinkedIn with Google or Apple? That can&rsquo;t work in this window, so set a LinkedIn
388
+ password first: on LinkedIn&rsquo;s sign-in page, <b>Forgot password</b> emails you a link to make one.
389
+ </span>
390
+ </>}
349
391
  launch={c.dependencies && (
350
392
  // Shown after sign-in too: a security check survives the session cookie (TRAPS §35).
351
- <Launch onClick={() => run('login')} disabled={busy || running || current < 2} quiet={!!c.signedIn}>
393
+ // Never without Chrome: the server would refuse it (lib/scanner-setup.js CHROME_REFUSAL).
394
+ <Launch onClick={() => run('login')} disabled={busy || running || current < 2 || !riskOk || needsChrome} quiet={!!c.signedIn}>
352
395
  {running && s.action === 'login' ? 'Waiting for you…' : c.signedIn ? 'Open LinkedIn again' : 'Open LinkedIn'}
353
396
  </Launch>
354
397
  )} />
@@ -364,14 +407,22 @@ function SetupInner() {
364
407
  </Launch>
365
408
  )}
366
409
  more={mapped > 0 && (
367
- <Btn onClick={() => run('refresh')} disabled={!canSearch || current < 3} primary>
368
- {running && s.action === 'refresh' ? 'Checking…' : '↻ Check for new'}
410
+ <Btn onClick={() => run('refresh')} disabled={!canSearch || current < 3} primary cluster active={Boolean(running && s.action === 'refresh')}>
411
+ <ClusterSpinner size={13} live={Boolean(running && s.action === 'refresh')} />
412
+ {running && s.action === 'refresh' ? 'Checking…' : 'Check for new'}
369
413
  </Btn>
370
414
  )} />
371
415
  </StepRow>
372
416
  <StepRow n={4} label="Who they know" state={stateOf(4, false)} last>
373
- <Mission title="Map who they know" time="A small batch a day, slowly"
374
- body={<>It opens your connections one at a time and reads who <i>they</i> know: that fills Degrees, Separation and Outlink. Every round picks up where the last one stopped.</>}>
417
+ {/* Honest about time (the 1.0 first-run list): a circle shows in minutes, a
418
+ network in days, because every page is a search and the budget caps a day's. */}
419
+ <Mission title="Map who they know" time={`First circle in ${firstCircle}`}
420
+ body={<>
421
+ It opens your connections one at a time and reads who <i>they</i> know: that fills Degrees, Separation
422
+ and Outlink. The first circle shows up in {firstCircle}. The rest fills in over days, a round at a time:
423
+ every page is a LinkedIn search, and {li?.limits?.daily ? <>your budget allows {li.limits.daily} a day</>
424
+ : <>a day&rsquo;s searches are best kept few</>}. Every round picks up where the last one stopped.
425
+ </>}>
375
426
  <CooldownBanner
376
427
  cooldown={li?.cooldown}
377
428
  disabled={busy}
@@ -385,21 +436,21 @@ function SetupInner() {
385
436
  scanning={Boolean(running && s?.action?.startsWith('auto-bridge'))}
386
437
  disabled={!canSearch || (order === 'score' && !tiers.length)}
387
438
  label={running && s?.action === 'auto-bridge' ? 'Mapping…' : 'Map 2nd degree'}
388
- sublabel={batch ? `${batch} people` : 'everyone'}
439
+ sublabel={running ? (batch ? `${batch} people` : 'everyone') : `first circle in ${firstCircle}`}
389
440
  onScan={() => run('auto-bridge', { maxBridges: batch, tiers: order === 'score' ? tiers : [], order, maxPages: pages, deeper: finish, experimental })}
390
441
  onPace={busy ? undefined : (pace) => run('set-limits', { ...(li?.limits || {}), pace })}
391
442
  />
392
443
  <div style={{ flex: '1 1 230px', display: 'flex', flexDirection: 'column', gap: 12 }}>
393
- <label style={{ display: 'flex', gap: 10, alignItems: 'center', fontSize: 13, color: '#cfd8d8' }}>
444
+ <label style={{ display: 'flex', gap: 10, alignItems: 'center', fontSize: 13, color: 'var(--sd-fg-2, #cfd8d8)' }}>
394
445
  This round
395
446
  <select value={batch} onChange={(e) => setBatch(Number(e.target.value))} disabled={running} style={selectStyle}>
396
447
  <option value={5}>5 people</option>
397
448
  <option value={10}>10 people</option>
398
449
  <option value={25}>25 people</option>
399
- <option value={0}>everyone — not advised</option>
450
+ <option value={0}>everyone (not advised)</option>
400
451
  </select>
401
452
  </label>
402
- <label style={{ display: 'flex', gap: 10, alignItems: 'center', fontSize: 13, color: '#cfd8d8' }}>
453
+ <label style={{ display: 'flex', gap: 10, alignItems: 'center', fontSize: 13, color: 'var(--sd-fg-2, #cfd8d8)' }}>
403
454
  Start with
404
455
  <select value={order} onChange={(e) => setOrder(e.target.value)} disabled={running} style={selectStyle}>
405
456
  <option value="newest">Newest connections</option>
@@ -407,7 +458,7 @@ function SetupInner() {
407
458
  </select>
408
459
  </label>
409
460
  {order === 'score' && <div style={{ display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' }}>
410
- <span style={{ fontSize: 12, color: '#8b9a9a' }}>Work through</span>
461
+ <span style={{ fontSize: 12, color: 'var(--sd-fg-3, #8b9a9a)' }}>Work through</span>
411
462
  {['S', 'A', 'B', 'C', 'D'].map((t) => {
412
463
  const on = tiers.includes(t);
413
464
  return (
@@ -418,18 +469,18 @@ function SetupInner() {
418
469
  style={{
419
470
  width: 30, height: 28, borderRadius: 7, fontSize: 12, fontWeight: 700,
420
471
  cursor: running ? 'not-allowed' : 'pointer', border: LINE,
421
- background: on ? 'rgba(52,152,219,0.22)' : 'rgba(255,255,255,0.05)',
422
- color: on ? '#cfe6f7' : '#667',
472
+ background: on ? 'rgba(52,152,219,0.22)' : 'rgba(var(--sd-ink, 255, 255, 255), 0.05)',
473
+ color: on ? 'var(--sd-fg-1, #cfe6f7)' : 'var(--sd-fg-4, #667)',
423
474
  }}
424
475
  >{t}</button>
425
476
  );
426
477
  })}
427
- <span style={{ fontSize: 11.5, color: '#667' }}>
478
+ <span style={{ fontSize: 11.5, color: 'var(--sd-fg-4, #667)' }}>
428
479
  {tiers.length ? '' : 'pick at least one'}
429
480
  </span>
430
481
  </div>}
431
482
  {order === 'newest' && (
432
- <div style={{ fontSize: 12, color: '#8b9a9a', lineHeight: 1.6 }}>
483
+ <div style={{ fontSize: 12, color: 'var(--sd-fg-3, #8b9a9a)', lineHeight: 1.6 }}>
433
484
  Goes by the date you connected, newest first, across every tier. Run
434
485
  {' '}<b>Check for new</b> first so your latest connections are in the list.
435
486
  </div>
@@ -437,6 +488,18 @@ function SetupInner() {
437
488
  <WhySlow />
438
489
  </div>
439
490
  </div>
491
+ {/* The circle being read, on the map: Bridge Chains looks again every 20
492
+ seconds while it fills in (app/page.js NetworkRefresh). */}
493
+ {running && s?.mapping?.id && (
494
+ <div style={{ marginTop: 14, fontSize: 13.5 }}>
495
+ <Link href={`/?chain=${encodeURIComponent(s.mapping.id)}`} style={{ color: 'var(--sd-green, #00ff88)', fontWeight: 700 }}>
496
+ Watch it fill in →
497
+ </Link>
498
+ <span style={{ color: 'var(--sd-fg-3, #8b9a9a)', marginLeft: 8 }}>
499
+ {s.mapping.name ? `${s.mapping.name}’s circle, ` : ''}saved every 10 pages.
500
+ </span>
501
+ </div>
502
+ )}
440
503
  </Mission>
441
504
  </StepRow>
442
505
  </div>
@@ -450,10 +513,10 @@ function SetupInner() {
450
513
  }}>
451
514
  <Spinner />
452
515
  <div style={{ flex: 1, fontSize: 13.5 }}>
453
- <div style={{ fontSize: 11, fontWeight: 800, letterSpacing: 1.2, color: '#00ff88', marginBottom: 2 }}>YOUR SCANNER IS WORKING</div>
516
+ <div style={{ fontSize: 11, fontWeight: 800, letterSpacing: 1.2, color: 'var(--sd-green, #00ff88)', marginBottom: 2 }}>YOUR SCANNER IS WORKING</div>
454
517
  <b>{ACTION_LABELS[s.action] || 'Working'}</b>
455
518
  {s.progress && <Progress p={s.progress} action={s.action} />}
456
- <div style={{ color: '#8b9a9a', fontSize: 12.5, marginTop: 2 }}>
519
+ <div style={{ color: 'var(--sd-fg-3, #8b9a9a)', fontSize: 12.5, marginTop: 2 }}>
457
520
  Stopping closes the browser cleanly and keeps everything found so far.
458
521
  </div>
459
522
  </div>
@@ -461,15 +524,27 @@ function SetupInner() {
461
524
  </div>
462
525
  )}
463
526
 
527
+ {/* ---- In progress: everyone whose scan stopped partway, with Resume (Blake, 2026-10-03:
528
+ "some sort of in progress ones in the scanner as well to see all the ones they stopped
529
+ and would like to resume"). Right after step 4, where someone who just stopped a scan
530
+ looks; it was folded away in Fine-tune, and nobody found it. Under Stop while a scan
531
+ runs, so Stop stays right under the step. Only there while someone is. ---- */}
532
+ <PausedList
533
+ paused={s?.paused || []}
534
+ disabled={!canSearch}
535
+ onResume={(p) => run('resume', { id: p.id })}
536
+ onResumeAll={() => run('resume-all', { maxBridges: batch })}
537
+ />
538
+
464
539
  {/* Everything you might want to change, out of the way until you do */}
465
- <details style={{ margin: '18px 0 4px', borderRadius: 10, border: LINE, background: 'rgba(255,255,255,0.02)' }}>
466
- <summary style={{ padding: '12px 16px', cursor: 'pointer', fontSize: 13.5, fontWeight: 650, color: '#cfd8d8' }}>
540
+ <details style={{ margin: '18px 0 4px', borderRadius: 10, border: LINE, background: 'rgba(var(--sd-ink, 255, 255, 255), 0.02)' }}>
541
+ <summary style={{ padding: '12px 16px', cursor: 'pointer', fontSize: 13.5, fontWeight: 650, color: 'var(--sd-fg-2, #cfd8d8)' }}>
467
542
  Fine-tune the scanner
468
- <span style={{ fontWeight: 500, color: '#778', marginLeft: 8 }}>daily budget, how much of each list, the hidden window, paused lists</span>
543
+ <span style={{ fontWeight: 500, color: 'var(--sd-fg-4, #778)', marginLeft: 8 }}>daily budget, how much of each list, the hidden window</span>
469
544
  </summary>
470
545
  <div style={{ padding: '4px 16px 16px', display: 'flex', flexDirection: 'column', gap: 12 }}>
471
546
  <BudgetBox li={li} disabled={busy} onSetLimits={(l) => run('set-limits', l)} />
472
- <label style={{ display: 'flex', gap: 10, alignItems: 'center', fontSize: 12.5, color: '#cfd8d8' }}>
547
+ <label style={{ display: 'flex', gap: 10, alignItems: 'center', fontSize: 12.5, color: 'var(--sd-fg-2, #cfd8d8)' }}>
473
548
  Read up to
474
549
  <select value={pages} onChange={(e) => setPages(Number(e.target.value))} disabled={running} style={selectStyle}>
475
550
  <option value={100}>every page, to the end of their list</option>
@@ -478,26 +553,26 @@ function SetupInner() {
478
553
  <option value={10}>10 pages (~100 people) each</option>
479
554
  </select>
480
555
  </label>
481
- <label style={{ display: 'flex', gap: 8, alignItems: 'center', fontSize: 12.5, color: '#cfd8d8', cursor: running ? 'not-allowed' : 'pointer' }}>
556
+ <label style={{ display: 'flex', gap: 8, alignItems: 'center', fontSize: 12.5, color: 'var(--sd-fg-2, #cfd8d8)', cursor: running ? 'not-allowed' : 'pointer' }}>
482
557
  <input type="checkbox" checked={finish} onChange={(e) => setFinish(e.target.checked)} disabled={running} />
483
558
  Also finish people already mapped, from the page each one stopped at
484
559
  </label>
485
- <label style={{ display: 'flex', gap: 8, alignItems: 'flex-start', fontSize: 12.5, color: '#b8c4c4', cursor: running ? 'default' : 'pointer' }}>
560
+ <label style={{ display: 'flex', gap: 8, alignItems: 'flex-start', fontSize: 12.5, color: 'var(--sd-fg-2, #b8c4c4)', cursor: running ? 'default' : 'pointer' }}>
486
561
  <input type="checkbox" checked={experimental} disabled={running} style={{ marginTop: 3 }}
487
562
  onChange={(e) => { setExperimental(e.target.checked); window.dispatchEvent(new Event('six-degrees:experimental')); }} />
488
563
  <span>
489
- <b style={{ color: '#FFD700' }}>Experimental:</b> all-day pacing. Up to 8 pages in a sitting,
564
+ <b style={{ color: 'var(--sd-gold, #FFD700)' }}>Experimental:</b> all-day pacing. Up to 8 pages in a sitting,
490
565
  then an hour&rsquo;s rest; searches only from 9:00 to 18:00; never more than 40 searches in a day
491
566
  or 200 in a week, however high your budget; two days&rsquo; rest after any check from LinkedIn; at
492
567
  the budget it waits instead of stopping; and it saves every page. It also reads LinkedIn&rsquo;s own data beside
493
568
  the page text, to fill gaps and measure how the two compare. It keeps running while the app is open.
494
569
  </span>
495
570
  </label>
496
- <label style={{ display: 'flex', gap: 8, alignItems: 'flex-start', fontSize: 12.5, color: '#b8c4c4', cursor: running ? 'default' : 'pointer' }}>
571
+ <label style={{ display: 'flex', gap: 8, alignItems: 'flex-start', fontSize: 12.5, color: 'var(--sd-fg-2, #b8c4c4)', cursor: running ? 'default' : 'pointer' }}>
497
572
  <input type="checkbox" checked={hideChrome} disabled={running} style={{ marginTop: 3 }}
498
573
  onChange={(e) => setHideChrome(e.target.checked)} />
499
574
  <span>
500
- <b style={{ color: '#FFD700' }}>Hide the Chrome window while scanning.</b> Every scan runs with no
575
+ <b style={{ color: 'var(--sd-gold, #FFD700)' }}>Hide the Chrome window while scanning.</b> Every scan runs with no
501
576
  window popping up; the status bar still shows what it&rsquo;s doing, and Stop still works. Signing
502
577
  in always opens the window.
503
578
  <span style={{ display: 'block', marginTop: 4, color: '#e0a080' }}>
@@ -509,7 +584,7 @@ function SetupInner() {
509
584
  </span>
510
585
  </span>
511
586
  </label>
512
- <div style={{ fontSize: 12, color: '#FFD700', lineHeight: 1.6 }}>
587
+ <div style={{ fontSize: 12, color: 'var(--sd-gold, #FFD700)', lineHeight: 1.6 }}>
513
588
  Every page is a LinkedIn search, so at {paceOf(li?.limits?.pace).label} it rests{' '}
514
589
  {paceOf(li?.limits?.pace).pagePause} seconds before each one and{' '}
515
590
  {paceOf(li?.limits?.pace).chunkCooldown / 60 === 1 ? 'a minute' : `${paceOf(li?.limits?.pace).chunkCooldown / 60} minutes`} after every 10, and a long list can take
@@ -522,14 +597,8 @@ function SetupInner() {
522
597
  <Btn onClick={() => run('auto-bridge-retry', { maxBridges: batch, tiers: order === 'score' ? tiers : [], order, maxPages: pages, deeper: finish })} disabled={!canSearch || (order === 'score' && !tiers.length)}>
523
598
  Retry hidden ones
524
599
  </Btn>
525
- <span style={{ fontSize: 12, color: '#8b9a9a', marginLeft: 10 }}>People whose list was hidden last time, in case they&rsquo;ve opened it.</span>
600
+ <span style={{ fontSize: 12, color: 'var(--sd-fg-3, #8b9a9a)', marginLeft: 10 }}>People whose list was hidden last time, in case they&rsquo;ve opened it.</span>
526
601
  </div>
527
- <PausedList
528
- paused={s?.paused || []}
529
- disabled={!canSearch}
530
- onResume={(p) => run('resume', { id: p.id })}
531
- onResumeAll={() => run('resume-all', { maxBridges: batch })}
532
- />
533
602
  </div>
534
603
  </details>
535
604
 
@@ -540,15 +609,15 @@ function SetupInner() {
540
609
  <details open={failed} style={{ marginTop: 20 }}>
541
610
  <summary style={{
542
611
  display: 'flex', alignItems: 'center', gap: 10, cursor: 'pointer',
543
- margin: '8px 0', fontSize: 12, color: '#788', textTransform: 'uppercase', letterSpacing: 0.6,
612
+ margin: '8px 0', fontSize: 12, color: 'var(--sd-fg-3, #788)', textTransform: 'uppercase', letterSpacing: 0.6,
544
613
  }}>
545
614
  {running && <Spinner />}
546
615
  {running ? 'What it’s doing (the log)' : 'The last run’s log'}
547
616
  </summary>
548
617
  <pre ref={logRef} style={{
549
- background: 'rgba(0,0,0,0.45)', border: LINE, borderRadius: 8,
618
+ background: 'rgba(var(--sd-shade, 0, 0, 0), 0.45)', border: LINE, borderRadius: 8,
550
619
  padding: 14, maxHeight: 280, overflow: 'auto', margin: 0,
551
- fontSize: 12.5, lineHeight: 1.7, color: '#b9c6c6',
620
+ fontSize: 12.5, lineHeight: 1.7, color: 'var(--sd-fg-2, #b9c6c6)',
552
621
  fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',
553
622
  whiteSpace: 'pre-wrap', wordBreak: 'break-word',
554
623
  }}>{s.log.join('\n')}</pre>
@@ -556,17 +625,6 @@ function SetupInner() {
556
625
  )}
557
626
  </>}
558
627
 
559
- <div style={{ marginTop: 32, paddingTop: 20, borderTop: LINE, fontSize: 13.5, color: '#8b9a9a' }}>
560
- Checking for updates has moved to{' '}
561
- <Link href="/settings#updates" style={{ color: '#3498DB' }}>Settings →</Link>
562
- </div>
563
-
564
- <p style={{ color: '#667', fontSize: 12.5, lineHeight: 1.7, marginTop: 32 }}>
565
- Automating LinkedIn may go against its User Agreement, and accounts have been
566
- restricted for it. This runs locally against your own account, at your own risk.
567
- LinkedIn’s own CSV export is the supported route and needs none of this —{' '}
568
- <Link href="/import" style={{ color: '#3498DB' }}>import a CSV instead</Link>.
569
- </p>
570
628
  </div>
571
629
 
572
630
  <style>{`@keyframes spin { to { transform: rotate(360deg) } }
@@ -589,35 +647,35 @@ function ScanOne({ pick, pages, setPages, li, running, s, canSearch, busy, onSta
589
647
  margin: '16px 0', padding: '16px 18px', borderRadius: 10, fontSize: 13.5, lineHeight: 1.6,
590
648
  background: 'rgba(0,255,136,0.05)', border: '1px solid rgba(0,255,136,0.3)',
591
649
  }}>
592
- <div style={{ fontSize: 11, fontWeight: 700, color: '#00ff88', letterSpacing: 0.6, textTransform: 'uppercase', marginBottom: 4 }}>
650
+ <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--sd-green, #00ff88)', letterSpacing: 0.6, textTransform: 'uppercase', marginBottom: 4 }}>
593
651
  Scan one circle
594
652
  </div>
595
653
  <div style={{ fontSize: 16, fontWeight: 700 }}>
596
654
  {person.name} <span style={{ fontSize: 12, color: TIER[person.tier] || '#888' }}>{person.tier}-tier</span>
597
655
  </div>
598
656
  {person.unlocked_from_name && (
599
- <div style={{ fontSize: 12.5, color: '#9aa' }}>Was in {person.unlocked_from_name}&rsquo;s circle</div>
657
+ <div style={{ fontSize: 12.5, color: 'var(--sd-fg-3, #9aa)' }}>Was in {person.unlocked_from_name}&rsquo;s circle</div>
600
658
  )}
601
659
  {theirs ? (
602
660
  <div style={{ marginTop: 10 }}>
603
661
  <b>Scanning {first}&rsquo;s circle.</b> It saves every 10 pages, and{' '}
604
- <Link href={`/?chain=${encodeURIComponent(person.id)}`} style={{ color: '#00ff88' }}>Bridge Chains shows it filling in →</Link>
662
+ <Link href={`/?chain=${encodeURIComponent(person.id)}`} style={{ color: 'var(--sd-green, #00ff88)' }}>Bridge Chains shows it filling in →</Link>
605
663
  </div>
606
664
  ) : (
607
665
  <>
608
- <div style={{ color: '#b8c4c4', marginTop: 10 }}>
666
+ <div style={{ color: 'var(--sd-fg-2, #b8c4c4)', marginTop: 10 }}>
609
667
  It costs <b>{cost.profileViews} profile view</b> to find their list, then <b>one LinkedIn search for
610
668
  every page</b> of it: up to {cost.searches} {cost.searches === 1 ? 'page' : 'pages'}, about {cost.minutes} minutes.
611
669
  {li?.leftToday != null && <> <b>{li.leftToday}</b> of your {li.limits?.daily} searches a day are left{short ? '; the scan stops when they run out, and can carry on from that page later' : ''}.</>}
612
670
  </div>
613
671
  {circle === 'scanned' && (
614
- <div style={{ color: '#FFD700', fontSize: 12.5, marginTop: 6 }}>
672
+ <div style={{ color: 'var(--sd-gold, #FFD700)', fontSize: 12.5, marginTop: 6 }}>
615
673
  Their circle is already scanned. This reads their whole list again from page 1; to carry on
616
- from where a read stopped, use Resume on their card or in the Paused list below.
674
+ from where a read stopped, use Resume on their card or under In progress below.
617
675
  </div>
618
676
  )}
619
677
  {circle === 'hidden' && (
620
- <div style={{ color: '#FFD700', fontSize: 12.5, marginTop: 6 }}>
678
+ <div style={{ color: 'var(--sd-gold, #FFD700)', fontSize: 12.5, marginTop: 6 }}>
621
679
  Their list was hidden last time it was tried. Trying again costs a profile view.
622
680
  </div>
623
681
  )}
@@ -633,7 +691,7 @@ function ScanOne({ pick, pages, setPages, li, running, s, canSearch, busy, onSta
633
691
  <Btn onClick={onUnpick}>Not now</Btn>
634
692
  </div>
635
693
  {!canSearch && (
636
- <div style={{ fontSize: 12.5, color: '#8b9a9a', marginTop: 8 }}>
694
+ <div style={{ fontSize: 12.5, color: 'var(--sd-fg-3, #8b9a9a)', marginTop: 8 }}>
637
695
  {running ? 'Something else is running. One scan at a time: this one can start when it finishes.'
638
696
  : li?.cooldown ? 'Scanning is paused for now (see below).'
639
697
  : 'The scanner isn’t ready yet: finish the steps below first.'}
@@ -665,10 +723,9 @@ function useRemembered(key, fallback) {
665
723
  return [value, set];
666
724
  }
667
725
 
668
- const code = { background: 'rgba(255,255,255,0.08)', padding: '1px 5px', borderRadius: 4 };
669
726
  const selectStyle = {
670
727
  padding: '9px 10px', borderRadius: 7, fontSize: 13.5, fontWeight: 600,
671
- background: 'rgba(255,255,255,0.08)', color: '#fff', border: LINE,
728
+ background: 'rgba(var(--sd-ink, 255, 255, 255), 0.08)', color: 'var(--sd-fg-1, #fff)', border: LINE,
672
729
  };
673
730
 
674
731
  const JOURNEY_CSS = `
@@ -695,26 +752,26 @@ function StepRow({ n, label, state, last = false, children }) {
695
752
  <span className={now ? 'journey-now' : undefined} aria-hidden="true" style={{
696
753
  position: 'relative', zIndex: 1, width: 38, height: 38, borderRadius: '50%', display: 'grid', placeItems: 'center',
697
754
  fontSize: 15, fontWeight: 800,
698
- background: done ? 'rgba(0,255,136,0.16)' : now ? 'linear-gradient(135deg, #00ff88, #1abc9c)' : '#12142a',
699
- color: done ? '#00ff88' : now ? '#04140c' : '#778',
700
- border: `2px solid ${done ? 'rgba(0,255,136,0.55)' : now ? 'transparent' : 'rgba(255,255,255,0.14)'}`,
755
+ background: done ? 'rgba(0,255,136,0.16)' : now ? 'linear-gradient(135deg, #00ff88, #1abc9c)' : 'var(--sd-card, #12142a)',
756
+ color: done ? 'var(--sd-green, #00ff88)' : now ? '#04140c' : 'var(--sd-fg-4, #778)',
757
+ border: `2px solid ${done ? 'rgba(0,255,136,0.55)' : now ? 'transparent' : 'rgba(var(--sd-ink, 255, 255, 255), 0.14)'}`,
701
758
  }}>{done ? '✓' : n}</span>
702
759
  {!last && (
703
760
  <span aria-hidden="true" style={{
704
761
  position: 'absolute', top: 40, bottom: 0, left: '50%', width: 2, marginLeft: -1, borderRadius: 1,
705
- background: done ? 'linear-gradient(rgba(0,255,136,0.75), rgba(0,255,136,0.3))' : 'rgba(255,255,255,0.1)',
762
+ background: done ? 'linear-gradient(rgba(0,255,136,0.75), rgba(0,255,136,0.3))' : 'rgba(var(--sd-ink, 255, 255, 255), 0.1)',
706
763
  }} />
707
764
  )}
708
765
  </div>
709
766
  <div style={{ minWidth: 0, paddingBottom: last ? 0 : 16, opacity: state === 'next' ? 0.75 : 1 }}>
710
767
  <div style={{ display: 'flex', alignItems: 'center', gap: 10, minHeight: 38, marginBottom: 6 }}>
711
- <span style={{ fontSize: 12, fontWeight: 800, letterSpacing: 1.2, textTransform: 'uppercase', color: done ? '#00ff88' : now ? '#fff' : '#889' }}>
768
+ <span style={{ fontSize: 12, fontWeight: 800, letterSpacing: 1.2, textTransform: 'uppercase', color: done ? 'var(--sd-green, #00ff88)' : now ? 'var(--sd-fg-1, #fff)' : 'var(--sd-fg-3, #889)' }}>
712
769
  Step {n} · {label}
713
770
  </span>
714
771
  <span style={{
715
772
  fontSize: 10.5, fontWeight: 800, padding: '2px 8px', borderRadius: 10,
716
- color: done ? '#00ff88' : now ? '#04140c' : '#889',
717
- background: done ? 'rgba(0,255,136,0.12)' : now ? '#00ff88' : 'rgba(255,255,255,0.06)',
773
+ color: done ? 'var(--sd-green, #00ff88)' : now ? '#04140c' : 'var(--sd-fg-3, #889)',
774
+ background: done ? 'rgba(0,255,136,0.12)' : now ? '#00ff88' : 'rgba(var(--sd-ink, 255, 255, 255), 0.06)',
718
775
  }}>{done ? 'Done' : now ? 'Now' : 'Next'}</span>
719
776
  </div>
720
777
  {children}
@@ -728,40 +785,57 @@ function Mission({ title, time, body, launch, more, done = false, children }) {
728
785
  return (
729
786
  <div style={{
730
787
  padding: done ? '14px 18px' : '18px 20px', borderRadius: 14,
731
- background: done ? 'rgba(0,255,136,0.03)' : 'rgba(255,255,255,0.035)',
732
- border: `1px solid ${done ? 'rgba(0,255,136,0.18)' : 'rgba(255,255,255,0.1)'}`,
788
+ background: done ? 'rgba(0,255,136,0.03)' : 'rgba(var(--sd-ink, 255, 255, 255), 0.035)',
789
+ border: `1px solid ${done ? 'rgba(0,255,136,0.18)' : 'rgba(var(--sd-ink, 255, 255, 255), 0.1)'}`,
733
790
  }}>
734
791
  <div style={{ display: 'flex', alignItems: 'baseline', gap: 10, flexWrap: 'wrap' }}>
735
792
  <span style={{ fontSize: done ? 16 : 19, fontWeight: 800 }}>{title}</span>
736
- {time && !done && <span style={{ fontSize: 12, color: '#8fd9b6', marginLeft: 'auto' }}>⏱ {time}</span>}
793
+ {time && !done && <span style={{ fontSize: 12, color: 'var(--sd-fg-2, #8fd9b6)', marginLeft: 'auto' }}>⏱ {time}</span>}
737
794
  </div>
738
- <div style={{ fontSize: done ? 13 : 14, color: '#9fb0bb', lineHeight: 1.6, margin: done ? '6px 0 10px' : '8px 0 14px', maxWidth: 600 }}>{body}</div>
795
+ <div style={{ fontSize: done ? 13 : 14, color: 'var(--sd-fg-3, #9fb0bb)', lineHeight: 1.6, margin: done ? '6px 0 10px' : '8px 0 14px', maxWidth: 600 }}>{body}</div>
739
796
  {children}
740
797
  {(launch || more) && <div style={{ display: 'flex', gap: 10, alignItems: 'center', flexWrap: 'wrap' }}>{launch}{more}</div>}
741
798
  </div>
742
799
  );
743
800
  }
744
801
 
745
- /** The big go button. `quiet` once that step is done, so the next thing to do stands out. */
746
- function Launch({ children, onClick, disabled, quiet = false }) {
802
+ /**
803
+ * The big go button. `quiet` once that step is done, so the next thing to do
804
+ * stands out. With `href`, a link that looks the same, opened outside the app
805
+ * (the desktop app sends it to the browser): Chrome's download.
806
+ */
807
+ function Launch({ children, onClick, disabled, quiet = false, href }) {
808
+ if (href) {
809
+ return (
810
+ <a className="launch-go" href={href} target="_blank" rel="noreferrer" style={{
811
+ ...launchLook(false, quiet), textDecoration: 'none',
812
+ }}>
813
+ <span aria-hidden="true" style={{ fontSize: quiet ? 11 : 13 }}>▶</span>{children}
814
+ </a>
815
+ );
816
+ }
747
817
  return (
748
- <button type="button" className="launch-go" onClick={onClick} disabled={disabled} style={{
749
- display: 'inline-flex', alignItems: 'center', gap: 10, padding: quiet ? '10px 18px' : '13px 26px', borderRadius: 12,
750
- fontSize: quiet ? 14 : 16, fontWeight: 800, cursor: disabled ? 'not-allowed' : 'pointer',
751
- color: disabled ? '#667' : quiet ? '#cfe8dc' : '#04140c', border: quiet ? '1px solid rgba(0,255,136,0.35)' : 'none',
752
- background: disabled ? 'rgba(255,255,255,0.06)' : quiet ? 'rgba(0,255,136,0.08)' : 'linear-gradient(135deg, #00ff88, #1abc9c)',
753
- boxShadow: disabled || quiet ? 'none' : '0 4px 22px rgba(0,255,136,0.25)',
754
- }}>
818
+ <button type="button" className="launch-go" onClick={onClick} disabled={disabled} style={launchLook(disabled, quiet)}>
755
819
  <span aria-hidden="true" style={{ fontSize: quiet ? 11 : 13 }}>▶</span>{children}
756
820
  </button>
757
821
  );
758
822
  }
759
823
 
824
+ function launchLook(disabled, quiet) {
825
+ return {
826
+ display: 'inline-flex', alignItems: 'center', gap: 10, padding: quiet ? '10px 18px' : '13px 26px', borderRadius: 12,
827
+ fontSize: quiet ? 14 : 16, fontWeight: 800, cursor: disabled ? 'not-allowed' : 'pointer',
828
+ color: disabled ? 'var(--sd-fg-4, #667)' : quiet ? 'var(--sd-fg-1, #cfe8dc)' : '#04140c', border: quiet ? '1px solid rgba(0,255,136,0.35)' : 'none',
829
+ background: disabled ? 'rgba(var(--sd-ink, 255, 255, 255), 0.06)' : quiet ? 'rgba(0,255,136,0.08)' : 'linear-gradient(135deg, #00ff88, #1abc9c)',
830
+ boxShadow: disabled || quiet ? 'none' : '0 4px 22px rgba(0,255,136,0.25)',
831
+ };
832
+ }
833
+
760
834
  /** Why the second degree goes slowly: one tap away, not in the way. */
761
835
  function WhySlow() {
762
836
  return (
763
- <details style={{ fontSize: 12.5, color: '#8b9a9a', lineHeight: 1.6 }}>
764
- <summary style={{ cursor: 'pointer', color: '#aab7c4', fontWeight: 600 }}>Why so slow?</summary>
837
+ <details style={{ fontSize: 12.5, color: 'var(--sd-fg-3, #8b9a9a)', lineHeight: 1.6 }}>
838
+ <summary style={{ cursor: 'pointer', color: 'var(--sd-fg-2, #aab7c4)', fontWeight: 600 }}>Why so slow?</summary>
765
839
  <div style={{ marginTop: 6 }}>
766
840
  This is the part LinkedIn notices. While this app was being built, a real account was
767
841
  restricted for a while after roughly <b>19 people in one sitting</b>. So: a small batch, a day&rsquo;s
@@ -773,25 +847,54 @@ function WhySlow() {
773
847
  );
774
848
  }
775
849
 
776
- function Btn({ children, onClick, disabled, primary, tone }) {
850
+ // `cluster`: its first child is a ClusterSpinner, built on hover (app/components/ClusterSpinner.js).
851
+ // `active`: its own job is running, so it stays lit (and can't be pressed again).
852
+ function Btn({ children, onClick, disabled, primary, tone, cluster = false, active = false }) {
777
853
  const bg = tone === 'bad' ? 'rgba(255,80,80,0.15)'
778
854
  : primary ? 'linear-gradient(135deg, #9B59B6, #3498DB)'
779
- : 'rgba(255,255,255,0.08)';
855
+ : 'rgba(var(--sd-ink, 255, 255, 255), 0.08)';
780
856
  return (
781
- <button onClick={onClick} disabled={disabled} style={{
857
+ <button onClick={onClick} disabled={disabled} className={cluster ? 'cluster-host' : undefined} style={{
782
858
  padding: '9px 18px', borderRadius: 7, fontSize: 13.5, fontWeight: 650,
783
- color: disabled ? '#667' : '#fff', background: disabled ? 'rgba(255,255,255,0.05)' : bg,
784
- border: LINE, cursor: disabled ? 'not-allowed' : 'pointer',
859
+ // White on the purple gradient in every look; the theme's words elsewhere.
860
+ color: disabled && !active ? 'var(--sd-fg-4, #667)' : primary ? '#fff' : 'var(--sd-fg-1, #fff)', background: disabled && !active ? 'rgba(var(--sd-ink, 255, 255, 255), 0.05)' : bg,
861
+ border: LINE, cursor: active ? 'progress' : disabled ? 'not-allowed' : 'pointer',
862
+ ...(cluster ? { display: 'inline-flex', alignItems: 'center', gap: 8 } : {}),
785
863
  }}>{children}</button>
786
864
  );
787
865
  }
788
866
 
867
+ // Before the first scan, once: what scanning does and risks, and an explicit
868
+ // "I understand" (lib/scan-risk.js). The CSV stays one click away for anyone
869
+ // who would rather not.
870
+ function RiskCard({ onAccept, busy }) {
871
+ return (
872
+ <div role="region" aria-label="Before your first scan" style={{
873
+ margin: '6px 0 18px', padding: '16px 18px', borderRadius: 12,
874
+ border: '1px solid rgba(var(--sd-ink, 255, 255, 255), 0.14)',
875
+ background: 'rgba(var(--sd-ink, 255, 255, 255), 0.04)',
876
+ }}>
877
+ <div style={{ fontSize: 15, fontWeight: 700, color: 'var(--sd-fg-1, #fff)', marginBottom: 8 }}>Before your first scan</div>
878
+ <ul style={{ margin: '0 0 14px', paddingLeft: 18, color: 'var(--sd-fg-2, #c8d0d0)', fontSize: 13.5, lineHeight: 1.65 }}>
879
+ {RISK_POINTS.map((p) => <li key={p} style={{ marginBottom: 4 }}>{p}</li>)}
880
+ </ul>
881
+ <div style={{ display: 'flex', gap: 14, alignItems: 'center', flexWrap: 'wrap' }}>
882
+ <Btn onClick={onAccept} disabled={busy} primary>I understand</Btn>
883
+ <span style={{ fontSize: 13, color: 'var(--sd-fg-3, #8b9a9a)' }}>
884
+ Rather not? LinkedIn’s own CSV export needs none of this:{' '}
885
+ <Link href="/import" style={{ color: 'var(--sd-blue, #3498DB)' }}>import a CSV instead</Link>.
886
+ </span>
887
+ </div>
888
+ </div>
889
+ );
890
+ }
891
+
789
892
  function Box({ children, tone }) {
790
893
  return (
791
894
  <div style={{
792
895
  margin: '16px 0', padding: '14px 16px', borderRadius: 8, fontSize: 13.5, lineHeight: 1.6,
793
- background: tone === 'bad' ? 'rgba(255,80,80,0.08)' : 'rgba(255,255,255,0.05)',
794
- border: `1px solid ${tone === 'bad' ? 'rgba(255,80,80,0.3)' : 'rgba(255,255,255,0.12)'}`,
896
+ background: tone === 'bad' ? 'rgba(255,80,80,0.08)' : 'rgba(var(--sd-ink, 255, 255, 255), 0.05)',
897
+ border: `1px solid ${tone === 'bad' ? 'rgba(255,80,80,0.3)' : 'rgba(var(--sd-ink, 255, 255, 255), 0.12)'}`,
795
898
  }}>{children}</div>
796
899
  );
797
900
  }
@@ -805,15 +908,15 @@ function Progress({ p, action }) {
805
908
  return (
806
909
  <div style={{ margin: '8px 0 6px' }}>
807
910
  <div role="progressbar" aria-label="Saving" style={{
808
- height: 8, borderRadius: 4, overflow: 'hidden', background: 'rgba(255,255,255,0.08)', marginBottom: 6,
911
+ height: 8, borderRadius: 4, overflow: 'hidden', background: 'rgba(var(--sd-ink, 255, 255, 255), 0.08)', marginBottom: 6,
809
912
  }}>
810
913
  <div style={{
811
914
  width: '35%', height: '100%', borderRadius: 4,
812
915
  background: 'linear-gradient(90deg, #9B59B6, #3498DB)', animation: 'slide 1.2s ease-in-out infinite',
813
916
  }} />
814
917
  </div>
815
- <div style={{ fontSize: 12.5, color: '#cfe6f7' }}>
816
- Saving to your network and fetching photos — this can take a minute or two.
918
+ <div style={{ fontSize: 12.5, color: 'var(--sd-fg-1, #cfe6f7)' }}>
919
+ Saving to your network and fetching photos. This can take a minute or two.
817
920
  </div>
818
921
  </div>
819
922
  );
@@ -822,7 +925,7 @@ function Progress({ p, action }) {
822
925
  let text;
823
926
  if (p.kind === 'download') text = `Downloading Python: ${p.done.toFixed(1)} of ${p.total.toFixed(1)} MB · ${pct}%`;
824
927
  else if (p.kind === 'batch') text = `Person ${p.current} of ${p.total}`;
825
- else if (action === 'refresh') text = `Looked at ${p.done.toLocaleString()} so far — stops once it reaches people already saved`;
928
+ else if (action === 'refresh') text = `Looked at ${p.done.toLocaleString()} so far, and stops once it reaches people already saved`;
826
929
  else text = `${p.done.toLocaleString()} of ${p.total.toLocaleString()} connections · ${pct}%`;
827
930
 
828
931
  return (
@@ -836,7 +939,7 @@ function Progress({ p, action }) {
836
939
  aria-label={text}
837
940
  style={{
838
941
  height: 8, borderRadius: 4, overflow: 'hidden',
839
- background: 'rgba(255,255,255,0.08)', marginBottom: 6,
942
+ background: 'rgba(var(--sd-ink, 255, 255, 255), 0.08)', marginBottom: 6,
840
943
  }}
841
944
  >
842
945
  <div style={{
@@ -846,7 +949,7 @@ function Progress({ p, action }) {
846
949
  }} />
847
950
  </div>
848
951
  )}
849
- <div style={{ fontSize: 12.5, color: '#cfe6f7' }}>{text}</div>
952
+ <div style={{ fontSize: 12.5, color: 'var(--sd-fg-1, #cfe6f7)' }}>{text}</div>
850
953
  </div>
851
954
  );
852
955
  }
@@ -854,7 +957,7 @@ function Progress({ p, action }) {
854
957
  function Spinner() {
855
958
  return <span style={{
856
959
  width: 11, height: 11, borderRadius: '50%', display: 'inline-block',
857
- border: '2px solid rgba(255,255,255,0.2)', borderTopColor: '#3498DB',
960
+ border: '2px solid rgba(var(--sd-ink, 255, 255, 255), 0.2)', borderTopColor: '#3498DB',
858
961
  animation: 'spin 0.8s linear infinite',
859
962
  }} />;
860
963
  }