@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
@@ -0,0 +1,18 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __defProp = Object.defineProperty;
3
+ var __exportAll = (all, no_symbols) => {
4
+ let target = {};
5
+ for (var name in all) {
6
+ __defProp(target, name, {
7
+ get: all[name],
8
+ enumerable: true
9
+ });
10
+ }
11
+ if (!no_symbols) {
12
+ __defProp(target, Symbol.toStringTag, { value: "Module" });
13
+ }
14
+ return target;
15
+ };
16
+
17
+ //#endregion
18
+ export { __exportAll };
@@ -10,16 +10,16 @@ import { Axes, Dot, Label, Polygon, Segment, Stage } from "@classytic/stage";
10
10
 
11
11
  //#region src/biology/enzyme-rate/preset.tsx
12
12
  /**
13
- * EnzymeRateLab — the optimum, then the cliff: enzymes denature.
13
+ * EnzymeRateLab, the optimum, then the cliff: enzymes denature.
14
14
  *
15
15
  * Drag temperature: the rate climbs to an optimum (more kinetic energy → more
16
16
  * successful enzyme–substrate collisions) then CRASHES as the lock-and-key active
17
- * site is mangled — and crucially, cooling back down does NOT restore it
17
+ * site is mangled, and crucially, cooling back down does NOT restore it
18
18
  * (thermal denaturation is irreversible). The bell is BUILT from plotted dots as
19
19
  * you sweep, never pre-drawn. pH mode shows the same optimum but reversibly; a
20
20
  * "fresh enzyme" reset is the only way back from a denatured run.
21
21
  *
22
- * Reuses core/util + kit/controls; tokenized; reduced-motion safe (no autoplay —
22
+ * Reuses core/util + kit/controls; tokenized; reduced-motion safe (no autoplay ,
23
23
  * the learner drags). The collision-theory vs denaturation split → a MathDerivation.
24
24
  */
25
25
  const CLIFF = 16;
@@ -71,7 +71,7 @@ function Enzyme({ denat }) {
71
71
  ]
72
72
  });
73
73
  }
74
- function EnzymeRateLab({ factor = "temperature", optimum = 40, factorMin = 0, factorMax = 80, title = "The optimum, then the cliff — enzymes denature", prompt = "Drag the temperature. Past the optimum the enzyme denatures — and cooling back down won’t fix it.", height = 240, objectives }) {
74
+ function EnzymeRateLab({ factor = "temperature", optimum = 40, factorMin = 0, factorMax = 80, title = "The optimum, then the cliff: enzymes denature", prompt = "Drag the temperature. Past the optimum the enzyme denatures, and cooling back down won’t fix it.", height = 240, objectives }) {
75
75
  const reversible = factor === "pH";
76
76
  const [f, setF] = useState(reversible ? optimum - 2 : factorMin + 5);
77
77
  const peak = useRef(f);
@@ -227,7 +227,7 @@ function EnzymeRateLab({ factor = "temperature", optimum = 40, factorMin = 0, fa
227
227
  ]
228
228
  }), /* @__PURE__ */ jsx(StatusPill, {
229
229
  ok: state === "optimum",
230
- children: state === "optimum" ? "at the optimum ✓" : state === "denatured" ? "denatured — no recovery" : state === "falling" ? reversible ? "past optimum" : "denaturing…" : "climbing (more collisions)"
230
+ children: state === "optimum" ? "at the optimum ✓" : state === "denatured" ? "denatured, no recovery" : state === "falling" ? reversible ? "past optimum" : "denaturing…" : "climbing (more collisions)"
231
231
  })]
232
232
  }),
233
233
  controls: /* @__PURE__ */ jsxs(ControlBar, { children: [/* @__PURE__ */ jsx(Field, {
@@ -1,6 +1,6 @@
1
1
  //#region src/biology/genetic-cross/core.d.ts
2
2
  /**
3
- * Genetics core — a SERIALIZABLE cross model + the rule that turns a genotype into
3
+ * Genetics core, a SERIALIZABLE cross model + the rule that turns a genotype into
4
4
  * a phenotype. Authored as data (so agents can declare it via JSON), resolved into
5
5
  * pure functions for the lab. One model covers simple dominance, multiple alleles,
6
6
  * codominance and incomplete dominance:
@@ -11,7 +11,7 @@
11
11
  * • an optional `blends` entry overrides a specific heterozygote
12
12
  * (INCOMPLETE DOMINANCE → red × white = pink)
13
13
  *
14
- * No reinvented numerics — this is just the genetics rule; UI lives in the preset.
14
+ * No reinvented numerics, this is just the genetics rule; UI lives in the preset.
15
15
  */
16
16
  interface AlleleSpec {
17
17
  symbol: string;
@@ -42,15 +42,15 @@ interface ResolvedModel {
42
42
  phenotypeColor: (label: string) => string;
43
43
  /** every possible genotype as a normalised [a,b] pair (for parent pickers). */
44
44
  genotypes: [string, string][];
45
- /** true if `a` masks `b` here — a dominant over a present lower-rank allele. */
45
+ /** true if `a` masks `b` here, a dominant over a present lower-rank allele. */
46
46
  masks: (a: string, b: string) => boolean;
47
47
  }
48
48
  declare function resolveModel(spec: CrossModelSpec): ResolvedModel;
49
- /** Simple dominant/recessive — the classic monohybrid (also backs PunnettCross). */
49
+ /** Simple dominant/recessive, the classic monohybrid (also backs PunnettCross). */
50
50
  declare const monohybridSpec: (letter?: string, dominant?: string, recessive?: string) => CrossModelSpec;
51
- /** ABO blood groups — multiple alleles + codominance (Aᴬ Aᴮ → AB). */
51
+ /** ABO blood groups, multiple alleles + codominance (Aᴬ Aᴮ → AB). */
52
52
  declare const BLOOD_TYPE_SPEC: CrossModelSpec;
53
- /** Incomplete dominance — red × white = pink (a blended heterozygote). */
53
+ /** Incomplete dominance, red × white = pink (a blended heterozygote). */
54
54
  declare const INCOMPLETE_SPEC: CrossModelSpec;
55
55
  declare const CROSS_PRESETS: {
56
56
  readonly monohybrid: CrossModelSpec;
@@ -58,7 +58,7 @@ declare const CROSS_PRESETS: {
58
58
  readonly incomplete: CrossModelSpec;
59
59
  };
60
60
  type CrossPresetKey = keyof typeof CROSS_PRESETS;
61
- /** Two independent genes — the classic dihybrid 9:3:3:1 (height × seed colour). */
61
+ /** Two independent genes, the classic dihybrid 9:3:3:1 (height × seed colour). */
62
62
  declare const DIHYBRID_LOCI: CrossModelSpec[];
63
63
  //#endregion
64
64
  export { AlleleSpec, BLOOD_TYPE_SPEC, BlendSpec, CROSS_PRESETS, CrossModelSpec, CrossPresetKey, DIHYBRID_LOCI, INCOMPLETE_SPEC, Phenotype, ResolvedModel, monohybridSpec, resolveModel };
@@ -45,7 +45,7 @@ function resolveModel(spec) {
45
45
  masks: (a, b) => !blends.has(blendKey(a, b)) && (rank.get(a) ?? 0) > (rank.get(b) ?? 0)
46
46
  };
47
47
  }
48
- /** Simple dominant/recessive — the classic monohybrid (also backs PunnettCross). */
48
+ /** Simple dominant/recessive, the classic monohybrid (also backs PunnettCross). */
49
49
  const monohybridSpec = (letter = "A", dominant = "tall", recessive = "short") => ({
50
50
  trait: "trait",
51
51
  alleles: [{
@@ -62,7 +62,7 @@ const monohybridSpec = (letter = "A", dominant = "tall", recessive = "short") =>
62
62
  [recessive]: "var(--stage-muted)"
63
63
  }
64
64
  });
65
- /** ABO blood groups — multiple alleles + codominance (Aᴬ Aᴮ → AB). */
65
+ /** ABO blood groups, multiple alleles + codominance (Aᴬ Aᴮ → AB). */
66
66
  const BLOOD_TYPE_SPEC = {
67
67
  trait: "blood type",
68
68
  alleles: [
@@ -89,7 +89,7 @@ const BLOOD_TYPE_SPEC = {
89
89
  O: "var(--stage-muted)"
90
90
  }
91
91
  };
92
- /** Incomplete dominance — red × white = pink (a blended heterozygote). */
92
+ /** Incomplete dominance, red × white = pink (a blended heterozygote). */
93
93
  const INCOMPLETE_SPEC = {
94
94
  trait: "flower colour",
95
95
  alleles: [{
@@ -116,7 +116,7 @@ const CROSS_PRESETS = {
116
116
  "blood-type": BLOOD_TYPE_SPEC,
117
117
  incomplete: INCOMPLETE_SPEC
118
118
  };
119
- /** Two independent genes — the classic dihybrid 9:3:3:1 (height × seed colour). */
119
+ /** Two independent genes, the classic dihybrid 9:3:3:1 (height × seed colour). */
120
120
  const DIHYBRID_LOCI = [monohybridSpec("A", "tall", "short"), monohybridSpec("B", "yellow", "green")];
121
121
  /** every distinct phenotype label a single-locus model can show (stable order). */
122
122
  function phenotypeLabels(m) {
@@ -1,13 +1,13 @@
1
1
  'use client';
2
2
 
3
3
  import { CheckButton, StatusPill } from "../../kit/controls.mjs";
4
- import { LabFrame, LiveRegion } from "../../kit/frame.mjs";
4
+ import { ControlBar, LabFrame, LiveRegion } from "../../kit/frame.mjs";
5
5
  import { useEffect, useState } from "react";
6
6
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
7
7
 
8
8
  //#region src/biology/genetic-cross/grid.tsx
9
9
  /**
10
- * CrossGrid — the shared Punnett-grid UI (single source of truth for every cross
10
+ * CrossGrid, the shared Punnett-grid UI (single source of truth for every cross
11
11
  * lab: monohybrid, dihybrid, sex-linked). It is PRESENTATIONAL: the parent labs
12
12
  * compute the gametes + the combine rule and hand them in; this draws the gametes
13
13
  * on the edges, fills the N×N grid, runs predict-before-reveal, and reads off the
@@ -91,6 +91,7 @@ function CrossGrid({ gametes1, gametes2, gameteLabel, combine, traitLabel, reset
91
91
  });
92
92
  };
93
93
  const cellBg = (c) => highlight === c.genotype ? `color-mix(in oklab, ${c.phenotype.color} 34%, var(--stage-bg))` : `color-mix(in oklab, ${c.phenotype.color} 13%, var(--stage-bg))`;
94
+ const cellAria = (c, r, ci) => revealed ? `${gameteLabel(gametes1[r])} × ${gameteLabel(gametes2[ci])} → ${c.genotype}, ${c.phenotype.label}` : `${gameteLabel(gametes1[r])} × ${gameteLabel(gametes2[ci])}, hidden until revealed`;
94
95
  const figure = /* @__PURE__ */ jsxs(Fragment$1, { children: [legend, /* @__PURE__ */ jsxs("div", {
95
96
  style: {
96
97
  borderRadius: 14,
@@ -99,141 +100,149 @@ function CrossGrid({ gametes1, gametes2, gameteLabel, combine, traitLabel, reset
99
100
  padding: 16,
100
101
  overflowX: "auto"
101
102
  },
102
- children: [
103
- header,
104
- /* @__PURE__ */ jsxs("div", {
105
- style: {
106
- display: "inline-grid",
107
- gridTemplateColumns: `${cellSize}px repeat(${gametes2.length}, ${cellSize}px)`,
108
- gap: 4
109
- },
110
- children: [
111
- /* @__PURE__ */ jsx("div", {}),
112
- gametes2.map((g, i) => /* @__PURE__ */ jsx("div", {
113
- style: {
114
- textAlign: "center",
115
- fontSize,
116
- fontWeight: 800,
117
- color: "var(--stage-fg)"
118
- },
119
- children: gameteLabel(g)
120
- }, i)),
121
- cells.map((row, r) => /* @__PURE__ */ jsxs(Frag, { children: [/* @__PURE__ */ jsx("div", {
122
- style: {
123
- display: "flex",
124
- alignItems: "center",
125
- justifyContent: "center",
126
- fontSize,
127
- fontWeight: 800,
128
- color: "var(--stage-fg)"
129
- },
130
- children: gameteLabel(gametes1[r])
131
- }), row.map((c, ci) => /* @__PURE__ */ jsx("button", {
132
- type: "button",
133
- onClick: () => revealed && setHighlight((h) => h === c.genotype ? null : c.genotype),
134
- title: revealed ? `${c.genotype} → ${c.phenotype.label}` : void 0,
135
- style: {
136
- width: cellSize,
137
- height: cellSize,
138
- borderRadius: 6,
139
- border: "1px solid var(--stage-grid)",
140
- background: revealed ? cellBg(c) : "var(--stage-bg)",
141
- cursor: revealed ? "pointer" : "default",
142
- fontSize,
143
- fontWeight: 700,
144
- color: "var(--stage-fg)",
145
- padding: 0
146
- },
147
- children: revealed ? c.genotype : "?"
148
- }, ci))] }, r))
149
- ]
150
- }),
151
- !revealed ? /* @__PURE__ */ jsxs("div", {
152
- className: "lab-bar",
153
- style: { marginTop: 12 },
154
- children: [/* @__PURE__ */ jsxs("span", {
155
- style: { fontWeight: 600 },
156
- children: [
157
- "Predict the ",
158
- traitLabel,
159
- " ratio, then…"
160
- ]
161
- }), /* @__PURE__ */ jsx(CheckButton, {
162
- onClick: reveal,
163
- children: "Reveal the cross"
164
- })]
165
- }) : /* @__PURE__ */ jsxs("div", {
166
- className: "lab-bar",
103
+ children: [/* @__PURE__ */ jsxs("div", {
104
+ role: "table",
105
+ "aria-label": revealed ? `Punnett grid, ${gametes1.length} by ${gametes2.length}. ${traitLabel} ratio ${phenoTally.map((p) => `${p.n} ${p.label}`).join(", ")}.` : `Punnett grid, ${gametes1.length} by ${gametes2.length}, offspring hidden until you reveal the cross.`,
106
+ style: {
107
+ display: "inline-grid",
108
+ gridTemplateColumns: `${cellSize}px repeat(${gametes2.length}, ${cellSize}px)`,
109
+ gap: 4
110
+ },
111
+ children: [/* @__PURE__ */ jsxs("div", {
112
+ role: "row",
113
+ style: { display: "contents" },
114
+ children: [/* @__PURE__ */ jsx("div", {
115
+ role: "columnheader",
116
+ "aria-hidden": true,
117
+ style: { pointerEvents: "none" }
118
+ }), gametes2.map((g, i) => /* @__PURE__ */ jsx("div", {
119
+ role: "columnheader",
120
+ style: {
121
+ textAlign: "center",
122
+ fontSize,
123
+ fontWeight: 800,
124
+ color: "var(--stage-fg)"
125
+ },
126
+ children: gameteLabel(g)
127
+ }, i))]
128
+ }), cells.map((row, r) => /* @__PURE__ */ jsxs("div", {
129
+ role: "row",
130
+ style: { display: "contents" },
131
+ children: [/* @__PURE__ */ jsx("div", {
132
+ role: "rowheader",
133
+ style: {
134
+ display: "flex",
135
+ alignItems: "center",
136
+ justifyContent: "center",
137
+ fontSize,
138
+ fontWeight: 800,
139
+ color: "var(--stage-fg)"
140
+ },
141
+ children: gameteLabel(gametes1[r])
142
+ }), row.map((c, ci) => /* @__PURE__ */ jsx("button", {
143
+ type: "button",
144
+ role: "cell",
145
+ "aria-label": cellAria(c, r, ci),
146
+ onClick: () => revealed && setHighlight((h) => h === c.genotype ? null : c.genotype),
147
+ title: revealed ? `${c.genotype} → ${c.phenotype.label}` : void 0,
148
+ style: {
149
+ width: cellSize,
150
+ height: cellSize,
151
+ borderRadius: 6,
152
+ border: "1px solid var(--stage-grid)",
153
+ background: revealed ? cellBg(c) : "var(--stage-bg)",
154
+ cursor: revealed ? "pointer" : "default",
155
+ fontSize,
156
+ fontWeight: 700,
157
+ color: "var(--stage-fg)",
158
+ padding: 0
159
+ },
160
+ children: revealed ? c.genotype : "?"
161
+ }, ci))]
162
+ }, r))]
163
+ }), revealed && highlight && (() => {
164
+ const c = flat.find((x) => x.genotype === highlight);
165
+ return /* @__PURE__ */ jsxs("p", {
167
166
  style: {
168
- marginTop: 14,
169
- gap: 16,
170
- flexWrap: "wrap"
167
+ fontSize: 12,
168
+ color: "var(--stage-muted)",
169
+ margin: "8px 0 0"
171
170
  },
172
171
  children: [
173
- showGenotypeTally && /* @__PURE__ */ jsx(Bar, {
174
- label: "Genotype",
175
- parts: genotypes.map((g) => ({
176
- n: genoCount(g),
177
- color: genoColor(g),
178
- tag: g
179
- }))
180
- }),
181
- /* @__PURE__ */ jsx(Bar, {
182
- label: traitLabel,
183
- parts: phenoTally.map((p) => ({
184
- n: p.n,
185
- color: p.color,
186
- tag: p.label
187
- }))
172
+ highlight,
173
+ ": ",
174
+ genoCount(highlight),
175
+ " of ",
176
+ flat.length,
177
+ " (",
178
+ (genoCount(highlight) / flat.length * 100).toFixed(0),
179
+ "%) → ",
180
+ /* @__PURE__ */ jsx("b", {
181
+ style: { color: c.phenotype.color },
182
+ children: c.phenotype.label
188
183
  }),
189
- /* @__PURE__ */ jsxs(StatusPill, {
190
- ok: true,
191
- children: [
192
- phenoTally.map((p) => p.n).join(":"),
193
- " ",
194
- phenoTally.map((p) => p.label).join(" : ")
195
- ]
196
- })
184
+ c.note ?? ""
197
185
  ]
198
- }),
199
- revealed && highlight && (() => {
200
- const c = flat.find((x) => x.genotype === highlight);
201
- return /* @__PURE__ */ jsxs("p", {
202
- style: {
203
- fontSize: 12,
204
- color: "var(--stage-muted)",
205
- margin: "8px 0 0"
206
- },
207
- children: [
208
- highlight,
209
- ": ",
210
- genoCount(highlight),
211
- " of ",
212
- flat.length,
213
- " (",
214
- (genoCount(highlight) / flat.length * 100).toFixed(0),
215
- "%) → ",
216
- /* @__PURE__ */ jsx("b", {
217
- style: { color: c.phenotype.color },
218
- children: c.phenotype.label
219
- }),
220
- c.note ?? ""
221
- ]
222
- });
223
- })()
224
- ]
186
+ });
187
+ })()]
225
188
  })] });
226
189
  return /* @__PURE__ */ jsx(LabFrame, {
227
190
  title,
228
191
  prompt,
229
192
  objectives,
193
+ controls: /* @__PURE__ */ jsxs(ControlBar, { children: [header, !revealed && /* @__PURE__ */ jsxs("div", {
194
+ className: "lab-bar",
195
+ children: [/* @__PURE__ */ jsxs("span", {
196
+ style: { fontWeight: 600 },
197
+ children: [
198
+ "Predict the ",
199
+ traitLabel,
200
+ " ratio, then…"
201
+ ]
202
+ }), /* @__PURE__ */ jsx(CheckButton, {
203
+ onClick: reveal,
204
+ children: "Reveal the cross"
205
+ })]
206
+ })] }),
207
+ aside: revealed ? /* @__PURE__ */ jsxs("div", {
208
+ className: "lab-bar",
209
+ style: {
210
+ gap: 16,
211
+ flexWrap: "wrap",
212
+ flexDirection: "column",
213
+ alignItems: "stretch"
214
+ },
215
+ children: [
216
+ showGenotypeTally && /* @__PURE__ */ jsx(Bar, {
217
+ label: "Genotype",
218
+ parts: genotypes.map((g) => ({
219
+ n: genoCount(g),
220
+ color: genoColor(g),
221
+ tag: g
222
+ }))
223
+ }),
224
+ /* @__PURE__ */ jsx(Bar, {
225
+ label: traitLabel,
226
+ parts: phenoTally.map((p) => ({
227
+ n: p.n,
228
+ color: p.color,
229
+ tag: p.label
230
+ }))
231
+ }),
232
+ /* @__PURE__ */ jsxs(StatusPill, {
233
+ ok: true,
234
+ children: [
235
+ phenoTally.map((p) => p.n).join(":"),
236
+ " ",
237
+ phenoTally.map((p) => p.label).join(" : ")
238
+ ]
239
+ })
240
+ ]
241
+ }) : void 0,
230
242
  footer: /* @__PURE__ */ jsx(LiveRegion, { children: revealed ? `${traitLabel} ratio ${phenoTally.map((p) => `${p.n} ${p.label}`).join(", ")}.` : "Predict, then reveal." }),
231
243
  children: figure
232
244
  });
233
245
  }
234
- function Frag({ children }) {
235
- return /* @__PURE__ */ jsx(Fragment$1, { children });
236
- }
237
246
 
238
247
  //#endregion
239
248
  export { CrossGrid };
@@ -8,7 +8,7 @@ import { useLearner } from "@classytic/stage";
8
8
 
9
9
  //#region src/biology/genetic-cross/preset.tsx
10
10
  /**
11
- * GeneticCrossLab — ONE authorable cross tool for every Mendelian pattern, now
11
+ * GeneticCrossLab, ONE authorable cross tool for every Mendelian pattern, now
12
12
  * MULTI-LOCUS. The creator declares one model per gene; the lab derives gametes by
13
13
  * independent assortment (one allele per locus → 2ⁿ gametes), fills the Punnett
14
14
  * grid via the shared CrossGrid, and reads off the genotype + phenotype ratios.
@@ -53,7 +53,7 @@ function GeneticCrossLab({ spec, loci, parent1, parent2, predictFirst = true, ti
53
53
  const [a, b] = perLocus[0].geno;
54
54
  if (a !== b) {
55
55
  const [hi, lo] = models[0].masks(a, b) ? [a, b] : models[0].masks(b, a) ? [b, a] : ["", ""];
56
- if (hi) note = ` — the recessive ${lo} is still there, masked`;
56
+ if (hi) note = `, the recessive ${lo} is still there, masked`;
57
57
  }
58
58
  }
59
59
  return {
@@ -159,8 +159,8 @@ function GeneticCrossLab({ spec, loci, parent1, parent2, predictFirst = true, ti
159
159
  predictFirst,
160
160
  header,
161
161
  legend,
162
- title: title ?? (multi ? "Dihybrid cross — 9 : 3 : 3 : 1" : "The cross you can count"),
163
- prompt: prompt ?? (multi ? "Two genes assort independently — four gametes each, sixteen boxes, four phenotype classes." : "Alleles segregate into gametes, recombine, and the ratio falls out."),
162
+ title: title ?? (multi ? "Dihybrid cross, 9 : 3 : 3 : 1" : "The cross you can count"),
163
+ prompt: prompt ?? (multi ? "Two genes assort independently, four gametes each, sixteen boxes, four phenotype classes." : "Alleles segregate into gametes, recombine, and the ratio falls out."),
164
164
  objectives,
165
165
  showGenotypeTally: !multi,
166
166
  onReveal: () => {
@@ -7,9 +7,9 @@ import { useLearner } from "@classytic/stage";
7
7
 
8
8
  //#region src/biology/genetic-cross/sex-linked.tsx
9
9
  /**
10
- * SexLinkedCrossLab — an X-linked gene cross (colour blindness, haemophilia…) on
11
- * the shared CrossGrid. The biology that's special — the Y carries no allele, so
12
- * males are HEMIZYGOUS (a single recessive X shows) — lives here; the grid/tally/
10
+ * SexLinkedCrossLab, an X-linked gene cross (colour blindness, haemophilia…) on
11
+ * the shared CrossGrid. The biology that's special, the Y carries no allele, so
12
+ * males are HEMIZYGOUS (a single recessive X shows), lives here; the grid/tally/
13
13
  * predict UI is reused. The payoff: affected sons from a carrier mother, while
14
14
  * daughters are carriers, not affected.
15
15
  */
@@ -60,7 +60,7 @@ function SexLinkedCrossLab({ allele = "B", dominant = "normal", recessive = "col
60
60
  label: `${affected ? recessive : dominant} ♂`,
61
61
  color: affected ? COL.recM : COL.domM
62
62
  },
63
- note: ` — males are hemizygous: one ${Xr} is enough to show ${recessive}`
63
+ note: `: males are hemizygous: one ${Xr} is enough to show ${recessive}`
64
64
  };
65
65
  }
66
66
  const xs = [mx, fx].sort((a, b) => (isDom(a) ? -1 : 1) - (isDom(b) ? -1 : 1));
@@ -72,7 +72,7 @@ function SexLinkedCrossLab({ allele = "B", dominant = "normal", recessive = "col
72
72
  label: `${domPresent ? dominant : recessive} ♀`,
73
73
  color: domPresent ? COL.domF : COL.recF
74
74
  },
75
- note: carrier ? ` — a carrier (one ${Xr}), ${dominant} herself but can pass it on` : ""
75
+ note: carrier ? `: a carrier (one ${Xr}), ${dominant} herself but can pass it on` : ""
76
76
  };
77
77
  };
78
78
  const cycleMom = (i) => setMom((m) => m.map((t, j) => j === i ? t === XD ? Xr : XD : t));
@@ -201,8 +201,8 @@ function SexLinkedCrossLab({ allele = "B", dominant = "normal", recessive = "col
201
201
  predictFirst,
202
202
  header,
203
203
  legend,
204
- title: title ?? "Sex linkage — why mostly sons are affected",
205
- prompt: prompt ?? "The gene rides on the X. A carrier mother passes it to half her sons — who, with no second X, show it.",
204
+ title: title ?? "Sex linkage, why mostly sons are affected",
205
+ prompt: prompt ?? "The gene rides on the X. A carrier mother passes it to half her sons, who, with no second X, show it.",
206
206
  objectives,
207
207
  showGenotypeTally: true,
208
208
  onReveal: () => {
@@ -11,10 +11,10 @@ import { Axes, Dot, Label, Polyline, Segment, Stage } from "@classytic/stage";
11
11
 
12
12
  //#region src/biology/photosynthesis-factors/preset.tsx
13
13
  /**
14
- * PhotosynthesisFactorsLab — limiting factors: the slowest worker sets the pace.
14
+ * PhotosynthesisFactorsLab, limiting factors: the slowest worker sets the pace.
15
15
  *
16
16
  * Sliders for light, CO₂ and temperature. The rate climbs with light then
17
- * PLATEAUS at whichever factor is in shortest supply — raise CO₂ and the SAME
17
+ * PLATEAUS at whichever factor is in shortest supply, raise CO₂ and the SAME
18
18
  * light curve climbs to a higher plateau, proving light was no longer limiting.
19
19
  * Temperature is different: it gives a PEAK (optimum) not a plateau, because past
20
20
  * the optimum enzymes denature. "Freeze curve" overlays a faint copy so two CO₂
@@ -26,7 +26,7 @@ import { Axes, Dot, Label, Polyline, Segment, Stage } from "@classytic/stage";
26
26
  const CLIFF = 14;
27
27
  const FACTORS_CHALLENGE = [{
28
28
  id: "plateau",
29
- prompt: "Raising light further does nothing — the rate-vs-light curve has flattened. What sets the height of that plateau?",
29
+ prompt: "Raising light further does nothing, the rate-vs-light curve has flattened. What sets the height of that plateau?",
30
30
  choices: [
31
31
  {
32
32
  value: "factor",
@@ -38,14 +38,14 @@ const FACTORS_CHALLENGE = [{
38
38
  },
39
39
  {
40
40
  value: "random",
41
- label: "nothing — it’s random"
41
+ label: "nothing: it’s random"
42
42
  }
43
43
  ],
44
44
  answer: "factor",
45
- explain: "Where the curve flattens, some OTHER factor (CO₂ supply or temperature) is now the bottleneck — the slowest worker sets the pace."
45
+ explain: "Where the curve flattens, some OTHER factor (CO₂ supply or temperature) is now the bottleneck, the slowest worker sets the pace."
46
46
  }, {
47
47
  id: "cliff",
48
- prompt: "Push temperature well ABOVE the optimum and the rate CRASHES — not just plateaus. Why?",
48
+ prompt: "Push temperature well ABOVE the optimum and the rate CRASHES, not just plateaus. Why?",
49
49
  choices: [
50
50
  {
51
51
  value: "denature",
@@ -61,9 +61,9 @@ const FACTORS_CHALLENGE = [{
61
61
  }
62
62
  ],
63
63
  answer: "denature",
64
- explain: "Past the optimum the enzymes lose their shape (denature) — that destroys capacity, unlike a mere limiting factor."
64
+ explain: "Past the optimum the enzymes lose their shape (denature), that destroys capacity, unlike a mere limiting factor."
65
65
  }];
66
- function PhotosynthesisFactorsLab({ light = 70, co2 = 50, temperature = 25, tempOptimum = 28, title = "Limiting factors — the slowest worker sets the pace", prompt = "Raise light: the rate plateaus where another factor (CO₂ or temperature) takes over.", height = 240, objectives }) {
66
+ function PhotosynthesisFactorsLab({ light = 70, co2 = 50, temperature = 25, tempOptimum = 28, title = "Limiting factors: the slowest worker sets the pace", prompt = "Raise light: the rate plateaus where another factor (CO₂ or temperature) takes over.", height = 240, objectives }) {
67
67
  const [l, setL] = useState(light);
68
68
  const [c, setC] = useState(co2);
69
69
  const [t, setT] = useState(temperature);
@@ -9,12 +9,12 @@ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
9
9
 
10
10
  //#region src/biology/respiration/preset.tsx
11
11
  /**
12
- * RespirationLab — photosynthesis ⇌ respiration: one runs the other backwards.
12
+ * RespirationLab, photosynthesis ⇌ respiration: one runs the other backwards.
13
13
  *
14
14
  * Two reaction flows, stacked, drawn with the SHARED MoleculeGlyph + ReactionFlow
15
15
  * engine: photosynthesis (6CO₂ + 6H₂O + light → glucose + 6O₂) and respiration
16
16
  * (glucose + 6O₂ → 6CO₂ + 6H₂O + ATP). The products of one are literally the
17
- * reactants of the other — the closed loop is impossible to forget. A day/night
17
+ * reactants of the other, the closed loop is impossible to forget. A day/night
18
18
  * toggle shows the NET gas exchange: by day photosynthesis outpaces respiration
19
19
  * (net O₂ out); at night only respiration runs (net CO₂ out).
20
20
  *
@@ -79,7 +79,7 @@ const RESP_CHALLENGE = [{
79
79
  answer: "o2",
80
80
  explain: "Photosynthesis fixes more CO₂ than respiration makes, and releases more O₂ than it uses."
81
81
  }];
82
- function RespirationLab({ mode = "day", title = "Photosynthesis ⇌ Respiration — one runs the other backwards", prompt = "The products of one are the reactants of the other. Flip day/night to see the net gas exchange.", objectives }) {
82
+ function RespirationLab({ mode = "day", title = "Photosynthesis ⇌ Respiration: one runs the other backwards", prompt = "The products of one are the reactants of the other. Flip day/night to see the net gas exchange.", objectives }) {
83
83
  const [when, setWhen] = useState(mode);
84
84
  const day = when === "day";
85
85
  const challenge = useChallenge(RESP_CHALLENGE);
@@ -138,7 +138,7 @@ function RespirationLab({ mode = "day", title = "Photosynthesis ⇌ Respiration
138
138
  color: "var(--stage-muted)",
139
139
  fontWeight: 600
140
140
  },
141
- children: "↑ products feed ↓ reactants — the same six molecules loop ↑"
141
+ children: "↑ products feed ↓ reactants, the same six molecules loop ↑"
142
142
  }),
143
143
  flowCard("Respiration", "mitochondrion (always)", RESP, true, "var(--stage-accent-2)")
144
144
  ]
@@ -9,12 +9,12 @@ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
9
9
 
10
10
  //#region src/biology/sequence/central-dogma.tsx
11
11
  /**
12
- * CentralDogmaLab — the whole central dogma in one flow: DNA → (transcription) →
12
+ * CentralDogmaLab, the whole central dogma in one flow: DNA → (transcription) →
13
13
  * mRNA → (translation) → protein. The learner does BOTH steps on one starting
14
14
  * strand: first pair the DNA template into mRNA (T→U), then read each 3-base codon
15
15
  * to its amino acid. Translation unlocks only once the mRNA is correct, so the
16
16
  * dependency (you can't translate what isn't transcribed) is felt. Reuses the
17
- * sequence core (TRANSCRIBE + CODON_TABLE) — no new pairing logic.
17
+ * sequence core (TRANSCRIBE + CODON_TABLE), no new pairing logic.
18
18
  */
19
19
  const hash = (s) => {
20
20
  let h = 0;
@@ -44,7 +44,7 @@ function CentralDogmaLab({ dna = [
44
44
  "A",
45
45
  "T",
46
46
  "T"
47
- ], title = "The central dogma — DNA → mRNA → protein", prompt = "Transcribe the DNA into mRNA (T→U), then translate each codon into an amino acid.", objectives }) {
47
+ ], title = "The central dogma: DNA → mRNA → protein", prompt = "Transcribe the DNA into mRNA (T→U), then translate each codon into an amino acid.", objectives }) {
48
48
  const nCodons = Math.floor(dna.length / 3);
49
49
  const [mrna, setMrna] = useState(() => dna.map(() => null));
50
50
  const [protein, setProtein] = useState(() => Array.from({ length: nCodons }, () => null));
@@ -154,7 +154,7 @@ function CentralDogmaLab({ dna = [
154
154
  children: b
155
155
  }, i))]
156
156
  }),
157
- arrow("transcription — copy the template, T → U"),
157
+ arrow("transcription, copy the template, T → U"),
158
158
  /* @__PURE__ */ jsxs("div", {
159
159
  style: {
160
160
  display: "flex",
@@ -194,7 +194,7 @@ function CentralDogmaLab({ dna = [
194
194
  }, i);
195
195
  })]
196
196
  }),
197
- arrow(transcribed ? "translation — read each codon off the genetic code" : "translation — locked until the mRNA is complete"),
197
+ arrow(transcribed ? "translation, read each codon off the genetic code" : "translation, locked until the mRNA is complete"),
198
198
  /* @__PURE__ */ jsxs("div", {
199
199
  style: {
200
200
  display: "flex",