six-degrees 0.3.0 → 0.4.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 (427) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-path-routes-manifest.json +1 -0
  3. package/.next/standalone/.next/build-manifest.json +3 -3
  4. package/.next/standalone/.next/prerender-manifest.json +35 -7
  5. package/.next/standalone/.next/required-server-files.json +6 -1
  6. package/.next/standalone/.next/routes-manifest.json +18 -1
  7. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  8. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  9. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  10. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  11. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  12. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  13. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  14. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  15. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  16. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  17. package/.next/standalone/.next/server/app/_not-found.rsc +11 -11
  18. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +11 -11
  19. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +10 -10
  20. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  21. package/.next/standalone/.next/server/app/api/admin-delete/route.js +1 -1
  22. package/.next/standalone/.next/server/app/api/admin-delete/route.js.nft.json +1 -1
  23. package/.next/standalone/.next/server/app/api/admin-update/route.js +1 -1
  24. package/.next/standalone/.next/server/app/api/admin-update/route.js.nft.json +1 -1
  25. package/.next/standalone/.next/server/app/api/bridges/route.js +1 -1
  26. package/.next/standalone/.next/server/app/api/bridges/route.js.nft.json +1 -1
  27. package/.next/standalone/.next/server/app/api/bulk-import/route.js +1 -1
  28. package/.next/standalone/.next/server/app/api/bulk-import/route.js.nft.json +1 -1
  29. package/.next/standalone/.next/server/app/api/company-scores/legacy/route.js.nft.json +1 -1
  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 +1 -1
  32. package/.next/standalone/.next/server/app/api/connections/route.js.nft.json +1 -1
  33. package/.next/standalone/.next/server/app/api/data/export/route.js.nft.json +1 -1
  34. package/.next/standalone/.next/server/app/api/data/import/route.js.nft.json +1 -1
  35. package/.next/standalone/.next/server/app/api/data/restart/route.js.nft.json +1 -1
  36. package/.next/standalone/.next/server/app/api/data/reveal/route.js.nft.json +1 -1
  37. package/.next/standalone/.next/server/app/api/data/route.js.nft.json +1 -1
  38. package/.next/standalone/.next/server/app/api/delete-cluster/route.js +1 -1
  39. package/.next/standalone/.next/server/app/api/delete-cluster/route.js.nft.json +1 -1
  40. package/.next/standalone/.next/server/app/api/ingest/route.js +1 -1
  41. package/.next/standalone/.next/server/app/api/ingest/route.js.nft.json +1 -1
  42. package/.next/standalone/.next/server/app/api/network/route.js +1 -1
  43. package/.next/standalone/.next/server/app/api/network/route.js.nft.json +1 -1
  44. package/.next/standalone/.next/server/app/api/notifications/route.js +1 -1
  45. package/.next/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  46. package/.next/standalone/.next/server/app/api/outreach/route.js +3 -3
  47. package/.next/standalone/.next/server/app/api/outreach/route.js.nft.json +1 -1
  48. package/.next/standalone/.next/server/app/api/queue/route.js +1 -1
  49. package/.next/standalone/.next/server/app/api/queue/route.js.nft.json +1 -1
  50. package/.next/standalone/.next/server/app/api/scraper/route.js +1 -1
  51. package/.next/standalone/.next/server/app/api/scraper/route.js.nft.json +1 -1
  52. package/.next/standalone/.next/server/app/api/settings/route.js.nft.json +1 -1
  53. package/.next/standalone/.next/server/app/api/settings/sector-preview/route.js.nft.json +1 -1
  54. package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route.js.nft.json +1 -1
  55. package/.next/standalone/.next/server/app/api/setup-profile/route.js +1 -1
  56. package/.next/standalone/.next/server/app/api/setup-profile/route.js.nft.json +1 -1
  57. package/.next/standalone/.next/server/app/api/unlock/route.js +1 -1
  58. package/.next/standalone/.next/server/app/api/unlock/route.js.nft.json +1 -1
  59. package/.next/standalone/.next/server/app/api/update/route.js.nft.json +1 -1
  60. package/.next/standalone/.next/server/app/api/update-images/route.js +1 -1
  61. package/.next/standalone/.next/server/app/api/update-images/route.js.nft.json +1 -1
  62. package/.next/standalone/.next/server/app/api/users/route.js +1 -1
  63. package/.next/standalone/.next/server/app/api/users/route.js.nft.json +1 -1
  64. package/.next/standalone/.next/server/app/avatars/[file]/route.js.nft.json +1 -1
  65. package/.next/standalone/.next/server/app/import/page.js.nft.json +1 -1
  66. package/.next/standalone/.next/server/app/import/page_client-reference-manifest.js +1 -1
  67. package/.next/standalone/.next/server/app/import.html +1 -1
  68. package/.next/standalone/.next/server/app/import.rsc +13 -13
  69. package/.next/standalone/.next/server/app/import.segments/_full.segment.rsc +13 -13
  70. package/.next/standalone/.next/server/app/import.segments/_tree.segment.rsc +2 -2
  71. package/.next/standalone/.next/server/app/import.segments/import/__PAGE__.segment.rsc +12 -12
  72. package/.next/standalone/.next/server/app/index.html +1 -1
  73. package/.next/standalone/.next/server/app/index.rsc +13 -13
  74. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +12 -12
  75. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +13 -13
  76. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  77. package/.next/standalone/.next/server/app/launch/page.js.nft.json +1 -1
  78. package/.next/standalone/.next/server/app/launch/page_client-reference-manifest.js +1 -1
  79. package/.next/standalone/.next/server/app/launch.html +2 -2
  80. package/.next/standalone/.next/server/app/launch.rsc +13 -13
  81. package/.next/standalone/.next/server/app/launch.segments/_full.segment.rsc +13 -13
  82. package/.next/standalone/.next/server/app/launch.segments/_tree.segment.rsc +2 -2
  83. package/.next/standalone/.next/server/app/launch.segments/launch/__PAGE__.segment.rsc +12 -12
  84. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  85. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  86. package/.next/standalone/.next/server/app/paths/page.js.nft.json +1 -1
  87. package/.next/standalone/.next/server/app/paths/page_client-reference-manifest.js +1 -1
  88. package/.next/standalone/.next/server/app/paths.html +1 -1
  89. package/.next/standalone/.next/server/app/paths.rsc +13 -13
  90. package/.next/standalone/.next/server/app/paths.segments/_full.segment.rsc +13 -13
  91. package/.next/standalone/.next/server/app/paths.segments/_tree.segment.rsc +2 -2
  92. package/.next/standalone/.next/server/app/paths.segments/paths/__PAGE__.segment.rsc +12 -12
  93. package/.next/standalone/.next/server/app/profile/page.js.nft.json +1 -1
  94. package/.next/standalone/.next/server/app/profile/page_client-reference-manifest.js +1 -1
  95. package/.next/standalone/.next/server/app/profile.html +1 -1
  96. package/.next/standalone/.next/server/app/profile.rsc +13 -13
  97. package/.next/standalone/.next/server/app/profile.segments/_full.segment.rsc +13 -13
  98. package/.next/standalone/.next/server/app/profile.segments/_tree.segment.rsc +2 -2
  99. package/.next/standalone/.next/server/app/profile.segments/profile/__PAGE__.segment.rsc +12 -12
  100. package/.next/standalone/.next/server/app/queue/page.js.nft.json +1 -1
  101. package/.next/standalone/.next/server/app/queue/page_client-reference-manifest.js +1 -1
  102. package/.next/standalone/.next/server/app/queue.html +1 -1
  103. package/.next/standalone/.next/server/app/queue.rsc +13 -13
  104. package/.next/standalone/.next/server/app/queue.segments/_full.segment.rsc +13 -13
  105. package/.next/standalone/.next/server/app/queue.segments/_tree.segment.rsc +2 -2
  106. package/.next/standalone/.next/server/app/queue.segments/queue/__PAGE__.segment.rsc +12 -12
  107. package/.next/standalone/.next/server/app/scores/page/app-paths-manifest.json +3 -0
  108. package/.next/standalone/.next/server/app/scores/page/build-manifest.json +20 -0
  109. package/.next/standalone/.next/server/app/scores/page/next-font-manifest.json +11 -0
  110. package/.next/standalone/.next/server/app/scores/page/react-loadable-manifest.json +1 -0
  111. package/.next/standalone/.next/server/app/scores/page/server-reference-manifest.json +4 -0
  112. package/.next/standalone/.next/server/app/scores/page.js +13 -0
  113. package/.next/standalone/.next/server/app/scores/page.js.map +5 -0
  114. package/.next/standalone/.next/server/app/scores/page.js.nft.json +1 -0
  115. package/.next/standalone/.next/server/app/scores/page_client-reference-manifest.js +3 -0
  116. package/.next/standalone/.next/server/app/scores.html +1 -0
  117. package/.next/standalone/.next/server/app/scores.meta +26 -0
  118. package/.next/standalone/.next/server/app/scores.rsc +24 -0
  119. package/.next/standalone/.next/server/app/scores.segments/_full.segment.rsc +24 -0
  120. package/.next/standalone/.next/server/app/scores.segments/_tree.segment.rsc +4 -0
  121. package/.next/standalone/.next/server/app/scores.segments/scores/__PAGE__.segment.rsc +28 -0
  122. package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
  123. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  124. package/.next/standalone/.next/server/app/settings.html +1 -1
  125. package/.next/standalone/.next/server/app/settings.rsc +13 -13
  126. package/.next/standalone/.next/server/app/settings.segments/_full.segment.rsc +13 -13
  127. package/.next/standalone/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
  128. package/.next/standalone/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +12 -12
  129. package/.next/standalone/.next/server/app/setup/page.js.nft.json +1 -1
  130. package/.next/standalone/.next/server/app/setup/page_client-reference-manifest.js +1 -1
  131. package/.next/standalone/.next/server/app/setup.html +1 -1
  132. package/.next/standalone/.next/server/app/setup.rsc +13 -13
  133. package/.next/standalone/.next/server/app/setup.segments/_full.segment.rsc +13 -13
  134. package/.next/standalone/.next/server/app/setup.segments/_tree.segment.rsc +2 -2
  135. package/.next/standalone/.next/server/app/setup.segments/setup/__PAGE__.segment.rsc +12 -12
  136. package/.next/standalone/.next/server/app-paths-manifest.json +1 -0
  137. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0-rnla2._.js +1 -1
  138. package/.next/standalone/.next/server/chunks/[root-of-the-server]__00la_y0._.js +1 -1
  139. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0i5hdu4._.js → [root-of-the-server]__03ydxxh._.js} +2 -2
  140. package/.next/standalone/.next/server/chunks/[root-of-the-server]__07t47cm._.js +1 -1
  141. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0bat8nx._.js +8 -0
  142. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0cj5jqc._.js +1 -1
  143. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0e0fei3._.js +1 -1
  144. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ljcioj._.js +1 -1
  145. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ljnyho._.js +1 -1
  146. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o5-tcg._.js +1 -1
  147. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0qrnous._.js +1 -1
  148. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0t3v1a1._.js +1 -1
  149. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0uag-k5._.js +1 -1
  150. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0um1uey._.js +1 -1
  151. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0wmexuc._.js +1 -1
  152. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0xu34sz._.js +1 -1
  153. package/.next/standalone/.next/server/chunks/[root-of-the-server]__133knx1._.js +1 -1
  154. package/.next/standalone/.next/server/chunks/[root-of-the-server]__14ou7j5._.js +1 -1
  155. package/.next/standalone/.next/server/chunks/[root-of-the-server]__15-17hl._.js +1 -1
  156. package/.next/standalone/.next/server/chunks/[root-of-the-server]__16iu0hv._.js +1 -1
  157. package/.next/standalone/.next/server/chunks/[root-of-the-server]__19b7mig._.js +1 -1
  158. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1bbcwub._.js +2 -2
  159. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1eris29._.js +1 -1
  160. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1gjo_cq._.js +1 -1
  161. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1kbl21f._.js +1 -1
  162. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1qcm08_._.js +1 -1
  163. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1rphsdk._.js +1 -1
  164. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1w25q0m._.js +1 -1
  165. package/.next/standalone/.next/server/chunks/_02twlca._.js +10 -0
  166. package/.next/standalone/.next/server/chunks/_072jl0y._.js +1 -1
  167. package/.next/standalone/.next/server/chunks/_0lw8_i0._.js +1 -1
  168. package/.next/standalone/.next/server/chunks/_1_fynia._.js +8 -6
  169. package/.next/standalone/.next/server/chunks/_1fn30_l._.js +1 -1
  170. package/.next/standalone/.next/server/chunks/_1itd1o_._.js +1 -1
  171. package/.next/standalone/.next/server/chunks/_1iwkh8t._.js +1 -1
  172. package/.next/standalone/.next/server/chunks/lib_db-client_15le7cw.js +13 -8
  173. package/.next/standalone/.next/server/chunks/{lib_rpc_02ndsg2.js → lib_rpc_03i8xef.js} +1 -1
  174. package/.next/standalone/.next/server/chunks/{lib_rpc_08q5vp6.js → lib_rpc_08fc3rp.js} +1 -1
  175. package/.next/standalone/.next/server/chunks/{lib_rpc_00tx2sm.js → lib_rpc_08r2t_q.js} +1 -1
  176. package/.next/standalone/.next/server/chunks/{lib_rpc_02-qa4d.js → lib_rpc_0btpv1t.js} +1 -1
  177. package/.next/standalone/.next/server/chunks/lib_rpc_0c9d9ti.js +5 -5
  178. package/.next/standalone/.next/server/chunks/lib_rpc_0cm2ev3.js +3 -0
  179. package/.next/standalone/.next/server/chunks/lib_rpc_0iovswz.js +3 -0
  180. package/.next/standalone/.next/server/chunks/lib_rpc_0is8flp.js +3 -0
  181. package/.next/standalone/.next/server/chunks/lib_rpc_0v8ajtd.js +3 -0
  182. package/.next/standalone/.next/server/chunks/lib_rpc_0xgmvvt.js +3 -0
  183. package/.next/standalone/.next/server/chunks/lib_rpc_144mzbf.js +3 -0
  184. package/.next/standalone/.next/server/chunks/lib_rpc_1bggi0n.js +3 -0
  185. package/.next/standalone/.next/server/chunks/lib_rpc_1dkcu9f.js +3 -0
  186. package/.next/standalone/.next/server/chunks/lib_rpc_1o0jb6w.js +3 -0
  187. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0an6blh._.js → [root-of-the-server]__0zzcbqg._.js} +2 -2
  188. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1194jps._.js +3 -0
  189. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1z1j3ek._.js → [root-of-the-server]__19ip1qq._.js} +2 -2
  190. package/.next/standalone/.next/server/chunks/ssr/_01f38ty._.js +3 -0
  191. package/.next/standalone/.next/server/chunks/ssr/_06w_gl4._.js +3 -0
  192. package/.next/standalone/.next/server/chunks/ssr/_0hw_qnj._.js +3 -0
  193. package/.next/standalone/.next/server/chunks/ssr/_13kzrwv._.js +3 -0
  194. package/.next/standalone/.next/server/chunks/ssr/_15xuwkv._.js +3 -0
  195. package/.next/standalone/.next/server/chunks/ssr/_1cyxocj._.js +3 -0
  196. package/.next/standalone/.next/server/chunks/ssr/_1gpbbw9._.js +3 -0
  197. package/.next/standalone/.next/server/chunks/ssr/_1hgd5dp._.js +3 -0
  198. package/.next/standalone/.next/server/chunks/ssr/_1vpfyd-._.js +3 -0
  199. package/.next/standalone/.next/server/chunks/ssr/_20w06i-._.js +3 -0
  200. package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_scores_page_actions_0x-w58n.js +3 -0
  201. package/.next/standalone/.next/server/chunks/ssr/app_components_settings_SectorPicker_1c-29qw.js +3 -0
  202. package/.next/standalone/.next/server/chunks/ssr/app_launch_page_19t0dyd.js +1 -1
  203. package/.next/standalone/.next/server/chunks/ssr/app_page_1fazqbf.js +11 -9
  204. package/.next/standalone/.next/server/chunks/ssr/app_paths_page_1ol90m7.js +4 -0
  205. package/.next/standalone/.next/server/chunks/ssr/app_profile_page_0u3-l5y.js +1 -1
  206. package/.next/standalone/.next/server/chunks/ssr/app_queue_page_0c6znd6.js +5 -5
  207. package/.next/standalone/.next/server/chunks/ssr/app_scores_page_09wepvv.js +3 -0
  208. package/.next/standalone/.next/server/chunks/ssr/app_settings_page_1f8mjj_.js +1 -1
  209. package/.next/standalone/.next/server/chunks/ssr/app_setup_page_1-282zx.js +2 -2
  210. package/.next/standalone/.next/server/chunks/ssr/lib_1bn38gs._.js +3 -0
  211. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_0x3i8za._.js +131 -0
  212. package/.next/standalone/.next/server/chunks/ssr/{node_modules_next_dist_1bunoni._.js → node_modules_next_dist_1v8aef8._.js} +2 -2
  213. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_client_components_server-async-storage_0t1dato.js +3 -0
  214. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  215. package/.next/standalone/.next/server/middleware-manifest.json +5 -5
  216. package/.next/standalone/.next/server/next-font-manifest.js +1 -1
  217. package/.next/standalone/.next/server/next-font-manifest.json +4 -0
  218. package/.next/standalone/.next/server/pages/404.html +1 -1
  219. package/.next/standalone/.next/server/pages/500.html +1 -1
  220. package/.next/standalone/.next/server/prefetch-hints.json +14 -0
  221. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  222. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  223. package/.next/standalone/.next/static/chunks/0ax_9zzboyv6d.js +44 -0
  224. package/.next/standalone/.next/static/chunks/0cuuo2jwc9h94.js +1 -0
  225. package/.next/standalone/.next/static/chunks/0l1568qff0efj.js +1 -0
  226. package/.next/standalone/.next/static/chunks/0muwt9bykzr-1.js +1 -0
  227. package/.next/standalone/.next/static/chunks/0w76iraw7ij3k.js +18 -0
  228. package/.next/standalone/.next/static/chunks/135n87ydxjrra.js +2 -0
  229. package/.next/standalone/.next/static/chunks/18xu0fbgo_qz-.js +1 -0
  230. package/.next/standalone/.next/static/chunks/28bu26ausqzmn.js +1 -0
  231. package/.next/standalone/.next/static/chunks/{40nvbgfn7-072.css → 2p6o90z0vgcwr.css} +1 -1
  232. package/.next/standalone/.next/static/chunks/2pnbm1z6j7xab.js +1 -0
  233. package/.next/standalone/.next/static/chunks/2xjho0lroiwlq.js +1 -0
  234. package/.next/standalone/.next/static/chunks/3e8zg6ctvvb8p.js +33 -0
  235. package/.next/standalone/.next/static/chunks/3qh78g2aqhprd.js +2 -0
  236. package/.next/standalone/CHANGELOG.md +286 -0
  237. package/.next/standalone/CONTRIBUTING.md +15 -4
  238. package/.next/standalone/README.md +50 -29
  239. package/.next/standalone/SECURITY.md +10 -0
  240. package/.next/standalone/app/api/company-scores/legacy/route.js +1 -1
  241. package/.next/standalone/app/api/company-scores/route.js +1 -1
  242. package/.next/standalone/app/api/ingest/route.js +23 -2
  243. package/.next/standalone/app/api/outreach/route.js +107 -44
  244. package/.next/standalone/app/api/scraper/route.js +146 -17
  245. package/.next/standalone/app/api/settings/sector-preview/route.js +3 -2
  246. package/.next/standalone/app/api/settings/sector-suggestions/route.js +1 -1
  247. package/.next/standalone/app/api/update-images/route.js +41 -7
  248. package/.next/standalone/app/avatars/[file]/route.js +6 -1
  249. package/.next/standalone/app/components/Avatar.js +5 -2
  250. package/.next/standalone/app/components/ChainView.js +659 -469
  251. package/.next/standalone/app/components/CompanyScores.js +16 -10
  252. package/.next/standalone/app/components/EmptyState.js +1 -1
  253. package/.next/standalone/app/components/FieldStep.js +94 -0
  254. package/.next/standalone/app/components/ForceGraph.js +183 -768
  255. package/.next/standalone/app/components/GridView.js +9 -7
  256. package/.next/standalone/app/components/LegacyScoresCard.js +1 -1
  257. package/.next/standalone/app/components/LinkedInLimits.js +22 -7
  258. package/.next/standalone/app/components/ListView.js +6 -4
  259. package/.next/standalone/app/components/MappingProgress.js +5 -6
  260. package/.next/standalone/app/components/OnboardingGate.js +1 -1
  261. package/.next/standalone/app/components/OrbitGraph.js +33 -1
  262. package/.next/standalone/app/components/OutlinkQuest.js +5 -4
  263. package/.next/standalone/app/components/PathsAnalyzer.js +1 -1
  264. package/.next/standalone/app/components/RingsView.js +9 -8
  265. package/.next/standalone/app/components/SeparationView.js +96 -14
  266. package/.next/standalone/app/components/Sidebar.js +366 -287
  267. package/.next/standalone/app/components/TheirCircle.js +300 -0
  268. package/.next/standalone/app/components/settings/SectorPicker.js +202 -0
  269. package/.next/standalone/app/components/settings/SectorSection.js +21 -195
  270. package/.next/standalone/app/components/settings/TierSection.js +99 -0
  271. package/.next/standalone/app/components/useRequests.js +12 -0
  272. package/.next/standalone/app/components/useScanner.js +13 -0
  273. package/.next/standalone/app/components/views.js +3 -5
  274. package/.next/standalone/app/globals.css +7 -0
  275. package/.next/standalone/app/launch/page.js +6 -3
  276. package/.next/standalone/app/page.js +183 -74
  277. package/.next/standalone/app/paths/page.js +20 -14
  278. package/.next/standalone/app/profile/page.js +3 -3
  279. package/.next/standalone/app/queue/page.js +56 -60
  280. package/.next/standalone/app/scores/page.js +72 -0
  281. package/.next/standalone/app/settings/page.js +15 -3
  282. package/.next/standalone/app/setup/page.js +423 -260
  283. package/.next/standalone/db/schema.js +2 -1
  284. package/.next/standalone/eslint.config.mjs +3 -3
  285. package/.next/standalone/install.sh +3 -3
  286. package/.next/standalone/lib/chain-layout.js +139 -0
  287. package/.next/standalone/lib/circle.js +169 -0
  288. package/.next/standalone/lib/companies.js +1 -1
  289. package/.next/standalone/lib/csv.js +21 -10
  290. package/.next/standalone/lib/data-export.js +2 -1
  291. package/.next/standalone/lib/data-folder.js +4 -2
  292. package/.next/standalone/lib/db-client.js +1 -0
  293. package/.next/standalone/lib/galaxy.js +12 -0
  294. package/.next/standalone/lib/ingest.js +27 -8
  295. package/.next/standalone/lib/legacy-offer.js +7 -6
  296. package/.next/standalone/lib/legacy-scores.js +2 -2
  297. package/.next/standalone/lib/linkedin-limits.js +30 -8
  298. package/.next/standalone/lib/photos.js +47 -0
  299. package/.next/standalone/lib/quest.js +8 -3
  300. package/.next/standalone/lib/rarity.js +80 -0
  301. package/.next/standalone/lib/reach.js +113 -0
  302. package/.next/standalone/lib/requests-client.js +113 -0
  303. package/.next/standalone/lib/rpc.js +26 -15
  304. package/.next/standalone/lib/scan-state.js +1 -0
  305. package/.next/standalone/lib/scanner-setup.js +20 -1
  306. package/.next/standalone/lib/score-guess.js +60 -0
  307. package/.next/standalone/lib/scoring.js +1761 -69
  308. package/.next/standalone/lib/scraper-client.js +235 -17
  309. package/.next/standalone/lib/sector-directory.js +1 -1
  310. package/.next/standalone/lib/sector-focus.js +17 -3
  311. package/.next/standalone/lib/separation.js +4 -2
  312. package/.next/standalone/lib/settings-client.js +21 -0
  313. package/.next/standalone/lib/settings-effects.js +19 -1
  314. package/.next/standalone/lib/settings.js +7 -2
  315. package/.next/standalone/next.config.mjs +25 -3
  316. package/.next/standalone/package-lock.json +2 -2
  317. package/.next/standalone/package.json +2 -2
  318. package/.next/standalone/public/demo-data.json +1 -1
  319. package/.next/standalone/scripts/build-app.mjs +11 -2
  320. package/.next/standalone/scripts/check-node.mjs +1 -1
  321. package/.next/standalone/scripts/gen-synthetic.mjs +1 -1
  322. package/.next/standalone/scripts/image_store.py +77 -21
  323. package/.next/standalone/scripts/scrape.py +305 -29
  324. package/.next/standalone/server.js +1 -1
  325. package/.next/static/chunks/0ax_9zzboyv6d.js +44 -0
  326. package/.next/static/chunks/0cuuo2jwc9h94.js +1 -0
  327. package/.next/static/chunks/0l1568qff0efj.js +1 -0
  328. package/.next/static/chunks/0muwt9bykzr-1.js +1 -0
  329. package/.next/static/chunks/0w76iraw7ij3k.js +18 -0
  330. package/.next/static/chunks/135n87ydxjrra.js +2 -0
  331. package/.next/static/chunks/18xu0fbgo_qz-.js +1 -0
  332. package/.next/static/chunks/28bu26ausqzmn.js +1 -0
  333. package/.next/static/chunks/{40nvbgfn7-072.css → 2p6o90z0vgcwr.css} +1 -1
  334. package/.next/static/chunks/2pnbm1z6j7xab.js +1 -0
  335. package/.next/static/chunks/2xjho0lroiwlq.js +1 -0
  336. package/.next/static/chunks/3e8zg6ctvvb8p.js +33 -0
  337. package/.next/static/chunks/3qh78g2aqhprd.js +2 -0
  338. package/CHANGELOG.md +286 -0
  339. package/README.md +50 -29
  340. package/SECURITY.md +10 -0
  341. package/db/schema.js +2 -1
  342. package/lib/chain-layout.js +139 -0
  343. package/lib/circle.js +169 -0
  344. package/lib/companies.js +1 -1
  345. package/lib/csv.js +21 -10
  346. package/lib/data-export.js +2 -1
  347. package/lib/data-folder.js +4 -2
  348. package/lib/db-client.js +1 -0
  349. package/lib/galaxy.js +12 -0
  350. package/lib/ingest.js +27 -8
  351. package/lib/legacy-offer.js +7 -6
  352. package/lib/legacy-scores.js +2 -2
  353. package/lib/linkedin-limits.js +30 -8
  354. package/lib/photos.js +47 -0
  355. package/lib/quest.js +8 -3
  356. package/lib/rarity.js +80 -0
  357. package/lib/reach.js +113 -0
  358. package/lib/requests-client.js +113 -0
  359. package/lib/rpc.js +26 -15
  360. package/lib/scan-state.js +1 -0
  361. package/lib/scanner-setup.js +20 -1
  362. package/lib/score-guess.js +60 -0
  363. package/lib/scoring.js +1761 -69
  364. package/lib/scraper-client.js +235 -17
  365. package/lib/sector-directory.js +1 -1
  366. package/lib/sector-focus.js +17 -3
  367. package/lib/separation.js +4 -2
  368. package/lib/settings-client.js +21 -0
  369. package/lib/settings-effects.js +19 -1
  370. package/lib/settings.js +7 -2
  371. package/package.json +2 -2
  372. package/public/demo-data.json +1 -1
  373. package/scripts/check-node.mjs +1 -1
  374. package/scripts/image_store.py +77 -21
  375. package/scripts/scrape.py +305 -29
  376. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1t3rugi._.js +0 -3
  377. package/.next/standalone/.next/server/chunks/lib_rpc_0_8i3ft.js +0 -3
  378. package/.next/standalone/.next/server/chunks/lib_rpc_0huvw-3.js +0 -3
  379. package/.next/standalone/.next/server/chunks/lib_rpc_0ip2vdh.js +0 -3
  380. package/.next/standalone/.next/server/chunks/lib_rpc_0jzisgh.js +0 -3
  381. package/.next/standalone/.next/server/chunks/lib_rpc_0yi9xvd.js +0 -3
  382. package/.next/standalone/.next/server/chunks/lib_rpc_1jyhd0o.js +0 -3
  383. package/.next/standalone/.next/server/chunks/lib_rpc_1kn59-i.js +0 -3
  384. package/.next/standalone/.next/server/chunks/lib_rpc_1q2jkza.js +0 -3
  385. package/.next/standalone/.next/server/chunks/lib_rpc_1vpm1sk.js +0 -3
  386. package/.next/standalone/.next/server/chunks/lib_rpc_1x6p_31.js +0 -3
  387. package/.next/standalone/.next/server/chunks/ssr/_07u8byv._.js +0 -3
  388. package/.next/standalone/.next/server/chunks/ssr/_08r_mlf._.js +0 -3
  389. package/.next/standalone/.next/server/chunks/ssr/_0942v8n._.js +0 -3
  390. package/.next/standalone/.next/server/chunks/ssr/_0hl_t7r._.js +0 -3
  391. package/.next/standalone/.next/server/chunks/ssr/_0tb83dw._.js +0 -132
  392. package/.next/standalone/.next/server/chunks/ssr/_1-87bs1._.js +0 -3
  393. package/.next/standalone/.next/server/chunks/ssr/_17gui6a._.js +0 -3
  394. package/.next/standalone/.next/server/chunks/ssr/lib_0i8v-s3._.js +0 -3
  395. package/.next/standalone/.next/server/chunks/ssr/node_modules_16vay6l._.js +0 -3
  396. package/.next/standalone/.next/server/chunks/ssr/node_modules_1kciwn4._.js +0 -3
  397. package/.next/standalone/.next/static/chunks/06x3jiiz96m5t.js +0 -1
  398. package/.next/standalone/.next/static/chunks/08k1crid-05dt.js +0 -1
  399. package/.next/standalone/.next/static/chunks/0ngx9s6-zgshe.js +0 -33
  400. package/.next/standalone/.next/static/chunks/0q-_khndfxubv.js +0 -2
  401. package/.next/standalone/.next/static/chunks/1c79veqedvubt.js +0 -1
  402. package/.next/standalone/.next/static/chunks/1chp3nx45meg5.js +0 -44
  403. package/.next/standalone/.next/static/chunks/1irqj0lf-fu3d.js +0 -1
  404. package/.next/standalone/.next/static/chunks/1uadqylrod5_v.js +0 -1
  405. package/.next/standalone/.next/static/chunks/23u0zclgwpc4d.js +0 -1
  406. package/.next/standalone/.next/static/chunks/289ktj97di6zg.js +0 -1
  407. package/.next/standalone/.next/static/chunks/2b3lmf8e6uj8m.js +0 -16
  408. package/.next/standalone/.next/static/chunks/3npq5yd7c4dmn.js +0 -2
  409. package/.next/standalone/app/components/BridgeRing.js +0 -753
  410. package/.next/static/chunks/06x3jiiz96m5t.js +0 -1
  411. package/.next/static/chunks/08k1crid-05dt.js +0 -1
  412. package/.next/static/chunks/0ngx9s6-zgshe.js +0 -33
  413. package/.next/static/chunks/0q-_khndfxubv.js +0 -2
  414. package/.next/static/chunks/1c79veqedvubt.js +0 -1
  415. package/.next/static/chunks/1chp3nx45meg5.js +0 -44
  416. package/.next/static/chunks/1irqj0lf-fu3d.js +0 -1
  417. package/.next/static/chunks/1uadqylrod5_v.js +0 -1
  418. package/.next/static/chunks/23u0zclgwpc4d.js +0 -1
  419. package/.next/static/chunks/289ktj97di6zg.js +0 -1
  420. package/.next/static/chunks/2b3lmf8e6uj8m.js +0 -16
  421. package/.next/static/chunks/3npq5yd7c4dmn.js +0 -2
  422. /package/.next/standalone/.next/static/{qqqcxvzBUizkECrT4swyK → WseE_5HuU-1q0ywC9CP3U}/_buildManifest.js +0 -0
  423. /package/.next/standalone/.next/static/{qqqcxvzBUizkECrT4swyK → WseE_5HuU-1q0ywC9CP3U}/_clientMiddlewareManifest.js +0 -0
  424. /package/.next/standalone/.next/static/{qqqcxvzBUizkECrT4swyK → WseE_5HuU-1q0ywC9CP3U}/_ssgManifest.js +0 -0
  425. /package/.next/static/{qqqcxvzBUizkECrT4swyK → WseE_5HuU-1q0ywC9CP3U}/_buildManifest.js +0 -0
  426. /package/.next/static/{qqqcxvzBUizkECrT4swyK → WseE_5HuU-1q0ywC9CP3U}/_clientMiddlewareManifest.js +0 -0
  427. /package/.next/static/{qqqcxvzBUizkECrT4swyK → WseE_5HuU-1q0ywC9CP3U}/_ssgManifest.js +0 -0
@@ -8,33 +8,55 @@
8
8
  // The old model added them (0.5 × seniority + 0.3 × company), which let an
9
9
  // intern at a famous company score like a director at an unknown one.
10
10
  //
11
- // title (0–10) read from the person's CURRENT role in their headline:
12
- // the first part that names a job, skipping "Ex-" and
13
- // "Former" parts; student clubs and fraternities don't
14
- // count as company titles.
15
- // company weight 0.45 + 0.055 × company score, so 0.615 when no company
16
- // is found (score 3) up to 1.0 (a company scored 10);
17
- // 0.505 is the floor, for a company you score 1.
11
+ // title (0–10) read from the person's roles in their headline, the
12
+ // strongest counting ("Ex-" and "Former" ones at 70%);
13
+ // student clubs and fraternities don't count as company
14
+ // titles. An audience of their own ("2.5M+ followers")
15
+ // counts like a title, and a title the rules can't read
16
+ // like the most common one, an individual contributor's.
17
+ // company weight 0.45 + 0.055 × company score, so 0.725 when the company
18
+ // is unknown or none is found (a neutral 5) up to 1.0 (a
19
+ // company scored 10); 0.505 is the floor, for a company
20
+ // you score 1.
18
21
  // reach bonus (≤1.5) real signals only, matched as whole words: investor,
19
22
  // YC, 30 under 30, audience or revenue in the millions,
20
23
  // TEDx/keynote/patents, and the top honours of every
21
24
  // field (a Nobel, a Pulitzer, an Oscar, an Olympic
22
- // medal…). Halved at a company scored 4 or less,
23
- // judged before any sector lean.
24
- // bridge boost (≤1) for a 1st-degree person whose circle is mapped, when
25
- // their circle is unusually strong. Recomputed each time,
26
- // never ratcheted upward.
25
+ // medal…). Halved at a company we don't know or one
26
+ // scored 4 or less, judged before any sector lean.
27
+ // bridge boost (≤2) for a 1st-degree person whose circle is mapped, when
28
+ // their circle is unusually strong: a high share of it at
29
+ // A or S (up to +1), or many people there (+1 for every
30
+ // 25, up to +2). Recomputed each time, never ratcheted.
27
31
  //
28
32
  // Company scores come from, in order: the score you set, a curated list of
29
33
  // well-known companies, and otherwise how many of your people work there.
30
34
  // If you picked sectors in Settings, a company in one of them gets +1 or +2
31
35
  // on top (never above 10, never on a score you set). That is worked out fresh
32
36
  // on every rescore and never written into your company scores.
37
+ //
38
+ // Tiers are graded on your network's curve unless you choose the fixed scale
39
+ // (Scores → Tiers): your top 3% of 1st-degree people are S, and so on down
40
+ // (CURVE). The curve only lifts, so a strong network keeps its fixed-scale
41
+ // tiers, and it never lifts anyone under 4 into S or A. Everyone, 2nd degree
42
+ // included, is graded on the same cut-offs, taken from your 1st degree.
33
43
  // Everything here is a plain function; tests/scoring.test.mjs pins it down.
34
44
 
35
45
  // Bump when the model changes: the app rescores stored rows once on next load.
36
46
  // 3: one industry per company (not per person), and the sector lean.
37
- export const SCORING_VERSION = 3;
47
+ // 4: an unknown company is neutral (5, not 4, and 5 when none is found, not 3),
48
+ // and tiers are graded on your network's curve by default.
49
+ // 5: the public company dataset (COMPANY_DATA, below the curated list), read after the curated
50
+ // list and before your network's estimate; names read through Unicode
51
+ // normalization, so styled letters, full-width bars and logo glyphs don't
52
+ // hide a company.
53
+ // 6: what a review found the score under-rating. A company named after a title
54
+ // without "at" ("President | The Coca-Cola Company", "Corporate VP,
55
+ // Samsung") is where the title is held; an audience of one's own counts like
56
+ // a title; a strong circle counts by its strong people as well as its share
57
+ // of them, up to +2; an unclear title counts as an IC's. (The title rules
58
+ // themselves are tables, fingerprinted below.)
59
+ export const SCORING_VERSION = 6;
38
60
 
39
61
  // ── title ────────────────────────────────────────────────────────────────────
40
62
 
@@ -46,30 +68,110 @@ export const LEVELS = {
46
68
  manager: { key: 'manager', label: 'Manager / Lead', level: 3, points: 6.5 },
47
69
  senior: { key: 'senior', label: 'Senior IC', level: 2, points: 5 },
48
70
  ic: { key: 'ic', label: 'IC / Entry', level: 1, points: 4 },
49
- unknown: { key: 'unknown', label: 'Title unclear', level: 1, points: 3 },
71
+ // A title the rules can't read ("Studio / Show", "Storyteller", a job they
72
+ // don't list) counts as the most common kind, an individual contributor's:
73
+ // not knowing someone's title says nothing about how senior they are. Until
74
+ // scoring 6 it was 3, below any job, which buried founders who state no title.
75
+ unknown: { key: 'unknown', label: 'Title unclear', level: 1, points: 4 },
50
76
  intern: { key: 'intern', label: 'Intern', level: 0, points: 2 },
51
77
  student: { key: 'student', label: 'Student', level: 0, points: 1 },
78
+ // Universities have their own ladder, on the same points as everyone's: a
79
+ // dean runs a school, as a VP runs a division; a professor is a director's
80
+ // equal, an associate professor a manager's, an assistant professor a senior
81
+ // IC's. A provost, a chancellor and a president are C-suite, above.
82
+ dean: { key: 'dean', label: 'Dean', level: 5, points: 9 },
83
+ professor: { key: 'professor', label: 'Professor', level: 4, points: 7.5 },
84
+ associateProfessor: { key: 'associateProfessor', label: 'Associate Professor', level: 3, points: 6.5 },
85
+ assistantProfessor: { key: 'assistantProfessor', label: 'Assistant Professor', level: 2, points: 5 },
86
+ // An audience of their own (AUDIENCE, below) is a position too: 100K+ counts
87
+ // like a manager's title, 1M+ a director's, 10M+ a VP's.
88
+ audience10m: { key: 'audience10m', label: 'Audience of 10M+', level: 5, points: 9 },
89
+ audience1m: { key: 'audience1m', label: 'Audience of 1M+', level: 4, points: 7.5 },
90
+ audience100k: { key: 'audience100k', label: 'Audience of 100K+', level: 3, points: 6.5 },
91
+ // Government and the services, on the same points. An elected or appointed
92
+ // leader (a senator, a governor, a mayor, a cabinet secretary) is C-suite;
93
+ // their deputies, state legislators, commissioners, ambassadors and judges
94
+ // are VPs; a deputy assistant secretary, a city councilmember or a sheriff a
95
+ // director. Officers by rank: a 3–4 star general or admiral is C-suite, a
96
+ // 1–2 star a VP, a colonel (a Navy captain) a director, a lieutenant colonel
97
+ // (a commander) a manager, a major (a captain) a senior IC; a command
98
+ // sergeant major or a master chief leads like a manager.
99
+ govLeader: { key: 'govLeader', label: 'Government Leader', level: 6, points: 10 },
100
+ govSenior: { key: 'govSenior', label: 'Senior Official', level: 5, points: 9 },
101
+ judge: { key: 'judge', label: 'Judge', level: 5, points: 9 },
102
+ govOfficial: { key: 'govOfficial', label: 'Government Official', level: 4, points: 7.5 },
103
+ seniorGeneral: { key: 'seniorGeneral', label: 'General / Admiral (3–4 star)', level: 6, points: 10 },
104
+ general: { key: 'general', label: 'General / Admiral (1–2 star)', level: 5, points: 9 },
105
+ colonel: { key: 'colonel', label: 'Colonel / Navy Captain', level: 4, points: 7.5 },
106
+ ltColonel: { key: 'ltColonel', label: 'Lt. Colonel / Commander', level: 3, points: 6.5 },
107
+ seniorEnlisted: { key: 'seniorEnlisted', label: 'Senior Enlisted Leader', level: 3, points: 6.5 },
108
+ nco: { key: 'nco', label: 'Senior NCO / Warrant Officer', level: 2, points: 5 },
109
+ major: { key: 'major', label: 'Major / Captain', level: 2, points: 5 },
52
110
  };
53
111
 
54
112
  // Checked in this order within one part of a headline. Earlier rules REMOVE
55
113
  // their words, so "Vice President" can't also read as "President", "Chief of
56
114
  // Staff" as a chief, or "Product Owner" as an owner. The highest level found wins.
115
+ // A title's possessive is an award or an office named for it, not the title:
116
+ // "President's Club" (sales), "Chairman's Award", "CEO's Office", "Dean's List".
117
+ // Staff are not their boss: "Chief of Staff to the CEO", "Executive Assistant
118
+ // to the General Manager" (but "Promoted to VP" is the VP). Government and
119
+ // military titles aren't here: they count only where a title is written
120
+ // (officeTitle, below).
57
121
  const TITLE_RULES = [
58
- [/\b(reporting )?(to|for) (the |our )?(ceo|cto|coo|cfo|cmo|founders?|co-?founders?|president|chair(man)?)\b/g, null],
122
+ [/\b(reporting )?(to|for) (the |our |a )?(ceo|cto|coo|cfo|cmo|founders?|co-?founders?|president|chair(man)?|professors?|dean|provost|chancellor)\b/g, null],
123
+ // An assistant's boss, with or without "the"; another staff word's only with
124
+ // it ("Associate to VP", "from Manager to GM" are promotions).
125
+ [/(?<!\bfrom\s+(?:[a-z]+\s+){0,2})(?:(?<=\b(?:assistant|aide|advisor|adviser|chief of staff|support|liaison|scheduler|ea)\s+)(to|for) (the |our |a )?|(?<=\b(?:paralegal|clerk|counsel|associate|coordinator|manager)\s+)(to|for) (the|our|a) )(general manager|managing director|gm|vice president|[se]?vp|general counsel|chief counsel)\b/g, null],
59
126
  [/\bchief of staff\b/g, 'director'],
60
127
  [/\b(senior |executive |assistant |associate )?vice[-\s]?president\b|\b(s|e|a)?vp\b/g, 'vp'],
128
+ // Universities, before the C-suite rule reads "Vice Chancellor" as a
129
+ // chancellor: deputies are VPs, and associate and assistant deans, provosts
130
+ // and a department's chair or head are directors. Adjunct, visiting and
131
+ // guest professors teach, as instructors do; an assistant professor is
132
+ // before an associate, an associate before a professor. "Prof." is one too.
133
+ [/\b(vice|deputy)[-\s]?(chancellor|provost)\b/g, 'vp'],
134
+ [/\b(associate|assistant) (dean|provost|chancellor)\b|\b(vice|deputy)[-\s]?dean\b|\b(department|dept\.?) (chair|head)\b|\bchair,? (of )?(the )?(department|dept\.?)\b/g, 'director'],
135
+ [/\b(adjunct|visiting|affiliate|courtesy|guest) (assistant |associate |full )?prof(essor)?\b\.?/g, 'ic'],
136
+ [/\bassistant prof(essor)?\b\.?/g, 'assistantProfessor'],
137
+ [/\bassociate prof(essor)?\b\.?/g, 'associateProfessor'],
138
+ [/\bprof(essor)?\b(?!['’]s\b)\.?/g, 'professor'],
139
+ // A dean only as a title: before "of", "for", a comma or the part's end, and
140
+ // never a company's name ("Dean Foods", "at Dean Health Plan").
141
+ [/(?<!\b(?:at|@)\s*)\bdean\b(?!['’]s\b)(?=\s*(?:(?:of|for|at|and|emerit(?:us|a))\b|[&@,(]|$))/g, 'dean'],
142
+ // A company's general counsel is an executive; the lawyers under a general
143
+ // or a chief counsel are directors and seniors. A military chief (a chief
144
+ // petty officer, a chief warrant officer) isn't a chief officer.
145
+ [/(?<!\b(?:promoted|from\s+[a-z]+(?:\s+[a-z]+)?)\s)\b(?:to|supporting|supports|support to) (?:the|our|a) (?:(?:deputy|associate|assistant) )?(?:(?:general|chief) counsel|division chief|section chief)\b/g, null],
146
+ [/\b(associate|assistant|deputy) general counsel\b/g, 'director'],
147
+ [/\b(associate|assistant|deputy) chief counsel\b/g, 'senior'],
148
+ [/(?<=\b(?:assistant|paralegal|clerk|coordinator|specialist|analyst|aide|supporting|support)\b[^|]*?|\b(?:attorney|lawyer|counsel|associate|manager|administrator)\b[^|,]*,[^|]*?)\b(general|chief) counsel\b/g, null],
149
+ [/\b(?:general|chief) counsel\b(?=[\s,]*(?:['’]s|office|division|practice|group|llp|l\.l\.p|p\.?c\.?|pllc|law|operations|team|department)\b)/g, null],
150
+ [/^\s*(?:(?:(?:senior |executive )?vice president|[se]?vp|chief legal officer|clo|head of legal|corporate secretary|secretary)\s*(?:,|&|and)\s*)*(?:general|chief) counsel\b|(?<=\b(?:[se]?vp|vice president|chief legal officer|clo|head of legal|president|coo|ceo)\s*(?:,|&|and)\s*|\b(?:attorney|lawyer)\s*(?:&|and)\s*)(?:general|chief) counsel\b/g, 'vp'],
151
+ [/\b(?:general|chief) counsel\b/g, null],
152
+ [/\b(senior |master )?chief petty officer\b|\bchief warrant officer\b|\bchief master sergeant\b/g, null],
153
+ // A government's or a lab's division and branch chiefs lead them, and a
154
+ // medical school's section chief is its division chief. A division's or a
155
+ // unit's chief officer is a chief officer ("Division Chief Nursing Officer").
156
+ [/\b(division chief|section chief(?= of\b))\b(?!\s+(\w+\s+){0,3}officer\b|\s+executive\b)|\bchief of (the )?[a-z]+ division\b/g, 'director'],
157
+ [/\b(branch|section|unit) chief\b(?!\s+(\w+\s+){0,3}officer\b|\s+executive\b)|^\s*chief,\s+[a-z &]+ (branch|section|office)\b/g, 'manager'],
158
+ [/^\s*chief,\s+[a-z &]+ division\b/g, 'director'],
61
159
  [/\b(product|process|content|data|feature|service|project|business process) owner\b/g, 'ic'],
62
160
  [/\b(client|channel|strategic|business|brand|creative|agency|solutions?|account|community|developer|technology|alliances?|content|media|marketing|talent|partner) partner\b/g, 'senior'],
63
161
  [/\bpartner (manager|marketing|development|success)\b/g, 'manager'],
64
162
  [/\blead gen(eration)?\b|\bthought leader(ship)?\b/g, null],
65
163
  [/\binvestor relations\b/g, 'ic'],
66
- [/\b(ceo|cto|cfo|coo|cmo|cro|cpo|cio|ciso|cdo|cso)\b|\bchief\s+(\w+\s+){0,3}officer\b|\bchief executive\b|\b(co-?)?founder\b|\bcofounder\b|\bpresident\b|\bchair(man|woman|person)\b|\bexecutive chair\b|\b(general|managing|founding) partner\b/g, 'csuite'],
164
+ [/(?:\b(ceo|cto|cfo|coo|cmo|cro|cpo|cio|ciso|cdo|cso)\b|\bchief\s+(\w+\s+){0,3}officer\b|\bchief executive\b|\b(co-?)?founder\b|\bcofounder\b|\bpresident\b|\bchair(man|woman|person)\b|\bexecutive chair\b|\b(general|managing|founding) partner\b|\bchancellor\b|\bprovost\b)(?!['’]s\b)/g, 'csuite'],
67
165
  [/\b(co-?)?owner\b|\bentrepreneur\b|\bself[-\s]employed\b|\bproprietor\b/g, 'owner'],
68
- [/\bmanaging director\b|\bgeneral manager\b|\bgm\b|\bcountry (manager|director|lead)\b|\bglobal head\b|\bchief (technologist|scientist|architect|economist|evangelist|strategist|engineer|of \w+)\b|^\s*partner\b|\bpartner (at|@)|\b(venture|senior|equity|operating) partner\b|\bboard (member|director|chair)\b|\bchair of the board\b|\bmember of the board\b|\bboard of directors\b/g, 'vp'],
166
+ // "MD" is a managing director only where a doctor's degree can't be meant:
167
+ // at a company that isn't a hospital's or a clinic's ("MD @ J.P. Morgan", read
168
+ // in readPart), or with a division after it ("MD, Investment Banking"), not a
169
+ // degree ("MD, MBA").
170
+ [/\bmanaging director\b|\bmd\b(?=\s*(?:at\s|@))|^\s*md,\s+(?!(?:mba|phd|mph|ms|msc|mhs|mha|mhsa|jd|facs|facp|facc|faap|dds|dmd|do|rn|np|pa|ma|mbe|mpp)\b)|\bgeneral manager\b|\bgm\b|\bcountry (manager|director|lead|head)\b|\bhead of country\b|\bglobal head\b|\bchief (technologist|scientist|architect|economist|evangelist|strategist|engineer|of \w+)\b|^\s*partner\b|\bpartner (at|@)|\b(venture|senior|equity|operating) partner\b|\bboard (member|director|chair)\b|\bchair of the board\b|\bmember of the board\b|\bboard of directors\b/g, 'vp'],
69
171
  [/\b(senior |executive |creative |art |associate )?director\b|\bhead of\b|\bhead\b(?= (coach|chef))|\b(angel |venture )?investor\b|\bprincipal at\b|\b(technical|distinguished|senior) fellow\b|(?<!account |sales |customer )\bexecutive\b(?! (assistant|producer|chef))/g, 'director'],
70
172
  [/\bmanager\b|\bmgr\b|\b(team |tech |design |engineering )?lead\b|\bleader\b|\bprincipal\b|\bstaff (engineer|designer|scientist|product|data)\b|\bsupervisor\b|\bsuperintendent\b/g, 'manager'],
71
173
  [/\bsenior\b|\bsr\b\.?|\bspecialist\b|\barchitect\b|\bexpert\b|\bexecutive producer\b/g, 'senior'],
72
- [/\b(engineer|developer|designer|analyst|associate|coordinator|consultant|strategist|recruiter|creator|producer|editor|writer|artist|scientist|researcher|representative|assistant|administrator|technician|officer|agent|teacher|professor|nurse|attorney|lawyer|accountant|marketer|photographer|videographer|freelancer?|contractor|account executive|creative|influencer|coach|trainer|instructor|advisor|adviser|mentor|programmer|animator|illustrator|planner|buyer|broker|realtor|swe|sde|sre|pm|recruiting)\b/g, 'ic'],
174
+ [/\b(engineer|developer|designer|analyst|associate|coordinator|consultant|strategist|recruiter|creator|producer|editor|writer|artist|scientist|researcher|representative|assistant|administrator|technician|officer|agent|teacher|lecturer|postdoc(toral)?|nurse|attorney|lawyer|accountant|marketer|photographer|videographer|freelancer?|contractor|account executive|creative|influencer|coach|trainer|instructor|advisor|adviser|mentor|programmer|animator|illustrator|planner|buyer|broker|realtor|swe|sde|sre|pm|recruiting)\b/g, 'ic'],
73
175
  ];
74
176
 
75
177
  const INTERN = /\b(intern|internship|trainee|apprentice)\b/;
@@ -108,7 +210,33 @@ const SHORT_NAME_CLUB = /\b(club|society)\b/;
108
210
  const FIELD_ASSOCIATION = /\b(marketing|finance|financial|business|economics|accounting|consulting|investment|investing|entrepreneurship|engineering|computer science|data science|nursing|pre-?law|pre-?med|students?)\b.*\bassociation\b/;
109
211
  // An alumni club or a parents' association is for grown-ups.
110
212
  const GROWN_UP = /\b(alumni|alumnae|alumnus|alum|parents?)\b/;
111
- const FORMER = /^\s*(ex[-\s]|former(ly)?\b|previously\b|prev\b|past\b|retired\b)/i;
213
+ const FORMER = /^\s*(ex[-\s]|former(ly)?\b|previously\b|prev\b|past\b|retired\b|ret(\.|d\.?)?\s)/i;
214
+ // Retired, written after the title: "Colonel (Ret.), U.S. Army", "COL (R)",
215
+ // "Admiral, USN, Ret.", "Army Colonel, Retired". A former role, like "Ex-" or
216
+ // "Retired" before it. A part that says only that ("Colonel, USAF - Retired")
217
+ // makes the role before it former (readRoles).
218
+ const RETIRED = /\(\s*(?:[a-z.]+,\s*)?ret(\.|ired|d\.?)?\s*\)|,\s*ret(\.|ired|d\.?)?\s*(?=,|$)|,\s*retired\s*(?=,|\)|$)|\bret\.\s*$|\b(army|navy|air force|marine corps|marines|usmc|usaf|usn|uscg|coast guard|space force)\s+(ret(\.|d\.?)?|retired)\s*$/i;
219
+ const RETIRED_ONLY = /^\s*\(?\s*(ret\.?|retd\.?|retired)\s*\)?\s*$/i;
220
+ // An office named for its head is where someone works, not their title: "IT
221
+ // Specialist, Office of the Chief Information Officer", "Attorney, Judge
222
+ // Advocate General's Corps". Only the head's title is taken out, so a title
223
+ // written after an office's own name stays ("Office of Technology Licensing
224
+ // Director").
225
+ const OFFICE_NAME = /\boffice of (the )?(chief [a-z]+ officer|ceo|cto|cfo|coo|cio|ciso|cmo|president|vice president|general counsel|chief counsel|inspector general|solicitor general|surgeon general|attorney general|(under |deputy )?secretary( of [a-z ]+?)?|governor|lieutenant governor|mayor|director( of [a-z ]+?)?|chair(man)?|commissioner|(u\.?s\.? )?(senator|congress(wo)?man|representative)( [a-z.]+){0,3})( of (the )?[a-z.& ]+?)?(?=\s*(,|$|\||\(|\sat\s|@))|\b(judge advocate|adjutant) general['’]?s? corps\b|\b(general|chief) counsel['’]?s? (office|division|section|staff|team|department)\b|\boffice of (the )?(general|chief) counsel\b/g;
226
+ // The company after "at" says where someone works, not what they do: its
227
+ // words aren't read as a title ("Server at President Hotel", "Driver at
228
+ // Executive Limo"). It runs to the next comma, a bracket, an emoji, or to
229
+ // what starts another title or says what they do there: "at Stripe as Head
230
+ // of Growth", "at Goldman Sachs (VP)", "at Google and Founder of Northwind".
231
+ // "at" is the word alone: "AT&T Director" and "At-Large Director" are titles.
232
+ // A part that starts with "at" has its title in the company's span ("At Home
233
+ // Store Manager", "At Microsoft: Principal PM"), so nothing is taken out.
234
+ const AT_COMPANY = /(?<=\S.*?)(\s(?:at\s|@)\s*)(?:(?!\s(?:as|where|leading|building|helping|working|and|while|also|plus|now|since|then|formerly|previously|x|in (?:19|20)\d\d)\s|\s[&+/]\s|\.\s|\s(?:at\s|@)|\s\S+(?:\s\S+)?\s(?:of|at|for)\s|\s\S+(?:\s\S+)?\s?@|\s?(?:→|►|->|=>)|[:(\[/\p{Extended_Pictographic}])[^,|])*/gu;
235
+ const HEALTH_ORG = /\b(?:hospitals?|clinics?|health|healthcare|medical|medicine|physicians?|pediatrics?|surgery|surgical|kaiser|mayo|hopkins|dermatology|cardiology|oncology|orthopa?edics?|urgent care)\b/;
236
+ // A doctor's specialty written after the hospital: "MD at Emory, Pediatrics".
237
+ // Not a banker's coverage group ("MD at Goldman Sachs, Healthcare").
238
+ const CARE_PLACE = /\b(?:hospitals?|clinic\w*|medical (?:center|school|group|director)|health system|school of medicine|residency|fellow(?:ship)?|resident|attending|physician|surgeon|hospitalist|professor|pediatric\w*|surg\w*|cardiolog\w*|oncolog\w*|hematolog\w*|orthopa?edic\w*|medicine|radiolog\w*|anesthesi\w*|psychiatr\w*|neurolog\w*|dermatolog\w*|urolog\w*|ophthalmolog\w*|patholog\w*|obstetric\w*|gynecolog\w*|gastroenterolog\w*|nephrolog\w*|endocrinolog\w*|rheumatolog\w*|pulmon\w*|geriatric\w*|palliative|critical care|primary care|infectious disease\w*|neonatolog\w*|otolaryngolog\w*|immunolog\w*|emergency|trauma)\b/;
239
+ const SPECIALTY = /^(?:[a-z-]+ ){0,2}(?:pediatrics?|surgery|cardiology|oncology|orthopa?edics?|medicine|radiology|anesthesiology|anesthesia|psychiatry|neurology|dermatology|urology|ophthalmology|pathology|obstetrics(?: and gynecology)?|gynecology|ob\/?gyn|neurosurgery|gastroenterology|nephrology|endocrinology|rheumatology|pulmonology|hematology|geriatrics|palliative care|critical care|primary care|infectious diseases?|hospitalist|neonatology|otolaryngology|allergy(?: and immunology)?|immunology|emergency|trauma)$/;
112
240
 
113
241
  /** Can this short name ("USC", "UBS") be a school's? Not one on NOT_A_SCHOOL, nor a company the curated list knows. */
114
242
  function schoolShortName(name) {
@@ -118,7 +246,11 @@ function schoolShortName(name) {
118
246
  }
119
247
 
120
248
  /** Does this part of a headline say they're studying now? "CS @ NYU", "Economics student". */
249
+ // A war or staff college's students are serving officers, not students.
250
+ const SERVICE_SCHOOL = /\b(war college|staff college|command and general staff|naval postgraduate school|air university|national defense university|eisenhower school|joint forces staff college|school of advanced (military|air|warfighting))\b/i;
251
+
121
252
  function studies(part) {
253
+ if (SERVICE_SCHOOL.test(part)) return false;
122
254
  if (STUDENT.test(` ${part.toLowerCase()} `)) return true;
123
255
  const at = MAJOR.test(part) && AT_SHORT_NAME.exec(part);
124
256
  return !!at && schoolShortName(at[1]);
@@ -141,12 +273,17 @@ function isSchoolClub(part) {
141
273
 
142
274
  /** The parts of a headline, in order: "CEO @ X | Ex-Google | Speaker" → three parts. */
143
275
  export function headlineParts(headline = '') {
144
- return String(headline || '').split(/\s*(?:\||•|·|⋅|\/\/| – | — | - |;)\s*/).map((s) => s.trim()).filter(Boolean);
276
+ return String(headline || '').normalize('NFKC').split(/\s*(?:\||•|·|⋅|\/\/| – | — | - |;)\s*/).map((s) => s.trim()).filter(Boolean);
145
277
  }
146
278
 
147
279
  function readPart(part) {
148
- let s = ` ${part.toLowerCase()} `;
280
+ let s = ` ${part.toLowerCase()} `.replace(OFFICE_NAME, ' ');
281
+ // "MD at a hospital" is a doctor, which only the company (or a specialty
282
+ // after it) says.
283
+ const at = s.match(/\s(?:at\s|@)\s*([^,|]*)((?:,[^,|]*)*)/);
284
+ if (at && /\bmd\b(?=\s*(?:at\s|@))/.test(s) && (HEALTH_ORG.test(at[1]) || at[2].split(',').some((p) => SPECIALTY.test(p.trim()) || CARE_PLACE.test(p)))) s = s.replace(/\bmd\b/, ' ');
149
285
  if (INTERN.test(s)) return LEVELS.intern;
286
+ s = s.replace(AT_COMPANY, '$1 ');
150
287
  if (studies(part)) return LEVELS.student;
151
288
  let best = null;
152
289
  for (const [re, key] of TITLE_RULES) {
@@ -159,33 +296,778 @@ function readPart(part) {
159
296
  return best;
160
297
  }
161
298
 
299
+ // ── government and the services ─────────────────────────────────────────────
300
+ // A government or military title counts only where a title is written: the
301
+ // start of a headline part, before its organization ("Senator, U.S. Senate",
302
+ // "Colonel | U.S. Air Force", "Deputy Secretary of Defense"). Anywhere else
303
+ // the same words name an office, a company or a club: "Staff Assistant,
304
+ // Office of the Secretary of Defense", "Store Manager at Dollar General",
305
+ // "Law Clerk to Chief Judge…". And a title means government only where its
306
+ // own organization is a government's (where(), below: "Speaker at Soho
307
+ // House", "Administrator at U.S. Bank" and "City Manager, Uber" aren't), and a
308
+ // club, a church, a school, a profession, a mock government, an honorary or a
309
+ // joke title never is (CIVIC: "Rotary District Governor", "Delegate, AMA House
310
+ // of Delegates", "Governor, Florida Boys State", "Mayor of Fun at Northwind";
311
+ // MOCK anywhere in the headline). Every rank but
312
+ // the flag ranks spelled out needs its service beside it, in the same part or
313
+ // as a part of its own ("Captain | U.S. Navy"), and nothing a veterans' group,
314
+ // a cadet, a team, a licence or an honorary title holds is a commission
315
+ // (NOT_MILITARY: "Kentucky Colonel", "Commander, VFW Post 42", "Captain, Navy
316
+ // Rugby", "Master Chief | Halo Cosplayer"). A captain is a colonel's equal only
317
+ // in a navy; a commander's level is their unit's (a division's is a general).
318
+ // Four rounds of adversarial review found what these rules keep out; the
319
+ // cases are in tests/scoring-misses.test.mjs.
320
+ const STATES = String.raw`alabama|alaska|arizona|arkansas|california|colorado|connecticut|delaware|florida|georgia|hawaii|idaho|illinois|indiana|iowa|kansas|kentucky|louisiana|maine|maryland|massachusetts|michigan|minnesota|mississippi|missouri|montana|nebraska|nevada|new hampshire|new jersey|new mexico|new york|north carolina|north dakota|ohio|oklahoma|oregon|pennsylvania|rhode island|south carolina|south dakota|tennessee|texas|utah|vermont|virginia|washington|west virginia|wisconsin|wyoming|puerto rico|guam|american samoa|(?:the )?(?:u\.?\s?s\.?\s)?virgin islands|(?:the )?northern mariana islands|district of columbia`;
321
+ const COUNTRIES = String.raw`afghanistan|albania|algeria|andorra|angola|argentina|armenia|australia|austria|azerbaijan|the bahamas|bahamas|bahrain|bangladesh|barbados|belarus|belgium|belize|benin|bhutan|bolivia|bosnia and herzegovina|botswana|brazil|brunei|bulgaria|burkina faso|burundi|cabo verde|cambodia|cameroon|canada|central african republic|chad|chile|china|colombia|comoros|congo|costa rica|cote d'ivoire|ivory coast|croatia|cuba|cyprus|czech republic|czechia|denmark|djibouti|dominica|dominican republic|ecuador|egypt|el salvador|equatorial guinea|eritrea|estonia|eswatini|ethiopia|fiji|finland|france|gabon|the gambia|gambia|georgia|germany|ghana|greece|grenada|guatemala|guinea|guinea-bissau|guyana|haiti|the holy see|holy see|honduras|hungary|iceland|india|indonesia|iran|iraq|ireland|israel|italy|jamaica|japan|jordan|kazakhstan|kenya|kiribati|kosovo|kuwait|kyrgyzstan|laos|latvia|lebanon|lesotho|liberia|libya|liechtenstein|lithuania|luxembourg|madagascar|malawi|malaysia|maldives|mali|malta|marshall islands|mauritania|mauritius|mexico|micronesia|moldova|monaco|mongolia|montenegro|morocco|mozambique|myanmar|burma|namibia|nauru|nepal|the netherlands|netherlands|new zealand|nicaragua|niger|nigeria|north korea|north macedonia|norway|oman|pakistan|palau|panama|papua new guinea|paraguay|peru|the philippines|philippines|poland|portugal|qatar|romania|russia|rwanda|saint kitts and nevis|saint lucia|saint vincent and the grenadines|samoa|san marino|sao tome and principe|saudi arabia|senegal|serbia|seychelles|sierra leone|singapore|slovakia|slovenia|solomon islands|somalia|south africa|south korea|the republic of korea|korea|south sudan|spain|sri lanka|sudan|suriname|sweden|switzerland|syria|taiwan|tajikistan|tanzania|thailand|timor-leste|togo|tonga|trinidad and tobago|tunisia|turkey|turkiye|turkmenistan|tuvalu|uganda|ukraine|the united arab emirates|united arab emirates|the united kingdom|united kingdom|great britain|uruguay|uzbekistan|vanuatu|venezuela|vietnam|yemen|zambia|zimbabwe|the kyrgyz republic|kyrgyz republic|the slovak republic|slovak republic|lao pdr|viet nam|the vatican|vatican|osce|the osce`;
322
+ // A country's own forces: "French Navy", "German Army" (not the Swiss Army, a knife).
323
+ const NATIONS = String.raw`u\.?\s?s\.?|united states|royal|british|canadian|australian|indian|israeli|french|german|italian|spanish|dutch|polish|norwegian|swedish|danish|finnish|japanese|korean|south korean|republic of korea|philippine|mexican|brazilian|new zealand|irish|belgian|greek|hellenic|turkish|ukrainian|singapore|south african|pakistani|egyptian|saudi|nigerian|kenyan|argentine|chilean|colombian|peruvian|portuguese|czech|romanian|hungarian|estonian|latvian|lithuanian|jordanian|emirati|qatari|taiwanese|thai|malaysian|indonesian|vietnamese|bangladeshi|sri lankan|nepalese|austrian`;
324
+ const INTERNATIONAL = String.raw`the united nations|united nations|u\.?n\.?|nato|the european union|european union|the organization of american states|organization of american states|the african union|african union|asean|the world trade organization|world trade organization|the oecd|oecd|opec|interpol`;
325
+ const STATE_NAME = new RegExp(String.raw`\b(${STATES})\b`);
326
+ // A state's government named as the place it is: "State of Florida", "Commonwealth of Virginia".
327
+ const STATE_GOV = new RegExp(String.raw`\b(?:state|commonwealth) of (?:${STATES})\b|\b(?:${STATES}) (?:state )?(?:government|legislature|senate|house of (?:representatives|delegates)|general assembly|state assembly|supreme court)\b|(?:^|[,|(@:]\s*|\b(?:the|at|of|for|with|in)\s)(?:${STATES}) (?:state )?(?:department|agency|office|cabinet)\b`);
328
+ // A place that is only a state: the whole part says nothing else.
329
+ const JUST_A_STATE = new RegExp(String.raw`^(?:the )?(?:(?:state|commonwealth) of )?(?:${STATES})(?: state)?$`);
330
+ // A government's departments: "Department of Defense", not "Department of Surgery".
331
+ const DEPT = String.raw`(?:the )?(?:state|defense|war|justice|treasury|interior|agriculture(?: and consumer services)?|commerce|labor(?: and (?:industry|workforce development))?|health(?: and human services| and mental hygiene)?|human services|social services|children and famil(?:y|ies)(?: services)?|(?:higher )?education|energy|transportation|veterans (?:affairs|services)|homeland security|housing(?: and urban development)?|army|navy|air force|environmental (?:protection|quality|conservation)|natural resources|conservation|fish and (?:wildlife|game)|parks(?: and recreation)?|revenue|taxation|finance(?: and administration)?|corrections|public safety|motor vehicles|highway safety(?: and motor vehicles)?|juvenile justice|law|insurance|financial (?:services|institutions)|banking(?: and finance)?|economic (?:development|opportunity|security)|community (?:affairs|development)|workforce development|employment(?: security)?|public health|mental health|developmental services|aging|elder affairs|military affairs|emergency management|information technology|administrative services|general services|management services|business(?: and professional)? regulation|consumer affairs|water resources|environment|public works|sanitation|buildings|city planning|homeless services|police|fire)`;
332
+ // Where a government title may name its government: its own body, not "U.S. Bank".
333
+ const GOV_ORG = new RegExp(String.raw`^(?:the )?(?:u\.?\s?s\.?|united states|federal|state of|commonwealth of|city of|county of|town of|village of|borough of|township of)\b[^,|]*?\b(?:department|dept\.?|agency|administration|bureau|commission|board|office|service|authority|court|senate|house of representatives|assembly|legislature|congress|marshals|attorney['’]?s office|embassy|mission)(?: of [a-z ,&'.-]+| for [a-z ,&'.-]+)?$|\b(?:department|dept\.?) of ${DEPT}\b|\b(?:senate(?!\s+(?:bank|federal|credit|capital|group|partners|consulting|solutions|inc|llc))|house of representatives|house of delegates|state assembly|legislature|library of congress|congressional (?:budget office|research service)|(?:u\.?\s?s\.?|united states|${STATES}|state) supreme court|supreme (?:judicial )?court of (?:the )?[a-z ]+|court of appeals|(?:district|circuit|superior|county|municipal|probate|family|juvenile|tax|bankruptcy) court|judicial circuit|supreme judicial court|court of (?:criminal )?appeals|appeals court|court of chancery|court of federal claims|court of international trade|appellate (?:court|division)|(?:congressional|legislative|house|senate|assembly) district|city council|town council|county commission|board of (?:county )?commissioners|board of supervisors|police department|sheriff['’]?s office|state attorney['’]?s office|district attorney['’]?s office|parliament)\b|^(?:the )?white house(?: office| staff| press office| national security council)?$|\bexecutive office of the president\b|\b(?:u\.?\s?s\.?|american) (?:embassy|consulate)\b|\b(?:embassy|consulate(?: general)?) (?:of|in)\b|\b(?:city|county|state|federal|tribal|municipal|local) government$|^(?:the )?government of\b|${STATE_GOV.source}`);
334
+ // Not a government's: clubs, churches, schools and students, professions,
335
+ // mock governments, honorary and joke titles.
336
+ const CIVIC = /\b(rotary|lions clubs?|kiwanis|circle k|jaycees|jci|toastmasters|optimist|civitan|elks|moose|masonic|freemasons?|lodge|knights of columbus|pta|pto|students?|sga|asg|associated students|student government|model (un|united nations|congress|senate|legislature|g20|nato|oas)|\w*mun|boys state|girls state|youth (in|and) government|mock (trial|congress|legislature|government)|intercollegiate|faculty|(staff|faculty|student|graduate|university|employee|classified|academic|campus) (senate|assembly)|honor (court|council|board)|scouts?|fraternity|sorority|district \d{4}|alumni|model parliament|youth parliament|high school|middle school|olympics|ama|aba|american medical association|american bar association|chamber of commerce|youth|church|catholic|diocese|synod|presbyterian|methodist|baptist|episcopal|lutheran|congregation|ministry|ministries|vestry|temple|mosque|synagogue|daughters of the american revolution|sons of the american revolution|lineage|association|society|convention|cosplay|honorary|fantasy|kickball|softball|soccer|baseball|basketball|football|hockey|bowling|golf|pickleball|volleyball|rugby|lacrosse|chess|cornhole|tennis|swim|rodeo|athletics?|league|clubs?|tournament|esports|gaming|panhellenic|interfraternity|greek life|honors college|debate|key club|builders club|american legion|vfw|veterans of foreign wars|freemasonry|scottish rite|shriners|collectors|hoa|homeowners|condo|undergraduate|scouting|bsa|deca|ffa|4-h|fbla|hosa|skillsusa|y ?& ?g|girlguiding|brownies|guides|st john ambulance|chamber|state bar|bar of|oxford union|cambridge union|debating (?:union|society)|youth council|bodybuilding|physique|npc|ifbb|powerlifting|junior chamber|republicans?|democrats?|democratic party|republican party|libertarian|green party|young republicans|young democrats|college republicans|college democrats|party of|gop|teen|campus|neighborhood watch|homeschool(?:ing|er)?|of (fun|vibes|content|culture|coffee|memes|good vibes|snacks|hot takes|takes|chaos|hustle|growth|mischief|awesome|everything|all things|sales|marketing|the (internet|office|slack|break room|group chat|home|family|kitchen|grill)|my (house|home|family|kitchen)))\b|\b(bar|medical|nursing|hospital|dental|bankers|realtors?) (association|board of governors)\b|\bboard of governors\b(?! of the federal reserve)/;
337
+ // Mock governments, anywhere in a headline: no official lists one.
338
+ const MOCK = /\b(boys state|girls state|boys nation|girls nation|model (?:[a-z]+ )?(un|united nations|congress|senate|legislature|g20|nato|oas|oecd|asean|parliament|supreme court|court|government|cabinet|eu|european union|arab league|african union|city council)|\w+mun|mun|youth (in|and|&) government|youth (parliament|senate|legislature|council)|mock (trial|congress|legislature|government|election)|junior state of america|junior chamber|jci|cowboy action|sass|reenact\w*|student (?:parliament|supreme court|court))\b/;
339
+ // A part about someone's past or a role beside the mock body isn't one: "Model UN Alumni".
340
+ const MOCK_PAST = /\b(alumni|alum|former|ex-|coach|advis[eo]r|mentor|judge|volunteer|director)\b/;
341
+ // A city's, a county's or a school district's government, as its own name
342
+ // says: "City of Orlando", "Orange County", "Broward County Public Schools",
343
+ // "Orlando Fire Department", "District 5".
344
+ const LOCAL_GOV = /^(?:the )?(?:city|town|village|borough|township|county|parish|municipality) of (?!hope\b)[a-z]|\b(?:city|town|village|county) (?:hall|government|commission)\b|^(?:the )?(?:[a-z.'-]+ ){1,3}(?:county|metropolitan|metro|city|town) council$|^(?:the )?city and county of [a-z]|\bboard of (?:county )?(?:commissioners|supervisors|aldermen|selectmen|education)\b|\b(?:public schools|school district|independent school district|isd|unified school district|county schools)\b|\bfire (?:rescue|department|district)\b|\bpolice department\b|\bsheriff['’]?s? (?:office|department)\b/;
345
+ // A county, a district or a ward named alone is a place: a local office's
346
+ // ("Commissioner, Orange County", "Council Member, District 5"), or where
347
+ // anyone else works ("Ambassador | Orange County | lululemon").
348
+ const LOCAL_PLACE = new RegExp(String.raw`^(?:(?:[a-z.'-]+ ){1,3}(?:county|parish)(?: government)?|(?:district|ward|precinct|seat|place) \d+|\d+(?:st|nd|rd|th) district|at-large)(?:,\s*(?:[a-z]{2}|${STATES}))?$`);
349
+ // Tribal nations, by the names most use.
350
+ const TRIBES = String.raw`cherokee|navajo|choctaw|chickasaw|muscogee|creek|seminole|osage|oneida|seneca|mohawk|onondaga|potawatomi|shawnee|comanche|kiowa|apache|hopi|zuni|lakota|dakota|oglala|sioux|ojibwe|chippewa|ho-chunk|menominee|blackfeet|crow|shoshone|arapaho|ute|yakama|nez perce|tlingit|haida|lumbee|pequot|mashantucket|mohegan|miccosukee|cheyenne|pawnee|quapaw|wyandotte|delaware|lenape|kickapoo|winnebago|omaha|ponca|tohono o'odham|gila river|salt river|pascua yaqui|yaqui|colville|tulalip|puyallup|lummi|makah|nisqually|quinault|coeur d'alene|kootenai|salish|klamath|karuk|yurok|hoopa|pechanga|morongo|agua caliente|san manuel|chumash|pomo|miwok|washoe|paiute|jicarilla|mescalero|laguna|acoma|isleta|jemez|taos|narragansett|wampanoag|passamaquoddy|penobscot|catawba|coushatta|chitimacha`;
351
+ // A tribe's government, not a business it owns ("Cherokee Nation Businesses")
352
+ // or a brand with a tribe's word ("Tribe Capital", "Growth Nation").
353
+ const TRIBAL_GOV = new RegExp(String.raw`\b(?:${TRIBES})(?: (?:indian|tribal))? (?:nation|tribe|tribes|indians|indian community|indian tribe|reservation)(?: of (?:the )?[a-z ]+)?$|\b(?:${TRIBES})[a-z -]* indian community\b|\b(?:nation|tribe|pueblo|band) of (?:the )?(?:${TRIBES})\b|\bpueblo of [a-z]+|\b(?:tribal (?:council|government|court|nation)|indian (?:community|reservation|tribe)|rancheria|first nations?)$|\bband of [a-z ]+ indians\b`);
354
+ const TRIBAL_BUSINESS = /\b(businesses|enterprises|holdings|entertainment|gaming|casino|resort|industries|development corporation|corp|corporation|inc|llc)\b/;
355
+ // A legislature named as the whole organization: "Florida Senate", "U.S. House of Representatives".
356
+ const LEGIS = new RegExp(String.raw`^(?:the )?(?:(?:u\.?\s?s\.?|united states|${STATES})\s+)?(?:state\s+)?(?:house of (?:representatives|delegates)|senate|legislature|congress)$|^(?:the )?senate of (?:the )?[a-z ]+$|^(?:the )?(?:${NATIONS}) senate$|^(?:(?:${STATES}) )?(?:state )?(?:house|senate|assembly|legislative) district \d+$|^(?:the )?(?:${STATES})\s+(?:state\s+)?(?:house|assembly|general assembly)$|^(?:the )?state (?:house|assembly)$`);
357
+ // A state's government itself, as the whole organization: "State of Florida".
358
+ const STATE_ITSELF = new RegExp(String.raw`^(?:the )?(?:(?:state|commonwealth|territory) of (?:${STATES})|(?:${STATES})(?: state)? government|government of (?:${STATES}))$`);
359
+ // A federal agency, by its name or its initials, at the start of an organization: "FBI Miami Field Office".
360
+ const AGENCY_NAMES = String.raw`(?:u\.?\s?s\.?\s|united states )?(?:environmental protection agency|federal aviation administration|federal emergency management agency|national aeronautics and space administration|transportation security administration|agency for international development|drug enforcement administration|national highway traffic safety administration|general services administration|small business administration|centers for medicare (?:and|&) medicaid services|federal highway administration|federal transit administration|federal railroad administration|maritime administration|national oceanic and atmospheric administration|federal bureau of investigation|internal revenue service|social security administration|customs and border protection|immigration and customs enforcement|citizenship and immigration services|secret service|marshals service|bureau of alcohol, tobacco, firearms and explosives|occupational safety and health administration|food and drug administration|veterans health administration|executive office for immigration review|border patrol)`;
361
+ const AGENCY_INITIALS = String.raw`fcc|sec|ftc|fec|nrc|ferc|cftc|eeoc|nlrb|uspto|fdic|cfpb|epa|faa|fema|nasa|tsa|usaid|dea|nhtsa|gsa|sba|cms|fhwa|fta|fra|noaa|fbi|irs|ssa|cbp|uscis|atf|osha|fda|vha|hsi|usss|usms|dhs|doj|hud|usda|hhs`;
362
+ const AGENCY = new RegExp(String.raw`^(?:the )?(?:${AGENCY_NAMES}|(?:u\.?\s?s\.?\s)?(?:${AGENCY_INITIALS}))(?:,?\s+(?:(?:[a-z.]+\s+){0,2}(?:field|district|regional|area|resident) office|region(?:al office)?(?: \d+| [ivx]+)?|headquarters|hq|(?:[a-z]+\s+){0,2}(?:division|sector)))?$`);
363
+ const AGENCY_EXACT = new RegExp(String.raw`^(?:the )?(?:${AGENCY_NAMES}|(?:u\.?\s?s\.?\s)(?:${AGENCY_INITIALS}))$`);
364
+ // An organization that isn't a government's, whatever else it says: "State of Florida Credit Union".
365
+ const NOT_GOV = /\b(credit union|fcu|bank|inc|llc|corp|corporation|company|foods|brands|pharma\w*|holdings|solutions|consulting|partners|realty|dental|university|college|academy|montessori|preparatory|prep school|day school|christian school|catholic school|hospital|health system|medical center|church|association|society|club|league|foundation|chapter|tech council|chamber|hotel|inn|suites|resort|restaurant|podcast|show|radio|meeting|forum|market|coffee|cafe|grill|garage|grocery|salon|studio|brewing|bistro|tavern|pub|deli|bakery|gallery|pac|press|accounts?|team|programs|contracts|relations|partnerships)\b/;
366
+ // A part that names no organization: a place, a credential, who they are.
367
+ const PLACE = new RegExp(String.raw`^(?:the )?(?:(?:state|commonwealth) of )?(?:${STATES}|${COUNTRIES})(?: state)?$|^[a-z .'-]+,\s*[a-z]{2}$|^[a-z]{2}$|\b(?:area|metro|region|based)\b`);
368
+ const NOT_AN_ORG = /^(?:cpa|mba|phd|jd|esq\.?|md|rn|pmp|cfa|cfp|pe|ms|ma|mpa|mph|llm|shrm-[a-z]+)$|\b(?:veteran|vet|mom|dad|mother|father|husband|wife|parent|grand(?:ma|pa|mother|father|parent)|christian|believer|author|speaker|podcaster|host|advocate|volunteer|mentor|runner|golfer|traveler|lover|enthusiast|fan|licensed|admitted|bar|retired|former)\b/;
369
+ const LEAD = String.raw`(?:(?:acting|interim|the|honorable|hon\.?|\d+(?:st|nd|rd|th)|principal|u\.?\s?s\.?|united states|(?:two|three|four|five|\d)[-\s]term|longtime|elected|sitting|incumbent|current|active duty)\s+)*`;
370
+ // A company's or a board's officers: "Assistant Secretary of the Corporation", "of Acme Holdings Inc.".
371
+ const CORP_OFFICER = /\b(corporation|company|board|inc\.?|llc|holdings|ltd|plc|trust|fund|bank|partners|group)\b/;
372
+ // Judging that isn't a court's: competitions, fairs, moot courts, a food court.
373
+ const NOT_COURT = /\b(universit(y|ies)|college|students?|sga|moot|mock|sommeliers?|food court|fairs?|competitions?|hackathons?|pageants?|shows?|debate|awards?|contests?|olympiads?|festivals?|teen court|cook-?off|bake-?off|rodeo|barrel racing|cheer(?:leading)?|bbq|barbecue|chili|ffa|4-h|livestock|cattle|horse show|equestrian|kennel club|dog show|gymnastics|figure skating|culinary|robotics|spelling bee|martial arts|pitch|startup|demo day|shark tank|bodybuilding|physique|npc|ifbb|powerlifting|car shows?|dance|cheer)\b/;
374
+ const FED_BODY = String.raw`(?:u\.?\s?s\.?\s|united states )?(?:securities and exchange commission|consumer product safety commission|nuclear regulatory commission|commodity futures trading commission|equal employment opportunity commission|international trade commission|federal (?:communications|trade|election|energy regulatory|maritime) commission|federal deposit insurance corporation|federal reserve(?! bank)(?: board| system)?|board of governors of the federal reserve(?: system)?|national (?:labor relations|transportation safety) board|internal revenue service|food and drug administration|social security administration|customs and border protection|council of economic advisers)`;
375
+
376
+ // The services, and the units and bases that say which one.
377
+ const SVC = String.raw`(?:(?:${NATIONS})\s+)?(?:army national guard|air national guard|national guard|army reserves?|navy reserves?|naval reserves?|air force reserves?|marine corps reserves?|coast guard reserves?|army (?:nurse|medical|dental|medical service|medical specialist|veterinary|chaplain) corps|navy (?:nurse|medical service|chaplain) corps|army|navy|air force|marine corps|marines|space force|coast guard|armed forces|canadian armed forces|department of defense|public health service(?: commissioned corps)?|noaa corps|noaa commissioned officer corps)|(?:u\.?\s?s\.?|united states) marine|\b(?:usmc|usmcr|usaf|usafr|afrc|usn|usnr|uscg|uscgr|ussf|usar|arng|ang|usphs|dod|raf|idf)\b`;
378
+ // "Army" and "Navy" alone are also a crowd's or a brand's words ("Church Army",
379
+ // "Brand Army", "Grassroots Army"): alone, a service is the whole organization
380
+ // ("Captain, U.S. Navy", "Colonel, Army National Guard"), or qualified.
381
+ const QUALIFIED_SVC = String.raw`(?:(?:${NATIONS}|the)\s+(?:army|navy|air force|marine corps|marines|space force|coast guard)|army national guard|air national guard|national guard|(?:army|navy|naval|air force|marine corps|coast guard) reserves?|air force|marine corps|space force|coast guard|armed forces|department of defense|public health service|noaa corps|noaa commissioned officer corps|army (?:nurse|medical|dental|medical service|medical specialist|veterinary|chaplain) corps|navy (?:nurse|medical service|chaplain) corps)|(?:u\.?\s?s\.?|united states) marine|\b(?:usmc|usmcr|usaf|usafr|afrc|usn|usnr|uscg|uscgr|ussf|usar|arng|ang|usphs|dod|raf|idf)\b`;
382
+ const NOT_SVC_AFTER = String.raw`(?!\s(?:spouses?|wife|wives|husbands?|moms?|mothers?|dads?|fathers?|grandmas?|grandpas?|brats?|famil(?:y|ies)|kids?|rotc|jrotc|federal|exchange|cross|pier|surplus|one|league|association|times|history|museum|band|academy|veterans?|vet|of|navy|army|surplus|store|beach|lifeguards?|blue|ferry|taxi|island|chess|debate|esports|rifle|pistol|sports|athletics|club|team|choir|chorus|yard|coffee|brewing|supply|outfitters|paintball|airsoft|wrestling|swimming|rugby|lacrosse|football|soccer|basketball|baseball|hockey|golf|tennis|volleyball|softball|sailing|rowing|crew)\b)`;
383
+ const SERVICE_IN = new RegExp(String.raw`(?<!(?:salvation|old|texas|nebraska|great|commemorative|church|brand|grassroots)\s)(?:${QUALIFIED_SVC})${NOT_SVC_AFTER}|\b(?:uss|usns|uscgc|afb)\s|\bnaval\b|\bv[a-z]{1,3}-\d+\b|\b(?:air force base|joint base|naval air station|naval station|marine corps (?:base|air station)|marine (?:division|expeditionary|regiment|aircraft wing|logistics group))\b|\b\d+(?:st|nd|rd|th) (?:[a-z]+ ){0,2}(?:division|brigade|battalion|regiment|wing|squadron|fleet|corps|group|airborne|infantry|cavalry)\b|\b(?:u\.?\s?s\.? )?(?:central|european|pacific|indo-pacific|africa|southern|northern|special operations|cyber|space|strategic|transportation) command\b|\b(?:pacific|u\.?\s?s\.? air forces in europe|air forces) air forces?\b|\bpacific air forces\b|\b(?:army|navy|air force|marine corps|fleet) forces command\b|\bnavy region\b|\b(?:u\.?\s?s\.? )?(?:pacific|atlantic|fleet forces|\d+(?:st|nd|rd|th)|second|third|fifth|sixth|seventh) fleet\b|\b(?:air combat|air mobility|air education and training|global strike|materiel|training and doctrine|forces|futures|sealift|military sealift|space and missile systems) command\b`);
384
+ // A part whose organization is just a service ("Colonel, Army", "Captain, Navy").
385
+ const REST_IS_SERVICE = new RegExp(String.raw`^(?:the\s+)?(?:${SVC})\b${NOT_SVC_AFTER}`);
386
+ const NAVY_IN = new RegExp(String.raw`(?<!(?:old|texas|nebraska|great)\s)\b(?:navy|naval|usn|usnr|coast guard|uscg|uscgr|noaa corps|noaa commissioned officer corps|public health service|usphs|uss|usns|uscgc)\b${NOT_SVC_AFTER}`);
387
+ // A part that is only a service ("U.S. Navy", "Retired U.S. Army", "USAF (Ret.)").
388
+ const SERVICE_ONLY = new RegExp(String.raw`^(?:(?:retired|former|ret\.?|retd\.?)\s+)?(?:the\s+)?(?:(?:${STATES})\s+)?(?:${SVC})(?:\s+reserves?)?(?:,?\s*(?:\((?:ret\.?|retd\.?|retired|active duty)\)|ret\.?|retd\.?|retired|active duty))?$`);
389
+ const RETIRED_SERVICE = /^(retired|former|ret\b)|\bret\.?\)?$|\bretired\)?$/;
390
+ // A service's retirement tag, a rank or two between: "U.S. Army (Ret.)", "(USAF, Ret.)", "Army Colonel (Retired)".
391
+ const SERVICE_RETIRED = new RegExp(String.raw`(?:${SVC})(?:\s+[a-z.]+){0,2}[\s,]*(?:\(\s*)?(?:ret\.?|retd\.?|retired)\b`);
392
+ const RANKED = new Set(['seniorGeneral', 'general', 'colonel', 'ltColonel', 'major', 'seniorEnlisted', 'nco']);
393
+ const MIL_UNIT = /\b(division|brigade|battalion|squadron|wing|regiment|fleet|command|corps|group|task force|carrier|uss|usns|uscgc|infantry|airborne|cavalry|artillery|armor|special forces|seal team|marines?|garrison|installation|base|detachment|company|battery|troop|flight)\b/;
394
+ const NOT_MILITARY = /\b(army and navy union|honorary|kentucky colonels?|tennessee colonel|commemorative air force|great navy|texas navy|nebraska navy|civil air patrol|rotc|jrotc|cadets?|midshipm[ae]n|american legion|vfw|veterans of foreign wars|amvets|disabled american veterans|marine corps league|navy league|air force association|association of the united states army|ausa|moaa|auxiliary|order of the|boy scouts|girl scouts|scouts bsa|sea cadets|young marines|salvation army|licensed|license|mariner|merchant marine|charter|vessel|yacht|\d+\s*-?\s*ton|oupv|six-pack|halo|cosplay\w*|reenact\w*|star trek|police|sheriff['’]?s?|lapd|nypd|highway patrol|state patrol|troopers?|corrections|fire (?:department|rescue|district|dept|station|company|service|marshal)|firefighters?|(?:engine|ladder|truck|rescue|squad|station) \d+|power squadron|boating|sailing|society|relief|ministr(?:y|ies)|fans?|store|shop|surplus|park rangers?|community services|engine company|restaurants?|street|avenue|cleaning|architects?|architecture|lifeguards?|boys brigade|girls brigade|pickleball|squad|hospital|university|college|drum corps|marching|charters?|fishing|ems|ambulance|museum|docent|association|veterans|alumni|chapter|memorial|credit union|fcu|casino|varsity|intramural|club|league|rugby|lacrosse|football|soccer|basketball|baseball|hockey|crew|rowing|sailing team|athletics|captain of|wrestling|swimming|diving|track|cross country|fencing|boxing|golf|tennis|volleyball|softball|water polo|rifle team|pistol team|squash|sprint football|gymnastics|cheer(?:leading)?|starfleet|sea scouts?|model ships?|paintball|airsoft|corps of cadets|citadel|composite squadron|model shipbuilders|chess|debate|esports|(?:usna|usma|usafa|uscga)\s*['’]?\d{2})\b|(?<!seal |combat |protection |support |engagement |training |assistance )\bteam\b/;
395
+ // Civilian words in a part beside a rank whose own part names its service only
396
+ // weakly (a numbered unit, a USS name, "naval"): "Commander, 3rd Division |
397
+ // Northwind Police Department", "Commanding Officer, USS Northwind | Starfleet International".
398
+ const NOT_MILITARY_NEAR = /\b(harbor pilot|ship pilot|river pilot|parasail\w*|watersports|sportfishing|marina|dive|eve online|nerf|warhammer|esports|gaming|game|guild|clan|minecraft|roblox|fortnite|call of duty|discord|virtual|dcs world|flight sim\w*|milsim|texas navy|nebraska navy|great navy|salvation army|cruises|fishing|guide|charters?|boat|yacht|tours?|ferry|cruise|towing|tug|airlines?|air lines|federal air marshal|fams|tsa|starfleet|star trek|sea cadets?|sea scouts?|cosplay\w*|halo|reenact\w*|police|sheriff|fire (?:department|rescue)|lapd|nypd|model ships?|shipbuilders|civil air patrol|cap|corps of cadets|cadets?|citadel|vmi|rotc|jrotc|paintball|airsoft)\b/;
399
+ // A part that belongs with a rank: its service, its unit, its job, a place, "Retired".
400
+ const milish = (p) => SERVICE_ONLY.test(p) || RETIRED_ONLY.test(p) || RETIRED_SERVICE.test(p) || (PLACE.test(p) && !/^[a-z]{2}$/.test(p)) || /\b(?:army|navy|naval|air force|marine|coast guard|military|infantry|staff) officer\b/.test(p) || (MIL_ROLE.test(p) && !isOrg(p) && !NOT_MILITARY_NEAR.test(p))
401
+ || (MIL_UNIT.test(p) && /\d/.test(p) && !isOrg(p) && !NOT_MILITARY.test(p) && !NOT_MILITARY_NEAR.test(p));
402
+ const STRONG_SERVICE = new RegExp(String.raw`(?:${QUALIFIED_SVC})`);
403
+ // Short forms that are also credentials or companies: a CSM is a Certified ScrumMaster,
404
+ // a CPT a personal trainer, LTC long-term care, ADM and MSG companies. With their
405
+ // service in the same part only ("LTC, U.S. Army"), never one borrowed from another part.
406
+ const LOOKALIKE_SHORT = /^(?:ltc|cpt|csm|cmc|msg|msgt|mg|bg|adm|gen)\b/;
407
+
408
+ // Military short forms, read only at the start of a title and only beside a service.
409
+ const RANK_SHORT = [
410
+ [/^(?:lt\.?\s?gen(?:eral|\.)?|ltgen|ltg|lieut\.?\s?general)(?=\s|$)/, 'lieutenant general'],
411
+ [/^(?:maj\.?\s?gen(?:eral|\.)?|majgen|mg)(?=\s|$)/, 'major general'],
412
+ [/^(?:brig\.?\s?gen(?:eral|\.)?|bgen|bg)(?=\s|$)/, 'brigadier general'],
413
+ [/^gen\.?(?=\s|$)/, 'general'],
414
+ [/^(?:vice\s?adm\.?|vadm)(?=\s|$)/, 'vice admiral'],
415
+ [/^(?:rear\s?adm\.?|radm|rdml)(?=\s|$)/, 'rear admiral'],
416
+ [/^adm\.?(?=\s|$)/, 'admiral'],
417
+ [/^(?:lt\.?\s?col(?:onel|\.)?|lieut\.?\s?colonel|ltcol|ltc|lcol)(?=\s|$)/, 'lieutenant colonel'],
418
+ [/^col\.?(?=\s|$)/, 'colonel'],
419
+ [/^(?:lt\.?\s?cdr\.?|lcdr|ltcdr|lt\.?\s?commander)(?=\s|$)/, 'lieutenant commander'],
420
+ [/^cdr\.?(?=\s|$)/, 'commander'],
421
+ [/^(?:capt\.?|cpt)(?=\s|$)/, 'captain'],
422
+ [/^maj\.?(?=\s|$)/, 'major'],
423
+ [/^lt\.?(?=\s|$)/, 'lieutenant'],
424
+ [/^csm(?=\s|$)/, 'command sergeant major'],
425
+ [/^(?:sgtmaj|sgt\.?\s?maj\.?)(?=\s|$)/, 'sergeant major'],
426
+ [/^sgm(?=\s|$)/, 'sergeant major'],
427
+ [/^cmsgt(?=\s|$)/, 'chief master sergeant'],
428
+ [/^(?:mcpo|mcpon|cmc)(?=\s|$)/, 'master chief'],
429
+ [/^scpo(?=\s|$)/, 'senior chief petty officer'],
430
+ [/^(?:cw[2-5]|cwo[2-5]?)(?=\s|$)/, 'chief warrant officer'],
431
+ [/^wo1(?=\s|$)/, 'warrant officer'],
432
+ [/^sfc(?=\s|$)/, 'sergeant first class'],
433
+ [/^1sg(?=\s|$)/, 'first sergeant'],
434
+ [/^(?:msg|msgt)(?=\s|$)/, 'master sergeant'],
435
+ [/^smsgt(?=\s|$)/, 'senior master sergeant'],
436
+ [/^mgysgt(?=\s|$)/, 'master gunnery sergeant'],
437
+ [/^gysgt(?=\s|$)/, 'gunnery sergeant'],
438
+ ];
439
+ // [the whole title, its level, whether it needs a service beside it]. The
440
+ // flag ranks spelled out, and the services' chiefs, are nobody else's. A
441
+ // captain is 'captain' (a colonel's equal in a navy, a major's elsewhere), a
442
+ // lieutenant counts only in a navy (a major's equal), and a commander,
443
+ // commanding or executive officer is 'commander': their unit decides.
444
+ const RANKS = [
445
+ [String.raw`chief of staff of the (?:u\.?\s?s\.?\s)?(?:army|air force)|vice chief of staff of the (?:u\.?\s?s\.?\s)?(?:army|air force)|chief of naval operations|vice chief of naval operations|commandant of the (?:u\.?\s?s\.?\s)?(?:marine corps|coast guard)|(?:vice )?chairman of the joint chiefs(?: of staff)?|chief of space operations|chief of the national guard bureau`, 'seniorGeneral', false],
446
+ [String.raw`sergeant major of the (?:army|marine corps)|master chief petty officer of the (?:navy|coast guard)|chief master sergeant of the (?:air force|space force)|senior enlisted advisor to the chairman`, 'seniorEnlisted', false],
447
+ [String.raw`lieutenant general|vice admiral|(?:three|four|3|4)[-\s]star (?:general|admiral)|general of the army|fleet admiral`, 'seniorGeneral', false],
448
+ [String.raw`air marshal|air chief marshal`, 'seniorGeneral', true],
449
+ [String.raw`major general|brigadier general|rear admiral(?: \((?:lower|upper) half\))?|(?:one|two|1|2)[-\s]star (?:general|admiral)`, 'general', false],
450
+ [String.raw`air vice marshal|air commodore`, 'general', true],
451
+ [String.raw`(?:deputy )?commanding general|brigadier|commodore`, 'general', true],
452
+ [String.raw`general|admiral`, 'seniorGeneral', true],
453
+ [String.raw`lieutenant colonel|wing commander`, 'ltColonel', true],
454
+ [String.raw`colonel|group captain`, 'colonel', true],
455
+ [String.raw`(?:(?:deputy|vice|garrison|installation|base|battalion|squadron|wing|group|ship|regimental|brigade|division|corps|fleet|company|battery|troop|flight|detachment|task force) )*commander|commanding officer|executive officer`, 'commander', true],
456
+ [String.raw`lieutenant commander|squadron leader|major`, 'major', true],
457
+ [String.raw`captain`, 'captain', true],
458
+ [String.raw`lieutenant`, 'lieutenant', true],
459
+ [String.raw`command sergeant major|sergeant major|(?:command )?master chief(?: petty officer)?|chief master sergeant|command chief(?: master sergeant)?|master gunnery sergeant`, 'seniorEnlisted', true],
460
+ [String.raw`(?:senior )?chief petty officer|senior chief|(?:senior )?master sergeant|(?:first|1st) sergeant|sergeant first class|gunnery sergeant|(?:chief )?warrant officer(?: [1-5])?`, 'nco', true],
461
+ [String.raw`o-?(?:9|10)`, 'seniorGeneral', true],
462
+ [String.raw`o-?[78]`, 'general', true],
463
+ [String.raw`o-?6`, 'colonel', true],
464
+ [String.raw`o-?5`, 'ltColonel', true],
465
+ [String.raw`o-?4`, 'major', true],
466
+ [String.raw`e-?9`, 'seniorEnlisted', true],
467
+ [String.raw`e-?[78]`, 'nco', true],
468
+ ].map(([src, key, needsService]) => [new RegExp(`^(?:${src})$`), key, needsService]);
469
+ const LEVEL_DOWN = { seniorGeneral: 'general', general: 'colonel', colonel: 'ltColonel', ltColonel: 'major', major: 'major' };
470
+
471
+ // A unit's usual commander, smallest first: the first unit a title names is the
472
+ // one commanded ("Executive Officer, 1st Battalion, 75th Ranger Regiment" is a
473
+ // battalion's).
474
+ const UNIT_LEVELS = [
475
+ [/\b(company|battery|troop|flight|detachment)\b/, 'major'],
476
+ [/\b(battalion|squadron|ship|uss|uscgc|submarine|destroyer|frigate|cutter|v[a-z]{1,3}-\d+)\b/, 'ltColonel'],
477
+ [/\b(brigade|wing|group|regiment|garrison|installation|base|naval (air )?station|naval hospital|joint base)\b/, 'colonel'],
478
+ [/\b(division|strike group|region|command|(surface|submarine|naval|expeditionary) forces?|air forces)\b/, 'general'],
479
+ [/\b(corps|fleet|combatant command|(materiel|combat|mobility|training and doctrine|futures|forces|special operations|space|cyber|strategic|transportation|northern|southern|central|european|pacific|indo-pacific|africa|global strike|education and training) command)\b/, 'seniorGeneral'],
480
+ ];
481
+
482
+ /** A commander's (or a commanding or executive officer's) level, from their unit. */
483
+ function commandLevel(n, where) {
484
+ const text = `${n.replace(/\b(commander|commanding officer|executive officer|deputy|vice)\b/g, ' ')} ${where}`
485
+ .replace(new RegExp(String.raw`(?:${SVC})(?![a-z])`, 'g'), ' ').replace(/\b(?:nurse|medical|dental|medical service|chaplain|supply|civil engineer|judge advocate general['’]?s?) corps\b/g, ' ');
486
+ let key = 'ltColonel';
487
+ let first = Infinity;
488
+ for (const [re, level] of UNIT_LEVELS) {
489
+ const m = text.match(re);
490
+ if (m && (m.index < first || (m.index === first && level === 'seniorGeneral'))) { first = m.index; key = level; }
491
+ }
492
+ if (/\b(deputy|vice)\b/.test(n) || /^executive officer/.test(n)) key = LEVEL_DOWN[key];
493
+ return key;
494
+ }
495
+
496
+ /** A rank written as the title, or null; `retired` when it says so. */
497
+ // A serving officer's job, as its own part: "F-35 Pilot", "Intelligence Officer".
498
+ const MIL_ROLE = /\b(pilot|aviator|navigator|operator|surgeon|physician|chaplain|jag|strategist|intelligence|logistics|signal|infantry|armor|artillery|cyber|special forces|seal|ranger|aviation|acquisition|commander|garrison|battalion|brigade|squadron|staff officer)\b/;
499
+
500
+ function militaryTitle(raw, t, title, rest, prev, next, others, nextRetired = false, after = '') {
501
+ if (NOT_MILITARY.test(t)) return null;
502
+ // A civilian word beside the rank ("| Warhammer", "| Fishing Guide") counts unless the rank's own
503
+ // part names its service; the Coast Guard's name is also on boat captains' licences.
504
+ const ownService = (STRONG_SERVICE.test(t.replace(/\bgeneral of the army\b/, ' ')) || REST_IS_SERVICE.test(rest)) && !/\b(?:coast guard|uscg)\b/.test(t);
505
+ if (!ownService && [prev, next].some((p) => p && NOT_MILITARY_NEAR.test(p))) return null;
506
+ const atOrg = rest.match(/(?:^|\s)(?:at|@)\s+(.+)$/);
507
+ if (atOrg && !SERVICE_IN.test(atOrg[1]) && !REST_IS_SERVICE.test(atOrg[1])) return null;
508
+ let n = title.replace(/(?<=[a-z])-(?=[a-z])/g, ' ').replace(/^(?:(?:acting|interim|the)\s+)*/, '');
509
+ let retired = /\(\s*r\s*\)/.test(raw.toLowerCase());
510
+ n = n.replace(/,?\s+(?:\(?ret\.?\)?|\(?retired\)?)$/, () => { retired = true; return ''; })
511
+ .replace(/,?\s+\(?active duty\)?$/, '');
512
+ let service = SERVICE_IN.test(t) || REST_IS_SERVICE.test(rest) || /^usa(?:,|$)/.test(rest);
513
+ // A numbered unit, a USS name or "naval" alone is weak: not beside a police
514
+ // department, a fire rescue, a fan club or any other organization.
515
+ const weak = service && !STRONG_SERVICE.test(t) && !REST_IS_SERVICE.test(rest);
516
+ if (weak && (isOrg(rest.replace(/\b(group|company|hospital|battery|troop)\b/g, ' ')) || [prev, next].some((p) => p && !milish(p)))) service = false;
517
+ const own = service;
518
+ const lead = n.match(new RegExp(`^(?:${SVC}|marine)(?:\\s+reserves?)?\\s+`));
519
+ if (lead) { n = n.slice(lead[0].length); service = true; }
520
+ const trail = n.match(new RegExp(`(?:\\s+(?:in|with|of) the)?\\s+(?:${SVC})$`));
521
+ const variants = trail ? [n, n.slice(0, -trail[0].length)] : [n];
522
+ if (trail) service = true;
523
+ // A service in a part of its own is the rank's when nothing else is named
524
+ // beside the rank but its units and places ("Commander, 1st Brigade | U.S.
525
+ // Army"), not a civilian employer ("Commander, Security Group, Northwind
526
+ // Casino | U.S. Army"); one further off past another title ("LTC |
527
+ // Acquisition Officer | U.S. Army"), not past an employer ("Captain | Delta
528
+ // Air Lines | Retired USAF" is an airline captain).
529
+ const servicePart = (p) => SERVICE_ONLY.test(p) || /^(?:the )?(?:u\.?\s?s\.? )?(?:central|european|pacific|indo-pacific|africa|southern|northern|special operations|cyber|space|strategic|transportation) command$/.test(p);
530
+ const alone = servicePart(next) ? next : !rest && servicePart(prev) ? prev : null;
531
+ const unitsOnly = pieces(rest).every((p) => SERVICE_IN.test(p) || REST_IS_SERVICE.test(p) || PLACE.test(p)
532
+ || (MIL_UNIT.test(p) && !isOrg(p) && /\d|\b(?:[ivxl]+|fort|camp|joint|naval|marine|battalion|brigade|squadron|regiment|fleet|garrison|infantry|airborne|cavalry|artillery|special forces|seal team|detachment|task force|expeditionary|corps)\b/.test(p)));
533
+ const formerThen = alone === next && !!after && (isOrg(after) || NOT_MILITARY_NEAR.test(after)) && !milish(after); // "Captain | Former USAF | Delta Air Lines"
534
+ // A service before the rank with an employer after it ("U.S. Navy | Captain | Delta Air Lines"),
535
+ // or a civilian job just before a bare rank ("Claims Handler | Admiral | Royal Navy Reserve").
536
+ const otherSide = alone === next ? prev : next;
537
+ const flanked = !otherSide || milish(otherSide); // "Claims Handler | Admiral | Royal Navy Reserve" isn't
538
+ const jobBefore = !rest && !!prev && !milish(prev);
539
+ if (alone && unitsOnly && !formerThen && flanked) { service = true; if (alone === next && (RETIRED_SERVICE.test(next) || nextRetired)) retired = true; }
540
+ // A service further off, past only the rank's own jobs and units ("LTC | Acquisition Officer |
541
+ // U.S. Army", "Colonel | 82nd Airborne Division | U.S. Army"), never past an employer.
542
+ const milPart = (p) => !isOrg(p) && !(isGovOrg(p) && !SERVICE_ONLY.test(p)) && !NOT_MILITARY.test(p) && !NOT_MILITARY_NEAR.test(p)
543
+ && (!!readPart(p) || MIL_ROLE.test(p) || RETIRED_ONLY.test(p) || (MIL_UNIT.test(p) && /\d|\b(?:division|brigade|battalion|squadron|wing|regiment|fleet|command)\b/.test(p)));
544
+ const at = others.indexOf(t);
545
+ const far = at < 0 ? -1 : others.findIndex((o, i) => i > at + 1 && servicePart(o));
546
+ if (!service && !rest && !jobBefore && far > 0 && others.slice(at + 1, far).every(milPart)) service = true;
547
+ for (let v of variants) {
548
+ let short = false;
549
+ for (const [re, full] of RANK_SHORT) {
550
+ if (re.test(v)) {
551
+ if (LOOKALIKE_SHORT.test(v) && !own && !others.every((o) => o === t || milish(o))) return null;
552
+ v = v.replace(re, full); short = true; break;
553
+ }
554
+ }
555
+ for (const [re, key, needsService] of RANKS) {
556
+ if (!re.test(v)) continue;
557
+ if ((needsService || short) && !service) return null;
558
+ const naval = NAVY_IN.test(t) || (!!alone && NAVY_IN.test(alone));
559
+ const level = key === 'captain' ? (naval ? 'colonel' : 'major')
560
+ : key === 'lieutenant' ? (naval ? 'major' : null)
561
+ : key === 'commander' ? commandLevel(v, rest) : key;
562
+ return level ? { key: level, retired } : null;
563
+ }
564
+ }
565
+ return null;
566
+ }
567
+
568
+ // Government titles, [the whole title after LEAD, a level or (c) => level | null].
569
+ // The first pattern that matches decides; a function that returns SKIP lets the
570
+ // later ones try. `c` is { n: the title without LEAD, rest: the part's text
571
+ // after the title, prev, next and after: the parts before and after it, text:
572
+ // the part with the parts on either side, at: whether the part names its
573
+ // organization with "at", us: whether the title says "U.S." }.
574
+ //
575
+ // A title means government only where its organization is a government's
576
+ // (where(), below): "Controller, State of Florida", not "Controller |
577
+ // Texas | Northwind Homes". Only a title nobody else holds counts with no
578
+ // organization named ("State Senator", "Special Agent in Charge"); one that
579
+ // others hold too needs its government named ("Mayor, City of Orlando",
580
+ // "Administrator, U.S. Small Business Administration"), or to be the whole
581
+ // headline ("Mayor of Orlando", "Secretary of Commerce").
582
+ const SKIP = Symbol('not this pattern');
583
+ const place = String.raw`(?:(?:${STATES}|al|ak|az|ar|ca|co|ct|de|fl|ga|hi|id|il|in|ia|ks|ky|la|me|md|ma|mi|mn|ms|mo|mt|ne|nv|nh|nj|nm|ny|nys|nc|nd|oh|ok|or|pa|ri|sc|sd|tn|tx|ut|vt|va|wa|wv|wi|wy) (?:state )?)?`;
584
+ // Courts named by their circuit or district: "Ninth Circuit", "Middle District of Florida".
585
+ const JUDICIAL_AREA = new RegExp(String.raw`^(?:the )?(?:(?:first|second|third|fourth|fifth|sixth|seventh|eighth|ninth|tenth|eleventh|twelfth|thirteenth|fourteenth|fifteenth|sixteenth|seventeenth|eighteenth|nineteenth|twentieth|federal|d\.?c\.?|\d+(?:st|nd|rd|th)) (?:judicial )?circuit(?: court)?(?: of [a-z ]+)?|(?:(?:northern|southern|eastern|western|middle|central) )?district of (?:${STATES}))$`);
586
+ const INTERNATIONAL_BODY = new RegExp(String.raw`^(?:the )?(?:${INTERNATIONAL})$`);
587
+ const INTERNATIONAL_IN = new RegExp(String.raw`\b(?:${INTERNATIONAL})\b`);
588
+ // An organization anyone can see is one: a company the lists know, or a name
589
+ // with a company's, a school's or a club's word ("Northwind Pharmaceuticals").
590
+ const ORG_WORD = /\b(inc|llc|ltd|corp|corporation|co|company|group|brands?|foods?|beverages?|pharma\w*|health|healthcare|bank|capital|partners|solutions|services|systems|technolog(?:y|ies)|labs?|media|studios?|apparel|fitness|coaching|consulting|realty|homes|law|title|insurance|airlines?|air lines|university|college|school|academy|institute|association|society|club|league|foundation|church|collective|agency|ventures|holdings|enterprises|industries|motors|logistics|staffing|restaurants?|cafe|coffee|sake|tequila|whisk(?:e)?y|wines?|spirits|brewing|distillery|hotels?|resorts?|casino|creative|design|digital|software|network|plan|clinic|hospital|medical|dental|pharmacy|store|shop|market|mall|refinery|plant|repair|recruiting|properties|real estate|mortgage|lending|financial|investments?|wealth|trust|credit union|kitchen|grill|bakery|diner|martial arts|dojo|gym|maritime|shipping|care|home care|living|travel|tours|yoga|retreats?|wellness|podcast|seeds|exports?|imports?)\b/;
591
+ const DEPT_OF = new RegExp(String.raw`^${DEPT}\b`);
592
+ // Cities people are mayors of: the largest U.S. cities, the state capitals and
593
+ // some more. "Mayor of Tampa" names a city; "Mayor of Candyland" doesn't.
594
+ const CITY = new RegExp(String.raw`^(?:the )?(?:city of )?(?:new york|new york city|los angeles|chicago|houston|phoenix|philadelphia|san antonio|san diego|dallas|austin|jacksonville|fort worth|san jose|columbus|charlotte|indianapolis|san francisco|seattle|denver|oklahoma city|nashville|el paso|las vegas|boston|detroit|portland|louisville|memphis|baltimore|milwaukee|albuquerque|tucson|fresno|sacramento|mesa|kansas city|atlanta|omaha|colorado springs|raleigh|long beach|virginia beach|miami|oakland|minneapolis|tulsa|bakersfield|wichita|arlington|aurora|tampa|new orleans|cleveland|honolulu|anaheim|lexington|stockton|corpus christi|henderson|riverside|newark|saint paul|st\. paul|santa ana|cincinnati|irvine|orlando|pittsburgh|st\. louis|saint louis|greensboro|jersey city|anchorage|lincoln|plano|durham|buffalo|chandler|chula vista|toledo|madison|gilbert|reno|fort wayne|north las vegas|st\. petersburg|saint petersburg|lubbock|irving|laredo|winston-salem|chesapeake|glendale|garland|scottsdale|norfolk|boise|fremont|spokane|santa clarita|baton rouge|richmond|hialeah|san bernardino|tacoma|modesto|huntsville|des moines|yonkers|rochester|moreno valley|fayetteville|fontana|columbus|worcester|port st\. lucie|little rock|augusta|oxnard|birmingham|montgomery|frisco|amarillo|salt lake city|grand rapids|huntington beach|overland park|glendale|tallahassee|grand prairie|mckinney|cape coral|sioux falls|peoria|providence|vancouver|knoxville|akron|shreveport|mobile|brownsville|newport news|fort lauderdale|chattanooga|tempe|ontario|santa rosa|elk grove|salem|pembroke pines|eugene|garden grove|cary|fort collins|corona|springfield|jackson|alexandria|hayward|clarksville|lakewood|lancaster|salinas|palmdale|springfield|macon|sunnyvale|pomona|killeen|escondido|pasadena|naperville|bellevue|joliet|murfreesboro|midland|rockford|paterson|savannah|bridgeport|torrance|mcallen|syracuse|surprise|denton|roseville|thornton|miramar|mesquite|olathe|dayton|carrollton|waco|orange|fullerton|charleston|west valley city|visalia|hampton|gainesville|warren|coral springs|cedar rapids|round rock|sterling heights|kent|columbia|santa clara|new haven|stamford|concord|elizabeth|athens|thousand oaks|lafayette|simi valley|topeka|norman|fargo|wilmington|abilene|odessa|pearland|victorville|hartford|vallejo|allentown|berkeley|richardson|arvada|ann arbor|cambridge|sugar land|lansing|evansville|college station|fairfield|clearwater|beaumont|independence|provo|west jordan|murrieta|palm bay|el monte|carlsbad|charleston|temecula|clovis|meridian|westminster|costa mesa|high point|manchester|pueblo|lakeland|pompano beach|west palm beach|antioch|everett|downey|lowell|centennial|elgin|broken arrow|miami gardens|billings|jurupa valley|sandy springs|gresham|lewisville|hillsboro|ventura|greeley|inglewood|waterbury|league city|santa maria|tyler|davie|daly city|boulder|allen|west covina|sparks|wichita falls|green bay|san mateo|norwalk|rialto|las cruces|chico|el cajon|burbank|south bend|renton|vista|davenport|edinburg|tuscaloosa|kenosha|albany|annapolis|augusta|bismarck|carson city|cheyenne|dover|frankfort|harrisburg|helena|jefferson city|juneau|montpelier|olympia|pierre|santa fe|trenton|winter park|winter garden|kissimmee|sanford|oviedo|maitland|altamonte springs|daytona beach|sarasota|naples|boca raton|delray beach|key west|ocala|pensacola|plant city|palm beach|miami beach|coral gables|hoboken|asheville|boulder|flagstaff|santa barbara|palo alto|mountain view|redmond|kirkland|scottsdale|sedona)(?:,\s*(?:[a-z]{2}|${STATES}))?$`);
595
+ // A municipality named as one: "Plant City", "League City", "College Station".
596
+ const MUNICIPALITY = /^[a-z .'-]+ (?:city|town|township|village|borough|station|springs|beach|heights|falls)$/;
597
+ const MUNICIPALITY_OF = /\bof (?:the )?[a-z .'-]+ (?:city|town|township|village|borough|station|springs|beach|heights|falls)\b/g;
598
+ const JOKE_PLACE = /\b(downtown|midtown|uptown|flavortown|funkytown|linkedin|twitter|tiktok|instagram|youtube|social media|the internet|the (block|neighborhood|hood|office|house)|my (house|block|street|home)|[a-z]+ town|real estate|sales|marketing|content|mortgages?)\b/;
599
+ const SALES = /\b(account|sales|manager|representative|specialist|consultant|recruiter|advisor|adviser|hr|benefits|payroll|lead|business development|partner)\b/;
600
+ const FED_RESERVE = /\bfederal reserve (board|system)\b|\bboard of governors of the federal reserve\b|^(the )?federal reserve$/;
601
+
602
+ const pieces = (s) => s.replace(/^(?:at|@)\s+/, '').replace(/(\S)\s*\([^)]*\)/g, '$1').split(/,\s*/).map((p) => p.trim()).filter(Boolean);
603
+ // A state's or the federal government's own body by its name: "Florida Public
604
+ // Service Commission", "Texas Medical Board", "Nuclear Regulatory Commission".
605
+ const STATE_BODY = new RegExp(String.raw`^(?:the )?(?:(?:${STATES})(?! city)(?: state)? )?(?:public service|public utilit(?:y|ies)|corporation|railroad) commission$|^(?:the )?(?:${STATES})(?! city)(?: state)? (?:gaming|ethics|elections?|parole|pardons and paroles|lottery|racing|athletic|real estate|medical|nursing|pharmacy|dental|bar examiners|workers['’]? compensation|industrial|civil service|human rights|tax|utility|water|environmental quality|fish and (?:game|wildlife)) (?:commission|board)$|^(?:the )?${FED_BODY}$`);
606
+ // A company the lists know is a government only when its own name says so
607
+ // (the public dataset has the U.S. Senate and the IRS): "Norfolk Southern
608
+ // Police Department" is the railroad's.
609
+ const govName = (name) => GOV_ORG.test(name) || AGENCY.test(name) || LEGIS.test(name) || STATE_BODY.test(name) || SERVICE_ONLY.test(name) || /\bu\.?\s?s\.? courts?\b/.test(name);
610
+ const knownCompany = (p) => isKnownCompany(p) && !govName(String(cleanCompany(p) || '').toLowerCase());
611
+ // A police or fire department named for a company, a campus or a mall is theirs.
612
+ const privateForce = (p) => { const m = p.match(/^(.+?)\s+(?:police|fire|public safety)(?: department)?$/); return !!m && (isOrg(m[1]) || isKnownCompany(m[1]) || /\b(campus|mall|railroad|railway|university|college|school|hospital|airport)\b/.test(m[1])); };
613
+ const isGovOrg = (p) => !NOT_GOV.test(p) && !CIVIC.test(p) && !STUDENT_ORG.test(p) && !knownCompany(p) && !privateForce(p) && (GOV_ORG.test(p) || LOCAL_GOV.test(p) || STATE_ITSELF.test(p) || LEGIS.test(p) || AGENCY.test(p)
614
+ || (TRIBAL_GOV.test(p) && !TRIBAL_BUSINESS.test(p) && !isOrg(p)) || INTERNATIONAL_BODY.test(p) || JUDICIAL_AREA.test(p) || STATE_BODY.test(p) || SERVICE_ONLY.test(p));
615
+ const isOrg = (p) => ORG_WORD.test(p) || isKnownCompany(p);
616
+ // A tag after a title that names no organization: a party and state ("(R-FL)"), a bracket.
617
+ const TAG = /^\(?[rdi]-?[a-z]{2}(?:-\d+)?\)?$|^\(.*\)$|^[a-z]{2}-(?:\d{1,2}|al)$|^(?:19|20)\d\d\s*[-–]\s*(?:(?:19|20)\d\d|present)$|^(?:[a-z .]+['’]s? )?\d+(?:st|nd|rd|th) (?:congressional |assembly |senate |house )?(?:district|ward)$/;
618
+ // A place a local office can name without its government's word: after its
619
+ // comma any name that isn't an organization or a title ("City Councilmember,
620
+ // Orlando"); as a part of its own only a county, a district or "City, State"
621
+ // ("Mayor | Oviedo, Florida").
622
+ const CITY_STATE = new RegExp(String.raw`^[a-z .'-]{2,30},\s*(?:[a-z]{2}|${STATES})$`);
623
+ const placeLike = (p, own = true) => PLACE.test(p) || LOCAL_PLACE.test(p) || CITY_STATE.test(p)
624
+ || (own && (CITY.test(p) || (MUNICIPALITY.test(p) && !JOKE_PLACE.test(p) && !BODY_WORD.test(p))));
625
+ // A name with a body's word is an organization, not a place: "The Joint Commission", "City Year".
626
+ const BODY_WORD = /\b(commission|council|committee|board|association|league|chamber|foundation|society|institute|club|center|centre|program|group|agency|office|department|authority|bureau|services?|team|network|alliance|coalition|project|initiative|fund|trust|year|corps|federation|union|guild|partnership)\b/;
627
+ // A piece after a comma that is a second title, not an organization: "Ambassador, Deputy Permanent Representative…".
628
+ const anotherTitle = (p) => !isOrg(p) && !!readPart(p);
629
+ /**
630
+ * Where the title is held: 'gov' when its organization is a government's,
631
+ * 'other' when it's some other organization, 'none' when none is named. The
632
+ * organization is the rest of the part ("Mayor, City of Orlando"); with none
633
+ * there, the next part, past a place ("Controller | Texas | Northwind
634
+ * Homes"), or a headline's first part when it's a government's ("State of
635
+ * Ohio | Governor"). Anything after a comma is an organization but a second
636
+ * title; a part of its own only when it looks like one, since it may be
637
+ * another title or who they are ("Retired Judge | Mediator").
638
+ */
639
+ function whereOwn(c) {
640
+ const own = pieces(c.rest).filter((p) => !TAG.test(p));
641
+ if (own.some((p) => CIVIC.test(p) || STUDENT_ORG.test(p))) return 'other';
642
+ if (own.some(isGovOrg)) return 'gov';
643
+ return own.some((p) => !placeLike(p) && (isOrg(p) || CIVIC.test(p) || (!NOT_AN_ORG.test(p) && !anotherTitle(p)))) ? 'other' : 'none';
644
+ }
645
+ // A part that says who someone is or what else they do, not an employer: a
646
+ // job title, a family or a hobby word ("Podcast Host", "Swim Dad", "Little
647
+ // League Coach", "Former Police Chief").
648
+ const BIO = /\b(host|personality|commentator|contributor|analyst|lover|dad|mom|father|mother|husband|wife|coach|fan|advocate|referee|deacon|elder|volunteer|mentor|planner|author|speaker|veteran|runner|golfer|reader|traveler|enthusiast|former|retired|ex-|alum\w*)\b/;
649
+ const PARTY = /^(?:a |proud )?(?:democrat|republican|independent|libertarian|conservative|progressive|moderate)s?$|^\(?[rdi]\)?$/;
650
+ const employer = (p) => !!p && (isOrg(p) || CIVIC.test(p) || STUDENT_ORG.test(p)) && !readPart(p) && !BIO.test(p) && !PARTY.test(p) && !isGovOrg(p);
651
+ // For a title that names its government ("County Sheriff", "Mayor of Tampa",
652
+ // "Ohio State Treasurer"): the other parts are its bio unless they name an employer.
653
+ function whereSoft(c) {
654
+ const own = whereOwn(c);
655
+ if (own !== 'none') return own;
656
+ const next = [c.next, PLACE.test(c.next) || LOCAL_PLACE.test(c.next) || CITY_STATE.test(c.next) ? c.after : ''];
657
+ return next.some((p) => employer(p)) ? 'other' : next.some((p) => p && isGovOrg(p)) || (c.prevLeads && isGovOrg(c.prev)) ? 'gov' : 'none';
658
+ }
659
+ const soft = (key) => (c) => (whereSoft(c) === 'other' ? null : key);
660
+ function where(c) {
661
+ const own = whereOwn(c);
662
+ if (own !== 'none') return own;
663
+ for (const p of [c.next, c.after]) {
664
+ if (!p) break;
665
+ if (isGovOrg(p)) return 'gov';
666
+ if (!PLACE.test(p) && !LOCAL_PLACE.test(p)) {
667
+ if (CIVIC.test(p) || STUDENT_ORG.test(p) || (!/\s(?:at|@)\s/.test(` ${p} `) && isOrg(p))) return 'other';
668
+ break;
669
+ }
670
+ }
671
+ return c.prevLeads && isGovOrg(c.prev) ? 'gov' : 'none';
672
+ }
673
+ // A local office's place: its own part's, or the next part's when that is only a place.
674
+ const localPlace = (c) => pieces(c.rest).some((p) => placeLike(p)) || (!c.rest && !!c.next && placeLike(c.next, false) && where(c) !== 'other');
675
+ // The title is the whole headline (a place after it aside).
676
+ const alone = (c) => !c.prev && !c.next && pieces(c.rest).every((p) => PLACE.test(p) || TAG.test(p));
677
+ const besides = (c) => [...pieces(c.rest), c.prevLeads ? c.prev : '', c.next].filter(Boolean);
678
+ const houseOf = (c) => besides(c).some((p) => LEGIS.test(p)) || /\bhouse district \d+/.test(c.part);
679
+ const congress = (c) => /\b(u\.?\s?s\.?|united states) (house|senate|congress)\b|\bcongressional district\b/.test(c.n)
680
+ || besides(c).some((p) => /^(?:the )?(?:u\.?\s?s\.?|united states) (?:house of representatives|house|senate|congress)$|congressional district(?: \d+)?$|^(the )?congress$/.test(p));
681
+ const houseOwn = (c) => pieces(c.rest).some((p) => LEGIS.test(p));
682
+ const inState = (c) => STATE_NAME.test(c.n) || besides(c).some((p) => STATE_GOV.test(p) || JUST_A_STATE.test(p));
683
+ // Judging that isn't a court's, in the part or the next part when it's where the title is held.
684
+ const notCourt = (c) => NOT_COURT.test(c.part) || (!c.rest && NOT_COURT.test(c.next));
685
+ // Nobody else holds these: any organization but some other one will do.
686
+ const notOther = (key) => (c) => (where(c) === 'other' ? null : key);
687
+ // Titles only officials hold: the other parts are their bio, not where the
688
+ // title is held ("U.S. Senator | Podcast Host").
689
+ const ownOnly = (key) => (c) => (whereSoft(c) === 'other' ? null : key);
690
+ const FOREIGN_WORDS = /\b(department of state|state department|foreign service|embassy|consulate|u\.?\s?s\.? mission|united nations|nato|usaid|diplomat)\b/;
691
+ const FOREIGN = { test: (p) => FOREIGN_WORDS.test(p) && !/\b(program|fulbright|alumni|club|volunteer|society|association|scholar|suites|hotel|hilton|inn)\b/.test(p) };
692
+ // A title that needs its government named, unless it's the whole headline.
693
+ const needGov = (key) => (c) => (where(c) === 'gov' || alone(c) ? key : null);
694
+ // Nothing else in the headline but the title (tags and places aside), or only a government beside it.
695
+ const nothingElse = (c) => alone(c) || where(c) === 'gov';
696
+ const GOV = [
697
+ // Congress and the legislatures.
698
+ [String.raw`(?:u\.?\s?s\.?|united states) senator(?: (?:for|from) .*)?`, ownOnly('govLeader')],
699
+ [String.raw`${place}state senator(?: .*)?`, ownOnly('govSenior')],
700
+ [String.raw`senator`, (c) => (c.us ? ownOnly('govLeader')(c) : SKIP)],
701
+ [String.raw`${place}state (?:representative|rep\.?|delegate|assembly ?(?:member|man|woman|person)|legislator)(?: .*)?`, (c) => (whereSoft(c) !== 'other' && (houseOf(c) || inState(c) || /\bdistrict\b/.test(`${c.n} ${c.rest} ${c.next}`)) ? 'govSenior' : null)],
702
+ [String.raw`${place}(?:district \d+ )?senator(?: (?:for|from|of) .*)?`, (c) => (where(c) === 'other' ? null : congress(c) ? 'govLeader'
703
+ : houseOf(c) || STATE_NAME.test(c.n) || (where(c) === 'gov' && inState(c)) ? 'govSenior' : null)],
704
+ [String.raw`(?:u\.?\s?s\.?|united states) representative (?:for|from) (?:${STATES})['’]?s? (?:\d+(?:st|nd|rd|th)|at-large)(?: congressional)? district`, 'govLeader'],
705
+ [String.raw`congress(?:wo)?man(?: (?:for|from) .*)?|congressperson(?: (?:for|from) .*)?|member of (?:the )?(?:u\.?\s?s\.?\s|united states )?congress|(?:member|delegate) (?:of|to) the (?:u\.?\s?s\.?|united states) house of representatives|resident commissioner(?: of puerto rico)?`, ownOnly('govLeader')],
706
+ [String.raw`(?:(?:u\.?\s?s\.?|united states|congressional) )?(?:representative|rep\.?)(?: (?:for|from|of) .*)?|member|legislator`, (c) => (where(c) === 'other' ? SKIP : congress(c) ? 'govLeader'
707
+ : houseOf(c) ? 'govSenior' : besides(c).some((p) => /\bcounty legislature\b/.test(p)) ? 'govOfficial' : SKIP)],
708
+ [String.raw`(?:(?:(?!(?:assistant|aide|driver|secretary|speechwriter|son|daughter|wife|husband|married|future|aspiring|campaign|former|endorsed|staff|intern|clerk|to|for|of|by|the|a|an|with)\b)[a-z.'-]+ ){0,3})?county legislator(?:, .*)?`, (c) => (nothingElse(c) || pieces(c.rest).some((p) => placeLike(p)) ? 'govOfficial' : null)],
709
+ [String.raw`member of the (?:[a-z.']+ ){0,3}(?:house of (?:representatives|delegates)|state assembly|assembly|state senate|senate|legislature|general assembly)(?: (?:from|for|representing) .*)?`, (c) => (where(c) !== 'other' && inState(c) ? 'govSenior' : null)],
710
+ [String.raw`${place}(?:assembly ?(?:member|man|woman|person)(?: .*)?|delegate(?: .*)?)`, (c) => (where(c) !== 'other' && (houseOf(c) || (STATE_NAME.test(c.n) && !/delegate/.test(c.n))) && inState(c) ? 'govSenior' : null)],
711
+ [String.raw`${place}(?:state )?(?:(?:senate|house|assembly) )?(?:majority|minority) (?:leader|whip)(?: .*)?|speaker(?: pro tem(?:pore)?)?(?: of the (?:u\.?\s?s\.?\s)?(?:house|assembly)(?: of (?:representatives|delegates))?)?(?: .*)?|(?:senate )?president(?: pro tem(?:pore)?)?(?: of the (?:[a-z.']+ ){0,2}senate)?`,
712
+ (c) => (!(/\b(senate|house|assembly|legislature)\b/.test(c.n) || houseOwn(c)) || whereOwn(c) === 'other' ? SKIP
713
+ : congress(c) ? 'govLeader' : inState(c) || /\bstate\b/.test(`${c.n} ${c.rest}`) ? 'govSenior'
714
+ : houseOwn(c) || alone(c) ? 'govLeader' : SKIP)],
715
+ // Governors and statewide offices.
716
+ [String.raw`(?:(?:${STATES}) )?(?:lieutenant|lt\.?) governor(?: of (?:the (?:state|commonwealth) of )?(?:${STATES}))?`, (c) => (STATE_NAME.test(c.n) ? ownOnly('govSenior')(c) : where(c) !== 'other' && inState(c) && !c.after ? 'govSenior' : null)],
717
+ [String.raw`(?:(?:${STATES}) )?governor(?: of (?:the (?:state|commonwealth|territory) of )?(?:${STATES}))?|governor of the (?:federal reserve(?: system| board)?|board of governors of the federal reserve(?: system)?)|governor of the pueblo of [a-z ]+|governor of (?:the )?[a-z' -]+ nation`,
718
+ (c) => {
719
+ const ownRest = pieces(c.rest).filter((p) => !TAG.test(p));
720
+ const own = ownRest.length ? ownRest : [c.next, c.prevLeads ? c.prev : ''];
721
+ if (FED_RESERVE.test(c.n) || /federal reserve/.test(c.n) || own.some((p) => FED_RESERVE.test(p))) return 'govSenior';
722
+ if (/pueblo of| nation$/.test(c.n)) return 'govLeader';
723
+ if (STATE_NAME.test(c.n)) return whereOwn(c) === 'other' ? null : 'govLeader';
724
+ if (where(c) === 'other') return null;
725
+ if (own.some((p) => TRIBAL_GOV.test(p) && !TRIBAL_BUSINESS.test(p))) return 'govLeader';
726
+ return STATE_NAME.test(c.n) || own.some((p) => JUST_A_STATE.test(p) || STATE_ITSELF.test(p)) ? 'govLeader' : null;
727
+ }],
728
+ [String.raw`federal reserve governor|member of the board of governors of the federal reserve(?: system)?`, 'govSenior'],
729
+ // A statewide officer names the state in the title or as the organization:
730
+ // "State Treasurer", "Insurance Commissioner, State of Georgia". A
731
+ // department's own auditor or a company's controller isn't one.
732
+ [String.raw`${place}(?:state )?(?:treasurer|comptroller|controller|auditor|auditor general|superintendent of public instruction|commissioner of (?:agriculture|insurance|education|labor|revenue)|land commissioner|insurance commissioner|(?:agriculture|education|labor|revenue|railroad) commissioner|surgeon general)(?: (?:of|for) .*)?`,
733
+ (c) => (STATE_NAME.test(c.n) && whereSoft(c) !== 'other') || (/^state /.test(c.n) && nothingElse(c))
734
+ || (!/^(?:controller|auditor)$/.test(c.n) && (pieces(c.rest).some((p) => STATE_ITSELF.test(p)) || (!c.rest && STATE_ITSELF.test(c.next)))) ? 'govSenior' : SKIP],
735
+ // Cities, counties and tribes.
736
+ [String.raw`mayor pro tem(?:pore)?(?:, .*)?`, needGov('govOfficial')],
737
+ [String.raw`(?:deputy|vice|assistant) mayor(?: for .*)?`, (c) => (where(c) === 'gov' || alone(c) || (/ for /.test(c.n) && whereSoft(c) !== 'other') || ((pieces(c.rest).some((p) => placeLike(p)) || CITY_STATE.test(c.next)) && whereSoft(c) !== 'other') ? 'govSenior' : null)],
738
+ [String.raw`mayor(?: of .*)?`, (c) => {
739
+ const w = where(c);
740
+ if (w === 'gov' || (w === 'none' && /\b(city|town|village|borough|township) of\b/.test(c.n))) return 'govLeader';
741
+ const of = c.n.match(/^mayor of (?:the )?(.+)$/);
742
+ // A city named beside the title: "Mayor | Oviedo, Florida", "Mayor, Winter Park".
743
+ const beside = pieces(c.rest)[0] || (!c.rest ? c.next : '');
744
+ if (w !== 'other' && !of && beside && !JOKE_PLACE.test(beside) && (pieces(c.rest).some((p) => placeLike(p)) || CITY_STATE.test(c.next)) && whereSoft(c) !== 'other') return 'govLeader';
745
+ return of && !c.prev && (CITY.test(of[1]) || CITY_STATE.test(of[1]) || MUNICIPALITY.test(of[1])) && !JOKE_PLACE.test(of[1]) && !isKnownCompany(of[1]) && whereSoft(c) !== 'other' ? 'govLeader' : null;
746
+ }],
747
+ [String.raw`(?:(?:(?!(?:assistant|aide|driver|secretary|speechwriter|son|daughter|wife|husband|married|future|aspiring|campaign|former|endorsed|staff|intern|clerk|to|for|of|by|the|a|an|with)\b)[a-z.'-]+ ){0,3})?county (?:executive|mayor|judge executive)(?: of .*)?`, (c) => (nothingElse(c) || pieces(c.rest).some((p) => placeLike(p)) || (!c.rest && LOCAL_PLACE.test(c.next) && !c.after) ? 'govLeader' : null)],
748
+ [String.raw`(?:principal )?chief|(?:tribal )?(?:chairman|chairwoman|chairperson|president)`, (c) => (!c.at && (c.rest ? pieces(c.rest) : [c.next]).some((p) => TRIBAL_GOV.test(p) && !TRIBAL_BUSINESS.test(p) && !isOrg(p)) ? 'govLeader' : SKIP)],
749
+ // "City Manager" is also a gig app's or a mobility company's operations
750
+ // title (Uber, Lime): only with a government's name.
751
+ [String.raw`(?:(?:assistant|deputy|acting|interim) )?(?:(?:(?!(?:assistant|aide|driver|secretary|speechwriter|son|daughter|wife|husband|married|future|aspiring|campaign|former|endorsed|staff|intern|clerk|to|for|of|by|the|a|an|with)\b)[a-z.'-]+ ){0,2}(?:county|town|village|borough)|city) (?:administrator|manager)(?: .*)?`,
752
+ (c) => { const w = where(c); return w === 'gov' || (w === 'none' && ((pieces(c.rest).some((p) => placeLike(p)) && !c.next) || ((alone(c) || localPlace(c)) && !/\bcity (manager|administrator)\b/.test(c.n)))) ? 'govOfficial' : null; }],
753
+ // Cabinets: the federal one's, and a state's when it says so. With no
754
+ // government named, only the whole headline or "U.S." ("Secretary of
755
+ // Education | Homeschool Mom" is a joke).
756
+ [String.raw`${place}secretary of (?:state|defense|war|commerce|labor|education|energy|agriculture|transportation|veterans affairs|homeland security|health(?: and human services)?|housing and urban development|the (?:treasury|interior|army|navy|air force))(?: (?:of|for) .*)?`,
757
+ (c) => {
758
+ if (/secretary of state of /.test(c.n) && !STATE_NAME.test(c.n)) return null;
759
+ const w = c.us || STATE_NAME.test(c.n) ? whereSoft(c) : where(c);
760
+ if (w === 'other') return null;
761
+ if (STATE_NAME.test(c.n) || besides(c).some((p) => STATE_GOV.test(p) || JUST_A_STATE.test(p))) return 'govSenior';
762
+ return c.us || w === 'gov' || alone(c) ? 'govLeader' : null;
763
+ }],
764
+ [String.raw`deputy assistant secretary(?: (?:of|for) .*)?`, (c) => (CORP_OFFICER.test(c.part) ? null : (/ of /.test(c.n) ? (DEPT_OF.test(c.n.replace(/^.*? of /, '')) && whereOwn(c) !== 'other') : nothingElse(c)) ? 'govOfficial' : null)],
765
+ // An under, deputy or assistant secretary "of" a department, or "for" a
766
+ // policy area; not a company's ("Assistant Secretary of Northwind Foods").
767
+ [String.raw`(?:deputy under|deputy|under)[-\s]?secretary(?: (?:of|for) .*)?|undersecretary(?: .*)?|assistant secretary(?: (?:of|for) .*)?`,
768
+ (c) => {
769
+ if (CORP_OFFICER.test(c.part) || whereOwn(c) === 'other') return null;
770
+ const of = c.n.match(/\b(of|for) (.+)$/);
771
+ if (of && of[1] === 'of') return DEPT_OF.test(of[2]) ? 'govSenior' : null;
772
+ if (where(c) === 'other') return null;
773
+ if (of) return where(c) === 'gov' || alone(c) || c.us ? 'govSenior' : null;
774
+ return where(c) === 'gov' ? 'govSenior' : null;
775
+ }],
776
+ [String.raw`(?:deputy )?(?:national security advis[eo]r|director of national intelligence)|white house chief of staff|director of the office of management and budget`, (c) => (where(c) === 'other' ? null : /^deputy/.test(c.n) ? 'govSenior' : 'govLeader')],
777
+ // A university's or a company's president has assistants too.
778
+ [String.raw`(?:deputy )?assistant to the president(?: (?:for|and) .*)?`, (c) => (/of the united states/.test(c.n) || (where(c) === 'gov' && [c.rest, c.next, c.prevLeads ? c.prev : ''].some((p) => /\b(white house|executive office of the president|national security council|nsc)\b/.test(p))) ? (/^deputy/.test(c.n) ? 'govSenior' : 'govLeader') : null)],
779
+ // A beverage brand's trade representative sells to its trade.
780
+ [String.raw`(?:deputy )?(?:u\.?\s?s\.?\s|united states )?trade representative`, (c) => (where(c) !== 'other' && (c.us || /\b(ustr|office of the (u\.?\s?s\.?|united states) trade representative)\b/.test(c.text)) ? (/^deputy/.test(c.n) ? 'govSenior' : 'govLeader') : null)],
781
+ [String.raw`director`, (c) => (/^(?:the )?(?:office of management and budget|federal bureau of investigation|central intelligence agency|national security agency|u\.?\s?s\.? secret service|u\.?\s?s\.? marshals service|u\.?\s?s\.? census bureau|national institutes of health|centers for disease control and prevention|u\.?\s?s\.? mint|bureau of alcohol, tobacco, firearms and explosives)$/.test(c.rest || (!c.prev && !c.after ? c.next : '')) || /^(?:the )?(?:fbi|cia|nsa|atf|dea)$/.test(c.rest) ? 'govSenior' : SKIP)],
782
+ [String.raw`(?:fbi|cia|nsa|atf|dea|cdc|nih) director`, (c) => (where(c) === 'gov' || alone(c) ? 'govSenior' : null)],
783
+ [String.raw`postmaster general|librarian of congress|archivist of the united states|auditor general of the (?:army|navy|air force)`, notOther('govSenior')],
784
+ [String.raw`(?:u\.?\s?s\.?\s|united states )?special (?:presidential )?envoy(?: .*)?`, (c) => (/ to the (ceo|cto|coo|cfo|founders?|president|chair\w*|board)\b/.test(c.n) ? null : where(c) === 'gov' || (where(c) === 'none' && (c.us || /presidential/.test(c.n) || (alone(c) && / for /.test(c.n)))) ? 'govSenior' : null)],
785
+ [String.raw`charge d'affaires(?: .*)?`, (c) => (c.us || (where(c) === 'gov' && [c.rest, c.next].some((p) => FOREIGN.test(p))) ? 'govSenior' : null)],
786
+ [String.raw`(?:under|assistant)[-\s]secretary[-\s]general(?: .*)?`, notOther('govSenior')],
787
+ [String.raw`special agent in charge|assistant special agent in charge|chief patrol agent|undersheriff`, needGov('govOfficial')],
788
+ // A hospital's, a home-health chain's or a senior-living company's
789
+ // regional and associate administrators are theirs.
790
+ [String.raw`(?:regional|associate|deputy associate) administrator|assistant inspector general(?: .*)?|(?:principal )?deputy assistant attorney general(?: .*)?|associate deputy attorney general(?: .*)?`,
791
+ (c) => (where(c) === 'gov' || (/inspector general|attorney general/.test(c.n) && where(c) !== 'other') ? 'govOfficial' : null)],
792
+ [String.raw`director of the (?:fbi|cia|nsa|federal bureau of investigation|central intelligence agency|national security agency|secret service|u\.?\s?s\.? marshals service)|(?:u\.?\s?s\.?|united states) marshal(?: for .*)?|comptroller (?:general of the united states|of the currency)|treasurer of the united states`, ownOnly('govSenior')],
793
+ // Lawyers for the government.
794
+ [String.raw`(?:principal )?deputy associate attorney general(?: .*)?`, notOther('govOfficial')],
795
+ [String.raw`associate attorney general(?: .*)?`, notOther('govSenior')],
796
+ [String.raw`(?:principal )?deputy attorney general(?: .*)?|assistant attorney general(?: .*)?`, (c) => (/\b(of the united states|u\.?\s?s\.? department of justice|department of justice|doj)\b/.test(c.text) && !STATE_GOV.test(c.text) ? 'govSenior' : 'senior')],
797
+ [String.raw`(?:special deputy|special assistant|senior assistant) attorney general(?: .*)?`, 'senior'],
798
+ [String.raw`${place}attorney general(?: (?:of|for) .*)?`, (c) => ((/ (?:of|for) /.test(` ${c.n} `) || STATE_NAME.test(c.n) || c.us ? ownOnly : needGov)('govLeader')(c))],
799
+ [String.raw`(?:assistant|deputy|senior assistant|chief assistant|executive assistant) (?:u\.?\s?s\.?|united states|district|state|county|commonwealth(?:['’]s)?) attorney(?: .*)?`, 'senior'],
800
+ // "US Attorney" is also what a U.S.-qualified lawyer abroad writes: the
801
+ // U.S. Attorney names a district, or is the whole headline.
802
+ [String.raw`(?:(?:(?!(?:assistant|aide|driver|secretary|speechwriter|son|daughter|wife|husband|married|future|aspiring|campaign|former|endorsed|staff|intern|clerk|to|for|of|by|the|a|an|with)\b)[a-z.'-]+ ){0,3}county |[a-z .'-]+ city )?(?:u\.?\s?s\.?|united states|district|state|state's|county|commonwealth(?:['’]s)?) attorney(?: (?:for|of) .*)?`,
803
+ (c) => {
804
+ if (/\battorney at law\b/.test(c.text)) return null;
805
+ const w = where(c);
806
+ if (w === 'other') return null;
807
+ if (w === 'gov' || pieces(c.rest).some((p) => /\b(district|county|circuit|judicial)\b/.test(p)) || /\bdistrict\b/.test(c.n)) return 'govSenior';
808
+ return w === 'other' || (c.us && !alone(c)) ? null : 'govSenior';
809
+ }],
810
+ [String.raw`deputy (?:inspector general|solicitor general|program executive officer|peo)(?: .*)?`, (c) => (SALES.test(c.n) ? null : notOther('govOfficial')(c))],
811
+ [String.raw`(?:solicitor|inspector|surgeon|adjutant) general(?: .*)?`, (c) => (/general (counsel|office|staff|investigator|auditor|attorney|agent)/.test(c.n) ? null
812
+ : / of /.test(c.n) ? (new RegExp(String.raw` of (?:the )?(?:united states|${STATES})$`).test(c.n) ? soft('govSenior')(c) : null)
813
+ : nothingElse(c) || (!c.rest && JUST_A_STATE.test(c.next) && !c.after) ? 'govSenior' : null)],
814
+ // Defense and civil-service executives. "PEO" is also a professional
815
+ // employer organization, the HR industry's word ("PEO Account Manager").
816
+ [String.raw`program executive officer(?: .*)?`, (c) => (c.service || /\bpeo\b|program executive office/.test(c.rest) || where(c) === 'gov' ? 'govSenior' : null)],
817
+ [String.raw`(?:member of the )?senior executive service(?: member)?|(?:tier (?:[1-3]|i{1,3}) )?ses(?: tier [1-3])?(?: member)?`, (c) => (/senior executive service/.test(c.n) || c.service || whereOwn(c) === 'gov' || (/tier|member/.test(c.n) && where(c) === 'gov') ? 'govSenior' : null)],
818
+ // Diplomats and international bodies. A brand's ambassador is theirs: an
819
+ // ambassador is a diplomat "to" a country, at an embassy or a mission, or
820
+ // retired as one ("Ambassador (Ret.)"; "Former Ambassador | Lululemon" isn't).
821
+ [String.raw`secretary[-\s]general(?: of (?:the )?.*)?`, (c) => ([c.n.replace(/^secretary[-\s]general(?: of (?:the )?)?/, ''), ...pieces(c.rest), ...(c.rest ? [] : [c.next])].some((p) => INTERNATIONAL_BODY.test(p)) ? 'govLeader' : null)],
822
+ [String.raw`(?:u\.?\s?s\.?\s|united states )?ambassador(?: of the united states| extraordinary and plenipotentiary)?(?: to (?:the )?(?:republic of |kingdom of |state of )?(?:${COUNTRIES}|${INTERNATIONAL})(?:,? (?:and|&) (?:the )?(?:${COUNTRIES}))*)?|ambassador-at-large(?: .*)?`,
823
+ (c) => (whereSoft(c) === 'other' ? null : [c.rest, c.next, c.prevLeads ? c.prev : ''].some((p) => FOREIGN.test(p)) || INTERNATIONAL_IN.test(c.rest)
824
+ || ((/at-large| to /.test(` ${c.n} `) || c.retTag) && (c.us || alone(c))) ? 'govSenior' : null)],
825
+ [String.raw`ambassador of (?:the )?(?:${COUNTRIES}) to (?:the )?(?:united states|${COUNTRIES}|${INTERNATIONAL})`, 'govSenior'],
826
+ [String.raw`(?:deputy |alternate )?(?:permanent )?representative (?:of .* )?to the (?:${INTERNATIONAL})(?: .*)?|(?:deputy |alternate )?permanent representative(?: .*)?`, (c) => (INTERNATIONAL_IN.test(c.text) && where(c) !== 'other' ? 'govSenior' : null)],
827
+ [String.raw`consul general(?: .*)?`, (c) => (c.us || new RegExp(String.raw` of (?:the )?(?:${COUNTRIES}|united states)\b`).test(c.n) || [c.rest, c.next].some((p) => FOREIGN.test(p)) || alone(c) ? 'govOfficial' : null)],
828
+ // Courts, not a fair's, a rodeo's or a campus's: the court is named, or the
829
+ // title says which kind it is ("U.S. District Judge").
830
+ [String.raw`chief justice(?: .*)?`, (c) => (notCourt(c) ? null : where(c) === 'gov' || (whereOwn(c) !== 'other' && (STATE_NAME.test(c.n) || /united states|supreme court/.test(c.n))) ? 'govLeader' : null)],
831
+ [String.raw`(?:(?:${STATES}|state|u\.?\s?s\.?) )?supreme court justice`, ownOnly('judge')],
832
+ [String.raw`(?:associate |presiding )?justice(?: of .*)?`, (c) => (!notCourt(c) && where(c) === 'gov' ? 'judge' : !notCourt(c) && where(c) !== 'other' && /\b(supreme|appeals|appellate|superior) (judicial )?court|court of (appeals|criminal appeals)\b/.test(`${c.n} ${c.rest}`) ? 'judge' : null)],
833
+ [String.raw`(?:(?:${STATES}) |(?:(?!(?:assistant|aide|driver|secretary|speechwriter|son|daughter|wife|husband|married|future|aspiring|campaign|former|endorsed|staff|intern|clerk|to|for|of|by|the|a|an|with)\b)[a-z.'-]+ ){0,3}county )?(?:(?:chief|presiding|senior|associate|federal|state|u\.?\s?s\.?|united states|district|circuit|county|superior|family|probate|municipal|juvenile|criminal|civil|city|justice|appellate|appeals|bankruptcy|magistrate|administrative law|immigration|tax|trial|tribal|court) )*judge(?: of .*)?`,
834
+ (c) => {
835
+ if (notCourt(c)) return null;
836
+ const named = /\b(federal|district|circuit|superior|probate|municipal|juvenile|criminal|appellate|appeals|bankruptcy|magistrate|administrative law|immigration|court|tribal)\b/.test(c.n) || c.us;
837
+ const w = named ? whereSoft(c) : where(c);
838
+ if (w !== 'none') return w === 'gov' ? 'judge' : null;
839
+ return /\b(federal|district|circuit|superior|probate|municipal|juvenile|criminal|appellate|appeals|bankruptcy|magistrate|administrative law|immigration|court|tribal)\b/.test(c.n) || c.us || (c.retired && /^(?:hon\.? )?judge$/.test(c.n)) ? 'judge' : null;
840
+ }],
841
+ // Commissions.
842
+ [String.raw`(?:(?:(?!(?:assistant|aide|driver|secretary|speechwriter|son|daughter|wife|husband|married|future|aspiring|campaign|former|endorsed|staff|intern|clerk|to|for|of|by|the|a|an|with)\b)[a-z.'-]+ ){0,3}(?:county|city|town|village|borough|parish) )?(?:(?:planning|zoning|parks?(?: and recreation)?|library|historic preservation) )*(?:county |city |town )?commissioner(?: .*)?`,
843
+ (c) => (/\b(county|city|town|village|borough|parish)\b/.test(c.n) ? soft('govOfficial')(c) : /\b(planning|zoning|parks?|library|historic)\b/.test(c.n) ? notOther('govOfficial')(c) : SKIP)],
844
+ [String.raw`(?:police|fire) (?:commissioner|chief)|chief of (?:police|the fire department)|superintendent of police`, needGov('govSenior')],
845
+ [String.raw`chief`, (c) => (where(c) === 'gov' && /\b(police|fire|sheriff)/.test(c.rest || c.next) ? 'govSenior' : SKIP)],
846
+ [String.raw`(?:fcc|sec|ftc|fec|nrc|ferc|cftc|eeoc|nlrb) (?:commissioner|chair(?:man|woman)?)`, notOther('govSenior')],
847
+ // An agency's initials are also its programs' ("SBA Administrator" at a
848
+ // bank lends SBA loans): its head names the agency, or is the whole headline.
849
+ [String.raw`(?:fda|irs|cbp|ice|fema|epa|ssa|uspto|nasa|faa|tsa|dea|atf|gsa|sba) (?:commissioner|administrator|chair(?:man|woman)?)`, (c) => (where(c) === 'gov' || alone(c) ? 'govSenior' : null)],
850
+ [String.raw`(?:deputy|assistant|associate) commissioner(?: .*)?`, (c) => (where(c) === 'gov' ? 'govOfficial' : null)],
851
+ [String.raw`commissioner(?: of .*)?`, (c) => {
852
+ const w = where(c);
853
+ if (w === 'other') return null;
854
+ const own = [c.n, ...pieces(c.rest), ...(c.rest ? [] : [c.next]), c.prevLeads ? c.prev : ''];
855
+ if (own.some((p) => STATE_BODY.test(p))) return 'govSenior';
856
+ if (own.some((p) => LOCAL_GOV.test(p))) return 'govOfficial';
857
+ if ((/^commissioner of (the )?(health|education|agriculture|insurance|labor|revenue|police|corrections|public safety|human services|social services|transportation|environmental protection|internal revenue|food and drugs|u\.?\s?s\.? customs|immigration|social security)$/.test(c.n) && nothingElse(c)) || w === 'gov') return 'govSenior';
858
+ return localPlace(c) ? 'govOfficial' : null;
859
+ }],
860
+ // An agency's head: the agency named in full, as the title's or the part's
861
+ // organization ("Administrator, U.S. Small Business Administration").
862
+ [String.raw`(?:deputy )?administrator(?: of .*)?`, (c) => {
863
+ const of = c.n.match(/ of (.+)$/);
864
+ const named = of ? AGENCY_EXACT.test(of[1]) || /^(?:the )?(?:nasa|epa|fema|usaid|sba|gsa|faa|tsa|nhtsa|noaa)$/.test(of[1]) : (c.rest ? pieces(c.rest) : [c.next]).some((p) => AGENCY_EXACT.test(p));
865
+ return named ? (/^deputy/.test(c.n) ? 'govOfficial' : 'govSenior') : null;
866
+ }],
867
+ [String.raw`chair(?:man|woman|person)?(?: of .*)?`, (c) => (!c.at && [c.n.replace(/^chair(?:man|woman|person)? of (?:the )?/, ''), ...pieces(c.rest), ...(c.rest ? [] : [c.next])].some((p) => STATE_BODY.test(p)) ? 'govSenior' : SKIP)],
868
+ // Local officials: a council's own name, or a city's, a county's or a district's.
869
+ [String.raw`(?:(?:${STATES}|[a-z.'-]+ (?:city|county)|city|town|village|borough|county|metro|district \d+|ward \d+|at-large|deputy|vice|chair|former) )*(?:council ?(?:member|man|woman|person)|councilmember|councill?or|alder(?:man|woman|person)|selectman|selectwoman|select board member)(?: .*)?`,
870
+ (c) => (/\b(forbes|advisory|parent|students?|youth|business|young entrepreneur|yec|ypo|eo|technology|tech|advisors?|chamber|young professionals|leadership|development|nonprofit)\b/.test(c.part) ? null
871
+ : where(c) === 'gov' || (/\b(city|town|village|borough|county|district|ward|metro|at-large|parish)\b/.test(c.n) && whereSoft(c) !== 'other') || (where(c) === 'none' && pieces(c.rest).some((p) => placeLike(p))) ? 'govOfficial' : null)],
872
+ [String.raw`(?:(?:(?!(?:assistant|aide|driver|secretary|speechwriter|son|daughter|wife|husband|married|future|aspiring|campaign|former|endorsed|staff|intern|clerk|to|for|of|by|the|a|an|with)\b)[a-z.'-]+ ){0,3})?county supervisor(?:, .*)?|member of the (?:[a-z.']+ ){0,2}board of supervisors`, (c) => (nothingElse(c) || pieces(c.rest).some((p) => placeLike(p)) ? 'govOfficial' : null)],
873
+ [String.raw`(?:(?:(?!(?:assistant|aide|driver|secretary|speechwriter|son|daughter|wife|husband|married|future|aspiring|campaign|former|endorsed|staff|intern|clerk|to|for|of|by|the|a|an|with)\b)[a-z.'-]+ ){0,3}(?:county|parish) )?sheriff(?: of .*)?`, (c) => (where(c) === 'gov' || (/\b(county|parish)\b/.test(c.n) && whereSoft(c) !== 'other') || (where(c) === 'none' && !c.after && [...pieces(c.rest), c.rest ? '' : c.next].some((p) => LOCAL_PLACE.test(p))) ? 'govOfficial' : null)],
874
+ [String.raw`supervisor`, (c) => (pieces(c.rest).some((p) => /board of supervisors$/.test(p) && isGovOrg(p)) ? 'govOfficial' : SKIP)],
875
+ // A private school's board is its trustees'.
876
+ [String.raw`school board (?:member|chair(?:man|woman|person)?|trustee|president|vice chair)(?:, .*)?|member of the (?:[a-z.']+ ){0,3}school board`, needGov('govOfficial')],
877
+ [String.raw`prime minister(?: of (?:the )?(?:${COUNTRIES}))?|member of parliament(?: for .*)?`, (c) => (/ of /.test(c.n) ? ownOnly('govLeader')(c) : needGov('govLeader')(c))],
878
+ ].map(([src, key]) => [new RegExp(`^${LEAD}(?:${src})$`), key]);
879
+ const OFFICE_TABLES = { corpOfficer: CORP_OFFICER, notCourt: NOT_COURT, fedBody: FED_BODY, dept: DEPT, mock: MOCK, localGov: LOCAL_GOV,
880
+ tribes: TRIBES, tribalGov: TRIBAL_GOV, tribalBusiness: TRIBAL_BUSINESS, legislature: LEGIS, stateItself: STATE_ITSELF, agency: AGENCY,
881
+ agencyExact: AGENCY_EXACT, notGov: NOT_GOV, place: PLACE, notAnOrg: NOT_AN_ORG, judicialArea: JUDICIAL_AREA, orgWord: ORG_WORD,
882
+ jokePlace: JOKE_PLACE, municipality: MUNICIPALITY, party: PARTY, nations: NATIONS, sales: SALES, fedReserve: FED_RESERVE, stateBody: STATE_BODY, milRole: MIL_ROLE, serviceRetired: SERVICE_RETIRED,
883
+ // How the tables are applied, too: a change to where a title is held rescores like a table's.
884
+ code: [pieces, isGovOrg, isOrg, anotherTitle, whereOwn, where, alone, besides, houseOf, congress, inState, notOther, notCourt, officeTitle, militaryTitle, commandLevel, readPart, readRoles].map(String),
885
+ qualifiedService: QUALIFIED_SVC, restIsService: REST_IS_SERVICE, unitLevels: UNIT_LEVELS, states: STATES, countries: COUNTRIES, international: INTERNATIONAL, stateGov: STATE_GOV, govOrg: GOV_ORG,
886
+ civic: CIVIC, lead: LEAD, service: SVC, serviceIn: SERVICE_IN, navy: NAVY_IN, serviceOnly: SERVICE_ONLY, milUnit: MIL_UNIT,
887
+ notMilitary: NOT_MILITARY, rankShort: RANK_SHORT, ranks: RANKS,
888
+ gov: GOV.map(([re, key]) => [re, typeof key === 'function' ? String(key) : key]) };
889
+
890
+ const lowerPart = (text) => String(text || '').normalize('NFKD').replace(/[\u0300-\u036f]/g, '').replace(/[\p{Extended_Pictographic}\u{1F1E6}-\u{1F1FF}\uFE0F\u200D]/gu, ' ').toLowerCase()
891
+ .replace(/\(\s*([a-z.]+),\s*(?:ret(?:\.|ired|d\.?)?|r)\s*\)/g, ' $1 ').replace(/\(\s*(ret(\.|ired|d\.?)?|r)\s*\)/g, ' ')
892
+ .replace(/[’‘]/g, "'").replace(/\bambassador at large\b/g, 'ambassador-at-large').replace(/\s+/g, ' ').trim();
893
+ // What an official is "for": a portfolio, not a company ("Under Secretary for Science and Technology").
894
+ const PORTFOLIO = /\b(technolog\w*|health|financial|science|security|policy|affairs|development|research|management|programs?|services?|education|energy|environment|resources|operations|legislation|planning|preparedness|intelligence|acquisition|readiness|innovation|infrastructure)\b/;
895
+ // Officials' titles written short, at the start of a title: "Sen., Florida Senate", "Gov. of Ohio".
896
+ const GOV_SHORT = [[/^state sen\.?(?=\s|,|$)/, 'state senator'], [/^sen\.?(?=\s|,|$)/, 'senator'], [/^lt\.? gov\.?(?=\s|,|$)/, 'lieutenant governor'], [/^gov\.?(?=\s|,|$)/, 'governor'],
897
+ [/^amb\.?(?=\s|,|$)/, 'ambassador'], [/^del\.?(?=\s|,|$)/, 'delegate'], [/^rep\.(?=\s|,|$)/, 'representative']];
898
+
899
+ /**
900
+ * A government or military title written where a title goes, or null: the
901
+ * part's text up to its first comma, "at", "@" or bracket is the title; the
902
+ * rest of the part, and the parts on either side, only say where it is held.
903
+ * A rank that says it's retired comes back with `retired`.
904
+ */
905
+ // Staff words: a part like this before an official's title names the official as their principal.
906
+ // An official's own title in the part before ("Former Governor | U.S. Senator") isn't a staffer's.
907
+ const officeLike = (p) => /\b(senator|congress\w*|representative|governor|mayor|secretary of|judge|justice|commissioner|general|admiral|colonel|captain|commander)\b/.test(p) && !/\b(aide|assistant|driver|clerk|staff|intern|secretary to|press secretary)\b/.test(p);
908
+ const STAFFER = /\b(aide|law clerk|assistant|staff(?:er)?|scheduler|clerk|paralegal|advocate|driver|intern|fellow|chief of staff|press secretary|secretary|speechwriter|director|counsel|analyst|investigator|deputy|dispatcher|detective|generalist|liaison|coordinator|caseworker|officer|manager|specialist|writer|photographer|agent)\b/;
909
+ function officeTitle(part, prev = '', next = '', others = [], former = false, after = '') {
910
+ const t = lowerPart(part);
911
+ const cut = t.search(/,|\s(?:at|@)\s|\s@|\(/);
912
+ const title = (cut < 0 ? t : t.slice(0, cut)).trim().replace(/[.:;]+$/, '');
913
+ const rest = cut < 0 ? '' : t.slice(cut).replace(/^[,\s]+/, '');
914
+ const side = { prev: lowerPart(prev), next: lowerPart(next) };
915
+ // The official or flag officer a staffer works for: "Flag Aide | Rear Admiral, U.S. Navy".
916
+ const principal = !!side.prev && STAFFER.test(side.prev) && !FORMER.test(prev) && !officeLike(side.prev);
917
+ const mil = militaryTitle(part, t, title, rest, side.prev, side.next, others.map(lowerPart), RETIRED.test(next) || RETIRED_ONLY.test(next), lowerPart(after));
918
+ if (mil && principal && (mil.key === 'seniorGeneral' || mil.key === 'general')) return null;
919
+ if (mil) return { ...LEVELS[mil.key], ...(mil.retired && { retired: true }) };
920
+ // Government: never a club's, a church's, a school's, a fraternity's, a
921
+ // mock government's or a joke's, and never at an organization that isn't a
922
+ // government's. A club or a school in another part is where() 's to see.
923
+ if (principal || CIVIC.test(t.replace(MUNICIPALITY_OF, ' ')) || STUDENT_ORG.test(t) || others.map(lowerPart).some((o) => MOCK.test(o) && !MOCK_PAST.test(o)) || /^(candidate|nominee|running)\b/.test(title)) return null;
924
+ const at = /^(?:at|@)\s/.test(rest);
925
+ if (at && !pieces(rest).some(isGovOrg)) return null;
926
+ let n = title.replace(new RegExp(`^${LEAD}`), '');
927
+ for (const [re, full] of GOV_SHORT) if (re.test(n)) { n = n.replace(re, full); break; }
928
+ // An organization written inside the title is its own: "State Representative for Northwind Insurance".
929
+ const inTitle = n.match(/ (?:for|of|to|at) (?:the )?(.+)$/);
930
+ if (inTitle && (isKnownCompany(inTitle[1]) || (isOrg(inTitle[1]) && !PORTFOLIO.test(inTitle[1]))) && !isGovOrg(inTitle[1]) && !DEPT_OF.test(inTitle[1]) && !MUNICIPALITY.test(inTitle[1])) return null;
931
+ const c = { n, part: t, rest, at, prev: side.prev, prevLeads: !!prev && others[0] === prev, next: side.next, after: lowerPart(after),
932
+ text: `${side.prev} ${t} ${side.next}`, service: SERVICE_IN.test(t), retired: former || RETIRED.test(part),
933
+ retTag: RETIRED.test(part), us: /\b(?:u\.?\s?s\.?|united states)\s/.test(title) };
934
+ for (const [re, key] of GOV) {
935
+ if (!re.test(title) && !re.test(n)) continue; // n: a short form spelled out
936
+ const k = typeof key === 'function' ? key(c) : key;
937
+ if (k === SKIP) continue;
938
+ return k ? LEVELS[k] : null;
939
+ }
940
+ return null;
941
+ }
942
+
943
+ // An audience of their own, in one part of a headline: "2.5M+ followers",
944
+ // "2,500,000 followers", "1.2M monthly listeners", "500K subscribers", "3M+ on
945
+ // TikTok". Not views, users or impressions, which are a campaign's or a
946
+ // product's (those are the reach bonus's), and not in a part about growing or
947
+ // managing someone else's ("Grew our TikTok to 2M followers", "Managed
948
+ // accounts with 10M+ followers").
949
+ const COUNT = String.raw`(\d{1,3}(?:,\d{3})+|\d+(?:\.\d+)?)\s?(k|m|b|thousand|million|billion)?\+?`;
950
+ const AUDIENCE = [
951
+ new RegExp(String.raw`(?<![\w.,$])${COUNT}((?:\s+[a-z]+){0,2}?)\s+(followers|subscribers|subs|listeners|readers|fans)\b`, 'gi'),
952
+ new RegExp(String.raw`(?<![\w.,$])${COUNT}\s+(on|across)\s+(tiktok|youtube|instagram|ig|twitter|x|linkedin|snapchat|twitch|facebook|threads|social media|socials)\b`, 'gi'),
953
+ ];
954
+ const NOT_THEIR_AUDIENCE = /\b(grew|grow|growing|grown|scaled|scaling|built|building|drove|driving|generated|generating|managed|managing|manage|helped|helping|clients?)\b/i;
955
+ const UNIT = { k: 1e3, thousand: 1e3, m: 1e6, million: 1e6, b: 1e9, billion: 1e9 };
956
+
957
+ /** The audience level a part of a headline claims (LEVELS key), or null. */
958
+ function audienceIn(part = '') {
959
+ if (NOT_THEIR_AUDIENCE.test(part)) return null;
960
+ let most = 0;
961
+ for (const re of AUDIENCE) {
962
+ for (const m of part.matchAll(re)) most = Math.max(most, Number(m[1].replace(/,/g, '')) * (UNIT[(m[2] || '').toLowerCase()] || 1));
963
+ }
964
+ return most >= 1e7 ? 'audience10m' : most >= 1e6 ? 'audience1m' : most >= 1e5 ? 'audience100k' : null;
965
+ }
966
+
967
+ // A title's company written without "at" (readRoles) is only a guess, so it's
968
+ // kept narrow. A founder, an owner or a CEO leads a venture of their own: a big
969
+ // company after their title is an accelerator, an investor, a school or a past
970
+ // employer ("Founder | Y Combinator", "CEO | Stanford"), almost never theirs.
971
+ // A program, an award, a membership or a degree is not a job there ("AWS
972
+ // Community Builder", "Forbes Council Member", "Harvard MBA", "Director,
973
+ // Microsoft Alliance"). And a school after any title but an academic one is
974
+ // more often where they studied ("VP Marketing | Harvard").
975
+ const OWN_VENTURE = /\b((co-?)?founder|cofounder|owner|entrepreneur|ceo|chief executive)\b/i;
976
+ const AFFILIATION = /\b(alum|alumn(i|us|a|ae)|community|builders?|alliances?|council|members?|fellows?|fellowship|accelerator|cohort|batch|portfolio|backed|residents?|residency|speakers?|summit|conference|awards?|honorees?|mentors?|advisors?|investors?|partners?|foundation|club|society|chapter|program(me)?|scholars?|grads?|graduate|mba|gsb|class)\b/i;
977
+ const ACADEMIC = /\b(prof(essor)?|lecturer|dean|provost|chancellor|faculty|instructor|postdoc(toral)?|research(er)?|scientist|department|dept)\b/i;
978
+
979
+ /** The company the lists know that `text` names, for the title in `titlePart` to be held at, or null. */
980
+ function heldAt(text, titlePart) {
981
+ if (OWN_VENTURE.test(titlePart) || AFFILIATION.test(text)) return null;
982
+ const name = cleanCompany(text);
983
+ if (!name || !(KNOWN_BY_NAME.has(name) || DATA_BY_NAME.has(name))) return null;
984
+ return KNOWN_INDUSTRY.get(name) === 'education' && !ACADEMIC.test(titlePart) ? null : name;
985
+ }
986
+
987
+ /** A company named after a comma in a title's part: "Corporate VP, Samsung". */
988
+ function heldAfterComma(part) {
989
+ for (const piece of part.split(/,\s+/).slice(1)) {
990
+ const name = heldAt(piece, part);
991
+ if (name) return name;
992
+ }
993
+ return null;
994
+ }
995
+
162
996
  /**
163
997
  * Every role a headline names: "CEO @ X | Ex-VP at Google | Speaker" gives a
164
998
  * current CEO role at X and a former VP role at Google. A part that names only
165
999
  * a company ("GTM @ Quillon") still says they work there.
1000
+ *
1001
+ * A title's company written without "at" is where it's held: after a comma
1002
+ * ("Corporate VP, Samsung") or as the next part ("President | The Coca-Cola
1003
+ * Company", "Head of Partnerships - Snap"). Only a company the lists know
1004
+ * (curated or public dataset), since anything can follow a title ("Founder |
1005
+ * Speaker", "President, North America"), only for a current title without
1006
+ * one, and not where heldAt() says it's an affiliation. Such a role is
1007
+ * `inferred`: a company scan's company goes before it.
1008
+ * An audience of their own is a role of its own (`audience`), with no company.
166
1009
  */
167
1010
  export function readRoles(headline = '', role = '') {
168
1011
  const out = [];
169
- for (const raw of headlineParts(headline || role)) {
170
- const former = FORMER.test(raw);
1012
+ const parts = headlineParts(headline || role);
1013
+ let last = null; // the last role a title gave: { role, i, rank }
1014
+ let retiredNext = false; // a lone "Retired" before any role: the next one's
1015
+ for (const [i, raw] of parts.entries()) {
1016
+ // "Colonel, U.S. Army | Retired": the role just before, or a rank's with
1017
+ // its service between ("Colonel | U.S. Army | Retired"); not a civilian
1018
+ // job further back ("Senior Manager at Deloitte | Navy Veteran | Retired").
1019
+ if (RETIRED_ONLY.test(raw)) {
1020
+ const afterwards = /\b(board|volunteer|advis[eo]r|mentor|trustee|chair|docent|member|consultant|adjunct|part-time|substitute|fractional|golfer|investor|coach|tutor)\b/i.test(last?.role.part || '');
1021
+ if (!last) { retiredNext = true; continue; }
1022
+ if (last && !afterwards && (last.i === i - 1 || (last.i === i - 2 && last.rank && SERVICE_ONLY.test(lowerPart(parts[i - 1]))))) last.role.former = true;
1023
+ continue;
1024
+ }
1025
+ // "Paralegal – General Counsel": the office they work in, split off by a dash.
1026
+ if (/^(?:the )?(?:general|chief) counsel(?:,.*)?$/i.test(raw.trim()) && i > 0 && !(readPart(parts[i - 1])?.level >= LEVELS.vp.level)) continue;
1027
+ const retiredTag = RETIRED.test(raw);
171
1028
  const part = raw.replace(FORMER, '').replace(/^[@\s.:]+/, '');
172
- let title = readPart(part);
173
- const company = companyIn(part) || (out.length === 0 && isKnownCompany(part) ? cleanCompany(part) : null);
1029
+ const office = officeTitle(part, parts[i - 1] ?? '', parts[i + 1] ?? '', parts, FORMER.test(raw) || retiredTag, parts[i + 2] ?? '');
1030
+ // A civilian job is retired when the tag is its own: "Teacher (Retired)",
1031
+ // "Nurse, Retired". Not a service's after it ("Program Manager at Leidos,
1032
+ // U.S. Army (Ret.)"), nor a second role's ("Realtor at Compass,
1033
+ // Firefighter (Ret.)", "Teacher (Retired), Realtor at Compass").
1034
+ const roles = part.replace(/\([^)]*\)/g, ' ').split(',').filter((p) => p.trim() && !RETIRED_ONLY.test(p));
1035
+ const former = FORMER.test(raw) || (retiredTag && (!!office || (!SERVICE_RETIRED.test(part.toLowerCase()) && roles.length <= 1)));
1036
+ let title = office || readPart(part);
1037
+ const retired = !!title?.retired;
1038
+ if (retired) { const { retired: _, ...rest } = title; title = rest; }
1039
+ let company = companyIn(part) || (out.length === 0 && isKnownCompany(part) ? cleanCompany(part) : null);
1040
+ let inferred = false;
1041
+ if (!company && title) {
1042
+ company = heldAfterComma(part);
1043
+ inferred = !!company;
1044
+ }
174
1045
  if (!title && company) title = { ...LEVELS.ic, label: 'Works there' };
175
- if (title) out.push({ title, company, former, part });
1046
+ if (title) {
1047
+ out.push({ title, company, former: former || retired || retiredNext, part, ...(inferred && { inferred }) });
1048
+ retiredNext = false;
1049
+ last = { role: out[out.length - 1], i, rank: RANKED.has(title.key) };
1050
+ }
1051
+ else if (!former) {
1052
+ const before = [...out].reverse().find((r) => !r.audience);
1053
+ const at = before && !before.former && !before.company ? heldAt(part, before.part) : null;
1054
+ if (at) Object.assign(before, { company: at, inferred: true });
1055
+ }
1056
+ const audience = audienceIn(part);
1057
+ if (audience) out.push({ title: LEVELS[audience], company: null, former, part, audience: true });
176
1058
  }
177
1059
  return out;
178
1060
  }
179
1061
 
180
1062
  /** Is this person a student right now? Then no other title makes them powerful yet. */
181
1063
  export function isStudent(headline = '') {
182
- return headlineParts(headline).some((p) => !FORMER.test(p) && (studies(p) || INTERN.test(` ${p.toLowerCase()} `)));
1064
+ return headlineParts(headline).some((p) => !FORMER.test(p) && !SERVICE_SCHOOL.test(p) && (studies(p) || INTERN.test(` ${p.toLowerCase()} `)));
183
1065
  }
184
1066
 
185
- /** The person's first current title (a quick read; scoring weighs every role). */
1067
+ /** The person's first current title (a quick read; scoring weighs every role), an audience only when it's all they state. */
186
1068
  export function readTitle(headline = '', role = '') {
187
1069
  const roles = readRoles(headline, role);
188
- const r = roles.find((x) => !x.former) || roles[0];
1070
+ const r = roles.find((x) => !x.former && !x.audience) || roles.find((x) => !x.former) || roles[0];
189
1071
  return r ? { ...r.title, part: r.part } : { ...LEVELS.unknown, part: headlineParts(headline || role)[0] || '' };
190
1072
  }
191
1073
 
@@ -205,7 +1087,7 @@ export function readTitle(headline = '', role = '') {
205
1087
  // Nothing on the list is below 7. Regional picks, picks from one person's
206
1088
  // career or network, and small startups are not on it: they are estimated
207
1089
  // from the network like any other company (4, or 5–6 when many of the
208
- // network's people work there), and anyone can score them on Paths → Scores,
1090
+ // network's people work there), and anyone can score them on the Scores tab,
209
1091
  // where a score set always wins. When in doubt, a company stays off: the
210
1092
  // estimate is the neutral default.
211
1093
  //
@@ -259,7 +1141,7 @@ export const KNOWN_COMPANIES = [
259
1141
  ['Apple', 10, /^apple( inc)?$/, 'tech'],
260
1142
  ['Microsoft', 10, /^microsoft\b/, 'tech'],
261
1143
  ['Amazon', 10, /^(amazon|aws|amazon web services)\b(?! (conservation|watch)\b)/, 'tech'],
262
- ['Meta', 10, /^meta( platforms)?$|^(facebook|instagram|whatsapp|reality labs)\b/, 'tech'],
1144
+ ['Meta', 10, /^meta( platforms| superintelligence labs| ai)?$|^(facebook|instagram|whatsapp|reality labs)\b/, 'tech'],
263
1145
  ['NVIDIA', 10, /^nvidia\b/, 'tech'],
264
1146
  ['OpenAI', 10, /^(openai|open ai)\b/, 'tech'],
265
1147
  ['Anthropic', 10, /^anthropic\b/, 'tech'],
@@ -296,7 +1178,7 @@ export const KNOWN_COMPANIES = [
296
1178
  // 8 — major companies and institutions
297
1179
  ['Salesforce', 8, /^salesforce\b/, 'tech'], ['Adobe', 8, /^adobe( systems)?$/, 'tech'], ['Oracle', 8, /^oracle( america| health| netsuite| cloud( infrastructure)?| financial services( software)?)?$/, 'tech'], ['IBM', 8, /^ibm\b/, 'tech'],
298
1180
  ['Uber', 8, /^uber( technologies| eats)?$/, 'tech'], ['Airbnb', 8, /^airbnb\b/, 'tech'], ['DoorDash', 8, /^doordash\b/, 'tech'], ['Spotify', 8, /^spotify\b/, 'entertainment'],
299
- ['Snap', 8, /^(snap|snapchat)( inc)?$/, 'media'], ['Pinterest', 8, /^pinterest\b/, 'media'], ['Reddit', 8, /^reddit\b/, 'media'], ['X', 8, /^(x corp|twitter)\b/, 'media'],
1181
+ ['Snap', 8, /^(snap|snapchat)( inc)?( (specs|spectacles|(mena|emea|apac|latam|north america)( region)?))?$/, 'media'], ['Pinterest', 8, /^pinterest\b/, 'media'], ['Reddit', 8, /^reddit\b/, 'media'], ['X', 8, /^(x corp|twitter)\b/, 'media'],
300
1182
  ['Roblox', 8, /^roblox\b/, 'entertainment'], ['Shopify', 8, /^shopify\b(?! (plus )?partners?\b)/, 'consumer'], ['Snowflake', 8, /^snowflake( computing)?$/, 'tech'], ['Datadog', 8, /^datadog\b/, 'tech'],
301
1183
  ['CrowdStrike', 8, /^crowdstrike\b/, 'tech'], ['ServiceNow', 8, /^servicenow\b/, 'tech'], ['Canva', 8, /^canva\b/, 'tech'],
302
1184
  ['Intuit', 8, /^intuit\b/, 'tech'], ['Cisco', 8, /^cisco\b/, 'tech'], ['Qualcomm', 8, /^qualcomm\b/, 'tech'], ['AMD', 8, /^amd\b/, 'tech'],
@@ -415,6 +1297,704 @@ export const KNOWN_COMPANIES = [
415
1297
  ['Vanderbilt University', 7, university('vanderbilt'), 'education'],
416
1298
  ];
417
1299
 
1300
+ // ── the public company dataset ─────────────────────────────────────────────
1301
+ // Organizations the curated list (KNOWN_COMPANIES, above) leaves off, scored
1302
+ // from public facts.
1303
+ //
1304
+ // The curated list is kept to household names, 7 to 10, and "when in doubt, a
1305
+ // company stays off". That leaves most of the places people actually work
1306
+ // unknown, and an unknown company scores a neutral 5. This is the second,
1307
+ // wider list: companies and institutions with a public footprint that most
1308
+ // people wouldn't know by name, each scored against the scale below from facts
1309
+ // anyone can check, with its source. It is read after the curated list and
1310
+ // before the estimate from a network's own headcount, and it grows each release.
1311
+ //
1312
+ // The scale, from public facts only:
1313
+ // 8 Fortune 500 / Forbes Global 2000 / S&P 500 scale (about $20B+ market
1314
+ // cap or valuation, or 20,000+ staff), a major pro league, a U.S. federal
1315
+ // department; or a studio or park whose staff are such a company's.
1316
+ // 7 a listed company or a private one valued at about $2–20B, a national TV
1317
+ // network, a large health system, a major defense research lab, a
1318
+ // university ranked about 11–50 (U.S. News Best National Universities).
1319
+ // 6 established and notable: a listed small or mid cap, a venture-backed
1320
+ // company with about $100M+ raised or 500+ staff, a university ranked
1321
+ // about 51–150, a national cultural institution.
1322
+ // Smaller than that isn't listed: it would score the neutral 5 anyway.
1323
+ //
1324
+ // Rules, as for the curated list:
1325
+ // - Built from public sources only (exchange listings, reported valuations,
1326
+ // rankings, the organizations' own sites). Never from anyone's scan: the app
1327
+ // uploads nothing, so nothing a user scans can reach this file.
1328
+ // - Organizations only; nothing here is about a person. A one-person business
1329
+ // or a personal brand is never listed: its name would point at someone.
1330
+ // - A name several organizations share is listed only in forms that say which
1331
+ // ("Hotwire Communications", not "Hotwire"; "Simon Property Group", not
1332
+ // "Simon"), and a venue named for a company ("Raymond James Stadium") never
1333
+ // matches it. tests/company-data.test.mjs holds the names each must read and
1334
+ // the names that must stay their own. It lives here, not in a file of its
1335
+ // own, because this module imports nothing (tests/legacy-scores.test.mjs).
1336
+ //
1337
+ // Each entry: [name, score, alias, industry, source]. The alias matches the
1338
+ // name as cleanCompany() reads it (lowercase, from the start); the industry is
1339
+ // one of lib/companies.js's INDUSTRIES keys; the source is where the score's
1340
+ // facts come from.
1341
+
1342
+ // Most entries match a few exact forms: the names people actually write, each
1343
+ // matched whole (after cleanCompany's trim: lowercase, no "Inc.", no "the"), so
1344
+ // a longer name that only starts the same way never reads as one.
1345
+ const esc = (x) => x.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
1346
+ const exactly = (...forms) => new RegExp(`^(${forms.map((f) => esc(f.toLowerCase())).join('|')})$`);
1347
+
1348
+ export const COMPANY_DATA = [
1349
+ // 8 — major companies and institutions
1350
+ ['Anduril', 8, /^anduril( industries)?$/, 'defense', '$61B valuation, Series H (May 2026)'],
1351
+ ['CoreWeave', 8, /^coreweave$/, 'tech', 'NASDAQ: CRWV, about $48B market cap (Sept 2026)'],
1352
+ ['GE Vernova', 8, /^ge (vernova|gas power|renewable energy|grid solutions|power)$/, 'industry', 'NYSE: GEV, about $255B market cap, 78,000 staff (2025–26)'],
1353
+ ['LSEG', 8, /^(lseg|london stock exchange( group)?|refinitiv|ftse russell)$/, 'finance', 'LSE: LSEG, FTSE 100, 28,500 staff (2025)'],
1354
+ ['MLB', 8, /^(mlb|major league baseball)\b(?! (players|the show)\b)/, 'entertainment', 'A major U.S. pro league, about $12B revenue (2024)'],
1355
+ ['Raymond James', 8, sponsor('raymond james'), 'finance', 'NYSE: RJF, S&P 500, about $31B market cap (Sept 2026)'],
1356
+ ['Siemens Energy', 8, /^siemens (energy|gamesa)\b/, 'industry', 'Xetra: ENR, about 103,000 staff (FY2025)'],
1357
+ ['Simon Property Group', 8, /^simon (property( group)?|malls|premium outlets)$/, 'realestate', 'NYSE: SPG, S&P 100, about $78B market cap (Sept 2026)'],
1358
+ ['U.S. Department of the Treasury', 8, /^((the )?u\.?s\.? )?(department of the treasury|treasury department)$|^(u\.?s\.? treasury|treasury\.gov)$/, 'defense', 'U.S. federal department, about 116,000 staff (2025)'],
1359
+ ['Universal Orlando', 8, /^universal( orlando( resort)?| studios (orlando|florida)|['’]?s (islands of adventure|volcano bay|epic universe)| epic universe)$|^(islands of adventure|epic universe)$/, 'entertainment', 'NBCUniversal (Comcast), about 28,000 staff (2024)'],
1360
+ ['Universal Pictures', 8, /^universal (pictures( international)?|filmed entertainment( group)?)$/, 'entertainment', 'NBCUniversal (Comcast), a Big Five Hollywood studio'],
1361
+ // 7 — well-known companies and institutions
1362
+ ['AdventHealth', 7, /^advent ?health( orlando| medical group)?$|^florida hospital$/, 'health', 'Nonprofit health system, about 100,000 staff (2025)'],
1363
+ ['AFRL', 7, /^(afrl|(u\.?s\.? )?air force research lab(oratory)?|afosr|air force office of scientific research)$/, 'defense', 'U.S. Air Force research laboratory, 11,000+ personnel (2024)'],
1364
+ ['AmTrust Financial', 7, /^amtrust( financial( services)?| north america| international| insurance)?$/, 'finance', 'Private insurer, about $9B gross written premium (2025)'],
1365
+ ['B&Q', 7, /^b ?& ?q$/, 'consumer', 'Kingfisher plc (LSE: KGF), 27,000 staff (2023)'],
1366
+ ['Black & Veatch', 7, /^black (&|and) veatch\b/, 'industry', 'Employee-owned engineering firm, about 13,000 staff, $5.1B revenue (2025)'],
1367
+ ['CBS Sports', 7, /^cbs ?sports( network| digital| hq| golazo network)?$|^cbssports\.com$/, 'entertainment', 'Paramount Skydance (NASDAQ: PSKY)'],
1368
+ ['DISH Network', 8, /^dish( network| tv| media| (&|and) sling( tv)?)?$|^sling tv$/, 'entertainment', 'EchoStar (8, like its parent); DISH and Sling about $9.7B revenue (2025)'],
1369
+ ['EliseAI', 7, /^(elise ?ai|meet ?elise)$/, 'tech', '$2.2B valuation, Series E (Aug 2025)'],
1370
+ ['fal', 7, /^fal( ?\.ai| ai)?$/, 'tech', '$4.5B valuation, Series D (Dec 2025)'],
1371
+ ['Genpact', 7, /^genpact\b/, 'consulting', 'NYSE: G, about 146,500 staff (2025)'],
1372
+ ['Hotwire Communications', 7, /^hotwire communications$/, 'tech', 'About $7B valuation in Brookfield deal (June 2025)'],
1373
+ ['IMAX', 7, /^imax\b/, 'entertainment', 'NYSE: IMAX, about $3B market cap (Sept 2026)'],
1374
+ ['Lionsgate', 7, /^lions ?gate( studios| films| television| entertainment| canada| uk)?$/, 'entertainment', 'NYSE: LION, about $3.2B market cap (Sept 2026)'],
1375
+ ['Magnolia Network', 7, /^magnolia network$/, 'media', 'Warner Bros. Discovery national cable network'],
1376
+ ['NiCE Cognigy', 7, /^(nice )?cognigy(\.ai)?$/, 'tech', 'NICE Ltd (NASDAQ: NICE), acquired for about $955M (2025)'],
1377
+ ['NSWC Dahlgren', 7, /^(naval surface warfare center,? dahlgren( division)?|nswc dahlgren( division)?|nswcdd)$/, 'defense', 'U.S. Navy warfare center, about 4,700 staff'],
1378
+ ['Orlando Health', 7, /^orlando (health|regional medical center)$/, 'health', 'Nonprofit health system, about 38,000 staff, $9.9B revenue (FY2025)'],
1379
+ ['Polymarket', 7, /^polymarket( us)?$/, 'finance', '$15B valuation, April 2026 round'],
1380
+ ['Roku', 7, /^roku$/, 'tech', 'NASDAQ: ROKU, S&P MidCap 400 (2026)'],
1381
+ ['TEKsystems', 7, /^tek ?systems( global services)?$/, 'consulting', 'Allegis Group, $7B+ revenue (2025)'],
1382
+ ['Temenos', 7, /^temenos( ag| group)?$/, 'tech', 'SIX: TEMN, about 5,100 staff (2025)'],
1383
+ ['Tufts University', 7, university('tufts'), 'education', 'U.S. News Best National Universities, 2025 edition: #37'],
1384
+ ['UC Irvine', 7, /^(uc irvine|uci|university of california,? irvine)$/, 'education', 'U.S. News Best National Universities: #32 (2026 edition)'],
1385
+ ['UC San Diego', 7, /^(uc san diego|ucsd|university of california,? san diego)$/, 'education', 'U.S. News Best National Universities, 2025 edition: #29'],
1386
+ ['UC Santa Barbara', 7, /^(uc santa barbara|ucsb|u\.c\. santa barbara|university of california,? santa barbara)$/, 'education', 'U.S. News Best National Universities, 2025 edition: #39'],
1387
+ ['Under Armour', 7, /^under ?arm(ou|o)r$/, 'consumer', 'NYSE: UAA, about 13,900 staff (2026)'],
1388
+ ['University of Florida', 7, university('university of florida|uf'), 'education', 'U.S. News Best National Universities, 2025 edition: #30'],
1389
+ ['Vanta', 7, /^vanta$/, 'tech', '$4.15B valuation, Series D (July 2025)'],
1390
+ ['Versant Media', 7, /^versant media( group)?$/, 'media', 'NASDAQ: VSNT, Comcast cable networks spin-off (2026)'],
1391
+ ['Whatnot', 7, /^whatnot$/, 'tech', 'Valued at $20B (Aug 2026)'],
1392
+ ['WWE', 7, /^(wwe|world wrestling entertainment)$/, 'entertainment', 'TKO Group Holdings (NYSE: TKO)'],
1393
+ // 6 — established and notable
1394
+ ['A-LIGN', 6, /^a[- ]?lign$/, 'tech', 'About $1B valuation in Hg deal (July 2025)'],
1395
+ ['Aleph Group', 6, /^aleph (group|holdings?)$/, 'media', 'About 2,000 staff, about $495M raised'],
1396
+ ['Angi', 6, /^(angi( homeservices)?|angie['’]?s list|homeadvisor)$/, 'tech', 'NASDAQ: ANGI, about 2,300 staff (2025)'],
1397
+ ['Anomaly', 6, /^anomaly( nyc| new york| la| london| toronto)?$/, 'media', 'Stagwell (NASDAQ: STGW) agency, 800+ staff (2025)'],
1398
+ ['Astrion', 6, /^astrion$/, 'defense', 'Defense contractor, 6,000+ staff (2025)'],
1399
+ ['Babylist', 6, /^babylist( health)?$/, 'consumer', '$750M revenue (2025)'],
1400
+ ['D&AD', 6, /^(d ?& ?ad|design (and|&) art direction)$/, 'media', 'UK design and advertising charity, home of the D&AD Pencils'],
1401
+ ['Even Realities', 6, /^even ?realities$/, 'tech', '$1B valuation (July 2026)'],
1402
+ ['Focusrite', 6, /^focusrite( plc| group| audio engineering)?$/, 'tech', 'LSE AIM: TUNE'],
1403
+ ['Freedom Mortgage', 6, /^freedom mortgage( corp(oration)?)?$/, 'finance', 'Large U.S. mortgage lender, $78B originations (2025)'],
1404
+ ['Hard Rock Digital', 6, /^hard rock (digital|bet)$/, 'entertainment', 'Hard Rock International / Seminole Gaming venture, 500+ staff (2026)'],
1405
+ ['Kurdistan24', 6, /^kurdistan ?24$/, 'media', 'National broadcaster in five languages (since 2015)'],
1406
+ ['Later', 6, /^later(\.com)?$/, 'media', 'Social media platform, Summit Partners-backed ($255M, 2021–22)'],
1407
+ ['National Trust for Scotland', 6, /^(the )?national trust for scotland$/, 'nonprofit', 'National conservation charity, 326,000 members'],
1408
+ ['NewDay USA', 6, /^new ?day (usa|financial)$/, 'finance', 'U.S. VA-loan lender, about 670 staff (2026)'],
1409
+ ['SRM Institute of Science and Technology', 6, /^(srmist|srm ist|srm institute of science (and|&) technology|srm university( chennai)?)$/, 'education', 'NIRF 2025: #11 among Indian universities'],
1410
+ ['ThreatLocker', 6, /^threat ?locker$/, 'tech', 'About $468M raised, $190M Series F (July 2026)'],
1411
+ // Open, as the old list had it: UCF's colleges and offices ("UCF College of
1412
+ // Business", "UCF IT") are UCF, and no other organization starts with its name.
1413
+ ['University of Central Florida', 6, /^(ucf|university of central florida)\b/, 'education', 'U.S. News Best National Universities: about #120 (2025–2027 editions)'],
1414
+ ['University of Minnesota', 6, university('university of minnesota|umn', '|[-,]? ?twin cities'), 'education', 'U.S. News Best National Universities, 2025 edition: #54'],
1415
+ ['University of South Florida', 6, university('university of south florida|usf', '| health| st\\.? petersburg| sarasota[- ]manatee'), 'education', 'U.S. News Best National Universities, 2025 edition: #91'],
1416
+ ['Voloridge', 6, /^voloridge( investment management)?$/, 'finance', 'Quantitative investment firm, $36B regulatory AUM (2025)'],
1417
+ ['Wales Millennium Centre', 6, /^wales millennium cent(re|er)$/, 'entertainment', 'National arts centre of Wales'],
1418
+ // ── grown from public lists (2026-09-28) ──
1419
+ // The Fortune 500 (2025), the U.S. federal government and U.S. News's Best
1420
+ // National Universities (2025 edition, ranks 21–100), less what either list
1421
+ // already had. Each matches only the whole names people write (exactly(),
1422
+ // or university() for a university and its schools), researched from the
1423
+ // lists themselves and the organizations' own pages; forms shared with
1424
+ // anyone else, or that are a common word alone, were left out.
1425
+ // Fortune 500 (2025)
1426
+ ['McKesson', 8, exactly('mckesson', 'covermymeds'), 'health', 'Fortune 500 (2025): #9, $309.0B revenue'],
1427
+ ['Cencora', 8, exactly('cencora', 'amerisourcebergen', 'amerisource bergen'), 'health', 'Fortune 500 (2025): #10, $294.0B revenue'],
1428
+ ['Cardinal Health', 8, exactly('cardinal health'), 'health', 'Fortune 500 (2025): #15, $226.8B revenue'],
1429
+ ['Centene', 8, exactly('centene', 'wellcare', 'wellcare health plans', 'health net', 'fidelis care', 'ambetter', 'ambetter health', 'superior healthplan'), 'health', 'Fortune 500 (2025): #23, $163.1B revenue'],
1430
+ ['Phillips 66', 8, exactly('phillips 66', 'phillips 66 company', 'phillips66'), 'industry', 'Fortune 500 (2025): #28, $145.5B revenue'],
1431
+ ['Marathon Petroleum', 8, exactly('marathon petroleum', 'marathon petroleum company', 'mplx'), 'industry', 'Fortune 500 (2025): #29, $140.4B revenue'],
1432
+ ['Valero', 8, exactly('valero', 'valero energy', 'valero refining'), 'industry', 'Fortune 500 (2025): #34, $124.0B revenue'],
1433
+ ['Archer Daniels Midland', 8, exactly('archer daniels midland', 'archer-daniels-midland company', 'archer daniels midland company', 'archer-daniels-midland', 'adm investor services'), 'industry', 'Fortune 500 (2025): #50, $85.5B revenue'],
1434
+ ['Energy Transfer', 8, exactly('energy transfer', 'energy transfer lp', 'energy transfer partners', 'energy transfer equity'), 'industry', 'Fortune 500 (2025): #53, $82.7B revenue'],
1435
+ ['Sysco', 8, exactly('sysco', 'freshpoint', 'sygma network'), 'consumer', 'Fortune 500 (2025): #56, $78.8B revenue'],
1436
+ ['Publix', 8, exactly('publix', 'publix super markets', 'publix supermarkets', 'publix pharmacy', 'publix liquors'), 'consumer', 'Fortune 500 (2025): #71, $60.2B revenue'],
1437
+ ['TD SYNNEX', 8, exactly('td synnex', 'tdsynnex', 'tech data', 'hyve solutions'), 'tech', 'Fortune 500 (2025): #73, $58.5B revenue'],
1438
+ ['Enterprise Products', 8, exactly('enterprise products', 'enterprise products partners', 'enterprise products partners lp', 'enterprise products company'), 'industry', 'Fortune 500 (2025): #78, $56.2B revenue'],
1439
+ ['Charter Communications', 8, exactly('charter communications', 'charter spectrum', 'spectrum enterprise', 'spectrum reach', 'spectrum business', 'spectrum news', 'spectrum news 13', 'spectrum news ny1', 'spectrum bay news 9', 'cox communications', 'cox business'), 'tech', 'Fortune 500 (2025): #79, $55.1B revenue'],
1440
+ ['Performance Food Group', 8, exactly('performance food group', 'performance food group company', 'performance foodservice', 'reinhart foodservice', 'core-mark international', 'core-mark', 'eby-brown', 'cheney brothers', 'cheney bros'), 'consumer', 'Fortune 500 (2025): #80, $54.7B revenue'],
1441
+ ['Broadcom', 8, exactly('broadcom', 'symantec'), 'tech', 'Fortune 500 (2025): #88, $52.4B revenue'],
1442
+ ['VMware', 8, exactly('vmware', 'vmware by broadcom'), 'tech', 'Broadcom\'s: Fortune 500 (2025): #88, $52.4B revenue'],
1443
+ ['Ingram Micro', 8, exactly('ingram micro', 'ingram micro holding'), 'tech', 'Fortune 500 (2025): #95, $48.0B revenue'],
1444
+ ['Dow', 8, exactly('dow', 'dow chemical company', 'dow chemical'), 'industry', 'Fortune 500 (2025): #103, $43.0B revenue'],
1445
+ ['Thermo Fisher Scientific', 8, exactly('thermo fisher scientific', 'thermo fisher', 'thermofisher', 'thermofisher scientific', 'fisher scientific', 'thermo scientific', 'patheon'), 'health', 'Fortune 500 (2025): #104, $42.9B revenue'],
1446
+ ['US Bancorp', 8, exactly('us bancorp', 'u.s. bancorp', 'u.s. bank', 'us bank', 'usbank', 'u.s. bank national association', 'elavon'), 'finance', 'Fortune 500 (2025): #105, $42.7B revenue'],
1447
+ ['Abbott', 8, exactly('abbott', 'abbott laboratories', 'abbott labs', 'abbott diagnostics', 'abbott nutrition', 'abbott vascular', 'abbott diabetes care', 'abbott rapid diagnostics', 'abbott molecular'), 'health', 'Fortune 500 (2025): #107, $42.0B revenue'],
1448
+ ['Best Buy', 8, exactly('best buy', 'best buy canada'), 'consumer', 'Fortune 500 (2025): #108, $41.5B revenue'],
1449
+ ['GE Aerospace', 8, exactly('ge aerospace', 'ge aviation', 'avio aero'), 'defense', 'Fortune 500 (2025): #118, $38.7B revenue'],
1450
+ ['Honeywell Technologies', 8, exactly('honeywell technologies', 'honeywell building automation', 'honeywell building technologies', 'honeywell industrial automation', 'honeywell process solutions', 'honeywell uop'), 'industry', 'Fortune 500 (2025): #119, $38.5B revenue'],
1451
+ ['Philip Morris International', 8, exactly('philip morris international', 'philip morris products', 'swedish match'), 'consumer', 'Fortune 500 (2025): #121, $37.9B revenue'],
1452
+ ['US Foods', 8, exactly('us foods', 'u.s. foods', 'us foods holding', 'usfoods', 'us foodservice', 'u.s. foodservice'), 'consumer', 'Fortune 500 (2025): #122, $37.9B revenue'],
1453
+ ['D.R. Horton', 8, exactly('d.r. horton', 'dr horton', 'd. r. horton', 'dhi mortgage'), 'realestate', 'Fortune 500 (2025): #123, $36.8B revenue'],
1454
+ ['Lithia Motors', 8, exactly('lithia motors', 'lithia', 'lithia & driveway', 'lithia and driveway'), 'consumer', 'Fortune 500 (2025): #124, $36.6B revenue'],
1455
+ ['Mondelez International', 8, exactly('mondelez international', 'mondelēz international', 'mondelez', 'mondelēz', 'nabisco', 'cadbury'), 'consumer', 'Fortune 500 (2025): #125, $36.4B revenue'],
1456
+ ['CBRE', 8, exactly('cbre', 'cbre group', 'cb richard ellis', 'cbre investment management', 'trammell crow company'), 'realestate', 'Fortune 500 (2025): #128, $35.8B revenue'],
1457
+ ['Lennar', 8, exactly('lennar', 'lennar homes', 'lennar mortgage'), 'realestate', 'Fortune 500 (2025): #129, $35.4B revenue'],
1458
+ ['PNC', 8, exactly('pnc', 'pnc bank', 'pnc financial services', 'pnc financial services group'), 'finance', 'Fortune 500 (2025): #131, $34.4B revenue'],
1459
+ ['Cummins', 8, exactly('cummins', 'accelera by cummins', 'cummins power generation', 'meritor'), 'industry', 'Fortune 500 (2025): #132, $34.1B revenue'],
1460
+ ['PACCAR', 8, exactly('paccar', 'kenworth truck company', 'peterbilt motors', 'peterbilt motors company', 'daf trucks', 'paccar parts', 'paccar financial'), 'industry', 'Fortune 500 (2025): #133, $33.7B revenue'],
1461
+ ['Amgen', 8, exactly('amgen', 'horizon therapeutics'), 'health', 'Fortune 500 (2025): #134, $33.4B revenue'],
1462
+ ['United Natural Foods', 8, exactly('united natural foods', 'unfi', 'supervalu'), 'consumer', 'Fortune 500 (2025): #138, $31.0B revenue'],
1463
+ ['Nucor', 8, exactly('nucor', 'nucor steel', 'vulcraft'), 'industry', 'Fortune 500 (2025): #140, $30.7B revenue'],
1464
+ ['Penske Automotive Group', 8, exactly('penske automotive group', 'penske automotive', 'premier truck group', 'sytner group'), 'consumer', 'Fortune 500 (2025): #141, $30.5B revenue'],
1465
+ ['Coupang', 8, exactly('coupang', 'farfetch'), 'tech', 'Fortune 500 (2025): #142, $30.3B revenue'],
1466
+ ['Hewlett Packard Enterprise', 8, exactly('hewlett packard enterprise', 'hewlett-packard enterprise', 'hpe', 'hpe aruba networking', 'aruba networks', 'hewlett packard labs'), 'tech', 'Fortune 500 (2025): #143, $30.1B revenue'],
1467
+ ['Juniper Networks', 8, exactly('juniper networks'), 'tech', 'Hewlett Packard Enterprise\'s: Fortune 500 (2025): #143, $30.1B revenue'],
1468
+ ['Duke Energy', 8, exactly('duke energy', 'duke energy florida', 'duke energy carolinas', 'duke energy progress', 'duke energy indiana', 'duke energy ohio', 'piedmont natural gas', 'piedmont natural gas company'), 'industry', 'Fortune 500 (2025): #144, $29.9B revenue'],
1469
+ ['Ferguson Enterprises', 8, exactly('ferguson enterprises', 'ferguson'), 'industry', 'Fortune 500 (2025): #146, $29.6B revenue'],
1470
+ ['Jabil', 8, exactly('jabil', 'jabil circuit'), 'tech', 'Fortune 500 (2025): #148, $28.9B revenue'],
1471
+ ['Gilead Sciences', 8, exactly('gilead sciences', 'gilead', 'kite pharma'), 'health', 'Fortune 500 (2025): #149, $28.8B revenue'],
1472
+ ['CarMax', 8, exactly('carmax', 'carmax auto finance', 'edmunds.com'), 'consumer', 'Fortune 500 (2025): #151, $28.2B revenue'],
1473
+ ['NRG Energy', 8, exactly('nrg energy', 'reliant energy', 'direct energy', 'green mountain energy'), 'industry', 'Fortune 500 (2025): #153, $28.1B revenue'],
1474
+ ['Vivint', 8, exactly('vivint', 'vivint smart home'), 'tech', 'NRG Energy\'s: Fortune 500 (2025): #153, $28.1B revenue'],
1475
+ ['Arrow Electronics', 8, exactly('arrow electronics', 'arrow enterprise computing solutions'), 'tech', 'Fortune 500 (2025): #154, $27.9B revenue'],
1476
+ ['Baker Hughes', 8, exactly('baker hughes', 'baker hughes company', 'bhge'), 'industry', 'Fortune 500 (2025): #155, $27.8B revenue'],
1477
+ ['AIG', 8, exactly('aig', 'american international group'), 'finance', 'Fortune 500 (2025): #157, $27.3B revenue'],
1478
+ ['Applied Materials', 8, exactly('applied materials'), 'tech', 'Fortune 500 (2025): #158, $27.2B revenue'],
1479
+ ['Occidental Petroleum', 8, exactly('occidental petroleum', 'occidental oil and gas', 'anadarko petroleum', '1pointfive'), 'industry', 'Fortune 500 (2025): #159, $26.9B revenue'],
1480
+ ['AutoNation', 8, exactly('autonation', 'autonation usa'), 'consumer', 'Fortune 500 (2025): #160, $26.8B revenue'],
1481
+ ['Southern Company', 8, exactly('southern company', 'southern company gas', 'southern company services', 'georgia power', 'georgia power company', 'alabama power', 'alabama power company', 'mississippi power', 'mississippi power company', 'southern nuclear', 'nicor gas'), 'industry', 'Fortune 500 (2025): #161, $26.7B revenue'],
1482
+ ['The Hartford', 8, exactly('hartford financial services group', 'hartford insurance group', 'hartford fire insurance company', 'hartford funds'), 'finance', 'Fortune 500 (2025): #162, $26.5B revenue'],
1483
+ ['Charles Schwab', 8, exactly('charles schwab', 'schwab', 'td ameritrade'), 'finance', 'Fortune 500 (2025): #164, $26.0B revenue'],
1484
+ ['Truist', 8, exactly('truist', 'truist financial', 'truist bank', 'truist securities', 'suntrust', 'suntrust bank', 'bb&t', 'branch banking and trust'), 'finance', 'Fortune 500 (2025): #168, $25.6B revenue'],
1485
+ ['Freeport-McMoRan', 8, exactly('freeport-mcmoran', 'freeport mcmoran', 'freeport-mcmoran copper & gold', 'freeport minerals', 'climax molybdenum'), 'industry', 'Fortune 500 (2025): #169, $25.5B revenue'],
1486
+ ['Micron Technology', 8, exactly('micron technology', 'micron', 'micron semiconductor'), 'tech', 'Fortune 500 (2025): #170, $25.1B revenue'],
1487
+ ['Carrier Global', 8, exactly('carrier global', 'carrier transicold', 'viessmann climate solutions'), 'industry', 'Fortune 500 (2025): #172, $24.8B revenue'],
1488
+ ['NextEra Energy', 8, exactly('nextera energy', 'nextera', 'nextera energy resources', 'florida power & light', 'florida power and light', 'florida power & light company', 'fpl group'), 'industry', 'Fortune 500 (2025): #173, $24.8B revenue'],
1489
+ ['3M', 8, exactly('3m', '3m company', 'minnesota mining and manufacturing'), 'industry', 'Fortune 500 (2025): #174, $24.6B revenue'],
1490
+ ['Marsh McLennan', 8, exactly('marsh mclennan', 'marsh & mclennan companies', 'marsh & mclennan', 'marsh mclennan companies', 'marsh mclennan agency', 'marsh risk', 'marsh re', 'marsh management consulting', 'marsh usa', 'guy carpenter', 'guy carpenter & company'), 'finance', 'Fortune 500 (2025): #175, $24.5B revenue'],
1491
+ ['Oliver Wyman', 8, exactly('oliver wyman'), 'finance', 'Marsh McLennan\'s: Fortune 500 (2025): #175, $24.5B revenue'],
1492
+ ['PG&E', 8, exactly('pg&e', 'pacific gas and electric company', 'pacific gas and electric', 'pacific gas & electric'), 'industry', 'Fortune 500 (2025): #176, $24.4B revenue'],
1493
+ ['Synchrony', 8, exactly('synchrony', 'synchrony financial', 'synchrony bank', 'carecredit'), 'finance', 'Fortune 500 (2025): #178, $24.2B revenue'],
1494
+ ['Danaher', 8, exactly('danaher', 'beckman coulter', 'cepheid', 'cytiva', 'leica biosystems', 'leica microsystems', 'sciex', 'integrated dna technologies', 'aldevron', 'abcam'), 'health', 'Fortune 500 (2025): #180, $23.9B revenue'],
1495
+ ['Booking Holdings', 8, exactly('booking holdings', 'booking.com', 'priceline', 'priceline.com', 'priceline group', 'agoda'), 'tech', 'Fortune 500 (2025): #182, $23.7B revenue'],
1496
+ ['OpenTable', 8, exactly('opentable'), 'tech', 'Booking Holdings\'s: Fortune 500 (2025): #182, $23.7B revenue'],
1497
+ ['EOG Resources', 8, exactly('eog resources', 'eog'), 'industry', 'Fortune 500 (2025): #183, $23.7B revenue'],
1498
+ ['Quanta Services', 8, exactly('quanta services'), 'industry', 'Fortune 500 (2025): #184, $23.7B revenue'],
1499
+ ['Discover Financial', 8, exactly('discover financial', 'discover financial services', 'discover bank', 'discover card'), 'finance', 'Fortune 500 (2025): #185, $23.6B revenue'],
1500
+ ['Constellation Energy', 8, exactly('constellation energy', 'constellation energy generation', 'constellation newenergy', 'constellation nuclear', 'calpine', 'exelon generation', 'exelon nuclear'), 'industry', 'Fortune 500 (2025): #186, $23.6B revenue'],
1501
+ ['Genuine Parts', 8, exactly('genuine parts', 'genuine parts company', 'motion industries'), 'industry', 'Fortune 500 (2025): #187, $23.5B revenue'],
1502
+ ['JLL', 8, exactly('jll', 'jones lang lasalle', 'lasalle investment management'), 'realestate', 'Fortune 500 (2025): #188, $23.4B revenue'],
1503
+ ['Lear', 8, exactly('lear'), 'industry', 'Fortune 500 (2025): #189, $23.3B revenue'],
1504
+ ['Live Nation Entertainment', 8, exactly('live nation entertainment', 'live nation', 'ticketmaster'), 'entertainment', 'Fortune 500 (2025): #190, $23.2B revenue'],
1505
+ ['Sherwin-Williams', 8, exactly('sherwin-williams', 'sherwin williams', 'sherwin-williams company', 'valspar'), 'industry', 'Fortune 500 (2025): #191, $23.1B revenue'],
1506
+ ['Exelon', 8, exactly('exelon', 'exelon utilities', 'comed', 'commonwealth edison', 'commonwealth edison company', 'peco energy', 'peco energy company', 'baltimore gas and electric', 'baltimore gas and electric company', 'baltimore gas & electric', 'pepco holdings', 'potomac electric power company', 'delmarva power', 'delmarva power & light', 'atlantic city electric'), 'industry', 'Fortune 500 (2025): #192, $23.0B revenue'],
1507
+ ['Macy\'s', 8, exactly('macy\'s', 'macys', 'bloomingdale\'s', 'bloomingdales', 'bluemercury'), 'consumer', 'Fortune 500 (2025): #193, $23.0B revenue'],
1508
+ ['Halliburton', 8, exactly('halliburton', 'halliburton company', 'halliburton energy services'), 'industry', 'Fortune 500 (2025): #194, $22.9B revenue'],
1509
+ ['Stryker', 8, exactly('stryker', 'inari medical', 'vocera'), 'health', 'Fortune 500 (2025): #195, $22.6B revenue'],
1510
+ ['Waste Management', 8, exactly('waste management', 'wm healthcare solutions', 'stericycle'), 'industry', 'Fortune 500 (2025): #197, $22.1B revenue'],
1511
+ ['State Street', 8, exactly('state street', 'state street bank and trust company', 'state street bank', 'state street global advisors', 'state street investment management', 'ssga'), 'finance', 'Fortune 500 (2025): #198, $22.1B revenue'],
1512
+ ['WESCO International', 8, exactly('wesco international', 'wesco distribution', 'anixter'), 'industry', 'Fortune 500 (2025): #199, $21.8B revenue'],
1513
+ ['ONEOK', 8, exactly('oneok', 'magellan midstream partners', 'magellan midstream', 'enlink midstream'), 'industry', 'Fortune 500 (2025): #200, $21.7B revenue'],
1514
+ ['Ross Stores', 8, exactly('ross stores', 'ross dress for less', 'dd\'s discounts', 'dds discounts'), 'consumer', 'Fortune 500 (2025): #204, $21.1B revenue'],
1515
+ ['Tenet Healthcare', 8, exactly('tenet healthcare', 'tenet health', 'united surgical partners international'), 'health', 'Fortune 500 (2025): #206, $20.7B revenue'],
1516
+ ['BJ\'s Wholesale Club', 8, exactly('bj\'s wholesale club', 'bjs wholesale club', 'bj\'s wholesale club holdings', 'bj\'s wholesale', 'bjs wholesale'), 'consumer', 'Fortune 500 (2025): #207, $20.5B revenue'],
1517
+ ['Fiserv', 8, exactly('fiserv', 'first data'), 'finance', 'Fortune 500 (2025): #208, $20.5B revenue'],
1518
+ ['Altria', 8, exactly('altria', 'altria group', 'philip morris usa', 'njoy'), 'consumer', 'Fortune 500 (2025): #209, $20.4B revenue'],
1519
+ ['Becton Dickinson', 8, exactly('becton dickinson', 'becton dickinson and company', 'becton'), 'health', 'Fortune 500 (2025): #211, $20.2B revenue'],
1520
+ ['Colgate-Palmolive', 8, exactly('colgate-palmolive', 'colgate palmolive', 'colgate-palmolive company', 'hill\'s pet nutrition', 'hills pet nutrition', 'tom\'s of maine'), 'consumer', 'Fortune 500 (2025): #212, $20.1B revenue'],
1521
+ ['Kimberly-Clark', 8, exactly('kimberly-clark', 'kimberly clark', 'kimberly-clark professional'), 'consumer', 'Fortune 500 (2025): #213, $20.1B revenue'],
1522
+ ['Parker Hannifin', 8, exactly('parker hannifin', 'parker-hannifin', 'parker aerospace'), 'industry', 'Fortune 500 (2025): #215, $19.9B revenue'],
1523
+ ['Cognizant', 8, exactly('cognizant', 'cognizant technology solutions'), 'consulting', 'Fortune 500 (2025): #217, $19.7B revenue'],
1524
+ ['American Electric Power', 8, exactly('american electric power', 'aep', 'aep ohio', 'aep texas', 'appalachian power', 'indiana michigan power', 'swepco', 'public service company of oklahoma'), 'industry', 'Fortune 500 (2025): #218, $19.7B revenue'],
1525
+ ['GE HealthCare', 8, exactly('ge healthcare', 'ge healthcare technologies', 'ge health care'), 'health', 'Fortune 500 (2025): #219, $19.7B revenue'],
1526
+ ['ADP', 8, exactly('adp', 'automatic data processing', 'adp totalsource'), 'tech', 'Fortune 500 (2025): #220, $19.2B revenue'],
1527
+ ['Cleveland-Cliffs', 8, exactly('cleveland-cliffs', 'cleveland cliffs', 'ak steel', 'stelco'), 'industry', 'Fortune 500 (2025): #221, $19.2B revenue'],
1528
+ ['Aflac', 8, exactly('aflac', 'aflac japan'), 'finance', 'Fortune 500 (2025): #222, $18.9B revenue'],
1529
+ ['Newmont', 8, exactly('newmont', 'newmont mining'), 'industry', 'Fortune 500 (2025): #225, $18.7B revenue'],
1530
+ ['International Paper', 8, exactly('international paper', 'international paper company', 'ds smith'), 'industry', 'Fortune 500 (2025): #226, $18.6B revenue'],
1531
+ ['AutoZone', 8, exactly('autozone', 'auto zone'), 'consumer', 'Fortune 500 (2025): #227, $18.5B revenue'],
1532
+ ['PulteGroup', 8, exactly('pultegroup', 'pulte group', 'pulte homes', 'pulte mortgage'), 'realestate', 'Fortune 500 (2025): #229, $17.9B revenue'],
1533
+ ['Ameriprise Financial', 8, exactly('ameriprise financial', 'ameriprise', 'ameriprise financial services', 'columbia threadneedle investments', 'columbia threadneedle'), 'finance', 'Fortune 500 (2025): #230, $17.9B revenue'],
1534
+ ['ManpowerGroup', 8, exactly('manpowergroup', 'manpower group', 'experis'), 'consulting', 'Fortune 500 (2025): #232, $17.9B revenue'],
1535
+ ['PPG', 8, exactly('ppg', 'ppg industries', 'ppg aerospace'), 'industry', 'Fortune 500 (2025): #234, $17.7B revenue'],
1536
+ ['Steel Dynamics', 8, exactly('steel dynamics', 'omnisource'), 'industry', 'Fortune 500 (2025): #236, $17.5B revenue'],
1537
+ ['Loews', 8, exactly('loews', 'boardwalk pipelines'), 'finance', 'Fortune 500 (2025): #237, $17.5B revenue'],
1538
+ ['Loews Hotels', 8, exactly('loews hotels', 'loews hotels &'), 'finance', 'Loews\'s: Fortune 500 (2025): #237, $17.5B revenue'],
1539
+ ['Emerson Electric', 8, exactly('emerson electric', 'emerson automation solutions', 'emerson process management', 'aspentech', 'national instruments'), 'industry', 'Fortune 500 (2025): #238, $17.5B revenue'],
1540
+ ['Aramark', 8, exactly('aramark'), 'consumer', 'Fortune 500 (2025): #239, $17.4B revenue'],
1541
+ ['MGM Resorts', 8, exactly('mgm resorts', 'mgm resorts international', 'mgm grand', 'bellagio', 'mandalay bay', 'aria resort & casino', 'mgm national harbor', 'borgata'), 'entertainment', 'Fortune 500 (2025): #240, $17.2B revenue'],
1542
+ ['Vistra Energy', 8, exactly('vistra energy', 'luminant', 'txu energy'), 'industry', 'Fortune 500 (2025): #241, $17.2B revenue'],
1543
+ ['W.W. Grainger', 8, exactly('w.w. grainger', 'ww grainger', 'w. w. grainger', 'grainger industrial supply'), 'industry', 'Fortune 500 (2025): #243, $17.2B revenue'],
1544
+ ['Jacobs Solutions', 8, exactly('jacobs solutions'), 'industry', 'Fortune 500 (2025): #245, $17.0B revenue'],
1545
+ ['Jacobs Engineering', 8, exactly('jacobs engineering', 'jacobs engineering group'), 'industry', 'Jacobs Solutions\'s: Fortune 500 (2025): #245, $17.0B revenue'],
1546
+ ['Kiewit', 8, exactly('kiewit', 'peter kiewit sons', 'kiewit infrastructure', 'kiewit power constructors', 'kiewit building group', 'kiewit engineering group'), 'industry', 'Fortune 500 (2025): #247, $16.8B revenue'],
1547
+ ['Boston Scientific', 8, exactly('boston scientific'), 'health', 'Fortune 500 (2025): #248, $16.7B revenue'],
1548
+ ['O\'Reilly Auto Parts', 8, exactly('o\'reilly auto parts', 'oreilly auto parts', 'o\'reilly automotive', 'oreilly automotive'), 'consumer', 'Fortune 500 (2025): #249, $16.7B revenue'],
1549
+ ['Markel', 8, exactly('markel', 'markel group', 'markel specialty', 'markel ventures'), 'finance', 'Fortune 500 (2025): #251, $16.6B revenue'],
1550
+ ['Whirlpool', 8, exactly('whirlpool'), 'industry', 'Fortune 500 (2025): #252, $16.6B revenue'],
1551
+ ['Builders FirstSource', 8, exactly('builders firstsource', 'builders first source'), 'industry', 'Fortune 500 (2025): #254, $16.4B revenue'],
1552
+ ['Targa Resources', 8, exactly('targa resources', 'targa resources partners', 'targa'), 'industry', 'Fortune 500 (2025): #256, $16.4B revenue'],
1553
+ ['Fluor', 8, exactly('fluor'), 'industry', 'Fortune 500 (2025): #257, $16.3B revenue'],
1554
+ ['AECOM', 8, exactly('aecom', 'aecom tishman'), 'industry', 'Fortune 500 (2025): #259, $16.3B revenue'],
1555
+ ['Edward Jones', 8, exactly('edward jones', 'edward jones investments', 'jones financial companies'), 'finance', 'Fortune 500 (2025): #260, $16.3B revenue'],
1556
+ ['Kohl\'s', 8, exactly('kohl\'s', 'kohls'), 'consumer', 'Fortune 500 (2025): #261, $16.2B revenue'],
1557
+ ['Principal Financial Group', 8, exactly('principal financial group', 'principal financial', 'principal global investors', 'principal asset management'), 'finance', 'Fortune 500 (2025): #263, $16.1B revenue'],
1558
+ ['Dominion Energy', 8, exactly('dominion energy', 'dominion energy virginia', 'dominion energy south carolina'), 'industry', 'Fortune 500 (2025): #264, $16.1B revenue'],
1559
+ ['Kyndryl', 8, exactly('kyndryl', 'kyndryl holdings'), 'tech', 'Fortune 500 (2025): #265, $16.1B revenue'],
1560
+ ['Republic Services', 8, exactly('republic services'), 'industry', 'Fortune 500 (2025): #266, $16.0B revenue'],
1561
+ ['Devon Energy', 8, exactly('devon energy', 'coterra energy', 'coterra'), 'industry', 'Fortune 500 (2025): #267, $15.9B revenue'],
1562
+ ['Illinois Tool Works', 8, exactly('illinois tool works', 'itw'), 'industry', 'Fortune 500 (2025): #268, $15.9B revenue'],
1563
+ ['Northern Trust', 8, exactly('northern trust', 'northern trust company', 'northern trust asset management'), 'finance', 'Fortune 500 (2025): #269, $15.9B revenue'],
1564
+ ['Universal Health Services', 8, exactly('universal health services'), 'health', 'Fortune 500 (2025): #271, $15.8B revenue'],
1565
+ ['EchoStar', 8, exactly('echostar', 'hughes network systems'), 'tech', 'Fortune 500 (2025): #273, $15.8B revenue'],
1566
+ ['Ecolab', 8, exactly('ecolab', 'nalco water'), 'industry', 'Fortune 500 (2025): #274, $15.7B revenue'],
1567
+ ['Cheniere Energy', 8, exactly('cheniere energy', 'cheniere', 'cheniere energy partners'), 'industry', 'Fortune 500 (2025): #275, $15.7B revenue'],
1568
+ ['Texas Instruments', 8, exactly('texas instruments'), 'tech', 'Fortune 500 (2025): #277, $15.6B revenue'],
1569
+ ['U.S. Steel', 8, exactly('u.s. steel', 'united states steel', 'us steel', 'big river steel'), 'industry', 'Fortune 500 (2025): #278, $15.6B revenue'],
1570
+ ['Estée Lauder', 8, exactly('estée lauder', 'estee lauder', 'estée lauder companies', 'estee lauder companies', 'mac cosmetics'), 'consumer', 'Fortune 500 (2025): #279, $15.6B revenue'],
1571
+ ['Kenvue', 8, exactly('kenvue'), 'consumer', 'Fortune 500 (2025): #281, $15.5B revenue'],
1572
+ ['IQVIA', 8, exactly('iqvia', 'iqvia holdings', 'quintiles', 'quintilesims', 'ims health'), 'health', 'Fortune 500 (2025): #282, $15.4B revenue'],
1573
+ ['Stanley Black & Decker', 8, exactly('stanley black & decker', 'stanley black and decker', 'black & decker', 'black and decker', 'dewalt'), 'industry', 'Fortune 500 (2025): #283, $15.4B revenue'],
1574
+ ['Keurig Dr Pepper', 8, exactly('keurig dr pepper', 'keurig', 'keurig green mountain', 'dr pepper snapple group', 'dr pepper'), 'consumer', 'Fortune 500 (2025): #284, $15.4B revenue'],
1575
+ ['United Rentals', 8, exactly('united rentals'), 'industry', 'Fortune 500 (2025): #285, $15.3B revenue'],
1576
+ ['Con Edison', 8, exactly('con edison', 'consolidated edison', 'con ed', 'coned', 'orange and rockland utilities', 'orange & rockland'), 'industry', 'Fortune 500 (2025): #286, $15.3B revenue'],
1577
+ ['Amphenol', 8, exactly('amphenol'), 'tech', 'Fortune 500 (2025): #287, $15.2B revenue'],
1578
+ ['Baxter International', 8, exactly('baxter international', 'baxter healthcare'), 'health', 'Fortune 500 (2025): #288, $15.1B revenue'],
1579
+ ['Kinder Morgan', 8, exactly('kinder morgan'), 'industry', 'Fortune 500 (2025): #289, $15.1B revenue'],
1580
+ ['Nordstrom', 8, exactly('nordstrom', 'nordstrom rack'), 'consumer', 'Fortune 500 (2025): #291, $15.0B revenue'],
1581
+ ['Supermicro', 8, exactly('supermicro', 'super micro computer', 'super micro'), 'tech', 'Fortune 500 (2025): #292, $15.0B revenue'],
1582
+ ['First Citizens BancShares', 8, exactly('first citizens bancshares', 'first-citizens bank & trust', 'first citizens bank & trust', 'first citizens bank and trust', 'silicon valley bank', 'cit bank'), 'finance', 'Fortune 500 (2025): #293, $15.0B revenue'],
1583
+ ['Lam Research', 8, exactly('lam research'), 'tech', 'Fortune 500 (2025): #295, $14.9B revenue'],
1584
+ ['Tractor Supply', 8, exactly('tractor supply', 'tractor supply company', 'petsense'), 'consumer', 'Fortune 500 (2025): #296, $14.9B revenue'],
1585
+ ['Casey\'s General Stores', 8, exactly('casey\'s general stores', 'caseys general stores', 'casey\'s general store'), 'consumer', 'Fortune 500 (2025): #297, $14.9B revenue'],
1586
+ ['Viatris', 8, exactly('viatris', 'mylan', 'mylan pharmaceuticals'), 'health', 'Fortune 500 (2025): #298, $14.7B revenue'],
1587
+ ['EMCOR', 8, exactly('emcor', 'emcor group', 'emcor services'), 'industry', 'Fortune 500 (2025): #300, $14.6B revenue'],
1588
+ ['CSX', 8, exactly('csx', 'csx transportation', 'csxt', 'csx intermodal terminals'), 'industry', 'Fortune 500 (2025): #301, $14.5B revenue'],
1589
+ ['LKQ', 8, exactly('lkq', 'lkq europe', 'lkq pick your part', 'euro car parts'), 'industry', 'Fortune 500 (2025): #302, $14.4B revenue'],
1590
+ ['Otis Worldwide', 8, exactly('otis worldwide', 'otis elevator company', 'otis elevator', 'otis elevators'), 'industry', 'Fortune 500 (2025): #303, $14.3B revenue'],
1591
+ ['S&P Global', 8, exactly('s&p global', 'standard & poor\'s', 'standard and poor\'s', 's&p global ratings', 's&p global market intelligence', 's&p global commodity insights', 's&p dow jones indices', 'platts', 'mcgraw hill financial'), 'finance', 'Fortune 500 (2025): #305, $14.2B revenue'],
1592
+ ['Regeneron', 8, exactly('regeneron', 'regeneron pharmaceuticals', 'regeneron genetics center'), 'health', 'Fortune 500 (2025): #306, $14.2B revenue'],
1593
+ ['BorgWarner', 8, exactly('borgwarner', 'borg warner', 'borg-warner'), 'industry', 'Fortune 500 (2025): #307, $14.1B revenue'],
1594
+ ['Textron', 8, exactly('textron', 'textron aviation', 'textron systems', 'bell textron', 'bell helicopter', 'bell flight', 'cessna', 'beechcraft', 'textron specialized vehicles', 'textron eaviation'), 'defense', 'Fortune 500 (2025): #311, $13.7B revenue'],
1595
+ ['Expedia Group', 8, exactly('expedia group', 'expedia', 'vrbo', 'homeaway', 'hotels.com', 'orbitz', 'travelocity'), 'tech', 'Fortune 500 (2025): #312, $13.7B revenue'],
1596
+ ['Fidelity National Financial', 8, exactly('fidelity national financial', 'fnf', 'fidelity national title group', 'fidelity national title', 'chicago title', 'chicago title insurance company', 'commonwealth land title', 'ticor title', 'alamo title'), 'finance', 'Fortune 500 (2025): #313, $13.7B revenue'],
1597
+ ['Carvana', 8, exactly('carvana'), 'consumer', 'Fortune 500 (2025): #314, $13.7B revenue'],
1598
+ ['DXC Technology', 8, exactly('dxc technology', 'dxc technology company', 'dxc', 'luxoft'), 'tech', 'Fortune 500 (2025): #315, $13.7B revenue'],
1599
+ ['W. R. Berkley', 8, exactly('w. r. berkley', 'w.r. berkley', 'wr berkley'), 'finance', 'Fortune 500 (2025): #316, $13.6B revenue'],
1600
+ ['M&T Bank', 8, exactly('m&t bank', 'm & t bank', 'm&t', 'manufacturers and traders trust company', 'wilmington trust'), 'finance', 'Fortune 500 (2025): #317, $13.5B revenue'],
1601
+ ['Dick\'s Sporting Goods', 8, exactly('dick\'s sporting goods', 'dicks sporting goods', 'dick\'s house of sport', 'golf galaxy'), 'consumer', 'Fortune 500 (2025): #318, $13.4B revenue'],
1602
+ ['Xcel Energy', 8, exactly('xcel energy', 'northern states power company', 'public service company of colorado', 'southwestern public service company'), 'industry', 'Fortune 500 (2025): #319, $13.4B revenue'],
1603
+ ['Fifth Third', 8, exactly('fifth third', 'fifth third bancorp', 'fifth third bank', 'fifth third securities', 'comerica bank', 'comerica'), 'finance', 'Fortune 500 (2025): #320, $13.3B revenue'],
1604
+ ['Sempra', 8, exactly('sempra', 'sempra energy', 'san diego gas & electric', 'sdg&e', 'southern california gas company', 'socalgas', 'southern california gas'), 'industry', 'Fortune 500 (2025): #322, $13.2B revenue'],
1605
+ ['Corning', 8, exactly('corning', 'corning optical communications', 'corning life sciences'), 'industry', 'Fortune 500 (2025): #324, $13.1B revenue'],
1606
+ ['Lumen Technologies', 8, exactly('lumen technologies', 'centurylink', 'century link'), 'tech', 'Fortune 500 (2025): #325, $13.1B revenue'],
1607
+ ['FirstEnergy', 8, exactly('firstenergy', 'first energy', 'jersey central power & light', 'jcp&l', 'ohio edison', 'met-ed', 'penelec', 'potomac edison', 'mon power', 'west penn power', 'toledo edison'), 'industry', 'Fortune 500 (2025): #326, $13.0B revenue'],
1608
+ ['Hess', 8, exactly('hess'), 'industry', 'Fortune 500 (2025): #327, $13.0B revenue'],
1609
+ ['Labcorp', 8, exactly('labcorp', 'labcorp holdings', 'laboratory corporation of america', 'laboratory corporation of america holdings', 'labcorp diagnostics'), 'health', 'Fortune 500 (2025): #328, $13.0B revenue'],
1610
+ ['Western Digital', 8, exactly('western digital', 'western digital technologies'), 'tech', 'Fortune 500 (2025): #329, $13.0B revenue'],
1611
+ ['DaVita', 8, exactly('davita', 'davita kidney care', 'davita healthcare partners'), 'health', 'Fortune 500 (2025): #331, $12.8B revenue'],
1612
+ ['Henry Schein', 8, exactly('henry schein', 'henry schein dental', 'henry schein medical', 'henry schein one'), 'health', 'Fortune 500 (2025): #333, $12.7B revenue'],
1613
+ ['Ryder System', 8, exactly('ryder system', 'ryder truck rental', 'ryder fleet management solutions', 'ryder supply chain solutions', 'ryder last mile'), 'industry', 'Fortune 500 (2025): #334, $12.6B revenue'],
1614
+ ['Community Health Systems', 8, exactly('community health systems', 'chspsc'), 'health', 'Fortune 500 (2025): #335, $12.6B revenue'],
1615
+ ['DTE Energy', 8, exactly('dte energy', 'dte energy company', 'dte electric', 'dte gas', 'detroit edison', 'michcon'), 'industry', 'Fortune 500 (2025): #337, $12.5B revenue'],
1616
+ ['LPL Financial', 8, exactly('lpl financial', 'lpl financial holdings', 'lpl', 'linsco private ledger'), 'finance', 'Fortune 500 (2025): #340, $12.4B revenue'],
1617
+ ['Citizens Financial Group', 8, exactly('citizens financial group', 'citizens jmp'), 'finance', 'Fortune 500 (2025): #341, $12.4B revenue'],
1618
+ ['MasTec', 8, exactly('mastec', 'mastec north america', 'mastec network solutions', 'mastec clean energy & infrastructure', 'mastec power delivery'), 'industry', 'Fortune 500 (2025): #342, $12.3B revenue'],
1619
+ ['Berry Global', 8, exactly('berry global', 'berry global group', 'berry plastics'), 'industry', 'Fortune 500 (2025): #344, $12.3B revenue'],
1620
+ ['Norfolk Southern', 8, exactly('norfolk southern', 'norfolk southern railway'), 'industry', 'Fortune 500 (2025): #346, $12.1B revenue'],
1621
+ ['Air Products', 8, exactly('air products', 'air products and chemicals', 'air products & chemicals'), 'industry', 'Fortune 500 (2025): #347, $12.1B revenue'],
1622
+ ['J.B. Hunt', 8, exactly('j.b. hunt', 'j.b. hunt transport services', 'j.b. hunt transport', 'jb hunt', 'j. b. hunt', 'jb hunt transport services', 'jbhunt'), 'industry', 'Fortune 500 (2025): #348, $12.1B revenue'],
1623
+ ['Huntington Bancshares', 8, exactly('huntington bancshares', 'huntington national bank', 'huntington bank'), 'finance', 'Fortune 500 (2025): #351, $12.0B revenue'],
1624
+ ['Eversource', 8, exactly('eversource', 'eversource energy', 'northeast utilities', 'nstar', 'connecticut light & power', 'public service of new hampshire'), 'industry', 'Fortune 500 (2025): #353, $11.9B revenue'],
1625
+ ['Entergy', 8, exactly('entergy', 'entergy louisiana', 'entergy arkansas', 'entergy texas', 'entergy mississippi', 'entergy new orleans'), 'industry', 'Fortune 500 (2025): #355, $11.9B revenue'],
1626
+ ['Crown Holdings', 8, exactly('crown holdings', 'crown cork & seal', 'crown cork and seal', 'crown cork & seal company'), 'industry', 'Fortune 500 (2025): #359, $11.8B revenue'],
1627
+ ['Avis Budget Group', 8, exactly('avis budget group', 'avis budget', 'avis car rental', 'avis rent a car', 'budget rent a car', 'budget car rental', 'zipcar'), 'consumer', 'Fortune 500 (2025): #360, $11.8B revenue'],
1628
+ ['Intercontinental Exchange', 8, exactly('intercontinental exchange', 'new york stock exchange', 'nyse', 'ice mortgage technology', 'ice futures', 'ice data services', 'ice clear'), 'finance', 'Fortune 500 (2025): #361, $11.8B revenue'],
1629
+ ['Alaska Air Group', 8, exactly('alaska air group', 'alaska air', 'horizon air'), 'consumer', 'Fortune 500 (2025): #362, $11.7B revenue'],
1630
+ ['Alaska Airlines', 8, exactly('alaska airlines'), 'consumer', 'Alaska Air Group\'s: Fortune 500 (2025): #362, $11.7B revenue'],
1631
+ ['Hawaiian Airlines', 8, exactly('hawaiian airlines'), 'consumer', 'Alaska Air Group\'s: Fortune 500 (2025): #362, $11.7B revenue'],
1632
+ ['GXO Logistics', 8, exactly('gxo logistics', 'gxo', 'wincanton', 'clipper logistics'), 'industry', 'Fortune 500 (2025): #363, $11.7B revenue'],
1633
+ ['AGCO', 8, exactly('agco', 'massey ferguson', 'valtra', 'precision planting'), 'industry', 'Fortune 500 (2025): #364, $11.7B revenue'],
1634
+ ['Arthur J. Gallagher', 8, exactly('arthur j. gallagher', 'arthur j. gallagher &', 'arthur j gallagher', 'ajg', 'gallagher re', 'gallagher bassett', 'gallagher benefit services'), 'finance', 'Fortune 500 (2025): #367, $11.6B revenue'],
1635
+ ['Huntington Ingalls Industries', 8, exactly('huntington ingalls industries', 'huntington ingalls', 'hii', 'newport news shipbuilding', 'ingalls shipbuilding', 'hii mission technologies'), 'defense', 'Fortune 500 (2025): #368, $11.5B revenue'],
1636
+ ['International Flavors & Fragrances', 8, exactly('international flavors & fragrances', 'international flavors and fragrances'), 'industry', 'Fortune 500 (2025): #369, $11.5B revenue'],
1637
+ ['Darden Restaurants', 8, exactly('darden restaurants', 'olive garden', 'longhorn steakhouse', 'capital grille', 'yard house', 'cheddar\'s scratch kitchen'), 'consumer', 'Fortune 500 (2025): #370, $11.4B revenue'],
1638
+ ['Cincinnati Financial', 8, exactly('cincinnati financial', 'cincinnati insurance companies', 'cincinnati insurance company', 'cincinnati insurance'), 'finance', 'Fortune 500 (2025): #371, $11.3B revenue'],
1639
+ ['Yum China', 8, exactly('yum china', 'yum china holdings', 'kfc china', 'pizza hut china'), 'consumer', 'Fortune 500 (2025): #373, $11.3B revenue'],
1640
+ ['Las Vegas Sands', 8, exactly('las vegas sands', 'sands china', 'marina bay sands', 'venetian macao'), 'entertainment', 'Fortune 500 (2025): #374, $11.3B revenue'],
1641
+ ['Ulta Beauty', 8, exactly('ulta beauty', 'ulta', 'ulta salon'), 'consumer', 'Fortune 500 (2025): #375, $11.3B revenue'],
1642
+ ['Caesars Entertainment', 8, exactly('caesars entertainment', 'caesars', 'caesars palace', 'caesars sportsbook', 'eldorado resorts'), 'entertainment', 'Fortune 500 (2025): #376, $11.3B revenue'],
1643
+ ['BrightSpring Health Services', 8, exactly('brightspring health services', 'brightspring', 'brightspring health', 'pharmerica'), 'health', 'Fortune 500 (2025): #377, $11.3B revenue'],
1644
+ ['The Hershey Company', 8, exactly('hershey company', 'hershey\'s', 'hershey foods'), 'consumer', 'Fortune 500 (2025): #379, $11.2B revenue'],
1645
+ ['Diamondback Energy', 8, exactly('diamondback energy'), 'industry', 'Fortune 500 (2025): #383, $11.1B revenue'],
1646
+ ['American Tower', 8, exactly('american tower', 'coresite'), 'realestate', 'Fortune 500 (2025): #384, $11.0B revenue'],
1647
+ ['Vertex Pharmaceuticals', 8, exactly('vertex pharmaceuticals', 'vertex pharma'), 'health', 'Fortune 500 (2025): #385, $11.0B revenue'],
1648
+ ['Owens Corning', 8, exactly('owens corning', 'owens-corning', 'owens corning fiberglas'), 'industry', 'Fortune 500 (2025): #387, $11.0B revenue'],
1649
+ ['Advance Auto Parts', 8, exactly('advance auto parts', 'advance auto', 'advance stores company'), 'consumer', 'Fortune 500 (2025): #389, $10.9B revenue'],
1650
+ ['Mohawk Industries', 8, exactly('mohawk industries', 'mohawk flooring', 'mohawk home', 'daltile', 'dal-tile', 'unilin', 'pergo'), 'industry', 'Fortune 500 (2025): #391, $10.8B revenue'],
1651
+ ['Motorola Solutions', 8, exactly('motorola solutions', 'avigilon', 'silvus technologies'), 'tech', 'Fortune 500 (2025): #392, $10.8B revenue'],
1652
+ ['Burlington Stores', 8, exactly('burlington stores', 'burlington coat factory', 'burlington coat factory warehouse'), 'consumer', 'Fortune 500 (2025): #399, $10.6B revenue'],
1653
+ ['Expeditors International', 8, exactly('expeditors international', 'expeditors international of washington', 'expeditors intl'), 'industry', 'Fortune 500 (2025): #400, $10.6B revenue'],
1654
+ ['Lululemon', 8, exactly('lululemon', 'lululemon athletica'), 'consumer', 'Fortune 500 (2025): #401, $10.59B revenue'],
1655
+ ['FIS', 8, exactly('fis', 'fidelity national information services', 'fis global', 'tsys', 'total system services'), 'finance', 'Fortune 500 (2025): #402, $10.54B revenue'],
1656
+ ['The Williams Companies', 8, exactly('williams companies'), 'industry', 'Fortune 500 (2025): #404, $10.50B revenue'],
1657
+ ['Autoliv', 8, exactly('autoliv'), 'industry', 'Fortune 500 (2025): #407, $10.39B revenue'],
1658
+ ['Wabtec', 8, exactly('wabtec', 'westinghouse air brake technologies', 'ge transportation'), 'industry', 'Fortune 500 (2025): #408, $10.39B revenue'],
1659
+ ['PSEG', 8, exactly('pseg', 'public service enterprise group', 'pse&g', 'public service electric and gas company', 'public service electric and gas', 'pseg long island', 'pseg nuclear'), 'industry', 'Fortune 500 (2025): #409, $10.29B revenue'],
1660
+ ['eBay', 8, exactly('ebay'), 'tech', 'Fortune 500 (2025): #411, $10.28B revenue'],
1661
+ ['Global Payments', 8, exactly('global payments', 'worldpay', 'heartland payment systems'), 'finance', 'Fortune 500 (2025): #413, $10.11B revenue'],
1662
+ ['NewsCorp', 8, exactly('newscorp', 'new york post', 'news uk', 'news corp australia'), 'media', 'Fortune 500 (2025): #414, $10.09B revenue'],
1663
+ ['Dow Jones', 8, exactly('dow jones', 'dow jones & company'), 'media', 'NewsCorp\'s: Fortune 500 (2025): #414, $10.09B revenue'],
1664
+ ['The Wall Street Journal', 8, exactly('wall street journal', 'wsj'), 'media', 'NewsCorp\'s: Fortune 500 (2025): #414, $10.09B revenue'],
1665
+ ['HarperCollins', 8, exactly('harpercollins', 'harpercollins publishers'), 'media', 'NewsCorp\'s: Fortune 500 (2025): #414, $10.09B revenue'],
1666
+ ['Thor Industries', 8, exactly('thor industries', 'jayco', 'keystone rv', 'thor motor coach', 'tiffin motorhomes'), 'industry', 'Fortune 500 (2025): #415, $10.04B revenue'],
1667
+ ['Constellation Brands', 8, exactly('constellation brands'), 'consumer', 'Fortune 500 (2025): #418, $9.96B revenue'],
1668
+ ['Quest Diagnostics', 8, exactly('quest diagnostics'), 'health', 'Fortune 500 (2025): #419, $9.87B revenue'],
1669
+ ['KLA', 8, exactly('kla', 'kla-tencor', 'kla tencor'), 'tech', 'Fortune 500 (2025): #420, $9.81B revenue'],
1670
+ ['Biogen', 8, exactly('biogen', 'biogen idec'), 'health', 'Fortune 500 (2025): #424, $9.68B revenue'],
1671
+ ['Concentrix', 8, exactly('concentrix', 'webhelp', 'convergys'), 'consulting', 'Fortune 500 (2025): #426, $9.62B revenue'],
1672
+ ['Cintas', 8, exactly('cintas'), 'industry', 'Fortune 500 (2025): #427, $9.60B revenue'],
1673
+ ['Analog Devices', 8, exactly('analog devices', 'maxim integrated', 'linear technology'), 'tech', 'Fortune 500 (2025): #430, $9.43B revenue'],
1674
+ ['Interactive Brokers', 8, exactly('interactive brokers', 'interactive brokers group', 'ibkr'), 'finance', 'Fortune 500 (2025): #432, $9.38B revenue'],
1675
+ ['Regions Financial', 8, exactly('regions financial', 'regions bank'), 'finance', 'Fortune 500 (2025): #433, $9.37B revenue'],
1676
+ ['Zoetis', 8, exactly('zoetis'), 'health', 'Fortune 500 (2025): #435, $9.26B revenue'],
1677
+ ['Hertz', 8, exactly('hertz', 'hertz global holdings', 'dollar thrifty automotive group', 'thrifty car rental', 'dollar rent a car'), 'consumer', 'Fortune 500 (2025): #440, $9.05B revenue'],
1678
+ ['NOV', 8, exactly('nov', 'national oilwell varco'), 'industry', 'Fortune 500 (2025): #443, $8.87B revenue'],
1679
+ ['Graphic Packaging', 8, exactly('graphic packaging', 'graphic packaging holding company', 'graphic packaging international'), 'industry', 'Fortune 500 (2025): #444, $8.81B revenue'],
1680
+ ['Avery Dennison', 8, exactly('avery dennison'), 'industry', 'Fortune 500 (2025): #445, $8.76B revenue'],
1681
+ ['Equinix', 8, exactly('equinix'), 'tech', 'Fortune 500 (2025): #446, $8.75B revenue'],
1682
+ ['PVH', 8, exactly('pvh', 'phillips-van heusen'), 'consumer', 'Fortune 500 (2025): #449, $8.65B revenue'],
1683
+ ['CenterPoint Energy', 8, exactly('centerpoint energy'), 'industry', 'Fortune 500 (2025): #450, $8.64B revenue'],
1684
+ ['WEC Energy Group', 8, exactly('wec energy group', 'we energies', 'wisconsin public service', 'wisconsin electric power company'), 'industry', 'Fortune 500 (2025): #451, $8.60B revenue'],
1685
+ ['Xylem', 8, exactly('xylem', 'evoqua water technologies', 'evoqua'), 'industry', 'Fortune 500 (2025): #452, $8.56B revenue'],
1686
+ ['PPL', 8, exactly('ppl', 'ppl electric utilities', 'lg&e and ku energy', 'lg&e', 'louisville gas and electric company', 'kentucky utilities', 'rhode island energy'), 'industry', 'Fortune 500 (2025): #454, $8.46B revenue'],
1687
+ ['ABM Industries', 8, exactly('abm industries'), 'industry', 'Fortune 500 (2025): #458, $8.36B revenue'],
1688
+ ['Intuitive Surgical', 8, exactly('intuitive surgical'), 'health', 'Fortune 500 (2025): #459, $8.35B revenue'],
1689
+ ['Rockwell Automation', 8, exactly('rockwell automation'), 'industry', 'Fortune 500 (2025): #461, $8.26B revenue'],
1690
+ ['Solventum', 8, exactly('solventum'), 'health', 'Fortune 500 (2025): #462, $8.25B revenue'],
1691
+ ['Prologis', 8, exactly('prologis'), 'realestate', 'Fortune 500 (2025): #465, $8.20B revenue'],
1692
+ ['XPO', 8, exactly('xpo', 'xpo logistics'), 'industry', 'Fortune 500 (2025): #468, $8.07B revenue'],
1693
+ ['Palo Alto Networks', 8, exactly('palo alto networks', 'cyberark', 'cyberark software'), 'tech', 'Fortune 500 (2025): #470, $8.03B revenue'],
1694
+ ['Vertiv', 8, exactly('vertiv', 'vertiv holdings'), 'industry', 'Fortune 500 (2025): #471, $8.01B revenue'],
1695
+ ['Welltower', 8, exactly('welltower'), 'realestate', 'Fortune 500 (2025): #472, $7.99B revenue'],
1696
+ ['Foot Locker', 8, exactly('foot locker', 'footlocker', 'champs sports', 'kids foot locker'), 'consumer', 'Fortune 500 (2025): #473, $7.99B revenue'],
1697
+ ['TransDigm', 8, exactly('transdigm', 'transdigm group'), 'defense', 'Fortune 500 (2025): #475, $7.94B revenue'],
1698
+ ['KBR', 8, exactly('kbr', 'kellogg brown & root', 'kellogg brown and root'), 'defense', 'Fortune 500 (2025): #480, $7.74B revenue'],
1699
+ ['Sprouts Farmers Market', 8, exactly('sprouts farmers market', 'sprouts farmers markets'), 'consumer', 'Fortune 500 (2025): #481, $7.72B revenue'],
1700
+ ['Williams-Sonoma', 8, exactly('williams-sonoma', 'williams sonoma', 'pottery barn', 'pottery barn kids', 'west elm', 'pbteen'), 'consumer', 'Fortune 500 (2025): #482, $7.71B revenue'],
1701
+ ['CACI', 8, exactly('caci', 'caci international'), 'defense', 'Fortune 500 (2025): #484, $7.66B revenue'],
1702
+ ['Microchip Technology', 8, exactly('microchip technology', 'microsemi', 'atmel'), 'tech', 'Fortune 500 (2025): #485, $7.63B revenue'],
1703
+ ['Newell Brands', 8, exactly('newell brands', 'newell rubbermaid', 'rubbermaid', 'rubbermaid commercial products', 'yankee candle', 'yankee candle company'), 'consumer', 'Fortune 500 (2025): #487, $7.58B revenue'],
1704
+ ['Sanmina', 8, exactly('sanmina', 'sanmina-sci'), 'tech', 'Fortune 500 (2025): #489, $7.57B revenue'],
1705
+ ['Yum Brands', 8, exactly('yum brands'), 'consumer', 'Fortune 500 (2025): #491, $7.55B revenue'],
1706
+ ['Fastenal', 8, exactly('fastenal', 'fastenal company'), 'industry', 'Fortune 500 (2025): #492, $7.55B revenue'],
1707
+ ['CMS Energy', 8, exactly('cms energy', 'consumers energy'), 'industry', 'Fortune 500 (2025): #493, $7.51B revenue'],
1708
+ ['Monster Beverage', 8, exactly('monster beverage', 'monster energy', 'monster energy company'), 'consumer', 'Fortune 500 (2025): #494, $7.49B revenue'],
1709
+ ['SAIC', 8, exactly('saic', 'science applications international'), 'defense', 'Fortune 500 (2025): #496, $7.48B revenue'],
1710
+ ['Howmet Aerospace', 8, exactly('howmet aerospace', 'howmet'), 'defense', 'Fortune 500 (2025): #498, $7.43B revenue'],
1711
+ ['Vulcan Materials', 8, exactly('vulcan materials', 'vulcan materials company'), 'industry', 'Fortune 500 (2025): #500, $7.42B revenue'],
1712
+ ['StoneX Group', 7, exactly('stonex group', 'stonex financial', 'stonex markets', 'intl fcstone', 'fcstone', 'gain capital', 'forex.com'), 'finance', 'Fortune 500 (2025): #42, $99.9B revenue'],
1713
+ ['Plains All American', 7, exactly('plains all american', 'plains all american pipeline', 'plains gp holdings'), 'industry', 'Fortune 500 (2025): #92, $50.1B revenue'],
1714
+ ['TIAA', 7, exactly('tiaa', 'teachers insurance and annuity association', 'tiaa-cref', 'tiaa cref'), 'finance', 'Fortune 500 (2025): #98, $46.9B revenue'],
1715
+ ['Nuveen', 7, exactly('nuveen', 'nuveen investments'), 'finance', 'TIAA\'s: Fortune 500 (2025): #98, $46.9B revenue'],
1716
+ ['MassMutual', 7, exactly('massmutual', 'massachusetts mutual life insurance company', 'mass mutual', 'massmutual financial group', 'massmutual ascend'), 'finance', 'Fortune 500 (2025): #102, $43.1B revenue'],
1717
+ ['World Kinect', 7, exactly('world kinect', 'world fuel services', 'kinect energy'), 'industry', 'Fortune 500 (2025): #106, $42.2B revenue'],
1718
+ ['Northwestern Mutual', 7, exactly('northwestern mutual', 'northwestern mutual life insurance company', 'northwestern mutual life', 'northwestern mutual wealth management company'), 'finance', 'Fortune 500 (2025): #109, $41.4B revenue'],
1719
+ ['Molina Healthcare', 7, exactly('molina healthcare', 'molina'), 'health', 'Fortune 500 (2025): #111, $40.7B revenue'],
1720
+ ['PBF Energy', 7, exactly('pbf energy', 'pbf logistics'), 'industry', 'Fortune 500 (2025): #135, $33.1B revenue'],
1721
+ ['GuideWell', 7, exactly('guidewell', 'guidewell mutual holding', 'florida blue', 'blue cross blue shield of florida', 'triple-s management'), 'health', 'Fortune 500 (2025): #136, $33.0B revenue'],
1722
+ ['HF Sinclair', 7, exactly('hf sinclair', 'hollyfrontier', 'holly frontier', 'sinclair oil', 'holly energy partners'), 'industry', 'Fortune 500 (2025): #150, $28.6B revenue'],
1723
+ ['Avnet', 7, exactly('avnet', 'premier farnell', 'farnell element14'), 'tech', 'Fortune 500 (2025): #181, $23.8B revenue'],
1724
+ ['Reinsurance Group of America', 7, exactly('reinsurance group of america', 'rga reinsurance company', 'rga reinsurance'), 'finance', 'Fortune 500 (2025): #196, $22.1B revenue'],
1725
+ ['American Family Insurance', 7, exactly('american family insurance', 'american family insurance group', 'american family mutual insurance', 'amfam'), 'finance', 'Fortune 500 (2025): #202, $21.3B revenue'],
1726
+ ['CDW', 7, exactly('cdw', 'cdw government', 'cdw-g', 'cdw canada', 'cdw uk'), 'tech', 'Fortune 500 (2025): #205, $21.0B revenue'],
1727
+ ['Group 1 Automotive', 7, exactly('group 1 automotive', 'group1 automotive'), 'consumer', 'Fortune 500 (2025): #214, $19.9B revenue'],
1728
+ ['Corebridge Financial', 7, exactly('corebridge financial', 'corebridge'), 'finance', 'Fortune 500 (2025): #224, $18.8B revenue'],
1729
+ ['Lincoln Financial', 7, exactly('lincoln financial', 'lincoln financial group', 'lincoln national', 'lincoln national life insurance company', 'lincoln financial distributors'), 'finance', 'Fortune 500 (2025): #228, $18.4B revenue'],
1730
+ ['Murphy USA', 7, exactly('murphy usa', 'murphy express', 'quickchek'), 'consumer', 'Fortune 500 (2025): #231, $17.9B revenue'],
1731
+ ['C.H. Robinson', 7, exactly('c.h. robinson', 'ch robinson', 'c. h. robinson', 'c.h. robinson worldwide', 'ch robinson worldwide', 'robinson fresh'), 'industry', 'Fortune 500 (2025): #233, $17.7B revenue'],
1732
+ ['Edison International', 7, exactly('edison international', 'southern california edison', 'so cal edison', 'socal edison'), 'industry', 'Fortune 500 (2025): #235, $17.6B revenue'],
1733
+ ['Asbury Automotive Group', 7, exactly('asbury automotive group', 'asbury automotive'), 'consumer', 'Fortune 500 (2025): #242, $17.2B revenue'],
1734
+ ['Global Partners LP', 7, exactly('global partners lp', 'alltown fresh'), 'industry', 'Fortune 500 (2025): #244, $17.2B revenue'],
1735
+ ['Corteva', 7, exactly('corteva', 'corteva agriscience'), 'industry', 'Fortune 500 (2025): #246, $16.9B revenue'],
1736
+ ['Guardian Life', 7, exactly('guardian life', 'guardian life insurance', 'guardian life insurance company of america'), 'finance', 'Fortune 500 (2025): #253, $16.5B revenue'],
1737
+ ['Ally Financial', 7, exactly('ally financial', 'ally bank', 'ally auto'), 'finance', 'Fortune 500 (2025): #255, $16.4B revenue'],
1738
+ ['Land O Lakes', 7, exactly('land o lakes', 'land o\'lakes', 'land o\' lakes', 'purina animal nutrition', 'winfield united'), 'consumer', 'Fortune 500 (2025): #262, $16.2B revenue'],
1739
+ ['Auto-Owners Insurance', 7, exactly('auto-owners insurance', 'auto owners insurance', 'auto-owners insurance company', 'auto-owners'), 'finance', 'Fortune 500 (2025): #270, $15.8B revenue'],
1740
+ ['Pacific Life', 7, exactly('pacific life', 'pacific life insurance company', 'pacific life re'), 'finance', 'Fortune 500 (2025): #272, $15.8B revenue'],
1741
+ ['Farmers Insurance', 7, exactly('farmers insurance', 'farmers insurance exchange', 'farmers insurance group'), 'finance', 'Fortune 500 (2025): #280, $15.5B revenue'],
1742
+ ['Mutual of Omaha', 7, exactly('mutual of omaha', 'mutual of omaha insurance company', 'mutual of omaha insurance', 'mutual of omaha mortgage'), 'finance', 'Fortune 500 (2025): #299, $14.6B revenue'],
1743
+ ['Sonic Automotive', 7, exactly('sonic automotive', 'echopark automotive', 'echopark'), 'consumer', 'Fortune 500 (2025): #304, $14.2B revenue'],
1744
+ ['Western & Southern Financial Group', 7, exactly('western & southern financial group', 'western and southern financial group', 'western & southern', 'western and southern', 'western & southern life', 'western-southern life', 'gerber life insurance', 'gerber life', 'fort washington investment advisors'), 'finance', 'Fortune 500 (2025): #310, $13.8B revenue'],
1745
+ ['Erie Insurance', 7, exactly('erie insurance', 'erie insurance group', 'erie indemnity company', 'erie indemnity', 'erie insurance exchange', 'erie family life insurance'), 'finance', 'Fortune 500 (2025): #323, $13.2B revenue'],
1746
+ ['Unum', 7, exactly('unum', 'unum group', 'unum us', 'unum uk'), 'finance', 'Fortune 500 (2025): #330, $12.9B revenue'],
1747
+ ['Delek US', 7, exactly('delek us', 'delek us holdings', 'delek us energy'), 'industry', 'Fortune 500 (2025): #336, $12.5B revenue'],
1748
+ ['Equitable Holdings', 7, exactly('equitable holdings', 'axa equitable', 'axa equitable life insurance company', 'equitable financial life insurance company', 'equitable advisors'), 'finance', 'Fortune 500 (2025): #338, $12.4B revenue'],
1749
+ ['DuPont', 7, exactly('dupont', 'dupont de nemours', 'du pont'), 'industry', 'Fortune 500 (2025): #339, $12.4B revenue'],
1750
+ ['Conagra Brands', 7, exactly('conagra brands', 'conagra', 'conagra foods'), 'consumer', 'Fortune 500 (2025): #350, $12.1B revenue'],
1751
+ ['Hormel Foods', 7, exactly('hormel foods', 'hormel', 'jennie-o turkey store', 'jennie-o'), 'consumer', 'Fortune 500 (2025): #352, $11.9B revenue'],
1752
+ ['Alcoa', 7, exactly('alcoa', 'alcoa world alumina'), 'industry', 'Fortune 500 (2025): #354, $11.9B revenue'],
1753
+ ['Assurant', 7, exactly('assurant'), 'finance', 'Fortune 500 (2025): #356, $11.9B revenue'],
1754
+ ['Chewy', 7, exactly('chewy', 'chewy.com', 'chewy health', 'chewy vet care', 'chewy pharmacy'), 'consumer', 'Fortune 500 (2025): #357, $11.9B revenue'],
1755
+ ['Wayfair', 7, exactly('wayfair', 'perigold', 'allmodern'), 'consumer', 'Fortune 500 (2025): #358, $11.9B revenue'],
1756
+ ['Graybar', 7, exactly('graybar', 'graybar electric company', 'graybar electric'), 'industry', 'Fortune 500 (2025): #365, $11.6B revenue'],
1757
+ ['Molson Coors', 7, exactly('molson coors', 'molson coors beverage company', 'molson coors brewing company', 'molsoncoors', 'millercoors', 'coors brewing company', 'molson coors canada'), 'consumer', 'Fortune 500 (2025): #366, $11.6B revenue'],
1758
+ ['The Andersons', 7, exactly('andersons'), 'industry', 'Fortune 500 (2025): #378, $11.3B revenue'],
1759
+ ['The Mosaic Company', 7, exactly('mosaic company', 'mosaic fertilizantes'), 'industry', 'Fortune 500 (2025): #381, $11.1B revenue'],
1760
+ ['Thrivent', 7, exactly('thrivent', 'thrivent financial', 'thrivent financial for lutherans'), 'finance', 'Fortune 500 (2025): #388, $10.9B revenue'],
1761
+ ['Toll Brothers', 7, exactly('toll brothers', 'toll bros'), 'realestate', 'Fortune 500 (2025): #390, $10.8B revenue'],
1762
+ ['Accendra Health', 7, exactly('accendra health', 'accendra', 'apria', 'apria healthcare', 'byram healthcare'), 'health', 'Fortune 500 (2025): #395, $10.7B revenue'],
1763
+ ['NVR', 7, exactly('nvr', 'ryan homes', 'nvhomes', 'heartland homes', 'nvr mortgage'), 'realestate', 'Fortune 500 (2025): #396, $10.7B revenue'],
1764
+ ['Jefferies', 7, exactly('jefferies', 'jefferies financial group', 'jefferies group', 'jefferies & company'), 'finance', 'Fortune 500 (2025): #403, $10.52B revenue'],
1765
+ ['FM Global', 7, exactly('fm global', 'factory mutual insurance company', 'factory mutual', 'fm affiliated', 'affiliated fm', 'fm approvals'), 'finance', 'Fortune 500 (2025): #406, $10.41B revenue'],
1766
+ ['Celanese', 7, exactly('celanese'), 'industry', 'Fortune 500 (2025): #412, $10.28B revenue'],
1767
+ ['QVC Group', 7, exactly('qvc group', 'qvc', 'qurate retail group', 'qurate retail', 'qurate'), 'consumer', 'Fortune 500 (2025): #416, $10.04B revenue'],
1768
+ ['Icahn Enterprises', 7, exactly('icahn enterprises', 'icahn enterprises l.p', 'icahn automotive group', 'icahn automotive'), 'finance', 'Fortune 500 (2025): #417, $10.02B revenue'],
1769
+ ['QXO', 7, exactly('qxo', 'qxo building products', 'beacon roofing supply', 'beacon building products', 'topbuild', 'kodiak building partners'), 'industry', 'Fortune 500 (2025): #421, $9.76B revenue'],
1770
+ ['Gold.com', 7, exactly('gold.com', 'a-mark precious metals', 'a-mark', 'jm bullion', 'stack\'s bowers galleries', 'govmint'), 'finance', 'Fortune 500 (2025): #423, $9.70B revenue'],
1771
+ ['SpartanNash', 7, exactly('spartannash', 'spartannash company', 'spartan nash'), 'consumer', 'Fortune 500 (2025): #428, $9.55B revenue'],
1772
+ ['Ace Hardware', 7, exactly('ace hardware', 'ace retail holdings', 'westlake ace hardware'), 'consumer', 'Fortune 500 (2025): #429, $9.49B revenue'],
1773
+ ['Eastman Chemical', 7, exactly('eastman chemical', 'eastman chemical company'), 'industry', 'Fortune 500 (2025): #431, $9.38B revenue'],
1774
+ ['JetBlue', 7, exactly('jetblue', 'jetblue airways', 'jet blue'), 'consumer', 'Fortune 500 (2025): #434, $9.28B revenue'],
1775
+ ['KeyCorp', 7, exactly('keycorp', 'keybank national association', 'keybanc capital markets'), 'finance', 'Fortune 500 (2025): #436, $9.24B revenue'],
1776
+ ['KeyBank', 7, exactly('keybank', 'key bank'), 'finance', 'KeyCorp\'s: Fortune 500 (2025): #436, $9.24B revenue'],
1777
+ ['Oscar Health', 7, exactly('oscar health', 'oscar insurance'), 'health', 'Fortune 500 (2025): #437, $9.18B revenue'],
1778
+ ['Ovintiv', 7, exactly('ovintiv'), 'industry', 'Fortune 500 (2025): #438, $9.15B revenue'],
1779
+ ['Skechers', 7, exactly('skechers', 'skechers u.s.a', 'skechers usa'), 'consumer', 'Fortune 500 (2025): #441, $8.97B revenue'],
1780
+ ['Optimum Communications', 7, exactly('optimum communications', 'altice usa', 'suddenlink', 'news 12 networks'), 'tech', 'Fortune 500 (2025): #442, $8.95B revenue'],
1781
+ ['Insight Enterprises', 7, exactly('insight enterprises'), 'tech', 'Fortune 500 (2025): #447, $8.70B revenue'],
1782
+ ['Franklin Templeton', 7, exactly('franklin templeton', 'franklin resources', 'franklin templeton investments', 'legg mason', 'clearbridge investments', 'western asset management', 'brandywine global investment management', 'putnam investments', 'benefit street partners', 'clarion partners', 'lexington partners'), 'finance', 'Fortune 500 (2025): #453, $8.48B revenue'],
1783
+ ['Packaging Corporation of America', 7, exactly('packaging corporation of america', 'packaging corp of america'), 'industry', 'Fortune 500 (2025): #457, $8.38B revenue'],
1784
+ ['American Financial Group', 7, exactly('american financial group', 'great american insurance group', 'great american insurance company', 'great american insurance'), 'finance', 'Fortune 500 (2025): #460, $8.32B revenue'],
1785
+ ['Old Republic International', 7, exactly('old republic international', 'old republic', 'old republic national title insurance company'), 'finance', 'Fortune 500 (2025): #463, $8.23B revenue'],
1786
+ ['Old Republic Title', 7, exactly('old republic title', 'old republic national title'), 'finance', 'Old Republic International\'s: Fortune 500 (2025): #463, $8.23B revenue'],
1787
+ ['Securian Financial', 7, exactly('securian financial', 'securian financial group', 'securian', 'minnesota life insurance company', 'minnesota life'), 'finance', 'Fortune 500 (2025): #464, $8.23B revenue'],
1788
+ ['J.M. Smucker', 7, exactly('j.m. smucker', 'j.m. smucker company', 'j. m. smucker', 'jm smucker', 'smucker\'s', 'smuckers'), 'consumer', 'Fortune 500 (2025): #466, $8.18B revenue'],
1789
+ ['Taylor Morrison', 7, exactly('taylor morrison', 'taylor morrison home', 'darling homes'), 'realestate', 'Fortune 500 (2025): #467, $8.17B revenue'],
1790
+ ['Voya Financial', 7, exactly('voya financial', 'voya', 'voya investment management'), 'finance', 'Fortune 500 (2025): #469, $8.05B revenue'],
1791
+ ['Par Pacific', 7, exactly('par pacific', 'par pacific holdings', 'par hawaii'), 'industry', 'Fortune 500 (2025): #474, $7.97B revenue'],
1792
+ ['Commercial Metals', 7, exactly('commercial metals', 'commercial metals company'), 'industry', 'Fortune 500 (2025): #476, $7.93B revenue'],
1793
+ ['Post Holdings', 7, exactly('post holdings', 'post consumer brands', 'michael foods', 'weetabix'), 'consumer', 'Fortune 500 (2025): #477, $7.92B revenue'],
1794
+ ['Masco', 7, exactly('masco', 'delta faucet company', 'delta faucet', 'behr paint company', 'behr process'), 'consumer', 'Fortune 500 (2025): #478, $7.83B revenue'],
1795
+ ['Rush Enterprises', 7, exactly('rush enterprises', 'rush truck centers'), 'industry', 'Fortune 500 (2025): #479, $7.80B revenue'],
1796
+ ['Zimmer Biomet', 7, exactly('zimmer biomet', 'zimmer biomet holdings', 'biomet'), 'health', 'Fortune 500 (2025): #483, $7.68B revenue'],
1797
+ ['Watsco', 7, exactly('watsco', 'carrier enterprise', 'baker distributing company', 'baker distributing', 'gemaire distributors'), 'industry', 'Fortune 500 (2025): #486, $7.62B revenue'],
1798
+ ['ARKO', 7, exactly('arko', 'gpm investments'), 'consumer', 'Fortune 500 (2025): #488, $7.57B revenue'],
1799
+ ['WME', 7, exactly('wme', 'endeavor group holdings', 'wme group', 'william morris endeavor', 'william morris endeavor entertainment', 'img licensing', '160over90'), 'entertainment', 'Fortune 500 (2025): #495, $7.48B revenue'],
1800
+ ['Core & Main', 7, exactly('core & main', 'core and main'), 'industry', 'Fortune 500 (2025): #497, $7.44B revenue'],
1801
+ ['Ingredion', 7, exactly('ingredion'), 'industry', 'Fortune 500 (2025): #498, $7.43B revenue'],
1802
+ // U.S. federal government
1803
+ ['U.S. Department of State', 8, exactly('u.s. department of state', 'us department of state', 'united states department of state', 'department of state', 'state department', 'u.s. state department', 'us state department', 'state.gov', 'u.s. foreign service', 'us foreign service', 'united states foreign service', 'u.s. embassy', 'us embassy', 'united states embassy', 'american embassy', 'u.s. consulate general', 'us consulate general', 'u.s. consulate', 'us consulate'), 'defense', 'U.S. executive department (state.gov, OPM data), about 77,000 staff incl. locally employed (2025)'],
1804
+ ['U.S. Department of Defense', 8, exactly('u.s. department of defense', 'us department of defense', 'united states department of defense', 'department of defense', 'u.s. department of war', 'us department of war', 'united states department of war', 'department of war', 'dod', 'u.s. dod', 'us dod', 'defense department', 'u.s. defense department', 'office of the secretary of defense', 'office of the secretary of war'), 'defense', 'U.S. executive department (war.gov, OPM and DMDC data), about 685,000 civilians and 1.3 million active duty (2026)'],
1805
+ ['U.S. Department of Justice', 8, exactly('u.s. department of justice', 'us department of justice', 'united states department of justice', 'u.s. doj', 'us doj', 'u.s. justice department', 'us justice department'), 'defense', 'U.S. executive department (justice.gov, OPM data), about 107,300 staff (July 2026)'],
1806
+ ['U.S. Department of the Interior', 8, exactly('u.s. department of the interior', 'us department of the interior', 'united states department of the interior', 'department of the interior', 'u.s. department of interior', 'us department of interior', 'department of interior', 'interior department', 'u.s. interior department'), 'defense', 'U.S. executive department (doi.gov, OPM data), about 59,900 staff (July 2026)'],
1807
+ ['U.S. Department of Agriculture', 8, exactly('u.s. department of agriculture', 'us department of agriculture', 'united states department of agriculture', 'usda', 'u.s. usda', 'natural resources conservation service', 'animal and plant health inspection service', 'food safety and inspection service', 'agricultural research service', 'agricultural marketing service', 'farm service agency', 'usda rural development', 'usda ars', 'usda aphis', 'usda nrcs', 'usda fsis', 'usda fsa', 'usda ams', 'usda fns', 'usda ers', 'usda nass', 'usda nifa'), 'defense', 'U.S. executive department (usda.gov, OPM data), about 78,000 staff (July 2026)'],
1808
+ ['U.S. Department of Commerce', 8, exactly('u.s. department of commerce', 'us department of commerce', 'united states department of commerce', 'u.s. commerce department', 'us commerce department', 'international trade administration', 'bureau of industry and security', 'bureau of economic analysis'), 'defense', 'U.S. executive department (commerce.gov, OPM data), about 41,200 staff (July 2026)'],
1809
+ ['U.S. Department of Labor', 8, exactly('u.s. department of labor', 'us department of labor', 'united states department of labor', 'usdol', 'u.s. dol', 'us dol', 'u.s. labor department', 'us labor department', 'bureau of labor statistics', 'u.s. bureau of labor statistics', 'us bureau of labor statistics', 'mine safety and health administration', 'u.s. osha', 'us osha', 'federal osha'), 'defense', 'U.S. executive department (dol.gov, OPM data), about 11,100 staff (July 2026)'],
1810
+ ['HHS', 8, exactly('hhs', 'u.s. hhs', 'us hhs', 'health resources and services administration', 'hrsa', 'administration for children and families', 'samhsa'), 'health', 'U.S. executive department (hhs.gov, OPM data), about 72,900 staff (July 2026)'],
1811
+ ['HUD', 8, exactly('hud', 'department of housing and urban development', 'u.s. hud', 'us hud'), 'defense', 'U.S. executive department (hud.gov, OPM data), about 5,900 staff (July 2026)'],
1812
+ ['U.S. Department of Transportation', 8, exactly('u.s. department of transportation', 'us department of transportation', 'united states department of transportation', 'usdot', 'u.s. dot', 'us dot', 'federal highway administration', 'fhwa', 'federal railroad administration', 'federal transit administration', 'federal motor carrier safety administration', 'fmcsa', 'national highway traffic safety administration', 'nhtsa', 'phmsa', 'u.s. maritime administration', 'marad'), 'defense', 'U.S. executive department (transportation.gov, OPM data), about 52,900 staff (July 2026)'],
1813
+ ['U.S. Department of Energy', 8, exactly('u.s. department of energy', 'us department of energy', 'united states department of energy', 'department of energy', 'usdoe', 'u.s. doe', 'us doe'), 'defense', 'U.S. executive department (energy.gov, OPM data), about 13,400 federal staff (July 2026)'],
1814
+ ['U.S. Department of Education', 8, exactly('u.s. department of education', 'us department of education', 'united states department of education', 'federal student aid'), 'defense', 'U.S. executive department (ed.gov, OPM data), about 2,300 staff (July 2026)'],
1815
+ ['U.S. Department of Veterans Affairs', 8, exactly('u.s. department of veterans affairs', 'us department of veterans affairs', 'united states department of veterans affairs', 'department of veterans affairs', 'veterans affairs', 'u.s. veterans affairs', 'us veterans affairs', 'u.s. va', 'us va', 'veterans health administration', 'veterans benefits administration', 'national cemetery administration', 'va medical center', 'veterans affairs medical center', 'va health care system', 'va healthcare system', 'va hospital'), 'health', 'U.S. executive department (va.gov, OPM data), about 446,500 staff (July 2026)'],
1816
+ ['U.S. Department of Homeland Security', 8, exactly('u.s. department of homeland security', 'us department of homeland security', 'united states department of homeland security', 'department of homeland security', 'u.s. dhs', 'us dhs', 'federal law enforcement training centers', 'federal law enforcement training center', 'fletc', 'federal protective service'), 'defense', 'U.S. executive department (dhs.gov, OPM data), about 225,500 civilian staff (July 2026)'],
1817
+ ['U.S. Army', 8, exactly('u.s. army', 'us army', 'united states army', 'u.s. army reserve', 'us army reserve', 'united states army reserve', 'department of the army', 'u.s. department of the army', 'us department of the army', 'united states department of the army', 'hqda'), 'defense', 'U.S. military branch (army.mil, DMDC and OPM data), about 458,100 active duty and 188,300 civilians (2026)'],
1818
+ ['U.S. Navy', 8, exactly('u.s. navy', 'us navy', 'united states navy', 'u.s. navy reserve', 'us navy reserve', 'united states navy reserve', 'u.s. naval reserve', 'us naval reserve', 'united states naval reserve', 'department of the navy', 'u.s. department of the navy', 'us department of the navy', 'united states department of the navy', 'office of naval research', 'usn'), 'defense', 'U.S. military branch (navy.mil, DMDC and OPM data), about 347,700 active duty and 184,300 civilians (2026)'],
1819
+ ['U.S. Air Force', 8, exactly('u.s. air force', 'us air force', 'united states air force', 'usaf', 'u.s. air force reserve', 'us air force reserve', 'united states air force reserve', 'air force reserve command', 'department of the air force', 'u.s. department of the air force', 'us department of the air force'), 'defense', 'U.S. military branch (af.mil, DMDC and OPM data), about 320,000 active duty and 144,000 civilians (2026)'],
1820
+ ['U.S. Marine Corps', 8, exactly('u.s. marine corps', 'us marine corps', 'united states marine corps', 'usmc', 'marine corps', 'u.s. marine corps reserve', 'us marine corps reserve', 'united states marine corps reserve', 'usmcr', 'marine forces reserve', 'u.s. marines', 'us marines', 'united states marines'), 'defense', 'U.S. military branch (marines.mil, DMDC and OPM data), about 169,900 active duty and 16,200 civilians (2026)'],
1821
+ ['U.S. Space Force', 8, exactly('u.s. space force', 'us space force', 'united states space force', 'space systems command', 'space operations command', 'space training and readiness command', 'space development agency', 'ussf'), 'defense', 'U.S. military branch (spaceforce.mil, DMDC and OPM data), about 10,200 Guardians and 7,100 civilians (2026)'],
1822
+ ['U.S. Coast Guard', 8, exactly('u.s. coast guard', 'us coast guard', 'united states coast guard', 'uscg', 'u.s. coast guard reserve', 'us coast guard reserve', 'united states coast guard reserve'), 'defense', 'U.S. military branch (uscg.mil, DMDC and OPM data), about 43,600 active duty and 8,700 civilians (2026)'],
1823
+ ['National Guard', 8, exactly('national guard', 'u.s. national guard', 'us national guard', 'united states national guard', 'army national guard', 'air national guard', 'national guard bureau', 'arng', 'alabama national guard', 'alabama army national guard', 'alabama air national guard', 'alaska national guard', 'alaska army national guard', 'alaska air national guard', 'arizona national guard', 'arizona army national guard', 'arizona air national guard', 'arkansas national guard', 'arkansas army national guard', 'arkansas air national guard', 'california national guard', 'california army national guard', 'california air national guard', 'colorado national guard', 'colorado army national guard', 'colorado air national guard', 'connecticut national guard', 'connecticut army national guard', 'connecticut air national guard', 'delaware national guard', 'delaware army national guard', 'delaware air national guard', 'florida national guard', 'florida army national guard', 'florida air national guard', 'georgia national guard', 'georgia army national guard', 'georgia air national guard', 'hawaii national guard', 'hawaii army national guard', 'hawaii air national guard', 'idaho national guard', 'idaho army national guard', 'idaho air national guard', 'illinois national guard', 'illinois army national guard', 'illinois air national guard', 'indiana national guard', 'indiana army national guard', 'indiana air national guard', 'iowa national guard', 'iowa army national guard', 'iowa air national guard', 'kansas national guard', 'kansas army national guard', 'kansas air national guard', 'kentucky national guard', 'kentucky army national guard', 'kentucky air national guard', 'louisiana national guard', 'louisiana army national guard', 'louisiana air national guard', 'maine national guard', 'maine army national guard', 'maine air national guard', 'maryland national guard', 'maryland army national guard', 'maryland air national guard', 'massachusetts national guard', 'massachusetts army national guard', 'massachusetts air national guard', 'michigan national guard', 'michigan army national guard', 'michigan air national guard', 'minnesota national guard', 'minnesota army national guard', 'minnesota air national guard', 'mississippi national guard', 'mississippi army national guard', 'mississippi air national guard', 'missouri national guard', 'missouri army national guard', 'missouri air national guard', 'montana national guard', 'montana army national guard', 'montana air national guard', 'nebraska national guard', 'nebraska army national guard', 'nebraska air national guard', 'nevada national guard', 'nevada army national guard', 'nevada air national guard', 'new hampshire national guard', 'new hampshire army national guard', 'new hampshire air national guard', 'new jersey national guard', 'new jersey army national guard', 'new jersey air national guard', 'new mexico national guard', 'new mexico army national guard', 'new mexico air national guard', 'new york national guard', 'new york army national guard', 'new york air national guard', 'north carolina national guard', 'north carolina army national guard', 'north carolina air national guard', 'north dakota national guard', 'north dakota army national guard', 'north dakota air national guard', 'ohio national guard', 'ohio army national guard', 'ohio air national guard', 'oklahoma national guard', 'oklahoma army national guard', 'oklahoma air national guard', 'oregon national guard', 'oregon army national guard', 'oregon air national guard', 'pennsylvania national guard', 'pennsylvania army national guard', 'pennsylvania air national guard', 'rhode island national guard', 'rhode island army national guard', 'rhode island air national guard', 'south carolina national guard', 'south carolina army national guard', 'south carolina air national guard', 'south dakota national guard', 'south dakota army national guard', 'south dakota air national guard', 'tennessee national guard', 'tennessee army national guard', 'tennessee air national guard', 'texas national guard', 'texas army national guard', 'texas air national guard', 'utah national guard', 'utah army national guard', 'utah air national guard', 'vermont national guard', 'vermont army national guard', 'vermont air national guard', 'virginia national guard', 'virginia army national guard', 'virginia air national guard', 'washington national guard', 'washington army national guard', 'washington air national guard', 'west virginia national guard', 'west virginia army national guard', 'west virginia air national guard', 'wisconsin national guard', 'wisconsin army national guard', 'wisconsin air national guard', 'wyoming national guard', 'wyoming army national guard', 'wyoming air national guard', 'district of columbia national guard', 'district of columbia army national guard', 'district of columbia air national guard', 'd.c. national guard', 'd.c. army national guard', 'd.c. air national guard', 'dc national guard', 'dc army national guard', 'dc air national guard', 'puerto rico national guard', 'puerto rico army national guard', 'puerto rico air national guard', 'guam national guard', 'guam army national guard', 'guam air national guard', 'virgin islands national guard', 'virgin islands army national guard', 'virgin islands air national guard', 'u.s. virgin islands national guard', 'u.s. virgin islands army national guard', 'u.s. virgin islands air national guard'), 'defense', 'U.S. military reserve component (nationalguard.mil, OPM data), about 433,000 members (FY2025)'],
1824
+ ['FBI', 8, exactly('fbi', 'federal bureau of investigation', 'u.s. federal bureau of investigation', 'us federal bureau of investigation'), 'defense', 'U.S. federal law-enforcement agency (fbi.gov, OPM data), about 35,300 staff (July 2026)'],
1825
+ ['CIA', 8, exactly('cia', 'central intelligence agency', 'u.s. central intelligence agency', 'us central intelligence agency'), 'defense', 'U.S. intelligence agency (cia.gov, Wikipedia), about 21,500 staff (estimate; staffing classified)'],
1826
+ ['NSA', 8, exactly('nsa', 'national security agency', 'u.s. national security agency', 'us national security agency', 'central security service'), 'defense', 'U.S. intelligence agency (nsa.gov, Wikipedia), 30,000-40,000 staff (estimate, 2024-25)'],
1827
+ ['Defense Logistics Agency', 8, exactly('defense logistics agency', 'u.s. defense logistics agency', 'us defense logistics agency', 'dla', 'dla troop support', 'dla aviation', 'dla land and maritime', 'dla distribution', 'dla energy', 'dla disposition services'), 'defense', 'U.S. defense agency (dla.mil, OPM data), about 23,000 civilians (May 2026)'],
1828
+ ['Defense Health Agency', 8, exactly('defense health agency', 'u.s. defense health agency', 'us defense health agency', 'walter reed national military medical center', 'brooke army medical center', 'naval medical center san diego', 'naval medical center portsmouth', 'madigan army medical center', 'tripler army medical center', 'womack army medical center', 'landstuhl regional medical center', 'fort belvoir community hospital', 'carl r. darnall army medical center', 'william beaumont army medical center', 'eisenhower army medical center'), 'health', 'U.S. defense health agency (health.mil, OPM data), about 46,400 civilians (May 2026)'],
1829
+ ['Army & Air Force Exchange Service', 8, exactly('army & air force exchange service', 'army air force exchange service', 'army & air force exchange', 'aafes'), 'defense', 'U.S. defense agency (aafes.com), about 35,000 associates (2026)'],
1830
+ ['NAVSEA', 8, exactly('navsea', 'naval sea systems command', 'naval surface warfare center', 'nswc', 'naval undersea warfare center', 'nuwc', 'norfolk naval shipyard', 'portsmouth naval shipyard', 'puget sound naval shipyard', 'pearl harbor naval shipyard'), 'defense', 'U.S. Navy systems command (navsea.navy.mil, OPM data), about 33,300 civilians (May 2026)'],
1831
+ ['NAVAIR', 8, exactly('navair', 'naval air systems command', 'naval air warfare center', 'nawcad', 'nawcwd', 'fleet readiness center', 'fleet readiness center east', 'fleet readiness center southeast', 'fleet readiness center southwest', 'frcse'), 'defense', 'U.S. Navy systems command (navair.navy.mil, OPM data), about 26,600 civilians (May 2026)'],
1832
+ ['Air Force Materiel Command', 8, exactly('air force materiel command', 'u.s. air force materiel command', 'us air force materiel command', 'air force life cycle management center', 'aflcmc', 'air force sustainment center', 'air force test center', 'air force nuclear weapons center', 'oklahoma city air logistics complex', 'ogden air logistics complex', 'warner robins air logistics complex'), 'defense', 'U.S. Air Force major command (afmc.af.mil, OPM data), about 64,500 civilians (May 2026)'],
1833
+ ['U.S. Army Corps of Engineers', 8, exactly('u.s. army corps of engineers', 'us army corps of engineers', 'united states army corps of engineers', 'army corps of engineers', 'usace'), 'defense', 'U.S. Army engineering command (usace.army.mil, OPM data), about 34,300 civilians (May 2026)'],
1834
+ ['Social Security Administration', 8, exactly('social security administration', 'u.s. social security administration', 'us social security administration', 'united states social security administration'), 'defense', 'U.S. federal agency (ssa.gov, OPM data), about 49,500 staff (July 2026)'],
1835
+ ['IRS', 8, exactly('irs', 'internal revenue service', 'u.s. internal revenue service', 'us internal revenue service', 'united states internal revenue service', 'irs criminal investigation', 'irs-ci', 'irs office of chief counsel'), 'defense', 'U.S. tax agency (irs.gov, OPM data), about 71,800 staff (July 2026)'],
1836
+ ['USPS', 8, exactly('usps', 'united states postal service', 'u.s. postal service', 'us postal service', 'united states post office', 'u.s. post office', 'us post office', 'usps office of inspector general'), 'defense', 'U.S. federal establishment (usps.com, Federal News Network), about 623,000 employees (August 2025)'],
1837
+ ['U.S. Customs and Border Protection', 8, exactly('u.s. customs and border protection', 'us customs and border protection', 'united states customs and border protection', 'customs and border protection', 'cbp', 'u.s. cbp', 'us cbp', 'u.s. border patrol', 'us border patrol', 'united states border patrol', 'border patrol'), 'defense', 'U.S. border agency (cbp.gov, OPM data), about 70,300 staff (July 2026)'],
1838
+ ['U.S. Immigration and Customs Enforcement', 8, exactly('u.s. immigration and customs enforcement', 'us immigration and customs enforcement', 'united states immigration and customs enforcement', 'immigration and customs enforcement', 'homeland security investigations', 'enforcement and removal operations', 'ice hsi', 'ice ero'), 'defense', 'U.S. immigration agency (ice.gov, OPM data), about 28,900 staff (July 2026)'],
1839
+ ['TSA', 8, exactly('tsa', 'transportation security administration', 'u.s. transportation security administration', 'us transportation security administration', 'federal air marshal service'), 'defense', 'U.S. aviation-security agency (tsa.gov, OPM data), about 59,600 staff (July 2026)'],
1840
+ ['USCIS', 8, exactly('uscis', 'u.s. citizenship and immigration services', 'us citizenship and immigration services', 'united states citizenship and immigration services', 'citizenship and immigration services'), 'defense', 'U.S. immigration-services agency (uscis.gov, OPM data), about 20,300 staff (July 2026)'],
1841
+ ['Federal Bureau of Prisons', 8, exactly('federal bureau of prisons', 'bureau of prisons', 'u.s. bureau of prisons', 'us bureau of prisons', 'federal prison system', 'federal prison industries', 'unicor'), 'defense', 'U.S. prison agency (bop.gov, OPM data), about 33,900 staff (July 2026)'],
1842
+ ['FAA', 8, exactly('faa', 'federal aviation administration', 'u.s. federal aviation administration', 'us federal aviation administration', 'united states federal aviation administration', 'u.s. faa', 'us faa'), 'defense', 'U.S. aviation agency (faa.gov, OPM data), about 44,700 staff (July 2026)'],
1843
+ ['U.S. Forest Service', 8, exactly('u.s. forest service', 'us forest service', 'united states forest service', 'usda forest service'), 'defense', 'U.S. land agency (fs.usda.gov, OPM data), about 33,500 staff (July 2026)'],
1844
+ ['Defense Intelligence Agency', 7, exactly('defense intelligence agency', 'u.s. defense intelligence agency', 'us defense intelligence agency'), 'defense', 'U.S. defense intelligence agency (dia.mil), about 16,500 staff (2025)'],
1845
+ ['National Geospatial-Intelligence Agency', 7, exactly('national geospatial-intelligence agency', 'national geospatial intelligence agency', 'u.s. national geospatial-intelligence agency', 'us national geospatial-intelligence agency'), 'defense', 'U.S. defense intelligence agency (nga.mil), about 14,500 staff (2025)'],
1846
+ ['National Reconnaissance Office', 7, exactly('national reconnaissance office', 'nro', 'u.s. national reconnaissance office', 'us national reconnaissance office'), 'defense', 'U.S. intelligence agency (nro.gov), about 3,000 staff (2025)'],
1847
+ ['DARPA', 7, exactly('darpa', 'defense advanced research projects agency', 'u.s. defense advanced research projects agency'), 'defense', 'U.S. defense research agency (darpa.mil, OPM data), about 220 staff and $4.3B budget (FY2026)'],
1848
+ ['ODNI', 7, exactly('odni', 'u.s. odni', 'us odni'), 'defense', 'U.S. intelligence office (dni.gov), about 1,300 staff after 2025 cuts'],
1849
+ ['Defense Information Systems Agency', 7, exactly('defense information systems agency', 'u.s. defense information systems agency', 'us defense information systems agency'), 'defense', 'U.S. defense agency (disa.mil, OPM data), about 6,200 civilians (May 2026)'],
1850
+ ['Defense Contract Management Agency', 7, exactly('defense contract management agency', 'dcma'), 'defense', 'U.S. defense agency (dcma.mil, OPM data), about 8,700 civilians (May 2026)'],
1851
+ ['Defense Finance and Accounting Service', 7, exactly('defense finance and accounting service', 'dfas'), 'defense', 'U.S. defense agency (dfas.mil, OPM data), about 9,500 civilians (May 2026)'],
1852
+ ['Missile Defense Agency', 7, exactly('missile defense agency', 'u.s. missile defense agency', 'us missile defense agency'), 'defense', 'U.S. defense agency (mda.mil, OPM data), about 2,500 civilians (May 2026)'],
1853
+ ['Defense Counterintelligence and Security Agency', 7, exactly('defense counterintelligence and security agency', 'dcsa', 'defense security service'), 'defense', 'U.S. defense agency (dcsa.mil, OPM data), about 5,000 civilians (May 2026)'],
1854
+ ['DoDEA', 7, exactly('dodea', 'department of defense education activity', 'department of war education activity', 'dodds'), 'defense', 'U.S. defense agency (dodea.edu, OPM data), about 14,500 staff (May 2026)'],
1855
+ ['NAVWAR', 7, exactly('navwar', 'naval information warfare systems command', 'naval information warfare center', 'niwc', 'niwc pacific', 'niwc atlantic', 'space and naval warfare systems command', 'spawar'), 'defense', 'U.S. Navy systems command (navwar.navy.mil, OPM data), about 9,500 civilians (May 2026)'],
1856
+ ['NAVFAC', 7, exactly('navfac', 'naval facilities engineering systems command', 'naval facilities engineering command'), 'defense', 'U.S. Navy systems command (navfac.navy.mil, OPM data), about 13,700 civilians (May 2026)'],
1857
+ ['U.S. Naval Research Laboratory', 7, exactly('u.s. naval research laboratory', 'us naval research laboratory', 'united states naval research laboratory', 'naval research laboratory', 'naval research lab', 'u.s. naval research lab'), 'defense', 'U.S. Navy research laboratory (nrl.navy.mil, Wikipedia), about 2,500 civilians (2015)'],
1858
+ ['Army Research Laboratory', 7, exactly('army research laboratory', 'army research lab', 'u.s. army research laboratory', 'us army research laboratory', 'devcom army research laboratory', 'devcom army research lab', 'devcom arl', 'army research office', 'u.s. army research office'), 'defense', 'U.S. Army research laboratory (arl.devcom.army.mil), about 2,500 staff (2024)'],
1859
+ ['NIH', 7, exactly('nih', 'national institutes of health', 'u.s. national institutes of health', 'us national institutes of health', 'united states national institutes of health', 'nih clinical center', 'u.s. national cancer institute', 'us national cancer institute', 'nih national cancer institute', 'national human genome research institute', 'national library of medicine', 'fogarty international center', 'niaid', 'nhlbi', 'nhgri', 'nichd', 'ninds', 'niddk', 'niehs', 'nibib', 'ncats', 'nigms', 'nimhd', 'ninr', 'nidcr', 'nidcd', 'nccih', 'niaaa'), 'health', 'U.S. health agency (nih.gov, OPM data), about 16,500 staff (July 2026)'],
1860
+ ['CDC', 7, exactly('cdc', 'centers for disease control and prevention', 'centers for disease control', 'center for disease control and prevention', 'center for disease control', 'u.s. cdc', 'us cdc', 'niosh'), 'health', 'U.S. health agency (cdc.gov, OPM data), about 9,100 staff (July 2026)'],
1861
+ ['FDA', 7, exactly('fda', 'u.s. food and drug administration', 'us food and drug administration', 'united states food and drug administration', 'food and drug administration', 'u.s. fda', 'us fda'), 'health', 'U.S. health agency (fda.gov, OPM data), about 16,300 staff (July 2026)'],
1862
+ ['Centers for Medicare & Medicaid Services', 7, exactly('centers for medicare & medicaid services', 'centers for medicare and medicaid services', 'center for medicare & medicaid services', 'center for medicare and medicaid services', 'u.s. cms', 'us cms'), 'health', 'U.S. health agency (cms.gov, OPM data), about 5,700 staff (July 2026)'],
1863
+ ['Indian Health Service', 7, exactly('indian health service', 'u.s. indian health service', 'us indian health service'), 'health', 'U.S. health agency (ihs.gov, OPM data), about 12,200 staff (July 2026)'],
1864
+ ['U.S. Public Health Service', 7, exactly('u.s. public health service', 'us public health service', 'united states public health service', 'usphs', 'usphs commissioned corps', 'public health service commissioned corps', 'u.s. public health service commissioned corps'), 'health', 'U.S. uniformed service (usphs.gov), about 6,500 officers (2025)'],
1865
+ ['FEMA', 7, exactly('fema', 'federal emergency management agency', 'u.s. federal emergency management agency'), 'defense', 'U.S. emergency-management agency (fema.gov, OPM data), about 20,300 staff incl. reservists (July 2026)'],
1866
+ ['U.S. Secret Service', 7, exactly('u.s. secret service', 'us secret service', 'united states secret service', 'secret service', 'usss'), 'defense', 'U.S. protective agency (secretservice.gov, OPM data), about 8,600 staff (July 2026)'],
1867
+ ['U.S. Marshals Service', 7, exactly('u.s. marshals service', 'us marshals service', 'united states marshals service', 'u.s. marshals', 'us marshals', 'united states marshals', 'u.s. marshal service', 'us marshal service', 'united states marshal service'), 'defense', 'U.S. law-enforcement agency (usmarshals.gov, OPM data), about 5,400 staff (July 2026)'],
1868
+ ['DEA', 7, exactly('dea', 'drug enforcement administration', 'u.s. drug enforcement administration', 'us drug enforcement administration', 'united states drug enforcement administration'), 'defense', 'U.S. drug-enforcement agency (dea.gov, OPM data), about 8,500 staff (July 2026)'],
1869
+ ['ATF', 7, exactly('atf', 'bureau of alcohol', 'bureau of alcohol tobacco and firearms', 'u.s. atf', 'us atf'), 'defense', 'U.S. firearms agency (atf.gov, OPM data), about 4,500 staff (July 2026)'],
1870
+ ['U.S. Attorney\'s Offices', 7, exactly('u.s. attorney\'s offices', 'u.s. attorney\'s office', 'us attorney\'s office', 'united states attorney\'s office', 'u.s. attorneys office', 'us attorneys office', 'united states attorneys office', 'u.s. attorney’s office', 'united states attorney’s office', 'executive office for u.s. attorneys', 'eousa', 'usao'), 'defense', 'U.S. federal prosecutors (justice.gov/usao, OPM data), about 10,400 staff (July 2026)'],
1871
+ ['NOAA', 7, exactly('noaa', 'national oceanic and atmospheric administration', 'noaa fisheries', 'national marine fisheries service', 'national weather service', 'noaa national weather service', 'national hurricane center', 'noaa corps'), 'defense', 'U.S. science agency (noaa.gov, OPM data), about 9,800 staff (July 2026)'],
1872
+ ['NIST', 7, exactly('nist', 'national institute of standards and technology'), 'defense', 'U.S. standards lab (nist.gov, OPM data), about 3,200 staff (July 2026)'],
1873
+ ['Census Bureau', 7, exactly('census bureau', 'u.s. census bureau', 'us census bureau', 'united states census bureau', 'bureau of the census', 'u.s. bureau of the census'), 'defense', 'U.S. statistical agency (census.gov, OPM data), about 10,900 staff (July 2026)'],
1874
+ ['USPTO', 7, exactly('uspto', 'united states patent and trademark office', 'u.s. patent and trademark office', 'us patent and trademark office', 'patent and trademark office', 'u.s. patent office', 'us patent office', 'united states patent office'), 'defense', 'U.S. patent office (uspto.gov, OPM data), about 13,500 staff (July 2026)'],
1875
+ ['EPA', 7, exactly('epa', 'u.s. environmental protection agency', 'us environmental protection agency', 'united states environmental protection agency', 'environmental protection agency', 'u.s. epa', 'us epa'), 'defense', 'U.S. environmental agency (epa.gov, OPM data), about 12,500 staff (July 2026)'],
1876
+ ['U.S. Securities and Exchange Commission', 7, exactly('u.s. securities and exchange commission', 'us securities and exchange commission', 'united states securities and exchange commission', 'u.s. sec', 'us sec'), 'finance', 'U.S. securities regulator (sec.gov, OPM data), about 3,900 staff (July 2026)'],
1877
+ ['Federal Trade Commission', 7, exactly('federal trade commission', 'ftc', 'u.s. federal trade commission', 'us federal trade commission', 'united states federal trade commission', 'u.s. ftc', 'us ftc'), 'defense', 'U.S. consumer-protection regulator (ftc.gov, OPM data), about 1,000 staff (July 2026)'],
1878
+ ['Federal Communications Commission', 7, exactly('federal communications commission', 'u.s. federal communications commission', 'us federal communications commission', 'united states federal communications commission', 'u.s. fcc', 'us fcc'), 'defense', 'U.S. communications regulator (fcc.gov, OPM data), about 1,200 staff (July 2026)'],
1879
+ ['Federal Reserve Board', 7, exactly('federal reserve board', 'federal reserve board of governors', 'u.s. federal reserve board'), 'finance', 'U.S. central bank board (federalreserve.gov), 3,057 authorized positions (2025 budget)'],
1880
+ ['FDIC', 7, exactly('fdic', 'federal deposit insurance'), 'finance', 'U.S. bank regulator (fdic.gov, OPM data), about 5,000 staff (July 2026)'],
1881
+ ['GAO', 7, exactly('gao', 'u.s. government accountability office', 'us government accountability office', 'united states government accountability office', 'government accountability office', 'u.s. gao', 'us gao', 'general accounting office', 'u.s. general accounting office'), 'defense', 'U.S. legislative audit agency (gao.gov budget request), about 3,300 staff (FY2026)'],
1882
+ ['Library of Congress', 7, exactly('library of congress', 'u.s. library of congress', 'us library of congress', 'congressional research service', 'u.s. copyright office', 'united states copyright office'), 'nonprofit', 'U.S. national library (loc.gov), 3,238 permanent staff (FY2023)'],
1883
+ ['Smithsonian Institution', 7, exactly('smithsonian institution', 'smithsonian', 'smithsonian institute', 'national air and space museum', 'national museum of american history', 'smithsonian\'s national zoo', 'smithsonian tropical research institute', 'smithsonian astrophysical observatory', 'smithsonian environmental research center', 'smithsonian american art museum'), 'nonprofit', 'U.S. museum and research institution (si.edu), 6,343 federal and trust staff (September 2025)'],
1884
+ ['USAID', 7, exactly('usaid', 'united states agency for international development', 'u.s. agency for international development', 'us agency for international development', 'agency for international development'), 'defense', 'U.S. foreign-aid agency, closed 2025 (usaid.gov, OPM data), more than 10,000 staff before 2025'],
1885
+ ['Peace Corps', 7, exactly('peace corps', 'u.s. peace corps', 'us peace corps', 'united states peace corps', 'peace corps response'), 'defense', 'U.S. volunteer agency (peacecorps.gov, OPM data), about 600 staff and 3,300 volunteers (2025-26)'],
1886
+ ['National Park Service', 7, exactly('national park service', 'u.s. national park service', 'us national park service', 'united states national park service'), 'defense', 'U.S. parks agency (nps.gov, OPM data), about 19,000 staff (July 2026)'],
1887
+ ['USGS', 7, exactly('usgs', 'u.s. geological survey', 'us geological survey', 'united states geological survey'), 'defense', 'U.S. science agency (usgs.gov, OPM data), about 5,900 staff (July 2026)'],
1888
+ ['U.S. Fish and Wildlife Service', 7, exactly('u.s. fish and wildlife service', 'us fish and wildlife service', 'united states fish and wildlife service', 'fish and wildlife service', 'usfws', 'u.s. fish & wildlife service', 'us fish & wildlife service'), 'defense', 'U.S. wildlife agency (fws.gov, OPM data), about 6,300 staff (July 2026)'],
1889
+ ['Bureau of Land Management', 7, exactly('bureau of land management', 'u.s. bureau of land management', 'us bureau of land management'), 'defense', 'U.S. land agency (blm.gov, OPM data), about 5,800 staff (July 2026)'],
1890
+ ['National Science Foundation', 7, exactly('national science foundation', 'u.s. national science foundation', 'us national science foundation', 'u.s. nsf', 'us nsf'), 'defense', 'U.S. science-funding agency (nsf.gov, OPM data), about 1,100 staff (July 2026)'],
1891
+ ['General Services Administration', 7, exactly('general services administration', 'u.s. general services administration', 'us general services administration', 'united states general services administration', 'u.s. gsa', 'us gsa'), 'defense', 'U.S. federal agency (gsa.gov, OPM data), about 8,200 staff (July 2026)'],
1892
+ ['U.S. Small Business Administration', 7, exactly('u.s. small business administration', 'us small business administration', 'united states small business administration', 'small business administration', 'u.s. sba', 'us sba'), 'defense', 'U.S. federal agency (sba.gov, OPM data), about 5,100 staff (July 2026)'],
1893
+ ['Cybersecurity and Infrastructure Security Agency', 7, exactly('cybersecurity and infrastructure security agency', 'cybersecurity & infrastructure security agency', 'u.s. cisa', 'us cisa', 'dhs cisa'), 'defense', 'U.S. cybersecurity agency (cisa.gov, OPM data), about 2,200 staff (July 2026)'],
1894
+ ['NNSA', 7, exactly('nnsa', 'national nuclear security administration', 'u.s. national nuclear security administration'), 'defense', 'U.S. nuclear-security agency (energy.gov/nnsa, Wikipedia), 2,600+ federal staff (2024)'],
1895
+ ['Tennessee Valley Authority', 7, exactly('tennessee valley authority'), 'defense', 'U.S. federal power corporation (tva.com annual report), more than 10,600 employees (FY2025)'],
1896
+ ['The White House', 7, exactly('white house office', 'u.s. executive office of the president', 'us executive office of the president'), 'defense', 'U.S. Executive Office of the President (whitehouse.gov annual staff report), 411 staff (July 2026)'],
1897
+ ['U.S. Senate', 7, exactly('u.s. senate', 'united states senate', 'us senate', 'senate of the united states'), 'defense', 'U.S. legislative chamber (senate.gov, CRS R43946), 6,019 staff (2022)'],
1898
+ ['U.S. House of Representatives', 7, exactly('u.s. house of representatives', 'us house of representatives', 'united states house of representatives', 'u.s. house'), 'defense', 'U.S. legislative chamber (house.gov, CRS R43947), 9,247 staff (2023)'],
1899
+ ['U.S. Congress', 7, exactly('u.s. congress', 'us congress', 'united states congress', 'congress of the united states'), 'defense', 'U.S. legislature (congress.gov, CRS), about 15,000 staff (2022-23)'],
1900
+ ['U.S. Courts', 7, exactly('u.s. courts', 'us courts', 'united states courts', 'u.s. district court', 'us district court', 'united states district court', 'u.s. court of appeals', 'us court of appeals', 'united states court of appeals', 'u.s. bankruptcy court', 'us bankruptcy court', 'united states bankruptcy court', 'u.s. court of federal claims', 'us court of federal claims', 'united states court of federal claims', 'u.s. court of international trade', 'u.s. probation office', 'united states probation office', 'u.s. probation and pretrial services', 'federal public defender', 'office of the federal public defender'), 'defense', 'U.S. federal judiciary (uscourts.gov), more than 32,000 staff (2026)'],
1901
+ ['Supreme Court of the United States', 7, exactly('supreme court of the united states', 'u.s. supreme court', 'us supreme court', 'united states supreme court', 'scotus'), 'defense', 'U.S. Supreme Court (supremecourt.gov), more than 500 staff (2026)'],
1902
+ ['Los Alamos National Laboratory', 7, exactly('los alamos national laboratory', 'los alamos national lab', 'los alamos national labs', 'lanl', 'triad national security', 'los alamos national security'), 'defense', 'U.S. national laboratory (lanl.gov economic impact report), about 16,500 workers (FY2025)'],
1903
+ ['Lawrence Livermore National Laboratory', 7, exactly('lawrence livermore national laboratory', 'lawrence livermore national lab', 'lawrence livermore', 'llnl', 'lawrence livermore lab', 'livermore lab', 'lawrence livermore national security'), 'defense', 'U.S. national laboratory (llnl.gov), about 9,000 staff (2025)'],
1904
+ ['Sandia National Laboratories', 7, exactly('sandia national laboratories', 'sandia national laboratory', 'sandia national labs', 'sandia national lab', 'sandia labs', 'sandia laboratories', 'ntess'), 'defense', 'U.S. national laboratory (sandia.gov facts and figures), about 16,300 staff (FY2025)'],
1905
+ ['Oak Ridge National Laboratory', 7, exactly('oak ridge national laboratory', 'oak ridge national lab', 'ornl', 'ut-battelle'), 'defense', 'U.S. national laboratory (ornl.gov), more than 7,000 staff (2026)'],
1906
+ ['Argonne National Laboratory', 7, exactly('argonne national laboratory', 'argonne national lab', 'argonne', 'uchicago argonne'), 'defense', 'U.S. national laboratory (anl.gov), 3,836 employees (FY2024)'],
1907
+ ['Jet Propulsion Laboratory', 7, exactly('jet propulsion laboratory', 'jet propulsion lab', 'jpl', 'caltech jpl', 'jpl caltech'), 'defense', 'NASA research center run by Caltech (jpl.nasa.gov, Wikipedia), about 4,500 staff (late 2025)'],
1908
+ ['MIT Lincoln Laboratory', 7, exactly('mit lincoln laboratory', 'mit lincoln lab', 'lincoln laboratory'), 'defense', 'DoD federally funded research center (ll.mit.edu, Wikipedia), about 4,500 staff (FY2024)'],
1909
+ ['Lawrence Berkeley National Laboratory', 7, exactly('lawrence berkeley national laboratory', 'lawrence berkeley national lab', 'lawrence berkeley lab', 'berkeley lab', 'lbnl'), 'defense', 'U.S. national laboratory (DOE Office of Science), about 3,400 employees (2026)'],
1910
+ ['Brookhaven National Laboratory', 7, exactly('brookhaven national laboratory', 'brookhaven national lab', 'brookhaven lab', 'brookhaven science associates'), 'defense', 'U.S. national laboratory (DOE Office of Science), about 3,000 employees (2026)'],
1911
+ ['Pacific Northwest National Laboratory', 7, exactly('pacific northwest national laboratory', 'pacific northwest national lab', 'pnnl'), 'defense', 'U.S. national laboratory (pnnl.gov, Wikipedia), about 6,100 staff (2026)'],
1912
+ ['Idaho National Laboratory', 7, exactly('idaho national laboratory', 'idaho national lab', 'inl', 'battelle energy alliance'), 'defense', 'U.S. national laboratory (inl.gov, Wikipedia), about 5,700 staff (2023)'],
1913
+ ['NREL', 7, exactly('nrel', 'national renewable energy laboratory', 'national renewable energy lab', 'national laboratory of the rockies'), 'defense', 'U.S. national laboratory (nrel.gov, Wikipedia), about 3,700 staff (FY2025)'],
1914
+ ['Fermilab', 7, exactly('fermilab', 'fermi national accelerator laboratory', 'fnal', 'fermi research alliance', 'fermiforward discovery group'), 'defense', 'U.S. national laboratory (DOE Office of Science), about 1,800 employees (2026)'],
1915
+ ['SLAC', 7, exactly('slac', 'slac national accelerator laboratory', 'slac national accelerator lab', 'stanford linear accelerator center'), 'defense', 'U.S. national laboratory (DOE Office of Science), about 1,700 employees (2026)'],
1916
+ ['Johns Hopkins APL', 7, exactly('johns hopkins apl', 'johns hopkins applied physics laboratory', 'johns hopkins applied physics lab', 'jhu apl', 'jhuapl'), 'defense', 'DoD university-affiliated research center (jhuapl.edu, Wikipedia), about 8,800 staff (2025)'],
1917
+ // U.S. News Best National Universities, 2025 edition: ranks 21–100
1918
+ ['Carnegie Mellon University', 7, university('carnegie mellon university|carnegie mellon'), 'education', 'U.S. News Best National Universities, 2025 edition: #21'],
1919
+ ['University of Michigan', 7, university('university of michigan|university of michigan-ann arbor|university of michigan ann arbor|umich'), 'education', 'U.S. News Best National Universities, 2025 edition: #21'],
1920
+ ['Washington University in St. Louis', 7, university('washington university in st\\. louis|washington university in st louis|washington university in saint louis|washington university|washu|wash u|wustl'), 'education', 'U.S. News Best National Universities, 2025 edition: #21'],
1921
+ ['Emory University', 7, university('emory university|emory'), 'education', 'U.S. News Best National Universities, 2025 edition: #24'],
1922
+ ['Georgetown University', 7, university('georgetown university|georgetown|georgetown law|georgetown university law center'), 'education', 'U.S. News Best National Universities, 2025 edition: #24'],
1923
+ ['University of Virginia', 7, university('university of virginia'), 'education', 'U.S. News Best National Universities, 2025 edition: #24'],
1924
+ ['UNC Chapel Hill', 7, university('unc chapel hill|university of north carolina-chapel hill|university of north carolina chapel hill|unc-chapel hill|unc-ch'), 'education', 'U.S. News Best National Universities, 2025 edition: #27'],
1925
+ ['University of Southern California', 7, university('university of southern california'), 'education', 'U.S. News Best National Universities, 2025 edition: #27'],
1926
+ ['New York University', 7, university('new york university|nyu'), 'education', 'U.S. News Best National Universities, 2025 edition: #30'],
1927
+ ['University of Texas at Austin', 7, university('university of texas at austin|university of texas-austin|university of texas austin|ut austin|ut-austin'), 'education', 'U.S. News Best National Universities, 2025 edition: #30'],
1928
+ ['Georgia Tech', 7, university('georgia tech|georgia institute of technology|gatech'), 'education', 'U.S. News Best National Universities, 2025 edition: #33'],
1929
+ ['UC Davis', 7, university('uc davis|university of california davis|university of california-davis|u\\.c\\. davis'), 'education', 'U.S. News Best National Universities, 2025 edition: #33'],
1930
+ ['University of Illinois Urbana-Champaign', 7, university('university of illinois urbana-champaign|university of illinois at urbana-champaign|university of illinois urbana champaign|uiuc'), 'education', 'U.S. News Best National Universities, 2025 edition: #33'],
1931
+ ['Boston College', 7, university('boston college'), 'education', 'U.S. News Best National Universities, 2025 edition: #37'],
1932
+ ['University of Wisconsin-Madison', 7, university('university of wisconsin-madison|university of wisconsin madison|uw-madison|uw madison'), 'education', 'U.S. News Best National Universities, 2025 edition: #39'],
1933
+ ['Boston University', 7, university('boston university'), 'education', 'U.S. News Best National Universities, 2025 edition: #41'],
1934
+ ['Ohio State University', 7, university('ohio state university|ohio state'), 'education', 'U.S. News Best National Universities, 2025 edition: #41'],
1935
+ ['Rutgers University-New Brunswick', 7, university('rutgers university-new brunswick|rutgers university new brunswick|rutgers-new brunswick|rutgers new brunswick'), 'education', 'U.S. News Best National Universities, 2025 edition: #41'],
1936
+ ['University of Maryland College Park', 7, university('university of maryland college park|university of maryland-college park|university of maryland at college park|umcp'), 'education', 'U.S. News Best National Universities, 2025 edition: #44'],
1937
+ ['University of Rochester', 7, university('university of rochester'), 'education', 'U.S. News Best National Universities, 2025 edition: #44'],
1938
+ ['Lehigh University', 7, university('lehigh university|lehigh'), 'education', 'U.S. News Best National Universities, 2025 edition: #46'],
1939
+ ['Purdue University', 7, university('purdue university|purdue|purdue university west lafayette|purdue university-west lafayette'), 'education', 'U.S. News Best National Universities, 2025 edition: #46'],
1940
+ ['University of Georgia', 7, university('university of georgia'), 'education', 'U.S. News Best National Universities, 2025 edition: #46'],
1941
+ ['University of Washington', 7, university('university of washington|university of washington seattle|university of washington-seattle|uw seattle'), 'education', 'U.S. News Best National Universities, 2025 edition: #46'],
1942
+ ['Wake Forest University', 7, university('wake forest university|wake forest'), 'education', 'U.S. News Best National Universities, 2025 edition: #46'],
1943
+ ['Case Western Reserve University', 6, university('case western reserve university|case western|cwru'), 'education', 'U.S. News Best National Universities, 2025 edition: #51'],
1944
+ ['Texas A&M University', 6, university('texas a&m university|texas a&m|texas a&m university-college station|texas a&m university college station|tamu'), 'education', 'U.S. News Best National Universities, 2025 edition: #51'],
1945
+ ['Virginia Tech', 6, university('virginia tech|virginia polytechnic institute'), 'education', 'U.S. News Best National Universities, 2025 edition: #51'],
1946
+ ['Florida State University', 6, university('florida state university|florida state'), 'education', 'U.S. News Best National Universities, 2025 edition: #54'],
1947
+ ['Northeastern University', 6, university('northeastern university|northeastern'), 'education', 'U.S. News Best National Universities, 2025 edition: #54'],
1948
+ ['William & Mary', 6, university('william & mary|college of william & mary|college of william and mary|william and mary|w&m'), 'education', 'U.S. News Best National Universities, 2025 edition: #54'],
1949
+ ['North Carolina State University', 6, university('north carolina state university|nc state university|nc state|n\\.c\\. state|ncsu'), 'education', 'U.S. News Best National Universities, 2025 edition: #58'],
1950
+ ['Stony Brook University', 6, university('stony brook university|stony brook|suny stony brook|stony brook university-suny'), 'education', 'U.S. News Best National Universities, 2025 edition: #58'],
1951
+ ['UC Merced', 6, university('uc merced|university of california merced|university of california-merced'), 'education', 'U.S. News Best National Universities, 2025 edition: #58'],
1952
+ ['UMass Amherst', 6, university('umass amherst|university of massachusetts amherst|university of massachusetts-amherst|umass-amherst'), 'education', 'U.S. News Best National Universities, 2025 edition: #58'],
1953
+ ['Villanova University', 6, university('villanova university|villanova'), 'education', 'U.S. News Best National Universities, 2025 edition: #58'],
1954
+ ['Brandeis University', 6, exactly('brandeis university', 'brandeis'), 'education', 'U.S. News Best National Universities, 2025 edition: #63'],
1955
+ ['George Washington University', 6, university('george washington university'), 'education', 'U.S. News Best National Universities, 2025 edition: #63'],
1956
+ ['Michigan State University', 6, university('michigan state university|michigan state'), 'education', 'U.S. News Best National Universities, 2025 edition: #63'],
1957
+ ['Penn State', 6, university('penn state|pennsylvania state university|pennsylvania state university-university park|penn state university park|penn state university'), 'education', 'U.S. News Best National Universities, 2025 edition: #63'],
1958
+ ['Santa Clara University', 6, university('santa clara university'), 'education', 'U.S. News Best National Universities, 2025 edition: #63'],
1959
+ ['Tulane University', 6, university('tulane university|tulane'), 'education', 'U.S. News Best National Universities, 2025 edition: #63'],
1960
+ ['University of Miami', 6, university('university of miami'), 'education', 'U.S. News Best National Universities, 2025 edition: #63'],
1961
+ ['Rensselaer Polytechnic Institute', 6, university('rensselaer polytechnic institute|rensselaer|rpi'), 'education', 'U.S. News Best National Universities, 2025 edition: #70'],
1962
+ ['University of Connecticut', 6, university('university of connecticut|uconn'), 'education', 'U.S. News Best National Universities, 2025 edition: #70'],
1963
+ ['University of Pittsburgh', 6, university('university of pittsburgh|pitt'), 'education', 'U.S. News Best National Universities, 2025 edition: #70'],
1964
+ ['Binghamton University', 6, university('binghamton university|binghamton university-suny|suny binghamton|binghamton'), 'education', 'U.S. News Best National Universities, 2025 edition: #73'],
1965
+ ['Indiana University Bloomington', 6, university('indiana university bloomington|indiana university-bloomington|iu bloomington|indiana university'), 'education', 'U.S. News Best National Universities, 2025 edition: #73'],
1966
+ ['Syracuse University', 6, university('syracuse university|syracuse'), 'education', 'U.S. News Best National Universities, 2025 edition: #73'],
1967
+ ['Colorado School of Mines', 6, university('colorado school of mines|colorado mines'), 'education', 'U.S. News Best National Universities, 2025 edition: #76'],
1968
+ ['Stevens Institute of Technology', 6, university('stevens institute of technology'), 'education', 'U.S. News Best National Universities, 2025 edition: #76'],
1969
+ ['University at Buffalo', 6, university('university at buffalo|university at buffalo-suny|suny buffalo|suny at buffalo|university of buffalo'), 'education', 'U.S. News Best National Universities, 2025 edition: #76'],
1970
+ ['UC Riverside', 6, university('uc riverside|university of california riverside|university of california-riverside'), 'education', 'U.S. News Best National Universities, 2025 edition: #76'],
1971
+ ['Clemson University', 6, university('clemson university|clemson'), 'education', 'U.S. News Best National Universities, 2025 edition: #80'],
1972
+ ['Pepperdine University', 6, university('pepperdine university|pepperdine'), 'education', 'U.S. News Best National Universities, 2025 edition: #80'],
1973
+ ['Rutgers University-Newark', 6, university('rutgers university-newark|rutgers university newark|rutgers-newark|rutgers newark'), 'education', 'U.S. News Best National Universities, 2025 edition: #80'],
1974
+ ['University of Illinois Chicago', 6, university('university of illinois chicago|university of illinois at chicago|university of illinois-chicago'), 'education', 'U.S. News Best National Universities, 2025 edition: #80'],
1975
+ ['New Jersey Institute of Technology', 6, university('new jersey institute of technology|njit'), 'education', 'U.S. News Best National Universities, 2025 edition: #84'],
1976
+ ['UC Santa Cruz', 6, university('uc santa cruz|university of california santa cruz|university of california-santa cruz'), 'education', 'U.S. News Best National Universities, 2025 edition: #84'],
1977
+ ['Drexel University', 6, university('drexel university|drexel'), 'education', 'U.S. News Best National Universities, 2025 edition: #86'],
1978
+ ['Howard University', 6, university('howard university'), 'education', 'U.S. News Best National Universities, 2025 edition: #86'],
1979
+ ['Marquette University', 6, university('marquette university|marquette'), 'education', 'U.S. News Best National Universities, 2025 edition: #86'],
1980
+ ['University of Delaware', 6, university('university of delaware|udel'), 'education', 'U.S. News Best National Universities, 2025 edition: #86'],
1981
+ ['Worcester Polytechnic Institute', 6, university('worcester polytechnic institute|wpi'), 'education', 'U.S. News Best National Universities, 2025 edition: #86'],
1982
+ ['American University', 6, university('american university'), 'education', 'U.S. News Best National Universities, 2025 edition: #91'],
1983
+ ['Baylor University', 6, university('baylor university'), 'education', 'U.S. News Best National Universities, 2025 edition: #91'],
1984
+ ['Fordham University', 6, university('fordham university|fordham'), 'education', 'U.S. News Best National Universities, 2025 edition: #91'],
1985
+ ['Loyola Marymount University', 6, university('loyola marymount university|loyola marymount'), 'education', 'U.S. News Best National Universities, 2025 edition: #91'],
1986
+ ['Rochester Institute of Technology', 6, university('rochester institute of technology|rit'), 'education', 'U.S. News Best National Universities, 2025 edition: #91'],
1987
+ ['Southern Methodist University', 6, university('southern methodist university'), 'education', 'U.S. News Best National Universities, 2025 edition: #91'],
1988
+ ['Florida International University', 6, university('florida international university|fiu'), 'education', 'U.S. News Best National Universities, 2025 edition: #98'],
1989
+ ['Gonzaga University', 6, university('gonzaga university|gonzaga'), 'education', 'U.S. News Best National Universities, 2025 edition: #98'],
1990
+ ['Rutgers University-Camden', 6, university('rutgers university-camden|rutgers university camden|rutgers-camden|rutgers camden'), 'education', 'U.S. News Best National Universities, 2025 edition: #98'],
1991
+ ['Temple University', 6, university('temple university'), 'education', 'U.S. News Best National Universities, 2025 edition: #98'],
1992
+ ['University of Colorado Boulder', 6, university('university of colorado boulder|university of colorado at boulder|university of colorado-boulder|cu boulder|cu-boulder'), 'education', 'U.S. News Best National Universities, 2025 edition: #98'],
1993
+ ['University of Iowa', 6, university('university of iowa|uiowa'), 'education', 'U.S. News Best National Universities, 2025 edition: #98'],
1994
+ ['Yeshiva University', 6, university('yeshiva university'), 'education', 'U.S. News Best National Universities, 2025 edition: #98'],
1995
+ // ── end of the public lists ──
1996
+ ];
1997
+
418
1998
  const JUNK_COMPANY = /^(self[-\s]?employed|freelance|various|multiple|confidential|n\/a|none|tbd|open to work|looking|seeking)$/i;
419
1999
  // "at scale", "at the intersection of…", "at heart", "at home", "at best",
420
2000
  // "at best-in-class companies": phrases, not employers. The Home Depot, Home
@@ -453,11 +2033,17 @@ const PLATFORMS = new Set(['tech', 'media', 'entertainment']);
453
2033
 
454
2034
  /** A company name as people write it → one clean, canonical name (or null). */
455
2035
  export function cleanCompany(raw) {
2036
+ // NFKC first: styled letters ("𝗠𝗶𝗰𝗿𝗼𝘀𝗼𝗳𝘁") and full-width punctuation ("|")
2037
+ // become plain ones. Private-use glyphs go with the emoji: the Apple logo
2038
+ // () after "Apple" used to leave it unread.
456
2039
  let s = String(raw || '')
457
- .replace(/[\p{Extended_Pictographic}\u{FE0F}‍]/gu, '')
2040
+ .normalize('NFKC')
2041
+ .replace(/[\p{Extended_Pictographic}\p{Co}\u{FE0F}‍]/gu, '')
458
2042
  .split(/\s*(?:\||•|·| – | — | - |!|\(|\/| {2,})\s*/)[0]
459
2043
  .split(NAME_END)[0]
460
- .replace(/[\s,.:;'"]+$/, '');
2044
+ .replace(/[\s,.:;'"]+$/, '')
2045
+ // A class year ("UCF ’26", "UF '28") is a student's; the school is the name.
2046
+ .replace(/\s+['’‘]\d{2}$/, '');
461
2047
  if (!WHOLE_NAME.test(s)) s = s.replace(LEGAL_FORM, '');
462
2048
  s = s.trim();
463
2049
  if (!s || s.length < 2 || JUNK_COMPANY.test(s) || NOT_A_COMPANY.test(s)) return null;
@@ -467,44 +2053,53 @@ export function cleanCompany(raw) {
467
2053
  const school = SCHOOL_NAME.test(lower);
468
2054
  const notStaff = NOT_ITS_STAFF.test(bare);
469
2055
  const platformRole = PLATFORM_ROLE.test(bare);
470
- for (const [name, , alias, industry] of KNOWN_COMPANIES) {
471
- if (school && industry !== 'education') continue;
472
- if (lower === name.toLowerCase()) return name;
473
- if (notStaff || (platformRole && PLATFORMS.has(industry))) continue;
474
- if (alias.test(lower) || alias.test(bare)) return name;
2056
+ // The curated list, then the public dataset: a name either one claims.
2057
+ for (const list of [KNOWN_COMPANIES, COMPANY_DATA]) {
2058
+ for (const [name, , alias, industry] of list) {
2059
+ if (school && industry !== 'education') continue;
2060
+ if (lower === name.toLowerCase()) return name;
2061
+ if (notStaff || (platformRole && PLATFORMS.has(industry))) continue;
2062
+ if (alias.test(lower) || alias.test(bare)) return name;
2063
+ }
475
2064
  }
476
2065
  return s;
477
2066
  }
478
2067
 
479
2068
  const KNOWN_BY_NAME = new Map(KNOWN_COMPANIES.map(([name, score]) => [name, score]));
480
- const KNOWN_INDUSTRY = new Map(KNOWN_COMPANIES.map(([name, , , industry]) => [name, industry]));
2069
+ const DATA_BY_NAME = new Map(COMPANY_DATA.map(([name, score]) => [name, score]));
2070
+ // Industries from both lists: a dataset company's own, like a curated one's.
2071
+ const KNOWN_INDUSTRY = new Map([...KNOWN_COMPANIES, ...COMPANY_DATA].map(([name, , , industry]) => [name, industry]));
481
2072
 
482
2073
  const isKnownCompany = (text) => {
483
2074
  const c = cleanCompany(text);
484
- return !!c && KNOWN_BY_NAME.has(c);
2075
+ return !!c && (KNOWN_BY_NAME.has(c) || DATA_BY_NAME.has(c));
485
2076
  };
486
2077
 
487
2078
  /**
488
2079
  * Each role with its company filled in where the headline didn't say: a
489
2080
  * company scan's company, else the stored company (unless that company is
490
- * only mentioned in an "Ex-" part), goes to the first current role.
2081
+ * only mentioned in an "Ex-" part), goes to the first current role that is a
2082
+ * title (an audience has no employer). A company scan's company also goes
2083
+ * before one only inferred from the headline (readRoles); the stored one,
2084
+ * which ingest reads from the headline's "at", doesn't.
491
2085
  */
492
2086
  export function rolesWithCompanies(row) {
493
2087
  const roles = readRoles(row?.headline, row?.role);
494
- const fill = cleanCompany(row?.scanned_company) || (() => {
2088
+ const scanned = cleanCompany(row?.scanned_company);
2089
+ const fill = scanned || (() => {
495
2090
  const stored = cleanCompany(row?.company);
496
2091
  return stored && !roles.some((r) => r.former && r.company === stored) ? stored : null;
497
2092
  })();
498
- const first = roles.find((r) => !r.former);
499
- if (fill && first && !first.company) first.company = fill;
2093
+ const first = roles.find((r) => !r.former && !r.audience);
2094
+ if (fill && first && (!first.company || (scanned && first.inferred))) first.company = fill;
500
2095
  if (fill && !first) roles.unshift({ title: { ...LEVELS.unknown }, company: fill, former: false, part: '' });
501
2096
  if (!roles.length) roles.push({ title: { ...LEVELS.unknown }, company: null, former: false, part: '' });
502
2097
  return roles;
503
2098
  }
504
2099
 
505
- /** The company a person works at now (their first current role's). */
2100
+ /** The company a person works at now (their first current title's). */
506
2101
  export function currentCompany(row) {
507
- return rolesWithCompanies(row).find((r) => !r.former)?.company || null;
2102
+ return rolesWithCompanies(row).find((r) => !r.former && !r.audience)?.company || null;
508
2103
  }
509
2104
 
510
2105
  function companyIn(part = '') {
@@ -655,11 +2250,20 @@ function leanToward(base, industry, industryFrom, sectors, sectorIndustries, foc
655
2250
  return { ...base, score, base: base.score, sector: pick, sectorBonus: score - base.score };
656
2251
  }
657
2252
 
2253
+ // A company the list doesn't know, or none found at all, is the middle of the
2254
+ // scale: not knowing a company says nothing about how big it is, so it neither
2255
+ // lifts someone's title nor sinks it. Until scoring 4 an unknown company was 4
2256
+ // and no company 3, which pushed down everyone the curated list doesn't know:
2257
+ // most of a network outside big tech, and founders who write only their
2258
+ // company's name. How many of your people work there still nudges it up.
2259
+ export const UNKNOWN_COMPANY = 5;
2260
+
658
2261
  /**
659
2262
  * A company's score and where it came from.
660
2263
  * yours you set it
661
2264
  * known the curated list above
662
- * network unknown to the list; nudged up when several of your people work there
2265
+ * data the public company dataset (COMPANY_DATA): 6 to 8, from public facts
2266
+ * network unknown to both; nudged up when several of your people work there
663
2267
  * default unknown, and few of your people there
664
2268
  * none no company found for this person
665
2269
  * With a sector focus, a company in one of your sectors gets +1 or +2 on top
@@ -673,21 +2277,22 @@ function leanToward(base, industry, industryFrom, sectors, sectorIndustries, foc
673
2277
  * read of the network.
674
2278
  */
675
2279
  export function companyScore(name, { overrides = new Map(), headcount = 0, industry, industryFrom, sectors, sectorIndustries, focus } = {}) {
676
- if (!name) return { score: 3, source: 'none' };
2280
+ if (!name) return { score: UNKNOWN_COMPANY, source: 'none' };
677
2281
  if (overrides.has(name)) return { score: overrides.get(name), source: 'yours' };
678
2282
  const ind = industry ?? KNOWN_INDUSTRY.get(name);
679
2283
  let base;
680
2284
  if (KNOWN_BY_NAME.has(name)) base = { score: KNOWN_BY_NAME.get(name), source: 'known' };
2285
+ else if (DATA_BY_NAME.has(name)) base = { score: DATA_BY_NAME.get(name), source: 'data' };
681
2286
  else if (ind !== 'education' && headcount >= 15) base = { score: 6, source: 'network' };
682
- else if (ind !== 'education' && headcount >= 5) base = { score: 5, source: 'network' };
683
- else base = { score: 4, source: 'default' };
2287
+ else if (ind !== 'education' && headcount >= 5) base = { score: 5.5, source: 'network' };
2288
+ else base = { score: UNKNOWN_COMPANY, source: 'default' };
684
2289
  return focus ? leanToward(base, ind, industryFrom, sectors, sectorIndustries, focus) : base;
685
2290
  }
686
2291
 
687
2292
  /**
688
2293
  * A company's score from a read of the network (readNetwork): its headcount,
689
2294
  * industry and where that came from, and its sectors, as scoreNetwork scores
690
- * it. Rescoring, Settings' preview and Paths → Scores all score a company
2295
+ * it. Rescoring, Settings' preview and the Scores tab all score a company
691
2296
  * through this, so they give it the same score.
692
2297
  */
693
2298
  export function companyScoreIn(read, name, { overrides, focus } = {}) {
@@ -722,7 +2327,7 @@ const BONUSES = [
722
2327
  [/\b(angel investor|investor|venture capital(ist)?|vc|general partner|limited partner)\b(?! relations)/i, 1, 'investor'],
723
2328
  [/\by ?combinator\b|\(yc\)|\byc\b ?[wsfx]?\d{0,2}\b/i, 1, 'YC'],
724
2329
  [/\b30 under 30\b/i, 1, '30 under 30'],
725
- [/\b\d[\d.,]*\s?(m|b|million|billion)\+?\s*(views|followers|subscribers|impressions|users|downloads|installs|listeners|students|customers|members|reach)\b|\$?\s?\d[\d.,]*\s?(m|b|million|billion)\+?\s*(in )?(sales|revenue|arr|gmv|raised|funding)\b|\braised \$?\s?\d[\d.,]*\s?(m|b|million|billion)\b/i, 0.75, 'reach in the millions'],
2330
+ [/\b(\d[\d.,]*\s?(m|b|million|billion)|\d{1,3}(,\d{3}){2,})\+?\s*(views|followers|subscribers|impressions|users|downloads|installs|listeners|students|customers|members|reach)\b|\$?\s?\d[\d.,]*\s?(m|b|million|billion)\+?\s*(in )?(sales|revenue|arr|gmv|raised|funding)\b|\braised \$?\s?\d[\d.,]*\s?(m|b|million|billion)\b/i, 0.75, 'reach in the millions'],
726
2331
  [new RegExp(String.raw`\b(tedx?|keynote|patents?|author of|best[-\s]?selling|award[-\s]winning|prize[-\s]winning|${HONOURS})\b`, 'i'), 0.5, 'recognition'],
727
2332
  ];
728
2333
 
@@ -737,8 +2342,9 @@ function readReach(headline = '') {
737
2342
  /**
738
2343
  * Bonus points from signals in the headline, capped at 1.5, with the reasons.
739
2344
  * Headlines are self-written: claims from someone at a company nobody knows
740
- * (company score 4 or less) count half. `found` is the headline's readReach(),
741
- * when it has been read already.
2345
+ * (company score 4 or less; scorePerson passes 4 for a company we don't know,
2346
+ * whatever its neutral score) count half. `found` is the headline's
2347
+ * readReach(), when it has been read already.
742
2348
  */
743
2349
  export function reachBonus(headline = '', companyScoreValue = 10, found = readReach(headline)) {
744
2350
  let { points } = found;
@@ -762,12 +2368,17 @@ export const RULE_TABLES = {
762
2368
  club: CLUB, shortNameClub: SHORT_NAME_CLUB, fieldAssociation: FIELD_ASSOCIATION, grownUp: GROWN_UP, former: FORMER,
763
2369
  junkCompany: JUNK_COMPANY, notACompany: NOT_A_COMPANY, nameEnd: NAME_END, legalForm: LEGAL_FORM, wholeName: WHOLE_NAME,
764
2370
  schoolName: SCHOOL_NAME, notItsStaff: NOT_ITS_STAFF, platformRole: PLATFORM_ROLE, platforms: PLATFORMS, bonuses: BONUSES,
2371
+ audience: AUDIENCE, notTheirAudience: NOT_THEIR_AUDIENCE, audienceUnits: UNIT, ownVenture: OWN_VENTURE,
2372
+ affiliation: AFFILIATION, academic: ACADEMIC, retired: RETIRED, retiredOnly: RETIRED_ONLY, officeName: OFFICE_NAME, atCompany: AT_COMPANY, healthOrg: HEALTH_ORG, specialty: SPECIALTY, serviceSchool: SERVICE_SCHOOL,
2373
+ offices: OFFICE_TABLES,
765
2374
  };
766
2375
 
767
2376
  // ── putting it together ──────────────────────────────────────────────────────
768
2377
 
769
- // S is the top ~3–4%: VP and up at strong companies, founders and C-suite at
770
- // known ones, directors only at 10/10 companies.
2378
+ // The fixed scale, the same lines for everyone. In a network like the one it
2379
+ // was tuned on, S is the top ~3–4%: VP and up at strong companies, founders and
2380
+ // C-suite at known ones, directors only at 10/10 companies. In a network the
2381
+ // curated list barely knows (most of them), hardly anyone reaches S or A.
771
2382
  export function tierFor(power) {
772
2383
  if (power >= 7.5) return 'S';
773
2384
  if (power >= 5.5) return 'A';
@@ -776,6 +2387,68 @@ export function tierFor(power) {
776
2387
  return 'D';
777
2388
  }
778
2389
 
2390
+ // Scores → Tiers: graded on your network's curve (the default), or on the
2391
+ // fixed scale above.
2392
+ export const TIER_SCALES = ['curve', 'fixed'];
2393
+ export const TIER_SCALE_SETTING = {
2394
+ default: 'curve',
2395
+ parse(value) {
2396
+ if (TIER_SCALES.includes(value)) return value;
2397
+ throw new Error("Tiers are graded either on your network's curve ('curve') or on the fixed scale ('fixed').");
2398
+ },
2399
+ };
2400
+
2401
+ // The curve: the share of your 1st-degree people at each tier or above. Your
2402
+ // top 3% are S, the next 12% A, the next 25% B, the next 30% C, the rest D:
2403
+ // about where the fixed scale puts a network full of companies it knows.
2404
+ export const CURVE = [['S', 0.03], ['A', 0.15], ['B', 0.4], ['C', 0.7]];
2405
+ // The curve finds the best of any network, but it doesn't lift anyone under
2406
+ // this power (B on the fixed scale) into S or A: in a network of students,
2407
+ // the strongest classmate is B at most.
2408
+ export const CURVE_FLOOR = 4;
2409
+ const TIER_RANK = { D: 0, C: 1, B: 2, A: 3, S: 4 };
2410
+
2411
+ /**
2412
+ * Where each tier starts on this network's curve: the power of the last person
2413
+ * inside each share of `powers` (your 1st-degree people's, before any circle
2414
+ * boost), best first. At least one person reaches each cut-off, so a small
2415
+ * network still has a top. People tied at a cut-off all come in or all stay
2416
+ * out, whichever lands nearer the share (in, when it's as near): a network
2417
+ * where eight people read "Store Manager" at companies nobody knows, all at
2418
+ * the same power, shouldn't put all eight in A to fill two places. Null for an
2419
+ * empty network.
2420
+ */
2421
+ export function curveCutoffs(powers = []) {
2422
+ const best = powers.filter(Number.isFinite).sort((a, b) => b - a);
2423
+ if (!best.length) return null;
2424
+ const cut = {};
2425
+ for (const [tier, share] of CURVE) {
2426
+ const k = Math.max(1, Math.round(best.length * share));
2427
+ const at = best[k - 1];
2428
+ const through = best.filter((p) => p >= at).length; // everyone tied there comes in…
2429
+ const above = best.filter((p) => p > at).length; // …or no one tied there does
2430
+ cut[tier] = above === 0 || through - k <= k - above ? at : best[above - 1];
2431
+ }
2432
+ return cut;
2433
+ }
2434
+
2435
+ /**
2436
+ * A tier graded on the curve: the fixed scale's tier, lifted to the curve's
2437
+ * when that is higher. The curve only lifts, so a strong network keeps its
2438
+ * fixed-scale tiers, and it never lifts anyone under CURVE_FLOOR into S or A.
2439
+ * Without `cutoffs` (the fixed scale chosen, or no network yet), the fixed tier.
2440
+ */
2441
+ export function curvedTier(power, cutoffs) {
2442
+ const fixed = tierFor(power);
2443
+ if (!cutoffs) return fixed;
2444
+ let curve = 'D';
2445
+ if (power >= cutoffs.C) curve = 'C';
2446
+ if (power >= cutoffs.B) curve = 'B';
2447
+ if (power >= cutoffs.A && power >= CURVE_FLOOR) curve = 'A';
2448
+ if (power >= cutoffs.S && power >= CURVE_FLOOR) curve = 'S';
2449
+ return TIER_RANK[curve] > TIER_RANK[fixed] ? curve : fixed;
2450
+ }
2451
+
779
2452
  const round1 = (n) => Math.round(n * 10) / 10;
780
2453
 
781
2454
  export const FORMER_WEIGHT = 0.7;
@@ -814,8 +2487,11 @@ export function scorePerson(row, companyFor = (name) => companyScore(name), read
814
2487
  if (!best || core > best.core) best = { role, co, points, core };
815
2488
  }
816
2489
  // Halved or not by the company's own score, before any sector lean: that you
817
- // like a sector says nothing about whether a self-written claim is true.
818
- const bonus = reachBonus(row?.headline, best.co.base ?? best.co.score, reach);
2490
+ // like a sector says nothing about whether a self-written claim is true. A
2491
+ // company we don't know counts as 4 here, as it did before it became neutral:
2492
+ // not knowing the company doesn't make a self-written claim any truer.
2493
+ const unknown = best.co.source === 'default' || best.co.source === 'none';
2494
+ const bonus = reachBonus(row?.headline, unknown ? 4 : best.co.base ?? best.co.score, reach);
819
2495
  const power = round1(best.core + bonus.points);
820
2496
  const title = { ...best.role.title, former: best.role.former, student, points: round1(best.points) };
821
2497
  if (best.role.former) title.label = `Former ${title.label}`;
@@ -903,9 +2579,13 @@ export function topCompanies(row) {
903
2579
  }
904
2580
 
905
2581
  /**
906
- * A 1st-degree person's boost for a strong mapped circle: up to +1 when the
907
- * share of their circle at A or S is well above normal. Circles under 20
908
- * people are too small to judge.
2582
+ * A 1st-degree person's boost for a strong mapped circle, the larger of:
2583
+ * - its share: up to +1 when the share of their circle at A or S is well
2584
+ * above normal (circles under 20 people are too small to judge a share);
2585
+ * - its strong people: +1 for every 25 at A or S, up to +2, however big the
2586
+ * circle. A big circle's share can look ordinary while it holds more
2587
+ * strong people than most circles have people: that's the hidden power a
2588
+ * vague title doesn't show. Until scoring 6 only the share counted.
909
2589
  */
910
2590
  export function bridgeBoost(circle = []) {
911
2591
  const total = circle.length;
@@ -913,7 +2593,8 @@ export function bridgeBoost(circle = []) {
913
2593
  const aCount = circle.filter((p) => p.tier === 'A').length;
914
2594
  const elitePct = total ? (sCount + aCount) / total : 0;
915
2595
  const circlePower = sCount * 3 + aCount * 1.5 + elitePct * 10 + Math.log(total + 1) * 1.5;
916
- const boost = total >= 20 ? Math.max(0, Math.min(1, (elitePct - 0.12) * 5)) : 0;
2596
+ const byShare = total >= 20 ? Math.max(0, Math.min(1, (elitePct - 0.12) * 5)) : 0;
2597
+ const boost = Math.max(byShare, Math.min(2, (sCount + aCount) / 25));
917
2598
  const isCatalyst = (sCount >= 5 && elitePct >= 0.25) || circlePower >= 50 || (sCount >= 3 && elitePct >= 0.3);
918
2599
  return { boost: round1(boost), total, sCount, aCount, elitePct, circlePower, isCatalyst };
919
2600
  }
@@ -982,14 +2663,20 @@ export function readNetwork(rows = [], { industryOf, sectorsOf, groupOf } = {})
982
2663
  /**
983
2664
  * Score a whole network. People first, with company scores that can use how
984
2665
  * many of your people work at each company and each company's one industry;
985
- * then 1st-degree bridges get their circle boost from their scored circle.
2666
+ * then, with `tierScale` 'curve', everyone is graded on the network's curve,
2667
+ * with cut-offs from the 1st-degree people's scores so far (the app passes
2668
+ * the saved Scores → Tiers, which is the curve unless you chose otherwise;
2669
+ * called without one, a network is graded on the fixed scale); then
2670
+ * 1st-degree bridges get their circle boost from their scored circle, judged
2671
+ * by the tiers you see, and are graded again on the same cut-offs.
986
2672
  * `focus` is the sector focus from Settings, or nothing. `read` is
987
2673
  * readNetwork() of these rows, when they have been read already. Returns one
988
- * result per row id, plus the per-company facts it used and each company's
989
- * score (companyScore(), by name).
2674
+ * result per row id, plus the per-company facts it used, each company's score
2675
+ * (companyScore(), by name) and the curve's cut-offs (null on the fixed scale).
990
2676
  */
991
2677
  export function scoreNetwork(rows = [], {
992
- overrides = new Map(), industryOf, sectorsOf, groupOf, focus, read = readNetwork(rows, { industryOf, sectorsOf, groupOf }),
2678
+ overrides = new Map(), industryOf, sectorsOf, groupOf, focus, tierScale = 'fixed',
2679
+ read = readNetwork(rows, { industryOf, sectorsOf, groupOf }),
993
2680
  } = {}) {
994
2681
  // Each company is scored once; everyone there shares the answer.
995
2682
  const companyScores = new Map();
@@ -999,6 +2686,11 @@ export function scoreNetwork(rows = [], {
999
2686
  };
1000
2687
  const out = new Map();
1001
2688
  for (const r of rows) out.set(r.id, { ...scorePerson(r, companyFor, read.people.get(r)), boost: 0 });
2689
+ // The curve's cut-offs come from your 1st-degree people before any circle
2690
+ // boost, so a boost (which reads the graded tiers) can't move its own cut-off.
2691
+ const cutoffs = tierScale === 'fixed' ? null
2692
+ : curveCutoffs(rows.filter((r) => r.degree !== 2).map((r) => out.get(r.id).power));
2693
+ if (cutoffs) for (const s of out.values()) s.tier = curvedTier(s.power, cutoffs);
1002
2694
  const circles = new Map();
1003
2695
  for (const r of rows) {
1004
2696
  if (r.degree !== 2 || !r.source_connection_id) continue;
@@ -1013,7 +2705,7 @@ export function scoreNetwork(rows = [], {
1013
2705
  s.circle = b;
1014
2706
  s.boost = b.boost;
1015
2707
  s.power = round1(s.power + b.boost);
1016
- s.tier = tierFor(s.power);
2708
+ s.tier = curvedTier(s.power, cutoffs);
1017
2709
  }
1018
- return { scores: out, headcount: read.headcount, industries: read.industries, companyScores };
2710
+ return { scores: out, headcount: read.headcount, industries: read.industries, companyScores, cutoffs };
1019
2711
  }