@classytic/labs 0.1.0 → 0.2.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 (455) hide show
  1. package/dist/_virtual/_rolldown/runtime.mjs +18 -0
  2. package/dist/biology/enzyme-rate/preset.mjs +5 -5
  3. package/dist/biology/genetic-cross/core.d.mts +7 -7
  4. package/dist/biology/genetic-cross/core.mjs +4 -4
  5. package/dist/biology/genetic-cross/grid.mjs +132 -123
  6. package/dist/biology/genetic-cross/preset.mjs +4 -4
  7. package/dist/biology/genetic-cross/sex-linked.mjs +7 -7
  8. package/dist/biology/photosynthesis-factors/preset.mjs +8 -8
  9. package/dist/biology/respiration/preset.mjs +4 -4
  10. package/dist/biology/sequence/central-dogma.mjs +5 -5
  11. package/dist/biology/sequence/core.d.mts +6 -6
  12. package/dist/biology/sequence/core.mjs +1 -1
  13. package/dist/biology/sequence/preset.mjs +6 -6
  14. package/dist/blocks/authoring.mjs +5 -5
  15. package/dist/blocks/biology.d.mts +2 -2
  16. package/dist/blocks/biology.mjs +5 -5
  17. package/dist/blocks/chem.d.mts +2 -2
  18. package/dist/blocks/chem.mjs +13 -13
  19. package/dist/blocks/circuits.d.mts +293 -4
  20. package/dist/blocks/circuits.mjs +874 -9
  21. package/dist/blocks/discrete.d.mts +30 -2
  22. package/dist/blocks/discrete.mjs +74 -4
  23. package/dist/blocks/economics.mjs +1 -1
  24. package/dist/blocks/geography.mjs +1 -1
  25. package/dist/blocks/geometry.mjs +3 -3
  26. package/dist/blocks/ict.d.mts +90 -1
  27. package/dist/blocks/ict.mjs +217 -7
  28. package/dist/blocks/index.d.mts +3064 -657
  29. package/dist/blocks/index.mjs +9 -9
  30. package/dist/blocks/lab-block.mjs +5 -5
  31. package/dist/blocks/lab-config.d.mts +1 -1
  32. package/dist/blocks/lab-config.mjs +4 -4
  33. package/dist/blocks/lab-gallery.d.mts +1 -1
  34. package/dist/blocks/lab-gallery.mjs +2 -2
  35. package/dist/blocks/language.d.mts +6 -6
  36. package/dist/blocks/language.mjs +12 -12
  37. package/dist/blocks/lesson.mjs +4 -4
  38. package/dist/blocks/math.d.mts +577 -11
  39. package/dist/blocks/math.mjs +1648 -14
  40. package/dist/blocks/ml.d.mts +45 -1
  41. package/dist/blocks/ml.mjs +80 -6
  42. package/dist/blocks/physics.d.mts +9 -4
  43. package/dist/blocks/physics.mjs +75 -28
  44. package/dist/blocks/statistics.mjs +1 -1
  45. package/dist/build/CircuitEditor.d.mts +14 -0
  46. package/dist/build/CircuitEditor.mjs +787 -0
  47. package/dist/build/CircuitPlayer.d.mts +19 -0
  48. package/dist/build/CircuitPlayer.mjs +53 -0
  49. package/dist/build/CircuitScene.d.mts +61 -0
  50. package/dist/build/CircuitScene.mjs +383 -0
  51. package/dist/build/contract.d.mts +116 -0
  52. package/dist/build/editor-ops.d.mts +65 -0
  53. package/dist/build/editor-ops.mjs +306 -0
  54. package/dist/build/editor-ui.mjs +121 -0
  55. package/dist/build/flow.d.mts +14 -0
  56. package/dist/build/flow.mjs +119 -0
  57. package/dist/build/index.d.mts +10 -0
  58. package/dist/build/index.mjs +10 -0
  59. package/dist/build/parts/ammeter.d.mts +1 -0
  60. package/dist/build/parts/ammeter.mjs +32 -0
  61. package/dist/build/parts/bulb.d.mts +1 -0
  62. package/dist/build/parts/bulb.mjs +50 -0
  63. package/dist/build/parts/capacitor.d.mts +1 -0
  64. package/dist/build/parts/capacitor.mjs +26 -0
  65. package/dist/build/parts/cell.d.mts +1 -0
  66. package/dist/build/parts/cell.mjs +40 -0
  67. package/dist/build/parts/diode.d.mts +1 -0
  68. package/dist/build/parts/diode.mjs +33 -0
  69. package/dist/build/parts/index.d.mts +5 -0
  70. package/dist/build/parts/index.mjs +43 -0
  71. package/dist/build/parts/mosfet.d.mts +1 -0
  72. package/dist/build/parts/mosfet.mjs +95 -0
  73. package/dist/build/parts/node.d.mts +1 -0
  74. package/dist/build/parts/node.mjs +32 -0
  75. package/dist/build/parts/resistor.d.mts +1 -0
  76. package/dist/build/parts/resistor.mjs +49 -0
  77. package/dist/build/parts/shared.mjs +42 -0
  78. package/dist/build/parts/switch.d.mts +1 -0
  79. package/dist/build/parts/switch.mjs +34 -0
  80. package/dist/build/parts.d.mts +1 -0
  81. package/dist/build/registry.d.mts +9 -0
  82. package/dist/build/registry.mjs +15 -0
  83. package/dist/build/solve.d.mts +8 -0
  84. package/dist/build/solve.mjs +0 -0
  85. package/dist/catalog/registry.d.mts +2 -2
  86. package/dist/catalog/templates.d.mts +1 -1
  87. package/dist/catalog/templates.mjs +6 -6
  88. package/dist/chem/battery.mjs +1 -1
  89. package/dist/chem/bohr-atom.mjs +4 -4
  90. package/dist/chem/diffusion/preset.mjs +4 -4
  91. package/dist/chem/electrochem/preset.mjs +5 -5
  92. package/dist/chem/equilibrium/preset.d.mts +1 -1
  93. package/dist/chem/equilibrium/preset.mjs +6 -6
  94. package/dist/chem/gas-box/preset.mjs +6 -6
  95. package/dist/chem/kinetics/preset.mjs +6 -6
  96. package/dist/chem/periodic-trends/preset.mjs +7 -7
  97. package/dist/chem/reaction-lab.mjs +3 -3
  98. package/dist/chem/reaction-profile.mjs +4 -4
  99. package/dist/chem/solution/dilution.mjs +6 -6
  100. package/dist/chem/solution/field.d.mts +2 -2
  101. package/dist/chem/solution/field.mjs +2 -2
  102. package/dist/chem/solution/solution-box.mjs +7 -7
  103. package/dist/chem/stoichiometry/preset.mjs +5 -5
  104. package/dist/chem/titration/preset.mjs +5 -5
  105. package/dist/circuits/ac-dc/asset.mjs +1 -1
  106. package/dist/circuits/ac-dc/preset.mjs +2 -2
  107. package/dist/circuits/brownout/index.d.mts +1 -0
  108. package/dist/circuits/brownout/preset.d.mts +22 -0
  109. package/dist/circuits/brownout/preset.mjs +399 -0
  110. package/dist/circuits/capacitor-leak/preset.mjs +13 -8
  111. package/dist/circuits/circuit/asset.mjs +71 -14
  112. package/dist/circuits/circuit/preset.mjs +23 -5
  113. package/dist/circuits/circuit-builder.mjs +60 -132
  114. package/dist/circuits/circuit-lab.mjs +60 -40
  115. package/dist/circuits/cmos-gate/index.d.mts +1 -0
  116. package/dist/circuits/cmos-gate/preset.d.mts +75 -0
  117. package/dist/circuits/cmos-gate/preset.mjs +1491 -0
  118. package/dist/circuits/diode/index.d.mts +1 -0
  119. package/dist/circuits/diode/preset.d.mts +25 -0
  120. package/dist/circuits/diode/preset.mjs +266 -0
  121. package/dist/circuits/index.d.mts +7 -1
  122. package/dist/circuits/index.mjs +7 -1
  123. package/dist/circuits/rc-charging/index.d.mts +1 -0
  124. package/dist/circuits/rc-charging/preset.d.mts +27 -0
  125. package/dist/circuits/rc-charging/preset.mjs +329 -0
  126. package/dist/circuits/semiconductor/index.d.mts +1 -0
  127. package/dist/circuits/semiconductor/preset.d.mts +102 -0
  128. package/dist/circuits/semiconductor/preset.mjs +1855 -0
  129. package/dist/circuits/transistor/index.d.mts +1 -0
  130. package/dist/circuits/transistor/preset.d.mts +27 -0
  131. package/dist/circuits/transistor/preset.mjs +329 -0
  132. package/dist/commerce/accounting/core.d.mts +1 -1
  133. package/dist/commerce/accounting/equation-balance.mjs +5 -5
  134. package/dist/commerce/accounting/journal-poster.mjs +8 -8
  135. package/dist/commerce/accounting/statement-sorter.mjs +4 -4
  136. package/dist/commerce/economics/core.d.mts +2 -2
  137. package/dist/commerce/economics/core.mjs +1 -1
  138. package/dist/commerce/economics/demand-shift-vs-move.mjs +6 -6
  139. package/dist/commerce/economics/elasticity-revenue.mjs +6 -6
  140. package/dist/commerce/economics/market-equilibrium.mjs +5 -5
  141. package/dist/core/easing.d.mts +3 -3
  142. package/dist/core/easing.mjs +2 -2
  143. package/dist/core/numeric.d.mts +3 -3
  144. package/dist/core/numeric.mjs +2 -2
  145. package/dist/core/reactive.d.mts +1 -1
  146. package/dist/core/reactive.mjs +1 -1
  147. package/dist/core/rng.d.mts +2 -2
  148. package/dist/core/rng.mjs +1 -1
  149. package/dist/core/tex.mjs +2 -2
  150. package/dist/core/timeline.d.mts +1 -1
  151. package/dist/core/timeline.mjs +1 -1
  152. package/dist/core/util.mjs +11 -1
  153. package/dist/discrete/arrangements/preset.mjs +6 -14
  154. package/dist/discrete/bayes/preset.mjs +43 -35
  155. package/dist/discrete/binomial/preset.mjs +2 -2
  156. package/dist/discrete/combination-studio/figure.d.mts +6 -0
  157. package/dist/discrete/combination-studio/figure.mjs +159 -0
  158. package/dist/discrete/combination-studio/index.d.mts +2 -0
  159. package/dist/discrete/combination-studio/preset.d.mts +44 -0
  160. package/dist/discrete/combination-studio/preset.mjs +440 -0
  161. package/dist/discrete/core/combinatorics.d.mts +23 -3
  162. package/dist/discrete/core/combinatorics.mjs +38 -3
  163. package/dist/discrete/core/pigeonhole.d.mts +1 -1
  164. package/dist/discrete/core/pigeonhole.mjs +1 -1
  165. package/dist/discrete/core/probability.d.mts +3 -3
  166. package/dist/discrete/core/probability.mjs +3 -3
  167. package/dist/discrete/core/sets.d.mts +1 -1
  168. package/dist/discrete/counting-slots/preset.mjs +8 -8
  169. package/dist/discrete/counting-tree/preset.mjs +65 -8
  170. package/dist/discrete/expected-value/preset.mjs +13 -13
  171. package/dist/discrete/hypergeometric/preset.mjs +48 -15
  172. package/dist/discrete/index.d.mts +4 -2
  173. package/dist/discrete/index.mjs +4 -2
  174. package/dist/discrete/karnaugh/preset.mjs +26 -20
  175. package/dist/discrete/lln/preset.mjs +44 -3
  176. package/dist/discrete/logic-circuit/preset.mjs +2 -2
  177. package/dist/discrete/monte-carlo/preset.d.mts +1 -1
  178. package/dist/discrete/monte-carlo/preset.mjs +14 -14
  179. package/dist/discrete/monty-hall/preset.mjs +6 -6
  180. package/dist/discrete/outcome-builder/preset.mjs +3 -3
  181. package/dist/discrete/pascal/preset.mjs +37 -7
  182. package/dist/discrete/rules.d.mts +20 -0
  183. package/dist/discrete/rules.mjs +264 -0
  184. package/dist/discrete/sample-space/preset.mjs +4 -4
  185. package/dist/discrete/selection/preset.mjs +7 -13
  186. package/dist/discrete/truth-table/preset.mjs +32 -9
  187. package/dist/discrete/venn/preset.mjs +71 -48
  188. package/dist/geography/cycle-lab/preset.mjs +17 -10
  189. package/dist/geography/cycles.d.mts +3 -3
  190. package/dist/geography/cycles.mjs +3 -3
  191. package/dist/geometry/board/preset.d.mts +2 -0
  192. package/dist/geometry/board/preset.mjs +11 -15
  193. package/dist/geometry/builder.mjs +3 -3
  194. package/dist/ict/number-systems/base-odometer.mjs +4 -4
  195. package/dist/ict/number-systems/bit-grouper.d.mts +1 -1
  196. package/dist/ict/number-systems/bit-grouper.mjs +4 -4
  197. package/dist/ict/number-systems/place-value-dial.d.mts +1 -1
  198. package/dist/ict/number-systems/place-value-dial.mjs +3 -3
  199. package/dist/ict/number-systems/wheel.d.mts +3 -3
  200. package/dist/ict/number-systems/wheel.mjs +4 -4
  201. package/dist/kit/annotate.mjs +3 -3
  202. package/dist/kit/answer-check.d.mts +2 -2
  203. package/dist/kit/answer-check.mjs +34 -6
  204. package/dist/kit/ask.d.mts +19 -0
  205. package/dist/kit/ask.mjs +46 -0
  206. package/dist/kit/bar-strip.mjs +53 -0
  207. package/dist/kit/calc.d.mts +33 -0
  208. package/dist/kit/calc.mjs +27 -0
  209. package/dist/kit/carrier-engine.mjs +147 -0
  210. package/dist/kit/clue-scene.d.mts +86 -0
  211. package/dist/kit/clue-scene.mjs +424 -0
  212. package/dist/kit/cluster.d.mts +30 -0
  213. package/dist/kit/cluster.mjs +81 -0
  214. package/dist/kit/controls.mjs +11 -5
  215. package/dist/kit/coords.d.mts +88 -0
  216. package/dist/kit/coords.mjs +192 -0
  217. package/dist/kit/data-scene.d.mts +27 -0
  218. package/dist/kit/data-scene.mjs +199 -0
  219. package/dist/kit/diagram.mjs +111 -50
  220. package/dist/kit/electronics.mjs +552 -60
  221. package/dist/kit/expr-analysis.d.mts +18 -6
  222. package/dist/kit/expr-analysis.mjs +82 -28
  223. package/dist/kit/frame.d.mts +3 -3
  224. package/dist/kit/frame.mjs +25 -6
  225. package/dist/kit/gameshow.mjs +2 -2
  226. package/dist/kit/index.d.mts +14 -2
  227. package/dist/kit/index.mjs +13 -1
  228. package/dist/kit/logic-gates.mjs +246 -47
  229. package/dist/kit/palette.mjs +26 -0
  230. package/dist/kit/pedagogy.d.mts +4 -4
  231. package/dist/kit/pedagogy.mjs +21 -17
  232. package/dist/kit/play.d.mts +1 -1
  233. package/dist/kit/play.mjs +3 -3
  234. package/dist/kit/predict.d.mts +55 -0
  235. package/dist/kit/predict.mjs +146 -0
  236. package/dist/kit/receipt.d.mts +29 -0
  237. package/dist/kit/receipt.mjs +94 -0
  238. package/dist/kit/rich.mjs +2 -2
  239. package/dist/kit/rule.d.mts +59 -0
  240. package/dist/kit/rule.mjs +215 -0
  241. package/dist/kit/scale.mjs +1 -1
  242. package/dist/kit/scene-library.d.mts +22 -0
  243. package/dist/kit/scene-library.mjs +311 -0
  244. package/dist/kit/scene-studio.d.mts +14 -0
  245. package/dist/kit/scene-studio.mjs +338 -0
  246. package/dist/kit/scenes.d.mts +31 -0
  247. package/dist/kit/scenes.mjs +569 -0
  248. package/dist/kit/slot-fill.d.mts +61 -0
  249. package/dist/kit/slot-fill.mjs +207 -0
  250. package/dist/kit/solve.d.mts +21 -0
  251. package/dist/kit/solve.mjs +75 -0
  252. package/dist/kit/space.mjs +5 -5
  253. package/dist/kit/steps.mjs +2 -2
  254. package/dist/kit/vessel.d.mts +69 -0
  255. package/dist/kit/vessel.mjs +191 -0
  256. package/dist/language/agreement/preset.mjs +2 -2
  257. package/dist/language/article-lens/preset.d.mts +1 -1
  258. package/dist/language/article-lens/preset.mjs +8 -8
  259. package/dist/language/deck.d.mts +3 -3
  260. package/dist/language/deck.mjs +1 -1
  261. package/dist/language/preposition-scene/preset.d.mts +2 -2
  262. package/dist/language/preposition-scene/preset.mjs +5 -5
  263. package/dist/language/sentence-builder/preset.mjs +5 -5
  264. package/dist/language/transform/preset.d.mts +2 -2
  265. package/dist/language/transform/preset.mjs +5 -5
  266. package/dist/language/ui.d.mts +3 -3
  267. package/dist/language/ui.mjs +4 -4
  268. package/dist/language/word-match/preset.mjs +3 -3
  269. package/dist/logic/LogicBuildLab.d.mts +22 -0
  270. package/dist/logic/LogicBuildLab.mjs +170 -0
  271. package/dist/logic/LogicEditScene.d.mts +31 -0
  272. package/dist/logic/LogicEditScene.mjs +276 -0
  273. package/dist/logic/LogicEditor.d.mts +14 -0
  274. package/dist/logic/LogicEditor.mjs +413 -0
  275. package/dist/logic/LogicScene.d.mts +32 -0
  276. package/dist/logic/LogicScene.mjs +277 -0
  277. package/dist/logic/contract.d.mts +72 -0
  278. package/dist/logic/display.d.mts +24 -0
  279. package/dist/logic/display.mjs +127 -0
  280. package/dist/logic/edit-ops.d.mts +44 -0
  281. package/dist/logic/edit-ops.mjs +177 -0
  282. package/dist/logic/evaluate.d.mts +11 -0
  283. package/dist/logic/evaluate.mjs +93 -0
  284. package/dist/logic/gates.d.mts +10 -0
  285. package/dist/logic/gates.mjs +73 -0
  286. package/dist/logic/index.d.mts +14 -0
  287. package/dist/logic/index.mjs +13 -0
  288. package/dist/logic/lab.d.mts +32 -0
  289. package/dist/logic/lab.mjs +160 -0
  290. package/dist/logic/presets.d.mts +12 -0
  291. package/dist/logic/presets.mjs +241 -0
  292. package/dist/logic/registry.d.mts +9 -0
  293. package/dist/logic/registry.mjs +15 -0
  294. package/dist/math/area-model/preset.mjs +70 -44
  295. package/dist/math/balance-algebra/preset.mjs +14 -5
  296. package/dist/math/broken-tree/index.d.mts +1 -0
  297. package/dist/math/broken-tree/preset.d.mts +26 -0
  298. package/dist/math/broken-tree/preset.mjs +435 -0
  299. package/dist/math/circle/index.d.mts +1 -0
  300. package/dist/math/circle/preset.d.mts +44 -0
  301. package/dist/math/circle/preset.mjs +198 -0
  302. package/dist/math/complex/core.d.mts +93 -0
  303. package/dist/math/complex/core.mjs +239 -0
  304. package/dist/math/complex/index.d.mts +3 -0
  305. package/dist/math/complex/preset.d.mts +31 -0
  306. package/dist/math/complex/preset.mjs +377 -0
  307. package/dist/math/complex/rules.d.mts +6 -0
  308. package/dist/math/complex/rules.mjs +121 -0
  309. package/dist/math/conic/index.d.mts +1 -0
  310. package/dist/math/conic/preset.d.mts +30 -0
  311. package/dist/math/conic/preset.mjs +334 -0
  312. package/dist/math/derivation.mjs +5 -5
  313. package/dist/math/derivative-explorer/preset.mjs +5 -5
  314. package/dist/math/domain-range/index.d.mts +1 -0
  315. package/dist/math/domain-range/preset.d.mts +33 -0
  316. package/dist/math/domain-range/preset.mjs +313 -0
  317. package/dist/math/fraction-bar/index.d.mts +1 -0
  318. package/dist/math/fraction-bar/preset.d.mts +27 -0
  319. package/dist/math/fraction-bar/preset.mjs +197 -0
  320. package/dist/math/function-machine/preset.mjs +2 -2
  321. package/dist/math/gradient-descent.mjs +6 -6
  322. package/dist/math/grapher/preset.d.mts +1 -1
  323. package/dist/math/grapher/preset.mjs +4 -4
  324. package/dist/math/harmonic-form/preset.mjs +6 -6
  325. package/dist/math/index.d.mts +27 -2
  326. package/dist/math/index.mjs +27 -2
  327. package/dist/math/integral-explorer/preset.mjs +2 -2
  328. package/dist/math/interactive/preset.mjs +3 -3
  329. package/dist/math/limit-explorer/preset.mjs +4 -4
  330. package/dist/math/linear-model/index.d.mts +1 -0
  331. package/dist/math/linear-model/preset.d.mts +53 -0
  332. package/dist/math/linear-model/preset.mjs +164 -0
  333. package/dist/math/linear-system/preset.mjs +4 -4
  334. package/dist/math/mystery-bucket/preset.mjs +6 -6
  335. package/dist/math/number-line/preset.mjs +3 -2
  336. package/dist/math/parabola/preset.mjs +4 -3
  337. package/dist/math/pattern/preset.mjs +7 -13
  338. package/dist/math/percent-bar/index.d.mts +1 -0
  339. package/dist/math/percent-bar/preset.d.mts +37 -0
  340. package/dist/math/percent-bar/preset.mjs +275 -0
  341. package/dist/math/poly/core.d.mts +50 -0
  342. package/dist/math/poly/core.mjs +268 -0
  343. package/dist/math/poly/index.d.mts +3 -0
  344. package/dist/math/poly/preset.d.mts +23 -0
  345. package/dist/math/poly/preset.mjs +141 -0
  346. package/dist/math/poly/steps.d.mts +10 -0
  347. package/dist/math/poly/steps.mjs +99 -0
  348. package/dist/math/rate-machine/index.d.mts +1 -0
  349. package/dist/math/rate-machine/preset.d.mts +35 -0
  350. package/dist/math/rate-machine/preset.mjs +281 -0
  351. package/dist/math/ratio-share/index.d.mts +1 -0
  352. package/dist/math/ratio-share/preset.d.mts +24 -0
  353. package/dist/math/ratio-share/preset.mjs +204 -0
  354. package/dist/math/receipt/index.d.mts +1 -0
  355. package/dist/math/receipt/preset.d.mts +22 -0
  356. package/dist/math/receipt/preset.mjs +137 -0
  357. package/dist/math/sequence-predict/index.d.mts +1 -0
  358. package/dist/math/sequence-predict/preset.d.mts +34 -0
  359. package/dist/math/sequence-predict/preset.mjs +130 -0
  360. package/dist/math/straight-line/index.d.mts +1 -0
  361. package/dist/math/straight-line/preset.d.mts +37 -0
  362. package/dist/math/straight-line/preset.mjs +374 -0
  363. package/dist/math/system-solve/index.d.mts +1 -0
  364. package/dist/math/system-solve/preset.d.mts +21 -0
  365. package/dist/math/system-solve/preset.mjs +227 -0
  366. package/dist/math/transform/index.d.mts +1 -0
  367. package/dist/math/transform/preset.d.mts +41 -0
  368. package/dist/math/transform/preset.mjs +343 -0
  369. package/dist/math/triangle-trig/preset.mjs +12 -9
  370. package/dist/math/trig/core.d.mts +37 -0
  371. package/dist/math/trig/core.mjs +150 -0
  372. package/dist/math/trig/diagrams.d.mts +1 -0
  373. package/dist/math/trig/diagrams.mjs +321 -0
  374. package/dist/math/trig/index.d.mts +3 -0
  375. package/dist/math/trig/preset.d.mts +25 -0
  376. package/dist/math/trig/preset.mjs +260 -0
  377. package/dist/math/trig/rules.d.mts +6 -0
  378. package/dist/math/trig/rules.mjs +159 -0
  379. package/dist/math/trig-explorer.mjs +4 -4
  380. package/dist/ml/boundary/preset.mjs +8 -3
  381. package/dist/ml/classifier/preset.mjs +31 -6
  382. package/dist/ml/kmeans/preset.mjs +4 -4
  383. package/dist/ml/knn/preset.mjs +47 -12
  384. package/dist/ml/regression/preset.mjs +36 -7
  385. package/dist/physics/atwood/preset.mjs +4 -4
  386. package/dist/physics/bullet-walls/preset.d.mts +1 -1
  387. package/dist/physics/bullet-walls/preset.mjs +7 -7
  388. package/dist/physics/carnot/preset.mjs +6 -6
  389. package/dist/physics/circular-motion/preset.mjs +36 -5
  390. package/dist/physics/collision-track/preset.mjs +35 -5
  391. package/dist/physics/efficiency/preset.d.mts +2 -2
  392. package/dist/physics/efficiency/preset.mjs +5 -5
  393. package/dist/physics/electric-field/preset.mjs +32 -23
  394. package/dist/physics/electric-flux/index.d.mts +1 -0
  395. package/dist/physics/electric-flux/preset.d.mts +29 -0
  396. package/dist/physics/electric-flux/preset.mjs +264 -0
  397. package/dist/physics/energy-skate/preset.mjs +5 -5
  398. package/dist/physics/entropy/preset.mjs +7 -7
  399. package/dist/physics/expansion/preset.mjs +13 -13
  400. package/dist/physics/exponential/asset.mjs +1 -1
  401. package/dist/physics/exponential/preset.mjs +4 -4
  402. package/dist/physics/gas-process/preset.mjs +3 -3
  403. package/dist/physics/gauss-law/index.d.mts +1 -0
  404. package/dist/physics/gauss-law/preset.d.mts +20 -0
  405. package/dist/physics/gauss-law/preset.mjs +286 -0
  406. package/dist/physics/gravitation/preset.mjs +7 -7
  407. package/dist/physics/gravity-drop.mjs +4 -4
  408. package/dist/physics/heat-transfer/preset.d.mts +1 -1
  409. package/dist/physics/heat-transfer/preset.mjs +10 -10
  410. package/dist/physics/impulse/preset.mjs +5 -5
  411. package/dist/physics/index.d.mts +4 -1
  412. package/dist/physics/index.mjs +4 -1
  413. package/dist/physics/kepler/preset.mjs +4 -4
  414. package/dist/physics/lever/preset.mjs +3 -3
  415. package/dist/physics/lorentz/preset.mjs +11 -11
  416. package/dist/physics/magnetism/preset.mjs +3 -3
  417. package/dist/physics/optics/preset.mjs +2 -2
  418. package/dist/physics/orbit-lab.mjs +5 -5
  419. package/dist/physics/projectile-lab.mjs +4 -4
  420. package/dist/physics/rain-relative/preset.mjs +5 -5
  421. package/dist/physics/ramp-forces/preset.mjs +5 -5
  422. package/dist/physics/river-boat.mjs +6 -6
  423. package/dist/physics/shm/preset.mjs +9 -9
  424. package/dist/physics/stopping-distance/preset.mjs +3 -3
  425. package/dist/physics/temperature-scales/preset.mjs +105 -116
  426. package/dist/physics/terminal-velocity/preset.mjs +5 -5
  427. package/dist/physics/thermal/preset.mjs +5 -5
  428. package/dist/physics/vector-board/preset.mjs +7 -6
  429. package/dist/physics/vector-scene.mjs +2 -2
  430. package/dist/physics/vector-types/preset.mjs +37 -3
  431. package/dist/physics/water-density/preset.mjs +12 -12
  432. package/dist/physics/waves/doppler.mjs +2 -2
  433. package/dist/physics/waves/preset.mjs +4 -4
  434. package/dist/physics/waves/ripple.mjs +6 -6
  435. package/dist/physics/waves/string.mjs +5 -5
  436. package/dist/physics/work-energy/preset.mjs +4 -4
  437. package/dist/physics/work-potential/index.d.mts +1 -0
  438. package/dist/physics/work-potential/preset.d.mts +20 -0
  439. package/dist/physics/work-potential/preset.mjs +276 -0
  440. package/dist/schemas/index.d.mts +6 -6
  441. package/dist/schemas/index.mjs +3 -3
  442. package/dist/statistics/center-spread/preset.mjs +3 -3
  443. package/dist/statistics/core/descriptive.d.mts +2 -2
  444. package/dist/statistics/core/descriptive.mjs +2 -2
  445. package/dist/statistics/core/normal.d.mts +3 -3
  446. package/dist/statistics/core/normal.mjs +3 -3
  447. package/dist/statistics/core/sequences.d.mts +1 -1
  448. package/dist/statistics/galton/preset.mjs +2 -2
  449. package/dist/statistics/histogram/preset.mjs +6 -6
  450. package/dist/statistics/normal/preset.mjs +2 -2
  451. package/dist/statistics/sampling/preset.mjs +4 -4
  452. package/dist/statistics/sequence/preset.mjs +58 -15
  453. package/dist/statistics/z-table/preset.mjs +17 -4
  454. package/package.json +11 -3
  455. package/styles.css +4 -1
@@ -10,9 +10,9 @@ import { Scene, registerAsset } from "@classytic/stage";
10
10
 
11
11
  //#region src/chem/diffusion/preset.tsx
12
12
  /**
13
- * DiffusionLab — two gases, one box: the `particles` core made tangible. The blue
13
+ * DiffusionLab, two gases, one box: the `particles` core made tangible. The blue
14
14
  * and red particles start on opposite sides; press Play and they random-walk into a
15
- * uniform mix — diffusion, and why it never spontaneously un-mixes. Hotter (faster)
15
+ * uniform mix, diffusion, and why it never spontaneously un-mixes. Hotter (faster)
16
16
  * particles mix sooner. SceneDoc + particles sim + the diffusion asset (sim ≠ render).
17
17
  */
18
18
  registerAsset("diffusion", DIFFUSION_ASSET);
@@ -23,7 +23,7 @@ const DIFFUSION_CHALLENGE = [{
23
23
  choices: [
24
24
  {
25
25
  value: "no",
26
- label: "No — mixing is one-way"
26
+ label: "No: mixing is one-way"
27
27
  },
28
28
  {
29
29
  value: "wait",
@@ -56,7 +56,7 @@ const DIFFUSION_CHALLENGE = [{
56
56
  answer: "faster",
57
57
  explain: "Faster particles travel and collide more, so the uniform mix is reached sooner."
58
58
  }];
59
- function DiffusionLab({ title = "Diffusion — why things mix", prompt = "Blue and red gas start apart. Press Play: random collisions spread them into a uniform mix — and it never un-mixes on its own.", objectives = [
59
+ function DiffusionLab({ title = "Diffusion: why things mix", prompt = "Blue and red gas start apart. Press Play: random collisions spread them into a uniform mix, and it never un-mixes on its own.", objectives = [
60
60
  "See diffusion as random motion, not a force",
61
61
  "Watch two gases mix to uniform (the \"mixed %\" climbs)",
62
62
  "Hotter (faster) particles mix sooner"
@@ -11,16 +11,16 @@ import { galvanicCell } from "@classytic/stage/chem";
11
11
 
12
12
  //#region src/chem/electrochem/preset.tsx
13
13
  /**
14
- * ElectrochemLab — a galvanic (voltaic) cell with a live voltmeter, on the shared
14
+ * ElectrochemLab, a galvanic (voltaic) cell with a live voltmeter, on the shared
15
15
  * `@classytic/stage/chem` Nernst engine. Two metal/metal-ion half-cells joined by a
16
16
  * salt bridge: the metal that's easier to oxidise (lower E°) becomes the ANODE (−),
17
17
  * the other the CATHODE (+), and electrons stream anode→cathode through the wire.
18
18
  *
19
19
  * The voltmeter reads the Nernst EMF E = E°cell − (RT/nF)·ln Q, so dragging an ion
20
- * concentration moves the needle in real time — dilute the cathode ion and the
20
+ * concentration moves the needle in real time, dilute the cathode ion and the
21
21
  * voltage drops; pick the SAME metal both sides for a concentration cell (E° = 0,
22
22
  * driven purely by the concentration difference). Pick the two electrodes (Daniell
23
- * Zn/Cu by default) — fully authorable. Play-gated electron flow; pure SVG.
23
+ * Zn/Cu by default), fully authorable. Play-gated electron flow; pure SVG.
24
24
  */
25
25
  const METALS = {
26
26
  Mg: {
@@ -89,7 +89,7 @@ const hc = (m, conc) => ({
89
89
  E0: METALS[m].E0,
90
90
  conc
91
91
  });
92
- function ElectrochemLab({ metalA = "Zn", metalB = "Cu", concA = 1, concB = 1, title = "Galvanic cell — the voltage from a reaction", prompt = "Two metals in their salt solutions, joined by a wire and a salt bridge. The voltmeter reads the cell EMF from the Nernst equation — change a concentration and watch it move.", objectives = [
92
+ function ElectrochemLab({ metalA = "Zn", metalB = "Cu", concA = 1, concB = 1, title = "Galvanic cell: the voltage from a reaction", prompt = "Two metals in their salt solutions, joined by a wire and a salt bridge. The voltmeter reads the cell EMF from the Nernst equation, change a concentration and watch it move.", objectives = [
93
93
  "Identify the anode (oxidation, −) and cathode (reduction, +) from E°",
94
94
  "Read the standard cell EMF E°cell = E°cathode − E°anode",
95
95
  "Use the Nernst equation E = E°cell − (RT/nF)·ln Q to see concentration shift the voltage"
@@ -335,7 +335,7 @@ function ElectrochemLab({ metalA = "Zn", metalB = "Cu", concA = 1, concB = 1, ti
335
335
  }),
336
336
  " is the cathode (reduced). ",
337
337
  sameMetal ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
338
- "Same metal both sides ⇒ E°cell = 0 — this is a ",
338
+ "Same metal both sides ⇒ E°cell = 0, this is a ",
339
339
  /* @__PURE__ */ jsx("strong", {
340
340
  style: { color: "var(--stage-fg)" },
341
341
  children: "concentration cell"
@@ -8,7 +8,7 @@ interface LeChatelierProps {
8
8
  productName?: string;
9
9
  /** Product stoichiometric coefficient ν (A ⇌ ν·B). */
10
10
  productCoeff?: number;
11
- /** Product colour token — the flask tints toward this as product forms. */
11
+ /** Product colour token, the flask tints toward this as product forms. */
12
12
  productColor?: string;
13
13
  /** Reactant colour token. */
14
14
  reactantColor?: string;
@@ -12,10 +12,10 @@ import { EquilibriumCore } from "@classytic/stage/sim";
12
12
 
13
13
  //#region src/chem/equilibrium/preset.tsx
14
14
  /**
15
- * LeChatelierLab — a reversible reaction at equilibrium that fights back, on the
15
+ * LeChatelierLab, a reversible reaction at equilibrium that fights back, on the
16
16
  * shared `equilibrium` core. The reaction is AUTHORABLE: a creator declares the two
17
17
  * species, the product coefficient, the colours, K, and whether the forward reaction
18
- * is endothermic — so the SAME lab teaches N₂O₄⇌2NO₂ (brown/colourless), the
18
+ * is endothermic, so the SAME lab teaches N₂O₄⇌2NO₂ (brown/colourless), the
19
19
  * chromate⇌dichromate colour change, a cobalt-complex equilibrium, and so on. The
20
20
  * default is the classic:
21
21
  *
@@ -23,7 +23,7 @@ import { EquilibriumCore } from "@classytic/stage/sim";
23
23
  *
24
24
  * The flask tint tracks the product; concentration bars + a live trace show both.
25
25
  * Apply a stress (add a species, compress, heat/cool) and watch Le Chatelier shift
26
- * it to oppose the change — the SHIFT DIRECTION emerges from the core's Q-vs-K, never
26
+ * it to oppose the change, the SHIFT DIRECTION emerges from the core's Q-vs-K, never
27
27
  * hardcoded, so it stays correct for whatever reaction the creator declares.
28
28
  * Hand-driven on EquilibriumCore, play-gated.
29
29
  */
@@ -48,7 +48,7 @@ const EQUILIBRIUM_CHALLENGE = [{
48
48
  }
49
49
  ],
50
50
  answer: "reactant",
51
- explain: "Squeezing favours the side with fewer gas moles — 1 mol N₂O₄ beats 2 mol NO₂, so the mix goes paler."
51
+ explain: "Squeezing favours the side with fewer gas moles, 1 mol N₂O₄ beats 2 mol NO₂, so the mix goes paler."
52
52
  }, {
53
53
  id: "heat",
54
54
  prompt: "The forward reaction is endothermic. Heating the flask makes the mix…",
@@ -69,7 +69,7 @@ const EQUILIBRIUM_CHALLENGE = [{
69
69
  answer: "browner",
70
70
  explain: "Heat is a reactant for an endothermic forward step, so it drives more NO₂ (browner) and raises K."
71
71
  }];
72
- function LeChatelierLab({ reactantName = "N₂O₄", productName = "NO₂", productCoeff = 2, productColor = "rgb(150,82,40)", reactantColor = "var(--stage-accent, #3b82f6)", K = .6, endothermic = true, title = "Le Chatelier — equilibrium fights back", prompt = "A reversible reaction sits at equilibrium (Q = K). Stress it — add a gas, squeeze it, heat it — and watch the reaction shift to oppose the change.", objectives = [
72
+ function LeChatelierLab({ reactantName = "N₂O₄", productName = "NO₂", productCoeff = 2, productColor = "rgb(150,82,40)", reactantColor = "var(--stage-accent, #3b82f6)", K = .6, endothermic = true, title = "Le Chatelier: equilibrium fights back", prompt = "A reversible reaction sits at equilibrium (Q = K). Stress it, add a gas, squeeze it, heat it, and watch the reaction shift to oppose the change.", objectives = [
73
73
  "Read equilibrium as Q = K (the reaction quotient meets the constant)",
74
74
  "Predict the shift when you add/remove a species or change the volume",
75
75
  "See heating favour the endothermic side and change K itself"
@@ -335,7 +335,7 @@ function LeChatelierLab({ reactantName = "N₂O₄", productName = "NO₂", prod
335
335
  }),
336
336
  ". Add a species and it’s consumed; compress and it shifts to fewer moles; ",
337
337
  endothermic ? "heat and the endothermic forward reaction wins" : "heat and the exothermic reverse reaction wins",
338
- " — and K itself changes with temperature."
338
+ ", and K itself changes with temperature."
339
339
  ]
340
340
  })]
341
341
  })] }),
@@ -12,17 +12,17 @@ import { CanvasLayer, fmt } from "@classytic/stage";
12
12
 
13
13
  //#region src/chem/gas-box/preset.tsx
14
14
  /**
15
- * GasBoxLab — gas in a box: pressure you can watch being MADE.
15
+ * GasBoxLab, gas in a box: pressure you can watch being MADE.
16
16
  *
17
17
  * Hundreds of molecules bounce in a box on <CanvasLayer>; drag the piston to set
18
18
  * volume, slide temperature (every molecule speeds up, cool→hot colour) and amount
19
- * n (dots appear/vanish). Pressure is NOT a control — it is MEASURED from how often
19
+ * n (dots appear/vanish). Pressure is NOT a control, it is MEASURED from how often
20
20
  * + how hard the molecules drum the walls (each wall strike flashes), so PV=nRT
21
21
  * emerges from the mechanism instead of being plugged in. A "hold constant" lock
22
22
  * yields Boyle (lock T), Gay-Lussac (lock V), Charles (lock P → piston floats).
23
23
  *
24
24
  * The kinetic-theory algebra (P = ⅓(N/V)m⟨v²⟩ → PV=nRT) lives in a PAIRED
25
- * MathDerivation block, not here — the sim makes it felt, the derivation proves it.
25
+ * MathDerivation block, not here, the sim makes it felt, the derivation proves it.
26
26
  * SVG gauge/readouts overlay the canvas; honours prefers-reduced-motion.
27
27
  */
28
28
  const GASBOX_CHALLENGE = [{
@@ -43,7 +43,7 @@ const GASBOX_CHALLENGE = [{
43
43
  }
44
44
  ],
45
45
  answer: "double",
46
- explain: "Same molecules strike half the space twice as often — Boyle’s law, P ∝ 1/V."
46
+ explain: "Same molecules strike half the space twice as often, Boyle’s law, P ∝ 1/V."
47
47
  }, {
48
48
  id: "gaylussac",
49
49
  prompt: "Hold the volume fixed and HEAT the gas. The pressure…",
@@ -62,12 +62,12 @@ const GASBOX_CHALLENGE = [{
62
62
  }
63
63
  ],
64
64
  answer: "rise",
65
- explain: "Hotter molecules move faster and hit the walls harder and more often — Gay-Lussac, P ∝ T."
65
+ explain: "Hotter molecules move faster and hit the walls harder and more often, Gay-Lussac, P ∝ T."
66
66
  }];
67
67
  const H = 6, MAXV = 10, MINV = 2.5, R = .13, MAXN = 320;
68
68
  const T0 = 300, SPEED0 = 5.5, TMIN = 80, TMAX = 600;
69
69
  const PDISP = 1.5;
70
- function GasBoxLab({ holdConstant = "none", particleCount = 180, temperature = 300, volume = 7, showGauge = true, title = "Gas in a box — watch pressure being made", prompt = "Drag the piston, heat it up, add molecules. Pressure is the drumbeat of hits on the walls.", height = 300, objectives }) {
70
+ function GasBoxLab({ holdConstant = "none", particleCount = 180, temperature = 300, volume = 7, showGauge = true, title = "Gas in a box: watch pressure being made", prompt = "Drag the piston, heat it up, add molecules. Pressure is the drumbeat of hits on the walls.", height = 300, objectives }) {
71
71
  const [mode, setMode] = useState(holdConstant);
72
72
  const [vol, setVol] = useState(clamp(volume, MINV, MAXV));
73
73
  const [temp, setTemp] = useState(clamp(temperature, TMIN, TMAX));
@@ -12,9 +12,9 @@ import { R, fractionAboveEa, halfLife } from "@classytic/stage/chem";
12
12
 
13
13
  //#region src/chem/kinetics/preset.tsx
14
14
  /**
15
- * KineticsLab — why heat and catalysts speed reactions, shown the visceral way: a
15
+ * KineticsLab, why heat and catalysts speed reactions, shown the visceral way: a
16
16
  * vessel of molecules bouncing around (faster when hot), where only collisions with
17
- * enough energy (≥ Eₐ) succeed — those flash and convert reactant A → product B.
17
+ * enough energy (≥ Eₐ) succeed, those flash and convert reactant A → product B.
18
18
  * Beside it, the Maxwell–Boltzmann energy spread shows the SAME story as the shaded
19
19
  * "can react" tail past Eₐ, and a composition bar tracks A→B in real time.
20
20
  *
@@ -49,7 +49,7 @@ const KINETICS_CHALLENGE = [{
49
49
  }
50
50
  ],
51
51
  answer: "energy",
52
- explain: "Heat widens the energy spread, so a larger fraction (e^(−Eₐ/RT)) clears the barrier — and they move faster, so collide more often."
52
+ explain: "Heat widens the energy spread, so a larger fraction (e^(−Eₐ/RT)) clears the barrier, and they move faster, so collide more often."
53
53
  }, {
54
54
  id: "cat",
55
55
  prompt: "A catalyst speeds a reaction by…",
@@ -68,9 +68,9 @@ const KINETICS_CHALLENGE = [{
68
68
  }
69
69
  ],
70
70
  answer: "lowerEa",
71
- explain: "A catalyst offers a lower-Eₐ path, so far more collisions succeed — without being used up or changing the energy of reactants/products."
71
+ explain: "A catalyst offers a lower-Eₐ path, so far more collisions succeed, without being used up or changing the energy of reactants/products."
72
72
  }];
73
- function KineticsLab({ EaKJ = 50, kRef = .6, order = 1, molecules = 30, T0 = 300, title = "Reaction rate — temperature, activation energy & collisions", prompt = "Molecules must collide with enough energy (≥ Eₐ) to react. Heat them up or lower Eₐ with a catalyst and watch many more collisions succeed.", objectives = [
73
+ function KineticsLab({ EaKJ = 50, kRef = .6, order = 1, molecules = 30, T0 = 300, title = "Reaction rate: temperature, activation energy & collisions", prompt = "Molecules must collide with enough energy (≥ Eₐ) to react. Heat them up or lower Eₐ with a catalyst and watch many more collisions succeed.", objectives = [
74
74
  "Explain rate by the collision model: enough-energy collisions react",
75
75
  "See temperature widen the energy spread so more molecules clear Eₐ",
76
76
  "Use Arrhenius k = A·e^(−Eₐ/RT); see a catalyst lower Eₐ, not ΔH"
@@ -417,7 +417,7 @@ function KineticsLab({ EaKJ = 50, kRef = .6, order = 1, molecules = 30, T0 = 300
417
417
  children: ["Only collisions with energy ≥ Eₐ react. ", catalyst ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("strong", {
418
418
  style: { color: B_COL },
419
419
  children: "Catalyst on"
420
- }), " — Eₐ is lowered, so far more collisions succeed (ΔH is unchanged)."] }) : /* @__PURE__ */ jsx(Fragment$1, { children: "Heat the vessel and the energy spread widens, pushing more molecules past Eₐ." })]
420
+ }), ", Eₐ is lowered, so far more collisions succeed (ΔH is unchanged)."] }) : /* @__PURE__ */ jsx(Fragment$1, { children: "Heat the vessel and the energy spread widens, pushing more molecules past Eₐ." })]
421
421
  })]
422
422
  })] });
423
423
  const footer = /* @__PURE__ */ jsx(ChallengeCard, {
@@ -9,12 +9,12 @@ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
9
9
 
10
10
  //#region src/chem/periodic-trends/preset.tsx
11
11
  /**
12
- * PeriodicTrendsLab — the periodic table as a heatmap, so a trend you usually have to
12
+ * PeriodicTrendsLab, the periodic table as a heatmap, so a trend you usually have to
13
13
  * memorise becomes a colour gradient you can read at a glance. Pick a property
14
14
  * (atomic radius, ionisation energy, electronegativity) and every tile recolours;
15
15
  * hover an element for its value. The gradients make the rules obvious: radius grows
16
16
  * DOWN and LEFT (toward caesium); ionisation energy and electronegativity grow UP and
17
- * RIGHT (toward fluorine). Periods 1–5 (H–Xe); a curated dataset, not a formula —
17
+ * RIGHT (toward fluorine). Periods 1–5 (H–Xe); a curated dataset, not a formula ,
18
18
  * which property is shown (and any highlighted element) is authorable, and a
19
19
  * predict-first question ships with it.
20
20
  */
@@ -602,7 +602,7 @@ const CHALLENGE = [{
602
602
  }
603
603
  ],
604
604
  answer: "down",
605
- explain: "More protons pull the same shell of electrons in tighter, so atoms shrink across a period — even as electrons are added."
605
+ explain: "More protons pull the same shell of electrons in tighter, so atoms shrink across a period, even as electrons are added."
606
606
  }, {
607
607
  id: "ie",
608
608
  prompt: "Ionisation energy is generally highest…",
@@ -623,7 +623,7 @@ const CHALLENGE = [{
623
623
  answer: "tr",
624
624
  explain: "Small, tightly-held atoms top-right cling hardest to their electrons, so they need the most energy to ionise."
625
625
  }];
626
- function PeriodicTrendsLab({ property: prop0 = "radius", highlight, title = "Periodic trends — read the table as a heatmap", prompt = "Colour every element by a property and the trend appears as a gradient. Hover an element for its value; switch the property to see the pattern flip.", objectives = [
626
+ function PeriodicTrendsLab({ property: prop0 = "radius", highlight, title = "Periodic trends: read the table as a heatmap", prompt = "Colour every element by a property and the trend appears as a gradient. Hover an element for its value; switch the property to see the pattern flip.", objectives = [
627
627
  "Read periodic trends as colour gradients across the table",
628
628
  "Atomic radius grows down a group and shrinks across a period",
629
629
  "Ionisation energy & electronegativity grow up and to the right"
@@ -664,7 +664,7 @@ function PeriodicTrendsLab({ property: prop0 = "radius", highlight, title = "Per
664
664
  children: [
665
665
  cfg.label,
666
666
  cfg.unit ? ` (${cfg.unit})` : "",
667
- " — ",
667
+ ", ",
668
668
  cfg.trend
669
669
  ]
670
670
  }),
@@ -767,7 +767,7 @@ function PeriodicTrendsLab({ property: prop0 = "radius", highlight, title = "Per
767
767
  children: [
768
768
  cfg.label,
769
769
  ": ",
770
- sel[cfg.idx] != null ? `${sel[cfg.idx]} ${cfg.unit}` : "—"
770
+ sel[cfg.idx] != null ? `${sel[cfg.idx]} ${cfg.unit}` : ", "
771
771
  ]
772
772
  })]
773
773
  }) : /* @__PURE__ */ jsxs("span", {
@@ -794,7 +794,7 @@ function PeriodicTrendsLab({ property: prop0 = "radius", highlight, title = "Per
794
794
  style: { color: "var(--stage-fg)" },
795
795
  children: cfg.trend
796
796
  }),
797
- " — ",
797
+ ", ",
798
798
  cfg.corner,
799
799
  ". Switch the property and watch the gradient flip direction."
800
800
  ]
@@ -10,9 +10,9 @@ import { Circle, Label, Segment, Stage, useFrameLoop, useInView } from "@classyt
10
10
 
11
11
  //#region src/chem/reaction-lab.tsx
12
12
  /**
13
- * ReactionLab — a synthesis reaction as moving atoms: A + B collide and bond into
13
+ * ReactionLab, a synthesis reaction as moving atoms: A + B collide and bond into
14
14
  * A–B. Raise the temperature and they collide harder/more often (kinetics); press
15
- * React to run it. Atoms are conserved — none created or destroyed, just
15
+ * React to run it. Atoms are conserved, none created or destroyed, just
16
16
  * rearranged.
17
17
  *
18
18
  * Now on the @classytic/stage engine (SVG, accessible, themed).
@@ -126,7 +126,7 @@ function ReactionLab({ a = "A", b = "B", title = "A + B → A–B", height = 300
126
126
  })] });
127
127
  return /* @__PURE__ */ jsx(LabFrame, {
128
128
  title,
129
- prompt: "Atoms rearrange — none are created or destroyed. Raise the temperature to react faster.",
129
+ prompt: "Atoms rearrange, none are created or destroyed. Raise the temperature to react faster.",
130
130
  aside: /* @__PURE__ */ jsx(Callout, {
131
131
  tone: "result",
132
132
  children: bonded ? "product" : playing ? "reacting…" : "reactants"
@@ -10,7 +10,7 @@ import { Label, Polyline, Segment, Stage } from "@classytic/stage";
10
10
 
11
11
  //#region src/chem/reaction-profile.tsx
12
12
  /**
13
- * ReactionProfile — an energy vs. reaction-coordinate diagram.
13
+ * ReactionProfile, an energy vs. reaction-coordinate diagram.
14
14
  *
15
15
  * Reactants plateau → activation-energy hump (transition state) → products
16
16
  * plateau. Tune ΔH (exothermic vs endothermic) and the activation energy Eₐ; flip
@@ -38,7 +38,7 @@ function sample(f) {
38
38
  }
39
39
  return pts;
40
40
  }
41
- /** The predict/classify activity — read straight off the diagram the learner just tuned. */
41
+ /** The predict/classify activity, read straight off the diagram the learner just tuned. */
42
42
  const CHALLENGE = [{
43
43
  id: "type",
44
44
  prompt: "When the products end up LOWER in energy than the reactants, the reaction is…",
@@ -69,7 +69,7 @@ const CHALLENGE = [{
69
69
  }
70
70
  ],
71
71
  answer: "ea",
72
- explain: "The reactant and product levels are unchanged — only the hump (Eₐ) drops, so ΔH is the same."
72
+ explain: "The reactant and product levels are unchanged, only the hump (Eₐ) drops, so ΔH is the same."
73
73
  }];
74
74
  function ReactionProfile({ deltaH, activationEnergy, catalyst: catalystInit = false, title = "Reaction energy profile", height = 320 } = {}) {
75
75
  const [dH, setDH] = useState(clamp(num(deltaH, -40), -80, 80));
@@ -252,7 +252,7 @@ function ReactionProfile({ deltaH, activationEnergy, catalyst: catalystInit = fa
252
252
  ] });
253
253
  return /* @__PURE__ */ jsx(LabFrame, {
254
254
  title,
255
- prompt: "Tune ΔH and the activation energy. A catalyst lowers the hump (green) — a faster path, same ΔH.",
255
+ prompt: "Tune ΔH and the activation energy. A catalyst lowers the hump (green), a faster path, same ΔH.",
256
256
  aside: /* @__PURE__ */ jsx(Callout, {
257
257
  tone: "result",
258
258
  children: /* @__PURE__ */ jsxs("span", {
@@ -11,11 +11,11 @@ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
11
11
 
12
12
  //#region src/chem/solution/dilution.tsx
13
13
  /**
14
- * DilutionLab — C₁V₁ = C₂V₂ is just: the dots don't leave.
14
+ * DilutionLab, C₁V₁ = C₂V₂ is just: the dots don't leave.
15
15
  *
16
16
  * Take an aliquot of stock (V₁) and dilute it to a final volume (V₂). Two beakers
17
- * show the SAME solute dots — concentrated in the small aliquot on the left,
18
- * spread through the larger volume on the right — so the conserved quantity
17
+ * show the SAME solute dots, concentrated in the small aliquot on the left,
18
+ * spread through the larger volume on the right, so the conserved quantity
19
19
  * (moles = C·V) is SEEN, not memorized: same dots, bigger box, paler colour, lower
20
20
  * C. Composes the shared SolutionField (single source of truth for the dots).
21
21
  *
@@ -41,7 +41,7 @@ const DILUTION_CHALLENGE = [{
41
41
  }
42
42
  ],
43
43
  answer: "moles",
44
- explain: "Adding water never removes solute — n = C·V is conserved, which is exactly C₁V₁ = C₂V₂."
44
+ explain: "Adding water never removes solute, n = C·V is conserved, which is exactly C₁V₁ = C₂V₂."
45
45
  }, {
46
46
  id: "doubleV",
47
47
  prompt: "Keep the same aliquot but DOUBLE the final volume V₂. The final concentration C₂…",
@@ -60,9 +60,9 @@ const DILUTION_CHALLENGE = [{
60
60
  }
61
61
  ],
62
62
  answer: "halves",
63
- explain: "C₂ = n/V₂ with n fixed — twice the volume means half the concentration."
63
+ explain: "C₂ = n/V₂ with n fixed, twice the volume means half the concentration."
64
64
  }];
65
- function DilutionLab({ stockConcentration = 2, aliquotVolume = .25, finalVolume = 1, maxMolarity = 4, hue = 200, title = "Dilution — the dots don’t leave", prompt = "Take an aliquot of stock, add water to the final volume. Same dots, bigger box → lower concentration.", height = 180, objectives }) {
65
+ function DilutionLab({ stockConcentration = 2, aliquotVolume = .25, finalVolume = 1, maxMolarity = 4, hue = 200, title = "Dilution: the dots don’t leave", prompt = "Take an aliquot of stock, add water to the final volume. Same dots, bigger box → lower concentration.", height = 180, objectives }) {
66
66
  const c1 = clamp(stockConcentration, .5, maxMolarity);
67
67
  const [v1, setV1] = useState(clamp(aliquotVolume, .1, .5));
68
68
  const [v2, setV2] = useState(clamp(finalVolume, .5, 1.5));
@@ -6,9 +6,9 @@ interface SolutionFieldProps {
6
6
  dots: number;
7
7
  /** Liquid's share of the box width, 0..1 (represents volume). */
8
8
  fill: number;
9
- /** Density tint 0..1 (e.g. molarity / maxMolarity) — deepens the colour. */
9
+ /** Density tint 0..1 (e.g. molarity / maxMolarity), deepens the colour. */
10
10
  tint: number;
11
- /** Solute hue in degrees (HSL) — encodes the species; default teal. */
11
+ /** Solute hue in degrees (HSL), encodes the species; default teal. */
12
12
  hue?: number;
13
13
  height?: number;
14
14
  /** Drag a fixed-size probe to count dots in a sub-region. */
@@ -8,13 +8,13 @@ import { CanvasLayer, useInView } from "@classytic/stage";
8
8
 
9
9
  //#region src/chem/solution/field.tsx
10
10
  /**
11
- * SolutionField — the SHARED "solute dots in a solution box" primitive (single
11
+ * SolutionField, the SHARED "solute dots in a solution box" primitive (single
12
12
  * source of truth for the concentration family). Both SolutionBoxLab and
13
13
  * DilutionLab compose it, so the dot-field, density tint, Brownian jitter and the
14
14
  * draggable probe live in exactly ONE place.
15
15
  *
16
16
  * GENERIC on purpose: it takes a dot COUNT + a fill fraction (the liquid's share
17
- * of the box = volume) + a tint 0..1 — the chemistry (moles→dots, M→tint) is the
17
+ * of the box = volume) + a tint 0..1, the chemistry (moles→dots, M→tint) is the
18
18
  * lab's job, not the field's. Dots hold fixed fractional positions so growing the
19
19
  * box spreads the SAME dots apart (dilution = spreading, never removing). SVG-free
20
20
  * CanvasLayer; deterministic seed (no Math.random at render) so SSR == client;
@@ -10,20 +10,20 @@ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
10
10
 
11
11
  //#region src/chem/solution/solution-box.tsx
12
12
  /**
13
- * SolutionBoxLab — molarity is a CROWD: particles per litre, seen.
13
+ * SolutionBoxLab, molarity is a CROWD: particles per litre, seen.
14
14
  *
15
15
  * Solute shown as discrete dots in a transparent box. Add solute (more dots =
16
16
  * more moles, the numerator) or add water (the box widens so the SAME dots spread
17
- * apart, the denominator) — and M = n/V is read off as both a number AND the
17
+ * apart, the denominator), and M = n/V is read off as both a number AND the
18
18
  * colour intensity. A draggable probe counts dots in a fixed region, proving
19
19
  * molarity is a LOCAL density, not a whole-apparatus label. Composes the shared
20
20
  * SolutionField (single source of truth for the dot engine).
21
21
  *
22
22
  * The unit-bridging algebra (mol↔g via molar mass, mol↔particles via Nₐ) belongs
23
- * in a paired MathDerivation — this lab only makes density-vs-amount felt.
23
+ * in a paired MathDerivation, this lab only makes density-vs-amount felt.
24
24
  */
25
25
  const DOTS_PER_MOL = 200;
26
- /** Predict how M = n/V responds to changing the numerator vs the denominator — the core molarity misconception. */
26
+ /** Predict how M = n/V responds to changing the numerator vs the denominator, the core molarity misconception. */
27
27
  const SOLUTION_CHALLENGE = [{
28
28
  id: "add-water",
29
29
  prompt: "Add water (more volume, same solute). The molarity M = n/V…",
@@ -42,7 +42,7 @@ const SOLUTION_CHALLENGE = [{
42
42
  }
43
43
  ],
44
44
  answer: "falls",
45
- explain: "The same dots spread through a bigger box — n is fixed, V grows, so the density n/V drops."
45
+ explain: "The same dots spread through a bigger box, n is fixed, V grows, so the density n/V drops."
46
46
  }, {
47
47
  id: "add-solute",
48
48
  prompt: "Add more solute at the same volume. The molarity…",
@@ -61,9 +61,9 @@ const SOLUTION_CHALLENGE = [{
61
61
  }
62
62
  ],
63
63
  answer: "rises",
64
- explain: "More dots in the same box — n grows, V is fixed, so n/V climbs."
64
+ explain: "More dots in the same box, n grows, V is fixed, so n/V climbs."
65
65
  }];
66
- function SolutionBoxLab({ moles = .5, volume = .5, maxMolarity = 4, hue = 178, showProbe = true, title = "Molarity is a crowd — particles per litre", prompt = "Add solute (more dots) or add water (same dots, bigger box). M = n / V is the dot density.", height = 230, objectives }) {
66
+ function SolutionBoxLab({ moles = .5, volume = .5, maxMolarity = 4, hue = 178, showProbe = true, title = "Molarity is a crowd: particles per litre", prompt = "Add solute (more dots) or add water (same dots, bigger box). M = n / V is the dot density.", height = 230, objectives }) {
67
67
  const [n, setN] = useState(clamp(moles, .1, 1));
68
68
  const [v, setV] = useState(clamp(volume, .2, 1));
69
69
  const M = n / v;
@@ -9,13 +9,13 @@ import { solveStoichiometry } from "@classytic/stage/chem";
9
9
 
10
10
  //#region src/chem/stoichiometry/preset.tsx
11
11
  /**
12
- * StoichiometryLab — the limiting reagent, seen as a recipe. A balanced reaction is
12
+ * StoichiometryLab, the limiting reagent, seen as a recipe. A balanced reaction is
13
13
  * a recipe (2 H₂ + O₂ → 2 H₂O = "2 hydrogens and 1 oxygen make 2 waters"); given how
14
14
  * much of each reactant you have, the one that runs out first caps how much product
15
15
  * you can make, and the rest is left over.
16
16
  *
17
17
  * Each reactant is a tray of molecule tokens: the part CONSUMED is solid, the
18
- * LEFTOVER fades out — so the limiting reagent is the tray that empties completely
18
+ * LEFTOVER fades out, so the limiting reagent is the tray that empties completely
19
19
  * (highlighted), and the excess shows as faded tokens. The product tray fills with
20
20
  * what's formed. Backed by `solveStoichiometry` (@classytic/stage/chem): extent,
21
21
  * limiting reagent, product moles/grams and leftovers. Drag the amounts, pick a
@@ -131,14 +131,14 @@ const STOICH_CHALLENGE = [{
131
131
  }
132
132
  ],
133
133
  answer: "runsout",
134
- explain: "Compare moles ÷ coefficient for each reactant — the smallest is the limiting one. Raw moles or the coefficient alone can mislead."
134
+ explain: "Compare moles ÷ coefficient for each reactant, the smallest is the limiting one. Raw moles or the coefficient alone can mislead."
135
135
  }, {
136
136
  id: "excess",
137
137
  prompt: "Adding MORE of the reactant that is already in excess changes the product made by…",
138
138
  choices: [
139
139
  {
140
140
  value: "none",
141
- label: "nothing — it just piles up as leftover"
141
+ label: "nothing: it just piles up as leftover"
142
142
  },
143
143
  {
144
144
  value: "more",
@@ -155,7 +155,7 @@ const STOICH_CHALLENGE = [{
155
155
  const co = (n) => n === 1 ? "" : `${n} `;
156
156
  const eqn = (rx) => `${rx.reactants.map((s) => co(s.coeff) + s.name).join(" + ")} → ${rx.products.map((s) => co(s.coeff) + s.name).join(" + ")}`;
157
157
  const fmt = (n) => Math.abs(n - Math.round(n)) < 1e-6 ? Math.round(n).toString() : n.toFixed(2);
158
- function StoichiometryLab({ reaction = "water", amounts: amounts0, reactants: customR, products: customP, title = "Stoichiometry — the limiting reagent", prompt = "A balanced equation is a recipe. Whichever reactant runs out first limits how much product you can make — the rest is left over. Drag the amounts and watch.", objectives = [
158
+ function StoichiometryLab({ reaction = "water", amounts: amounts0, reactants: customR, products: customP, title = "Stoichiometry: the limiting reagent", prompt = "A balanced equation is a recipe. Whichever reactant runs out first limits how much product you can make, the rest is left over. Drag the amounts and watch.", objectives = [
159
159
  "Read a balanced equation as a mole ratio (a recipe)",
160
160
  "Find the limiting reagent: the one that runs out first (smallest moles ÷ coeff)",
161
161
  "Work out the product formed and the reactant left in excess"
@@ -10,7 +10,7 @@ import { pHAt, titrationCurve } from "@classytic/stage/chem";
10
10
 
11
11
  //#region src/chem/titration/preset.tsx
12
12
  /**
13
- * TitrationLab — add base to an acid drop by drop and watch the pH curve build, on
13
+ * TitrationLab, add base to an acid drop by drop and watch the pH curve build, on
14
14
  * the shared `@classytic/stage/chem` acid–base kernel (pH solved exactly from the
15
15
  * charge balance at every volume).
16
16
  *
@@ -19,7 +19,7 @@ import { pHAt, titrationCurve } from "@classytic/stage/chem";
19
19
  * signature shape: a gentle start, then for a WEAK acid a flat BUFFER region whose
20
20
  * midpoint sits at pH = pKa, a steep jump through the equivalence point, and a
21
21
  * levelling-off in excess base. A strong acid skips the buffer and crosses pH 7 at
22
- * equivalence; a weak acid's equivalence point is basic (pH > 7). Interactive — drag
22
+ * equivalence; a weak acid's equivalence point is basic (pH > 7). Interactive, drag
23
23
  * the volume, no simulation loop.
24
24
  */
25
25
  const W = 720, H = 400;
@@ -64,7 +64,7 @@ const TITRATION_CHALLENGE = [{
64
64
  answer: "basic",
65
65
  explain: "All acid is now its conjugate base, which hydrolyses water to give pH > 7. (A strong acid would cross pH 7.)"
66
66
  }];
67
- function TitrationLab({ analyte: analyte0 = "weak-acid", concAcid = .1, volAcidMl = 25, concBase = .1, pKa: pKa0 = 4.76, title = "Acid–base titration — build the pH curve", prompt = "Drip strong base into the acid and track the pH. Watch the buffer region, the steep jump at the equivalence point, and the indicator flip pink.", objectives = [
67
+ function TitrationLab({ analyte: analyte0 = "weak-acid", concAcid = .1, volAcidMl = 25, concBase = .1, pKa: pKa0 = 4.76, title = "Acid–base titration: build the pH curve", prompt = "Drip strong base into the acid and track the pH. Watch the buffer region, the steep jump at the equivalence point, and the indicator flip pink.", objectives = [
68
68
  "Read a titration curve: start, buffer, equivalence jump, excess base",
69
69
  "For a weak acid, see the half-equivalence pH equals the pKa",
70
70
  "See the equivalence pH is 7 for a strong acid but >7 for a weak acid"
@@ -178,7 +178,7 @@ function TitrationLab({ analyte: analyte0 = "weak-acid", concAcid = .1, volAcidM
178
178
  textAnchor: "middle",
179
179
  fontSize: 11,
180
180
  fill: "var(--stage-muted)",
181
- children: pink > .5 ? "pink — past end point" : "colourless"
181
+ children: pink > .5 ? "pink, past end point" : "colourless"
182
182
  }),
183
183
  /* @__PURE__ */ jsx("line", {
184
184
  x1: GX0,
@@ -349,7 +349,7 @@ function TitrationLab({ analyte: analyte0 = "weak-acid", concAcid = .1, volAcidM
349
349
  }), /* @__PURE__ */ jsxs("span", {
350
350
  style: { color: "var(--stage-muted)" },
351
351
  children: [
352
- "In the buffer region the pH barely moves — at the half-equivalence point [A⁻] = [HA] so ",
352
+ "In the buffer region the pH barely moves, at the half-equivalence point [A⁻] = [HA] so ",
353
353
  /* @__PURE__ */ jsxs("strong", {
354
354
  style: { color: "var(--stage-fg)" },
355
355
  children: ["pH = pKa = ", pKa.toFixed(2)]
@@ -226,7 +226,7 @@ function Component({ geom }) {
226
226
  fontSize: 12,
227
227
  fill: "var(--stage-metal)",
228
228
  children: [
229
- "water analogy — ",
229
+ "water analogy, ",
230
230
  m.mode === "dc" ? "steady one-way flow" : "back-and-forth slosh",
231
231
  " (same signal)"
232
232
  ]
@@ -9,10 +9,10 @@ import { Scene, registerAsset } from "@classytic/stage";
9
9
 
10
10
  //#region src/circuits/ac-dc/preset.tsx
11
11
  /**
12
- * AcDcLab — "AC or DC?", now the STANDARD data-driven way: a SceneDoc with one
12
+ * AcDcLab, "AC or DC?", now the STANDARD data-driven way: a SceneDoc with one
13
13
  * `wave` sim (meta.sims) and one `ac-dc` asset that reads the sim live via simBind.
14
14
  * `<Scene>` steps the sim each frame and the pure resolver re-evaluates, so the
15
- * whole lab is data — the glowing lamp, flowing electrons, water-pipe analogy and
15
+ * whole lab is data, the glowing lamp, flowing electrons, water-pipe analogy and
16
16
  * live scope are all one sim → three synced skins (see ./asset). Controls write the
17
17
  * sim's params; the runtime merges them without restarting the wave (time persists).
18
18
  */
@@ -0,0 +1 @@
1
+ import { BrownoutLab, BrownoutProps } from "./preset.mjs";
@@ -0,0 +1,22 @@
1
+ import { LabAskSpec } from "../../kit/ask.mjs";
2
+ import { ReactNode } from "react";
3
+
4
+ //#region src/circuits/brownout/preset.d.ts
5
+ interface BrownoutProps {
6
+ vth?: number;
7
+ vmax?: number;
8
+ title?: string;
9
+ prompt?: string;
10
+ ask?: LabAskSpec;
11
+ activity?: string;
12
+ }
13
+ declare function BrownoutLab({
14
+ vth,
15
+ vmax,
16
+ title,
17
+ prompt,
18
+ ask,
19
+ activity
20
+ }?: BrownoutProps): ReactNode;
21
+ //#endregion
22
+ export { BrownoutLab, BrownoutProps };