@classytic/stage 0.2.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 (458) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +5 -1
  3. package/dist/_virtual/_rolldown/runtime.mjs +18 -0
  4. package/dist/assets/index.mjs +0 -1
  5. package/dist/atomic/aufbau.d.mts +144 -0
  6. package/dist/atomic/aufbau.mjs +384 -0
  7. package/dist/atomic/elements.d.mts +67 -0
  8. package/dist/atomic/elements.mjs +785 -0
  9. package/dist/atomic/emission.d.mts +112 -0
  10. package/dist/atomic/emission.mjs +179 -0
  11. package/dist/atomic/index.d.mts +8 -0
  12. package/dist/atomic/index.mjs +9 -0
  13. package/dist/atomic/periodic.d.mts +82 -0
  14. package/dist/atomic/periodic.mjs +231 -0
  15. package/dist/atomic/properties.d.mts +100 -0
  16. package/dist/atomic/properties.mjs +574 -0
  17. package/dist/atomic/shells.d.mts +137 -0
  18. package/dist/atomic/shells.mjs +170 -0
  19. package/dist/atomic/trends.d.mts +148 -0
  20. package/dist/atomic/trends.mjs +225 -0
  21. package/dist/builder/Palette.mjs +50 -89
  22. package/dist/builder/SceneBuilder.mjs +15 -73
  23. package/dist/chem/chromatography.d.mts +66 -0
  24. package/dist/chem/chromatography.mjs +63 -0
  25. package/dist/chem/complex.d.mts +114 -0
  26. package/dist/chem/complex.mjs +234 -0
  27. package/dist/chem/cycle.d.mts +75 -0
  28. package/dist/chem/cycle.mjs +145 -0
  29. package/dist/chem/equation.d.mts +86 -0
  30. package/dist/chem/equation.mjs +168 -0
  31. package/dist/chem/formula.d.mts +90 -0
  32. package/dist/chem/formula.mjs +201 -0
  33. package/dist/chem/functional-groups.d.mts +31 -0
  34. package/dist/chem/functional-groups.mjs +187 -0
  35. package/dist/chem/hazard.d.mts +94 -0
  36. package/dist/chem/hazard.mjs +329 -0
  37. package/dist/chem/index.d.mts +34 -33
  38. package/dist/chem/index.mjs +34 -28
  39. package/dist/chem/ionic.d.mts +98 -0
  40. package/dist/chem/ionic.mjs +156 -0
  41. package/dist/chem/layout.d.mts +46 -0
  42. package/dist/chem/layout.mjs +342 -0
  43. package/dist/chem/lewis.d.mts +79 -0
  44. package/dist/chem/lewis.mjs +163 -0
  45. package/dist/chem/molecular-orbital.d.mts +114 -0
  46. package/dist/chem/molecular-orbital.mjs +201 -0
  47. package/dist/chem/molecule.d.mts +154 -0
  48. package/dist/chem/molecule.mjs +282 -0
  49. package/dist/chem/nmr.d.mts +153 -0
  50. package/dist/chem/nmr.mjs +165 -0
  51. package/dist/chem/polymer.d.mts +65 -0
  52. package/dist/chem/polymer.mjs +179 -0
  53. package/dist/chem/redox.d.mts +138 -0
  54. package/dist/chem/redox.mjs +328 -0
  55. package/dist/chem/relations.d.mts +183 -0
  56. package/dist/chem/relations.mjs +299 -0
  57. package/dist/chem/skeleton.d.mts +51 -0
  58. package/dist/chem/skeleton.mjs +186 -0
  59. package/dist/chem/solution.d.mts +116 -0
  60. package/dist/chem/solution.mjs +186 -0
  61. package/dist/chem/species.d.mts +47 -0
  62. package/dist/chem/species.mjs +128 -0
  63. package/dist/chem/stereo.d.mts +108 -0
  64. package/dist/chem/stereo.mjs +286 -0
  65. package/dist/chem/stoichiometry.d.mts +95 -0
  66. package/dist/chem/stoichiometry.mjs +145 -0
  67. package/dist/chem/synthesis.d.mts +113 -0
  68. package/dist/chem/synthesis.mjs +281 -0
  69. package/dist/chem/vsepr.d.mts +80 -0
  70. package/dist/chem/vsepr.mjs +247 -0
  71. package/dist/circuit/ac.d.mts +163 -0
  72. package/dist/circuit/ac.mjs +452 -0
  73. package/dist/circuit/dc.d.mts +92 -0
  74. package/dist/circuit/dc.mjs +333 -0
  75. package/dist/circuit/index.d.mts +5 -92
  76. package/dist/circuit/index.mjs +5 -332
  77. package/dist/circuit/network.d.mts +99 -0
  78. package/dist/circuit/network.mjs +440 -0
  79. package/dist/circuit/topology.d.mts +102 -0
  80. package/dist/circuit/topology.mjs +143 -0
  81. package/dist/colour/absorption.d.mts +79 -0
  82. package/dist/colour/absorption.mjs +137 -0
  83. package/dist/colour/index.d.mts +6 -0
  84. package/dist/colour/index.mjs +7 -0
  85. package/dist/colour/name.d.mts +14 -0
  86. package/dist/colour/name.mjs +76 -0
  87. package/dist/colour/observer.d.mts +31 -0
  88. package/dist/colour/observer.mjs +46 -0
  89. package/dist/colour/spectrum.d.mts +61 -0
  90. package/dist/colour/spectrum.mjs +108 -0
  91. package/dist/colour/srgb.d.mts +49 -0
  92. package/dist/colour/srgb.mjs +108 -0
  93. package/dist/core/constants.d.mts +138 -0
  94. package/dist/core/constants.mjs +139 -0
  95. package/dist/core/index.d.mts +4 -1
  96. package/dist/core/index.mjs +4 -1
  97. package/dist/core/math.d.mts +26 -0
  98. package/dist/core/math.mjs +37 -0
  99. package/dist/core/vec3.d.mts +94 -0
  100. package/dist/core/vec3.mjs +123 -0
  101. package/dist/core/worked.d.mts +35 -0
  102. package/dist/core/worked.mjs +44 -0
  103. package/dist/electro/cell.d.mts +102 -0
  104. package/dist/electro/cell.mjs +170 -0
  105. package/dist/electro/conductivity.d.mts +157 -0
  106. package/dist/electro/conductivity.mjs +156 -0
  107. package/dist/electro/couples.d.mts +114 -0
  108. package/dist/electro/couples.mjs +334 -0
  109. package/dist/electro/electrolysis.d.mts +96 -0
  110. package/dist/electro/electrolysis.mjs +274 -0
  111. package/dist/electro/faraday.d.mts +150 -0
  112. package/dist/electro/faraday.mjs +118 -0
  113. package/dist/electro/index.d.mts +6 -0
  114. package/dist/electro/index.mjs +7 -0
  115. package/dist/finance/accounting/adjustments.d.mts +17 -0
  116. package/dist/finance/accounting/adjustments.mjs +202 -0
  117. package/dist/finance/accounting/analysis.d.mts +8 -0
  118. package/dist/finance/accounting/analysis.mjs +205 -0
  119. package/dist/finance/accounting/clubs.d.mts +21 -0
  120. package/dist/finance/accounting/clubs.mjs +217 -0
  121. package/dist/finance/accounting/company-statements.d.mts +7 -0
  122. package/dist/finance/accounting/company-statements.mjs +150 -0
  123. package/dist/finance/accounting/harness.d.mts +7 -0
  124. package/dist/finance/accounting/harness.mjs +45 -0
  125. package/dist/finance/accounting/index.d.mts +18 -0
  126. package/dist/finance/accounting/index.mjs +18 -0
  127. package/dist/finance/accounting/journalize.d.mts +16 -0
  128. package/dist/finance/accounting/journalize.mjs +128 -0
  129. package/dist/finance/accounting/manufacturing.d.mts +8 -0
  130. package/dist/finance/accounting/manufacturing.mjs +236 -0
  131. package/dist/finance/accounting/partnership.d.mts +7 -0
  132. package/dist/finance/accounting/partnership.mjs +152 -0
  133. package/dist/finance/accounting/period-case.d.mts +6 -0
  134. package/dist/finance/accounting/period-case.mjs +71 -0
  135. package/dist/finance/accounting/post.d.mts +9 -0
  136. package/dist/finance/accounting/post.mjs +84 -0
  137. package/dist/finance/accounting/precision.d.mts +9 -0
  138. package/dist/finance/accounting/precision.mjs +15 -0
  139. package/dist/finance/accounting/rules.d.mts +21 -0
  140. package/dist/finance/accounting/rules.mjs +37 -0
  141. package/dist/finance/accounting/solve.d.mts +28 -0
  142. package/dist/finance/accounting/solve.mjs +92 -0
  143. package/dist/finance/accounting/statements.d.mts +7 -0
  144. package/dist/finance/accounting/statements.mjs +142 -0
  145. package/dist/finance/accounting/types.d.mts +649 -0
  146. package/dist/finance/accounting/validate.d.mts +7 -0
  147. package/dist/finance/accounting/validate.mjs +67 -0
  148. package/dist/finance/accounting/verification.d.mts +24 -0
  149. package/dist/finance/accounting/verification.mjs +386 -0
  150. package/dist/finance/bizsim.d.mts +75 -0
  151. package/dist/finance/bizsim.mjs +296 -0
  152. package/dist/finance/index.d.mts +95 -0
  153. package/dist/finance/index.mjs +145 -0
  154. package/dist/finance/investment-math.d.mts +7 -0
  155. package/dist/finance/investment-math.mjs +18 -0
  156. package/dist/finance/management-accounting/budgeting.d.mts +7 -0
  157. package/dist/finance/management-accounting/budgeting.mjs +189 -0
  158. package/dist/finance/management-accounting/cash-budget.d.mts +7 -0
  159. package/dist/finance/management-accounting/cash-budget.mjs +154 -0
  160. package/dist/finance/management-accounting/costing.d.mts +8 -0
  161. package/dist/finance/management-accounting/costing.mjs +175 -0
  162. package/dist/finance/management-accounting/decisions.d.mts +8 -0
  163. package/dist/finance/management-accounting/decisions.mjs +164 -0
  164. package/dist/finance/management-accounting/index.d.mts +13 -0
  165. package/dist/finance/management-accounting/index.mjs +13 -0
  166. package/dist/finance/management-accounting/integrated-budget.d.mts +8 -0
  167. package/dist/finance/management-accounting/integrated-budget.mjs +67 -0
  168. package/dist/finance/management-accounting/inventory-costing.d.mts +7 -0
  169. package/dist/finance/management-accounting/inventory-costing.mjs +173 -0
  170. package/dist/finance/management-accounting/investment-appraisal.d.mts +7 -0
  171. package/dist/finance/management-accounting/investment-appraisal.mjs +148 -0
  172. package/dist/finance/management-accounting/management-case.d.mts +8 -0
  173. package/dist/finance/management-accounting/management-case.mjs +91 -0
  174. package/dist/finance/management-accounting/master-budget.d.mts +7 -0
  175. package/dist/finance/management-accounting/master-budget.mjs +137 -0
  176. package/dist/finance/management-accounting/production-costing.d.mts +8 -0
  177. package/dist/finance/management-accounting/production-costing.mjs +214 -0
  178. package/dist/finance/management-accounting/types.d.mts +644 -0
  179. package/dist/finance/management-accounting/variances.d.mts +7 -0
  180. package/dist/finance/management-accounting/variances.mjs +150 -0
  181. package/dist/index.d.mts +9 -8
  182. package/dist/index.mjs +5 -5
  183. package/dist/interaction/MovableDot.mjs +19 -0
  184. package/dist/interaction/useDraggable.mjs +24 -4
  185. package/dist/math/analysis.d.mts +61 -0
  186. package/dist/math/analysis.mjs +187 -0
  187. package/dist/math/answer-check.d.mts +50 -0
  188. package/dist/math/answer-check.mjs +106 -0
  189. package/dist/math/calculus.d.mts +17 -1
  190. package/dist/math/calculus.mjs +365 -2
  191. package/dist/math/complex.d.mts +93 -0
  192. package/dist/math/complex.mjs +239 -0
  193. package/dist/math/expr.d.mts +23 -0
  194. package/dist/math/expr.mjs +36 -0
  195. package/dist/math/index.d.mts +9 -23
  196. package/dist/math/index.mjs +9 -38
  197. package/dist/math/latex.mjs +10 -1
  198. package/dist/math/parse.mjs +1 -1
  199. package/dist/math/poly.d.mts +55 -0
  200. package/dist/math/poly.mjs +273 -0
  201. package/dist/math/rearrange.d.mts +14 -0
  202. package/dist/math/rearrange.mjs +125 -0
  203. package/dist/math/solve.d.mts +21 -0
  204. package/dist/math/solve.mjs +75 -0
  205. package/dist/networking/addressing.d.mts +26 -0
  206. package/dist/networking/addressing.mjs +33 -0
  207. package/dist/networking/cloud/access.d.mts +36 -0
  208. package/dist/networking/cloud/access.mjs +95 -0
  209. package/dist/networking/cloud/containers.d.mts +43 -0
  210. package/dist/networking/cloud/containers.mjs +54 -0
  211. package/dist/networking/cloud/edge.d.mts +17 -0
  212. package/dist/networking/cloud/edge.mjs +31 -0
  213. package/dist/networking/cloud/failure-domains.d.mts +19 -0
  214. package/dist/networking/cloud/failure-domains.mjs +22 -0
  215. package/dist/networking/cloud/geo-routing.d.mts +22 -0
  216. package/dist/networking/cloud/geo-routing.mjs +64 -0
  217. package/dist/networking/cloud/index.d.mts +18 -0
  218. package/dist/networking/cloud/index.mjs +19 -0
  219. package/dist/networking/cloud/inference-reliability.d.mts +30 -0
  220. package/dist/networking/cloud/inference-reliability.mjs +76 -0
  221. package/dist/networking/cloud/inference.d.mts +118 -0
  222. package/dist/networking/cloud/inference.mjs +179 -0
  223. package/dist/networking/cloud/infrastructure.d.mts +45 -0
  224. package/dist/networking/cloud/infrastructure.mjs +96 -0
  225. package/dist/networking/cloud/observability.d.mts +24 -0
  226. package/dist/networking/cloud/observability.mjs +34 -0
  227. package/dist/networking/cloud/orchestration.d.mts +32 -0
  228. package/dist/networking/cloud/orchestration.mjs +38 -0
  229. package/dist/networking/cloud/recovery.d.mts +21 -0
  230. package/dist/networking/cloud/recovery.mjs +27 -0
  231. package/dist/networking/cloud/releases.d.mts +42 -0
  232. package/dist/networking/cloud/releases.mjs +135 -0
  233. package/dist/networking/cloud/scaling.d.mts +25 -0
  234. package/dist/networking/cloud/scaling.mjs +65 -0
  235. package/dist/networking/cloud/secrets.d.mts +39 -0
  236. package/dist/networking/cloud/secrets.mjs +68 -0
  237. package/dist/networking/cloud/server-deployment.d.mts +29 -0
  238. package/dist/networking/cloud/server-deployment.mjs +72 -0
  239. package/dist/networking/cloud/storage.d.mts +16 -0
  240. package/dist/networking/cloud/storage.mjs +58 -0
  241. package/dist/networking/cloud/vpc.d.mts +18 -0
  242. package/dist/networking/cloud/vpc.mjs +100 -0
  243. package/dist/networking/delivery.d.mts +34 -0
  244. package/dist/networking/delivery.mjs +52 -0
  245. package/dist/networking/index.d.mts +47 -0
  246. package/dist/networking/index.mjs +47 -0
  247. package/dist/networking/ipv6.d.mts +28 -0
  248. package/dist/networking/ipv6.mjs +17 -0
  249. package/dist/networking/journeys.d.mts +83 -0
  250. package/dist/networking/journeys.mjs +161 -0
  251. package/dist/networking/models/airtime.d.mts +87 -0
  252. package/dist/networking/models/airtime.mjs +130 -0
  253. package/dist/networking/models/cellular.d.mts +157 -0
  254. package/dist/networking/models/cellular.mjs +252 -0
  255. package/dist/networking/models/encapsulation.d.mts +98 -0
  256. package/dist/networking/models/encapsulation.mjs +132 -0
  257. package/dist/networking/models/handover.d.mts +116 -0
  258. package/dist/networking/models/handover.mjs +209 -0
  259. package/dist/networking/models/handshake.d.mts +90 -0
  260. package/dist/networking/models/handshake.mjs +122 -0
  261. package/dist/networking/models/index.d.mts +14 -0
  262. package/dist/networking/models/index.mjs +15 -0
  263. package/dist/networking/models/media.d.mts +82 -0
  264. package/dist/networking/models/media.mjs +188 -0
  265. package/dist/networking/models/satellite.d.mts +86 -0
  266. package/dist/networking/models/satellite.mjs +121 -0
  267. package/dist/networking/models/spectrum.d.mts +83 -0
  268. package/dist/networking/models/spectrum.mjs +235 -0
  269. package/dist/networking/models/switch.d.mts +80 -0
  270. package/dist/networking/models/switch.mjs +155 -0
  271. package/dist/networking/models/vlan.d.mts +62 -0
  272. package/dist/networking/models/vlan.mjs +100 -0
  273. package/dist/networking/models/vpn.d.mts +66 -0
  274. package/dist/networking/models/vpn.mjs +125 -0
  275. package/dist/networking/models/wifi-privacy.d.mts +82 -0
  276. package/dist/networking/models/wifi-privacy.mjs +130 -0
  277. package/dist/networking/models/wifi.d.mts +240 -0
  278. package/dist/networking/models/wifi.mjs +562 -0
  279. package/dist/networking/nat-traversal.d.mts +24 -0
  280. package/dist/networking/nat-traversal.mjs +38 -0
  281. package/dist/networking/protocols.d.mts +17 -0
  282. package/dist/networking/protocols.mjs +57 -0
  283. package/dist/networking/queue.d.mts +12 -0
  284. package/dist/networking/queue.mjs +18 -0
  285. package/dist/networking/route-learning.d.mts +23 -0
  286. package/dist/networking/route-learning.mjs +43 -0
  287. package/dist/networking/routing.d.mts +11 -0
  288. package/dist/networking/routing.mjs +25 -0
  289. package/dist/networking/signals.d.mts +26 -0
  290. package/dist/networking/signals.mjs +35 -0
  291. package/dist/networking/subnet.d.mts +49 -0
  292. package/dist/networking/subnet.mjs +89 -0
  293. package/dist/networking/tcp-reliability.d.mts +24 -0
  294. package/dist/networking/tcp-reliability.mjs +38 -0
  295. package/dist/networking/topology/contract.d.mts +123 -0
  296. package/dist/networking/topology/index.d.mts +4 -0
  297. package/dist/networking/topology/index.mjs +4 -0
  298. package/dist/networking/topology/presets.d.mts +7 -0
  299. package/dist/networking/topology/presets.mjs +302 -0
  300. package/dist/networking/topology/simulation.d.mts +8 -0
  301. package/dist/networking/topology/simulation.mjs +179 -0
  302. package/dist/networking/wireless.d.mts +11 -0
  303. package/dist/networking/wireless.mjs +17 -0
  304. package/dist/optics/imaging.d.mts +218 -0
  305. package/dist/optics/imaging.mjs +276 -0
  306. package/dist/optics/index.d.mts +7 -0
  307. package/dist/optics/index.mjs +8 -0
  308. package/dist/optics/laws.d.mts +70 -0
  309. package/dist/optics/laws.mjs +195 -0
  310. package/dist/optics/prism.d.mts +148 -0
  311. package/dist/optics/prism.mjs +197 -0
  312. package/dist/optics/refraction.d.mts +201 -0
  313. package/dist/optics/refraction.mjs +270 -0
  314. package/dist/optics/wave-optics.d.mts +171 -0
  315. package/dist/optics/wave-optics.mjs +259 -0
  316. package/dist/physics/ac/index.d.mts +183 -0
  317. package/dist/physics/ac/index.mjs +203 -0
  318. package/dist/physics/dynamics/forces.d.mts +98 -0
  319. package/dist/physics/dynamics/forces.mjs +153 -0
  320. package/dist/physics/dynamics/friction.d.mts +76 -0
  321. package/dist/physics/dynamics/friction.mjs +119 -0
  322. package/dist/physics/dynamics/system.d.mts +68 -0
  323. package/dist/physics/dynamics/system.mjs +125 -0
  324. package/dist/physics/electrostatics/index.d.mts +169 -0
  325. package/dist/physics/electrostatics/index.mjs +249 -0
  326. package/dist/physics/energy/centre-of-mass.d.mts +115 -0
  327. package/dist/physics/energy/centre-of-mass.mjs +180 -0
  328. package/dist/physics/energy/conservation.d.mts +81 -0
  329. package/dist/physics/energy/conservation.mjs +129 -0
  330. package/dist/physics/energy/power.d.mts +90 -0
  331. package/dist/physics/energy/power.mjs +167 -0
  332. package/dist/physics/energy/spring.d.mts +73 -0
  333. package/dist/physics/energy/spring.mjs +129 -0
  334. package/dist/physics/energy/store.d.mts +63 -0
  335. package/dist/physics/energy/store.mjs +108 -0
  336. package/dist/physics/energy/theorem.d.mts +65 -0
  337. package/dist/physics/energy/theorem.mjs +113 -0
  338. package/dist/physics/energy/work.d.mts +114 -0
  339. package/dist/physics/energy/work.mjs +219 -0
  340. package/dist/physics/gravitation/body.d.mts +85 -0
  341. package/dist/physics/gravitation/body.mjs +168 -0
  342. package/dist/physics/gravitation/kepler.d.mts +127 -0
  343. package/dist/physics/gravitation/kepler.mjs +216 -0
  344. package/dist/physics/gravitation/law.d.mts +117 -0
  345. package/dist/physics/gravitation/law.mjs +175 -0
  346. package/dist/physics/gravitation/orbit.d.mts +119 -0
  347. package/dist/physics/gravitation/orbit.mjs +202 -0
  348. package/dist/physics/gravitation/potential.d.mts +114 -0
  349. package/dist/physics/gravitation/potential.mjs +202 -0
  350. package/dist/physics/gravitation/variation.d.mts +97 -0
  351. package/dist/physics/gravitation/variation.mjs +175 -0
  352. package/dist/physics/index.d.mts +35 -0
  353. package/dist/physics/index.mjs +36 -0
  354. package/dist/physics/integral-sweep.d.mts +63 -0
  355. package/dist/physics/integral-sweep.mjs +126 -0
  356. package/dist/physics/kinematics/equations.d.mts +47 -0
  357. package/dist/physics/kinematics/equations.mjs +126 -0
  358. package/dist/physics/kinematics/free-fall.d.mts +53 -0
  359. package/dist/physics/kinematics/free-fall.mjs +71 -0
  360. package/dist/physics/kinematics/given.d.mts +16 -0
  361. package/dist/physics/kinematics/given.mjs +55 -0
  362. package/dist/physics/kinematics/roots.d.mts +41 -0
  363. package/dist/physics/kinematics/roots.mjs +72 -0
  364. package/dist/physics/kinematics/solve.d.mts +52 -0
  365. package/dist/physics/kinematics/solve.mjs +172 -0
  366. package/dist/physics/magnetism/biot-savart.d.mts +161 -0
  367. package/dist/physics/magnetism/biot-savart.mjs +353 -0
  368. package/dist/physics/magnetism/flux.d.mts +94 -0
  369. package/dist/physics/magnetism/flux.mjs +313 -0
  370. package/dist/physics/magnetism/geomagnetism.d.mts +151 -0
  371. package/dist/physics/magnetism/geomagnetism.mjs +184 -0
  372. package/dist/physics/magnetism/index.d.mts +12 -0
  373. package/dist/physics/magnetism/index.mjs +74 -0
  374. package/dist/physics/magnetism/lorentz.d.mts +28 -0
  375. package/dist/physics/magnetism/lorentz.mjs +88 -0
  376. package/dist/physics/magnetism/magnetic-force.d.mts +102 -0
  377. package/dist/physics/magnetism/magnetic-force.mjs +169 -0
  378. package/dist/physics/momentum/collide.d.mts +77 -0
  379. package/dist/physics/momentum/collide.mjs +115 -0
  380. package/dist/physics/momentum/impulse.d.mts +89 -0
  381. package/dist/physics/momentum/impulse.mjs +159 -0
  382. package/dist/physics/momentum/planar.d.mts +60 -0
  383. package/dist/physics/momentum/planar.mjs +110 -0
  384. package/dist/physics/projectile.d.mts +107 -0
  385. package/dist/physics/projectile.mjs +185 -0
  386. package/dist/physics/rotation/angular.d.mts +85 -0
  387. package/dist/physics/rotation/angular.mjs +130 -0
  388. package/dist/physics/rotation/circular.d.mts +79 -0
  389. package/dist/physics/rotation/circular.mjs +131 -0
  390. package/dist/physics/rotation/inertia.d.mts +164 -0
  391. package/dist/physics/rotation/inertia.mjs +332 -0
  392. package/dist/physics/rotation/torque.d.mts +65 -0
  393. package/dist/physics/rotation/torque.mjs +134 -0
  394. package/dist/physics/vectors.d.mts +64 -0
  395. package/dist/physics/vectors.mjs +114 -0
  396. package/dist/primitives/Dot.d.mts +2 -15
  397. package/dist/primitives/Dot.mjs +6 -4
  398. package/dist/primitives/Grid.d.mts +33 -17
  399. package/dist/primitives/Grid.mjs +89 -17
  400. package/dist/primitives/Label.d.mts +1 -14
  401. package/dist/primitives/Label.mjs +3 -2
  402. package/dist/primitives/Lines.d.mts +4 -32
  403. package/dist/primitives/Lines.mjs +10 -8
  404. package/dist/primitives/Shapes.d.mts +5 -43
  405. package/dist/primitives/Shapes.mjs +12 -10
  406. package/dist/primitives/index.d.mts +2 -2
  407. package/dist/primitives/index.mjs +2 -2
  408. package/dist/primitives/props.mjs +31 -0
  409. package/dist/quantity/index.d.mts +119 -0
  410. package/dist/quantity/index.mjs +417 -0
  411. package/dist/relation/derive.d.mts +74 -0
  412. package/dist/relation/derive.mjs +73 -0
  413. package/dist/relation/index.d.mts +56 -0
  414. package/dist/relation/index.mjs +234 -0
  415. package/dist/scene/Scene.d.mts +6 -1
  416. package/dist/scene/Scene.mjs +15 -40
  417. package/dist/scene/evaluators.mjs +1 -1
  418. package/dist/sim/thermal.mjs +45 -20
  419. package/dist/thermo/calorimetry.d.mts +207 -0
  420. package/dist/thermo/calorimetry.mjs +345 -0
  421. package/dist/thermo/cycles.d.mts +142 -0
  422. package/dist/thermo/cycles.mjs +256 -0
  423. package/dist/thermo/entropy.d.mts +87 -0
  424. package/dist/thermo/entropy.mjs +140 -0
  425. package/dist/thermo/expansion.d.mts +130 -0
  426. package/dist/thermo/expansion.mjs +178 -0
  427. package/dist/thermo/gas.d.mts +197 -0
  428. package/dist/thermo/gas.mjs +279 -0
  429. package/dist/thermo/heat-transfer.d.mts +164 -0
  430. package/dist/thermo/heat-transfer.mjs +217 -0
  431. package/dist/thermo/index.d.mts +9 -82
  432. package/dist/thermo/index.mjs +9 -132
  433. package/dist/thermo/processes.d.mts +95 -0
  434. package/dist/thermo/processes.mjs +154 -0
  435. package/dist/thermo/temperature.d.mts +174 -0
  436. package/dist/thermo/temperature.mjs +236 -0
  437. package/dist/view/Stage.mjs +4 -11
  438. package/dist/waves/damping.d.mts +224 -0
  439. package/dist/waves/damping.mjs +317 -0
  440. package/dist/waves/doppler.d.mts +72 -0
  441. package/dist/waves/doppler.mjs +125 -0
  442. package/dist/waves/index.d.mts +10 -0
  443. package/dist/waves/index.mjs +10 -0
  444. package/dist/waves/pendulum.d.mts +130 -0
  445. package/dist/waves/pendulum.mjs +211 -0
  446. package/dist/waves/pitch.d.mts +125 -0
  447. package/dist/waves/pitch.mjs +158 -0
  448. package/dist/waves/shm.d.mts +170 -0
  449. package/dist/waves/shm.mjs +279 -0
  450. package/dist/waves/springs.d.mts +103 -0
  451. package/dist/waves/springs.mjs +176 -0
  452. package/dist/waves/superposition.d.mts +124 -0
  453. package/dist/waves/superposition.mjs +196 -0
  454. package/dist/waves/wave.d.mts +154 -0
  455. package/dist/waves/wave.mjs +178 -0
  456. package/package.json +103 -23
  457. package/styles.css +125 -8
  458. package/dist/assets/kit/index.mjs +0 -4
@@ -0,0 +1,79 @@
1
+ import { Centre } from "./species.mjs";
2
+
3
+ //#region src/chem/lewis.d.ts
4
+ /** Valence electrons of an element, from its configuration. */
5
+ declare function valenceElectronsFor(symbol: string): number;
6
+ interface LewisCount {
7
+ /** Valence electrons of all the atoms, adjusted for the overall charge. */
8
+ readonly totalValenceElectrons: number;
9
+ /** Sigma bonds from the central atom, one per ligand atom. */
10
+ readonly bondingPairs: number;
11
+ /** Lone pairs left on the central atom. */
12
+ readonly lonePairs: number;
13
+ /**
14
+ * Bonding pairs plus lone pairs: the number of regions of electron density.
15
+ *
16
+ * Pi bonds are deliberately NOT counted. A double bond points the same way as the single bond
17
+ * underneath it, so it is one region, which is why carbon dioxide is linear.
18
+ */
19
+ readonly stericNumber: number;
20
+ /**
21
+ * Pi bonds formed by pulling a lone pair off an outer atom into the bond.
22
+ *
23
+ * Derived rather than guessed. Every pi bond moves the central atom's formal charge one step
24
+ * toward zero and the donating atom's one step away from it, so they are added while that trade
25
+ * is an improvement and stopped when it is not. Two guards end the process:
26
+ *
27
+ * the central atom's formal charge reaches zero, so there is nothing left to gain;
28
+ * the donor would end up positively charged while being MORE electronegative than the centre,
29
+ * which is the situation no real structure adopts.
30
+ *
31
+ * That second guard is the whole of the difference between carbon dioxide and boron trifluoride.
32
+ * Carbon starts at +2 with two oxygens at -1, and two pi bonds take all three to zero. Boron
33
+ * starts at 0 already, so no pi bond would improve anything, and one would push fluorine, the most
34
+ * electronegative element there is, to +1.
35
+ */
36
+ readonly piBonds: number;
37
+ /** Bond order to each outer atom, in the order the formula writes them. */
38
+ readonly bondOrders: readonly {
39
+ readonly element: string;
40
+ readonly order: number;
41
+ }[];
42
+ /** Electrons around the central atom, pi bonds included. */
43
+ readonly centralElectrons: number;
44
+ /**
45
+ * How many electrons short of an octet the central atom REMAINS once pi bonding has done what it
46
+ * can.
47
+ *
48
+ * Zero for carbon dioxide, which closes its gap completely. Two for boron trifluoride, which
49
+ * cannot close it at all and is genuinely electron deficient: that is not a limitation of the
50
+ * calculation, it is the reason boron trifluoride is such a strong Lewis acid.
51
+ */
52
+ readonly octetShortfall: number;
53
+ /**
54
+ * Formal charge on the central atom in the structure this record describes.
55
+ *
56
+ * Worth being precise about, because formal charge belongs to a STRUCTURE and not to a species.
57
+ * Carbon dioxide drawn with single bonds gives its carbon +2 and drawn with two double bonds gives
58
+ * it 0, and both are statements about drawings. This is the charge in the pi-bonded structure the
59
+ * rest of this record describes, which is the one a chemist would draw.
60
+ */
61
+ readonly formalCharge: number;
62
+ /** Whether the central atom can hold more than eight, which needs an accessible d subshell. */
63
+ readonly canExpand: boolean;
64
+ /** Set when the count needs more than an octet on an atom that cannot hold one. */
65
+ readonly impossible?: string;
66
+ }
67
+ /**
68
+ * Work out the electron budget of a species.
69
+ *
70
+ * Returns the count rather than a drawing: where the electrons GO on the page is a layout decision,
71
+ * and how many there are is chemistry.
72
+ */
73
+ declare function lewisCount(centre: Centre): LewisCount;
74
+ /** How the central atom's electron count compares with an octet. */
75
+ type OctetStatus = 'short of an octet' | 'an octet' | 'an expanded octet';
76
+ /** Whether the central atom has fewer than eight electrons, eight, or more. */
77
+ declare function octetStatus(count: LewisCount): OctetStatus;
78
+ //#endregion
79
+ export { LewisCount, OctetStatus, lewisCount, octetStatus, valenceElectronsFor };
@@ -0,0 +1,163 @@
1
+ import { periodOf, valenceElectronsOf } from "../atomic/periodic.mjs";
2
+ import { elementBySymbol } from "../atomic/elements.mjs";
3
+ import { electronegativity } from "../atomic/properties.mjs";
4
+
5
+ //#region src/chem/lewis.ts
6
+ /**
7
+ * The electron budget of a species: how many bonding pairs and how many lone pairs.
8
+ *
9
+ * ## The counting, stated once
10
+ *
11
+ * Every shape question reduces to two numbers, and both come out of one budget:
12
+ *
13
+ * 1. total valence electrons = the valence electrons of every atom, plus one for each unit of
14
+ * negative charge and minus one for each unit of positive charge;
15
+ * 2. one sigma bond to each ligand uses two of them;
16
+ * 3. each non-hydrogen ligand then takes six more to complete its own octet (hydrogen takes none,
17
+ * because its bonding pair already fills its shell);
18
+ * 4. whatever is left belongs to the central atom, as lone pairs.
19
+ *
20
+ * That is the whole method, and it gets SF4, XeF2, ClF3, NH4+ and SO4 right with no special cases.
21
+ *
22
+ * ## Multiple bonds, decided by formal charge
23
+ *
24
+ * Where the central atom ends up short of an octet, that gap is what multiple bonding closes. The
25
+ * question is whether it actually does, and the answer is not in the electron count: carbon dioxide
26
+ * closes its gap completely and boron trifluoride cannot close it at all.
27
+ *
28
+ * Formal charge settles it, with electronegativity as the guard. Every pi bond moves the central
29
+ * atom one step toward zero and the donating outer atom one step away, so pi bonds are added while
30
+ * that trade improves the structure and stopped when it does not:
31
+ *
32
+ * carbon dioxide starts as C(+2) with two O(-1), and two pi bonds take all three to zero;
33
+ * boron trifluoride starts at B(0) with three F(0), so no pi bond improves anything, and one
34
+ * would push fluorine, the most electronegative element there is, to +1.
35
+ *
36
+ * That is the whole difference between them, and it needs no special case for either. A second-
37
+ * period centre is additionally capped at an octet, which is why nitrate gets exactly one double
38
+ * bond and leaves its nitrogen at +1 rather than reaching zero.
39
+ *
40
+ * None of it affects the shape. A double bond points the same way as the single bond underneath it
41
+ * and is one region of electron density, which is why carbon dioxide is linear.
42
+ *
43
+ * ## Where the valence electron counts come from
44
+ *
45
+ * From the atomic engine, not from a table typed out here. An element's valence electron count is
46
+ * already a consequence of its configuration, and duplicating it would let the two disagree. So
47
+ * oxygen having six and xenon having eight is derived in one place and used here.
48
+ *
49
+ * ## On the octet rule and its exceptions
50
+ *
51
+ * The octet rule is a useful summary of the second period and is broken routinely below it. This
52
+ * engine does not enforce it: it counts electrons and REPORTS whether the central atom ended up
53
+ * with fewer than eight, exactly eight, or more. Boron trifluoride comes out with six and sulfur
54
+ * hexafluoride with twelve, and both are correct, so a rule that forbade them would be a rule that
55
+ * had to be switched off for the interesting cases.
56
+ *
57
+ * Expansion beyond eight needs d orbitals close enough in energy to be used, which is why it starts
58
+ * in the third period. {@link LewisCount.canExpand} says whether the central atom is in a position
59
+ * to do it, so a count that expands a second-period atom can be flagged as impossible rather than
60
+ * reported as fact.
61
+ *
62
+ * Pure: no React, no pixels.
63
+ */
64
+ /** Valence electrons of an element, from its configuration. */
65
+ function valenceElectronsFor(symbol) {
66
+ const element = elementBySymbol(symbol);
67
+ if (!element) throw new Error(`no element with symbol "${symbol}"`);
68
+ return valenceElectronsOf(element.Z);
69
+ }
70
+ /** Electrons a ligand needs beyond its bonding pair to fill its own shell. */
71
+ function ligandDemand(symbol) {
72
+ return symbol === "H" ? 0 : 6;
73
+ }
74
+ /**
75
+ * Work out the electron budget of a species.
76
+ *
77
+ * Returns the count rather than a drawing: where the electrons GO on the page is a layout decision,
78
+ * and how many there are is chemistry.
79
+ */
80
+ function lewisCount(centre) {
81
+ const centralValence = valenceElectronsFor(centre.central);
82
+ const totalValenceElectrons = centralValence + centre.bonded.reduce((total, l) => total + valenceElectronsFor(l.element) * l.count, 0) - centre.charge;
83
+ const bondingPairs = centre.bondedCount;
84
+ const usedBySigma = 2 * bondingPairs;
85
+ const demandedByLigands = centre.bonded.reduce((total, l) => total + ligandDemand(l.element) * l.count, 0);
86
+ const leftForCentre = totalValenceElectrons - usedBySigma - demandedByLigands;
87
+ const lonePairs = Math.max(0, Math.floor(leftForCentre / 2));
88
+ const stericNumber = bondingPairs + lonePairs;
89
+ const singleBondElectrons = 2 * bondingPairs + 2 * lonePairs;
90
+ const period = periodOf(elementBySymbol(centre.central).Z);
91
+ const canExpand = period >= 3;
92
+ const bondOrders = shareOutPiBonds(centre, {
93
+ centralValence,
94
+ lonePairs,
95
+ bondingPairs,
96
+ singleBondElectrons,
97
+ canExpand
98
+ });
99
+ const piBonds = bondOrders.reduce((total, b) => total + b.order - 1, 0);
100
+ const centralElectrons = singleBondElectrons + 2 * piBonds;
101
+ const octetShortfall = Math.max(0, 8 - centralElectrons);
102
+ const formalCharge = centralValence - 2 * lonePairs - (bondingPairs + piBonds);
103
+ let impossible;
104
+ if (leftForCentre < 0) impossible = `${centre.formula} has ${totalValenceElectrons} valence electrons, which is ${-leftForCentre} short of what its ${bondingPairs} bonds and its outer atoms need: check the formula and the charge`;
105
+ else if (singleBondElectrons > 8 && !canExpand) impossible = `${centre.central} is in period ${period} and has no d subshell available, so it cannot hold the ${singleBondElectrons} electrons this arrangement needs`;
106
+ return {
107
+ totalValenceElectrons,
108
+ bondingPairs,
109
+ lonePairs,
110
+ stericNumber,
111
+ piBonds,
112
+ bondOrders,
113
+ centralElectrons,
114
+ octetShortfall,
115
+ formalCharge,
116
+ canExpand,
117
+ ...impossible ? { impossible } : {}
118
+ };
119
+ }
120
+ /** Formal charge on an outer atom holding `pi` extra bonds beyond its single one. */
121
+ const outerFormalCharge = (symbol, pi) => valenceElectronsFor(symbol) - 2 * (3 - pi) - (1 + pi);
122
+ /**
123
+ * Decide how many pi bonds form, and to which outer atoms.
124
+ *
125
+ * Greedy and one bond at a time, because that is what the reasoning actually is: would drawing one
126
+ * more double bond here make the structure better? Better means the central atom's formal charge
127
+ * moves toward zero without pushing a more electronegative neighbour above it.
128
+ *
129
+ * Spread across the outer atoms rather than piled onto one, so carbon dioxide comes out as two
130
+ * double bonds and not as a triple and a single. Both satisfy the counting; only one of them is the
131
+ * molecule.
132
+ */
133
+ function shareOutPiBonds(centre, state) {
134
+ const orders = centre.bonded.flatMap((b) => Array.from({ length: b.count }, () => ({
135
+ element: b.element,
136
+ order: 1
137
+ })));
138
+ const centralPull = electronegativity(elementBySymbol(centre.central).Z);
139
+ for (;;) {
140
+ const piSoFar = orders.reduce((total, b) => total + b.order - 1, 0);
141
+ if (state.centralValence - 2 * state.lonePairs - (state.bondingPairs + piSoFar) <= 0) break;
142
+ if (!state.canExpand && state.singleBondElectrons + 2 * (piSoFar + 1) > 8) break;
143
+ const donor = orders.filter((bond) => {
144
+ if (bond.element === "H" || bond.order >= 4) return false;
145
+ if (outerFormalCharge(bond.element, bond.order) <= 0) return true;
146
+ const donorPull = electronegativity(elementBySymbol(bond.element).Z);
147
+ if (donorPull === void 0 || centralPull === void 0) return false;
148
+ return donorPull <= centralPull;
149
+ }).sort((a, b) => a.order - b.order)[0];
150
+ if (!donor) break;
151
+ donor.order += 1;
152
+ }
153
+ return orders;
154
+ }
155
+ /** Whether the central atom has fewer than eight electrons, eight, or more. */
156
+ function octetStatus(count) {
157
+ if (count.centralElectrons < 8) return "short of an octet";
158
+ if (count.centralElectrons === 8) return "an octet";
159
+ return "an expanded octet";
160
+ }
161
+
162
+ //#endregion
163
+ export { lewisCount, octetStatus, valenceElectronsFor };
@@ -0,0 +1,114 @@
1
+ //#region src/chem/molecular-orbital.d.ts
2
+ /**
3
+ * Molecular orbitals for a diatomic: bond order, and whether the molecule is magnetic.
4
+ *
5
+ * ## What this explains that dot-and-cross cannot
6
+ *
7
+ * Oxygen is paramagnetic. Liquid oxygen sticks to a magnet, which is a thing anyone can watch, and
8
+ * the Lewis structure O=O has every electron neatly paired and predicts the opposite. That failure
9
+ * is the reason molecular orbital theory is taught at all: put the electrons into orbitals that
10
+ * belong to the whole molecule rather than to one atom or one bond, and two of them end up alone in
11
+ * a pair of degenerate antibonding orbitals.
12
+ *
13
+ * So this engine answers two questions a Lewis structure cannot: how strongly the atoms are held
14
+ * together when the answer is not a whole number, and whether the molecule has unpaired electrons.
15
+ *
16
+ * bond order = (bonding electrons - antibonding electrons) / 2
17
+ *
18
+ * A bond order of zero means the molecule does not exist, which is why there is no He2 and no Ne2.
19
+ *
20
+ * ## The crossover, which is the part usually left out
21
+ *
22
+ * The order of the 2p-derived orbitals is not fixed. For the earlier second-period elements the two
23
+ * pi orbitals lie BELOW the sigma; from oxygen onward the sigma drops below the pi. The cause is
24
+ * mixing between the 2s and 2p sigma orbitals, which pushes the sigma up, and it matters most where
25
+ * the 2s and 2p levels are closest together, which is at the left of the period.
26
+ *
27
+ * This is not a detail. Boron's B2 has exactly two electrons to place in that region: with pi
28
+ * lowest they go one into each pi orbital and B2 is paramagnetic, which it is; with sigma lowest
29
+ * they pair up in it and B2 would be diamagnetic, which it is not. So an engine that ignored the
30
+ * crossover would get the right bond order and the wrong magnetism, and the magnetism is the
31
+ * evidence.
32
+ *
33
+ * ## What is covered
34
+ *
35
+ * Diatomics of the first two periods, neutral or charged: H2, He2, Li2 through Ne2, and the
36
+ * heteronuclear and ionic ones built from the same orbitals, so NO, CO, CN- and the oxygen family
37
+ * O2+, O2-, O2 2-. Core electrons are left out: they sit in bonding and antibonding pairs that
38
+ * cancel exactly, so they change no answer and only lengthen the diagram.
39
+ *
40
+ * Pure: no React, no pixels.
41
+ */
42
+ interface MolecularOrbital {
43
+ readonly label: string;
44
+ readonly bonding: boolean;
45
+ /** How many orbitals are at this energy: two for a pi level, one for a sigma. */
46
+ readonly orbitals: number;
47
+ }
48
+ /**
49
+ * Where the sigma made from 2p sits relative to the pair of pi orbitals.
50
+ *
51
+ * Mixing with the 2s sigma pushes the 2p sigma up, and the effect is strongest where 2s and 2p are
52
+ * closest in energy, which is toward the left of the period. So the pi orbitals are lower for the
53
+ * earlier elements and the sigma is lower from oxygen onward.
54
+ */
55
+ declare const S_P_MIXING_NOTE = "The sigma orbital built from 2p is pushed up by mixing with the sigma built from 2s, and that mixing is strongest where the 2s and 2p levels lie closest together, toward the left of the period. So for boron, carbon and nitrogen the two pi orbitals lie below the sigma, and from oxygen onward the sigma drops below them.";
56
+ /** The orbitals in energy order, for a diatomic with this many valence electrons. */
57
+ declare function orbitalSequence(valenceElectrons: number, firstPeriod: boolean): readonly MolecularOrbital[];
58
+ interface Level {
59
+ readonly orbital: MolecularOrbital;
60
+ readonly electrons: number;
61
+ /** Electrons in this level with no partner, by Hund's rule. */
62
+ readonly unpaired: number;
63
+ }
64
+ /**
65
+ * Fill the orbitals from the bottom, singly across a degenerate level before pairing.
66
+ *
67
+ * Hund's rule again, and for the same reason it applies inside an atom: two electrons in one
68
+ * orbital repel, so they spread out while there is anywhere to spread to. It is what leaves oxygen
69
+ * with two unpaired electrons instead of one filled antibonding orbital.
70
+ */
71
+ declare function fillOrbitals(sequence: readonly MolecularOrbital[], electrons: number): {
72
+ levels: Level[];
73
+ unpaired: number;
74
+ unplaced: number;
75
+ };
76
+ type Magnetism = 'paramagnetic' | 'diamagnetic';
77
+ interface DiatomicResult {
78
+ readonly formula: string;
79
+ readonly atoms: readonly string[];
80
+ readonly charge: number;
81
+ /** Valence electrons only: core pairs cancel and change no answer. */
82
+ readonly valenceElectrons: number;
83
+ readonly levels: readonly Level[];
84
+ readonly bondingElectrons: number;
85
+ readonly antibondingElectrons: number;
86
+ /**
87
+ * (bonding - antibonding) / 2, so it can be a half.
88
+ *
89
+ * A half-integer bond order is not a rounding error: it is what an odd number of electrons gives,
90
+ * and it is why nitrogen monoxide exists as a stable radical with a bond between a double and a
91
+ * triple.
92
+ */
93
+ readonly bondOrder: number;
94
+ readonly unpairedElectrons: number;
95
+ readonly magnetism: Magnetism;
96
+ /** A bond order of zero means there is nothing holding the atoms together. */
97
+ readonly exists: boolean;
98
+ /** True when the pi orbitals lie below the sigma, which is the crossover. */
99
+ readonly piBelowSigma: boolean;
100
+ }
101
+ /**
102
+ * Work out the molecular orbitals of a diatomic written as a formula.
103
+ *
104
+ * `diatomic('O2')`, `diatomic('N2')`, `diatomic('NO')`, `diatomic('CN-')`, `diatomic('O2+')`.
105
+ */
106
+ declare function diatomic(formula: string): DiatomicResult;
107
+ /**
108
+ * The configuration written out, for a diagram caption.
109
+ *
110
+ * Empty levels are dropped, since writing them adds nothing a reader needs.
111
+ */
112
+ declare const formatOccupancy: (result: DiatomicResult) => string;
113
+ //#endregion
114
+ export { DiatomicResult, Level, Magnetism, MolecularOrbital, S_P_MIXING_NOTE, diatomic, fillOrbitals, formatOccupancy, orbitalSequence };
@@ -0,0 +1,201 @@
1
+ import { readFormula } from "./species.mjs";
2
+ import { valenceElectronsFor } from "./lewis.mjs";
3
+
4
+ //#region src/chem/molecular-orbital.ts
5
+ /**
6
+ * Molecular orbitals for a diatomic: bond order, and whether the molecule is magnetic.
7
+ *
8
+ * ## What this explains that dot-and-cross cannot
9
+ *
10
+ * Oxygen is paramagnetic. Liquid oxygen sticks to a magnet, which is a thing anyone can watch, and
11
+ * the Lewis structure O=O has every electron neatly paired and predicts the opposite. That failure
12
+ * is the reason molecular orbital theory is taught at all: put the electrons into orbitals that
13
+ * belong to the whole molecule rather than to one atom or one bond, and two of them end up alone in
14
+ * a pair of degenerate antibonding orbitals.
15
+ *
16
+ * So this engine answers two questions a Lewis structure cannot: how strongly the atoms are held
17
+ * together when the answer is not a whole number, and whether the molecule has unpaired electrons.
18
+ *
19
+ * bond order = (bonding electrons - antibonding electrons) / 2
20
+ *
21
+ * A bond order of zero means the molecule does not exist, which is why there is no He2 and no Ne2.
22
+ *
23
+ * ## The crossover, which is the part usually left out
24
+ *
25
+ * The order of the 2p-derived orbitals is not fixed. For the earlier second-period elements the two
26
+ * pi orbitals lie BELOW the sigma; from oxygen onward the sigma drops below the pi. The cause is
27
+ * mixing between the 2s and 2p sigma orbitals, which pushes the sigma up, and it matters most where
28
+ * the 2s and 2p levels are closest together, which is at the left of the period.
29
+ *
30
+ * This is not a detail. Boron's B2 has exactly two electrons to place in that region: with pi
31
+ * lowest they go one into each pi orbital and B2 is paramagnetic, which it is; with sigma lowest
32
+ * they pair up in it and B2 would be diamagnetic, which it is not. So an engine that ignored the
33
+ * crossover would get the right bond order and the wrong magnetism, and the magnetism is the
34
+ * evidence.
35
+ *
36
+ * ## What is covered
37
+ *
38
+ * Diatomics of the first two periods, neutral or charged: H2, He2, Li2 through Ne2, and the
39
+ * heteronuclear and ionic ones built from the same orbitals, so NO, CO, CN- and the oxygen family
40
+ * O2+, O2-, O2 2-. Core electrons are left out: they sit in bonding and antibonding pairs that
41
+ * cancel exactly, so they change no answer and only lengthen the diagram.
42
+ *
43
+ * Pure: no React, no pixels.
44
+ */
45
+ /**
46
+ * Where the sigma made from 2p sits relative to the pair of pi orbitals.
47
+ *
48
+ * Mixing with the 2s sigma pushes the 2p sigma up, and the effect is strongest where 2s and 2p are
49
+ * closest in energy, which is toward the left of the period. So the pi orbitals are lower for the
50
+ * earlier elements and the sigma is lower from oxygen onward.
51
+ */
52
+ const S_P_MIXING_NOTE = "The sigma orbital built from 2p is pushed up by mixing with the sigma built from 2s, and that mixing is strongest where the 2s and 2p levels lie closest together, toward the left of the period. So for boron, carbon and nitrogen the two pi orbitals lie below the sigma, and from oxygen onward the sigma drops below them.";
53
+ /** Valence electron count at or below which the pi orbitals lie below the sigma. */
54
+ const MIXING_LIMIT = 10;
55
+ const PERIOD_1 = [{
56
+ label: "σ1s",
57
+ bonding: true,
58
+ orbitals: 1
59
+ }, {
60
+ label: "σ*1s",
61
+ bonding: false,
62
+ orbitals: 1
63
+ }];
64
+ const PI_BELOW_SIGMA = [
65
+ {
66
+ label: "σ2s",
67
+ bonding: true,
68
+ orbitals: 1
69
+ },
70
+ {
71
+ label: "σ*2s",
72
+ bonding: false,
73
+ orbitals: 1
74
+ },
75
+ {
76
+ label: "π2p",
77
+ bonding: true,
78
+ orbitals: 2
79
+ },
80
+ {
81
+ label: "σ2p",
82
+ bonding: true,
83
+ orbitals: 1
84
+ },
85
+ {
86
+ label: "π*2p",
87
+ bonding: false,
88
+ orbitals: 2
89
+ },
90
+ {
91
+ label: "σ*2p",
92
+ bonding: false,
93
+ orbitals: 1
94
+ }
95
+ ];
96
+ const SIGMA_BELOW_PI = [
97
+ {
98
+ label: "σ2s",
99
+ bonding: true,
100
+ orbitals: 1
101
+ },
102
+ {
103
+ label: "σ*2s",
104
+ bonding: false,
105
+ orbitals: 1
106
+ },
107
+ {
108
+ label: "σ2p",
109
+ bonding: true,
110
+ orbitals: 1
111
+ },
112
+ {
113
+ label: "π2p",
114
+ bonding: true,
115
+ orbitals: 2
116
+ },
117
+ {
118
+ label: "π*2p",
119
+ bonding: false,
120
+ orbitals: 2
121
+ },
122
+ {
123
+ label: "σ*2p",
124
+ bonding: false,
125
+ orbitals: 1
126
+ }
127
+ ];
128
+ /** The orbitals in energy order, for a diatomic with this many valence electrons. */
129
+ function orbitalSequence(valenceElectrons, firstPeriod) {
130
+ if (firstPeriod) return PERIOD_1;
131
+ return valenceElectrons <= MIXING_LIMIT ? PI_BELOW_SIGMA : SIGMA_BELOW_PI;
132
+ }
133
+ /**
134
+ * Fill the orbitals from the bottom, singly across a degenerate level before pairing.
135
+ *
136
+ * Hund's rule again, and for the same reason it applies inside an atom: two electrons in one
137
+ * orbital repel, so they spread out while there is anywhere to spread to. It is what leaves oxygen
138
+ * with two unpaired electrons instead of one filled antibonding orbital.
139
+ */
140
+ function fillOrbitals(sequence, electrons) {
141
+ let left = electrons;
142
+ const levels = sequence.map((orbital) => {
143
+ const capacity = 2 * orbital.orbitals;
144
+ const placed = Math.min(left, capacity);
145
+ left -= placed;
146
+ return {
147
+ orbital,
148
+ electrons: placed,
149
+ unpaired: placed <= orbital.orbitals ? placed : 2 * orbital.orbitals - placed
150
+ };
151
+ });
152
+ return {
153
+ levels,
154
+ unpaired: levels.reduce((total, l) => total + l.unpaired, 0),
155
+ unplaced: left
156
+ };
157
+ }
158
+ /**
159
+ * Work out the molecular orbitals of a diatomic written as a formula.
160
+ *
161
+ * `diatomic('O2')`, `diatomic('N2')`, `diatomic('NO')`, `diatomic('CN-')`, `diatomic('O2+')`.
162
+ */
163
+ function diatomic(formula) {
164
+ const { counts, charge } = readFormula(formula);
165
+ const atoms = counts.flatMap((c) => Array(c.count).fill(c.element));
166
+ if (atoms.length !== 2) throw new Error(`${formula} has ${atoms.length} atoms: this engine describes diatomic molecules, which have two`);
167
+ const firstPeriod = atoms.every((a) => a === "H" || a === "He");
168
+ const valenceElectrons = atoms.reduce((total, a) => total + valenceElectronsFor(a), 0) - charge;
169
+ if (valenceElectrons < 0) throw new Error(`${formula} works out to a negative electron count`);
170
+ const piBelowSigma = !firstPeriod && valenceElectrons <= MIXING_LIMIT;
171
+ const { levels, unpaired, unplaced } = fillOrbitals(orbitalSequence(valenceElectrons, firstPeriod), valenceElectrons);
172
+ if (unplaced > 0) throw new Error(`${formula} has ${valenceElectrons} valence electrons, more than the orbitals of the first two periods can hold`);
173
+ const bondingElectrons = levels.filter((l) => l.orbital.bonding).reduce((total, l) => total + l.electrons, 0);
174
+ const antibondingElectrons = levels.filter((l) => !l.orbital.bonding).reduce((total, l) => total + l.electrons, 0);
175
+ const bondOrder = (bondingElectrons - antibondingElectrons) / 2;
176
+ return {
177
+ formula,
178
+ atoms,
179
+ charge,
180
+ valenceElectrons,
181
+ levels,
182
+ bondingElectrons,
183
+ antibondingElectrons,
184
+ bondOrder,
185
+ unpairedElectrons: unpaired,
186
+ magnetism: unpaired > 0 ? "paramagnetic" : "diamagnetic",
187
+ exists: bondOrder > 0,
188
+ piBelowSigma
189
+ };
190
+ }
191
+ /**
192
+ * The configuration written out, for a diagram caption.
193
+ *
194
+ * Empty levels are dropped, since writing them adds nothing a reader needs.
195
+ */
196
+ const formatOccupancy = (result) => result.levels.filter((l) => l.electrons > 0).map((l) => `${l.orbital.label}${l.electrons === 1 ? "" : superscript(l.electrons)}`).join(" ");
197
+ const SUPERSCRIPT = "⁰¹²³⁴⁵⁶⁷⁸⁹";
198
+ const superscript = (value) => String(value).split("").map((d) => SUPERSCRIPT[Number(d)] ?? d).join("");
199
+
200
+ //#endregion
201
+ export { S_P_MIXING_NOTE, diatomic, fillOrbitals, formatOccupancy, orbitalSequence };