Each plant's photosynthetic capacity is the product of four independent 0–1 stress factors, the same multiplicative-limitation approach used in crop models like DSSAT/APSIM — no single "growth slider" fakes the outcome:
f_light = I / (I + Ik) Ik = 220 µmol/m²/s (rectangular hyperbola)
f_co2 = C / (C + Kc) Kc = 350 ppm (Michaelis-Menten, C3 pathway)
f_temp = exp(-(T-24)² / 128) Gaussian response, optimum 24°C
f_nutr = EC / (EC + Kn) Kn = 0.9 mS/cm
growth = Gmax · f_light · f_co2 · f_temp · f_nutr · B · (1 - B/Bmax)
Biomass follows logistic growth gated by that combined factor, so growth saturates near canopy capacity instead of exploding. The limiting-factor readout reports whichever of the four terms is currently smallest — drag light, CO₂ or nutrient EC down far enough and watch that label switch.
The habitat atmosphere is a real coupled balance, not decoration: net canopy photosynthesis pulls CO₂ down and pushes O₂ up (stoichiometric 1:1 gas exchange scaled by canopy area), while the crew slider adds a constant CO₂ production / O₂ consumption load. The CO₂ injector nudges the cabin toward your setpoint at a finite rate, so a large crew or a starved canopy can still drive CO₂ and O₂ away from safe range — the "O₂ self-sufficiency" readout is the fraction of crew O₂ demand the canopy is currently replacing.
- Canopy grid — each cell's fill and colour track that plant's own biomass fraction of capacity.
- Strip chart — biomass (green) and O₂ self-sufficiency (blue) traced over mission days.
- Harvest — cuts the canopy back to 15% of capacity and banks the removed mass as yield.