six-degrees 0.6.0 → 0.7.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 (557) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-path-routes-manifest.json +3 -0
  3. package/.next/standalone/.next/build-manifest.json +3 -3
  4. package/.next/standalone/.next/prerender-manifest.json +14 -14
  5. package/.next/standalone/.next/routes-manifest.json +18 -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 +2 -2
  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 +4 -2
  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/launch/page.js +1 -1
  115. package/.next/standalone/.next/server/app/launch/page.js.nft.json +1 -1
  116. package/.next/standalone/.next/server/app/launch/page_client-reference-manifest.js +1 -1
  117. package/.next/standalone/.next/server/app/launch.html +2 -2
  118. package/.next/standalone/.next/server/app/launch.rsc +32 -24
  119. package/.next/standalone/.next/server/app/launch.segments/_full.segment.rsc +32 -24
  120. package/.next/standalone/.next/server/app/launch.segments/_tree.segment.rsc +2 -2
  121. package/.next/standalone/.next/server/app/launch.segments/launch/__PAGE__.segment.rsc +23 -18
  122. package/.next/standalone/.next/server/app/page.js +1 -1
  123. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  124. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  125. package/.next/standalone/.next/server/app/paths/page.js +1 -1
  126. package/.next/standalone/.next/server/app/paths/page.js.nft.json +1 -1
  127. package/.next/standalone/.next/server/app/paths/page_client-reference-manifest.js +1 -1
  128. package/.next/standalone/.next/server/app/paths.html +1 -1
  129. package/.next/standalone/.next/server/app/paths.rsc +32 -24
  130. package/.next/standalone/.next/server/app/paths.segments/_full.segment.rsc +32 -24
  131. package/.next/standalone/.next/server/app/paths.segments/_tree.segment.rsc +2 -2
  132. package/.next/standalone/.next/server/app/paths.segments/paths/__PAGE__.segment.rsc +21 -18
  133. package/.next/standalone/.next/server/app/profile/page.js +1 -1
  134. package/.next/standalone/.next/server/app/profile/page.js.nft.json +1 -1
  135. package/.next/standalone/.next/server/app/profile/page_client-reference-manifest.js +1 -1
  136. package/.next/standalone/.next/server/app/profile.html +1 -1
  137. package/.next/standalone/.next/server/app/profile.rsc +32 -24
  138. package/.next/standalone/.next/server/app/profile.segments/_full.segment.rsc +32 -24
  139. package/.next/standalone/.next/server/app/profile.segments/_tree.segment.rsc +2 -2
  140. package/.next/standalone/.next/server/app/profile.segments/profile/__PAGE__.segment.rsc +23 -18
  141. package/.next/standalone/.next/server/app/queue/page.js +1 -1
  142. package/.next/standalone/.next/server/app/queue/page.js.nft.json +1 -1
  143. package/.next/standalone/.next/server/app/queue/page_client-reference-manifest.js +1 -1
  144. package/.next/standalone/.next/server/app/queue.html +1 -1
  145. package/.next/standalone/.next/server/app/queue.rsc +32 -24
  146. package/.next/standalone/.next/server/app/queue.segments/_full.segment.rsc +32 -24
  147. package/.next/standalone/.next/server/app/queue.segments/_tree.segment.rsc +2 -2
  148. package/.next/standalone/.next/server/app/queue.segments/queue/__PAGE__.segment.rsc +20 -18
  149. package/.next/standalone/.next/server/app/scores/page.js +1 -1
  150. package/.next/standalone/.next/server/app/scores/page.js.nft.json +1 -1
  151. package/.next/standalone/.next/server/app/scores/page_client-reference-manifest.js +1 -1
  152. package/.next/standalone/.next/server/app/scores.html +1 -1
  153. package/.next/standalone/.next/server/app/scores.rsc +32 -24
  154. package/.next/standalone/.next/server/app/scores.segments/_full.segment.rsc +32 -24
  155. package/.next/standalone/.next/server/app/scores.segments/_tree.segment.rsc +2 -2
  156. package/.next/standalone/.next/server/app/scores.segments/scores/__PAGE__.segment.rsc +23 -18
  157. package/.next/standalone/.next/server/app/settings/page.js +1 -1
  158. package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
  159. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  160. package/.next/standalone/.next/server/app/settings.html +1 -1
  161. package/.next/standalone/.next/server/app/settings.rsc +32 -24
  162. package/.next/standalone/.next/server/app/settings.segments/_full.segment.rsc +32 -24
  163. package/.next/standalone/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
  164. package/.next/standalone/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +20 -18
  165. package/.next/standalone/.next/server/app/setup/page.js +1 -1
  166. package/.next/standalone/.next/server/app/setup/page.js.nft.json +1 -1
  167. package/.next/standalone/.next/server/app/setup/page_client-reference-manifest.js +1 -1
  168. package/.next/standalone/.next/server/app/setup.html +1 -1
  169. package/.next/standalone/.next/server/app/setup.rsc +32 -24
  170. package/.next/standalone/.next/server/app/setup.segments/_full.segment.rsc +32 -24
  171. package/.next/standalone/.next/server/app/setup.segments/_tree.segment.rsc +2 -2
  172. package/.next/standalone/.next/server/app/setup.segments/setup/__PAGE__.segment.rsc +21 -18
  173. package/.next/standalone/.next/server/app/social/page.js +1 -1
  174. package/.next/standalone/.next/server/app/social/page.js.nft.json +1 -1
  175. package/.next/standalone/.next/server/app/social/page_client-reference-manifest.js +1 -1
  176. package/.next/standalone/.next/server/app/social.html +1 -1
  177. package/.next/standalone/.next/server/app/social.rsc +32 -24
  178. package/.next/standalone/.next/server/app/social.segments/_full.segment.rsc +32 -24
  179. package/.next/standalone/.next/server/app/social.segments/_tree.segment.rsc +2 -2
  180. package/.next/standalone/.next/server/app/social.segments/social/__PAGE__.segment.rsc +23 -18
  181. package/.next/standalone/.next/server/app-paths-manifest.json +3 -0
  182. package/.next/standalone/.next/server/chunks/[root-of-the-server]__00la_y0._.js +1 -1
  183. package/.next/standalone/.next/server/chunks/[root-of-the-server]__05_3-22._.js +1 -1
  184. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__15wc9e-._.js → [root-of-the-server]__063s0x7._.js} +2 -2
  185. package/.next/standalone/.next/server/chunks/[root-of-the-server]__066rab1._.js +7 -0
  186. package/.next/standalone/.next/server/chunks/[root-of-the-server]__07t47cm._.js +1 -1
  187. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__13dx4sd._.js → [root-of-the-server]__0_4y8z7._.js} +3 -3
  188. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0cj5jqc._.js +1 -1
  189. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0e0fei3._.js +1 -1
  190. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0fooke1._.js +7 -0
  191. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ljnyho._.js +1 -1
  192. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o5-tcg._.js +1 -1
  193. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0qrnous._.js +1 -1
  194. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0t3v1a1._.js +1 -1
  195. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0t6y79e._.js +7 -0
  196. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0wmexuc._.js +1 -1
  197. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0x29muh._.js +7 -0
  198. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0xu34sz._.js +1 -1
  199. package/.next/standalone/.next/server/chunks/[root-of-the-server]__133knx1._.js +1 -1
  200. package/.next/standalone/.next/server/chunks/[root-of-the-server]__15-17hl._.js +1 -1
  201. package/.next/standalone/.next/server/chunks/[root-of-the-server]__19b7mig._.js +1 -1
  202. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1a_6x37._.js +8 -0
  203. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1an_8pa._.js +7 -0
  204. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1bbcwub._.js +1 -1
  205. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1ducpz2._.js +3 -0
  206. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1eris29._.js +1 -1
  207. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1gjo_cq._.js +1 -1
  208. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1qcm08_._.js +1 -1
  209. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1tir0vc._.js +1 -1
  210. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1w25q0m._.js +1 -1
  211. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1xhyinn._.js +3 -0
  212. package/.next/standalone/.next/server/chunks/[root-of-the-server]__20rwfdw._.js +1 -1
  213. package/.next/standalone/.next/server/chunks/_02twlca._.js +1 -1
  214. package/.next/standalone/.next/server/chunks/_072jl0y._.js +1 -1
  215. package/.next/standalone/.next/server/chunks/_0lw8_i0._.js +1 -1
  216. package/.next/standalone/.next/server/chunks/_0sqqpzb._.js +3 -0
  217. package/.next/standalone/.next/server/chunks/_1_fynia._.js +7 -7
  218. package/.next/standalone/.next/server/chunks/_1fn30_l._.js +1 -1
  219. package/.next/standalone/.next/server/chunks/_1itd1o_._.js +1 -1
  220. package/.next/standalone/.next/server/chunks/_1iwkh8t._.js +1 -1
  221. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_data_backup_route_actions_0zoj04p.js +3 -0
  222. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_data_csv_route_actions_0l6m7lg.js +3 -0
  223. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_data_restore_route_actions_0-b05bv.js +3 -0
  224. package/.next/standalone/.next/server/chunks/lib_02iz_9q._.js +4 -0
  225. package/.next/standalone/.next/server/chunks/lib_05agvk3._.js +4 -0
  226. package/.next/standalone/.next/server/chunks/lib_0v84u66._.js +4 -0
  227. package/.next/standalone/.next/server/chunks/lib_db-client_0_dch35.js +174 -0
  228. package/.next/standalone/.next/server/chunks/lib_linkedin-export_12imqxg.js +1 -1
  229. package/.next/standalone/.next/server/chunks/lib_rpc_005abye.js +3 -0
  230. package/.next/standalone/.next/server/chunks/lib_rpc_0b17r6v.js +3 -0
  231. package/.next/standalone/.next/server/chunks/lib_rpc_0c9d9ti.js +7 -0
  232. package/.next/standalone/.next/server/chunks/lib_rpc_0doq0t-.js +3 -0
  233. package/.next/standalone/.next/server/chunks/lib_rpc_0fd2rlw.js +3 -0
  234. package/.next/standalone/.next/server/chunks/lib_rpc_0is4qoc.js +3 -0
  235. package/.next/standalone/.next/server/chunks/lib_rpc_0jnfp2e.js +3 -0
  236. package/.next/standalone/.next/server/chunks/lib_rpc_0nef_n7.js +3 -0
  237. package/.next/standalone/.next/server/chunks/lib_rpc_0plrzra.js +3 -0
  238. package/.next/standalone/.next/server/chunks/lib_rpc_13a4m0c.js +3 -0
  239. package/.next/standalone/.next/server/chunks/lib_rpc_1if17c-.js +3 -0
  240. package/.next/standalone/.next/server/chunks/lib_rpc_1j-zw7v.js +3 -0
  241. package/.next/standalone/.next/server/chunks/lib_rpc_1sngt-q.js +3 -0
  242. package/.next/standalone/.next/server/chunks/lib_rpc_1v2sgme.js +3 -0
  243. package/.next/standalone/.next/server/chunks/lib_rpc_1vh-tgx.js +3 -0
  244. package/.next/standalone/.next/server/chunks/lib_rpc_1zaubz7.js +3 -0
  245. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qd8pzm._.js +3 -0
  246. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0qdeuyo._.js → [root-of-the-server]__1-012q1._.js} +2 -2
  247. package/.next/standalone/.next/server/chunks/ssr/_01o3i5y._.js +7 -0
  248. package/.next/standalone/.next/server/chunks/ssr/_02sband._.js +7 -0
  249. package/.next/standalone/.next/server/chunks/ssr/_06rgzfh._.js +3 -0
  250. package/.next/standalone/.next/server/chunks/ssr/_07zb7lu._.js +3 -0
  251. package/.next/standalone/.next/server/chunks/ssr/_0_79idq._.js +3 -0
  252. package/.next/standalone/.next/server/chunks/ssr/_0gy11ar._.js +3 -0
  253. package/.next/standalone/.next/server/chunks/ssr/_0hb-dhy._.js +3 -0
  254. package/.next/standalone/.next/server/chunks/ssr/_14nxd3q._.js +3 -0
  255. package/.next/standalone/.next/server/chunks/ssr/_189g8lg._.js +3 -0
  256. package/.next/standalone/.next/server/chunks/ssr/_1f_n00p._.js +1 -1
  257. package/.next/standalone/.next/server/chunks/ssr/_1fm1ih_._.js +2 -2
  258. package/.next/standalone/.next/server/chunks/ssr/_1k2nmbw._.js +2 -2
  259. package/.next/standalone/.next/server/chunks/ssr/_1k9qfsk._.js +3 -0
  260. package/.next/standalone/.next/server/chunks/ssr/app_141w189._.js +1 -1
  261. package/.next/standalone/.next/server/chunks/ssr/app_components_0t908t-._.js +1 -1
  262. package/.next/standalone/.next/server/chunks/ssr/app_components_0uuff77._.js +25 -2
  263. package/.next/standalone/.next/server/chunks/ssr/app_components_1j3q-h5._.js +25 -2
  264. package/.next/standalone/.next/server/chunks/ssr/app_components_CompanyScores_1g0mytz.js +1 -1
  265. package/.next/standalone/.next/server/chunks/ssr/app_import_page_1fmu6_l.js +1 -1
  266. package/.next/standalone/.next/server/chunks/ssr/app_launch_page_19t0dyd.js +1 -1
  267. package/.next/standalone/.next/server/chunks/ssr/app_page_1fazqbf.js +25 -13
  268. package/.next/standalone/.next/server/chunks/ssr/app_paths_page_1ol90m7.js +2 -2
  269. package/.next/standalone/.next/server/chunks/ssr/app_profile_page_0u3-l5y.js +1 -1
  270. package/.next/standalone/.next/server/chunks/ssr/app_queue_page_0c6znd6.js +11 -11
  271. package/.next/standalone/.next/server/chunks/ssr/app_settings_page_1f8mjj_.js +1 -1
  272. package/.next/standalone/.next/server/chunks/ssr/app_setup_page_1-282zx.js +12 -13
  273. package/.next/standalone/.next/server/chunks/ssr/app_social_page_0h7zxda.js +1 -1
  274. package/.next/standalone/.next/server/chunks/ssr/{lib_1c4ieuw._.js → lib_csv_1ttiu_h.js} +2 -2
  275. package/.next/standalone/.next/server/chunks/ssr/lib_galaxy-lab_108_lu-.js +1 -1
  276. package/.next/standalone/.next/server/chunks/ssr/lib_separation_1305zsx.js +3 -0
  277. package/.next/standalone/.next/server/edge/chunks/[root-of-the-server]__0pco7a6._.js +1 -1
  278. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  279. package/.next/standalone/.next/server/middleware-manifest.json +5 -5
  280. package/.next/standalone/.next/server/pages/404.html +1 -1
  281. package/.next/standalone/.next/server/pages/500.html +1 -1
  282. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  283. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  284. package/.next/standalone/.next/static/chunks/03-_esd2x_yk6.js +1 -0
  285. package/.next/standalone/.next/static/chunks/03-demj2iy-0p.js +44 -0
  286. package/.next/standalone/.next/static/chunks/0_1r-3csplxnj.js +1 -0
  287. package/.next/standalone/.next/static/chunks/0an_b6zi1r_qq.js +5 -0
  288. package/.next/standalone/.next/static/chunks/0e3g0sil79cus.js +21 -0
  289. package/.next/standalone/.next/static/chunks/0kscsqnvfq3-r.js +1 -0
  290. package/.next/standalone/.next/static/chunks/0p3g5tfostsep.js +7 -0
  291. package/.next/standalone/.next/static/chunks/0zd0t7e60bn4z.js +1 -0
  292. package/.next/standalone/.next/static/chunks/163b-20vwa06i.js +34 -0
  293. package/.next/standalone/.next/static/chunks/{0ws7zy0w57ufi.js → 1eyajb9ntzlrl.js} +1 -1
  294. package/.next/standalone/.next/static/chunks/1pa-2v1ajvrko.js +1 -0
  295. package/.next/standalone/.next/static/chunks/1qbjermbf68xj.js +1 -0
  296. package/.next/standalone/.next/static/chunks/1z9lb-dbcg4aa.js +1 -0
  297. package/.next/standalone/.next/static/chunks/23_1z47al92nz.js +57 -0
  298. package/.next/standalone/.next/static/chunks/260bomtr214m8.js +34 -0
  299. package/.next/standalone/.next/static/chunks/2eo9pqq9gay3r.js +34 -0
  300. package/.next/standalone/.next/static/chunks/2xk2ra4piiuod.js +34 -0
  301. package/.next/standalone/.next/static/chunks/2z1-q0_vunbql.js +2 -0
  302. package/.next/standalone/.next/static/chunks/2zf4jmz9l3li2.js +1 -0
  303. package/.next/standalone/.next/static/chunks/34g73qhayuevu.js +1 -0
  304. package/.next/standalone/.next/static/chunks/3b0-14cxqsprt.js +1 -0
  305. package/.next/standalone/.next/static/chunks/3jarus1_38s2z.js +1 -0
  306. package/.next/standalone/.next/static/chunks/3ssu341hav_sq.css +3 -0
  307. package/.next/standalone/.next/static/chunks/3v1qd3sqhqn0d.js +1 -0
  308. package/.next/standalone/.next/static/chunks/43pg2sursiypz.js +1 -0
  309. package/.next/standalone/.next/static/chunks/44yn0tcd9dfk3.js +1 -0
  310. package/.next/standalone/CHANGELOG.md +143 -0
  311. package/.next/standalone/README.md +71 -49
  312. package/.next/standalone/SECURITY.md +17 -11
  313. package/.next/standalone/app/api/data/backup/route.js +25 -0
  314. package/.next/standalone/app/api/data/csv/route.js +74 -0
  315. package/.next/standalone/app/api/data/export/route.js +1 -1
  316. package/.next/standalone/app/api/data/restore/route.js +48 -0
  317. package/.next/standalone/app/api/data/reveal/route.js +19 -6
  318. package/.next/standalone/app/api/data/route.js +15 -4
  319. package/.next/standalone/app/api/ingest/route.js +1 -1
  320. package/.next/standalone/app/api/queue/route.js +1 -1
  321. package/.next/standalone/app/api/scraper/route.js +120 -32
  322. package/.next/standalone/app/api/social/crm/route.js +2 -1
  323. package/.next/standalone/app/components/AppHeader.js +20 -16
  324. package/.next/standalone/app/components/AppTabs.js +8 -8
  325. package/.next/standalone/app/components/AutoScanButton.js +2 -2
  326. package/.next/standalone/app/components/Avatar.js +1 -1
  327. package/.next/standalone/app/components/ChainView.js +184 -112
  328. package/.next/standalone/app/components/CirclePanel.js +16 -16
  329. package/.next/standalone/app/components/ClusterSpinner.js +64 -0
  330. package/.next/standalone/app/components/CompanyScores.js +20 -20
  331. package/.next/standalone/app/components/EmptyState.js +39 -18
  332. package/.next/standalone/app/components/FieldStep.js +15 -13
  333. package/.next/standalone/app/components/FilterPanel.js +17 -17
  334. package/.next/standalone/app/components/ForceGraph.js +49 -14
  335. package/.next/standalone/app/components/GalaxyLab.js +33 -33
  336. package/.next/standalone/app/components/GridView.js +18 -18
  337. package/.next/standalone/app/components/LegacyScoresCard.js +10 -11
  338. package/.next/standalone/app/components/LinkedInLimits.js +24 -19
  339. package/.next/standalone/app/components/LiquidGlass.js +99 -0
  340. package/.next/standalone/app/components/ListView.js +20 -20
  341. package/.next/standalone/app/components/MapControls.js +5 -5
  342. package/.next/standalone/app/components/MappingProgress.js +16 -16
  343. package/.next/standalone/app/components/NoteDetail.js +13 -13
  344. package/.next/standalone/app/components/OnboardingGate.js +4 -4
  345. package/.next/standalone/app/components/OutlinkQuest.js +25 -25
  346. package/.next/standalone/app/components/PathsAnalyzer.js +37 -36
  347. package/.next/standalone/app/components/PeopleMap.js +21 -21
  348. package/.next/standalone/app/components/RingsView.js +11 -11
  349. package/.next/standalone/app/components/ScanRadar.js +84 -39
  350. package/.next/standalone/app/components/ScanStatusBar.js +22 -18
  351. package/.next/standalone/app/components/ScanTrail.js +8 -5
  352. package/.next/standalone/app/components/SeparationView.js +168 -104
  353. package/.next/standalone/app/components/Sidebar.js +161 -161
  354. package/.next/standalone/app/components/StaleServerBanner.js +4 -4
  355. package/.next/standalone/app/components/TheirCircle.js +26 -26
  356. package/.next/standalone/app/components/ThemeDefs.js +42 -0
  357. package/.next/standalone/app/components/ThemeLoader.js +20 -1
  358. package/.next/standalone/app/components/UpdatePanel.js +22 -22
  359. package/.next/standalone/app/components/UserProvider.js +22 -15
  360. package/.next/standalone/app/components/settings/AppearanceSection.js +47 -24
  361. package/.next/standalone/app/components/settings/DataSection.js +276 -109
  362. package/.next/standalone/app/components/settings/NetworkHealthSection.js +13 -13
  363. package/.next/standalone/app/components/settings/SectorPicker.js +12 -12
  364. package/.next/standalone/app/components/settings/SectorSection.js +13 -14
  365. package/.next/standalone/app/components/settings/TierSection.js +9 -9
  366. package/.next/standalone/app/components/settings/TitleSection.js +11 -11
  367. package/.next/standalone/app/components/settings/UsageSection.js +313 -0
  368. package/.next/standalone/app/components/ui.js +8 -8
  369. package/.next/standalone/app/globals.css +159 -2
  370. package/.next/standalone/app/import/page.js +94 -38
  371. package/.next/standalone/app/launch/page.js +5 -5
  372. package/.next/standalone/app/layout.js +6 -2
  373. package/.next/standalone/app/page.js +53 -37
  374. package/.next/standalone/app/paths/page.js +63 -63
  375. package/.next/standalone/app/profile/page.js +58 -58
  376. package/.next/standalone/app/queue/page.js +54 -54
  377. package/.next/standalone/app/scores/page.js +2 -2
  378. package/.next/standalone/app/settings/page.js +16 -13
  379. package/.next/standalone/app/setup/page.js +221 -125
  380. package/.next/standalone/app/social/Crm.js +63 -62
  381. package/.next/standalone/app/social/SocialHub.js +22 -22
  382. package/.next/standalone/app/social/Thread.js +7 -7
  383. package/.next/standalone/app/social/page.js +2 -2
  384. package/.next/standalone/lib/backups.js +458 -0
  385. package/.next/standalone/lib/chain-layout.js +32 -0
  386. package/.next/standalone/lib/csv-store.js +131 -0
  387. package/.next/standalone/lib/csv.js +137 -39
  388. package/.next/standalone/lib/data-folder.js +19 -3
  389. package/.next/standalone/lib/data-import.js +5 -2
  390. package/.next/standalone/lib/db-client.js +78 -20
  391. package/.next/standalone/lib/demo.js +5 -4
  392. package/.next/standalone/lib/galaxy-export.js +9 -2
  393. package/.next/standalone/lib/galaxy-lab.js +19 -5
  394. package/.next/standalone/lib/galaxy-layouts.js +43 -0
  395. package/.next/standalone/lib/gate.js +10 -4
  396. package/.next/standalone/lib/ingest.js +1 -1
  397. package/.next/standalone/lib/linkedin-limits.js +212 -11
  398. package/.next/standalone/lib/liquid-glass.js +59 -0
  399. package/.next/standalone/lib/notifications.js +13 -0
  400. package/.next/standalone/lib/scan-pace.js +11 -0
  401. package/.next/standalone/lib/scan-progress.js +20 -0
  402. package/.next/standalone/lib/scan-risk.js +44 -0
  403. package/.next/standalone/lib/scanner-setup.js +97 -15
  404. package/.next/standalone/lib/scraper-client.js +17 -3
  405. package/.next/standalone/lib/search-risk.js +7 -3
  406. package/.next/standalone/lib/settings-client.js +5 -3
  407. package/.next/standalone/lib/settings.js +10 -0
  408. package/.next/standalone/lib/social-store.js +3 -2
  409. package/.next/standalone/lib/synced-setting.js +46 -0
  410. package/.next/standalone/lib/theme-store.js +42 -10
  411. package/.next/standalone/lib/themes.js +111 -21
  412. package/.next/standalone/lib/usage.js +195 -0
  413. package/.next/standalone/package-lock.json +2 -2
  414. package/.next/standalone/package.json +1 -1
  415. package/.next/standalone/scripts/scrape.py +26 -2
  416. package/.next/static/chunks/03-_esd2x_yk6.js +1 -0
  417. package/.next/static/chunks/03-demj2iy-0p.js +44 -0
  418. package/.next/static/chunks/0_1r-3csplxnj.js +1 -0
  419. package/.next/static/chunks/0an_b6zi1r_qq.js +5 -0
  420. package/.next/static/chunks/0e3g0sil79cus.js +21 -0
  421. package/.next/static/chunks/0kscsqnvfq3-r.js +1 -0
  422. package/.next/static/chunks/0p3g5tfostsep.js +7 -0
  423. package/.next/static/chunks/0zd0t7e60bn4z.js +1 -0
  424. package/.next/static/chunks/163b-20vwa06i.js +34 -0
  425. package/.next/static/chunks/{0ws7zy0w57ufi.js → 1eyajb9ntzlrl.js} +1 -1
  426. package/.next/static/chunks/1pa-2v1ajvrko.js +1 -0
  427. package/.next/static/chunks/1qbjermbf68xj.js +1 -0
  428. package/.next/static/chunks/1z9lb-dbcg4aa.js +1 -0
  429. package/.next/static/chunks/23_1z47al92nz.js +57 -0
  430. package/.next/static/chunks/260bomtr214m8.js +34 -0
  431. package/.next/static/chunks/2eo9pqq9gay3r.js +34 -0
  432. package/.next/static/chunks/2xk2ra4piiuod.js +34 -0
  433. package/.next/static/chunks/2z1-q0_vunbql.js +2 -0
  434. package/.next/static/chunks/2zf4jmz9l3li2.js +1 -0
  435. package/.next/static/chunks/34g73qhayuevu.js +1 -0
  436. package/.next/static/chunks/3b0-14cxqsprt.js +1 -0
  437. package/.next/static/chunks/3jarus1_38s2z.js +1 -0
  438. package/.next/static/chunks/3ssu341hav_sq.css +3 -0
  439. package/.next/static/chunks/3v1qd3sqhqn0d.js +1 -0
  440. package/.next/static/chunks/43pg2sursiypz.js +1 -0
  441. package/.next/static/chunks/44yn0tcd9dfk3.js +1 -0
  442. package/CHANGELOG.md +143 -0
  443. package/README.md +71 -49
  444. package/SECURITY.md +17 -11
  445. package/lib/backups.js +458 -0
  446. package/lib/chain-layout.js +32 -0
  447. package/lib/csv-store.js +131 -0
  448. package/lib/csv.js +137 -39
  449. package/lib/data-folder.js +19 -3
  450. package/lib/data-import.js +5 -2
  451. package/lib/db-client.js +78 -20
  452. package/lib/demo.js +5 -4
  453. package/lib/galaxy-export.js +9 -2
  454. package/lib/galaxy-lab.js +19 -5
  455. package/lib/galaxy-layouts.js +43 -0
  456. package/lib/gate.js +10 -4
  457. package/lib/ingest.js +1 -1
  458. package/lib/linkedin-limits.js +212 -11
  459. package/lib/liquid-glass.js +59 -0
  460. package/lib/notifications.js +13 -0
  461. package/lib/scan-pace.js +11 -0
  462. package/lib/scan-progress.js +20 -0
  463. package/lib/scan-risk.js +44 -0
  464. package/lib/scanner-setup.js +97 -15
  465. package/lib/scraper-client.js +17 -3
  466. package/lib/search-risk.js +7 -3
  467. package/lib/settings-client.js +5 -3
  468. package/lib/settings.js +10 -0
  469. package/lib/social-store.js +3 -2
  470. package/lib/synced-setting.js +46 -0
  471. package/lib/theme-store.js +42 -10
  472. package/lib/themes.js +111 -21
  473. package/lib/usage.js +195 -0
  474. package/package.json +1 -1
  475. package/scripts/scrape.py +26 -2
  476. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0-rnla2._.js +0 -3
  477. package/.next/standalone/.next/server/chunks/[root-of-the-server]__14ou7j5._.js +0 -3
  478. package/.next/standalone/.next/server/chunks/[root-of-the-server]__16iu0hv._.js +0 -3
  479. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1kbl21f._.js +0 -3
  480. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1rphsdk._.js +0 -3
  481. package/.next/standalone/.next/server/chunks/lib_0851sk0._.js +0 -8
  482. package/.next/standalone/.next/server/chunks/lib_1q7p2ro._.js +0 -8
  483. package/.next/standalone/.next/server/chunks/lib_1r6l86l._.js +0 -8
  484. package/.next/standalone/.next/server/chunks/lib_db-client_15le7cw.js +0 -174
  485. package/.next/standalone/.next/server/chunks/lib_rpc_04s8mzr.js +0 -3
  486. package/.next/standalone/.next/server/chunks/lib_rpc_053z7as.js +0 -3
  487. package/.next/standalone/.next/server/chunks/lib_rpc_0b_-2te.js +0 -3
  488. package/.next/standalone/.next/server/chunks/lib_rpc_0dhbxdm.js +0 -3
  489. package/.next/standalone/.next/server/chunks/lib_rpc_0dxlk31.js +0 -3
  490. package/.next/standalone/.next/server/chunks/lib_rpc_0f8b-qc.js +0 -3
  491. package/.next/standalone/.next/server/chunks/lib_rpc_0pzie7_.js +0 -3
  492. package/.next/standalone/.next/server/chunks/lib_rpc_0r76fq_.js +0 -3
  493. package/.next/standalone/.next/server/chunks/lib_rpc_0ut7pjp.js +0 -3
  494. package/.next/standalone/.next/server/chunks/lib_rpc_15zyqaz.js +0 -3
  495. package/.next/standalone/.next/server/chunks/lib_rpc_18zpjtq.js +0 -3
  496. package/.next/standalone/.next/server/chunks/lib_rpc_1a8xkiz.js +0 -3
  497. package/.next/standalone/.next/server/chunks/lib_rpc_1e_55xo.js +0 -3
  498. package/.next/standalone/.next/server/chunks/lib_rpc_1oxfd1_.js +0 -3
  499. package/.next/standalone/.next/server/chunks/lib_rpc_1s0lod0.js +0 -3
  500. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__08oxiqh._.js +0 -3
  501. package/.next/standalone/.next/server/chunks/ssr/_03l7vge._.js +0 -3
  502. package/.next/standalone/.next/server/chunks/ssr/_08g31gm._.js +0 -3
  503. package/.next/standalone/.next/server/chunks/ssr/_0gk_ofx._.js +0 -3
  504. package/.next/standalone/.next/server/chunks/ssr/_0nwsf93._.js +0 -3
  505. package/.next/standalone/.next/server/chunks/ssr/_0vho1lb._.js +0 -3
  506. package/.next/standalone/.next/server/chunks/ssr/_1-658fq._.js +0 -3
  507. package/.next/standalone/.next/server/chunks/ssr/_1bc46kz._.js +0 -3
  508. package/.next/standalone/.next/server/chunks/ssr/_2105jz8._.js +0 -3
  509. package/.next/standalone/.next/server/chunks/ssr/app_components_settings_SectorPicker_1c-29qw.js +0 -3
  510. package/.next/standalone/.next/static/chunks/02pq76u7y4v9-.js +0 -22
  511. package/.next/standalone/.next/static/chunks/0cmq0exd4d0h9.js +0 -1
  512. package/.next/standalone/.next/static/chunks/0i02yxppzds1o.js +0 -1
  513. package/.next/standalone/.next/static/chunks/0m_p4k-q2qh--.js +0 -1
  514. package/.next/standalone/.next/static/chunks/0oyslj62jkubd.js +0 -1
  515. package/.next/standalone/.next/static/chunks/0vo-l8hxneba6.css +0 -3
  516. package/.next/standalone/.next/static/chunks/0yh8z2tbrc5i_.js +0 -1
  517. package/.next/standalone/.next/static/chunks/17-rhp8sg4m1b.js +0 -44
  518. package/.next/standalone/.next/static/chunks/172e10mi-tpo_.js +0 -34
  519. package/.next/standalone/.next/static/chunks/1ei5vbe2uw6fl.js +0 -1
  520. package/.next/standalone/.next/static/chunks/1f7_pl_wq7lh3.js +0 -11
  521. package/.next/standalone/.next/static/chunks/1jzbe7zdx9vbj.js +0 -2
  522. package/.next/standalone/.next/static/chunks/1m3017gp790pw.js +0 -45
  523. package/.next/standalone/.next/static/chunks/1t20e8u0st7ep.js +0 -1
  524. package/.next/standalone/.next/static/chunks/2-ch9rm27eril.js +0 -11
  525. package/.next/standalone/.next/static/chunks/2ldv-v3s9yaif.js +0 -1
  526. package/.next/standalone/.next/static/chunks/3bp284gjf7dyq.js +0 -1
  527. package/.next/standalone/.next/static/chunks/3k1f6clbn3gj3.js +0 -7
  528. package/.next/standalone/.next/static/chunks/3l4t8je6iguzc.js +0 -1
  529. package/.next/standalone/.next/static/chunks/3tplzuc9jk-tl.js +0 -1
  530. package/.next/standalone/.next/static/chunks/42m0bqr8pbovz.js +0 -11
  531. package/.next/static/chunks/02pq76u7y4v9-.js +0 -22
  532. package/.next/static/chunks/0cmq0exd4d0h9.js +0 -1
  533. package/.next/static/chunks/0i02yxppzds1o.js +0 -1
  534. package/.next/static/chunks/0m_p4k-q2qh--.js +0 -1
  535. package/.next/static/chunks/0oyslj62jkubd.js +0 -1
  536. package/.next/static/chunks/0vo-l8hxneba6.css +0 -3
  537. package/.next/static/chunks/0yh8z2tbrc5i_.js +0 -1
  538. package/.next/static/chunks/17-rhp8sg4m1b.js +0 -44
  539. package/.next/static/chunks/172e10mi-tpo_.js +0 -34
  540. package/.next/static/chunks/1ei5vbe2uw6fl.js +0 -1
  541. package/.next/static/chunks/1f7_pl_wq7lh3.js +0 -11
  542. package/.next/static/chunks/1jzbe7zdx9vbj.js +0 -2
  543. package/.next/static/chunks/1m3017gp790pw.js +0 -45
  544. package/.next/static/chunks/1t20e8u0st7ep.js +0 -1
  545. package/.next/static/chunks/2-ch9rm27eril.js +0 -11
  546. package/.next/static/chunks/2ldv-v3s9yaif.js +0 -1
  547. package/.next/static/chunks/3bp284gjf7dyq.js +0 -1
  548. package/.next/static/chunks/3k1f6clbn3gj3.js +0 -7
  549. package/.next/static/chunks/3l4t8je6iguzc.js +0 -1
  550. package/.next/static/chunks/3tplzuc9jk-tl.js +0 -1
  551. package/.next/static/chunks/42m0bqr8pbovz.js +0 -11
  552. /package/.next/standalone/.next/static/{dQUvvVSXqbkEFC3-CNcwT → ZVpLBK-2vpllv2HxOFs2d}/_buildManifest.js +0 -0
  553. /package/.next/standalone/.next/static/{dQUvvVSXqbkEFC3-CNcwT → ZVpLBK-2vpllv2HxOFs2d}/_clientMiddlewareManifest.js +0 -0
  554. /package/.next/standalone/.next/static/{dQUvvVSXqbkEFC3-CNcwT → ZVpLBK-2vpllv2HxOFs2d}/_ssgManifest.js +0 -0
  555. /package/.next/static/{dQUvvVSXqbkEFC3-CNcwT → ZVpLBK-2vpllv2HxOFs2d}/_buildManifest.js +0 -0
  556. /package/.next/static/{dQUvvVSXqbkEFC3-CNcwT → ZVpLBK-2vpllv2HxOFs2d}/_clientMiddlewareManifest.js +0 -0
  557. /package/.next/static/{dQUvvVSXqbkEFC3-CNcwT → ZVpLBK-2vpllv2HxOFs2d}/_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',
@@ -133,13 +135,32 @@ function SetupInner() {
133
135
  poll();
134
136
  }
135
137
 
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.
138
+ // The question is answered: a line takes its place, and the page goes back
139
+ // to the top, since it may have been answered from far down the picker.
138
140
  function answered(sectors) {
139
141
  setField({ sectors });
140
142
  window.scrollTo(0, 0);
141
143
  }
142
144
 
145
+ // "I understand": when, kept with your settings so it travels with a copy.
146
+ async function acceptRisk() {
147
+ setError(null);
148
+ setBusy(true);
149
+ try {
150
+ const r = await fetch('/api/settings', {
151
+ method: 'POST',
152
+ headers: { 'Content-Type': 'application/json' },
153
+ body: JSON.stringify({ settings: { scanRiskAccepted: new Date().toISOString() } }),
154
+ });
155
+ if (!r.ok) setError((await r.json().catch(() => null))?.error || 'Could not save that. Try again.');
156
+ } catch (e) {
157
+ setError(e.message);
158
+ } finally {
159
+ setBusy(false);
160
+ poll();
161
+ }
162
+ }
163
+
143
164
  async function run(action, extra = {}) {
144
165
  setError(null);
145
166
  setBusy(true);
@@ -168,9 +189,13 @@ function SetupInner() {
168
189
  // and a line of its own when the Python inside the app didn't work.
169
190
  const step1 = setupStep(s);
170
191
  const needsDeps = s && !c.dependencies;
171
- const needsChrome = s && !c.chrome;
192
+ // Step 1 says so and offers the download (lib/scanner-setup.js); nothing that opens LinkedIn can start.
193
+ const needsChrome = s && c.chrome === false;
172
194
  const notFound = s && !c.scriptsFound;
173
- const canScrape = s?.ready && !running;
195
+ // The one-time "I understand" before anything opens LinkedIn (lib/scan-risk.js);
196
+ // the server refuses without it too. Unknown (an older server) counts as given.
197
+ const riskOk = c.riskAccepted !== false;
198
+ const canScrape = s?.ready && !running && riskOk;
174
199
  // Anything that searches LinkedIn waits out a cooldown (TRAPS §35).
175
200
  const li = s?.linkedin;
176
201
  const cooling = Boolean(li?.cooldown);
@@ -183,9 +208,12 @@ function SetupInner() {
183
208
  const current = !s || !step1.done ? 1 : !c.signedIn ? 2 : mapped === 0 ? 3 : 4;
184
209
  // Each step: done, the one you're on (now), or still to come (next).
185
210
  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).
211
+ // Your field, asked once when your connections are in, before who they know
212
+ // (lib/scanner-setup.js askForField); left out while that isn't known (null).
188
213
  const askField = IS_DEMO || field ? false : askForField(s, settings);
214
+ // Step 4, honestly: the first circle shows in minutes, the rest takes days.
215
+ const pace = li?.limits?.pace;
216
+ const firstCircle = durationText(firstCircleSeconds(pace));
189
217
  // A run that ended badly, and the line that says why — the last thing it
190
218
  // printed before stopping. Shown as a box, not left for someone to find in the log.
191
219
  const failed = s && !running && s.exitCode != null && s.exitCode !== 0;
@@ -198,7 +226,7 @@ function SetupInner() {
198
226
 
199
227
  return (
200
228
  <div style={{
201
- minHeight: '100vh', background: BG, color: '#fff',
229
+ minHeight: '100vh', background: BG, color: 'var(--sd-fg-1, #fff)',
202
230
  fontFamily: 'var(--sd-font)',
203
231
  }}>
204
232
  {/* The same header as every page, Scan lit (Blake, 2026-10-02: continuity) */}
@@ -209,32 +237,37 @@ function SetupInner() {
209
237
  {/* What the scanner is, in one breath, and what it never does */}
210
238
  <div style={{
211
239
  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%)',
240
+ 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
241
  border: '1px solid rgba(0,255,136,0.22)',
214
242
  }}>
215
- <div style={{ fontSize: 11, fontWeight: 800, letterSpacing: 1.6, color: '#00ff88' }}>YOUR SCANNER</div>
243
+ <div style={{ fontSize: 11, fontWeight: 800, letterSpacing: 1.6, color: 'var(--sd-green, #00ff88)' }}>YOUR SCANNER</div>
244
+ {/* Steps 1 to 3 draw the galaxy in minutes; step 4 is days of small rounds,
245
+ and saying "four steps" made it sound like one sitting. */}
216
246
  <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.'}
247
+ {mapped > 0 ? 'Your network is mapped. Send the scanner further.' : <>
248
+ Your galaxy in three steps.
249
+ <span style={{ display: 'block', color: 'var(--sd-fg-2, #aab7c4)', fontSize: 20, fontWeight: 700, marginTop: 4 }}>
250
+ Who they know fills in over days.
251
+ </span>
252
+ </>}
218
253
  </h1>
219
- <div style={{ fontSize: 14.5, color: '#aab7c4', lineHeight: 1.6, maxWidth: 560 }}>
254
+ <div style={{ fontSize: 14.5, color: 'var(--sd-fg-2, #aab7c4)', lineHeight: 1.6, maxWidth: 560 }}>
220
255
  It works in your own Chrome on this Mac, slowly and in the open, and keeps everything here.
221
256
  You launch it; it does the reading; you watch it go.
222
257
  </div>
223
258
  <div style={{ display: 'flex', gap: '8px 18px', flexWrap: 'wrap', marginTop: 16 }}>
224
259
  {['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
+ <span key={t} style={{ fontSize: 12.5, color: 'var(--sd-fg-1, #cfe8dc)', display: 'flex', alignItems: 'center', gap: 6 }}>
261
+ <span style={{ color: 'var(--sd-green, #00ff88)', fontWeight: 900 }}>✓</span>{t}
227
262
  </span>
228
263
  ))}
229
264
  </div>
230
265
  </div>
231
266
 
232
267
  {/* 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} />}
268
+ {!s && <p style={{ color: 'var(--sd-fg-4, #778)', fontSize: 13 }}>Checking your setup…</p>}
236
269
 
237
- {askField === false && <>
270
+ {s && <>
238
271
  {/* By id: the server finds them by their profile, since two connections can share a name. */}
239
272
  {pick?.person.id === pickId && (
240
273
  <ScanOne
@@ -252,7 +285,7 @@ function SetupInner() {
252
285
  {net.second > 0 && <>, plus {net.second.toLocaleString()} people in their circles</>}
253
286
  {net.third > 0 && <> and {net.third.toLocaleString()} from company scans</>}
254
287
  .{' '}
255
- <span style={{ color: '#9aa' }}>Your galaxy is ready.</span>
288
+ <span style={{ color: 'var(--sd-fg-3, #9aa)' }}>Your galaxy is ready.</span>
256
289
  </div>
257
290
  <Link href="/" style={{
258
291
  padding: '9px 18px', borderRadius: 7, fontSize: 13.5, fontWeight: 700,
@@ -263,6 +296,11 @@ function SetupInner() {
263
296
  </Box>
264
297
  )}
265
298
 
299
+ {/* Your field, once, now that there are people to rank with it (it used to
300
+ stand in front of step 1); then a line saying what it did. */}
301
+ {askField && <FieldStep onDone={answered} />}
302
+ {field && <FieldAnswer sectors={field.sectors} />}
303
+
266
304
  {/* Photos an older version kept as links to LinkedIn. The app shows
267
305
  only photos saved here (lib/photos.js), so until then those people
268
306
  show initials. Every scan saves them at its end; this is the way
@@ -272,14 +310,14 @@ function SetupInner() {
272
310
  <div style={{ display: 'flex', alignItems: 'center', gap: 14, flexWrap: 'wrap' }}>
273
311
  <div style={{ flex: 1, minWidth: 200 }}>
274
312
  <b>{s.photosWaiting.toLocaleString()} {s.photosWaiting === 1 ? 'photo isn’t' : 'photos aren’t'} saved on this computer yet.</b>{' '}
275
- <span style={{ color: '#9aa' }}>
313
+ <span style={{ color: 'var(--sd-fg-3, #9aa)' }}>
276
314
  An older version kept them as links to LinkedIn. The app doesn’t load
277
315
  photos from LinkedIn while you browse, so those people show initials until
278
316
  the photos are saved here: now, or at the end of your next scan. An expired
279
317
  link can’t be saved; that person’s photo comes back when they’re next scanned.
280
318
  </span>
281
319
  {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>
320
+ <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
321
  )}
284
322
  </div>
285
323
  <Btn onClick={() => run('photos')} disabled={busy || !c.dependencies}>Save photos</Btn>
@@ -292,31 +330,20 @@ function SetupInner() {
292
330
  <b>The last run stopped before it finished.</b>
293
331
  {failReason && (
294
332
  <div style={{
295
- marginTop: 6, color: '#e8c4c4', whiteSpace: 'pre-wrap',
333
+ marginTop: 6, color: 'var(--sd-fg-2, #e8c4c4)', whiteSpace: 'pre-wrap',
296
334
  fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace', fontSize: 12.5,
297
335
  }}>{failReason}</div>
298
336
  )}
299
- <div style={{ color: '#9aa', marginTop: 6 }}>The full log is below.</div>
337
+ <div style={{ color: 'var(--sd-fg-3, #9aa)', marginTop: 6 }}>The full log is below.</div>
300
338
  </Box>
301
339
  )}
302
340
 
303
341
  {notFound && (
304
342
  <Box tone="bad">
305
343
  <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.
344
+ <span style={{ color: 'var(--sd-fg-3, #9aa)' }}>
345
+ This copy of Six Degrees is missing part of its scanner. Download it again from
346
+ sixdegreesapp.com and put the new copy in place of this one.
320
347
  </span>
321
348
  </Box>
322
349
  )}
@@ -333,22 +360,37 @@ function SetupInner() {
333
360
  displayed with the line following"): every step shown at once, down a line that turns
334
361
  green as each is done, the one you're on lit, one button each. Everything else waits
335
362
  in Fine-tune. ---- */}
363
+ {s && !riskOk && <RiskCard onAccept={acceptRisk} busy={busy} />}
364
+
336
365
  <div role="list" aria-label="Scanning, step by step" style={{ margin: '4px 0 8px' }}>
337
366
  <style>{JOURNEY_CSS}</style>
338
367
  <StepRow n={1} label="Get ready" state={stateOf(1, step1.done)}>
339
368
  <Mission title="Get your scanner ready" time="A minute or two, once" done={step1.done} body={s ? step1.text : 'Checking…'}
340
369
  launch={s && step1.button && (
341
370
  <Launch onClick={() => run(step1.button.action)} disabled={busy || running}>{step1.button.label}</Launch>
371
+ )}
372
+ // No Chrome: the way to get it. The step turns done by itself once
373
+ // it's installed, since the page keeps asking.
374
+ more={s && step1.chrome && (
375
+ <Launch href={step1.chrome.href} quiet={Boolean(step1.button)}>{step1.chrome.label}</Launch>
342
376
  )} />
343
377
  </StepRow>
344
378
  <StepRow n={2} label="Sign in" state={stateOf(2, !!c.signedIn)}>
345
379
  <Mission title="Sign in to LinkedIn, once" time="You do this part" done={!!c.signedIn}
346
380
  body={c.signedIn
347
381
  ? '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.)'}
382
+ : <>
383
+ A Chrome window opens. Sign in with your email and password there: the scanner never sees them.
384
+ {/* TRAPS §12: Google and Apple block their sign-in in automated browsers, so the fix is a password. */}
385
+ <span style={{ display: 'block', marginTop: 6 }}>
386
+ Sign in to LinkedIn with Google or Apple? That can&rsquo;t work in this window, so set a LinkedIn
387
+ password first: on LinkedIn&rsquo;s sign-in page, <b>Forgot password</b> emails you a link to make one.
388
+ </span>
389
+ </>}
349
390
  launch={c.dependencies && (
350
391
  // 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}>
392
+ // Never without Chrome: the server would refuse it (lib/scanner-setup.js CHROME_REFUSAL).
393
+ <Launch onClick={() => run('login')} disabled={busy || running || current < 2 || !riskOk || needsChrome} quiet={!!c.signedIn}>
352
394
  {running && s.action === 'login' ? 'Waiting for you…' : c.signedIn ? 'Open LinkedIn again' : 'Open LinkedIn'}
353
395
  </Launch>
354
396
  )} />
@@ -364,14 +406,22 @@ function SetupInner() {
364
406
  </Launch>
365
407
  )}
366
408
  more={mapped > 0 && (
367
- <Btn onClick={() => run('refresh')} disabled={!canSearch || current < 3} primary>
368
- {running && s.action === 'refresh' ? 'Checking…' : '↻ Check for new'}
409
+ <Btn onClick={() => run('refresh')} disabled={!canSearch || current < 3} primary cluster active={Boolean(running && s.action === 'refresh')}>
410
+ <ClusterSpinner size={13} live={Boolean(running && s.action === 'refresh')} />
411
+ {running && s.action === 'refresh' ? 'Checking…' : 'Check for new'}
369
412
  </Btn>
370
413
  )} />
371
414
  </StepRow>
372
415
  <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.</>}>
416
+ {/* Honest about time (the 1.0 first-run list): a circle shows in minutes, a
417
+ network in days, because every page is a search and the budget caps a day's. */}
418
+ <Mission title="Map who they know" time={`First circle in ${firstCircle}`}
419
+ body={<>
420
+ It opens your connections one at a time and reads who <i>they</i> know: that fills Degrees, Separation
421
+ and Outlink. The first circle shows up in {firstCircle}. The rest fills in over days, a round at a time:
422
+ every page is a LinkedIn search, and {li?.limits?.daily ? <>your budget allows {li.limits.daily} a day</>
423
+ : <>a day&rsquo;s searches are best kept few</>}. Every round picks up where the last one stopped.
424
+ </>}>
375
425
  <CooldownBanner
376
426
  cooldown={li?.cooldown}
377
427
  disabled={busy}
@@ -385,21 +435,21 @@ function SetupInner() {
385
435
  scanning={Boolean(running && s?.action?.startsWith('auto-bridge'))}
386
436
  disabled={!canSearch || (order === 'score' && !tiers.length)}
387
437
  label={running && s?.action === 'auto-bridge' ? 'Mapping…' : 'Map 2nd degree'}
388
- sublabel={batch ? `${batch} people` : 'everyone'}
438
+ sublabel={running ? (batch ? `${batch} people` : 'everyone') : `first circle in ${firstCircle}`}
389
439
  onScan={() => run('auto-bridge', { maxBridges: batch, tiers: order === 'score' ? tiers : [], order, maxPages: pages, deeper: finish, experimental })}
390
440
  onPace={busy ? undefined : (pace) => run('set-limits', { ...(li?.limits || {}), pace })}
391
441
  />
392
442
  <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' }}>
443
+ <label style={{ display: 'flex', gap: 10, alignItems: 'center', fontSize: 13, color: 'var(--sd-fg-2, #cfd8d8)' }}>
394
444
  This round
395
445
  <select value={batch} onChange={(e) => setBatch(Number(e.target.value))} disabled={running} style={selectStyle}>
396
446
  <option value={5}>5 people</option>
397
447
  <option value={10}>10 people</option>
398
448
  <option value={25}>25 people</option>
399
- <option value={0}>everyone — not advised</option>
449
+ <option value={0}>everyone (not advised)</option>
400
450
  </select>
401
451
  </label>
402
- <label style={{ display: 'flex', gap: 10, alignItems: 'center', fontSize: 13, color: '#cfd8d8' }}>
452
+ <label style={{ display: 'flex', gap: 10, alignItems: 'center', fontSize: 13, color: 'var(--sd-fg-2, #cfd8d8)' }}>
403
453
  Start with
404
454
  <select value={order} onChange={(e) => setOrder(e.target.value)} disabled={running} style={selectStyle}>
405
455
  <option value="newest">Newest connections</option>
@@ -407,7 +457,7 @@ function SetupInner() {
407
457
  </select>
408
458
  </label>
409
459
  {order === 'score' && <div style={{ display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' }}>
410
- <span style={{ fontSize: 12, color: '#8b9a9a' }}>Work through</span>
460
+ <span style={{ fontSize: 12, color: 'var(--sd-fg-3, #8b9a9a)' }}>Work through</span>
411
461
  {['S', 'A', 'B', 'C', 'D'].map((t) => {
412
462
  const on = tiers.includes(t);
413
463
  return (
@@ -418,18 +468,18 @@ function SetupInner() {
418
468
  style={{
419
469
  width: 30, height: 28, borderRadius: 7, fontSize: 12, fontWeight: 700,
420
470
  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',
471
+ background: on ? 'rgba(52,152,219,0.22)' : 'rgba(var(--sd-ink, 255, 255, 255), 0.05)',
472
+ color: on ? 'var(--sd-fg-1, #cfe6f7)' : 'var(--sd-fg-4, #667)',
423
473
  }}
424
474
  >{t}</button>
425
475
  );
426
476
  })}
427
- <span style={{ fontSize: 11.5, color: '#667' }}>
477
+ <span style={{ fontSize: 11.5, color: 'var(--sd-fg-4, #667)' }}>
428
478
  {tiers.length ? '' : 'pick at least one'}
429
479
  </span>
430
480
  </div>}
431
481
  {order === 'newest' && (
432
- <div style={{ fontSize: 12, color: '#8b9a9a', lineHeight: 1.6 }}>
482
+ <div style={{ fontSize: 12, color: 'var(--sd-fg-3, #8b9a9a)', lineHeight: 1.6 }}>
433
483
  Goes by the date you connected, newest first, across every tier. Run
434
484
  {' '}<b>Check for new</b> first so your latest connections are in the list.
435
485
  </div>
@@ -437,6 +487,18 @@ function SetupInner() {
437
487
  <WhySlow />
438
488
  </div>
439
489
  </div>
490
+ {/* The circle being read, on the map: Bridge Chains looks again every 20
491
+ seconds while it fills in (app/page.js NetworkRefresh). */}
492
+ {running && s?.mapping?.id && (
493
+ <div style={{ marginTop: 14, fontSize: 13.5 }}>
494
+ <Link href={`/?chain=${encodeURIComponent(s.mapping.id)}`} style={{ color: 'var(--sd-green, #00ff88)', fontWeight: 700 }}>
495
+ Watch it fill in →
496
+ </Link>
497
+ <span style={{ color: 'var(--sd-fg-3, #8b9a9a)', marginLeft: 8 }}>
498
+ {s.mapping.name ? `${s.mapping.name}’s circle, ` : ''}saved every 10 pages.
499
+ </span>
500
+ </div>
501
+ )}
440
502
  </Mission>
441
503
  </StepRow>
442
504
  </div>
@@ -450,10 +512,10 @@ function SetupInner() {
450
512
  }}>
451
513
  <Spinner />
452
514
  <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>
515
+ <div style={{ fontSize: 11, fontWeight: 800, letterSpacing: 1.2, color: 'var(--sd-green, #00ff88)', marginBottom: 2 }}>YOUR SCANNER IS WORKING</div>
454
516
  <b>{ACTION_LABELS[s.action] || 'Working'}</b>
455
517
  {s.progress && <Progress p={s.progress} action={s.action} />}
456
- <div style={{ color: '#8b9a9a', fontSize: 12.5, marginTop: 2 }}>
518
+ <div style={{ color: 'var(--sd-fg-3, #8b9a9a)', fontSize: 12.5, marginTop: 2 }}>
457
519
  Stopping closes the browser cleanly and keeps everything found so far.
458
520
  </div>
459
521
  </div>
@@ -462,14 +524,14 @@ function SetupInner() {
462
524
  )}
463
525
 
464
526
  {/* 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' }}>
527
+ <details style={{ margin: '18px 0 4px', borderRadius: 10, border: LINE, background: 'rgba(var(--sd-ink, 255, 255, 255), 0.02)' }}>
528
+ <summary style={{ padding: '12px 16px', cursor: 'pointer', fontSize: 13.5, fontWeight: 650, color: 'var(--sd-fg-2, #cfd8d8)' }}>
467
529
  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>
530
+ <span style={{ fontWeight: 500, color: 'var(--sd-fg-4, #778)', marginLeft: 8 }}>daily budget, how much of each list, the hidden window, paused lists</span>
469
531
  </summary>
470
532
  <div style={{ padding: '4px 16px 16px', display: 'flex', flexDirection: 'column', gap: 12 }}>
471
533
  <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' }}>
534
+ <label style={{ display: 'flex', gap: 10, alignItems: 'center', fontSize: 12.5, color: 'var(--sd-fg-2, #cfd8d8)' }}>
473
535
  Read up to
474
536
  <select value={pages} onChange={(e) => setPages(Number(e.target.value))} disabled={running} style={selectStyle}>
475
537
  <option value={100}>every page, to the end of their list</option>
@@ -478,26 +540,26 @@ function SetupInner() {
478
540
  <option value={10}>10 pages (~100 people) each</option>
479
541
  </select>
480
542
  </label>
481
- <label style={{ display: 'flex', gap: 8, alignItems: 'center', fontSize: 12.5, color: '#cfd8d8', cursor: running ? 'not-allowed' : 'pointer' }}>
543
+ <label style={{ display: 'flex', gap: 8, alignItems: 'center', fontSize: 12.5, color: 'var(--sd-fg-2, #cfd8d8)', cursor: running ? 'not-allowed' : 'pointer' }}>
482
544
  <input type="checkbox" checked={finish} onChange={(e) => setFinish(e.target.checked)} disabled={running} />
483
545
  Also finish people already mapped, from the page each one stopped at
484
546
  </label>
485
- <label style={{ display: 'flex', gap: 8, alignItems: 'flex-start', fontSize: 12.5, color: '#b8c4c4', cursor: running ? 'default' : 'pointer' }}>
547
+ <label style={{ display: 'flex', gap: 8, alignItems: 'flex-start', fontSize: 12.5, color: 'var(--sd-fg-2, #b8c4c4)', cursor: running ? 'default' : 'pointer' }}>
486
548
  <input type="checkbox" checked={experimental} disabled={running} style={{ marginTop: 3 }}
487
549
  onChange={(e) => { setExperimental(e.target.checked); window.dispatchEvent(new Event('six-degrees:experimental')); }} />
488
550
  <span>
489
- <b style={{ color: '#FFD700' }}>Experimental:</b> all-day pacing. Up to 8 pages in a sitting,
551
+ <b style={{ color: 'var(--sd-gold, #FFD700)' }}>Experimental:</b> all-day pacing. Up to 8 pages in a sitting,
490
552
  then an hour&rsquo;s rest; searches only from 9:00 to 18:00; never more than 40 searches in a day
491
553
  or 200 in a week, however high your budget; two days&rsquo; rest after any check from LinkedIn; at
492
554
  the budget it waits instead of stopping; and it saves every page. It also reads LinkedIn&rsquo;s own data beside
493
555
  the page text, to fill gaps and measure how the two compare. It keeps running while the app is open.
494
556
  </span>
495
557
  </label>
496
- <label style={{ display: 'flex', gap: 8, alignItems: 'flex-start', fontSize: 12.5, color: '#b8c4c4', cursor: running ? 'default' : 'pointer' }}>
558
+ <label style={{ display: 'flex', gap: 8, alignItems: 'flex-start', fontSize: 12.5, color: 'var(--sd-fg-2, #b8c4c4)', cursor: running ? 'default' : 'pointer' }}>
497
559
  <input type="checkbox" checked={hideChrome} disabled={running} style={{ marginTop: 3 }}
498
560
  onChange={(e) => setHideChrome(e.target.checked)} />
499
561
  <span>
500
- <b style={{ color: '#FFD700' }}>Hide the Chrome window while scanning.</b> Every scan runs with no
562
+ <b style={{ color: 'var(--sd-gold, #FFD700)' }}>Hide the Chrome window while scanning.</b> Every scan runs with no
501
563
  window popping up; the status bar still shows what it&rsquo;s doing, and Stop still works. Signing
502
564
  in always opens the window.
503
565
  <span style={{ display: 'block', marginTop: 4, color: '#e0a080' }}>
@@ -509,7 +571,7 @@ function SetupInner() {
509
571
  </span>
510
572
  </span>
511
573
  </label>
512
- <div style={{ fontSize: 12, color: '#FFD700', lineHeight: 1.6 }}>
574
+ <div style={{ fontSize: 12, color: 'var(--sd-gold, #FFD700)', lineHeight: 1.6 }}>
513
575
  Every page is a LinkedIn search, so at {paceOf(li?.limits?.pace).label} it rests{' '}
514
576
  {paceOf(li?.limits?.pace).pagePause} seconds before each one and{' '}
515
577
  {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,7 +584,7 @@ function SetupInner() {
522
584
  <Btn onClick={() => run('auto-bridge-retry', { maxBridges: batch, tiers: order === 'score' ? tiers : [], order, maxPages: pages, deeper: finish })} disabled={!canSearch || (order === 'score' && !tiers.length)}>
523
585
  Retry hidden ones
524
586
  </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>
587
+ <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
588
  </div>
527
589
  <PausedList
528
590
  paused={s?.paused || []}
@@ -540,15 +602,15 @@ function SetupInner() {
540
602
  <details open={failed} style={{ marginTop: 20 }}>
541
603
  <summary style={{
542
604
  display: 'flex', alignItems: 'center', gap: 10, cursor: 'pointer',
543
- margin: '8px 0', fontSize: 12, color: '#788', textTransform: 'uppercase', letterSpacing: 0.6,
605
+ margin: '8px 0', fontSize: 12, color: 'var(--sd-fg-3, #788)', textTransform: 'uppercase', letterSpacing: 0.6,
544
606
  }}>
545
607
  {running && <Spinner />}
546
608
  {running ? 'What it’s doing (the log)' : 'The last run’s log'}
547
609
  </summary>
548
610
  <pre ref={logRef} style={{
549
- background: 'rgba(0,0,0,0.45)', border: LINE, borderRadius: 8,
611
+ background: 'rgba(var(--sd-shade, 0, 0, 0), 0.45)', border: LINE, borderRadius: 8,
550
612
  padding: 14, maxHeight: 280, overflow: 'auto', margin: 0,
551
- fontSize: 12.5, lineHeight: 1.7, color: '#b9c6c6',
613
+ fontSize: 12.5, lineHeight: 1.7, color: 'var(--sd-fg-2, #b9c6c6)',
552
614
  fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',
553
615
  whiteSpace: 'pre-wrap', wordBreak: 'break-word',
554
616
  }}>{s.log.join('\n')}</pre>
@@ -556,17 +618,6 @@ function SetupInner() {
556
618
  )}
557
619
  </>}
558
620
 
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
621
  </div>
571
622
 
572
623
  <style>{`@keyframes spin { to { transform: rotate(360deg) } }
@@ -589,35 +640,35 @@ function ScanOne({ pick, pages, setPages, li, running, s, canSearch, busy, onSta
589
640
  margin: '16px 0', padding: '16px 18px', borderRadius: 10, fontSize: 13.5, lineHeight: 1.6,
590
641
  background: 'rgba(0,255,136,0.05)', border: '1px solid rgba(0,255,136,0.3)',
591
642
  }}>
592
- <div style={{ fontSize: 11, fontWeight: 700, color: '#00ff88', letterSpacing: 0.6, textTransform: 'uppercase', marginBottom: 4 }}>
643
+ <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--sd-green, #00ff88)', letterSpacing: 0.6, textTransform: 'uppercase', marginBottom: 4 }}>
593
644
  Scan one circle
594
645
  </div>
595
646
  <div style={{ fontSize: 16, fontWeight: 700 }}>
596
647
  {person.name} <span style={{ fontSize: 12, color: TIER[person.tier] || '#888' }}>{person.tier}-tier</span>
597
648
  </div>
598
649
  {person.unlocked_from_name && (
599
- <div style={{ fontSize: 12.5, color: '#9aa' }}>Was in {person.unlocked_from_name}&rsquo;s circle</div>
650
+ <div style={{ fontSize: 12.5, color: 'var(--sd-fg-3, #9aa)' }}>Was in {person.unlocked_from_name}&rsquo;s circle</div>
600
651
  )}
601
652
  {theirs ? (
602
653
  <div style={{ marginTop: 10 }}>
603
654
  <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>
655
+ <Link href={`/?chain=${encodeURIComponent(person.id)}`} style={{ color: 'var(--sd-green, #00ff88)' }}>Bridge Chains shows it filling in →</Link>
605
656
  </div>
606
657
  ) : (
607
658
  <>
608
- <div style={{ color: '#b8c4c4', marginTop: 10 }}>
659
+ <div style={{ color: 'var(--sd-fg-2, #b8c4c4)', marginTop: 10 }}>
609
660
  It costs <b>{cost.profileViews} profile view</b> to find their list, then <b>one LinkedIn search for
610
661
  every page</b> of it: up to {cost.searches} {cost.searches === 1 ? 'page' : 'pages'}, about {cost.minutes} minutes.
611
662
  {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
663
  </div>
613
664
  {circle === 'scanned' && (
614
- <div style={{ color: '#FFD700', fontSize: 12.5, marginTop: 6 }}>
665
+ <div style={{ color: 'var(--sd-gold, #FFD700)', fontSize: 12.5, marginTop: 6 }}>
615
666
  Their circle is already scanned. This reads their whole list again from page 1; to carry on
616
667
  from where a read stopped, use Resume on their card or in the Paused list below.
617
668
  </div>
618
669
  )}
619
670
  {circle === 'hidden' && (
620
- <div style={{ color: '#FFD700', fontSize: 12.5, marginTop: 6 }}>
671
+ <div style={{ color: 'var(--sd-gold, #FFD700)', fontSize: 12.5, marginTop: 6 }}>
621
672
  Their list was hidden last time it was tried. Trying again costs a profile view.
622
673
  </div>
623
674
  )}
@@ -633,7 +684,7 @@ function ScanOne({ pick, pages, setPages, li, running, s, canSearch, busy, onSta
633
684
  <Btn onClick={onUnpick}>Not now</Btn>
634
685
  </div>
635
686
  {!canSearch && (
636
- <div style={{ fontSize: 12.5, color: '#8b9a9a', marginTop: 8 }}>
687
+ <div style={{ fontSize: 12.5, color: 'var(--sd-fg-3, #8b9a9a)', marginTop: 8 }}>
637
688
  {running ? 'Something else is running. One scan at a time: this one can start when it finishes.'
638
689
  : li?.cooldown ? 'Scanning is paused for now (see below).'
639
690
  : 'The scanner isn’t ready yet: finish the steps below first.'}
@@ -665,10 +716,9 @@ function useRemembered(key, fallback) {
665
716
  return [value, set];
666
717
  }
667
718
 
668
- const code = { background: 'rgba(255,255,255,0.08)', padding: '1px 5px', borderRadius: 4 };
669
719
  const selectStyle = {
670
720
  padding: '9px 10px', borderRadius: 7, fontSize: 13.5, fontWeight: 600,
671
- background: 'rgba(255,255,255,0.08)', color: '#fff', border: LINE,
721
+ background: 'rgba(var(--sd-ink, 255, 255, 255), 0.08)', color: 'var(--sd-fg-1, #fff)', border: LINE,
672
722
  };
673
723
 
674
724
  const JOURNEY_CSS = `
@@ -695,26 +745,26 @@ function StepRow({ n, label, state, last = false, children }) {
695
745
  <span className={now ? 'journey-now' : undefined} aria-hidden="true" style={{
696
746
  position: 'relative', zIndex: 1, width: 38, height: 38, borderRadius: '50%', display: 'grid', placeItems: 'center',
697
747
  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)'}`,
748
+ background: done ? 'rgba(0,255,136,0.16)' : now ? 'linear-gradient(135deg, #00ff88, #1abc9c)' : 'var(--sd-card, #12142a)',
749
+ color: done ? 'var(--sd-green, #00ff88)' : now ? '#04140c' : 'var(--sd-fg-4, #778)',
750
+ border: `2px solid ${done ? 'rgba(0,255,136,0.55)' : now ? 'transparent' : 'rgba(var(--sd-ink, 255, 255, 255), 0.14)'}`,
701
751
  }}>{done ? '✓' : n}</span>
702
752
  {!last && (
703
753
  <span aria-hidden="true" style={{
704
754
  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)',
755
+ 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
756
  }} />
707
757
  )}
708
758
  </div>
709
759
  <div style={{ minWidth: 0, paddingBottom: last ? 0 : 16, opacity: state === 'next' ? 0.75 : 1 }}>
710
760
  <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' }}>
761
+ <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
762
  Step {n} · {label}
713
763
  </span>
714
764
  <span style={{
715
765
  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)',
766
+ color: done ? 'var(--sd-green, #00ff88)' : now ? '#04140c' : 'var(--sd-fg-3, #889)',
767
+ background: done ? 'rgba(0,255,136,0.12)' : now ? '#00ff88' : 'rgba(var(--sd-ink, 255, 255, 255), 0.06)',
718
768
  }}>{done ? 'Done' : now ? 'Now' : 'Next'}</span>
719
769
  </div>
720
770
  {children}
@@ -728,40 +778,57 @@ function Mission({ title, time, body, launch, more, done = false, children }) {
728
778
  return (
729
779
  <div style={{
730
780
  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)'}`,
781
+ background: done ? 'rgba(0,255,136,0.03)' : 'rgba(var(--sd-ink, 255, 255, 255), 0.035)',
782
+ border: `1px solid ${done ? 'rgba(0,255,136,0.18)' : 'rgba(var(--sd-ink, 255, 255, 255), 0.1)'}`,
733
783
  }}>
734
784
  <div style={{ display: 'flex', alignItems: 'baseline', gap: 10, flexWrap: 'wrap' }}>
735
785
  <span style={{ fontSize: done ? 16 : 19, fontWeight: 800 }}>{title}</span>
736
- {time && !done && <span style={{ fontSize: 12, color: '#8fd9b6', marginLeft: 'auto' }}>⏱ {time}</span>}
786
+ {time && !done && <span style={{ fontSize: 12, color: 'var(--sd-fg-2, #8fd9b6)', marginLeft: 'auto' }}>⏱ {time}</span>}
737
787
  </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>
788
+ <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
789
  {children}
740
790
  {(launch || more) && <div style={{ display: 'flex', gap: 10, alignItems: 'center', flexWrap: 'wrap' }}>{launch}{more}</div>}
741
791
  </div>
742
792
  );
743
793
  }
744
794
 
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 }) {
795
+ /**
796
+ * The big go button. `quiet` once that step is done, so the next thing to do
797
+ * stands out. With `href`, a link that looks the same, opened outside the app
798
+ * (the desktop app sends it to the browser): Chrome's download.
799
+ */
800
+ function Launch({ children, onClick, disabled, quiet = false, href }) {
801
+ if (href) {
802
+ return (
803
+ <a className="launch-go" href={href} target="_blank" rel="noreferrer" style={{
804
+ ...launchLook(false, quiet), textDecoration: 'none',
805
+ }}>
806
+ <span aria-hidden="true" style={{ fontSize: quiet ? 11 : 13 }}>▶</span>{children}
807
+ </a>
808
+ );
809
+ }
747
810
  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
- }}>
811
+ <button type="button" className="launch-go" onClick={onClick} disabled={disabled} style={launchLook(disabled, quiet)}>
755
812
  <span aria-hidden="true" style={{ fontSize: quiet ? 11 : 13 }}>▶</span>{children}
756
813
  </button>
757
814
  );
758
815
  }
759
816
 
817
+ function launchLook(disabled, quiet) {
818
+ return {
819
+ display: 'inline-flex', alignItems: 'center', gap: 10, padding: quiet ? '10px 18px' : '13px 26px', borderRadius: 12,
820
+ fontSize: quiet ? 14 : 16, fontWeight: 800, cursor: disabled ? 'not-allowed' : 'pointer',
821
+ 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',
822
+ background: disabled ? 'rgba(var(--sd-ink, 255, 255, 255), 0.06)' : quiet ? 'rgba(0,255,136,0.08)' : 'linear-gradient(135deg, #00ff88, #1abc9c)',
823
+ boxShadow: disabled || quiet ? 'none' : '0 4px 22px rgba(0,255,136,0.25)',
824
+ };
825
+ }
826
+
760
827
  /** Why the second degree goes slowly: one tap away, not in the way. */
761
828
  function WhySlow() {
762
829
  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>
830
+ <details style={{ fontSize: 12.5, color: 'var(--sd-fg-3, #8b9a9a)', lineHeight: 1.6 }}>
831
+ <summary style={{ cursor: 'pointer', color: 'var(--sd-fg-2, #aab7c4)', fontWeight: 600 }}>Why so slow?</summary>
765
832
  <div style={{ marginTop: 6 }}>
766
833
  This is the part LinkedIn notices. While this app was being built, a real account was
767
834
  restricted for a while after roughly <b>19 people in one sitting</b>. So: a small batch, a day&rsquo;s
@@ -773,25 +840,54 @@ function WhySlow() {
773
840
  );
774
841
  }
775
842
 
776
- function Btn({ children, onClick, disabled, primary, tone }) {
843
+ // `cluster`: its first child is a ClusterSpinner, built on hover (app/components/ClusterSpinner.js).
844
+ // `active`: its own job is running, so it stays lit (and can't be pressed again).
845
+ function Btn({ children, onClick, disabled, primary, tone, cluster = false, active = false }) {
777
846
  const bg = tone === 'bad' ? 'rgba(255,80,80,0.15)'
778
847
  : primary ? 'linear-gradient(135deg, #9B59B6, #3498DB)'
779
- : 'rgba(255,255,255,0.08)';
848
+ : 'rgba(var(--sd-ink, 255, 255, 255), 0.08)';
780
849
  return (
781
- <button onClick={onClick} disabled={disabled} style={{
850
+ <button onClick={onClick} disabled={disabled} className={cluster ? 'cluster-host' : undefined} style={{
782
851
  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',
852
+ // White on the purple gradient in every look; the theme's words elsewhere.
853
+ 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,
854
+ border: LINE, cursor: active ? 'progress' : disabled ? 'not-allowed' : 'pointer',
855
+ ...(cluster ? { display: 'inline-flex', alignItems: 'center', gap: 8 } : {}),
785
856
  }}>{children}</button>
786
857
  );
787
858
  }
788
859
 
860
+ // Before the first scan, once: what scanning does and risks, and an explicit
861
+ // "I understand" (lib/scan-risk.js). The CSV stays one click away for anyone
862
+ // who would rather not.
863
+ function RiskCard({ onAccept, busy }) {
864
+ return (
865
+ <div role="region" aria-label="Before your first scan" style={{
866
+ margin: '6px 0 18px', padding: '16px 18px', borderRadius: 12,
867
+ border: '1px solid rgba(var(--sd-ink, 255, 255, 255), 0.14)',
868
+ background: 'rgba(var(--sd-ink, 255, 255, 255), 0.04)',
869
+ }}>
870
+ <div style={{ fontSize: 15, fontWeight: 700, color: 'var(--sd-fg-1, #fff)', marginBottom: 8 }}>Before your first scan</div>
871
+ <ul style={{ margin: '0 0 14px', paddingLeft: 18, color: 'var(--sd-fg-2, #c8d0d0)', fontSize: 13.5, lineHeight: 1.65 }}>
872
+ {RISK_POINTS.map((p) => <li key={p} style={{ marginBottom: 4 }}>{p}</li>)}
873
+ </ul>
874
+ <div style={{ display: 'flex', gap: 14, alignItems: 'center', flexWrap: 'wrap' }}>
875
+ <Btn onClick={onAccept} disabled={busy} primary>I understand</Btn>
876
+ <span style={{ fontSize: 13, color: 'var(--sd-fg-3, #8b9a9a)' }}>
877
+ Rather not? LinkedIn’s own CSV export needs none of this:{' '}
878
+ <Link href="/import" style={{ color: 'var(--sd-blue, #3498DB)' }}>import a CSV instead</Link>.
879
+ </span>
880
+ </div>
881
+ </div>
882
+ );
883
+ }
884
+
789
885
  function Box({ children, tone }) {
790
886
  return (
791
887
  <div style={{
792
888
  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)'}`,
889
+ background: tone === 'bad' ? 'rgba(255,80,80,0.08)' : 'rgba(var(--sd-ink, 255, 255, 255), 0.05)',
890
+ border: `1px solid ${tone === 'bad' ? 'rgba(255,80,80,0.3)' : 'rgba(var(--sd-ink, 255, 255, 255), 0.12)'}`,
795
891
  }}>{children}</div>
796
892
  );
797
893
  }
@@ -805,15 +901,15 @@ function Progress({ p, action }) {
805
901
  return (
806
902
  <div style={{ margin: '8px 0 6px' }}>
807
903
  <div role="progressbar" aria-label="Saving" style={{
808
- height: 8, borderRadius: 4, overflow: 'hidden', background: 'rgba(255,255,255,0.08)', marginBottom: 6,
904
+ height: 8, borderRadius: 4, overflow: 'hidden', background: 'rgba(var(--sd-ink, 255, 255, 255), 0.08)', marginBottom: 6,
809
905
  }}>
810
906
  <div style={{
811
907
  width: '35%', height: '100%', borderRadius: 4,
812
908
  background: 'linear-gradient(90deg, #9B59B6, #3498DB)', animation: 'slide 1.2s ease-in-out infinite',
813
909
  }} />
814
910
  </div>
815
- <div style={{ fontSize: 12.5, color: '#cfe6f7' }}>
816
- Saving to your network and fetching photos — this can take a minute or two.
911
+ <div style={{ fontSize: 12.5, color: 'var(--sd-fg-1, #cfe6f7)' }}>
912
+ Saving to your network and fetching photos. This can take a minute or two.
817
913
  </div>
818
914
  </div>
819
915
  );
@@ -822,7 +918,7 @@ function Progress({ p, action }) {
822
918
  let text;
823
919
  if (p.kind === 'download') text = `Downloading Python: ${p.done.toFixed(1)} of ${p.total.toFixed(1)} MB · ${pct}%`;
824
920
  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`;
921
+ else if (action === 'refresh') text = `Looked at ${p.done.toLocaleString()} so far, and stops once it reaches people already saved`;
826
922
  else text = `${p.done.toLocaleString()} of ${p.total.toLocaleString()} connections · ${pct}%`;
827
923
 
828
924
  return (
@@ -836,7 +932,7 @@ function Progress({ p, action }) {
836
932
  aria-label={text}
837
933
  style={{
838
934
  height: 8, borderRadius: 4, overflow: 'hidden',
839
- background: 'rgba(255,255,255,0.08)', marginBottom: 6,
935
+ background: 'rgba(var(--sd-ink, 255, 255, 255), 0.08)', marginBottom: 6,
840
936
  }}
841
937
  >
842
938
  <div style={{
@@ -846,7 +942,7 @@ function Progress({ p, action }) {
846
942
  }} />
847
943
  </div>
848
944
  )}
849
- <div style={{ fontSize: 12.5, color: '#cfe6f7' }}>{text}</div>
945
+ <div style={{ fontSize: 12.5, color: 'var(--sd-fg-1, #cfe6f7)' }}>{text}</div>
850
946
  </div>
851
947
  );
852
948
  }
@@ -854,7 +950,7 @@ function Progress({ p, action }) {
854
950
  function Spinner() {
855
951
  return <span style={{
856
952
  width: 11, height: 11, borderRadius: '50%', display: 'inline-block',
857
- border: '2px solid rgba(255,255,255,0.2)', borderTopColor: '#3498DB',
953
+ border: '2px solid rgba(var(--sd-ink, 255, 255, 255), 0.2)', borderTopColor: '#3498DB',
858
954
  animation: 'spin 0.8s linear infinite',
859
955
  }} />;
860
956
  }