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
@@ -76,7 +76,7 @@ export default function SectorPicker({ sectors, onChange, disabled, suggest }) {
76
76
  return (
77
77
  <Chip key={key} color={sectorByKey(key).color} on={on} blocked={!on && full} disabled={disabled} title={title}
78
78
  onClick={() => toggle(key)}>
79
- {label}{note && <span style={{ fontWeight: 400, color: on ? '#dfe7e7' : '#8b9a9a' }}>{note}</span>}
79
+ {label}{note && <span style={{ fontWeight: 400, color: on ? 'var(--sd-fg-1, #dfe7e7)' : 'var(--sd-fg-3, #8b9a9a)' }}>{note}</span>}
80
80
  </Chip>
81
81
  );
82
82
  };
@@ -84,17 +84,17 @@ export default function SectorPicker({ sectors, onChange, disabled, suggest }) {
84
84
  return (
85
85
  <>
86
86
  <div style={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap', gap: 6 }}>
87
- <span style={{ fontSize: 13, color: '#8b9a9a' }}>Your picks ({sectors.length} of {MAX_SECTORS}):</span>
88
- {!sectors.length && <span style={{ fontSize: 13, color: '#667' }}>none yet</span>}
87
+ <span style={{ fontSize: 13, color: 'var(--sd-fg-3, #8b9a9a)' }}>Your picks ({sectors.length} of {MAX_SECTORS}):</span>
88
+ {!sectors.length && <span style={{ fontSize: 13, color: 'var(--sd-fg-4, #667)' }}>none yet</span>}
89
89
  {sectors.map((k) => {
90
90
  const s = sectorByKey(k);
91
91
  return (
92
92
  <button key={k} type="button" disabled={disabled} onClick={() => toggle(k)} aria-label={`Remove ${s.label}`}
93
93
  style={{
94
94
  display: 'flex', alignItems: 'center', gap: 6, padding: '4px 10px', borderRadius: 999, fontSize: 12.5,
95
- fontWeight: 600, color: '#fff', background: `${s.color}33`, border: `1px solid ${s.color}`, cursor: 'pointer',
95
+ fontWeight: 600, color: 'var(--sd-fg-1, #fff)', background: `${s.color}33`, border: `1px solid ${s.color}`, cursor: 'pointer',
96
96
  }}>
97
- {s.label} <span aria-hidden="true" style={{ color: '#cfd8d8' }}>×</span>
97
+ {s.label} <span aria-hidden="true" style={{ color: 'var(--sd-fg-2, #cfd8d8)' }}>×</span>
98
98
  </button>
99
99
  );
100
100
  })}
@@ -102,7 +102,7 @@ export default function SectorPicker({ sectors, onChange, disabled, suggest }) {
102
102
 
103
103
  {suggest && <Suggestions state={suggest} chip={chip} />}
104
104
 
105
- <label htmlFor="sector-search" style={{ display: 'block', fontSize: 13, color: '#8b9a9a', margin: '16px 0 6px' }}>
105
+ <label htmlFor="sector-search" style={{ display: 'block', fontSize: 13, color: 'var(--sd-fg-3, #8b9a9a)', margin: '16px 0 6px' }}>
106
106
  Find a sector
107
107
  </label>
108
108
  <div style={{ display: 'flex', gap: 8 }}>
@@ -110,8 +110,8 @@ export default function SectorPicker({ sectors, onChange, disabled, suggest }) {
110
110
  placeholder="Try dentist, bakery or Stripe"
111
111
  autoComplete="off" spellCheck={false}
112
112
  style={{
113
- flex: 1, minWidth: 0, padding: '8px 12px', borderRadius: 7, fontSize: 14, color: '#fff',
114
- background: 'rgba(255,255,255,0.05)', border: LINE, outline: 'none',
113
+ flex: 1, minWidth: 0, padding: '8px 12px', borderRadius: 7, fontSize: 14, color: 'var(--sd-fg-1, #fff)',
114
+ background: 'rgba(var(--sd-ink, 255, 255, 255), 0.05)', border: LINE, outline: 'none',
115
115
  }} />
116
116
  {query && <Btn onClick={() => setQuery('')}>Clear</Btn>}
117
117
  </div>
@@ -142,7 +142,7 @@ export default function SectorPicker({ sectors, onChange, disabled, suggest }) {
142
142
  {chip(g.key, g.label, { title: 'The whole industry: companies its sectors place, or whose name or the well-known list says so' })}
143
143
  <button type="button" aria-expanded={isOpen} aria-controls={`sectors-${g.key}`} onClick={() => flip(g.key)}
144
144
  style={{
145
- padding: '4px 6px', fontSize: 12.5, color: inside ? '#9fd3ff' : '#8b9a9a', background: 'none', border: 'none',
145
+ padding: '4px 6px', fontSize: 12.5, color: inside ? 'var(--sd-fg-2, #9fd3ff)' : 'var(--sd-fg-3, #8b9a9a)', background: 'none', border: 'none',
146
146
  cursor: 'pointer',
147
147
  }}>
148
148
  {isOpen ? '▾' : '▸'} {plural(inIndustry.length, 'sector')}{inside ? ` · ${inside} picked` : ''}
@@ -171,8 +171,8 @@ function Chip({ color, on, blocked, disabled, title, onClick, children }) {
171
171
  style={{
172
172
  display: 'flex', alignItems: 'center', gap: 7, padding: '6px 12px', borderRadius: 999, maxWidth: '100%',
173
173
  fontSize: 12.5, fontWeight: 600, textAlign: 'left', cursor: blocked ? 'not-allowed' : 'pointer',
174
- color: on ? '#fff' : blocked ? '#556' : '#b8c4c4',
175
- background: on ? `${color}33` : 'rgba(255,255,255,0.04)',
174
+ color: on ? 'var(--sd-fg-1, #fff)' : blocked ? 'var(--sd-fg-5, #556)' : 'var(--sd-fg-2, #b8c4c4)',
175
+ background: on ? `${color}33` : 'rgba(var(--sd-ink, 255, 255, 255), 0.04)',
176
176
  border: on ? `1px solid ${color}` : LINE,
177
177
  }}>
178
178
  <span style={{ width: 8, height: 8, borderRadius: '50%', background: color, opacity: blocked ? 0.4 : 1, flexShrink: 0 }} />
@@ -190,7 +190,7 @@ function Suggestions({ state, chip }) {
190
190
  if (!state.list.length) return <Body style={note}>None of the list&rsquo;s sectors stands out among the people you&rsquo;ve scanned yet.</Body>;
191
191
  return (
192
192
  <div style={{ marginTop: 14 }}>
193
- <div style={{ fontSize: 13, color: '#8b9a9a', marginBottom: 6 }}>Suggested from your network</div>
193
+ <div style={{ fontSize: 13, color: 'var(--sd-fg-3, #8b9a9a)', marginBottom: 6 }}>Suggested from your network</div>
194
194
  <div role="group" aria-label="Suggested from your network" style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
195
195
  {state.list.map((s) => chip(s.key, s.label, {
196
196
  note: `: ${plural(s.people, 'person', 'people')} at ${plural(s.companies, 'company', 'companies')}`,
@@ -51,16 +51,15 @@ export default function SectorSection({ onSaved } = {}) {
51
51
  const [result, setResult] = useState(null);
52
52
  const [loadError, setLoadError] = useState(null);
53
53
  const [suggest, setSuggest] = useState({ loading: true });
54
- // A CSV import or the sample network held in this window. This section only
55
- // renders in the browser (the page waits in OnboardingGate), so reading
56
- // sessionStorage here can't disagree with a server render.
57
- const [onScreen] = useState(() => (typeof window === 'undefined' ? null : csvNetworkSource()));
54
+ // A CSV import or the sample network open instead of yours.
55
+ const [onScreen, setOnScreen] = useState(null);
58
56
  const timer = useRef(null);
59
57
  const ticket = useRef(0);
60
58
  const jumped = useRef(false);
61
59
 
62
60
  useEffect(() => {
63
61
  let off = false;
62
+ csvNetworkSource().then((source) => { if (!off) setOnScreen(source); });
64
63
  fetch('/api/settings')
65
64
  .then((r) => r.json().then((d) => (r.ok ? d : Promise.reject(new Error(d.error || 'Could not load your sector.')))))
66
65
  .then((d) => {
@@ -154,13 +153,13 @@ export default function SectorSection({ onSaved } = {}) {
154
153
  suggest={suggest} />
155
154
 
156
155
  <div style={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap', gap: 8, marginTop: 14 }}>
157
- <span style={{ fontSize: 13, color: '#8b9a9a' }}>How much:</span>
156
+ <span style={{ fontSize: 13, color: 'var(--sd-fg-3, #8b9a9a)' }}>How much:</span>
158
157
  {Object.keys(SECTOR_BONUS).map((s) => (
159
158
  <button key={s} type="button" aria-pressed={draft.strength === s} disabled={saving}
160
159
  onClick={() => change({ ...draft, strength: s })}
161
160
  style={{
162
161
  padding: '5px 12px', borderRadius: 7, fontSize: 12.5, fontWeight: 600, cursor: 'pointer',
163
- color: draft.strength === s ? '#fff' : '#8b9a9a',
162
+ color: draft.strength === s ? 'var(--sd-fg-1, #fff)' : 'var(--sd-fg-3, #8b9a9a)',
164
163
  background: draft.strength === s ? 'rgba(52,152,219,0.25)' : 'transparent', border: LINE,
165
164
  }}>
166
165
  {STRENGTH_LABEL[s]} · +{SECTOR_BONUS[s]}
@@ -183,9 +182,9 @@ export default function SectorSection({ onSaved } = {}) {
183
182
  </div>
184
183
  {result && <Status tone={result.tone}>{result.text}</Status>}
185
184
 
186
- <ul style={{ margin: '16px 0 0', paddingLeft: 18, fontSize: 12.5, color: '#778', lineHeight: 1.7 }}>
185
+ <ul style={{ margin: '16px 0 0', paddingLeft: 18, fontSize: 12.5, color: 'var(--sd-fg-4, #778)', lineHeight: 1.7 }}>
187
186
  <li>Tiers rank how reachable someone is through your network, not the people themselves.</li>
188
- <li>A company score you set on <a href="#companies" style={{ color: '#3498DB' }}>Company scores</a>, below, always wins. Your sector never changes it.</li>
187
+ <li>A company score you set on <a href="#companies" style={{ color: 'var(--sd-blue, #3498DB)' }}>Company scores</a>, below, always wins. Your sector never changes it.</li>
189
188
  <li>If you scan highest tier first, people in your sectors come up sooner. Scanning newest first, the default, doesn&rsquo;t go by tier.</li>
190
189
  <li>
191
190
  An industry includes its sectors. It counts a company in any of its sectors (Healthcare &amp; Biotech counts a
@@ -204,8 +203,8 @@ export default function SectorSection({ onSaved } = {}) {
204
203
  Staffing, Smith CPA), and so does a kind of firm in a headline (staffing agency, law firm, SaaS).
205
204
  </li>
206
205
  {onScreen && (
207
- <li style={{ color: '#FFD700' }}>
208
- {onScreen === 'sample' ? 'The sample network' : 'The CSV import'} open in this window isn&rsquo;t changed by this, and
206
+ <li style={{ color: 'var(--sd-gold, #FFD700)' }}>
207
+ {onScreen === 'sample' ? 'The sample network open in this window' : 'The CSV import you have open'} isn&rsquo;t changed by this, and
209
208
  isn&rsquo;t counted in the suggestions. Your sector applies to networks you&rsquo;ve scanned.
210
209
  </li>
211
210
  )}
@@ -233,7 +232,7 @@ function savedLine(focus, effect) {
233
232
  function Preview({ preview, draft }) {
234
233
  if (!preview) return null;
235
234
  if (preview.key !== focusFingerprint(draft)) return null;
236
- const box = { marginTop: 12, padding: '10px 14px', borderRadius: 8, fontSize: 13, lineHeight: 1.6, border: LINE, background: 'rgba(255,255,255,0.03)', color: '#cfd8d8' };
235
+ const box = { marginTop: 12, padding: '10px 14px', borderRadius: 8, fontSize: 13, lineHeight: 1.6, border: LINE, background: 'rgba(var(--sd-ink, 255, 255, 255), 0.03)', color: 'var(--sd-fg-2, #cfd8d8)' };
237
236
  if (preview.loading) return <div style={box} aria-live="polite">Working out what would change…</div>;
238
237
  if (preview.error) return <Status tone="bad">{preview.error}</Status>;
239
238
  if (!preview.scored) {
@@ -247,13 +246,13 @@ function Preview({ preview, draft }) {
247
246
  return (
248
247
  <div style={box} aria-live="polite">
249
248
  <div>
250
- <b style={{ color: '#fff' }}>If you save:</b> {cos ? `${cos}.` : 'No company changes score.'} {tierLine(preview.up, preview.down, false)}
249
+ <b style={{ color: 'var(--sd-fg-1, #fff)' }}>If you save:</b> {cos ? `${cos}.` : 'No company changes score.'} {tierLine(preview.up, preview.down, false)}
251
250
  </div>
252
251
  {preview.examples?.length > 0 && (
253
252
  <div style={{ marginTop: 6, display: 'flex', flexWrap: 'wrap', gap: '4px 12px', fontSize: 12.5 }}>
254
253
  {preview.examples.map((e, n) => (
255
254
  <span key={n} title={e.company || undefined}>
256
- {e.name}{e.degree ? <span style={{ color: '#667' }}> ({DEGREE[e.degree] || `${e.degree}th`})</span> : null}{' '}
255
+ {e.name}{e.degree ? <span style={{ color: 'var(--sd-fg-4, #667)' }}> ({DEGREE[e.degree] || `${e.degree}th`})</span> : null}{' '}
257
256
  <b style={{ color: TIER_COLORS_CLASSIC[e.from] || '#889' }}>{e.from || '–'}</b>
258
257
  {' → '}
259
258
  <b style={{ color: TIER_COLORS_CLASSIC[e.to] || '#889' }}>{e.to}</b>
@@ -262,7 +261,7 @@ function Preview({ preview, draft }) {
262
261
  </div>
263
262
  )}
264
263
  {preview.companyExamples?.length > 0 && (
265
- <div style={{ marginTop: 4, fontSize: 12, color: '#8b9a9a' }}>
264
+ <div style={{ marginTop: 4, fontSize: 12, color: 'var(--sd-fg-3, #8b9a9a)' }}>
266
265
  {preview.companyExamples.slice(0, 3).map((c) => `${c.name} ${c.from} → ${c.to}`).join(' · ')}
267
266
  </div>
268
267
  )}
@@ -35,14 +35,14 @@ export default function TierSection({ onSaved } = {}) {
35
35
  const [saving, setSaving] = useState(false);
36
36
  const [result, setResult] = useState(null);
37
37
  const [loadError, setLoadError] = useState(null);
38
- // A CSV import or the sample network held in this window: neither is changed
39
- // by this (a CSV is always graded on its own curve; the sample keeps its
40
- // tiers). This section only renders in the browser (OnboardingGate), so
41
- // reading sessionStorage here can't disagree with a server render.
42
- const [onScreen] = useState(() => (typeof window === 'undefined' ? null : csvNetworkSource()));
38
+ // A CSV import or the sample network open instead of yours: neither is
39
+ // changed by this (a CSV is always graded on its own curve; the sample keeps
40
+ // its tiers).
41
+ const [onScreen, setOnScreen] = useState(null);
43
42
 
44
43
  useEffect(() => {
45
44
  let off = false;
45
+ csvNetworkSource().then((source) => { if (!off) setOnScreen(source); });
46
46
  fetch('/api/settings')
47
47
  .then((r) => r.json().then((d) => (r.ok ? d : Promise.reject(new Error(d.error || 'Could not load how tiers are graded.')))))
48
48
  .then((d) => { if (!off) setSaved(d.settings?.tierScale || 'curve'); })
@@ -74,8 +74,8 @@ export default function TierSection({ onSaved } = {}) {
74
74
  const on = saved === o.key;
75
75
  return (
76
76
  <button key={o.key} type="button" role="radio" aria-checked={on} disabled={saving} onClick={() => choose(o.key)} style={{
77
- textAlign: 'left', padding: '12px 14px', borderRadius: 8, cursor: saving ? 'wait' : on ? 'default' : 'pointer', color: '#fff',
78
- background: on ? 'rgba(155,89,182,0.14)' : 'rgba(255,255,255,0.03)',
77
+ textAlign: 'left', padding: '12px 14px', borderRadius: 8, cursor: saving ? 'wait' : on ? 'default' : 'pointer', color: 'var(--sd-fg-1, #fff)',
78
+ background: on ? 'rgba(155,89,182,0.14)' : 'rgba(var(--sd-ink, 255, 255, 255), 0.03)',
79
79
  border: on ? '1px solid rgba(155,89,182,0.6)' : LINE,
80
80
  }}>
81
81
  <div style={{ fontSize: 14, fontWeight: 650 }}>{on ? '● ' : '○ '}{o.label}{o.key === 'curve' ? ' (recommended)' : ''}</div>
@@ -86,10 +86,10 @@ export default function TierSection({ onSaved } = {}) {
86
86
  </div>
87
87
  )}
88
88
  {onScreen && (
89
- <Body style={{ color: '#FFD700', marginTop: 10 }}>
89
+ <Body style={{ color: 'var(--sd-gold, #FFD700)', marginTop: 10 }}>
90
90
  {onScreen === 'sample'
91
91
  ? 'The sample network open in this window keeps its own tiers (they’re the same either way).'
92
- : 'The CSV import open in this window is always graded on its own curve.'}{' '}
92
+ : 'The CSV import you have open is always graded on its own curve.'}{' '}
93
93
  This applies to networks you&rsquo;ve scanned.
94
94
  </Body>
95
95
  )}
@@ -17,7 +17,7 @@ const POINTS = [10, 9.5, 9, 8.5, 8, 7.5, 7, 6.5, 6, 5.5, 5, 4.5, 4, 3, 2, 1, 0];
17
17
  const plural = (n, one, many) => `${n.toLocaleString()} ${n === 1 ? one : many}`;
18
18
  const select = {
19
19
  padding: '5px 8px', borderRadius: 6, fontSize: 12.5, cursor: 'pointer',
20
- border: LINE, background: 'rgba(0,0,0,0.3)', color: '#fff',
20
+ border: LINE, background: 'rgba(var(--sd-shade, 0, 0, 0), 0.3)', color: 'var(--sd-fg-1, #fff)',
21
21
  };
22
22
 
23
23
  export default function TitleSection({ onSaved } = {}) {
@@ -87,7 +87,7 @@ export default function TitleSection({ onSaved } = {}) {
87
87
  <button key={p.key} type="button" onClick={() => pick(p)} aria-pressed={preset === p.key} title={p.note} style={{
88
88
  padding: '6px 12px', borderRadius: 16, fontSize: 12.5, fontWeight: 650, cursor: 'pointer',
89
89
  border: preset === p.key ? '1px solid rgba(155,89,182,0.7)' : LINE,
90
- background: preset === p.key ? 'rgba(155,89,182,0.16)' : 'rgba(255,255,255,0.03)', color: preset === p.key ? '#fff' : '#bbb',
90
+ background: preset === p.key ? 'rgba(155,89,182,0.16)' : 'rgba(var(--sd-ink, 255, 255, 255), 0.03)', color: preset === p.key ? 'var(--sd-fg-1, #fff)' : 'var(--sd-fg-2, #bbb)',
91
91
  }}>{p.label}</button>
92
92
  ))}
93
93
  </div>
@@ -100,26 +100,26 @@ export default function TitleSection({ onSaved } = {}) {
100
100
  {RANKED_LEVELS.map((key) => {
101
101
  const mine = draft.points?.[key] != null;
102
102
  return [
103
- <div key={`${key}-l`} style={{ fontSize: 13, color: mine ? '#fff' : '#ccc', fontWeight: mine ? 700 : 500 }}>{LEVELS[key].label}</div>,
103
+ <div key={`${key}-l`} style={{ fontSize: 13, color: mine ? 'var(--sd-fg-1, #fff)' : 'var(--sd-fg-2, #ccc)', fontWeight: mine ? 700 : 500 }}>{LEVELS[key].label}</div>,
104
104
  <select key={`${key}-s`} aria-label={`Points for ${LEVELS[key].label}`} value={pointsOf(key)} onChange={(e) => setPoints(key, Number(e.target.value))}
105
105
  style={{ ...select, borderColor: mine ? 'rgba(155,89,182,0.7)' : undefined }}>
106
106
  {POINTS.map((p) => <option key={p} value={p}>{p}</option>)}
107
107
  </select>,
108
- <div key={`${key}-d`} style={{ fontSize: 11, color: '#667', minWidth: 70 }}>
109
- {mine ? <button type="button" onClick={() => setPoints(key, LEVELS[key].points)} style={{ background: 'none', border: 'none', color: '#9b9bd0', cursor: 'pointer', fontSize: 11, padding: 0 }}>back to {LEVELS[key].points}</button> : 'as it comes'}
108
+ <div key={`${key}-d`} style={{ fontSize: 11, color: 'var(--sd-fg-4, #667)', minWidth: 70 }}>
109
+ {mine ? <button type="button" onClick={() => setPoints(key, LEVELS[key].points)} style={{ background: 'none', border: 'none', color: 'var(--sd-fg-3, #9b9bd0)', cursor: 'pointer', fontSize: 11, padding: 0 }}>back to {LEVELS[key].points}</button> : 'as it comes'}
110
110
  </div>,
111
111
  ];
112
112
  })}
113
113
  </div>
114
114
 
115
115
  {/* Roles you're looking for */}
116
- <div style={{ marginTop: 18, fontSize: 13.5, fontWeight: 700, color: '#eee' }}>Roles you&rsquo;re looking for</div>
116
+ <div style={{ marginTop: 18, fontSize: 13.5, fontWeight: 700, color: 'var(--sd-fg-1, #eee)' }}>Roles you&rsquo;re looking for</div>
117
117
  <Body style={{ margin: '4px 0 10px' }}>
118
118
  Anyone whose title has these words counts what you give them, whatever their level: for outbound to one role, or hiring for it. &ldquo;Account executive&rdquo; at 10 puts every account executive you can reach near the top.
119
119
  </Body>
120
120
  <form onSubmit={(e) => { e.preventDefault(); addRole(); }} style={{ display: 'flex', gap: 8, flexWrap: 'wrap', alignItems: 'center' }}>
121
121
  <input ref={roleBox} value={role} onChange={(e) => setRole(e.target.value)} placeholder="e.g. head of growth, recruiter, founder"
122
- maxLength={60} style={{ flex: '1 1 220px', padding: '7px 10px', borderRadius: 6, fontSize: 13, border: LINE, background: 'rgba(0,0,0,0.3)', color: '#fff' }} />
122
+ maxLength={60} style={{ flex: '1 1 220px', padding: '7px 10px', borderRadius: 6, fontSize: 13, border: LINE, background: 'rgba(var(--sd-shade, 0, 0, 0), 0.3)', color: 'var(--sd-fg-1, #fff)' }} />
123
123
  <select aria-label="Points for this role" value={rolePoints} onChange={(e) => setRolePoints(Number(e.target.value))} style={select}>
124
124
  {POINTS.map((p) => <option key={p} value={p}>{p}</option>)}
125
125
  </select>
@@ -130,10 +130,10 @@ export default function TitleSection({ onSaved } = {}) {
130
130
  {draft.roles.map((r) => (
131
131
  <span key={r.text} style={{
132
132
  display: 'inline-flex', alignItems: 'center', gap: 6, padding: '4px 6px 4px 11px', borderRadius: 14, fontSize: 12.5,
133
- border: '1px solid rgba(155,89,182,0.5)', background: 'rgba(155,89,182,0.12)', color: '#eee',
133
+ border: '1px solid rgba(155,89,182,0.5)', background: 'rgba(155,89,182,0.12)', color: 'var(--sd-fg-1, #eee)',
134
134
  }}>
135
- {r.text} <b style={{ color: '#d2b4ff' }}>{r.points}</b>
136
- <button type="button" onClick={() => dropRole(r.text)} aria-label={`Remove ${r.text}`} style={{ background: 'none', border: 'none', color: '#aaa', cursor: 'pointer', fontSize: 13 }}>✕</button>
135
+ {r.text} <b style={{ color: 'var(--sd-fg-2, #d2b4ff)' }}>{r.points}</b>
136
+ <button type="button" onClick={() => dropRole(r.text)} aria-label={`Remove ${r.text}`} style={{ background: 'none', border: 'none', color: 'var(--sd-fg-3, #aaa)', cursor: 'pointer', fontSize: 13 }}>✕</button>
137
137
  </span>
138
138
  ))}
139
139
  </div>
@@ -141,7 +141,7 @@ export default function TitleSection({ onSaved } = {}) {
141
141
 
142
142
  <div style={{ display: 'flex', gap: 10, alignItems: 'center', marginTop: 16 }}>
143
143
  <Btn primary onClick={save} disabled={!dirty || saving}>{saving ? 'Rescoring…' : 'Save and rescore'}</Btn>
144
- {dirty && <span style={{ fontSize: 12, color: '#999' }}>Not saved yet. Saving rescores everyone.</span>}
144
+ {dirty && <span style={{ fontSize: 12, color: 'var(--sd-fg-3, #999)' }}>Not saved yet. Saving rescores everyone.</span>}
145
145
  </div>
146
146
  {result && <Status tone={result.tone}>{result.text}</Status>}
147
147
  </Section>
@@ -0,0 +1,313 @@
1
+ 'use client';
2
+
3
+ // Settings → LinkedIn usage: how close this LinkedIn account is to the line,
4
+ // in one look, the way Claude's usage page shows a plan's limits (neo's
5
+ // handoff, 2026-10-03; Blake's 1.0 list, item 3). Until now the only view of
6
+ // it was the budget box folded away in the Scan page's "Fine-tune the
7
+ // scanner", and an account was restricted once after 373 searches in 24 hours
8
+ // (TRAPS §16). The notch and that box link here.
9
+ //
10
+ // Every number is counted from the scanner's own record on this computer
11
+ // (GET /api/scraper?usage, lib/linkedin-limits.js linkedinUsage) or is a rule
12
+ // that says where it came from (lib/usage.js). LinkedIn publishes no limits and
13
+ // shows no count of its own, so nothing here claims to be LinkedIn's number.
14
+ // The page only reads; its one button is the Scan page's own "Back to 50 a
15
+ // day, 250 a month".
16
+
17
+ import { useCallback, useEffect, useState } from 'react';
18
+ import Link from 'next/link';
19
+ import { Section, Body, LINE } from '../ui';
20
+ import {
21
+ AUTO, PEOPLE_PER_SEARCH, DANGER_AT, REPORTED_MONTH, LEVELS, usageLevel, warningParts, estimate,
22
+ barMax, pacificText, whenText, untilText, agoText, hoursText,
23
+ } from '../../../lib/usage';
24
+ import { RESTRICTED_AT, RISKY_DAILY, SAFE_LIMITS } from '../../../lib/search-risk';
25
+ import { paceOf, searchesPerHour } from '../../../lib/scan-pace';
26
+
27
+ // Looked at again while the page is open, as the Scan page's own checks are.
28
+ const REFRESH_MS = 30 * 1000;
29
+
30
+ const count = (n) => (Number.isFinite(n) ? n.toLocaleString('en-US') : '?');
31
+ const plural = (n, one, many = `${one}s`) => `${count(n)} ${n === 1 ? one : many}`;
32
+ const link = { color: 'var(--sd-blue, #3498DB)', textDecoration: 'none', fontWeight: 600 };
33
+ const small = { fontSize: 12, color: 'var(--sd-fg-4, #778)', lineHeight: 1.6, marginTop: 4 };
34
+
35
+ function Pill({ level }) {
36
+ const l = LEVELS[level] || LEVELS.unknown;
37
+ return (
38
+ <span role="status" style={{
39
+ display: 'inline-flex', alignItems: 'center', gap: 7, padding: '4px 11px', borderRadius: 999,
40
+ fontSize: 12.5, fontWeight: 700, color: l.color, background: `${l.color}1f`, border: `1px solid ${l.color}55`, whiteSpace: 'nowrap',
41
+ }}>
42
+ <span style={{ width: 7, height: 7, borderRadius: '50%', background: l.color }} />
43
+ {l.label}
44
+ </span>
45
+ );
46
+ }
47
+
48
+ /** Where on the bar a number sits, as a percentage. */
49
+ const at = (n, max) => `${Math.max(0, Math.min(100, (n / max) * 100))}%`;
50
+
51
+ /**
52
+ * One meter: a heading with the count, a bar with its marks (and a shaded
53
+ * range), the marks' numbers under it, then what they mean.
54
+ */
55
+ function Meter({ title, used, of, max, color, ticks = [], band, children }) {
56
+ return (
57
+ <div style={{ marginTop: 18 }}>
58
+ <div style={{ display: 'flex', alignItems: 'baseline', gap: 10, flexWrap: 'wrap' }}>
59
+ <span style={{ fontSize: 13.5, fontWeight: 650, color: 'var(--sd-fg-1, #e8e8ee)' }}>{title}</span>
60
+ <span style={{ marginLeft: 'auto', fontSize: 13, color: 'var(--sd-fg-3, #8b9a9a)', fontVariantNumeric: 'tabular-nums' }}>
61
+ <b style={{ fontSize: 17, color: 'var(--sd-fg-1, #fff)' }}>{count(used)}</b>{of ? ` ${of}` : ''}
62
+ </span>
63
+ </div>
64
+ <div style={{ position: 'relative', height: 10, borderRadius: 5, marginTop: 7, background: 'rgba(var(--sd-ink, 255, 255, 255), 0.07)' }}>
65
+ {band && (
66
+ <div title={band.title} style={{
67
+ position: 'absolute', top: 0, bottom: 0, left: at(band.from, max), width: `calc(${at(band.to, max)} - ${at(band.from, max)})`,
68
+ background: 'repeating-linear-gradient(135deg, rgba(255,215,0,0.28) 0 4px, rgba(255,215,0,0.08) 4px 8px)',
69
+ }} />
70
+ )}
71
+ <div style={{
72
+ position: 'absolute', top: 0, bottom: 0, left: 0, width: Number.isFinite(used) ? at(used, max) : 0,
73
+ borderRadius: 5, background: color, transition: 'width 0.4s ease',
74
+ }} />
75
+ {ticks.map((t) => (
76
+ <div key={t.at} title={t.title} style={{
77
+ position: 'absolute', top: -3, bottom: -3, left: at(t.at, max), width: 2, marginLeft: -1, borderRadius: 1,
78
+ background: t.color || 'rgba(var(--sd-ink, 255, 255, 255), 0.55)',
79
+ }} />
80
+ ))}
81
+ </div>
82
+ {(ticks.length > 0 || band) && (
83
+ <div aria-hidden="true" style={{ position: 'relative', height: 16, marginTop: 3, fontSize: 10.5, color: 'var(--sd-fg-4, #778)', fontVariantNumeric: 'tabular-nums' }}>
84
+ {/* The shaded range's ends, where no mark already says the number */}
85
+ {(band ? [band.from, band.to] : []).filter((n) => !ticks.some((t) => t.at === n))
86
+ .map((n) => ({ at: n, label: String(n), color: 'rgba(255,215,0,0.75)' }))
87
+ .concat(ticks).map((t) => {
88
+ const p = (t.at / max) * 100;
89
+ return (
90
+ <span key={t.at} style={{
91
+ position: 'absolute', left: `${Math.min(100, p)}%`, whiteSpace: 'nowrap', color: t.color || undefined,
92
+ transform: p > 94 ? 'translateX(-100%)' : p < 4 ? 'none' : 'translateX(-50%)',
93
+ }}>{t.label}</span>
94
+ );
95
+ })}
96
+ </div>
97
+ )}
98
+ <div style={{ fontSize: 12.5, color: 'var(--sd-fg-3, #8b9a9a)', lineHeight: 1.6, marginTop: 2 }}>{children}</div>
99
+ </div>
100
+ );
101
+ }
102
+
103
+ function Row({ label, children }) {
104
+ return (
105
+ <div style={{ display: 'flex', gap: '4px 16px', flexWrap: 'wrap', padding: '10px 0', borderTop: LINE, fontSize: 13 }}>
106
+ <span style={{ flex: '0 0 150px', color: 'var(--sd-fg-1, #e8e8ee)', fontWeight: 600 }}>{label}</span>
107
+ <span style={{ flex: '1 1 280px', color: 'var(--sd-fg-3, #8b9a9a)', lineHeight: 1.6 }}>{children}</span>
108
+ </div>
109
+ );
110
+ }
111
+
112
+ /** "in 2 h 5 min (Sat, Oct 3, 5:20 PM)" */
113
+ const whenAndUntil = (ms, now) => `${untilText(ms, now)} (${whenText(ms)})`;
114
+
115
+ export default function UsageSection() {
116
+ const [u, setU] = useState(null);
117
+ const [error, setError] = useState(null);
118
+ const [saving, setSaving] = useState(false);
119
+
120
+ const load = useCallback(() => fetch('/api/scraper?usage=1', { cache: 'no-store' })
121
+ .then((r) => r.json().then((d) => (r.ok && !d.error ? d : Promise.reject(new Error(d.error || 'The usage could not be read.')))))
122
+ .then((d) => { setU(d); setError(null); })
123
+ .catch((e) => setError(e.message)), []);
124
+
125
+ useEffect(() => {
126
+ load();
127
+ const timer = setInterval(load, REFRESH_MS);
128
+ return () => clearInterval(timer);
129
+ }, [load]);
130
+
131
+ const backToSafe = async () => {
132
+ setSaving(true);
133
+ try {
134
+ const r = await fetch('/api/scraper', {
135
+ method: 'POST', headers: { 'Content-Type': 'application/json' },
136
+ body: JSON.stringify({ action: 'set-limits', ...SAFE_LIMITS }),
137
+ });
138
+ if (!r.ok) throw new Error((await r.json().catch(() => ({}))).error || 'The budget could not be saved.');
139
+ await load();
140
+ } catch (e) {
141
+ setError(e.message);
142
+ } finally {
143
+ setSaving(false);
144
+ }
145
+ };
146
+
147
+ if (!u) {
148
+ return (
149
+ <Section id="usage" title="LinkedIn usage">
150
+ <Body>{error ? `${error}` : 'Counting…'}</Body>
151
+ </Section>
152
+ );
153
+ }
154
+
155
+ // The server's clock, the one the windows were counted on.
156
+ const now = u.now;
157
+ const { limits = {} } = u;
158
+ const day = u.searchesToday;
159
+ const level = usageLevel({ cooldown: u.cooldown, searchesDay: day, lastPushback: u.lastPushback, searchesSincePushback: u.searchesSincePushback, now });
160
+ // The level's warning, then the budget's own when it invites trouble whatever has been
161
+ // used; the 373 said once between them (lib/usage.js warningParts).
162
+ const warnings = warningParts(level, { searchesDay: day, cooldown: u.cooldown, lastPushback: u.lastPushback, now }, limits);
163
+ const aboveSafe = limits.daily > SAFE_LIMITS.daily || limits.monthly === 0 || limits.monthly > SAFE_LIMITS.monthly;
164
+ const left = estimate({ leftDay: u.leftToday, leftMonth: u.leftMonth, paused: Boolean(u.cooldown) });
165
+ const pace = paceOf(limits.pace);
166
+ const push = u.lastPushback;
167
+
168
+ // The 24-hour bar's colour is its count's own level, so a pause elsewhere doesn't redden it.
169
+ const dayLevel = usageLevel({ searchesDay: day });
170
+ const dayTicks = [
171
+ { at: SAFE_LIMITS.daily, label: String(SAFE_LIMITS.daily), title: 'The default budget' },
172
+ { at: RISKY_DAILY, label: String(RISKY_DAILY), title: 'Above this is risky', color: '#FF8C42' },
173
+ { at: RESTRICTED_AT, label: String(RESTRICTED_AT), title: 'A real account was restricted here', color: '#ff6b6b' },
174
+ ];
175
+ if (limits.daily && !dayTicks.some((t) => t.at === limits.daily)) {
176
+ dayTicks.push({ at: limits.daily, label: `${limits.daily} yours`, title: 'Your daily budget', color: 'var(--sd-blue, #3498DB)' });
177
+ }
178
+ const dayMax = barMax(day, dayTicks.map((t) => t.at));
179
+
180
+ const month = u.searchesMonth;
181
+ const monthTicks = limits.monthly ? [{ at: limits.monthly, label: `${limits.monthly} yours`, title: 'Your monthly budget', color: 'var(--sd-blue, #3498DB)' }] : [];
182
+ const monthMax = barMax(month, [REPORTED_MONTH[1], limits.monthly || 0]);
183
+ const monthColor = limits.monthly && month >= limits.monthly ? '#ff6b6b' : month >= REPORTED_MONTH[0] ? '#FFD700' : '#3498DB';
184
+
185
+ const week = u.searchesWeek;
186
+ const weekMax = barMax(week, [AUTO.week]);
187
+
188
+ const views = u.profilesToday;
189
+ const viewsMax = Math.max(limits.profiles || 1, Number(views) || 0);
190
+
191
+ return (
192
+ <Section id="usage" title="LinkedIn usage">
193
+ <div style={{ display: 'flex', alignItems: 'center', gap: 12, flexWrap: 'wrap' }}>
194
+ <Pill level={level} />
195
+ <span style={{ fontSize: 13, color: 'var(--sd-fg-3, #8b9a9a)', flex: '1 1 260px', lineHeight: 1.5 }}>
196
+ What Six Degrees has asked of your LinkedIn account from this computer, and how close that is to the line.
197
+ </span>
198
+ </div>
199
+
200
+ {warnings.length > 0 && (
201
+ <div style={{
202
+ marginTop: 14, padding: '11px 14px', borderRadius: 8, fontSize: 13, lineHeight: 1.6,
203
+ color: 'var(--sd-fg-2, #e3d9c4)', background: `${(LEVELS[level] || LEVELS.unknown).color}14`,
204
+ border: `1px solid ${(LEVELS[level] || LEVELS.unknown).color}55`,
205
+ }}>
206
+ {warnings.map((text, i) => <div key={i} style={{ marginTop: i ? 6 : 0 }}>{text}</div>)}
207
+ {aboveSafe && (
208
+ <button onClick={backToSafe} disabled={saving} style={{
209
+ marginTop: 9, padding: '6px 12px', borderRadius: 7, fontSize: 12.5, fontWeight: 650,
210
+ cursor: saving ? 'not-allowed' : 'pointer', background: 'rgba(255,215,0,0.08)',
211
+ color: 'var(--sd-gold, #FFD700)', border: '1px solid rgba(255,215,0,0.4)',
212
+ }}>{saving ? 'Saving…' : `Back to ${SAFE_LIMITS.daily} a day, ${SAFE_LIMITS.monthly} a month`}</button>
213
+ )}
214
+ </div>
215
+ )}
216
+ {error && <Body style={{ color: 'var(--sd-red, #ff7676)' }}>{error}</Body>}
217
+
218
+ <Meter title="Searches in the last 24 hours" used={day} of={limits.daily ? `of ${limits.daily} a day` : 'no daily cap'}
219
+ max={dayMax} color={(LEVELS[dayLevel] || LEVELS.unknown).color} ticks={dayTicks}>
220
+ {u.unreadable ? null : limits.daily
221
+ ? (u.dayFreesAt
222
+ ? <>Your {limits.daily} a day are used. The next one frees {whenAndUntil(u.dayFreesAt, now)}.</>
223
+ : <>{plural(u.leftToday, 'search', 'searches')} left under your budget{u.cooldown ? ', once the pause ends' : ''}.</>)
224
+ : <>No daily cap is set, so only the monthly one stops a scan.</>}
225
+ {u.dayClearAt && <> All clear {whenAndUntil(u.dayClearAt, now)}, when the newest of these turns 24 hours old.</>}
226
+ <div style={small}>
227
+ {SAFE_LIMITS.daily} is the default budget. Over {RISKY_DAILY} is risky: the budget picker asks first.
228
+ {' '}{RESTRICTED_AT} is where a real account was restricted, on Sep 28, 2026, with searches run back to back.
229
+ {' '}{DANGER_AT} (60% of that) or more shows as too close.
230
+ </div>
231
+ </Meter>
232
+
233
+ <Meter title="Searches this month" used={month} of={limits.monthly ? `of ${limits.monthly} a month` : 'no monthly cap'}
234
+ max={monthMax} color={monthColor} ticks={monthTicks}
235
+ band={{ from: REPORTED_MONTH[0], to: REPORTED_MONTH[1], title: 'The range people report for a free account' }}>
236
+ LinkedIn&rsquo;s month resets {pacificText(u.monthResets)} ({whenText(u.monthResets)} here).
237
+ {!limits.monthly ? <> No monthly cap is set (Premium).</>
238
+ : Number.isFinite(u.leftMonth) && <> {plural(u.leftMonth, 'search', 'searches')} left under your budget.</>}
239
+ <div style={small}>
240
+ The shaded {REPORTED_MONTH[0]} to {REPORTED_MONTH[1]} is the range people report for a free account&rsquo;s
241
+ monthly search limit. LinkedIn doesn&rsquo;t publish one, so it&rsquo;s a guide, not a fact.
242
+ Every page of someone&rsquo;s connections is one search.
243
+ </div>
244
+ </Meter>
245
+
246
+ <Meter title="Searches in the last 7 days" used={week} of={`against Auto scan's ${AUTO.week}`}
247
+ max={weekMax} color={week >= AUTO.week ? '#FFD700' : '#3498DB'}
248
+ ticks={[{ at: AUTO.week, label: String(AUTO.week), title: 'Auto scan stops here' }]}>
249
+ Auto scan stops at {AUTO.week} in any 7 days. A scan you start yourself stops only at your daily and monthly budget.
250
+ </Meter>
251
+
252
+ <Meter title="Profile views in the last 24 hours" used={views} of={`of ${limits.profiles} a day`}
253
+ max={viewsMax} color={views >= limits.profiles ? '#ff6b6b' : '#9B59B6'}>
254
+ {u.profilesFreeAt
255
+ ? <>Your {limits.profiles} a day are used. The next one frees {whenAndUntil(u.profilesFreeAt, now)}.</>
256
+ : Number.isFinite(views) && <>{plural(u.profilesLeftToday, 'view', 'views')} left.</>}
257
+ <div style={small}>
258
+ Each circle scan opens the person&rsquo;s profile once. Profile views are what got an account restricted on
259
+ Sep 9, 2026, after about 20 to 25 in an hour; at {pace.label} the scanner opens at most one every {pace.profileGap} seconds.
260
+ </div>
261
+ </Meter>
262
+
263
+ <div style={{ marginTop: 22 }}>
264
+ <Row label="Speed">
265
+ {pace.label}: about {searchesPerHour(limits.pace)} searches an hour at most while a scan runs.
266
+ {Number.isFinite(u.searchesLastHour) && <> In the last hour: {plural(u.searchesLastHour, 'search', 'searches')}.</>}
267
+ {' '}<Link href="/setup" style={link}>Change it on the Scan page</Link>
268
+ </Row>
269
+ <Row label="Can still map">
270
+ {u.unreadable
271
+ ? <>Can&rsquo;t tell until the record of searches can be read.</>
272
+ : !left
273
+ ? <>No cap is set, so there&rsquo;s no count of what&rsquo;s left.</>
274
+ : u.cooldown
275
+ ? <>No one until the pause ends.</>
276
+ : left.searches === 0
277
+ ? <>No one for now: your {left.by === 'day' ? 'daily' : 'monthly'} budget is used.</>
278
+ : <>
279
+ About {count(left.people)} people: {plural(left.searches, 'search', 'searches')} left under your
280
+ {' '}{left.by === 'day' ? 'daily' : 'monthly'} budget, at about {PEOPLE_PER_SEARCH} people a search.
281
+ <span style={{ color: 'var(--sd-fg-4, #778)' }}> An estimate: a page of results shows up to 10 people, and the last page of a list is usually short.</span>
282
+ </>}
283
+ </Row>
284
+ <Row label="Last pushback">
285
+ {!push
286
+ ? <>None on record on this computer.</>
287
+ : <>
288
+ {push.at ? <>{whenText(push.at)} ({agoText(push.at, now)}): </> : null}{push.reason}.
289
+ {push.active && <> Scanning is paused until {whenText(push.pausedUntil)}.</>}
290
+ {push.liftedAt && <> You lifted the pause {whenText(push.liftedAt)}; it would have run until {whenText(push.pausedUntil)}.</>}
291
+ {!push.active && !push.liftedAt && push.pausedUntil && <> The pause ended {whenText(push.pausedUntil)}.</>}
292
+ {u.searchesSincePushback > 0 && <> {plural(u.searchesSincePushback, 'search', 'searches')} since.</>}
293
+ </>}
294
+ </Row>
295
+ <Row label="Auto scan">
296
+ However high your budget is set, Auto scan keeps under its own limits: {AUTO.day} searches in any 24 hours,
297
+ {' '}{AUTO.week} in any 7 days, only from {hoursText(AUTO.hours)} on this computer&rsquo;s clock,
298
+ {' '}{AUTO.sittingRest === 3600 ? 'an hour’s rest' : `a ${AUTO.sittingRest / 60}-minute rest`} after every {AUTO.sitting} searches,
299
+ {' '}and {AUTO.pushbackRest / 86400} days off after any check from LinkedIn.
300
+ </Row>
301
+ </div>
302
+
303
+ <div style={{ ...small, marginTop: 14, paddingTop: 12, borderTop: LINE }}>
304
+ Where these numbers come from: Six Degrees writes down every search and profile view it makes on your
305
+ LinkedIn account, on this computer, and counts them here. Searches you make yourself on linkedin.com
306
+ aren&rsquo;t in it, and LinkedIn shows no count of its own. The {RESTRICTED_AT} searches and the 20 to 25
307
+ profile views are what happened to one real account, not safe limits. Change the budget on the
308
+ {' '}<Link href="/setup" style={link}>Scan page</Link>, under Fine-tune the scanner. Nothing here is sent anywhere.
309
+ {' '}Counted {whenText(now)}.
310
+ </div>
311
+ </Section>
312
+ );
313
+ }