six-degrees 0.5.0 → 0.6.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 (366) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/build-manifest.json +3 -3
  3. package/.next/standalone/.next/prerender-manifest.json +14 -14
  4. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  5. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  6. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  7. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  8. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  9. package/.next/standalone/.next/server/app/_not-found/page.js +1 -1
  10. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  11. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  12. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  13. package/.next/standalone/.next/server/app/_not-found.rsc +20 -19
  14. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +20 -19
  15. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +16 -15
  16. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  17. package/.next/standalone/.next/server/app/api/admin-delete/route.js.nft.json +1 -1
  18. package/.next/standalone/.next/server/app/api/admin-update/route.js.nft.json +1 -1
  19. package/.next/standalone/.next/server/app/api/bridges/route.js.nft.json +1 -1
  20. package/.next/standalone/.next/server/app/api/bulk-import/route.js.nft.json +1 -1
  21. package/.next/standalone/.next/server/app/api/company-scores/legacy/route.js.nft.json +1 -1
  22. package/.next/standalone/.next/server/app/api/company-scores/route.js.nft.json +1 -1
  23. package/.next/standalone/.next/server/app/api/connections/route.js.nft.json +1 -1
  24. package/.next/standalone/.next/server/app/api/data/export/route.js.nft.json +1 -1
  25. package/.next/standalone/.next/server/app/api/data/import/route.js.nft.json +1 -1
  26. package/.next/standalone/.next/server/app/api/data/restart/route.js.nft.json +1 -1
  27. package/.next/standalone/.next/server/app/api/data/reveal/route.js.nft.json +1 -1
  28. package/.next/standalone/.next/server/app/api/data/route.js.nft.json +1 -1
  29. package/.next/standalone/.next/server/app/api/delete-cluster/route.js.nft.json +1 -1
  30. package/.next/standalone/.next/server/app/api/ingest/route.js.nft.json +1 -1
  31. package/.next/standalone/.next/server/app/api/network/route.js.nft.json +1 -1
  32. package/.next/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  33. package/.next/standalone/.next/server/app/api/outreach/route.js.nft.json +1 -1
  34. package/.next/standalone/.next/server/app/api/queue/route.js.nft.json +1 -1
  35. package/.next/standalone/.next/server/app/api/scraper/route.js.nft.json +1 -1
  36. package/.next/standalone/.next/server/app/api/settings/route.js.nft.json +1 -1
  37. package/.next/standalone/.next/server/app/api/settings/sector-preview/route.js.nft.json +1 -1
  38. package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route.js.nft.json +1 -1
  39. package/.next/standalone/.next/server/app/api/setup-profile/route.js.nft.json +1 -1
  40. package/.next/standalone/.next/server/app/api/social/crm/route.js.nft.json +1 -1
  41. package/.next/standalone/.next/server/app/api/social/messages/route.js.nft.json +1 -1
  42. package/.next/standalone/.next/server/app/api/social/route.js.nft.json +1 -1
  43. package/.next/standalone/.next/server/app/api/unlock/route.js.nft.json +1 -1
  44. package/.next/standalone/.next/server/app/api/update/route.js +1 -1
  45. package/.next/standalone/.next/server/app/api/update/route.js.nft.json +1 -1
  46. package/.next/standalone/.next/server/app/api/update-images/route.js.nft.json +1 -1
  47. package/.next/standalone/.next/server/app/api/users/route.js.nft.json +1 -1
  48. package/.next/standalone/.next/server/app/avatars/[file]/route.js.nft.json +1 -1
  49. package/.next/standalone/.next/server/app/import/page.js +1 -1
  50. package/.next/standalone/.next/server/app/import/page.js.nft.json +1 -1
  51. package/.next/standalone/.next/server/app/import/page_client-reference-manifest.js +1 -1
  52. package/.next/standalone/.next/server/app/import.html +1 -1
  53. package/.next/standalone/.next/server/app/import.rsc +24 -23
  54. package/.next/standalone/.next/server/app/import.segments/_full.segment.rsc +24 -23
  55. package/.next/standalone/.next/server/app/import.segments/_tree.segment.rsc +2 -2
  56. package/.next/standalone/.next/server/app/import.segments/import/__PAGE__.segment.rsc +18 -17
  57. package/.next/standalone/.next/server/app/index.html +1 -1
  58. package/.next/standalone/.next/server/app/index.rsc +22 -21
  59. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +18 -17
  60. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +22 -21
  61. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  62. package/.next/standalone/.next/server/app/launch/page.js +1 -1
  63. package/.next/standalone/.next/server/app/launch/page.js.nft.json +1 -1
  64. package/.next/standalone/.next/server/app/launch/page_client-reference-manifest.js +1 -1
  65. package/.next/standalone/.next/server/app/launch.html +2 -2
  66. package/.next/standalone/.next/server/app/launch.rsc +24 -23
  67. package/.next/standalone/.next/server/app/launch.segments/_full.segment.rsc +24 -23
  68. package/.next/standalone/.next/server/app/launch.segments/_tree.segment.rsc +2 -2
  69. package/.next/standalone/.next/server/app/launch.segments/launch/__PAGE__.segment.rsc +18 -17
  70. package/.next/standalone/.next/server/app/page.js +1 -1
  71. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  72. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  73. package/.next/standalone/.next/server/app/paths/page.js +1 -1
  74. package/.next/standalone/.next/server/app/paths/page.js.nft.json +1 -1
  75. package/.next/standalone/.next/server/app/paths/page_client-reference-manifest.js +1 -1
  76. package/.next/standalone/.next/server/app/paths.html +1 -1
  77. package/.next/standalone/.next/server/app/paths.rsc +24 -23
  78. package/.next/standalone/.next/server/app/paths.segments/_full.segment.rsc +24 -23
  79. package/.next/standalone/.next/server/app/paths.segments/_tree.segment.rsc +2 -2
  80. package/.next/standalone/.next/server/app/paths.segments/paths/__PAGE__.segment.rsc +18 -17
  81. package/.next/standalone/.next/server/app/profile/page.js +1 -1
  82. package/.next/standalone/.next/server/app/profile/page.js.nft.json +1 -1
  83. package/.next/standalone/.next/server/app/profile/page_client-reference-manifest.js +1 -1
  84. package/.next/standalone/.next/server/app/profile.html +1 -1
  85. package/.next/standalone/.next/server/app/profile.rsc +24 -23
  86. package/.next/standalone/.next/server/app/profile.segments/_full.segment.rsc +24 -23
  87. package/.next/standalone/.next/server/app/profile.segments/_tree.segment.rsc +2 -2
  88. package/.next/standalone/.next/server/app/profile.segments/profile/__PAGE__.segment.rsc +18 -17
  89. package/.next/standalone/.next/server/app/queue/page.js +1 -1
  90. package/.next/standalone/.next/server/app/queue/page.js.nft.json +1 -1
  91. package/.next/standalone/.next/server/app/queue/page_client-reference-manifest.js +1 -1
  92. package/.next/standalone/.next/server/app/queue.html +1 -1
  93. package/.next/standalone/.next/server/app/queue.rsc +24 -23
  94. package/.next/standalone/.next/server/app/queue.segments/_full.segment.rsc +24 -23
  95. package/.next/standalone/.next/server/app/queue.segments/_tree.segment.rsc +2 -2
  96. package/.next/standalone/.next/server/app/queue.segments/queue/__PAGE__.segment.rsc +18 -17
  97. package/.next/standalone/.next/server/app/scores/page.js +1 -1
  98. package/.next/standalone/.next/server/app/scores/page.js.nft.json +1 -1
  99. package/.next/standalone/.next/server/app/scores/page_client-reference-manifest.js +1 -1
  100. package/.next/standalone/.next/server/app/scores.html +1 -1
  101. package/.next/standalone/.next/server/app/scores.rsc +24 -23
  102. package/.next/standalone/.next/server/app/scores.segments/_full.segment.rsc +24 -23
  103. package/.next/standalone/.next/server/app/scores.segments/_tree.segment.rsc +2 -2
  104. package/.next/standalone/.next/server/app/scores.segments/scores/__PAGE__.segment.rsc +18 -17
  105. package/.next/standalone/.next/server/app/settings/page.js +1 -1
  106. package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
  107. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  108. package/.next/standalone/.next/server/app/settings.html +1 -1
  109. package/.next/standalone/.next/server/app/settings.rsc +24 -23
  110. package/.next/standalone/.next/server/app/settings.segments/_full.segment.rsc +24 -23
  111. package/.next/standalone/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
  112. package/.next/standalone/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +18 -17
  113. package/.next/standalone/.next/server/app/setup/page.js +1 -1
  114. package/.next/standalone/.next/server/app/setup/page.js.nft.json +1 -1
  115. package/.next/standalone/.next/server/app/setup/page_client-reference-manifest.js +1 -1
  116. package/.next/standalone/.next/server/app/setup.html +1 -1
  117. package/.next/standalone/.next/server/app/setup.rsc +24 -23
  118. package/.next/standalone/.next/server/app/setup.segments/_full.segment.rsc +24 -23
  119. package/.next/standalone/.next/server/app/setup.segments/_tree.segment.rsc +2 -2
  120. package/.next/standalone/.next/server/app/setup.segments/setup/__PAGE__.segment.rsc +18 -17
  121. package/.next/standalone/.next/server/app/social/page.js +1 -1
  122. package/.next/standalone/.next/server/app/social/page.js.nft.json +1 -1
  123. package/.next/standalone/.next/server/app/social/page_client-reference-manifest.js +1 -1
  124. package/.next/standalone/.next/server/app/social.html +1 -1
  125. package/.next/standalone/.next/server/app/social.rsc +24 -23
  126. package/.next/standalone/.next/server/app/social.segments/_full.segment.rsc +24 -23
  127. package/.next/standalone/.next/server/app/social.segments/_tree.segment.rsc +2 -2
  128. package/.next/standalone/.next/server/app/social.segments/social/__PAGE__.segment.rsc +18 -17
  129. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0-rnla2._.js +1 -1
  130. package/.next/standalone/.next/server/chunks/[root-of-the-server]__00la_y0._.js +1 -1
  131. package/.next/standalone/.next/server/chunks/[root-of-the-server]__05_3-22._.js +1 -1
  132. package/.next/standalone/.next/server/chunks/[root-of-the-server]__07t47cm._.js +1 -1
  133. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0cj5jqc._.js +1 -1
  134. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0e0fei3._.js +1 -1
  135. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ljnyho._.js +1 -1
  136. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o5-tcg._.js +1 -1
  137. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0qrnous._.js +1 -1
  138. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0t3v1a1._.js +1 -1
  139. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0um1uey._.js +1 -1
  140. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0wmexuc._.js +1 -1
  141. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0xu34sz._.js +1 -1
  142. package/.next/standalone/.next/server/chunks/[root-of-the-server]__133knx1._.js +1 -1
  143. package/.next/standalone/.next/server/chunks/[root-of-the-server]__13dx4sd._.js +1 -1
  144. package/.next/standalone/.next/server/chunks/[root-of-the-server]__14ou7j5._.js +1 -1
  145. package/.next/standalone/.next/server/chunks/[root-of-the-server]__15-17hl._.js +1 -1
  146. package/.next/standalone/.next/server/chunks/[root-of-the-server]__15wc9e-._.js +1 -1
  147. package/.next/standalone/.next/server/chunks/[root-of-the-server]__16iu0hv._.js +1 -1
  148. package/.next/standalone/.next/server/chunks/[root-of-the-server]__18bcnu4._.js +3 -0
  149. package/.next/standalone/.next/server/chunks/[root-of-the-server]__19b7mig._.js +1 -1
  150. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1bbcwub._.js +2 -2
  151. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1eris29._.js +1 -1
  152. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1gjo_cq._.js +1 -1
  153. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1kbl21f._.js +1 -1
  154. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1qcm08_._.js +1 -1
  155. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1rphsdk._.js +1 -1
  156. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1tir0vc._.js +2 -2
  157. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1w25q0m._.js +1 -1
  158. package/.next/standalone/.next/server/chunks/[root-of-the-server]__20rwfdw._.js +2 -2
  159. package/.next/standalone/.next/server/chunks/_1_fynia._.js +7 -7
  160. package/.next/standalone/.next/server/chunks/_1itd1o_._.js +2 -2
  161. package/.next/standalone/.next/server/chunks/lib_0851sk0._.js +5 -5
  162. package/.next/standalone/.next/server/chunks/lib_1q7p2ro._.js +5 -5
  163. package/.next/standalone/.next/server/chunks/lib_1r6l86l._.js +5 -5
  164. package/.next/standalone/.next/server/chunks/lib_db-client_15le7cw.js +9 -9
  165. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__08oxiqh._.js +3 -0
  166. package/.next/standalone/.next/server/chunks/ssr/_03l7vge._.js +1 -1
  167. package/.next/standalone/.next/server/chunks/ssr/_08g31gm._.js +3 -0
  168. package/.next/standalone/.next/server/chunks/ssr/_0gk_ofx._.js +3 -0
  169. package/.next/standalone/.next/server/chunks/ssr/_0nwsf93._.js +3 -0
  170. package/.next/standalone/.next/server/chunks/ssr/_0vho1lb._.js +3 -0
  171. package/.next/standalone/.next/server/chunks/ssr/{_0jdkqgi._.js → _1-658fq._.js} +2 -2
  172. package/.next/standalone/.next/server/chunks/ssr/_1bc46kz._.js +3 -0
  173. package/.next/standalone/.next/server/chunks/ssr/_1f_n00p._.js +3 -0
  174. package/.next/standalone/.next/server/chunks/ssr/_1fm1ih_._.js +9 -0
  175. package/.next/standalone/.next/server/chunks/ssr/_1k2nmbw._.js +9 -0
  176. package/.next/standalone/.next/server/chunks/ssr/_2105jz8._.js +3 -0
  177. package/.next/standalone/.next/server/chunks/ssr/app_141w189._.js +1 -1
  178. package/.next/standalone/.next/server/chunks/ssr/app_components_0t908t-._.js +3 -0
  179. package/.next/standalone/.next/server/chunks/ssr/app_components_0uuff77._.js +13 -0
  180. package/.next/standalone/.next/server/chunks/ssr/app_components_1j3q-h5._.js +13 -0
  181. package/.next/standalone/.next/server/chunks/ssr/{_0gtv9jb._.js → app_components_CompanyScores_1g0mytz.js} +2 -2
  182. package/.next/standalone/.next/server/chunks/ssr/app_components_settings_SectorPicker_1c-29qw.js +1 -1
  183. package/.next/standalone/.next/server/chunks/ssr/app_import_page_1fmu6_l.js +1 -1
  184. package/.next/standalone/.next/server/chunks/ssr/app_page_1fazqbf.js +14 -12
  185. package/.next/standalone/.next/server/chunks/ssr/app_paths_page_1ol90m7.js +2 -2
  186. package/.next/standalone/.next/server/chunks/ssr/app_profile_page_0u3-l5y.js +1 -1
  187. package/.next/standalone/.next/server/chunks/ssr/app_queue_page_0c6znd6.js +6 -6
  188. package/.next/standalone/.next/server/chunks/ssr/app_settings_page_1f8mjj_.js +1 -1
  189. package/.next/standalone/.next/server/chunks/ssr/app_setup_page_1-282zx.js +4 -4
  190. package/.next/standalone/.next/server/chunks/ssr/app_social_page_0h7zxda.js +1 -1
  191. package/.next/standalone/.next/server/chunks/ssr/{lib_0i8v-s3._.js → lib_1c4ieuw._.js} +2 -2
  192. package/.next/standalone/.next/server/chunks/ssr/lib_galaxy-lab_108_lu-.js +1 -1
  193. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  194. package/.next/standalone/.next/server/middleware-manifest.json +5 -5
  195. package/.next/standalone/.next/server/pages/404.html +1 -1
  196. package/.next/standalone/.next/server/pages/500.html +1 -1
  197. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  198. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  199. package/.next/standalone/.next/static/chunks/02pq76u7y4v9-.js +22 -0
  200. package/.next/standalone/.next/static/chunks/0cmq0exd4d0h9.js +1 -0
  201. package/.next/{static/chunks/2wgz9ietkqqe6.js → standalone/.next/static/chunks/0i02yxppzds1o.js} +1 -1
  202. package/.next/standalone/.next/static/chunks/0m_p4k-q2qh--.js +1 -0
  203. package/.next/standalone/.next/static/chunks/0oyslj62jkubd.js +1 -0
  204. package/.next/standalone/.next/static/chunks/{1x_ysly42-teq.css → 0vo-l8hxneba6.css} +1 -1
  205. package/.next/{static/chunks/3sowbvbaj1s6n.js → standalone/.next/static/chunks/0ws7zy0w57ufi.js} +1 -1
  206. package/.next/standalone/.next/static/chunks/0yh8z2tbrc5i_.js +1 -0
  207. package/.next/standalone/.next/static/chunks/172e10mi-tpo_.js +34 -0
  208. package/.next/standalone/.next/static/chunks/1ei5vbe2uw6fl.js +1 -0
  209. package/.next/standalone/.next/static/chunks/1f7_pl_wq7lh3.js +11 -0
  210. package/.next/standalone/.next/static/chunks/1jzbe7zdx9vbj.js +2 -0
  211. package/.next/standalone/.next/static/chunks/1m3017gp790pw.js +45 -0
  212. package/.next/standalone/.next/static/chunks/1t20e8u0st7ep.js +1 -0
  213. package/.next/standalone/.next/static/chunks/2-ch9rm27eril.js +11 -0
  214. package/.next/standalone/.next/static/chunks/2ldv-v3s9yaif.js +1 -0
  215. package/.next/standalone/.next/static/chunks/3bp284gjf7dyq.js +1 -0
  216. package/.next/standalone/.next/static/chunks/3k1f6clbn3gj3.js +7 -0
  217. package/.next/standalone/.next/static/chunks/3l4t8je6iguzc.js +1 -0
  218. package/.next/standalone/.next/static/chunks/{0muwt9bykzr-1.js → 3tplzuc9jk-tl.js} +1 -1
  219. package/.next/standalone/.next/static/chunks/42m0bqr8pbovz.js +11 -0
  220. package/.next/standalone/CHANGELOG.md +61 -0
  221. package/.next/standalone/README.md +22 -8
  222. package/.next/standalone/app/api/scraper/route.js +40 -3
  223. package/.next/standalone/app/api/update/route.js +12 -6
  224. package/.next/standalone/app/components/AppHeader.js +257 -0
  225. package/.next/standalone/app/components/Avatar.js +2 -1
  226. package/.next/standalone/app/components/ChainView.js +12 -12
  227. package/.next/standalone/app/components/FilterPanel.js +20 -12
  228. package/.next/standalone/app/components/ForceGraph.js +163 -25
  229. package/.next/standalone/app/components/GalaxyLab.js +43 -12
  230. package/.next/standalone/app/components/GridView.js +4 -4
  231. package/.next/standalone/app/components/LinkedInLimits.js +2 -1
  232. package/.next/standalone/app/components/ListView.js +3 -3
  233. package/.next/standalone/app/components/NoteDetail.js +2 -1
  234. package/.next/standalone/app/components/OnboardingGate.js +2 -2
  235. package/.next/standalone/app/components/OutlinkQuest.js +2 -1
  236. package/.next/standalone/app/components/PathsAnalyzer.js +3 -2
  237. package/.next/standalone/app/components/PeopleMap.js +2 -1
  238. package/.next/standalone/app/components/RingsView.js +3 -3
  239. package/.next/standalone/app/components/ScanTrail.js +85 -0
  240. package/.next/standalone/app/components/SeparationView.js +100 -77
  241. package/.next/standalone/app/components/Sidebar.js +4 -4
  242. package/.next/standalone/app/components/TheirCircle.js +2 -1
  243. package/.next/standalone/app/components/ThemeLoader.js +9 -0
  244. package/.next/standalone/app/components/UpdatePanel.js +20 -2
  245. package/.next/standalone/app/components/settings/AppearanceSection.js +226 -0
  246. package/.next/standalone/app/components/settings/NetworkHealthSection.js +2 -1
  247. package/.next/standalone/app/components/ui.js +2 -1
  248. package/.next/standalone/app/globals.css +70 -2
  249. package/.next/standalone/app/import/page.js +3 -3
  250. package/.next/standalone/app/layout.js +11 -2
  251. package/.next/standalone/app/page.js +69 -215
  252. package/.next/standalone/app/paths/page.js +8 -21
  253. package/.next/standalone/app/profile/page.js +11 -10
  254. package/.next/standalone/app/queue/page.js +8 -21
  255. package/.next/standalone/app/scores/page.js +1 -1
  256. package/.next/standalone/app/settings/page.js +7 -3
  257. package/.next/standalone/app/setup/page.js +83 -88
  258. package/.next/standalone/app/social/Crm.js +2 -1
  259. package/.next/standalone/app/social/SocialHub.js +2 -2
  260. package/.next/standalone/app/social/page.js +1 -1
  261. package/.next/standalone/lib/data-import.js +1 -0
  262. package/.next/standalone/lib/galaxy-export.js +2 -1
  263. package/.next/standalone/lib/galaxy-lab.js +24 -8
  264. package/.next/standalone/lib/level.js +51 -0
  265. package/.next/standalone/lib/release.js +13 -7
  266. package/.next/standalone/lib/scanner-python.js +38 -8
  267. package/.next/standalone/lib/scraper-client.js +2 -1
  268. package/.next/standalone/lib/separation.js +4 -2
  269. package/.next/standalone/lib/theme-store.js +61 -0
  270. package/.next/standalone/lib/themes.js +186 -0
  271. package/.next/standalone/lib/tiers.js +2 -8
  272. package/.next/standalone/package-lock.json +2 -2
  273. package/.next/standalone/package.json +4 -4
  274. package/.next/standalone/scripts/build-desktop.mjs +325 -0
  275. package/.next/standalone/scripts/build-site.mjs +85 -15
  276. package/.next/standalone/scripts/gen-test-network.mjs +93 -0
  277. package/.next/standalone/scripts/next.mjs +20 -0
  278. package/.next/standalone/scripts/readme_buttons.py +3 -0
  279. package/.next/standalone/scripts/requirements.txt +18 -1
  280. package/.next/standalone/scripts/site-news.mjs +54 -9
  281. package/.next/standalone/scripts/smoke-desktop.mjs +177 -0
  282. package/.next/standalone/scripts/windows/six-degrees.iss +100 -0
  283. package/.next/static/chunks/02pq76u7y4v9-.js +22 -0
  284. package/.next/static/chunks/0cmq0exd4d0h9.js +1 -0
  285. package/.next/{standalone/.next/static/chunks/2wgz9ietkqqe6.js → static/chunks/0i02yxppzds1o.js} +1 -1
  286. package/.next/static/chunks/0m_p4k-q2qh--.js +1 -0
  287. package/.next/static/chunks/0oyslj62jkubd.js +1 -0
  288. package/.next/static/chunks/{1x_ysly42-teq.css → 0vo-l8hxneba6.css} +1 -1
  289. package/.next/{standalone/.next/static/chunks/3sowbvbaj1s6n.js → static/chunks/0ws7zy0w57ufi.js} +1 -1
  290. package/.next/static/chunks/0yh8z2tbrc5i_.js +1 -0
  291. package/.next/static/chunks/172e10mi-tpo_.js +34 -0
  292. package/.next/static/chunks/1ei5vbe2uw6fl.js +1 -0
  293. package/.next/static/chunks/1f7_pl_wq7lh3.js +11 -0
  294. package/.next/static/chunks/1jzbe7zdx9vbj.js +2 -0
  295. package/.next/static/chunks/1m3017gp790pw.js +45 -0
  296. package/.next/static/chunks/1t20e8u0st7ep.js +1 -0
  297. package/.next/static/chunks/2-ch9rm27eril.js +11 -0
  298. package/.next/static/chunks/2ldv-v3s9yaif.js +1 -0
  299. package/.next/static/chunks/3bp284gjf7dyq.js +1 -0
  300. package/.next/static/chunks/3k1f6clbn3gj3.js +7 -0
  301. package/.next/static/chunks/3l4t8je6iguzc.js +1 -0
  302. package/.next/static/chunks/{0muwt9bykzr-1.js → 3tplzuc9jk-tl.js} +1 -1
  303. package/.next/static/chunks/42m0bqr8pbovz.js +11 -0
  304. package/CHANGELOG.md +61 -0
  305. package/README.md +22 -8
  306. package/lib/data-import.js +1 -0
  307. package/lib/galaxy-export.js +2 -1
  308. package/lib/galaxy-lab.js +24 -8
  309. package/lib/level.js +51 -0
  310. package/lib/release.js +13 -7
  311. package/lib/scanner-python.js +38 -8
  312. package/lib/scraper-client.js +2 -1
  313. package/lib/separation.js +4 -2
  314. package/lib/theme-store.js +61 -0
  315. package/lib/themes.js +186 -0
  316. package/lib/tiers.js +2 -8
  317. package/package.json +4 -4
  318. package/scripts/requirements.txt +18 -1
  319. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ljcioj._.js +0 -3
  320. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__16hs8kw._.js +0 -3
  321. package/.next/standalone/.next/server/chunks/ssr/_01kacen._.js +0 -3
  322. package/.next/standalone/.next/server/chunks/ssr/_0xi-fbs._.js +0 -3
  323. package/.next/standalone/.next/server/chunks/ssr/_0xmwmfv._.js +0 -3
  324. package/.next/standalone/.next/server/chunks/ssr/_1-b9hj7._.js +0 -9
  325. package/.next/standalone/.next/server/chunks/ssr/_112ewem._.js +0 -3
  326. package/.next/standalone/.next/server/chunks/ssr/_16ab63q._.js +0 -3
  327. package/.next/standalone/.next/server/chunks/ssr/_1fxm0-s._.js +0 -3
  328. package/.next/standalone/.next/server/chunks/ssr/_1ra1d3r._.js +0 -9
  329. package/.next/standalone/.next/server/chunks/ssr/app_components_ui_0pdmz2z.js +0 -3
  330. package/.next/standalone/.next/server/chunks/ssr/lib_13rapwj._.js +0 -3
  331. package/.next/standalone/.next/static/chunks/03bziijw5srol.js +0 -1
  332. package/.next/standalone/.next/static/chunks/0bgq8wmopl_ig.js +0 -7
  333. package/.next/standalone/.next/static/chunks/0ezus6p2eb-vg.js +0 -1
  334. package/.next/standalone/.next/static/chunks/0g_fy2034bp0x.js +0 -34
  335. package/.next/standalone/.next/static/chunks/0q5dru4q6gxl5.js +0 -22
  336. package/.next/standalone/.next/static/chunks/0w-byiwb2zax8.js +0 -2
  337. package/.next/standalone/.next/static/chunks/1g7jcovdejc9-.js +0 -1
  338. package/.next/standalone/.next/static/chunks/1i51yylxdzht1.js +0 -1
  339. package/.next/standalone/.next/static/chunks/1zf8swaasjf1e.js +0 -43
  340. package/.next/standalone/.next/static/chunks/2dwtoszeq91us.js +0 -1
  341. package/.next/standalone/.next/static/chunks/2rqtpccruavf2.js +0 -1
  342. package/.next/standalone/.next/static/chunks/30x3oq_st7a5r.js +0 -1
  343. package/.next/standalone/.next/static/chunks/355ryio1b7sm1.js +0 -1
  344. package/.next/standalone/.next/static/chunks/3ap5hgma7n0o7.js +0 -1
  345. package/.next/standalone/.next/static/chunks/3fci6qi39-1n5.js +0 -1
  346. package/.next/static/chunks/03bziijw5srol.js +0 -1
  347. package/.next/static/chunks/0bgq8wmopl_ig.js +0 -7
  348. package/.next/static/chunks/0ezus6p2eb-vg.js +0 -1
  349. package/.next/static/chunks/0g_fy2034bp0x.js +0 -34
  350. package/.next/static/chunks/0q5dru4q6gxl5.js +0 -22
  351. package/.next/static/chunks/0w-byiwb2zax8.js +0 -2
  352. package/.next/static/chunks/1g7jcovdejc9-.js +0 -1
  353. package/.next/static/chunks/1i51yylxdzht1.js +0 -1
  354. package/.next/static/chunks/1zf8swaasjf1e.js +0 -43
  355. package/.next/static/chunks/2dwtoszeq91us.js +0 -1
  356. package/.next/static/chunks/2rqtpccruavf2.js +0 -1
  357. package/.next/static/chunks/30x3oq_st7a5r.js +0 -1
  358. package/.next/static/chunks/355ryio1b7sm1.js +0 -1
  359. package/.next/static/chunks/3ap5hgma7n0o7.js +0 -1
  360. package/.next/static/chunks/3fci6qi39-1n5.js +0 -1
  361. /package/.next/standalone/.next/static/{I-cj79yE2IZ8taX2dZGp3 → dQUvvVSXqbkEFC3-CNcwT}/_buildManifest.js +0 -0
  362. /package/.next/standalone/.next/static/{I-cj79yE2IZ8taX2dZGp3 → dQUvvVSXqbkEFC3-CNcwT}/_clientMiddlewareManifest.js +0 -0
  363. /package/.next/standalone/.next/static/{I-cj79yE2IZ8taX2dZGp3 → dQUvvVSXqbkEFC3-CNcwT}/_ssgManifest.js +0 -0
  364. /package/.next/static/{I-cj79yE2IZ8taX2dZGp3 → dQUvvVSXqbkEFC3-CNcwT}/_buildManifest.js +0 -0
  365. /package/.next/static/{I-cj79yE2IZ8taX2dZGp3 → dQUvvVSXqbkEFC3-CNcwT}/_clientMiddlewareManifest.js +0 -0
  366. /package/.next/static/{I-cj79yE2IZ8taX2dZGp3 → dQUvvVSXqbkEFC3-CNcwT}/_ssgManifest.js +0 -0
@@ -41,9 +41,10 @@ import useRequests from './useRequests';
41
41
  import { initialsFor } from '../../lib/tiers';
42
42
  import { watchNotchShown, notchShownNow, noNotch } from '../../lib/island';
43
43
  import Avatar from './Avatar';
44
+ import { TIER_COLORS as THEME_TIERS } from '../../lib/themes';
44
45
 
45
46
  const ORANGE = '#FF6B35';
46
- const CLASSIC = { S: '#FFD700', A: '#9B59B6', B: '#3498DB', C: '#95A5A6', D: '#BDC3C7' };
47
+ const CLASSIC = THEME_TIERS; // the theme's dot colours (lib/themes.js)
47
48
  const CANT_NAME = 'a connection we can’t name';
48
49
  // The fixed Filters (left:16) and Details (right:16) pills sit at viewport
49
50
  // top:140 — inside the header band on a desktop, in the controls row on a
@@ -243,7 +244,7 @@ export default function SeparationView({ connections = [], degree2 = [], fullDeg
243
244
  : summitLayout(top, cw || 800, isMobile, { cards })),
244
245
  [single, target, top, cw, isMobile, cards, rarityBy],
245
246
  );
246
- const captionH = isMobile ? 58 : 40; // fixed, so HEAD is arithmetic; the phone legend takes two lines
247
+ const captionH = isMobile ? 58 : 28; // fixed, so HEAD is arithmetic; the phone legend takes two lines, a computer's is the tooltip
247
248
  const NEXT_H = nextUp.length ? 38 : 0;
248
249
  const mapH = single ? (target ? layout.height + NEXT_H : 0) : layout.height;
249
250
  const mapBlockH = mapH ? captionH + mapH + 12 : 0;
@@ -305,24 +306,78 @@ export default function SeparationView({ connections = [], degree2 = [], fullDeg
305
306
  const youLabel = !userName || /^you$/i.test(String(userName).trim()) ? 'You' : initialsFor(userName);
306
307
  const rows = visible.slice(start, end);
307
308
 
309
+ // Where the slider is, in words (and in full, as its tooltip).
310
+ const pillEl = (
311
+ <span aria-live="polite" title={`${slide.name}. ${slide.detail} It only reorders: scores, tiers and ranks stay as they are.`} style={{
312
+ ...(isMobile ? { marginLeft: 'auto' } : {}), textTransform: 'none', letterSpacing: 0, flexShrink: 0, height: isMobile ? 40 : 26, padding: '0 12px', borderRadius: 15, boxSizing: 'border-box',
313
+ display: 'inline-flex', alignItems: 'center', gap: 7, fontSize: 12, fontWeight: 700, whiteSpace: 'nowrap',
314
+ border: `1px solid ${slideColor}66`, background: `${slideColor}14`, color: slideColor,
315
+ }}>
316
+ <span style={{ width: 7, height: 7, borderRadius: '50%', background: slideColor }} />
317
+ <span style={{ fontVariantNumeric: 'tabular-nums' }}>{at}</span>
318
+ {slide.name}
319
+ </span>
320
+ );
321
+ // The search, in the title's row on a computer and under it on a phone.
322
+ const searchBox = (
323
+ <input
324
+ ref={searchRef}
325
+ type="search"
326
+ value={query}
327
+ onChange={(e) => changeQuery(e.target.value)}
328
+ onKeyDown={onSearchKey}
329
+ placeholder={isMobile ? 'Search people, companies, or who knows them' : 'Search people, companies, who knows them'}
330
+ aria-label="Search people, companies, or who knows them"
331
+ style={{
332
+ width: isMobile ? '100%' : 300, flexShrink: 0, minWidth: 0, height: isMobile ? 44 : 32, boxSizing: 'border-box',
333
+ padding: '0 12px', borderRadius: 8, outline: 'none', color: '#fff',
334
+ fontSize: isMobile ? 16 : 13, // under 16px, iOS zooms the page on focus
335
+ border: '1px solid rgba(255,255,255,0.12)', background: 'rgba(255,255,255,0.05)',
336
+ }}
337
+ />
338
+ );
339
+ // "Only show": the rarity chips, beside the tiers on a computer, on their own row on a phone.
340
+ const rarityChips = (
341
+ <>
342
+ <span title={RARITY_NOTE} style={{ fontSize: 10, color: '#666', whiteSpace: 'nowrap', flexShrink: 0, textTransform: 'uppercase', letterSpacing: 0.5, cursor: 'help' }}>Only show</span>
343
+ {RARITY.map((r) => {
344
+ const on = rarities.has(r.key);
345
+ return (
346
+ <button key={r.key} type="button" aria-pressed={on} onClick={() => changeRarity(r.key)}
347
+ title={`${r.label}: ${r.range} mutual connection${r.range === '1' ? '' : 's'}. ${RARITY_NOTE}`} style={{
348
+ height: isMobile ? 40 : 28, padding: isMobile ? '0 10px' : '0 8px', borderRadius: 14, cursor: 'pointer', flexShrink: 0,
349
+ fontSize: 11.5, fontWeight: 700, whiteSpace: 'nowrap',
350
+ border: `1px solid ${on ? r.color : 'rgba(255,255,255,0.1)'}`,
351
+ background: on ? `${r.color}22` : 'rgba(255,255,255,0.03)',
352
+ color: on ? r.color : '#999',
353
+ }}>
354
+ {r.label}
355
+ <span style={{ marginLeft: 5, fontWeight: 500, color: on ? r.color : '#666', opacity: 0.85 }}>{fmt(byRarity[r.key])}</span>
356
+ </button>
357
+ );
358
+ })}
359
+ </>
360
+ );
361
+
308
362
  return (
309
363
  <div style={{
310
364
  flex: 1, minWidth: 0, display: 'flex', flexDirection: 'column',
311
- background: '#0a0a1a', color: '#fff', overflow: 'hidden',
365
+ background: 'var(--sd-page)', color: '#fff', overflow: 'hidden',
312
366
  }}>
313
367
  {/* ── Header: what this is, how many, and what it can't say ── */}
314
368
  <div style={{ padding: `${notch ? 48 : 14}px ${SIDE}px 8px`, flexShrink: 0 }}>
315
- <div style={{ display: 'flex', alignItems: 'baseline', gap: 10, flexWrap: 'wrap' }}>
316
- <h2 style={{
369
+ <div style={{ display: 'flex', alignItems: isMobile ? 'baseline' : 'center', gap: 10, flexWrap: isMobile ? 'wrap' : 'nowrap' }}>
370
+ <h2 title={RANK_NOTE} style={{
317
371
  margin: 0, fontSize: 18, fontWeight: 800,
318
372
  background: 'linear-gradient(135deg, #FFD700, #FF6B35)',
319
373
  WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent',
320
374
  }}>Separation</h2>
321
- <span style={{ fontSize: 12, color: '#aaa' }}>
375
+ <span style={{ fontSize: 12, color: '#aaa', ...(isMobile ? {} : { flex: 1, minWidth: 0, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }) }}>
322
376
  {isMobile
323
377
  ? `${plural(summary.people, 'person', 'people')} · ${fmt(summary.byTier.S)} S · ${fmt(summary.multi)} with 2+ ways`
324
378
  : `${plural(summary.people, 'person', 'people')} two steps away · ${fmt(summary.byTier.S)} S-tier · ${fmt(summary.multi)} reachable 2+ ways · through ${fmt(summary.bridges)} of your connections`}
325
379
  </span>
380
+ {!isMobile && searchBox}
326
381
  </div>
327
382
  {/* The whole population at a glance: one segment per tier, to scale. */}
328
383
  <div aria-hidden="true" style={{ display: 'flex', gap: 1, height: 6, borderRadius: 3, overflow: 'hidden', margin: '8px 0 6px', background: 'rgba(255,255,255,0.04)' }}>
@@ -330,11 +385,10 @@ export default function SeparationView({ connections = [], degree2 = [], fullDeg
330
385
  <div key={t} style={{ flex: summary.byTier[t], background: tierColors[t] || '#555' }} />
331
386
  ))}
332
387
  </div>
333
- <div style={{ fontSize: 11, color: '#777', lineHeight: 1.4 }}>
334
- {isMobile
335
- ? 'Ranks reachability, not people · lists scanned so far'
336
- : 'Ranked by each person’s own score (title, company, headline). It ranks reachability, not people. From the lists scanned so far.'}
337
- </div>
388
+ {/* On a computer the line says it on its own; what it ranks is the title's tooltip (RANK_NOTE). */}
389
+ {isMobile && (
390
+ <div style={{ fontSize: 11, color: '#777', lineHeight: 1.4 }}>Ranks reachability, not people · lists scanned so far</div>
391
+ )}
338
392
  {summary.peopleOnlyUnresolved > 0 && (
339
393
  <div style={{
340
394
  marginTop: 8, padding: '8px 10px', borderRadius: 8, fontSize: 11.5, lineHeight: 1.5, color: '#e8d9a0',
@@ -354,30 +408,16 @@ export default function SeparationView({ connections = [], degree2 = [], fullDeg
354
408
  {/* ── Controls: search, then the slider with their tier and rarity ── */}
355
409
  <div style={{ padding: `0 ${SIDE}px 10px`, flexShrink: 0, borderBottom: '1px solid rgba(255,255,255,0.06)' }}>
356
410
  <style>{SLIDER_CSS}</style>
357
- <input
358
- ref={searchRef}
359
- type="search"
360
- value={query}
361
- onChange={(e) => changeQuery(e.target.value)}
362
- onKeyDown={onSearchKey}
363
- placeholder="Search people, companies, or who knows them"
364
- aria-label="Search people, companies, or who knows them"
365
- style={{
366
- width: '100%', minWidth: 0, height: isMobile ? 44 : 34, boxSizing: 'border-box',
367
- padding: '0 12px', borderRadius: 8, outline: 'none', color: '#fff',
368
- fontSize: isMobile ? 16 : 13, // under 16px, iOS zooms the page on focus
369
- border: '1px solid rgba(255,255,255,0.12)', background: 'rgba(255,255,255,0.05)',
370
- }}
371
- />
411
+ {isMobile && searchBox}
372
412
  <div style={{
373
- marginTop: 8, padding: isMobile ? '8px 10px' : '8px 14px', borderRadius: 12, position: 'relative',
413
+ marginTop: isMobile ? 8 : 2, padding: isMobile ? '8px 10px' : '8px 14px', borderRadius: 12, position: 'relative',
374
414
  border: '1px solid rgba(255,255,255,0.08)', background: 'rgba(255,255,255,0.025)',
375
415
  }}>
376
416
  {pathOpen && (
377
417
  <PathPicker facets={facets} text={pathText} onText={setPathText} isMobile={isMobile}
378
418
  onPick={pickPath} onClose={() => setPathOpen(false)} />
379
419
  )}
380
- <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: isMobile ? 'nowrap' : 'wrap', minWidth: 0,
420
+ <div style={{ display: 'flex', alignItems: 'center', gap: isMobile ? 8 : 6, flexWrap: isMobile ? 'nowrap' : 'wrap', minWidth: 0,
381
421
  // A phone scrolls this strip sideways, so the page itself never does.
382
422
  overflowX: isMobile ? 'auto' : 'visible', scrollbarWidth: 'thin' }}>
383
423
  <span style={{ fontSize: 10, color: '#666', whiteSpace: 'nowrap', flexShrink: 0, textTransform: 'uppercase', letterSpacing: 0.5 }}>Their tier</span>
@@ -387,7 +427,7 @@ export default function SeparationView({ connections = [], degree2 = [], fullDeg
387
427
  const n = t === 'all' ? summary.people : summary.byTier[t];
388
428
  return (
389
429
  <button key={t} type="button" aria-pressed={on} onClick={() => changeTier(t)} style={{
390
- height: isMobile ? 40 : 30, padding: '0 10px', borderRadius: 15, cursor: 'pointer', flexShrink: 0,
430
+ height: isMobile ? 40 : 28, padding: isMobile ? '0 10px' : '0 8px', borderRadius: 14, cursor: 'pointer', flexShrink: 0,
391
431
  fontSize: 12, fontWeight: 700, whiteSpace: 'nowrap',
392
432
  border: `1px solid ${on ? c : 'rgba(255,255,255,0.1)'}`,
393
433
  background: on ? `${c === '#fff' ? '#ffffff' : c}22` : 'rgba(255,255,255,0.03)',
@@ -414,23 +454,19 @@ export default function SeparationView({ connections = [], degree2 = [], fullDeg
414
454
  }}>×</button>
415
455
  )}
416
456
  </span>
417
- {/* Where the slider is, in words */}
418
- <span aria-live="polite" style={{
419
- marginLeft: 'auto', flexShrink: 0, height: isMobile ? 40 : 30, padding: '0 12px', borderRadius: 15, boxSizing: 'border-box',
420
- display: 'inline-flex', alignItems: 'center', gap: 7, fontSize: 12, fontWeight: 700, whiteSpace: 'nowrap',
421
- border: `1px solid ${slideColor}66`, background: `${slideColor}14`, color: slideColor,
422
- }}>
423
- <span style={{ width: 7, height: 7, borderRadius: '50%', background: slideColor }} />
424
- <span style={{ fontVariantNumeric: 'tabular-nums' }}>{at}</span>
425
- {slide.name}
426
- </span>
457
+ {!isMobile && <>
458
+ <span aria-hidden="true" style={{ width: 1, height: 18, background: 'rgba(255,255,255,0.12)', margin: '0 2px' }} />
459
+ {rarityChips}
460
+ </>}
461
+ {isMobile && pillEl}
427
462
  </div>
428
463
 
429
464
  {/* The slider: the rarest ways in at one end, the easiest at the other, power alone in the middle */}
430
- <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginTop: 8, fontSize: 10.5, fontWeight: 800, letterSpacing: 0.5, textTransform: 'uppercase' }}>
431
- <span style={{ color: RARE }}>Rare{isMobile ? '' : ' · one way in'}</span>
432
- <span style={{ color: '#FFD700' }}>Power</span>
433
- <span style={{ color: EASY }}>Easy{isMobile ? '' : ' · many mutual connections'}</span>
465
+ {/* On a computer the pill saying where the slider is sits over its middle, in place of "Power" */}
466
+ <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: isMobile ? 'baseline' : 'center', marginTop: 8, fontSize: 10.5, fontWeight: 800, letterSpacing: 0.5, textTransform: 'uppercase' }}>
467
+ <span style={{ color: RARE, flex: isMobile ? undefined : 1 }}>Rare{isMobile ? '' : ' · one way in'}</span>
468
+ {isMobile ? <span style={{ color: '#FFD700' }}>Power</span> : pillEl}
469
+ <span style={{ color: EASY, flex: isMobile ? undefined : 1, textAlign: 'right' }}>Easy{isMobile ? '' : ' · many mutual connections'}</span>
434
470
  </div>
435
471
  <input
436
472
  className="sepslide" type="range" min={0} max={100} step={1} value={at}
@@ -448,31 +484,16 @@ export default function SeparationView({ connections = [], degree2 = [], fullDeg
448
484
  }}>{v}{name && !isMobile ? ` · ${name}` : ''}</button>
449
485
  ))}
450
486
  </div>
451
- <div style={{ marginTop: 4, fontSize: 11.5, lineHeight: 1.45, color: '#bbb' }}>
452
- <span style={{ color: slideColor, fontWeight: 700 }}>{slide.name}.</span>{' '}{slide.detail}
453
- {!isMobile && <span style={{ color: '#667' }}>{' '}It only reorders: scores, tiers and ranks stay as they are.</span>}
454
- </div>
455
-
456
- <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 8, minWidth: 0, flexWrap: isMobile ? 'nowrap' : 'wrap',
457
- overflowX: isMobile ? 'auto' : 'visible', scrollbarWidth: 'thin' }}>
458
- <span title={RARITY_NOTE} style={{ fontSize: 10, color: '#666', whiteSpace: 'nowrap', flexShrink: 0, textTransform: 'uppercase', letterSpacing: 0.5, cursor: 'help' }}>Only show</span>
459
- {RARITY.map((r) => {
460
- const on = rarities.has(r.key);
461
- return (
462
- <button key={r.key} type="button" aria-pressed={on} onClick={() => changeRarity(r.key)}
463
- title={`${r.label}: ${r.range} mutual connection${r.range === '1' ? '' : 's'}. ${RARITY_NOTE}`} style={{
464
- height: isMobile ? 40 : 28, padding: '0 10px', borderRadius: 14, cursor: 'pointer', flexShrink: 0,
465
- fontSize: 11.5, fontWeight: 700, whiteSpace: 'nowrap',
466
- border: `1px solid ${on ? r.color : 'rgba(255,255,255,0.1)'}`,
467
- background: on ? `${r.color}22` : 'rgba(255,255,255,0.03)',
468
- color: on ? r.color : '#999',
469
- }}>
470
- {r.label}
471
- <span style={{ marginLeft: 5, fontWeight: 500, color: on ? r.color : '#666', opacity: 0.85 }}>{fmt(byRarity[r.key])}</span>
472
- </button>
473
- );
474
- })}
475
- </div>
487
+ {/* On a phone: the sentence, and the rarity chips on a row of their own */}
488
+ {isMobile && <>
489
+ <div style={{ marginTop: 4, fontSize: 11.5, lineHeight: 1.45, color: '#bbb' }}>
490
+ <span style={{ color: slideColor, fontWeight: 700 }}>{slide.name}.</span>{' '}{slide.detail}
491
+ </div>
492
+ <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 8, minWidth: 0, flexWrap: 'nowrap',
493
+ overflowX: 'auto', scrollbarWidth: 'thin' }}>
494
+ {rarityChips}
495
+ </div>
496
+ </>}
476
497
  </div>
477
498
  </div>
478
499
 
@@ -486,18 +507,19 @@ export default function SeparationView({ connections = [], degree2 = [], fullDeg
486
507
  {mapBlockH > 0 && (
487
508
  <div style={{ height: mapBlockH, boxSizing: 'border-box', paddingTop: 10 }}>
488
509
  <div style={{ height: captionH - 10, overflow: 'hidden' }}>
489
- <div style={{ fontSize: 12, fontWeight: 700, color: '#ddd', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
510
+ <div title={isMobile ? undefined : `${!single && askedShown > 0 ? `${fmt(askedShown)} asked or connected, so it moved on. ` : ''}Solid orange: the top-scored bridge. Dashed: other routes.${single ? ' Pick anyone in the list to aim at them instead.' : cards ? ' A lit pill is someone’s best way in.' : ' Dot size: ways in.'}`}
511
+ style={{ fontSize: 12, fontWeight: 700, color: '#ddd', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
490
512
  {single
491
513
  ? <>Aiming at {target.person.name} · {layout.unscanned
492
514
  ? `${fmt(target.waysIn + layout.unscanned)} mutual connections: ${fmt(target.waysIn)} drawn, ${fmt(layout.unscanned)} in circles not scanned yet`
493
515
  : target.waysIn === 1 ? 'the one connection of yours who leads to them' : `all ${fmt(target.waysIn)} connections of yours who lead to them`}</>
494
516
  : <>Top {fmt(top.length)} you haven’t asked, of {fmt(visible.length)}{filtered ? ' shown' : ''}{at !== SLIDER_MIDDLE ? ` · ${slide.name.toLowerCase()}` : ''} · every way in drawn</>}
495
517
  </div>
496
- <div style={{ fontSize: 10, color: '#777', marginTop: 2, whiteSpace: isMobile ? 'normal' : 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', lineHeight: 1.35 }}>
518
+ {isMobile && <div style={{ fontSize: 10, color: '#777', marginTop: 2, whiteSpace: 'normal', overflow: 'hidden', textOverflow: 'ellipsis', lineHeight: 1.35 }}>
497
519
  {!single && askedShown > 0 && <span style={{ color: '#FFD700' }}>{fmt(askedShown)} asked or connected, so it moved on · </span>}
498
520
  <span style={{ color: ORANGE }}>solid orange</span> = top-scored bridge · dashed = other routes
499
521
  {single ? ' · pick anyone in the list to aim at them instead' : cards ? ' · a lit pill is someone’s best way in' : ' · dot size = ways in'}
500
- </div>
522
+ </div>}
501
523
  </div>
502
524
  {cw > 0 && (
503
525
  <SummitMap
@@ -628,7 +650,8 @@ const MAP_CSS = `
628
650
  .sepmap .in { animation: none; }
629
651
  }
630
652
  `;
631
- const HALO = { paintOrder: 'stroke', stroke: '#0a0a1a', strokeWidth: 3, strokeLinejoin: 'round' };
653
+ const RANK_NOTE = 'Ranked by each person’s own score (title, company, headline). It ranks reachability, not people. From the lists scanned so far.';
654
+ const HALO = { paintOrder: 'stroke', stroke: 'var(--sd-bg)', strokeWidth: 3, strokeLinejoin: 'round' };
632
655
  const at = (x, y) => ({ transform: `translate(${x}px, ${y}px)` });
633
656
 
634
657
  /**
@@ -746,7 +769,7 @@ const SummitMap = memo(function SummitMap({ layout, selectedKey, tierColors, you
746
769
  <SmallCard p={p} c={c} tag={tag} width={Math.max(240, Math.min(340, width - pp.x - 4))} sel={sel} />
747
770
  ) : pp.big ? (
748
771
  <>
749
- <circle r={pp.r} fill="#0a0a1a" stroke={c} strokeWidth={3} strokeOpacity={0.35 + 0.65 * drawn} />
772
+ <circle r={pp.r} fill="var(--sd-bg)" stroke={c} strokeWidth={3} strokeOpacity={0.35 + 0.65 * drawn} />
750
773
  <text dy="0.35em" textAnchor="middle" fontSize={11} fontWeight={800} fill={c}>{initialsFor(p.person.name)}</text>
751
774
  <text x={lx} y={-20} fontSize={fs + 3} fontWeight={800} fill="#fff" style={HALO}>{clip(p.person.name)}</text>
752
775
  <text x={lx} y={-4} fontSize={fs} fill="#aaa" style={HALO}>{clip(subline(p.person))}</text>
@@ -800,7 +823,7 @@ const SummitMap = memo(function SummitMap({ layout, selectedKey, tierColors, you
800
823
  <circle
801
824
  r={b.r}
802
825
  fill={b.unresolved ? 'none' : c}
803
- stroke={b.unresolved ? '#777' : '#0a0a1a'}
826
+ stroke={b.unresolved ? '#777' : 'var(--sd-bg)'}
804
827
  strokeWidth={b.unresolved ? 1 : 1.5}
805
828
  strokeDasharray={b.unresolved ? '2 2' : undefined}
806
829
  />
@@ -893,7 +916,7 @@ function BigCard({ p, c, tag, width, fs }) {
893
916
  return (
894
917
  <g>
895
918
  <rect x={0} y={-76} width={width} height={152} rx={16} fill="#151830" stroke="rgba(255,215,0,0.45)" />
896
- <circle cx={48} r={32} fill="#0a0a1a" stroke={c} strokeWidth={3} />
919
+ <circle cx={48} r={32} fill="var(--sd-bg)" stroke={c} strokeWidth={3} />
897
920
  <text x={48} dy="0.35em" textAnchor="middle" fontSize={18} fontWeight={800} fill={c}>{initialsFor(p.person.name)}</text>
898
921
  <text x={tx} y={-40} fontSize={11} fontWeight={800} fill="#FFD700">#{p.rank}{p.tied ? '=' : ''} · {p.tier}-tier · {p.score.toFixed(1)}</text>
899
922
  <text x={tx} y={-17} fontSize={fs + 8} fontWeight={800} fill="#fff">{clipText(p.person.name, Math.floor(room * 0.72))}</text>
@@ -1075,9 +1098,9 @@ const EASY = '#FF7043';
1075
1098
  const SLIDER_CSS = `
1076
1099
  .sepslide { -webkit-appearance: none; appearance: none; display: block; width: 100%; height: 24px; margin: 4px 0 0; background: transparent; cursor: pointer; }
1077
1100
  .sepslide::-webkit-slider-runnable-track { height: 6px; border-radius: 3px; background: linear-gradient(90deg, ${RARE} 0%, #FFD700 50%, ${EASY} 100%); }
1078
- .sepslide::-webkit-slider-thumb { -webkit-appearance: none; width: 20px; height: 20px; margin-top: -7px; border-radius: 50%; background: #0a0a1a; border: 3px solid #fff; box-shadow: 0 0 10px rgba(255,255,255,0.45); }
1101
+ .sepslide::-webkit-slider-thumb { -webkit-appearance: none; width: 20px; height: 20px; margin-top: -7px; border-radius: 50%; background: var(--sd-bg); border: 3px solid #fff; box-shadow: 0 0 10px rgba(255,255,255,0.45); }
1079
1102
  .sepslide::-moz-range-track { height: 6px; border-radius: 3px; background: linear-gradient(90deg, ${RARE} 0%, #FFD700 50%, ${EASY} 100%); }
1080
- .sepslide::-moz-range-thumb { width: 14px; height: 14px; border-radius: 50%; background: #0a0a1a; border: 3px solid #fff; box-shadow: 0 0 10px rgba(255,255,255,0.45); }
1103
+ .sepslide::-moz-range-thumb { width: 14px; height: 14px; border-radius: 50%; background: var(--sd-bg); border: 3px solid #fff; box-shadow: 0 0 10px rgba(255,255,255,0.45); }
1081
1104
  .sepslide:focus-visible { outline: 2px solid rgba(255,255,255,0.7); outline-offset: 3px; border-radius: 6px; }
1082
1105
  `;
1083
1106
  const RARITY_NOTE = 'Rarity is how many mutual connections lead to them: few is a rare way in, many is warm (likely to accept). It never changes a score or a tier.';
@@ -575,7 +575,7 @@ export default function Sidebar({ selected, stats, tierColors, connections, degr
575
575
  return (
576
576
  <div style={{
577
577
  position: 'absolute', top: '100%', left: 0, right: 0, zIndex: 50,
578
- background: 'rgba(10,10,26,0.98)', border: '1px solid rgba(255,255,255,0.1)',
578
+ background: 'color-mix(in srgb, var(--sd-bg) 97%, transparent)', border: '1px solid rgba(255,255,255,0.1)',
579
579
  borderRadius: 8, overflow: 'hidden', maxHeight: 200, overflowY: 'auto',
580
580
  boxShadow: '0 8px 24px rgba(0,0,0,0.5)',
581
581
  }}>
@@ -790,7 +790,7 @@ export default function Sidebar({ selected, stats, tierColors, connections, degr
790
790
  {searchResults.length > 0 && (
791
791
  <div style={{
792
792
  position: 'absolute', top: '100%', left: 0, right: 0, zIndex: 10,
793
- background: 'rgba(10,10,26,0.98)', border: '1px solid rgba(255,255,255,0.1)',
793
+ background: 'color-mix(in srgb, var(--sd-bg) 97%, transparent)', border: '1px solid rgba(255,255,255,0.1)',
794
794
  borderRadius: 8, marginTop: 4, overflow: 'hidden',
795
795
  boxShadow: '0 8px 24px rgba(0,0,0,0.5)',
796
796
  }}>
@@ -966,8 +966,8 @@ function SidebarWrapper({ children, collapsed, onToggle }) {
966
966
  borderLeft: '1px solid rgba(255,215,0,0.12)',
967
967
  padding: isMobile ? '12px 10px' : '16px 16px',
968
968
  overflowY: 'auto', overflowX: 'hidden',
969
- background: isMobile ? 'rgba(15,12,5,0.98)' : 'rgba(15,12,5,0.65)', fontSize: 13,
970
- backdropFilter: 'blur(24px) saturate(1.4)', WebkitBackdropFilter: 'blur(24px) saturate(1.4)',
969
+ background: isMobile ? 'rgba(15,12,5,0.98)' : 'var(--sd-panel)', fontSize: 13,
970
+ backdropFilter: 'var(--sd-panel-blur)', WebkitBackdropFilter: 'var(--sd-panel-blur)',
971
971
  boxShadow: 'inset 0 0 60px rgba(255,215,0,0.03), -4px 0 24px rgba(0,0,0,0.3)',
972
972
  marginLeft: isMobile ? 'auto' : 0,
973
973
  }}>
@@ -18,8 +18,9 @@ import { circleIndex, circleRings, circleLayout, requestedByDefault } from '../.
18
18
  import { keyFor, routeIndex } from '../../lib/separation';
19
19
  import { RARITY, rarityOf, passes, countByRarity, toggle, rarityInfo } from '../../lib/rarity';
20
20
  import { scoreGuess } from '../../lib/score-guess';
21
+ import { TIER_COLORS as THEME_TIERS } from '../../lib/themes';
21
22
 
22
- const CLASSIC = { S: '#FFD700', A: '#9B59B6', B: '#3498DB', C: '#95A5A6', D: '#BDC3C7' };
23
+ const CLASSIC = THEME_TIERS; // the theme's dot colours (lib/themes.js)
23
24
  const TIERS = ['S', 'A', 'B', 'C', 'D'];
24
25
  const GREEN = '#00ff88';
25
26
 
@@ -0,0 +1,9 @@
1
+ 'use client';
2
+
3
+ // Loads the theme store on every page (lib/theme-store.js), which applies the
4
+ // theme in use before anything draws. It renders nothing.
5
+ import '../../lib/theme-store';
6
+
7
+ export default function ThemeLoader() {
8
+ return null;
9
+ }
@@ -278,7 +278,9 @@ function InstalledUpdates({ local }) {
278
278
  // whenever it can't install the update itself, or the last time it tried
279
279
  // didn't work (so a second try that fails the same way isn't the only way),
280
280
  // except where the line would do harm.
281
- const showLine = result?.newer && (!mac || fallback)
281
+ // Windows and Linux (DESKTOP.md D3): no Terminal line, ever; the release page's installer replaces the app.
282
+ const desktop = local.kind === 'windows-app' || local.kind === 'linux-app';
283
+ const showLine = !desktop && result?.newer && (!mac || fallback)
282
284
  && (!canInstall || failed || refused || local.lastUpdate?.tone === 'bad');
283
285
  const how = fallbackText({ mac, kind: local.kind, canInstall, fallback });
284
286
 
@@ -328,6 +330,22 @@ function InstalledUpdates({ local }) {
328
330
  </>
329
331
  )}
330
332
  {mac && !canInstall && result.install?.reason && <Body>{result.install.reason}</Body>}
333
+ {desktop && (
334
+ <>
335
+ <Body>
336
+ {local.kind === 'windows-app'
337
+ ? 'Download its Setup.exe from the release page and run it: it closes this copy, puts the new version in its place and opens it.'
338
+ : 'Download its .deb (or .tar.gz) from the release page and install it over this one, after quitting Six Degrees.'}
339
+ {' '}Your network stays where it is.
340
+ </Body>
341
+ <Row>
342
+ <a href={(result.download || result.latest).url} target="_blank" rel="noreferrer" style={{
343
+ display: 'inline-block', padding: '8px 16px', borderRadius: 8, fontSize: 13, fontWeight: 700, textDecoration: 'none',
344
+ background: 'linear-gradient(135deg, #9B59B6, #3498DB)', color: '#fff',
345
+ }}>Open the release page</a>
346
+ </Row>
347
+ </>
348
+ )}
331
349
  {showLine && (
332
350
  <>
333
351
  <Body>{how}</Body>
@@ -346,7 +364,7 @@ function InstalledUpdates({ local }) {
346
364
  )}
347
365
  </>
348
366
  )}
349
- {!canInstall && !showLine && <Row><WhatChanged url={result.latest.url} /></Row>}
367
+ {!canInstall && !showLine && !desktop && <Row><WhatChanged url={result.latest.url} /></Row>}
350
368
  </>
351
369
  )}
352
370