@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,17 +10,17 @@ import { Label, Polygon, Polyline, Segment, Stage, useInView, useLearner } from
10
10
 
11
11
  //#region src/physics/impulse/preset.tsx
12
12
  /**
13
- * ImpulseLab — "Catch the egg", why a long contact time saves you.
13
+ * ImpulseLab, "Catch the egg", why a long contact time saves you.
14
14
  *
15
15
  * The SAME ball at the SAME speed is brought to rest, so the impulse it delivers
16
16
  * is FIXED: J = Δp = m·v. You only change HOW LONG the stop takes (a hard wall vs
17
17
  * a soft glove / airbag). The force–time pulse is modelled as a half-sine,
18
- * F(t) = F_peak·sin(πt/Δt), whose area ∫F dt = F_peak·(2Δt/π) is pinned to Δp —
18
+ * F(t) = F_peak·sin(πt/Δt), whose area ∫F dt = F_peak·(2Δt/π) is pinned to Δp ,
19
19
  * so as Δt grows the curve morphs from a tall-thin SPIKE (hard, big peak force)
20
20
  * to a low-wide BUMP (soft), the two shaded areas staying equal on FIXED axes:
21
21
  * the single-image proof that impulse is conserved while peak force is not.
22
22
  *
23
- * A fragile target (egg) cracks if the peak force tops its limit — so "bend your
23
+ * A fragile target (egg) cracks if the peak force tops its limit, so "bend your
24
24
  * knees / airbags / follow-through" stops being a slogan and becomes a number.
25
25
  *
26
26
  * Tokenized SVG; time-dependent (integrator here); honours reduced-motion.
@@ -44,7 +44,7 @@ function pulse(dp, dt) {
44
44
  }
45
45
  return pts;
46
46
  }
47
- function ImpulseLab({ mass = .5, speed = 8, contact = .05, crackForce = 120, title = "Catch the egg — stretch the stop, shrink the force", prompt = "Same ball, same speed, so the impulse J = m·v is fixed. Drag the contact time: a softer, slower stop keeps the same area but a much smaller peak force.", objectives, controlConfig }) {
47
+ function ImpulseLab({ mass = .5, speed = 8, contact = .05, crackForce = 120, title = "Catch the egg: stretch the stop, shrink the force", prompt = "Same ball, same speed, so the impulse J = m·v is fixed. Drag the contact time: a softer, slower stop keeps the same area but a much smaller peak force.", objectives, controlConfig }) {
48
48
  const [m, setM] = useState(mass);
49
49
  const [v, setV] = useState(speed);
50
50
  const [dt, setDt] = useState(clamp(contact, DT_MIN, DT_MAX));
@@ -383,7 +383,7 @@ function ImpulseLab({ mass = .5, speed = 8, contact = .05, crackForce = 120, tit
383
383
  }),
384
384
  /* @__PURE__ */ jsx(StatusPill, {
385
385
  ok: !cracks,
386
- children: cracks ? "💥 Too hard — the egg cracks" : "✓ Gentle enough — egg survives"
386
+ children: cracks ? "💥 Too hard, the egg cracks" : "✓ Gentle enough, egg survives"
387
387
  }),
388
388
  /* @__PURE__ */ jsxs("p", {
389
389
  style: {
@@ -28,6 +28,9 @@ import { DopplerLab, DopplerProps } from "./waves/doppler.mjs";
28
28
  import { EndType, StringMode, StringReflectionLab, StringReflectionProps } from "./waves/string.mjs";
29
29
  import { MagnetismLab, MagnetismProps } from "./magnetism/preset.mjs";
30
30
  import { ElectricFieldLab, ElectricFieldProps } from "./electric-field/preset.mjs";
31
+ import { ElectricFluxLab, ElectricFluxProps } from "./electric-flux/preset.mjs";
32
+ import { GaussLab, GaussProps } from "./gauss-law/preset.mjs";
33
+ import { WorkPotentialLab, WorkPotentialProps } from "./work-potential/preset.mjs";
31
34
  import { LorentzForceLab, LorentzProps } from "./lorentz/preset.mjs";
32
35
  import { DecayCoolingLab, DecayCoolingProps } from "./exponential/preset.mjs";
33
36
  import { WorkEnergyLab, WorkEnergyProps } from "./work-energy/preset.mjs";
@@ -40,4 +43,4 @@ import { GasProcessLab, GasProcessProps } from "./gas-process/preset.mjs";
40
43
  import { CarnotCycleLab, CarnotProps } from "./carnot/preset.mjs";
41
44
  import { EntropyLab, EntropyProps } from "./entropy/preset.mjs";
42
45
  import { EffStream, EfficiencyLab, EfficiencyProps } from "./efficiency/preset.mjs";
43
- export { AtwoodLab, type AtwoodProps, BALANCE_LEVER_ASSET, type BoardVector, BulletWallsLab, type BulletWallsProps, CarnotCycleLab, type CarnotProps, CircularMotionLab, type CircularMotionProps, CollisionTrackLab, type CollisionTrackProps, DecayCoolingLab, type DecayCoolingProps, DopplerLab, type DopplerProps, type EffStream, EfficiencyLab, type EfficiencyProps, ElectricFieldLab, type ElectricFieldProps, type EndType, EnergySkateLab, type EnergySkateProps, EntropyLab, type EntropyProps, GasProcessLab, type GasProcessProps, GravitationLab, type GravitationProps, GravityDrop, type GravityDropProps, HeatTransferLab, type HeatTransferProps, HeatingCurveLab, type HeatingCurveProps, ImpulseLab, type ImpulseProps, KeplerLab, type KeplerProps, LeverBalanceLab, type LeverBalanceProps, type LeverItemSpec, LorentzForceLab, type LorentzProps, MagnetismLab, type MagnetismProps, OPTICS_RAY_ASSET, OpticsLab, type OpticsProps, OrbitLab, ProjectileLab, type ProjectileLabProps, RainRelativeLab, type RainRelativeProps, RampForcesLab, type RampForcesProps, RippleTankLab, type RippleTankProps, type RippleView, RiverBoat, type RiverBoatProps, type SHMMode, type SceneVector, SimpleHarmonicLab, type SimpleHarmonicProps, StoppingDistanceLab, type StoppingDistanceProps, type StringMode, StringReflectionLab, type StringReflectionProps, TemperatureScalesLab, type TemperatureScalesProps, TerminalVelocityLab, type TerminalVelocityProps, ThermalExpansionLab, type ThermalExpansionProps, type TypePanel, VectorBoardLab, type VectorBoardProps, VectorScene, type VectorSceneProps, VectorTypesLab, type VectorTypesProps, WaterDensityLab, type WaterDensityProps, WaveLab, type WaveLabProps, type WaveMode, WorkEnergyLab, type WorkEnergyProps, leverBalanceDoc, opticsDoc };
46
+ export { AtwoodLab, type AtwoodProps, BALANCE_LEVER_ASSET, type BoardVector, BulletWallsLab, type BulletWallsProps, CarnotCycleLab, type CarnotProps, CircularMotionLab, type CircularMotionProps, CollisionTrackLab, type CollisionTrackProps, DecayCoolingLab, type DecayCoolingProps, DopplerLab, type DopplerProps, type EffStream, EfficiencyLab, type EfficiencyProps, ElectricFieldLab, type ElectricFieldProps, ElectricFluxLab, type ElectricFluxProps, type EndType, EnergySkateLab, type EnergySkateProps, EntropyLab, type EntropyProps, GasProcessLab, type GasProcessProps, GaussLab, type GaussProps, GravitationLab, type GravitationProps, GravityDrop, type GravityDropProps, HeatTransferLab, type HeatTransferProps, HeatingCurveLab, type HeatingCurveProps, ImpulseLab, type ImpulseProps, KeplerLab, type KeplerProps, LeverBalanceLab, type LeverBalanceProps, type LeverItemSpec, LorentzForceLab, type LorentzProps, MagnetismLab, type MagnetismProps, OPTICS_RAY_ASSET, OpticsLab, type OpticsProps, OrbitLab, ProjectileLab, type ProjectileLabProps, RainRelativeLab, type RainRelativeProps, RampForcesLab, type RampForcesProps, RippleTankLab, type RippleTankProps, type RippleView, RiverBoat, type RiverBoatProps, type SHMMode, type SceneVector, SimpleHarmonicLab, type SimpleHarmonicProps, StoppingDistanceLab, type StoppingDistanceProps, type StringMode, StringReflectionLab, type StringReflectionProps, TemperatureScalesLab, type TemperatureScalesProps, TerminalVelocityLab, type TerminalVelocityProps, ThermalExpansionLab, type ThermalExpansionProps, type TypePanel, VectorBoardLab, type VectorBoardProps, VectorScene, type VectorSceneProps, VectorTypesLab, type VectorTypesProps, WaterDensityLab, type WaterDensityProps, WaveLab, type WaveLabProps, type WaveMode, WorkEnergyLab, type WorkEnergyProps, WorkPotentialLab, type WorkPotentialProps, leverBalanceDoc, opticsDoc };
@@ -28,6 +28,9 @@ import { DopplerLab } from "./waves/doppler.mjs";
28
28
  import { StringReflectionLab } from "./waves/string.mjs";
29
29
  import { MagnetismLab } from "./magnetism/preset.mjs";
30
30
  import { ElectricFieldLab } from "./electric-field/preset.mjs";
31
+ import { ElectricFluxLab } from "./electric-flux/preset.mjs";
32
+ import { GaussLab } from "./gauss-law/preset.mjs";
33
+ import { WorkPotentialLab } from "./work-potential/preset.mjs";
31
34
  import { LorentzForceLab } from "./lorentz/preset.mjs";
32
35
  import { DecayCoolingLab } from "./exponential/preset.mjs";
33
36
  import { WorkEnergyLab } from "./work-energy/preset.mjs";
@@ -41,4 +44,4 @@ import { CarnotCycleLab } from "./carnot/preset.mjs";
41
44
  import { EntropyLab } from "./entropy/preset.mjs";
42
45
  import { EfficiencyLab } from "./efficiency/preset.mjs";
43
46
 
44
- export { AtwoodLab, BALANCE_LEVER_ASSET, BulletWallsLab, CarnotCycleLab, CircularMotionLab, CollisionTrackLab, DecayCoolingLab, DopplerLab, EfficiencyLab, ElectricFieldLab, EnergySkateLab, EntropyLab, GasProcessLab, GravitationLab, GravityDrop, HeatTransferLab, HeatingCurveLab, ImpulseLab, KeplerLab, LeverBalanceLab, LorentzForceLab, MagnetismLab, OPTICS_RAY_ASSET, OpticsLab, OrbitLab, ProjectileLab, RainRelativeLab, RampForcesLab, RippleTankLab, RiverBoat, SimpleHarmonicLab, StoppingDistanceLab, StringReflectionLab, TemperatureScalesLab, TerminalVelocityLab, ThermalExpansionLab, VectorBoardLab, VectorScene, VectorTypesLab, WaterDensityLab, WaveLab, WorkEnergyLab, leverBalanceDoc, opticsDoc };
47
+ export { AtwoodLab, BALANCE_LEVER_ASSET, BulletWallsLab, CarnotCycleLab, CircularMotionLab, CollisionTrackLab, DecayCoolingLab, DopplerLab, EfficiencyLab, ElectricFieldLab, ElectricFluxLab, EnergySkateLab, EntropyLab, GasProcessLab, GaussLab, GravitationLab, GravityDrop, HeatTransferLab, HeatingCurveLab, ImpulseLab, KeplerLab, LeverBalanceLab, LorentzForceLab, MagnetismLab, OPTICS_RAY_ASSET, OpticsLab, OrbitLab, ProjectileLab, RainRelativeLab, RampForcesLab, RippleTankLab, RiverBoat, SimpleHarmonicLab, StoppingDistanceLab, StringReflectionLab, TemperatureScalesLab, TerminalVelocityLab, ThermalExpansionLab, VectorBoardLab, VectorScene, VectorTypesLab, WaterDensityLab, WaveLab, WorkEnergyLab, WorkPotentialLab, leverBalanceDoc, opticsDoc };
@@ -12,11 +12,11 @@ import { Dot, Label, Polygon, Polyline, Segment, Stage } from "@classytic/stage"
12
12
 
13
13
  //#region src/physics/kepler/preset.tsx
14
14
  /**
15
- * KeplerLab — "Equal areas, equal time", the shape and rhythm of orbits.
15
+ * KeplerLab, "Equal areas, equal time", the shape and rhythm of orbits.
16
16
  *
17
17
  * A planet on a true ellipse with the star at one FOCUS (Kepler 1). It moves by
18
18
  * solving Kepler's equation M = E − e·sinE, so it genuinely speeds up at
19
- * perihelion and dawdles at aphelion — and the wedges swept in equal time slices
19
+ * perihelion and dawdles at aphelion, and the wedges swept in equal time slices
20
20
  * (shaded alternately) come out EQUAL in area (Kepler 2): fat-and-short near the
21
21
  * star, thin-and-long far away. The period follows T² ∝ a³ (Kepler 3), so a wider
22
22
  * orbit takes disproportionately longer.
@@ -31,7 +31,7 @@ function solveE(M, e) {
31
31
  for (let i = 0; i < 6; i++) E = E - (E - e * Math.sin(E) - M) / (1 - e * Math.cos(E));
32
32
  return E;
33
33
  }
34
- function KeplerLab({ semiMajor = 4, eccentricity = .5, wedges = true, title = "Kepler — equal areas in equal time", prompt = "The planet rides a true ellipse with the star at a focus. It speeds up near the star and slows far away, yet the wedge it sweeps in each equal time-slice has the SAME area (Kepler’s 2nd law). Stretch the orbit, and the period grows as T² ∝ a³.", objectives, controlConfig }) {
34
+ function KeplerLab({ semiMajor = 4, eccentricity = .5, wedges = true, title = "Kepler: equal areas in equal time", prompt = "The planet rides a true ellipse with the star at a focus. It speeds up near the star and slows far away, yet the wedge it sweeps in each equal time-slice has the SAME area (Kepler’s 2nd law). Stretch the orbit, and the period grows as T² ∝ a³.", objectives, controlConfig }) {
35
35
  const [a, setA] = useState(semiMajor);
36
36
  const [e, setE] = useState(eccentricity);
37
37
  const [showWedge, setShowWedge] = useState(wedges);
@@ -206,7 +206,7 @@ function KeplerLab({ semiMajor = 4, eccentricity = .5, wedges = true, title = "K
206
206
  margin: 0
207
207
  },
208
208
  children: [
209
- "Each shaded wedge is one equal time-slice — they look different but enclose the ",
209
+ "Each shaded wedge is one equal time-slice, they look different but enclose the ",
210
210
  /* @__PURE__ */ jsx("strong", { children: "same area" }),
211
211
  "(Kepler’s 2nd law), so the planet must move fastest at perihelion. T²/a³ stays constant as you widen the orbit (Kepler’s 3rd law)."
212
212
  ]
@@ -10,12 +10,12 @@ import { Scene, controlsFromScene, registerAsset, resolve, useControlSurface, us
10
10
 
11
11
  //#region src/physics/lever/preset.tsx
12
12
  /**
13
- * Balance-lever (torque) — a SceneDoc FACTORY, built on @classytic/stage. A
13
+ * Balance-lever (torque), a SceneDoc FACTORY, built on @classytic/stage. A
14
14
  * creator places weights at distances along an arm; exactly one is unknown, and
15
15
  * the learner sets it so the lever balances (net torque zero). Physics is typed
16
16
  * derivations that evaluate: torque_i = w_i·d_i (linop, fixed distance), net =
17
17
  * ΣL − ΣR, tilt = clamp(gain·net), balanced = (net == 0). v1 ships solveFor:
18
- * 'weight' (one unknown mass, fixed slots) — single-DOF, uniquely solvable.
18
+ * 'weight' (one unknown mass, fixed slots), single-DOF, uniquely solvable.
19
19
  */
20
20
  registerAsset("balance-lever", BALANCE_LEVER_ASSET);
21
21
  const UNIT_GAP = .9;
@@ -246,7 +246,7 @@ function LeverBalanceLab({ items = DEFAULT_ITEMS, start = 1, maxWeight = 12, con
246
246
  }), /* @__PURE__ */ jsxs(Callout, {
247
247
  tone: "result",
248
248
  children: [
249
- "turning effect — left ",
249
+ "turning effect, left ",
250
250
  leftSum.toFixed(1),
251
251
  " · right ",
252
252
  rightSum.toFixed(1)
@@ -12,14 +12,14 @@ import { Circle, Dot, Label, Stage, Vector, useControlSurface } from "@classytic
12
12
 
13
13
  //#region src/physics/lorentz/preset.tsx
14
14
  /**
15
- * LorentzForceLab — the magnetic force on a moving charge, F = q·v×B, made visible.
15
+ * LorentzForceLab, the magnetic force on a moving charge, F = q·v×B, made visible.
16
16
  * A charge fired into a uniform field (into ⊗ or out ⊙ of the page) feels a force
17
17
  * ALWAYS PERPENDICULAR to its velocity, so it curves into a circle (cyclotron
18
- * motion). The lab draws the three perpendicular players live — v (green, tangent),
19
- * B (the field symbols), F (orange, toward the centre) — and the right-hand rule
18
+ * motion). The lab draws the three perpendicular players live, v (green, tangent),
19
+ * B (the field symbols), F (orange, toward the centre), and the right-hand rule
20
20
  * spelled out. Flip the charge sign OR the field direction and the curve reverses;
21
21
  * F⟂v means the speed never changes (no work). Radius r = mv/(qB); the period is
22
- * independent of speed — the trick behind the cyclotron, mass spectrometer, and the
22
+ * independent of speed, the trick behind the cyclotron, mass spectrometer, and the
23
23
  * aurora (solar particles spiralling in Earth's field).
24
24
  */
25
25
  const R = 5;
@@ -36,7 +36,7 @@ const LORENTZ_CHALLENGE = [{
36
36
  choices: [
37
37
  {
38
38
  value: "none",
39
- label: "nothing — speed stays constant"
39
+ label: "nothing: speed stays constant"
40
40
  },
41
41
  {
42
42
  value: "up",
@@ -48,7 +48,7 @@ const LORENTZ_CHALLENGE = [{
48
48
  }
49
49
  ],
50
50
  answer: "none",
51
- explain: "F = qv×B is always ⟂ to v, so it does no work — only the direction turns, the speed is constant."
51
+ explain: "F = qv×B is always ⟂ to v, so it does no work, only the direction turns, the speed is constant."
52
52
  }, {
53
53
  id: "radius",
54
54
  prompt: "Crank up the field B (same charge and speed). The circle becomes…",
@@ -237,13 +237,13 @@ function LorentzForceLab({ charge = 1, fieldOut = true, B: B0 = 1.4, speed: v0 =
237
237
  tone: "result",
238
238
  children: [
239
239
  /* @__PURE__ */ jsx("div", {
240
- className: "lab-field-label",
240
+ style: { fontSize: 16 },
241
241
  children: /* @__PURE__ */ jsx(Tex$1, { tex: "F = q\\,v \\times B" })
242
242
  }),
243
243
  /* @__PURE__ */ jsxs("div", {
244
244
  style: {
245
- fontSize: 15,
246
- fontWeight: 800
245
+ fontSize: 14,
246
+ fontWeight: 600
247
247
  },
248
248
  children: ["curves ", sense > 0 ? "counter-clockwise" : "clockwise"]
249
249
  }),
@@ -280,7 +280,7 @@ function LorentzForceLab({ charge = 1, fieldOut = true, B: B0 = 1.4, speed: v0 =
280
280
  style: { color: ORANGE },
281
281
  children: "F"
282
282
  }),
283
- " (for +q; reverse for −q). F always ⟂ v, so it only turns the charge — the speed never changes."
283
+ " (for +q; reverse for −q). F always ⟂ v, so it only turns the charge, the speed never changes."
284
284
  ]
285
285
  }),
286
286
  /* @__PURE__ */ jsx("p", {
@@ -289,7 +289,7 @@ function LorentzForceLab({ charge = 1, fieldOut = true, B: B0 = 1.4, speed: v0 =
289
289
  fontSize: 12,
290
290
  color: "var(--stage-muted)"
291
291
  },
292
- children: "Same idea runs the cyclotron, the mass spectrometer, and the aurora — charged particles from the Sun spiralling in Earth's field."
292
+ children: "Same idea runs the cyclotron, the mass spectrometer, and the aurora, charged particles from the Sun spiralling in Earth's field."
293
293
  })
294
294
  ] }),
295
295
  controls: /* @__PURE__ */ jsxs(ControlBar, { children: [
@@ -10,9 +10,9 @@ import { barMagnet, fieldAt, fieldLines } from "@classytic/stage/field";
10
10
 
11
11
  //#region src/physics/magnetism/preset.tsx
12
12
  /**
13
- * MagnetismLab — a magnetic field you can SEE and probe (the "magnetism visualized"
13
+ * MagnetismLab, a magnetic field you can SEE and probe (the "magnetism visualized"
14
14
  * gap). Drag a bar magnet (and its ends to rotate), or switch to a current-carrying
15
- * wire, and the FIELD LINES retrace live on the @classytic/stage `field` kernel —
15
+ * wire, and the FIELD LINES retrace live on the @classytic/stage `field` kernel ,
16
16
  * radial dipole lines N→S for the magnet, circular loops for the wire. Drag the
17
17
  * compass anywhere and its needle snaps to the field there. Interactive, not a
18
18
  * timed sim (no Play needed): the field is recomputed on every drag.
@@ -208,7 +208,7 @@ function FieldFigure({ sources, lines, mode, center, northOff, compass, current
208
208
  })
209
209
  ] });
210
210
  }
211
- function MagnetismLab({ title = "Magnetism — field you can see", prompt = "Drag the magnet (and its ends to turn it), or switch to a wire. The compass snaps to the field wherever you drop it.", objectives = [
211
+ function MagnetismLab({ title = "Magnetism: field you can see", prompt = "Drag the magnet (and its ends to turn it), or switch to a wire. The compass snaps to the field wherever you drop it.", objectives = [
212
212
  "Read a magnetic field as field lines",
213
213
  "Field lines run N → S; a compass aligns with them",
214
214
  "A current makes circular field loops"
@@ -9,7 +9,7 @@ import { Scene, isAssetGeom, registerAsset, resolve } from "@classytic/stage";
9
9
 
10
10
  //#region src/physics/optics/preset.tsx
11
11
  /**
12
- * Optics flagship — drag the source, the aim point, or the mirrors so the light
12
+ * Optics flagship, drag the source, the aim point, or the mirrors so the light
13
13
  * ray reflects into the target. A general tool built on @classytic/stage:
14
14
  * creators place any mirrors + target.
15
15
  */
@@ -182,7 +182,7 @@ function OpticsLab({ height = 380 }) {
182
182
  color: hit ? "var(--stage-good)" : "var(--stage-warn)",
183
183
  fontWeight: 600
184
184
  },
185
- children: hit ? "✓ Target lit!" : "not yet — keep adjusting"
185
+ children: hit ? "✓ Target lit!" : "not yet, keep adjusting"
186
186
  })]
187
187
  })
188
188
  }),
@@ -8,13 +8,13 @@ import { CanvasLayer, useFrameLoop, useInView } from "@classytic/stage";
8
8
 
9
9
  //#region src/physics/orbit-lab.tsx
10
10
  /**
11
- * OrbitLab — an orbit is just falling sideways fast enough to keep missing the
11
+ * OrbitLab, an orbit is just falling sideways fast enough to keep missing the
12
12
  * ground. Too slow → crash; too fast → escape; just right → a closed ellipse.
13
13
  *
14
14
  * A genuine high-element-count animation (a 260-point fading trail + starfield +
15
15
  * a sub-stepped N-body integrator mutating a ref every frame), so it renders on
16
16
  * the engine's zero-dependency `<CanvasLayer>` (raw Canvas2D) rather than one SVG
17
- * node per trail point — the same boundary GradientDescent uses.
17
+ * node per trail point, the same boundary GradientDescent uses.
18
18
  */
19
19
  const GM = 9e3;
20
20
  const R0 = 120;
@@ -149,10 +149,10 @@ function OrbitLab() {
149
149
  setPhase("running");
150
150
  };
151
151
  const verdict = phase === "crashed" ? {
152
- text: "💥 Too slow — it fell back and crashed",
152
+ text: "💥 Too slow, it fell back and crashed",
153
153
  ok: false
154
154
  } : phase === "escaped" ? {
155
- text: "🚀 Too fast — it escaped into space",
155
+ text: "🚀 Too fast, it escaped into space",
156
156
  ok: false
157
157
  } : phase === "running" ? {
158
158
  text: "…orbiting (watch the path close into an ellipse)",
@@ -175,7 +175,7 @@ function OrbitLab() {
175
175
  children: [
176
176
  "The dashed ring is a stable circular orbit. Press ",
177
177
  /* @__PURE__ */ jsx("strong", { children: "Launch" }),
178
- " — too slow and it spirals in, too fast and it escapes."
178
+ ", too slow and it spirals in, too fast and it escapes."
179
179
  ]
180
180
  })]
181
181
  });
@@ -9,7 +9,7 @@ import { Circle, Dot, Label, Polyline, Segment, Stage, StageAssetDefs, fmt, useC
9
9
 
10
10
  //#region src/physics/projectile-lab.tsx
11
11
  /**
12
- * ProjectileLab — tune launch angle + speed, land the shot on the target. Now on
12
+ * ProjectileLab, tune launch angle + speed, land the shot on the target. Now on
13
13
  * the @classytic/stage engine (SVG, accessible): the ground, cannon, predicted
14
14
  * arc, target, and ball are real primitives in a metre coordinate system; the
15
15
  * flight animates on the engine clock.
@@ -17,7 +17,7 @@ import { Circle, Dot, Label, Polyline, Segment, Stage, StageAssetDefs, fmt, useC
17
17
  /**
18
18
  * A field cannon anchored at the launch point (math origin), elevated to
19
19
  * `angle`. Drawn in a LOCAL pixel frame with STATIC coordinates and rotated via
20
- * an SVG transform — so no transcendental-derived coordinate is ever serialized
20
+ * an SVG transform, so no transcendental-derived coordinate is ever serialized
21
21
  * into an attribute (SSR-deterministic, per the engine's `fmt` rule). Sized in
22
22
  * world units (px-per-metre) so it tracks pan/zoom like the rest of the scene.
23
23
  */
@@ -297,11 +297,11 @@ function ProjectileLab(props) {
297
297
  ] });
298
298
  return /* @__PURE__ */ jsx(LabFrame, {
299
299
  title: "Projectile Lab",
300
- prompt: "Tune the angle and speed — can you land the shot on the target?",
300
+ prompt: "Tune the angle and speed, can you land the shot on the target?",
301
301
  aside: /* @__PURE__ */ jsxs(Fragment$1, { children: [
302
302
  (phase === "hit" || phase === "miss") && /* @__PURE__ */ jsx(StatusPill, {
303
303
  ok: phase === "hit",
304
- children: phase === "hit" ? "🎯 Direct hit!" : "So close — adjust and retry"
304
+ children: phase === "hit" ? "🎯 Direct hit!" : "So close, adjust and retry"
305
305
  }),
306
306
  /* @__PURE__ */ jsx(Callout, {
307
307
  tone: "result",
@@ -12,18 +12,18 @@ import { CanvasLayer, Label, Segment, Stage, Vector, useCoords } from "@classyti
12
12
 
13
13
  //#region src/physics/rain-relative/preset.tsx
14
14
  /**
15
- * RainRelativeLab — relative velocity you can FEEL.
15
+ * RainRelativeLab, relative velocity you can FEEL.
16
16
  *
17
17
  * Sit in a car in the rain. The rain falls straight down in the ground frame,
18
- * but in YOUR frame it slants — its apparent velocity is V_rain − V_car. Drag
18
+ * but in YOUR frame it slants, its apparent velocity is V_rain − V_car. Drag
19
19
  * the speed up and the rain streaks harder and leans more; the velocity triangle
20
20
  * and the angle θ track it live. This is the "show me" the static board lacked.
21
21
  *
22
22
  * Architecture on purpose: the hundreds of raindrops are drawn on `CanvasLayer`
23
- * (zero-dep Canvas2D — the engine's particle escape hatch, no Pixi), animated by
23
+ * (zero-dep Canvas2D, the engine's particle escape hatch, no Pixi), animated by
24
24
  * the shared `useFrameLoop` RAF clock; the car, the velocity triangle and the
25
25
  * labels sit on an SVG `<Stage>` overlaid on top (crisp + accessible). Honors
26
- * prefers-reduced-motion. One source of truth — `ratio = tan θ` — drives the
26
+ * prefers-reduced-motion. One source of truth, `ratio = tan θ`, drives the
27
27
  * canvas slant, the triangle, and the readout, so they can never disagree.
28
28
  */
29
29
  const VIEW = {
@@ -160,7 +160,7 @@ function Car({ baseY, wheelAngle }) {
160
160
  ]
161
161
  });
162
162
  }
163
- function RainRelativeLab({ maxSpeed = 10, start = 0, title = "Rain on a moving car", prompt = "Speed up — watch the rain slant. In your frame the rain comes at V_rain − V_car.", height = 360 }) {
163
+ function RainRelativeLab({ maxSpeed = 10, start = 0, title = "Rain on a moving car", prompt = "Speed up, watch the rain slant. In your frame the rain comes at V_rain − V_car.", height = 360 }) {
164
164
  const [speed, setSpeed] = useState(start);
165
165
  const drops = useRef([]);
166
166
  const lastT = useRef(0);
@@ -12,15 +12,15 @@ import { Label, Polygon, Segment, Stage, Vector, useFrameLoop, useInView } from
12
12
 
13
13
  //#region src/physics/ramp-forces/preset.tsx
14
14
  /**
15
- * RampForcesLab — "Tilt the Ramp", where gravity gets a share (F = ma) AND you
15
+ * RampForcesLab, "Tilt the Ramp", where gravity gets a share (F = ma) AND you
16
16
  * can push/pull the crate.
17
17
  *
18
18
  * Tilt the incline and the weight SPLITS into a down-slope share (mg sinθ) and a
19
- * press-in share (mg cosθ = the normal N, which visibly shrinks as you tilt — the
19
+ * press-in share (mg cosθ = the normal N, which visibly shrinks as you tilt, the
20
20
  * headline misconception). Add an applied force (push up-slope / pull down) and
21
21
  * watch the SUM of forces: static friction holds it (adjusting up to μs·N) until
22
22
  * the drive exceeds that grip, then kinetic friction (μk·N, weaker) takes over
23
- * and it accelerates — a = net/m. A force-ledger bar shows every along-slope
23
+ * and it accelerates, a = net/m. A force-ledger bar shows every along-slope
24
24
  * force adding to the net, so "the forces add up" is visual, not just stated.
25
25
  *
26
26
  * Up-slope is the POSITIVE axis throughout. Tokenized SVG; reuses the diagram kit;
@@ -96,7 +96,7 @@ function LedgerBar({ label, v, max, color, bold }) {
96
96
  ]
97
97
  });
98
98
  }
99
- function RampForcesLab({ angleDeg = 25, mass = 2, friction = .4, frictionKinetic = .3, appliedN = 0, g = 9.8, showComponents = false, title = "Tilt the Ramp — split the weight, add a push, sum the forces", prompt = "Tilt it, then push or pull: static friction holds until the forces win, then it slides at a = net/m.", objectives, controlConfig }) {
99
+ function RampForcesLab({ angleDeg = 25, mass = 2, friction = .4, frictionKinetic = .3, appliedN = 0, g = 9.8, showComponents = false, title = "Tilt the Ramp: split the weight, add a push, sum the forces", prompt = "Tilt it, then push or pull: static friction holds until the forces win, then it slides at a = net/m.", objectives, controlConfig }) {
100
100
  const [deg, setDeg] = useState(angleDeg);
101
101
  const [mus, setMus] = useState(friction);
102
102
  const [mukRaw, setMuk] = useState(frictionKinetic);
@@ -455,7 +455,7 @@ function RampForcesLab({ angleDeg = 25, mass = 2, friction = .4, frictionKinetic
455
455
  }),
456
456
  /* @__PURE__ */ jsx(StatusPill, {
457
457
  ok: !held,
458
- children: held ? "balanced — friction holds it" : `slides ${slidesUp ? "up" : "down"} · a = ${a.toFixed(1)} m/s²`
458
+ children: held ? "balanced, friction holds it" : `slides ${slidesUp ? "up" : "down"} · a = ${a.toFixed(1)} m/s²`
459
459
  }),
460
460
  /* @__PURE__ */ jsxs("span", {
461
461
  style: {
@@ -11,13 +11,13 @@ import { Dot, Grid, Label, Polygon, Segment, Stage, fmt, useControlSurface, useC
11
11
 
12
12
  //#region src/physics/river-boat.tsx
13
13
  /**
14
- * RiverBoat — the classic "boat crossing a flowing river" vector problem, the one
14
+ * RiverBoat, the classic "boat crossing a flowing river" vector problem, the one
15
15
  * that trips students on component resolution. A boat aims across the current at a
16
16
  * heading θ; the river carries it downstream. Walk the steps to SEE why you add
17
17
  * the boat and current velocities tip-to-tail, then resolve the resultant into
18
18
  * an "across" component (v_b·cosθ, sets crossing time) and a "downstream"
19
19
  * component (v_c − v_b·sinθ, sets the drift). Aim upstream at θ = arcsin(v_c/v_b)
20
- * and the drift cancels — you land straight across.
20
+ * and the drift cancels, you land straight across.
21
21
  *
22
22
  * Now on the @classytic/stage engine (SVG vectors via the shared `LabeledVector`
23
23
  * helper, accessible, themed); keeps the agent `useControlSurface` seam.
@@ -25,7 +25,7 @@ import { Dot, Grid, Label, Polygon, Segment, Stage, fmt, useControlSurface, useC
25
25
  /**
26
26
  * A small boat anchored at the launch point (math origin), heading `thetaDeg`
27
27
  * upstream from straight-across. Fixed on-screen size (a constant glyph, like an
28
- * angle mark), rotated via a transform with static local coordinates — nose
28
+ * angle mark), rotated via a transform with static local coordinates, nose
29
29
  * points along +across, so rotate(−θ) aims it upstream. SSR-safe: no
30
30
  * transcendental-derived coordinate is serialized.
31
31
  */
@@ -89,7 +89,7 @@ function BoatGlyph({ thetaDeg }) {
89
89
  }
90
90
  /**
91
91
  * Wave streaks drifting downstream, illustrating the current. Drift speed scales
92
- * with `current` (vᵧ) — a still river is calm, a fast one streams. Animated with
92
+ * with `current` (vᵧ), a still river is calm, a fast one streams. Animated with
93
93
  * a CSS keyframe (declarative, SSR-safe, honours prefers-reduced-motion); the
94
94
  * dash period equals the keyframe translate, so the loop is seamless.
95
95
  */
@@ -125,7 +125,7 @@ function RiverWaves({ view, W, current }) {
125
125
  });
126
126
  }
127
127
  const STEPS = [
128
- "Aim the boat across — this is its velocity through the water.",
128
+ "Aim the boat across, this is its velocity through the water.",
129
129
  "The river flows, pushing the boat downstream at vᵧ.",
130
130
  "Add them tip-to-tail: the resultant is the boat’s true path over the ground.",
131
131
  "Resolve the resultant: across = vᵦ·cos θ, downstream = vᵧ − vᵦ·sin θ.",
@@ -386,7 +386,7 @@ function RiverBoat({ boatSpeed, current, riverWidth, title = "Crossing a flowing
386
386
  fontWeight: 800,
387
387
  fontVariantNumeric: "tabular-nums"
388
388
  },
389
- children: cross ? `lands ${drift.toFixed(1)} m downstream` : "—"
389
+ children: cross ? `lands ${drift.toFixed(1)} m downstream` : ", "
390
390
  }),
391
391
  /* @__PURE__ */ jsx("span", {
392
392
  style: {
@@ -12,18 +12,18 @@ import { Circle, Dot, Label, Polyline, Segment, Stage, Vector } from "@classytic
12
12
 
13
13
  //#region src/physics/shm/preset.tsx
14
14
  /**
15
- * SimpleHarmonicLab — "The same swing", where a spring and a pendulum turn out to
15
+ * SimpleHarmonicLab, "The same swing", where a spring and a pendulum turn out to
16
16
  * be the SAME motion, and where a wave comes from.
17
17
  *
18
18
  * One SHM kernel, two skins. A restoring force pulls back in proportion to the
19
19
  * displacement (spring: F = −kx; pendulum, small angle: F ≈ −mg·x/L), which forces
20
20
  * a = −ω²x and the solution x(t) = A·cos(ωt). The mass oscillates while a pen
21
- * traces x against time — and the trace IS a sine curve, the very shape of the
21
+ * traces x against time, and the trace IS a sine curve, the very shape of the
22
22
  * waves lessons (a wave is SHM spread through space). Energy sloshes between
23
23
  * elastic/PE and KE, summing to a constant (ties to the energy-skate lab).
24
24
  *
25
- * ω = √(k/m) (spring) T = 2π√(m/k) — heavier or softer ⇒ slower
26
- * ω = √(g/L) (pendulum) T = 2π√(L/g) — independent of mass AND amplitude
25
+ * ω = √(k/m) (spring) T = 2π√(m/k) , heavier or softer ⇒ slower
26
+ * ω = √(g/L) (pendulum) T = 2π√(L/g) , independent of mass AND amplitude
27
27
  *
28
28
  * Ambient PlayWrap gate (pause to read the force arrow). Tokenized SVG.
29
29
  */
@@ -68,7 +68,7 @@ const SHM_CHALLENGE = [{
68
68
  }];
69
69
  const G = 9.8;
70
70
  const WIN = 6;
71
- function SimpleHarmonicLab({ mode = "spring", k = 8, length = 2, mass = 1, amplitude, title = "The same swing — spring, pendulum, and where a wave comes from", prompt = "A restoring force pulls back in proportion to displacement, so a = −ω²x and the motion is x(t) = A·cos(ωt). Watch the pen trace a sine — that’s the shape of a wave. Swap to a pendulum: its period ignores both mass and amplitude.", objectives, controlConfig }) {
71
+ function SimpleHarmonicLab({ mode = "spring", k = 8, length = 2, mass = 1, amplitude, title = "The same swing: spring, pendulum, and where a wave comes from", prompt = "A restoring force pulls back in proportion to displacement, so a = −ω²x and the motion is x(t) = A·cos(ωt). Watch the pen trace a sine, that’s the shape of a wave. Swap to a pendulum: its period ignores both mass and amplitude.", objectives, controlConfig }) {
72
72
  const [md, setMd] = useState(mode);
73
73
  const [kk, setKk] = useState(k);
74
74
  const [L, setL] = useState(length);
@@ -347,7 +347,7 @@ function SimpleHarmonicLab({ mode = "spring", k = 8, length = 2, mass = 1, ampli
347
347
  },
348
348
  height: 130,
349
349
  preserveAspect: false,
350
- ariaLabel: "Displacement traced against time — a sine curve",
350
+ ariaLabel: "Displacement traced against time, a sine curve",
351
351
  children: [
352
352
  /* @__PURE__ */ jsx(Segment, {
353
353
  from: {
@@ -447,8 +447,8 @@ function SimpleHarmonicLab({ mode = "spring", k = 8, length = 2, mass = 1, ampli
447
447
  children: [
448
448
  "The trace is a ",
449
449
  /* @__PURE__ */ jsx("strong", { children: "sine" }),
450
- " — a wave is just this swing spread through space (v = fλ in the waves lab). ",
451
- isSpring ? "Heavier or softer spring ⇒ slower (T = 2π√(m/k))." : "Notice: change the mass or the amplitude and T doesn’t move — a pendulum’s period is T = 2π√(L/g)."
450
+ ", a wave is just this swing spread through space (v = fλ in the waves lab). ",
451
+ isSpring ? "Heavier or softer spring ⇒ slower (T = 2π√(m/k))." : "Notice: change the mass or the amplitude and T doesn’t move, a pendulum’s period is T = 2π√(L/g)."
452
452
  ]
453
453
  }),
454
454
  /* @__PURE__ */ jsx(LiveRegion, { children: `${isSpring ? "Spring" : "Pendulum"} oscillator. Angular frequency ${omega.toFixed(2)}, period ${T.toFixed(2)} seconds.` })
@@ -524,7 +524,7 @@ function SimpleHarmonicLab({ mode = "spring", k = 8, length = 2, mass = 1, ampli
524
524
  max: 5,
525
525
  step: .5,
526
526
  onChange: setM,
527
- ariaLabel: "bob mass (kg) — does not change the period"
527
+ ariaLabel: "bob mass (kg): does not change the period"
528
528
  })
529
529
  }),
530
530
  /* @__PURE__ */ jsx(Field, {
@@ -10,12 +10,12 @@ import { Dot, Label, MovableDot, Polygon, Polyline, Segment, Stage, fmt, useCoor
10
10
 
11
11
  //#region src/physics/stopping-distance/preset.tsx
12
12
  /**
13
- * StoppingDistanceLab — "Drive & Brake", the two-distance stopping tape.
13
+ * StoppingDistanceLab, "Drive & Brake", the two-distance stopping tape.
14
14
  *
15
15
  * A car cruises at v; a hazard appears; the driver REACTS (constant speed for
16
16
  * t_react → a blue THINKING stripe), then BRAKES at a (→ a red BRAKING stripe)
17
17
  * to a stop. The road paints the two stripes as the car passes, and stacked v–t
18
- * and s–t graphs draw underneath sharing ONE playhead with the car — so the
18
+ * and s–t graphs draw underneath sharing ONE playhead with the car, so the
19
19
  * v–t area visibly IS the distance. "Double the speed" keeps a ghost of the last
20
20
  * run so the learner sees thinking double (linear) while braking quadruples (v²).
21
21
  *
@@ -84,7 +84,7 @@ function Car({ x }) {
84
84
  ]
85
85
  });
86
86
  }
87
- function StoppingDistanceLab({ speed = 20, reactionTime = .7, deceleration = 6, maxSpeed = 40, predict = false, showGraphs = false, title = "Drive & Brake — the two-distance stopping tape", prompt = "A hazard appears: react, then brake. Watch the road paint thinking (blue) + braking (red).", objectives, hints = [] }) {
87
+ function StoppingDistanceLab({ speed = 20, reactionTime = .7, deceleration = 6, maxSpeed = 40, predict = false, showGraphs = false, title = "Drive & Brake: the two-distance stopping tape", prompt = "A hazard appears: react, then brake. Watch the road paint thinking (blue) + braking (red).", objectives, hints = [] }) {
88
88
  const [v, setV] = useState(speed);
89
89
  const [tr, setTr] = useState(reactionTime);
90
90
  const [a, setA] = useState(deceleration);