@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,1491 @@
1
+ 'use client';
2
+
3
+ import { Chip, Slider } from "../../kit/controls.mjs";
4
+ import { Callout, ControlBar, Field, LabFrame } from "../../kit/frame.mjs";
5
+ import { ChallengeCard, useChallenge, useCheckpoint } from "../../kit/pedagogy.mjs";
6
+ import { FlowDots, MosfetGlyph, ResistorGlyph, Tag, Wire } from "../../kit/electronics.mjs";
7
+ import { useReducedMotion } from "../../kit/anim.mjs";
8
+ import { LabAsk } from "../../kit/ask.mjs";
9
+ import { CoordPlane } from "../../kit/coords.mjs";
10
+ import { useState } from "react";
11
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
12
+ import { Dot, Label, Polyline, useFrameLoop } from "@classytic/stage";
13
+ import { solveDC } from "@classytic/stage/circuit";
14
+
15
+ //#region src/circuits/cmos-gate/preset.tsx
16
+ /**
17
+ * CmosInverterLab — the moment a pair of transistors BECOMES a logic gate. A PMOS
18
+ * pull-up (to VDD) and an NMOS pull-down (to GND) share one input A and one output
19
+ * Y. Drag the input: when A is LOW the PMOS conducts and pulls Y HIGH; when A is
20
+ * HIGH the NMOS conducts and pulls Y LOW. The output is the inverse of the input —
21
+ * a NOT gate — and the output voltage is SOLVED by the circuit engine (so the
22
+ * transfer curve shows the real, sharp analog-to-digital transition near VDD/2).
23
+ * Exactly one network conducts at the rails, which is why CMOS draws ~no static
24
+ * power. This is the bridge from the silicon to the truth table.
25
+ */
26
+ const C_HI = "var(--stage-good)";
27
+ const C_LO = "var(--stage-danger)";
28
+ const K = .5;
29
+ const PREDICT_Q = [{
30
+ id: "invert-high",
31
+ prompt: "This is a CMOS inverter (NOT gate). What is the output Y when the input A is HIGH (1)?",
32
+ choices: [{
33
+ value: "0",
34
+ label: "Y = 0 (LOW)"
35
+ }, {
36
+ value: "1",
37
+ label: "Y = 1 (HIGH)"
38
+ }],
39
+ answer: "0",
40
+ explain: "A HIGH input turns the NMOS pull-down ON and the PMOS pull-up OFF, so Y is pulled to GND: Y = 0. The output is the inverse of the input."
41
+ }];
42
+ const W = 460, H = 250;
43
+ const STK = 300;
44
+ const PCX = STK - 9, NCX = STK - 9;
45
+ const PCY = 82, NCY = 166, MHALF = 36;
46
+ const VDD_Y = 30, GND_Y = 220, Y_Y = (284 - MHALF) / 2;
47
+ const GATE_X = PCX - 13 - 24;
48
+ function CmosInverterLab({ vdd = 5, vth = 2, show = "both", title = "CMOS inverter: two transistors become a NOT gate", prompt = "Drag the input A. Low input: the top (PMOS) opens and pulls the output HIGH; high input: the bottom (NMOS) opens and pulls it LOW. The output is the inverse, a NOT gate.", ask, activity = "cmos-inverter" } = {}) {
49
+ const [A, setA] = useState(0);
50
+ const [phase, setPhase] = useState(0);
51
+ const reduce = useReducedMotion();
52
+ const ch = useChallenge(PREDICT_Q);
53
+ useCheckpoint({
54
+ solved: ch.allCorrect,
55
+ activity: "cmos-gate:predict"
56
+ });
57
+ const mk = (a) => [
58
+ {
59
+ kind: "V",
60
+ n1: 1,
61
+ n2: 0,
62
+ value: vdd
63
+ },
64
+ {
65
+ kind: "V",
66
+ n1: 3,
67
+ n2: 0,
68
+ value: a
69
+ },
70
+ {
71
+ kind: "M",
72
+ pmos: true,
73
+ n1: 2,
74
+ n2: 1,
75
+ n3: 3,
76
+ value: 0,
77
+ vth,
78
+ k: K
79
+ },
80
+ {
81
+ kind: "M",
82
+ n1: 2,
83
+ n2: 0,
84
+ n3: 3,
85
+ value: 0,
86
+ vth,
87
+ k: K
88
+ }
89
+ ];
90
+ const Y = solveDC(mk(A)).nodeV[2] ?? 0;
91
+ const pmosOn = vdd - A > vth;
92
+ const nmosOn = A > vth;
93
+ const aHi = A > vdd / 2, yHi = Y > vdd / 2;
94
+ useFrameLoop((f) => setPhase((p) => (p + f.dtMs / 1e3 * .4) % 1), { running: (pmosOn || nmosOn) && !reduce });
95
+ const pTop = [STK, PCY - MHALF], pBot = [STK, 118];
96
+ const nTop = [STK, NCY - MHALF], nBot = [STK, 202];
97
+ const vddRail = [[200, VDD_Y], [360, VDD_Y]];
98
+ const scene = /* @__PURE__ */ jsx("div", {
99
+ style: {
100
+ borderRadius: 14,
101
+ overflow: "hidden",
102
+ background: "var(--stage-bg)",
103
+ border: "1px solid var(--stage-grid)"
104
+ },
105
+ children: /* @__PURE__ */ jsxs("svg", {
106
+ viewBox: `0 0 ${W} ${H}`,
107
+ width: "100%",
108
+ role: "img",
109
+ "aria-label": `CMOS inverter, input ${aHi ? "high" : "low"}, output ${yHi ? "high" : "low"}`,
110
+ children: [
111
+ /* @__PURE__ */ jsx(Wire, {
112
+ points: vddRail,
113
+ live: pmosOn
114
+ }),
115
+ /* @__PURE__ */ jsx(Wire, {
116
+ points: [[200, GND_Y], [360, GND_Y]],
117
+ live: nmosOn
118
+ }),
119
+ /* @__PURE__ */ jsx(Wire, {
120
+ points: [[STK, VDD_Y], pTop],
121
+ live: pmosOn
122
+ }),
123
+ /* @__PURE__ */ jsx(Wire, {
124
+ points: [nBot, [STK, GND_Y]],
125
+ live: nmosOn
126
+ }),
127
+ /* @__PURE__ */ jsx(Wire, {
128
+ points: [
129
+ pBot,
130
+ [STK, Y_Y],
131
+ [430, Y_Y]
132
+ ],
133
+ live: true
134
+ }),
135
+ /* @__PURE__ */ jsx(Wire, { points: [
136
+ [GATE_X, PCY],
137
+ [220, PCY],
138
+ [220, NCY],
139
+ [GATE_X, NCY]
140
+ ] }),
141
+ /* @__PURE__ */ jsx(Wire, { points: [[110, Y_Y], [220, Y_Y]] }),
142
+ pmosOn && /* @__PURE__ */ jsx(FlowDots, {
143
+ points: [
144
+ ...vddRail.slice(1),
145
+ pTop,
146
+ pBot,
147
+ [STK, Y_Y]
148
+ ],
149
+ phase
150
+ }),
151
+ nmosOn && /* @__PURE__ */ jsx(FlowDots, {
152
+ points: [
153
+ [STK, Y_Y],
154
+ nTop,
155
+ nBot,
156
+ [STK, GND_Y]
157
+ ],
158
+ phase
159
+ }),
160
+ /* @__PURE__ */ jsx(MosfetGlyph, {
161
+ cx: PCX,
162
+ cy: PCY,
163
+ half: MHALF,
164
+ pmos: true,
165
+ on: pmosOn,
166
+ live: pmosOn,
167
+ label: "PMOS"
168
+ }),
169
+ /* @__PURE__ */ jsx(MosfetGlyph, {
170
+ cx: NCX,
171
+ cy: NCY,
172
+ half: MHALF,
173
+ on: nmosOn,
174
+ live: nmosOn,
175
+ label: "NMOS"
176
+ }),
177
+ /* @__PURE__ */ jsx(Tag, {
178
+ x: 365,
179
+ y: 34,
180
+ text: `VDD ${vdd}V`,
181
+ color: "var(--stage-fg)",
182
+ size: 12,
183
+ weight: 700,
184
+ anchor: "start"
185
+ }),
186
+ /* @__PURE__ */ jsx(Tag, {
187
+ x: 365,
188
+ y: 224,
189
+ text: "GND",
190
+ color: "var(--stage-muted)",
191
+ size: 12,
192
+ weight: 700,
193
+ anchor: "start"
194
+ }),
195
+ /* @__PURE__ */ jsx(Tag, {
196
+ x: 104,
197
+ y: Y_Y - 8,
198
+ text: "A",
199
+ color: "var(--stage-fg)",
200
+ size: 12,
201
+ weight: 700,
202
+ anchor: "end"
203
+ }),
204
+ /* @__PURE__ */ jsx(Tag, {
205
+ x: 104,
206
+ y: 134,
207
+ text: aHi ? "1" : "0",
208
+ color: aHi ? C_HI : C_LO,
209
+ size: 12,
210
+ weight: 700,
211
+ anchor: "end"
212
+ }),
213
+ /* @__PURE__ */ jsx("circle", {
214
+ cx: 434,
215
+ cy: Y_Y,
216
+ r: 4,
217
+ fill: yHi ? C_HI : C_LO
218
+ }),
219
+ /* @__PURE__ */ jsx(Tag, {
220
+ x: 442,
221
+ y: Y_Y - 8,
222
+ text: "Y",
223
+ color: "var(--stage-fg)",
224
+ size: 12,
225
+ weight: 700,
226
+ anchor: "start"
227
+ }),
228
+ /* @__PURE__ */ jsx(Tag, {
229
+ x: 442,
230
+ y: 134,
231
+ text: yHi ? "1" : "0",
232
+ color: yHi ? C_HI : C_LO,
233
+ size: 12,
234
+ weight: 700,
235
+ anchor: "start"
236
+ })
237
+ ]
238
+ })
239
+ });
240
+ const pts = [];
241
+ for (let a = 0; a <= vdd + 1e-6; a += vdd / 60) pts.push({
242
+ x: a,
243
+ y: solveDC(mk(a)).nodeV[2] ?? 0
244
+ });
245
+ const graph = /* @__PURE__ */ jsxs(CoordPlane, {
246
+ view: {
247
+ xMin: 0,
248
+ xMax: vdd,
249
+ yMin: 0,
250
+ yMax: vdd
251
+ },
252
+ height: 150,
253
+ preserveAspect: false,
254
+ step: 1,
255
+ ariaLabel: "CMOS transfer curve",
256
+ children: [
257
+ /* @__PURE__ */ jsx(Polyline, {
258
+ points: pts,
259
+ color: "var(--stage-accent)",
260
+ weight: 2.5
261
+ }),
262
+ /* @__PURE__ */ jsx(Dot, {
263
+ x: A,
264
+ y: Math.max(0, Math.min(vdd, Y)),
265
+ r: 5,
266
+ color: yHi ? C_HI : C_LO
267
+ }),
268
+ /* @__PURE__ */ jsx(Label, {
269
+ x: vdd,
270
+ y: vdd * .96,
271
+ text: "output Y (V) vs input A (V)",
272
+ color: "var(--stage-muted)",
273
+ size: 10,
274
+ anchor: "end"
275
+ })
276
+ ]
277
+ });
278
+ const figure = show === "circuit" ? scene : show === "graph" ? graph : /* @__PURE__ */ jsxs("div", {
279
+ style: {
280
+ display: "flex",
281
+ flexDirection: "column",
282
+ gap: 10
283
+ },
284
+ children: [scene, graph]
285
+ });
286
+ return /* @__PURE__ */ jsx(LabFrame, {
287
+ title,
288
+ prompt,
289
+ controls: /* @__PURE__ */ jsxs(ControlBar, { children: [/* @__PURE__ */ jsx(Field, {
290
+ label: "input A",
291
+ value: `${A.toFixed(1)} V`,
292
+ children: /* @__PURE__ */ jsx(Slider, {
293
+ value: A,
294
+ min: 0,
295
+ max: vdd,
296
+ step: .1,
297
+ onChange: setA,
298
+ ariaLabel: "input voltage"
299
+ })
300
+ }), /* @__PURE__ */ jsx(Field, {
301
+ label: "quick set",
302
+ children: /* @__PURE__ */ jsxs("span", {
303
+ className: "lab-field-row",
304
+ children: [/* @__PURE__ */ jsx(Chip, {
305
+ selected: A === 0,
306
+ onClick: () => setA(0),
307
+ children: "A = 0"
308
+ }), /* @__PURE__ */ jsx(Chip, {
309
+ selected: A === vdd,
310
+ onClick: () => setA(vdd),
311
+ children: "A = 1"
312
+ })]
313
+ })
314
+ })] }),
315
+ aside: /* @__PURE__ */ jsxs("div", {
316
+ style: {
317
+ display: "flex",
318
+ flexDirection: "column",
319
+ gap: 10
320
+ },
321
+ children: [/* @__PURE__ */ jsx("div", {
322
+ className: "lab-pill",
323
+ "data-state": pmosOn !== nmosOn ? "ok" : "no",
324
+ role: "status",
325
+ style: { alignSelf: "flex-start" },
326
+ children: pmosOn && !nmosOn ? "✓ PMOS conducts, output pulled HIGH" : nmosOn && !pmosOn ? "✓ NMOS conducts, output pulled LOW" : "both partly on (the transition)"
327
+ }), /* @__PURE__ */ jsxs(Callout, {
328
+ tone: "result",
329
+ children: [/* @__PURE__ */ jsxs("table", {
330
+ style: {
331
+ fontSize: 13,
332
+ fontVariantNumeric: "tabular-nums",
333
+ borderCollapse: "collapse"
334
+ },
335
+ children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [/* @__PURE__ */ jsx("th", {
336
+ style: {
337
+ textAlign: "left",
338
+ paddingRight: 18
339
+ },
340
+ children: "A"
341
+ }), /* @__PURE__ */ jsx("th", {
342
+ style: { textAlign: "left" },
343
+ children: "Y = A′"
344
+ })] }) }), /* @__PURE__ */ jsxs("tbody", { children: [/* @__PURE__ */ jsxs("tr", {
345
+ style: { fontWeight: aHi ? 400 : 700 },
346
+ children: [/* @__PURE__ */ jsx("td", { children: "0" }), /* @__PURE__ */ jsx("td", { children: "1" })]
347
+ }), /* @__PURE__ */ jsxs("tr", {
348
+ style: { fontWeight: aHi ? 700 : 400 },
349
+ children: [/* @__PURE__ */ jsx("td", { children: "1" }), /* @__PURE__ */ jsx("td", { children: "0" })]
350
+ })] })]
351
+ }), /* @__PURE__ */ jsxs("div", {
352
+ style: {
353
+ marginTop: 6,
354
+ color: "var(--stage-muted)",
355
+ fontSize: 12
356
+ },
357
+ children: [
358
+ "output = ",
359
+ Y.toFixed(2),
360
+ " V (",
361
+ yHi ? "logic 1" : "logic 0",
362
+ ")"
363
+ ]
364
+ })]
365
+ })]
366
+ }),
367
+ footer: /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(ChallengeCard, {
368
+ questions: PREDICT_Q,
369
+ state: ch,
370
+ title: "Predict first"
371
+ }), ask ? /* @__PURE__ */ jsx(LabAsk, {
372
+ ask,
373
+ activity
374
+ }) : null] }),
375
+ children: figure
376
+ });
377
+ }
378
+ const RN_W = 460, RN_H = 250;
379
+ function RNmosNotLab({ vdd = 5, vth = 2, rpull = 2e3, title = "A NOT gate from ONE transistor", prompt = "Flip the input. HIGH turns the transistor on and pulls the output LOW; LOW leaves it off, so the resistor pulls the output HIGH. One transistor inverts — that is a NOT gate.", ask, activity = "rnmos-not" } = {}) {
380
+ const [A, setA] = useState(0);
381
+ const [phase, setPhase] = useState(0);
382
+ const reduce = useReducedMotion();
383
+ const ch = useChallenge(RN_PREDICT_Q);
384
+ useCheckpoint({
385
+ solved: ch.allCorrect,
386
+ activity: "rnmos-not:predict"
387
+ });
388
+ const mk = (a) => [
389
+ {
390
+ kind: "V",
391
+ n1: 1,
392
+ n2: 0,
393
+ value: vdd
394
+ },
395
+ {
396
+ kind: "V",
397
+ n1: 3,
398
+ n2: 0,
399
+ value: a
400
+ },
401
+ {
402
+ kind: "R",
403
+ n1: 1,
404
+ n2: 2,
405
+ value: rpull
406
+ },
407
+ {
408
+ kind: "M",
409
+ n1: 2,
410
+ n2: 0,
411
+ n3: 3,
412
+ value: 0,
413
+ vth,
414
+ k: K
415
+ }
416
+ ];
417
+ const Va = A ? vdd : 0;
418
+ const Y = solveDC(mk(Va)).nodeV[2] ?? 0;
419
+ const nmosOn = Va > vth;
420
+ const yHi = Y > vdd / 2;
421
+ const Iload = (vdd - Y) / rpull;
422
+ const Pres = Math.max(0, Iload * (vdd - Y));
423
+ useFrameLoop((f) => setPhase((p) => (p + f.dtMs / 1e3 * .4) % 1), { running: nmosOn && !reduce });
424
+ const SX = 250, VDD_Y = 30, GND_Y = 220, Y_Y = 125;
425
+ const RCY = 72, NCY = 168, NHALF = 32;
426
+ const scene = /* @__PURE__ */ jsx("div", {
427
+ style: {
428
+ borderRadius: 12,
429
+ overflow: "hidden",
430
+ background: "var(--stage-bg)",
431
+ border: "1px solid var(--stage-grid)",
432
+ maxWidth: RN_W,
433
+ margin: "0 auto"
434
+ },
435
+ children: /* @__PURE__ */ jsxs("svg", {
436
+ viewBox: `0 0 ${RN_W} ${RN_H}`,
437
+ width: "100%",
438
+ role: "img",
439
+ "aria-label": `resistor-NMOS NOT gate, input ${A ? "high" : "low"}, output ${yHi ? "high" : "low"}`,
440
+ children: [
441
+ /* @__PURE__ */ jsx(Wire, {
442
+ points: [[170, VDD_Y], [330, VDD_Y]],
443
+ live: nmosOn
444
+ }),
445
+ /* @__PURE__ */ jsx(Wire, {
446
+ points: [[170, GND_Y], [330, GND_Y]],
447
+ live: nmosOn
448
+ }),
449
+ /* @__PURE__ */ jsx(Wire, {
450
+ points: [[SX, VDD_Y], [SX, RCY - 30]],
451
+ live: nmosOn
452
+ }),
453
+ /* @__PURE__ */ jsx(Wire, {
454
+ points: [[SX, 102], [SX, Y_Y]],
455
+ live: nmosOn
456
+ }),
457
+ /* @__PURE__ */ jsx(Wire, {
458
+ points: [[SX, Y_Y], [SX, NCY - NHALF]],
459
+ live: nmosOn
460
+ }),
461
+ /* @__PURE__ */ jsx(Wire, {
462
+ points: [[SX, 200], [SX, GND_Y]],
463
+ live: nmosOn
464
+ }),
465
+ /* @__PURE__ */ jsx(Wire, {
466
+ points: [[SX, Y_Y], [392, Y_Y]],
467
+ live: yHi
468
+ }),
469
+ /* @__PURE__ */ jsx(Wire, { points: [[96, NCY], [SX - 37, NCY]] }),
470
+ nmosOn && /* @__PURE__ */ jsx(FlowDots, {
471
+ points: [
472
+ [SX, VDD_Y],
473
+ [SX, RCY],
474
+ [SX, Y_Y],
475
+ [SX, NCY],
476
+ [SX, GND_Y]
477
+ ],
478
+ phase
479
+ }),
480
+ /* @__PURE__ */ jsx("g", {
481
+ transform: `rotate(90 ${SX} ${RCY})`,
482
+ children: /* @__PURE__ */ jsx(ResistorGlyph, {
483
+ cx: SX,
484
+ cy: RCY,
485
+ half: 30,
486
+ live: nmosOn
487
+ })
488
+ }),
489
+ /* @__PURE__ */ jsx(MosfetGlyph, {
490
+ cx: SX,
491
+ cy: NCY,
492
+ half: NHALF,
493
+ on: nmosOn,
494
+ live: nmosOn,
495
+ label: "NMOS"
496
+ }),
497
+ /* @__PURE__ */ jsx(Tag, {
498
+ x: 335,
499
+ y: 34,
500
+ text: `VDD ${vdd}V`,
501
+ color: "var(--stage-fg)",
502
+ size: 12,
503
+ weight: 700,
504
+ anchor: "start"
505
+ }),
506
+ /* @__PURE__ */ jsx(Tag, {
507
+ x: 335,
508
+ y: 224,
509
+ text: "GND",
510
+ color: "var(--stage-muted)",
511
+ size: 12,
512
+ weight: 700,
513
+ anchor: "start"
514
+ }),
515
+ /* @__PURE__ */ jsx(Tag, {
516
+ x: 90,
517
+ y: NCY - 8,
518
+ text: "A (in)",
519
+ color: "var(--stage-fg)",
520
+ size: 12,
521
+ weight: 700,
522
+ anchor: "end"
523
+ }),
524
+ /* @__PURE__ */ jsx(Tag, {
525
+ x: 90,
526
+ y: 179,
527
+ text: A ? "1" : "0",
528
+ color: A ? C_HI : C_LO,
529
+ size: 13,
530
+ weight: 800,
531
+ anchor: "end"
532
+ }),
533
+ /* @__PURE__ */ jsx("circle", {
534
+ cx: 396,
535
+ cy: Y_Y,
536
+ r: 4.5,
537
+ fill: yHi ? C_HI : C_LO
538
+ }),
539
+ /* @__PURE__ */ jsx(Tag, {
540
+ x: 404,
541
+ y: Y_Y - 8,
542
+ text: "Y (out)",
543
+ color: "var(--stage-fg)",
544
+ size: 12,
545
+ weight: 700,
546
+ anchor: "start"
547
+ }),
548
+ /* @__PURE__ */ jsx(Tag, {
549
+ x: 404,
550
+ y: 136,
551
+ text: yHi ? "1" : "0",
552
+ color: yHi ? C_HI : C_LO,
553
+ size: 13,
554
+ weight: 800,
555
+ anchor: "start"
556
+ }),
557
+ /* @__PURE__ */ jsx(Tag, {
558
+ x: 272,
559
+ y: 76,
560
+ text: `${(rpull / 1e3).toFixed(rpull % 1e3 ? 1 : 0)}kΩ`,
561
+ color: "var(--stage-muted)",
562
+ size: 11,
563
+ weight: 700,
564
+ anchor: "start"
565
+ })
566
+ ]
567
+ })
568
+ });
569
+ return /* @__PURE__ */ jsx(LabFrame, {
570
+ title,
571
+ prompt,
572
+ controls: /* @__PURE__ */ jsx(ControlBar, { children: /* @__PURE__ */ jsx(Field, {
573
+ label: "input A",
574
+ children: /* @__PURE__ */ jsxs("span", {
575
+ className: "lab-field-row",
576
+ children: [/* @__PURE__ */ jsx(Chip, {
577
+ selected: A === 0,
578
+ onClick: () => setA(0),
579
+ children: "A = 0"
580
+ }), /* @__PURE__ */ jsx(Chip, {
581
+ selected: A === 1,
582
+ onClick: () => setA(1),
583
+ children: "A = 1"
584
+ })]
585
+ })
586
+ }) }),
587
+ aside: /* @__PURE__ */ jsxs("div", {
588
+ style: {
589
+ display: "flex",
590
+ flexDirection: "column",
591
+ gap: 10
592
+ },
593
+ children: [
594
+ /* @__PURE__ */ jsx("div", {
595
+ className: "lab-pill",
596
+ "data-state": yHi !== !!A ? "ok" : "no",
597
+ role: "status",
598
+ style: { alignSelf: "flex-start" },
599
+ children: A ? "transistor ON → output pulled LOW" : "transistor OFF → resistor pulls output HIGH"
600
+ }),
601
+ /* @__PURE__ */ jsxs(Callout, {
602
+ tone: "result",
603
+ children: [/* @__PURE__ */ jsxs("table", {
604
+ style: {
605
+ fontSize: 13,
606
+ fontVariantNumeric: "tabular-nums",
607
+ borderCollapse: "collapse"
608
+ },
609
+ children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [/* @__PURE__ */ jsx("th", {
610
+ style: {
611
+ textAlign: "left",
612
+ paddingRight: 18
613
+ },
614
+ children: "A"
615
+ }), /* @__PURE__ */ jsx("th", {
616
+ style: { textAlign: "left" },
617
+ children: "Y = A′"
618
+ })] }) }), /* @__PURE__ */ jsxs("tbody", { children: [/* @__PURE__ */ jsxs("tr", {
619
+ style: { fontWeight: A ? 400 : 700 },
620
+ children: [/* @__PURE__ */ jsx("td", { children: "0" }), /* @__PURE__ */ jsx("td", { children: "1" })]
621
+ }), /* @__PURE__ */ jsxs("tr", {
622
+ style: { fontWeight: A ? 700 : 400 },
623
+ children: [/* @__PURE__ */ jsx("td", { children: "1" }), /* @__PURE__ */ jsx("td", { children: "0" })]
624
+ })] })]
625
+ }), /* @__PURE__ */ jsxs("div", {
626
+ style: {
627
+ marginTop: 6,
628
+ color: "var(--stage-muted)",
629
+ fontSize: 12
630
+ },
631
+ children: [
632
+ "output = ",
633
+ Y.toFixed(2),
634
+ " V (",
635
+ yHi ? "logic 1" : "logic 0",
636
+ ")"
637
+ ]
638
+ })]
639
+ }),
640
+ /* @__PURE__ */ jsx(Callout, {
641
+ tone: "info",
642
+ children: /* @__PURE__ */ jsxs("div", {
643
+ style: {
644
+ fontSize: 12.5,
645
+ lineHeight: 1.5
646
+ },
647
+ children: [
648
+ /* @__PURE__ */ jsx("strong", { children: "The catch:" }),
649
+ " while the output is LOW, ",
650
+ Pres > 1e-4 ? `${(Pres * 1e3).toFixed(1)} mW` : "~0 mW",
651
+ " of steady current wastes power in the resistor. CMOS replaces the resistor with a second transistor so only one path ever conducts — that is why chips use CMOS."
652
+ ]
653
+ })
654
+ })
655
+ ]
656
+ }),
657
+ footer: /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(ChallengeCard, {
658
+ questions: RN_PREDICT_Q,
659
+ state: ch,
660
+ title: "Predict first"
661
+ }), ask ? /* @__PURE__ */ jsx(LabAsk, {
662
+ ask,
663
+ activity
664
+ }) : null] }),
665
+ children: scene
666
+ });
667
+ }
668
+ const RN_PREDICT_Q = [{
669
+ id: "rnmos-high",
670
+ prompt: "Input A is HIGH (1). The NMOS turns on and connects the output to ground. What is the output Y?",
671
+ choices: [{
672
+ value: "0",
673
+ label: "Y = 0 (LOW)"
674
+ }, {
675
+ value: "1",
676
+ label: "Y = 1 (HIGH)"
677
+ }],
678
+ answer: "0",
679
+ explain: "A HIGH input turns the transistor ON, so it pulls Y down to ground: Y = 0. One transistor + a pull-up resistor inverts the input — a NOT gate."
680
+ }];
681
+ const NAND_W = 480, NAND_H = 300;
682
+ function CmosNandLab({ vdd = 5, vth = 2, title = "NAND from four transistors: the universal gate", prompt = "Toggle A and B. The top PMOS pair pulls the output HIGH unless BOTH inputs are HIGH; only then does the bottom NMOS pair connect it to ground. That is a NAND, and a NAND can build every other gate.", ask, activity = "cmos-nand" } = {}) {
683
+ const [A, setA] = useState(0);
684
+ const [B, setB] = useState(0);
685
+ const [phase, setPhase] = useState(0);
686
+ const reduce = useReducedMotion();
687
+ const ch = useChallenge(NAND_PREDICT_Q);
688
+ useCheckpoint({
689
+ solved: ch.allCorrect,
690
+ activity: "cmos-nand:predict"
691
+ });
692
+ const mk = (a, b) => [
693
+ {
694
+ kind: "V",
695
+ n1: 1,
696
+ n2: 0,
697
+ value: vdd
698
+ },
699
+ {
700
+ kind: "V",
701
+ n1: 3,
702
+ n2: 0,
703
+ value: a
704
+ },
705
+ {
706
+ kind: "V",
707
+ n1: 4,
708
+ n2: 0,
709
+ value: b
710
+ },
711
+ {
712
+ kind: "M",
713
+ pmos: true,
714
+ n1: 2,
715
+ n2: 1,
716
+ n3: 3,
717
+ value: 0,
718
+ vth,
719
+ k: K
720
+ },
721
+ {
722
+ kind: "M",
723
+ pmos: true,
724
+ n1: 2,
725
+ n2: 1,
726
+ n3: 4,
727
+ value: 0,
728
+ vth,
729
+ k: K
730
+ },
731
+ {
732
+ kind: "M",
733
+ n1: 2,
734
+ n2: 5,
735
+ n3: 3,
736
+ value: 0,
737
+ vth,
738
+ k: K
739
+ },
740
+ {
741
+ kind: "M",
742
+ n1: 5,
743
+ n2: 0,
744
+ n3: 4,
745
+ value: 0,
746
+ vth,
747
+ k: K
748
+ }
749
+ ];
750
+ const Va = A ? vdd : 0, Vb = B ? vdd : 0;
751
+ const Y = solveDC(mk(Va, Vb)).nodeV[2] ?? 0;
752
+ const pA = vdd - Va > vth, pB = vdd - Vb > vth;
753
+ const nA = Va > vth, nB = Vb > vth;
754
+ const pullDown = nA && nB;
755
+ const yHi = Y > vdd / 2;
756
+ useFrameLoop((f) => setPhase((p) => (p + f.dtMs / 1e3 * .4) % 1), { running: (pA || pB || pullDown) && !reduce });
757
+ const VDD_Y = 30, GND_Y = 290, Y_Y = 145;
758
+ const PAt = 180, PBt = 300, Nt = 240, OUTx = 440;
759
+ const wire = (a, b) => [a, b];
760
+ const scene = /* @__PURE__ */ jsx("div", {
761
+ style: {
762
+ borderRadius: 12,
763
+ overflow: "hidden",
764
+ background: "var(--stage-bg)",
765
+ border: "1px solid var(--stage-grid)",
766
+ maxWidth: NAND_W,
767
+ margin: "0 auto"
768
+ },
769
+ children: /* @__PURE__ */ jsxs("svg", {
770
+ viewBox: `0 0 ${NAND_W} ${NAND_H}`,
771
+ width: "100%",
772
+ role: "img",
773
+ "aria-label": `CMOS NAND, A ${A}, B ${B}, output ${yHi ? "high" : "low"}`,
774
+ children: [
775
+ /* @__PURE__ */ jsx(Wire, {
776
+ points: [[120, VDD_Y], [360, VDD_Y]],
777
+ live: pA || pB
778
+ }),
779
+ /* @__PURE__ */ jsx(Wire, {
780
+ points: [[120, GND_Y], [360, GND_Y]],
781
+ live: pullDown
782
+ }),
783
+ /* @__PURE__ */ jsx(Wire, {
784
+ points: wire([PAt, VDD_Y], [PAt, 55]),
785
+ live: pA
786
+ }),
787
+ /* @__PURE__ */ jsx(Wire, {
788
+ points: wire([PAt, 115], [PAt, Y_Y]),
789
+ live: pA
790
+ }),
791
+ /* @__PURE__ */ jsx(Wire, {
792
+ points: wire([PBt, VDD_Y], [PBt, 55]),
793
+ live: pB
794
+ }),
795
+ /* @__PURE__ */ jsx(Wire, {
796
+ points: wire([PBt, 115], [PBt, Y_Y]),
797
+ live: pB
798
+ }),
799
+ /* @__PURE__ */ jsx(Wire, {
800
+ points: [[PAt, Y_Y], [OUTx, Y_Y]],
801
+ live: yHi
802
+ }),
803
+ /* @__PURE__ */ jsx(Wire, {
804
+ points: wire([Nt, Y_Y], [Nt, 160]),
805
+ live: pullDown
806
+ }),
807
+ /* @__PURE__ */ jsx(Wire, {
808
+ points: wire([Nt, 280], [Nt, GND_Y]),
809
+ live: pullDown
810
+ }),
811
+ pA && /* @__PURE__ */ jsx(FlowDots, {
812
+ points: [[PAt, VDD_Y], [PAt, Y_Y]],
813
+ phase
814
+ }),
815
+ pB && /* @__PURE__ */ jsx(FlowDots, {
816
+ points: [[PBt, VDD_Y], [PBt, Y_Y]],
817
+ phase
818
+ }),
819
+ pullDown && /* @__PURE__ */ jsx(FlowDots, {
820
+ points: [[Nt, Y_Y], [Nt, GND_Y]],
821
+ phase
822
+ }),
823
+ /* @__PURE__ */ jsx(MosfetGlyph, {
824
+ cx: PAt - 9,
825
+ cy: 85,
826
+ half: 30,
827
+ pmos: true,
828
+ on: pA,
829
+ live: pA,
830
+ label: "A"
831
+ }),
832
+ /* @__PURE__ */ jsx(MosfetGlyph, {
833
+ cx: PBt - 9,
834
+ cy: 85,
835
+ half: 30,
836
+ pmos: true,
837
+ on: pB,
838
+ live: pB,
839
+ label: "B"
840
+ }),
841
+ /* @__PURE__ */ jsx(MosfetGlyph, {
842
+ cx: Nt - 9,
843
+ cy: 190,
844
+ half: 30,
845
+ on: nA,
846
+ live: pullDown,
847
+ label: "A"
848
+ }),
849
+ /* @__PURE__ */ jsx(MosfetGlyph, {
850
+ cx: Nt - 9,
851
+ cy: 250,
852
+ half: 30,
853
+ on: nB,
854
+ live: pullDown,
855
+ label: "B"
856
+ }),
857
+ /* @__PURE__ */ jsx(Tag, {
858
+ x: 364,
859
+ y: 34,
860
+ text: `VDD ${vdd}V`,
861
+ color: "var(--stage-fg)",
862
+ size: 12,
863
+ weight: 700,
864
+ anchor: "start"
865
+ }),
866
+ /* @__PURE__ */ jsx(Tag, {
867
+ x: 364,
868
+ y: 294,
869
+ text: "GND",
870
+ color: "var(--stage-muted)",
871
+ size: 12,
872
+ weight: 700,
873
+ anchor: "start"
874
+ }),
875
+ /* @__PURE__ */ jsx(Tag, {
876
+ x: 92,
877
+ y: 66,
878
+ text: "PMOS pull-up",
879
+ color: "var(--stage-muted)",
880
+ size: 11,
881
+ weight: 700,
882
+ anchor: "start"
883
+ }),
884
+ /* @__PURE__ */ jsx(Tag, {
885
+ x: 92,
886
+ y: 222,
887
+ text: "NMOS pull-down",
888
+ color: "var(--stage-muted)",
889
+ size: 11,
890
+ weight: 700,
891
+ anchor: "start"
892
+ }),
893
+ /* @__PURE__ */ jsx("circle", {
894
+ cx: 444,
895
+ cy: Y_Y,
896
+ r: 4.5,
897
+ fill: yHi ? C_HI : C_LO
898
+ }),
899
+ /* @__PURE__ */ jsx(Tag, {
900
+ x: 452,
901
+ y: Y_Y - 8,
902
+ text: "Y",
903
+ color: "var(--stage-fg)",
904
+ size: 12,
905
+ weight: 700,
906
+ anchor: "start"
907
+ }),
908
+ /* @__PURE__ */ jsx(Tag, {
909
+ x: 452,
910
+ y: 156,
911
+ text: yHi ? "1" : "0",
912
+ color: yHi ? C_HI : C_LO,
913
+ size: 13,
914
+ weight: 800,
915
+ anchor: "start"
916
+ })
917
+ ]
918
+ })
919
+ });
920
+ return /* @__PURE__ */ jsx(LabFrame, {
921
+ title,
922
+ prompt,
923
+ controls: /* @__PURE__ */ jsxs(ControlBar, { children: [/* @__PURE__ */ jsx(Field, {
924
+ label: "input A",
925
+ children: /* @__PURE__ */ jsxs("span", {
926
+ className: "lab-field-row",
927
+ children: [/* @__PURE__ */ jsx(Chip, {
928
+ selected: A === 0,
929
+ onClick: () => setA(0),
930
+ children: "0"
931
+ }), /* @__PURE__ */ jsx(Chip, {
932
+ selected: A === 1,
933
+ onClick: () => setA(1),
934
+ children: "1"
935
+ })]
936
+ })
937
+ }), /* @__PURE__ */ jsx(Field, {
938
+ label: "input B",
939
+ children: /* @__PURE__ */ jsxs("span", {
940
+ className: "lab-field-row",
941
+ children: [/* @__PURE__ */ jsx(Chip, {
942
+ selected: B === 0,
943
+ onClick: () => setB(0),
944
+ children: "0"
945
+ }), /* @__PURE__ */ jsx(Chip, {
946
+ selected: B === 1,
947
+ onClick: () => setB(1),
948
+ children: "1"
949
+ })]
950
+ })
951
+ })] }),
952
+ aside: /* @__PURE__ */ jsxs("div", {
953
+ style: {
954
+ display: "flex",
955
+ flexDirection: "column",
956
+ gap: 10
957
+ },
958
+ children: [
959
+ /* @__PURE__ */ jsx("div", {
960
+ className: "lab-pill",
961
+ "data-state": (pA || pB) !== pullDown ? "ok" : "no",
962
+ role: "status",
963
+ style: { alignSelf: "flex-start" },
964
+ children: pullDown ? "✓ both inputs HIGH → NMOS pair pulls Y LOW" : "✓ a PMOS conducts → Y pulled HIGH"
965
+ }),
966
+ /* @__PURE__ */ jsxs(Callout, {
967
+ tone: "result",
968
+ children: [/* @__PURE__ */ jsxs("table", {
969
+ style: {
970
+ fontSize: 13,
971
+ fontVariantNumeric: "tabular-nums",
972
+ borderCollapse: "collapse"
973
+ },
974
+ children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
975
+ /* @__PURE__ */ jsx("th", {
976
+ style: {
977
+ textAlign: "left",
978
+ paddingRight: 14
979
+ },
980
+ children: "A"
981
+ }),
982
+ /* @__PURE__ */ jsx("th", {
983
+ style: {
984
+ textAlign: "left",
985
+ paddingRight: 14
986
+ },
987
+ children: "B"
988
+ }),
989
+ /* @__PURE__ */ jsx("th", {
990
+ style: { textAlign: "left" },
991
+ children: "Y"
992
+ })
993
+ ] }) }), /* @__PURE__ */ jsx("tbody", { children: [
994
+ [
995
+ 0,
996
+ 0,
997
+ 1
998
+ ],
999
+ [
1000
+ 0,
1001
+ 1,
1002
+ 1
1003
+ ],
1004
+ [
1005
+ 1,
1006
+ 0,
1007
+ 1
1008
+ ],
1009
+ [
1010
+ 1,
1011
+ 1,
1012
+ 0
1013
+ ]
1014
+ ].map(([a, b, y]) => /* @__PURE__ */ jsxs("tr", {
1015
+ style: {
1016
+ fontWeight: a === A && b === B ? 800 : 400,
1017
+ background: a === A && b === B ? "color-mix(in oklab, var(--stage-accent) 12%, transparent)" : void 0
1018
+ },
1019
+ children: [
1020
+ /* @__PURE__ */ jsx("td", { children: a }),
1021
+ /* @__PURE__ */ jsx("td", { children: b }),
1022
+ /* @__PURE__ */ jsx("td", {
1023
+ style: { color: y ? "var(--stage-good)" : "var(--stage-fg)" },
1024
+ children: y
1025
+ })
1026
+ ]
1027
+ }, `${a}${b}`)) })]
1028
+ }), /* @__PURE__ */ jsxs("div", {
1029
+ style: {
1030
+ marginTop: 6,
1031
+ color: "var(--stage-muted)",
1032
+ fontSize: 12
1033
+ },
1034
+ children: [
1035
+ "output = ",
1036
+ Y.toFixed(2),
1037
+ " V (",
1038
+ yHi ? "logic 1" : "logic 0",
1039
+ "), so Y = (A·B)′"
1040
+ ]
1041
+ })]
1042
+ }),
1043
+ /* @__PURE__ */ jsx(Callout, {
1044
+ tone: "info",
1045
+ children: /* @__PURE__ */ jsxs("div", {
1046
+ style: {
1047
+ fontSize: 12.5,
1048
+ lineHeight: 1.5
1049
+ },
1050
+ children: [/* @__PURE__ */ jsx("strong", { children: "NAND is universal." }), " Tie both inputs together → a NOT. A NAND then a NOT → AND. By De Morgan, NANDs make OR too. So these four transistors are the one building block every gate, and an entire CPU, is made from."]
1051
+ })
1052
+ })
1053
+ ]
1054
+ }),
1055
+ footer: /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(ChallengeCard, {
1056
+ questions: NAND_PREDICT_Q,
1057
+ state: ch,
1058
+ title: "Predict first"
1059
+ }), ask ? /* @__PURE__ */ jsx(LabAsk, {
1060
+ ask,
1061
+ activity
1062
+ }) : null] }),
1063
+ children: scene
1064
+ });
1065
+ }
1066
+ const NAND_PREDICT_Q = [{
1067
+ id: "nand-11",
1068
+ prompt: "Both inputs are HIGH (A = 1, B = 1). Both NMOS transistors turn on, completing the path to ground. What is the output Y?",
1069
+ choices: [{
1070
+ value: "0",
1071
+ label: "Y = 0 (LOW)"
1072
+ }, {
1073
+ value: "1",
1074
+ label: "Y = 1 (HIGH)"
1075
+ }],
1076
+ answer: "0",
1077
+ explain: "With both inputs HIGH the series NMOS pair conducts and pulls Y to ground (and both PMOS turn off). Y = 0 only when A AND B are 1, which is NAND = (A·B)′."
1078
+ }];
1079
+ const NOR_W = 480, NOR_H = 300;
1080
+ function CmosNorLab({ vdd = 5, vth = 2, title = "NOR: the De Morgan twin of NAND", prompt = "Toggle A and B. The networks are flipped from the NAND: a SERIES PMOS pair pulls the output HIGH only when BOTH inputs are LOW, and a PARALLEL NMOS pair pulls it LOW the moment EITHER input goes HIGH. NOR is the other universal gate.", ask, activity = "cmos-nor" } = {}) {
1081
+ const [A, setA] = useState(0);
1082
+ const [B, setB] = useState(0);
1083
+ const [phase, setPhase] = useState(0);
1084
+ const reduce = useReducedMotion();
1085
+ const ch = useChallenge(NOR_PREDICT_Q);
1086
+ useCheckpoint({
1087
+ solved: ch.allCorrect,
1088
+ activity: "cmos-nor:predict"
1089
+ });
1090
+ const mk = (a, b) => [
1091
+ {
1092
+ kind: "V",
1093
+ n1: 1,
1094
+ n2: 0,
1095
+ value: vdd
1096
+ },
1097
+ {
1098
+ kind: "V",
1099
+ n1: 3,
1100
+ n2: 0,
1101
+ value: a
1102
+ },
1103
+ {
1104
+ kind: "V",
1105
+ n1: 4,
1106
+ n2: 0,
1107
+ value: b
1108
+ },
1109
+ {
1110
+ kind: "M",
1111
+ pmos: true,
1112
+ n1: 5,
1113
+ n2: 1,
1114
+ n3: 3,
1115
+ value: 0,
1116
+ vth,
1117
+ k: K
1118
+ },
1119
+ {
1120
+ kind: "M",
1121
+ pmos: true,
1122
+ n1: 2,
1123
+ n2: 5,
1124
+ n3: 4,
1125
+ value: 0,
1126
+ vth,
1127
+ k: K
1128
+ },
1129
+ {
1130
+ kind: "M",
1131
+ n1: 2,
1132
+ n2: 0,
1133
+ n3: 3,
1134
+ value: 0,
1135
+ vth,
1136
+ k: K
1137
+ },
1138
+ {
1139
+ kind: "M",
1140
+ n1: 2,
1141
+ n2: 0,
1142
+ n3: 4,
1143
+ value: 0,
1144
+ vth,
1145
+ k: K
1146
+ }
1147
+ ];
1148
+ const Va = A ? vdd : 0, Vb = B ? vdd : 0;
1149
+ const Y = solveDC(mk(Va, Vb)).nodeV[2] ?? 0;
1150
+ const pA = vdd - Va > vth, pB = vdd - Vb > vth;
1151
+ const nA = Va > vth, nB = Vb > vth;
1152
+ const pullUp = pA && pB;
1153
+ const yHi = Y > vdd / 2;
1154
+ useFrameLoop((f) => setPhase((p) => (p + f.dtMs / 1e3 * .4) % 1), { running: (pullUp || nA || nB) && !reduce });
1155
+ const VDD_Y = 30, GND_Y = 290, Y_Y = 200;
1156
+ const Px = 240;
1157
+ const NAt = 180, NBt = 300, OUTx = 440;
1158
+ const wire = (a, b) => [a, b];
1159
+ const scene = /* @__PURE__ */ jsx("div", {
1160
+ style: {
1161
+ borderRadius: 12,
1162
+ overflow: "hidden",
1163
+ background: "var(--stage-bg)",
1164
+ border: "1px solid var(--stage-grid)",
1165
+ maxWidth: NOR_W,
1166
+ margin: "0 auto"
1167
+ },
1168
+ children: /* @__PURE__ */ jsxs("svg", {
1169
+ viewBox: `0 0 ${NOR_W} ${NOR_H}`,
1170
+ width: "100%",
1171
+ role: "img",
1172
+ "aria-label": `CMOS NOR, A ${A}, B ${B}, output ${yHi ? "high" : "low"}`,
1173
+ children: [
1174
+ /* @__PURE__ */ jsx(Wire, {
1175
+ points: [[120, VDD_Y], [360, VDD_Y]],
1176
+ live: pullUp
1177
+ }),
1178
+ /* @__PURE__ */ jsx(Wire, {
1179
+ points: [[120, GND_Y], [360, GND_Y]],
1180
+ live: nA || nB
1181
+ }),
1182
+ /* @__PURE__ */ jsx(Wire, {
1183
+ points: wire([Px, VDD_Y], [Px, 55]),
1184
+ live: pullUp
1185
+ }),
1186
+ /* @__PURE__ */ jsx(Wire, {
1187
+ points: wire([Px, 115], [Px, 119]),
1188
+ live: pullUp
1189
+ }),
1190
+ /* @__PURE__ */ jsx(Wire, {
1191
+ points: wire([Px, 179], [Px, Y_Y]),
1192
+ live: pullUp
1193
+ }),
1194
+ /* @__PURE__ */ jsx(Wire, {
1195
+ points: [[NAt, Y_Y], [OUTx, Y_Y]],
1196
+ live: yHi
1197
+ }),
1198
+ /* @__PURE__ */ jsx(Wire, {
1199
+ points: wire([NAt, Y_Y], [NAt, 210]),
1200
+ live: nA
1201
+ }),
1202
+ /* @__PURE__ */ jsx(Wire, {
1203
+ points: wire([NAt, 270], [NAt, GND_Y]),
1204
+ live: nA
1205
+ }),
1206
+ /* @__PURE__ */ jsx(Wire, {
1207
+ points: wire([NBt, Y_Y], [NBt, 210]),
1208
+ live: nB
1209
+ }),
1210
+ /* @__PURE__ */ jsx(Wire, {
1211
+ points: wire([NBt, 270], [NBt, GND_Y]),
1212
+ live: nB
1213
+ }),
1214
+ pullUp && /* @__PURE__ */ jsx(FlowDots, {
1215
+ points: [[Px, VDD_Y], [Px, Y_Y]],
1216
+ phase
1217
+ }),
1218
+ nA && /* @__PURE__ */ jsx(FlowDots, {
1219
+ points: [[NAt, Y_Y], [NAt, GND_Y]],
1220
+ phase
1221
+ }),
1222
+ nB && /* @__PURE__ */ jsx(FlowDots, {
1223
+ points: [[NBt, Y_Y], [NBt, GND_Y]],
1224
+ phase
1225
+ }),
1226
+ /* @__PURE__ */ jsx(MosfetGlyph, {
1227
+ cx: Px - 9,
1228
+ cy: 85,
1229
+ half: 30,
1230
+ pmos: true,
1231
+ on: pA,
1232
+ live: pullUp,
1233
+ label: "A"
1234
+ }),
1235
+ /* @__PURE__ */ jsx(MosfetGlyph, {
1236
+ cx: Px - 9,
1237
+ cy: 149,
1238
+ half: 30,
1239
+ pmos: true,
1240
+ on: pB,
1241
+ live: pullUp,
1242
+ label: "B"
1243
+ }),
1244
+ /* @__PURE__ */ jsx(MosfetGlyph, {
1245
+ cx: NAt - 9,
1246
+ cy: 240,
1247
+ half: 30,
1248
+ on: nA,
1249
+ live: nA,
1250
+ label: "A"
1251
+ }),
1252
+ /* @__PURE__ */ jsx(MosfetGlyph, {
1253
+ cx: NBt - 9,
1254
+ cy: 240,
1255
+ half: 30,
1256
+ on: nB,
1257
+ live: nB,
1258
+ label: "B"
1259
+ }),
1260
+ /* @__PURE__ */ jsx(Tag, {
1261
+ x: 364,
1262
+ y: 34,
1263
+ text: `VDD ${vdd}V`,
1264
+ color: "var(--stage-fg)",
1265
+ size: 12,
1266
+ weight: 700,
1267
+ anchor: "start"
1268
+ }),
1269
+ /* @__PURE__ */ jsx(Tag, {
1270
+ x: 364,
1271
+ y: 294,
1272
+ text: "GND",
1273
+ color: "var(--stage-muted)",
1274
+ size: 12,
1275
+ weight: 700,
1276
+ anchor: "start"
1277
+ }),
1278
+ /* @__PURE__ */ jsx(Tag, {
1279
+ x: 92,
1280
+ y: 118,
1281
+ text: "PMOS pull-up",
1282
+ color: "var(--stage-muted)",
1283
+ size: 11,
1284
+ weight: 700,
1285
+ anchor: "start"
1286
+ }),
1287
+ /* @__PURE__ */ jsx(Tag, {
1288
+ x: 92,
1289
+ y: 244,
1290
+ text: "NMOS pull-down",
1291
+ color: "var(--stage-muted)",
1292
+ size: 11,
1293
+ weight: 700,
1294
+ anchor: "start"
1295
+ }),
1296
+ /* @__PURE__ */ jsx("circle", {
1297
+ cx: 444,
1298
+ cy: Y_Y,
1299
+ r: 4.5,
1300
+ fill: yHi ? C_HI : C_LO
1301
+ }),
1302
+ /* @__PURE__ */ jsx(Tag, {
1303
+ x: 452,
1304
+ y: Y_Y - 8,
1305
+ text: "Y",
1306
+ color: "var(--stage-fg)",
1307
+ size: 12,
1308
+ weight: 700,
1309
+ anchor: "start"
1310
+ }),
1311
+ /* @__PURE__ */ jsx(Tag, {
1312
+ x: 452,
1313
+ y: 211,
1314
+ text: yHi ? "1" : "0",
1315
+ color: yHi ? C_HI : C_LO,
1316
+ size: 13,
1317
+ weight: 800,
1318
+ anchor: "start"
1319
+ })
1320
+ ]
1321
+ })
1322
+ });
1323
+ return /* @__PURE__ */ jsx(LabFrame, {
1324
+ title,
1325
+ prompt,
1326
+ controls: /* @__PURE__ */ jsxs(ControlBar, { children: [/* @__PURE__ */ jsx(Field, {
1327
+ label: "input A",
1328
+ children: /* @__PURE__ */ jsxs("span", {
1329
+ className: "lab-field-row",
1330
+ children: [/* @__PURE__ */ jsx(Chip, {
1331
+ selected: A === 0,
1332
+ onClick: () => setA(0),
1333
+ children: "0"
1334
+ }), /* @__PURE__ */ jsx(Chip, {
1335
+ selected: A === 1,
1336
+ onClick: () => setA(1),
1337
+ children: "1"
1338
+ })]
1339
+ })
1340
+ }), /* @__PURE__ */ jsx(Field, {
1341
+ label: "input B",
1342
+ children: /* @__PURE__ */ jsxs("span", {
1343
+ className: "lab-field-row",
1344
+ children: [/* @__PURE__ */ jsx(Chip, {
1345
+ selected: B === 0,
1346
+ onClick: () => setB(0),
1347
+ children: "0"
1348
+ }), /* @__PURE__ */ jsx(Chip, {
1349
+ selected: B === 1,
1350
+ onClick: () => setB(1),
1351
+ children: "1"
1352
+ })]
1353
+ })
1354
+ })] }),
1355
+ aside: /* @__PURE__ */ jsxs("div", {
1356
+ style: {
1357
+ display: "flex",
1358
+ flexDirection: "column",
1359
+ gap: 10
1360
+ },
1361
+ children: [
1362
+ /* @__PURE__ */ jsx("div", {
1363
+ className: "lab-pill",
1364
+ "data-state": pullUp !== (nA || nB) ? "ok" : "no",
1365
+ role: "status",
1366
+ style: { alignSelf: "flex-start" },
1367
+ children: pullUp ? "✓ both inputs LOW → series PMOS pulls Y HIGH" : "✓ an NMOS conducts → Y pulled LOW"
1368
+ }),
1369
+ /* @__PURE__ */ jsxs(Callout, {
1370
+ tone: "result",
1371
+ children: [/* @__PURE__ */ jsxs("table", {
1372
+ style: {
1373
+ fontSize: 13,
1374
+ fontVariantNumeric: "tabular-nums",
1375
+ borderCollapse: "collapse"
1376
+ },
1377
+ children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
1378
+ /* @__PURE__ */ jsx("th", {
1379
+ style: {
1380
+ textAlign: "left",
1381
+ paddingRight: 14
1382
+ },
1383
+ children: "A"
1384
+ }),
1385
+ /* @__PURE__ */ jsx("th", {
1386
+ style: {
1387
+ textAlign: "left",
1388
+ paddingRight: 14
1389
+ },
1390
+ children: "B"
1391
+ }),
1392
+ /* @__PURE__ */ jsx("th", {
1393
+ style: { textAlign: "left" },
1394
+ children: "Y"
1395
+ })
1396
+ ] }) }), /* @__PURE__ */ jsx("tbody", { children: [
1397
+ [
1398
+ 0,
1399
+ 0,
1400
+ 1
1401
+ ],
1402
+ [
1403
+ 0,
1404
+ 1,
1405
+ 0
1406
+ ],
1407
+ [
1408
+ 1,
1409
+ 0,
1410
+ 0
1411
+ ],
1412
+ [
1413
+ 1,
1414
+ 1,
1415
+ 0
1416
+ ]
1417
+ ].map(([a, b, y]) => /* @__PURE__ */ jsxs("tr", {
1418
+ style: {
1419
+ fontWeight: a === A && b === B ? 800 : 400,
1420
+ background: a === A && b === B ? "color-mix(in oklab, var(--stage-accent) 12%, transparent)" : void 0
1421
+ },
1422
+ children: [
1423
+ /* @__PURE__ */ jsx("td", { children: a }),
1424
+ /* @__PURE__ */ jsx("td", { children: b }),
1425
+ /* @__PURE__ */ jsx("td", {
1426
+ style: { color: y ? "var(--stage-good)" : "var(--stage-fg)" },
1427
+ children: y
1428
+ })
1429
+ ]
1430
+ }, `${a}${b}`)) })]
1431
+ }), /* @__PURE__ */ jsxs("div", {
1432
+ style: {
1433
+ marginTop: 6,
1434
+ color: "var(--stage-muted)",
1435
+ fontSize: 12
1436
+ },
1437
+ children: [
1438
+ "output = ",
1439
+ Y.toFixed(2),
1440
+ " V (",
1441
+ yHi ? "logic 1" : "logic 0",
1442
+ "), so Y = (A + B)′"
1443
+ ]
1444
+ })]
1445
+ }),
1446
+ /* @__PURE__ */ jsx(Callout, {
1447
+ tone: "info",
1448
+ children: /* @__PURE__ */ jsxs("div", {
1449
+ style: {
1450
+ fontSize: 12.5,
1451
+ lineHeight: 1.5
1452
+ },
1453
+ children: [/* @__PURE__ */ jsx("strong", { children: "NOR is universal too." }), " Compare with the NAND: swapping series for parallel in each network turns AND-logic into OR-logic (De Morgan in silicon). NAND and NOR are the two single bricks any digital circuit, from a gate to a CPU, can be built from."]
1454
+ })
1455
+ })
1456
+ ]
1457
+ }),
1458
+ footer: /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(ChallengeCard, {
1459
+ questions: NOR_PREDICT_Q,
1460
+ state: ch,
1461
+ title: "Predict first"
1462
+ }), ask ? /* @__PURE__ */ jsx(LabAsk, {
1463
+ ask,
1464
+ activity
1465
+ }) : null] }),
1466
+ children: scene
1467
+ });
1468
+ }
1469
+ const NOR_PREDICT_Q = [{
1470
+ id: "nor-00",
1471
+ prompt: "A NOR outputs HIGH for exactly one input combination. Which one?",
1472
+ choices: [
1473
+ {
1474
+ value: "a",
1475
+ label: "both LOW: A = 0, B = 0"
1476
+ },
1477
+ {
1478
+ value: "b",
1479
+ label: "both HIGH: A = 1, B = 1"
1480
+ },
1481
+ {
1482
+ value: "c",
1483
+ label: "whenever the inputs differ"
1484
+ }
1485
+ ],
1486
+ answer: "a",
1487
+ explain: "Only when both inputs are LOW do both series PMOS conduct (and both parallel NMOS stay off), pulling Y HIGH. Any HIGH input opens an NMOS to ground, so Y = (A + B)′."
1488
+ }];
1489
+
1490
+ //#endregion
1491
+ export { CmosInverterLab, CmosNandLab, CmosNorLab, RNmosNotLab };