diff --git a/devTools/types/FC/mods.d.ts b/devTools/types/FC/mods.d.ts
index 093b1317a64add79242937b2b36aca1a32c3f595..9d477f878a3efc8e0cd097fa40cdb66c5a56c932 100644
--- a/devTools/types/FC/mods.d.ts
+++ b/devTools/types/FC/mods.d.ts
@@ -1,46 +1,48 @@
-declare namespace FC {
-	namespace Mods {
-		/** The base mod interface, from which all mod interfaces inherit. */
-		interface Base {
-			/** Whether the mod is enabled. */
-			enabled: boolean;
-		}
-
-		/** Properties relating to the food system mod. */
-		interface Food extends Base {
-			/** How much food the arcology has, in kg. */
-			amount: number;
-			/** The base price of 1kg of food. */
-			cost: number;
-			/** How much food the arcology had at the end of last week, in kg. */
-			lastWeek: number;
-			/** Whether the food market has been established. */
-			market: boolean;
-			/** The amount of food produced this week, in kg. */
-			produced: number;
-			/** The amount of food each class consumes in a week. */
-			rate: {
-				/** The amount of food a slave consumes in a week, in kg. */
-				slave: 8,
-				/** The amount of food the lower class consumes in a week, in kg. */
-				lower: 14.5,
-				/** The amount of food the middle class consumes in a week, in kg. */
-				middle: 16,
-				/** The amount of food the upper class consumes in a week, in kg. */
-				upper: 17.5,
-				/** The amount of food the elite class consumes in a week, in kg. */
-				top: 19,
-			},
-			/**
-			 * How much food you are providing your citizens weekly.
-			 *
-			 * Not in kg.
-			 */
-			rations: 0 | 1 | 2 | 3 | 4 | 5;
-			/** How much food the arcology has produced in total, in kg. */
-			total: number;
-			/** Whether the player has received a warning about a lack of food. */
-			warned: boolean;
-		}
-	}
-}
+declare namespace FC {
+	namespace Mods {
+		/** The base mod interface, from which all mod interfaces inherit. */
+		interface Base {
+			/** Whether the mod is enabled. */
+			enabled: boolean;
+		}
+
+		/** Properties relating to the food system mod. */
+		interface Food extends Base {
+			/** How much food the arcology has, in kg. */
+			amount: number;
+			/** The base price of 1kg of food. */
+			cost: number;
+			/** How much food the arcology had at the end of last week, in kg. */
+			lastWeek: number;
+			/** Whether the food market has been established. */
+			market: boolean;
+			/** The amount of food that needed to be bought this week to to stop people from starving */
+			deficit: number,
+			/** The amount of food that had to be sold this week because there was not enough storage space */
+			overstocked: number,
+			/** The amount of food each class consumes in a week. */
+			rate: {
+				/** The amount of food a slave consumes in a week, in kg. */
+				slave: 8,
+				/** The amount of food the lower class consumes in a week, in kg. */
+				lower: 14.5,
+				/** The amount of food the middle class consumes in a week, in kg. */
+				middle: 16,
+				/** The amount of food the upper class consumes in a week, in kg. */
+				upper: 17.5,
+				/** The amount of food the elite class consumes in a week, in kg. */
+				top: 19,
+			},
+			/**
+			 * How much food you are providing your citizens weekly.
+			 *
+			 * Not in kg.
+			 */
+			rations: 0 | 1 | 2 | 3 | 4 | 5;
+			/** How much food the arcology has produced in total, in kg. */
+			total: number;
+			/** Whether the player has received a warning about a lack of food. */
+			warned: boolean;
+		}
+	}
+}
diff --git a/js/003-data/gameVariableData.js b/js/003-data/gameVariableData.js
index 85898008382ce7d78e0ec447fa50d20183f7d4de..fc390fb52f12b4640bdc172a143a4a927d6b5f15 100644
--- a/js/003-data/gameVariableData.js
+++ b/js/003-data/gameVariableData.js
@@ -364,9 +364,10 @@ App.Data.defaultGameStateVariables = {
 
 			amount: 125000,
 			cost: 25,
-			lastWeek: 0,
+			lastWeek: 125000,
 			market: false,
-			produced: 0,
+			deficit: 0,
+			overstocked: 0,
 			rate: {
 				slave: 8,
 				lower: 14.5,
@@ -812,6 +813,8 @@ App.Data.resetOnNGPlus = {
 		hydroponics: 0,
 		machinery: 0,
 		seeds: 0,
+		/** available food storage in tons */
+		foodStorage: 150,
 	},
 	farmyardCrops: 0,
 	farmyardStables: 0,
diff --git a/src/arcologyBuilding/ManageArcology.js b/src/arcologyBuilding/ManageArcology.js
index a55cbfe253345fb67623040bed9784e092baf0d1..42843ed1a28b3cc6f983982107e2ed5da4aa772f 100644
--- a/src/arcologyBuilding/ManageArcology.js
+++ b/src/arcologyBuilding/ManageArcology.js
@@ -611,7 +611,7 @@ App.UI.manageArcology = function() {
 
 		if (V.mods.food.enabled && V.mods.food.market) {
 			App.UI.DOM.appendNewElement("h2", div, "Food Management");
-			div.append(App.UI.foodMarket());
+			div.append(App.UI.foodMarket.main());
 		} else if (V.eventResults.foodCrisis && !V.mods.food.rations) {
 			const price = V.PC.skill.trading >= 50 && ["capitalist", "entrepreneur", "business kid"].includes(V.PC.career) || V.PC.skill.trading >= 100 ? 112_500 : 150_000;
 
diff --git a/src/data/backwardsCompatibility/farmyardBC.js b/src/data/backwardsCompatibility/farmyardBC.js
index ff48d37a05d4a4e438d152ee89c8a2e815adac13..cf4bdf66ed5542466aa4adc4876cc95bde6add93 100644
--- a/src/data/backwardsCompatibility/farmyardBC.js
+++ b/src/data/backwardsCompatibility/farmyardBC.js
@@ -6,6 +6,10 @@ App.Facilities.Farmyard.BC = function() {
 		};
 	}
 
+	V.farmyardUpgrades.foodStorage = V.farmyardUpgrades.foodStorage ?? (V.mods.food.amount > 0)
+		? Math.trunc(V.mods.food.amount / 1000) + 50 // old saves get enough storage to hold all their food plus a buffer
+		: 150;
+
 	if (App.Data.Animals.size === 0) {
 		App.Facilities.Farmyard.animals.init();
 	}
@@ -16,6 +20,9 @@ App.Facilities.Farmyard.BC = function() {
 		delete V.foodStored;
 	}
 
+	V.mods.food.deficit = V.mods.food.deficit ?? 0;
+	V.mods.food.overstocked = V.mods.food.overstocked ?? 0;
+
 	if (V.canine) {
 		V.animals.canine = Array.from(V.canine);
 
diff --git a/src/data/backwardsCompatibility/modsBC.js b/src/data/backwardsCompatibility/modsBC.js
index d536a0f680db20dcb3148e9e6c3b0708a76185bf..2f8ce80a13ca051626c586f145565a903c9897e0 100644
--- a/src/data/backwardsCompatibility/modsBC.js
+++ b/src/data/backwardsCompatibility/modsBC.js
@@ -9,7 +9,6 @@ App.Update.mods = function(node) {
 			amount: "food",
 			lastWeek: "foodLastWeek",
 			market: "foodMarket",
-			produced: "foodProduced",
 			rate: "foodRate",
 			rations: "foodRations",
 			total: "foodTotal",
diff --git a/src/data/newGamePlus.js b/src/data/newGamePlus.js
index 2a677ac110f5ad0948b17db06e2d0aff678abe15..ea1cb7a996569a93fdc3ad5ce096af3c424f2a1f 100644
--- a/src/data/newGamePlus.js
+++ b/src/data/newGamePlus.js
@@ -232,15 +232,12 @@ App.Data.NewGamePlus = (function() {
 	}
 
 	function updateMods() {
-		if (V.mods.food.enabled) {
-			V.mods.food.amount = 0;
-			V.mods.food.lastWeek = 0;
-			V.mods.food.market = false;
-			V.mods.food.produced = 0;
-			V.mods.food.rations = 0;
-			V.mods.food.total = 0;
-			V.mods.food.warned = false;
-		}
+		V.mods.food.amount = 0;
+		V.mods.food.lastWeek = 0;
+		V.mods.food.market = false;
+		V.mods.food.rations = 0;
+		V.mods.food.total = 0;
+		V.mods.food.warned = false;
 	}
 
 	function doNGPSetup() {
diff --git a/src/endWeek/economics/arcmgmt.js b/src/endWeek/economics/arcmgmt.js
index fef8be08a884c1d9d7c7d8dba98ab4d6b22c5314..f57fb35e284a248ae60ee31065662f404f3c8d6b 100644
--- a/src/endWeek/economics/arcmgmt.js
+++ b/src/endWeek/economics/arcmgmt.js
@@ -722,12 +722,7 @@ App.EndWeek.arcManagement = function() {
 		r = [];
 	}
 
-	const food = document.createElement("span");
-	food.id = "food";
-	if (V.mods.food.enabled && V.mods.food.market) {
-		food.append(App.UI.foodReport());
-	}
-	el.append(food);
+	App.Events.addParagraph(el, [App.UI.foodReport()]);
 
 	App.Events.addNode(el, r);
 	return el;
diff --git a/src/endWeek/economics/economics.js b/src/endWeek/economics/economics.js
index 6a8a3fffcc4481b0169e21004c66d2f1cdb957a6..4245c2cca3cf9d5a9141b14719a8b453bc35d878 100644
--- a/src/endWeek/economics/economics.js
+++ b/src/endWeek/economics/economics.js
@@ -5,9 +5,13 @@ App.EndWeek.economics = function() {
 	if (V.cash > -10000) {
 		V.debtWarned = 0;
 	}
-	if (V.mods.food.enabled && V.mods.food.market &&
-		(V.mods.food.amount > App.Facilities.Farmyard.foodConsumption() ||
-		V.cash > App.Facilities.Farmyard.foodConsumption() * V.mods.food.cost)) {
+	if (
+		V.mods.food.enabled && V.mods.food.market &&
+		(
+			App.Facilities.Farmyard.foodAvailable() > App.Facilities.Farmyard.foodConsumption() ||
+			V.cash > App.Facilities.Farmyard.foodBuyCost(App.Facilities.Farmyard.foodConsumption())
+		)
+	) {
 		V.mods.food.warned = false;
 	}
 
diff --git a/src/endWeek/economics/persBusiness.js b/src/endWeek/economics/persBusiness.js
index 66d0f8dbdf48ef0ef137f60f832300bf2a972a40..615b6ce3c341947081d07a3d57e663b914ef9a76 100644
--- a/src/endWeek/economics/persBusiness.js
+++ b/src/endWeek/economics/persBusiness.js
@@ -49,9 +49,9 @@ App.EndWeek.personalBusiness = function() {
 		}
 	}
 	if (V.mods.food.enabled && V.mods.food.market) {
-		if (V.mods.food.amount < App.Facilities.Farmyard.foodConsumption() && V.cash < (App.Facilities.Farmyard.foodConsumption() * V.mods.food.cost)) {
+		if (App.Facilities.Farmyard.foodAvailable() < App.Facilities.Farmyard.foodConsumption() && V.cash < App.Facilities.Farmyard.foodBuyCost(App.Facilities.Farmyard.foodConsumption())) {
 			r.push(`<span class="red">WARNING: your arcology will starve in the coming week unless action is taken.</span>`);
-			if (V.mods.food.warned) {
+			if (V.mods.food.warned === true) {
 				V.gameover = "starving citizens";
 				V.nextLink = "Gameover";
 			} else {
@@ -256,12 +256,16 @@ App.EndWeek.personalBusiness = function() {
 		}
 	}
 	if (V.mods.food.enabled && V.mods.food.market) {
-		if (V.mods.food.amount < App.Facilities.Farmyard.foodConsumption()) {
-			const foodCost = (App.Facilities.Farmyard.foodConsumption() - V.mods.food.amount) * V.mods.food.cost;
-			r.push(`You also spent ${cashFormat(Math.trunc(foodCost))} this week buying enough food to keep your citizens fed, as you promised.`);
-			cashX(forceNeg(foodCost), "food");
+		if (V.mods.food.deficit > 0) {
+			const foodCost = App.Facilities.Farmyard.foodBuyCost(V.mods.food.deficit);
+			r.push(`You also spent <span class="red">${cashFormat(Math.trunc(foodCost))}</span> this week buying enough food to keep your citizens fed, as you promised.`);
 		}
-		V.mods.food.amount -= App.Facilities.Farmyard.foodConsumption();
+		// actual food purchasing and consumption happens in endWeek().food()
+	}
+	if (V.mods.food.overstocked > 0) {
+		const foodvalue = App.Facilities.Farmyard.foodSellValue(V.mods.food.overstocked);
+		r.push(`You did not have enough storage for all of the food you produced this week, so ${massFormat(V.mods.food.overstocked)} were sold for <span class="yellowgreen">${cashFormat(Math.trunc(foodvalue))}</span>`);
+		// The actual selling happens in endWeek().food()
 	}
 	App.Events.addParagraph(el, r);
 	r = [];
diff --git a/src/endWeek/endWeek.js b/src/endWeek/endWeek.js
index 22f8e463847ec69e720a1378bf8c5e60f9914a5c..d2beca55eb40be52277ba4c508caedc14e5b722d 100644
--- a/src/endWeek/endWeek.js
+++ b/src/endWeek/endWeek.js
@@ -92,7 +92,7 @@ globalThis.endWeek = (function() {
 	function saveWeekTotals() {
 		V.cashLastWeek = V.cash;
 		V.repLastWeek = V.rep;
-		V.mods.food.lastWeek = V.mods.food.amount;
+		V.mods.food.lastWeek = App.Facilities.Farmyard.foodAvailable();
 	}
 
 	function weather() {
@@ -175,11 +175,25 @@ globalThis.endWeek = (function() {
 	}
 
 	function food() {
-		if (V.mods.food.enabled && V.mods.food.market) {
-			const foodAmount = App.Facilities.Farmyard.foodProduction();
-			V.mods.food.amount += foodAmount;
-			V.mods.food.produced += foodAmount;
-			V.mods.food.total += foodAmount;
+		// produce food
+		App.Facilities.Farmyard.foodAdd(App.Facilities.Farmyard.foodProduction());
+		if (V.mods.food.enabled && V.eventResults.foodCrisis) {
+			// buy food if there is a deficit
+			const deficit = App.Facilities.Farmyard.foodConsumption() - App.Facilities.Farmyard.foodAvailable();
+			V.mods.food.deficit = Math.max(0, deficit);
+			if (deficit > 0 && V.cash > App.Facilities.Farmyard.foodBuyCost(V.mods.food.deficit)) {
+				App.Facilities.Farmyard.foodBuy(deficit);
+			}
+			// consume food
+			App.Facilities.Farmyard.foodRemove(App.Facilities.Farmyard.foodConsumption());
+		} else {
+			V.mods.food.deficit = 0;
+		}
+		// sell excess food if there is not enough storage
+		const overstocked = -App.Facilities.Farmyard.foodStorageAvailable();
+		V.mods.food.overstocked = Math.max(0, overstocked);
+		if (overstocked > 0) {
+			App.Facilities.Farmyard.foodSell(overstocked);
 		}
 	}
 
diff --git a/src/endWeek/nextWeek/nextWeek.js b/src/endWeek/nextWeek/nextWeek.js
index 8803e85fa2420b72418a79fcee82ab7a01a9ea12..3c314e87883fb4223b2d8e485a522d3c0c35b634 100644
--- a/src/endWeek/nextWeek/nextWeek.js
+++ b/src/endWeek/nextWeek/nextWeek.js
@@ -147,16 +147,13 @@ App.EndWeek.nextWeek = function() {
 			V.localEcon = 20;
 		}
 
-		if (V.mods.food.enabled && V.mods.food.market) {
-			if (V.localEcon > 100) {
-				V.mods.food.cost = Math.max(5 / (1 + (Math.trunc(1000 - 100000 / V.localEcon) / 10) / 100), 3.125);
-			} else if (V.localEcon === 100) {
-				V.mods.food.cost = 5;
-			} else {
-				V.mods.food.cost = Math.min(5 * (1 + 1.5 * Math.sqrt(Math.trunc(100000 / V.localEcon - 1000) / 10) / 100), 6.5);
-			}
+		if (V.localEcon > 100) {
+			V.mods.food.cost = Math.max(5 / (1 + (Math.trunc(1000 - 100000 / V.localEcon) / 10) / 100), 3.125);
+		} else if (V.localEcon === 100) {
+			V.mods.food.cost = 5;
+		} else {
+			V.mods.food.cost = Math.min(5 * (1 + 1.5 * Math.sqrt(Math.trunc(100000 / V.localEcon - 1000) / 10) / 100), 6.5);
 		}
-		V.mods.food.cost = Math.trunc(2500 / V.localEcon);
 		V.drugsCost = Math.trunc(10000 / V.localEcon);
 		if (V.dispensaryUpgrade) {
 			V.drugsCost *= 0.5;
diff --git a/src/endWeek/reports/farmyardReport.js b/src/endWeek/reports/farmyardReport.js
index 762581e593347c4c705e8d36c4cd01949e419aff..c26932624228936cb48d7cd3f0ea8e369921d770 100644
--- a/src/endWeek/reports/farmyardReport.js
+++ b/src/endWeek/reports/farmyardReport.js
@@ -26,8 +26,6 @@ App.EndWeek.farmyardReport = function farmyardReport() {
 
 	text.toParagraph();
 
-	// V.mods.food.amount += food; // food amount is changed in endWeek().food()
-
 	if (slaves) {
 		const intro = App.UI.DOM.appendNewElement("p", beforeFrag, null, ["indent"]);
 
@@ -511,16 +509,16 @@ App.EndWeek.farmyardReport = function farmyardReport() {
 			if (profits) {
 				text.push(`makes you <span class="cash">${cashFormat(Math.trunc(profits))}</span>`);
 			}
-
-			if (V.mods.food.market) {
-				if (profits && food) {
-					text.push(`and`);
-				}
-				if (food) {
-					text.push(`produced <span class="chocolate"> ${massFormat(food)}</span> of food`);
+			if (profits && food) {
+				text.push(`and`);
+			}
+			text.push(`produced <span class="chocolate"> ${massFormat(food)}</span> of food this week.`);
+			if (food) {
+				if (V.mods.food.overstocked > 0) {
+					text.push(text.pop().replace(".", ","));
+					text.push(`of which <span class="chocolate"> ${massFormat(V.mods.food.overstocked)}</span> were sold due to lack of storage space.`);
 				}
 			}
-			text.push(`this week.`);
 		}
 
 		return text.join(' ');
@@ -530,7 +528,11 @@ App.EndWeek.farmyardReport = function farmyardReport() {
 		let total = 0;
 
 		for (const slave of slaves) {
-			total += farmhandProfit(slave);
+			total += farmhandProfit(slave); // TODO: these values do not match the values from App.Facilities.Farmyard.Stats()
+		}
+
+		if (V.mods.food.overstocked > 0) {
+			total += App.Facilities.Farmyard.foodSellValue(V.mods.food.overstocked);
 		}
 
 		return total;
diff --git a/src/endWeek/saWorkTheFarm.js b/src/endWeek/saWorkTheFarm.js
index a23ae36411877f326d3692ebf09840ed0c047457..c1de9b888afdf7f8f4af29c74eefa305513ea45c 100644
--- a/src/endWeek/saWorkTheFarm.js
+++ b/src/endWeek/saWorkTheFarm.js
@@ -44,13 +44,10 @@ App.SlaveAssignment.workTheFarm = function(slave) {
 	}
 
 	function food() {
-		if (V.mods.food.market && V.farmyardShows < 2) {
+		if (V.farmyardShows < 2) {
 			const fsGain = 0.0001 * foodAmount;
 
 			FutureSocieties.DecorationBonus(V.farmyardDecoration, fsGain);
-			// V.mods.food.amount += foodAmount;  // food amount is changed in endWeek().food()
-			// V.mods.food.produced += foodAmount;  // food amount is changed in endWeek().food()
-			// V.mods.food.total += foodAmount;  // food amount is changed in endWeek().food()
 			incomeStats.food += foodAmount;
 
 			if (V.farmyardShows !== 2) {
diff --git a/src/events/intro/introSummary.js b/src/events/intro/introSummary.js
index de9b46f9bb673387394234671e040545776df9d1..25c35a6783b7f56f272bae422d8d494bd0701661 100644
--- a/src/events/intro/introSummary.js
+++ b/src/events/intro/introSummary.js
@@ -328,6 +328,10 @@ App.Intro.summary = function() {
 			.addValue("Enabled", 1).on().addValue("Disabled", 0).off();
 		options.addComment(`This mod allows you to start your own lategame bioengineering project, focused around creating functional catgirls for recreational purposes. The ultimate dream of any anime-addicted billionaire. After enabling, bioengineering must be manually activated from the genelab through expensive upgrades to see any of the mod's content.`);
 
+		options.addOption("The food mod is", "enabled", V.mods.food)
+			.addValue("Enabled", true).on().addValue("Disabled", false).off();
+		options.addComment("This mod will enable food supply and demand. This mod can be activated/deactivated at any time.");
+
 		el.append(options.render());
 		return el;
 	}
diff --git a/src/facilities/farmyard/farmyard.js b/src/facilities/farmyard/farmyard.js
index 0cd469ec6666574a686d7fcd67e52fdcd757c572..3f9f911ee25d9362af9b8166a3679a28f32ea1ed 100644
--- a/src/facilities/farmyard/farmyard.js
+++ b/src/facilities/farmyard/farmyard.js
@@ -31,7 +31,8 @@ App.Facilities.Farmyard.farmyard = class Farmyard extends App.Facilities.Facilit
 				fertilizer: 0,
 				hydroponics: 0,
 				machinery: 0,
-				seeds: 0
+				seeds: 0,
+				foodStorage: 150,
 			};
 
 			V.animals = {
@@ -734,10 +735,29 @@ App.Facilities.Farmyard.farmyard = class Farmyard extends App.Facilities.Facilit
 		}
 	}
 
+	/** @returns {DocumentFragment} */
+	get foodStorage() {
+		const frag = new DocumentFragment();
+
+		App.UI.DOM.appendNewElement("h2", frag, `Food Storage`);
+
+		frag.append(
+			App.UI.foodMarket.foodStorageDescription(),
+			App.UI.foodMarket.foodStorageUpgrades(),
+		);
+		if (V.mods.food.enabled && V.mods.food.market) {
+			frag.append(App.UI.foodMarket.buyLinks());
+		}
+		frag.append(App.UI.foodMarket.sellLinks());
+
+		return frag;
+	}
+
 	/** @returns {DocumentFragment[]} */
 	get customNodes() {
 		return [
 			this.animals,
+			this.foodStorage,
 		];
 	}
 };
diff --git a/src/facilities/farmyard/food/food.js b/src/facilities/farmyard/food/food.js
index a6cef721233d7196a88f3a5071cc8838e1362995..970846d5e3f300893ff1e5d1b8ac3a75bb66c5d8 100644
--- a/src/facilities/farmyard/food/food.js
+++ b/src/facilities/farmyard/food/food.js
@@ -175,3 +175,85 @@ App.Facilities.Farmyard.foodConsumption = function(target = 'both') {
 
 	return citizenConsumption() + slaveConsumption();
 };
+
+/**
+ * @returns {number} The amount of food currently available
+ */
+App.Facilities.Farmyard.foodAvailable = () => {
+	return V.mods.food.amount;
+};
+
+/**
+ * @returns {number} The amount of storage currently available for food
+ */
+App.Facilities.Farmyard.foodStorageAvailable = () => {
+	return (V.farmyardUpgrades.foodStorage * 1000) - V.mods.food.amount;
+};
+
+/**
+ * @param {number} foodAmount The amount of food to get the sell value of
+ * @returns {number} The value of the food if sold in the current economy
+ */
+App.Facilities.Farmyard.foodSellValue = (foodAmount) => {
+	if (V.mods.food.enabled === true) {
+		return Math.ceil((V.mods.food.cost * foodAmount) * 0.7);
+	} else {
+		return Math.ceil((V.mods.food.cost * foodAmount) * 0.1); // food sales for a lot less for balancing reasons
+	}
+};
+
+/**
+ * @param {number} foodAmount The amount of food to sell. The arcology must have at least this much food
+ */
+App.Facilities.Farmyard.foodSell = (foodAmount) => {
+	if (foodAmount > V.mods.food.amount) {
+		throw new Error(`App.Facilities.Farmyard.foodSell() was given a food amount greater than the available amount of food.`);
+	}
+	cashX(Math.trunc(App.Facilities.Farmyard.foodSellValue(foodAmount)), "food");
+	V.mods.food.amount -= foodAmount;
+};
+
+/**
+ * @returns {number} The maximum amount of food that can currently be bought
+ */
+App.Facilities.Farmyard.foodMaxBuyable = () => {
+	let amount = Math.trunc(V.cash / V.mods.food.cost);
+	amount = Math.min(amount, App.Facilities.Farmyard.foodStorageAvailable());
+	return amount;
+};
+
+/**
+ * @param {number} foodAmount The amount of food to get the purchase value of
+ * @returns {number} The cost of the food if bought in the current economy
+ */
+App.Facilities.Farmyard.foodBuyCost = (foodAmount) => {
+	return Math.ceil(V.mods.food.cost * foodAmount);
+};
+
+
+/**
+ * @param {number} foodAmount The amount of food to add to the total amount. This should not be used for purchased food (use `foodBuy()` instead).
+ */
+App.Facilities.Farmyard.foodAdd = (foodAmount) => {
+	V.mods.food.amount += foodAmount;
+	V.mods.food.total += foodAmount;
+};
+
+/**
+ * @param {number} foodAmount The amount of food to remove from the total amount. This should not be used for sold food (use `foodSell()` instead).
+ */
+App.Facilities.Farmyard.foodRemove = (foodAmount) => {
+	V.mods.food.amount -= foodAmount;
+};
+
+/**
+ * @param {number} foodAmount The amount of food to buy. The arcology must have at least this much food storage available
+ */
+App.Facilities.Farmyard.foodBuy = (foodAmount) => {
+	if (foodAmount > App.Facilities.Farmyard.foodStorageAvailable()) {
+		throw new Error(`App.Facilities.Farmyard.foodBuy() was given an amount greater than App.Facilities.Farmyard.foodStorageAvailable()`);
+	}
+	cashX(forceNeg(App.Facilities.Farmyard.foodBuyCost(foodAmount)), "food");
+	V.mods.food.amount += foodAmount;
+	V.mods.food.total += foodAmount;
+};
diff --git a/src/facilities/farmyard/food/foodMarket.js b/src/facilities/farmyard/food/foodMarket.js
index 6fcbd010a7d7a2c4a0a5f7dce57c07e889502fb1..1c433b893280a4717843066ba0d3e8756abb3830 100644
--- a/src/facilities/farmyard/food/foodMarket.js
+++ b/src/facilities/farmyard/food/foodMarket.js
@@ -1,105 +1,173 @@
-App.UI.foodMarket = function() {
-	const frag = new DocumentFragment();
-	const quantities = new Set([1, 10, 100, 1000, 10000, 100000]);
-
-	const maxFood = Math.trunc(V.cash / V.mods.food.cost);
-
-	frag.append(
-		overview(),
-		buy(),
-		// sell(),	// TODO: temporarily disabled for balancing
-		remove(),
-	);
-
-	return frag;
+App.UI.foodMarket = {};
 
-	function overview() {
-		const div = document.createElement("div");
-		const text = new SpacedTextAccumulator(div);
-
-		const consumption = App.Facilities.Farmyard.foodConsumption();
-		const foodValue = Math.trunc(V.mods.food.amount * V.mods.food.cost);
-		const citizens = V.lowerClass + V.middleClass + V.upperClass + V.topClass;
-
-		if (V.useTabs === 0) {
-			App.UI.DOM.appendNewElement("h2", div, "The Food Market");
-		}
-
-		text.push(`The food market has <span class="food">${massFormat(V.mods.food.amount)}</span> in storage, valued at a total of ${cashFormat(foodValue)}.`);
-
-		if (V.mods.food.amount > consumption) {
-			text.push(`This is enough to provide for ${numberWithPluralOne(V.slaves.length, `slave`)} and ${numberWithPluralOne(citizens, `citizen`)} for about ${years(Math.trunc(V.mods.food.amount / consumption))}.`);
-		} else if (V.mods.food.amount < consumption) {
-			text.push(`You will need an additional ${massFormat(consumption - V.mods.food.amount)} to provide for ${numberWithPluralOne(V.slaves.length, `slave`)} and ${numberWithPluralOne(citizens, `citizen`)} during the upcoming week.`);
-		}
+App.UI.foodMarket.quantities = new Set([1, 10, 100, 1000, 10000, 100000]);
 
-		text.toChildren();
+App.UI.foodMarket.buyLinks = () => {
+	const div = App.UI.DOM.makeElement("div", null, ['indent']);
+	const links = [];
+	const maxFood = App.Facilities.Farmyard.foodMaxBuyable();
 
+	if (maxFood === 0) {
+		div.append(`You have no storage space left for food.`);
 		return div;
 	}
 
-	function buy() {
-		const div = App.UI.DOM.makeElement("div", null, ['indent']);
-		const links = [];
+	div.append(`Buy `);
 
-		div.append(`Buy `);
-
-		for (const q of quantities) {
+	for (const q of App.UI.foodMarket.quantities) {
+		if (App.Facilities.Farmyard.foodStorageAvailable() >= q) {
 			links.push(App.UI.DOM.link(
 				massFormat(q),
 				() => {
-					cashX(forceNeg(V.mods.food.cost * q), "farmyard");
-					V.mods.food.amount += q;
+					App.Facilities.Farmyard.foodBuy(q);
 					App.UI.reload();
-				}
+				},
+				undefined,
+				undefined,
+				cashFormat(Math.trunc(App.Facilities.Farmyard.foodBuyCost(q))),
 			));
 		}
+	}
+	if (!App.UI.foodMarket.quantities.has(maxFood)) {
 		links.push(App.UI.DOM.link(
-			"max",
+			massFormat(maxFood),
 			() => {
-				cashX(forceNeg(maxFood * V.mods.food.cost), "farmyard");
-				V.mods.food.amount += maxFood;
+				App.Facilities.Farmyard.foodBuy(maxFood);
 				App.UI.reload();
-			}
+			},
+			undefined,
+			undefined,
+			cashFormat(Math.trunc(App.Facilities.Farmyard.foodBuyCost(maxFood))),
 		));
+	}
+
+	div.append(App.UI.DOM.generateLinksStrip(links));
+	div.append(` of food.`);
+
+	return div;
+};
 
-		div.append(App.UI.DOM.generateLinksStrip(links));
+App.UI.foodMarket.sellLinks = () => {
+	const div = App.UI.DOM.makeElement("div", null, ['indent']);
+	const links = [];
 
+	if (App.Facilities.Farmyard.foodAvailable() === 0) {
+		div.append(`You have no food left to sell.`);
 		return div;
 	}
 
-	function sell() {
-		const div = App.UI.DOM.makeElement("div", null, ['indent']);
-		const links = [];
+	div.append(`Sell `);
 
-		div.append(`Sell `);
-
-		if (V.mods.food.amount > 0) {
-			for (const q of quantities) {
+	if (App.Facilities.Farmyard.foodAvailable() > 0) {
+		for (const q of App.UI.foodMarket.quantities) {
+			if (App.Facilities.Farmyard.foodAvailable() >= q) {
 				links.push(App.UI.DOM.link(
 					massFormat(q),
 					() => {
-						cashX(V.mods.food.cost * q, "farmyard");
-						V.mods.food.amount -= q;
+						App.Facilities.Farmyard.foodSell(q);
 						App.UI.reload();
-					}
+					},
+					undefined,
+					undefined,
+					cashFormat(Math.trunc(App.Facilities.Farmyard.foodSellValue(q))),
 				));
 			}
+		}
+		if (!App.UI.foodMarket.quantities.has(App.Facilities.Farmyard.foodAvailable())) {
 			links.push(App.UI.DOM.link(
-				"max",
+				massFormat(App.Facilities.Farmyard.foodAvailable()),
 				() => {
-					cashX((V.mods.food.cost * V.mods.food.amount), "farmyard");
-					V.mods.food.amount = 0;
+					App.Facilities.Farmyard.foodSell(App.Facilities.Farmyard.foodAvailable());
 					App.UI.reload();
-				}
+				},
+				undefined,
+				undefined,
+				cashFormat(Math.trunc(App.Facilities.Farmyard.foodSellValue(App.Facilities.Farmyard.foodAvailable()))),
 			));
 		}
+	}
 
-		div.append(App.UI.DOM.generateLinksStrip(links));
+	div.append(App.UI.DOM.generateLinksStrip(links));
+	div.append(` of food.`);
 
-		return div;
+	return div;
+};
+
+
+App.UI.foodMarket.foodStorageDescription = () => {
+	const div = document.createElement("div");
+	const text = new SpacedTextAccumulator(div);
+
+	const consumption = App.Facilities.Farmyard.foodConsumption();
+	const foodAvailable = App.Facilities.Farmyard.foodAvailable();
+	const foodValue = App.Facilities.Farmyard.foodSellValue(foodAvailable);
+	const citizens = V.lowerClass + V.middleClass + V.upperClass + V.topClass;
+
+	text.push(`You have <span class="food">${massFormat(foodAvailable)}</span> of food stored in your storehouses, valued at a total of ${cashFormat(foodValue)}.`);
+
+	if (V.mods.food.enabled && V.eventResults.foodCrisis) {
+		if (foodAvailable > consumption) {
+			text.push(`This is enough to provide for ${numberWithPluralOne(V.slaves.length, `slave`)} and ${numberWithPluralOne(citizens, `citizen`)} for about ${years(Math.trunc(foodAvailable / consumption))}.`);
+		} else if (foodAvailable < consumption) {
+			text.push(`You will need an additional ${massFormat(consumption - foodAvailable)} to provide for ${numberWithPluralOne(V.slaves.length, `slave`)} and ${numberWithPluralOne(citizens, `citizen`)} during the upcoming week.`);
+		}
+	}
+
+	text.toChildren();
+
+	return div;
+};
+
+App.UI.foodMarket.foodStorageUpgrades = () => {
+	const div = document.createElement("div");
+	const text = new SpacedTextAccumulator(div);
+	text.push(`You have storage for ${massFormat(V.farmyardUpgrades.foodStorage * 1000)} of food. Any food produced that you don't have storage for will be sold immediately.`);
+	text.toParagraph();
+	text.push(`Buy an extra`);
+	const costPerTon = Math.trunc((100 + (V.farmyardUpgrades.foodStorage / 10)));
+	const links = [];
+
+	for (const q of [1, 10, 100, 1000]) {
+		if ((costPerTon * q) < V.cash) {
+			links.push(App.UI.DOM.link(
+				massFormat(q * 1000),
+				() => {
+					cashX(forceNeg(costPerTon * q), "farmyard");
+					V.farmyardUpgrades.foodStorage += q;
+					App.UI.reload();
+				},
+				undefined,
+				undefined,
+				cashFormat(costPerTon * q),
+			));
+		}
 	}
 
+	text.push(App.UI.DOM.generateLinksStrip(links));
+
+	text.push(`of food storage.`);
+
+	text.toChildren();
+	return div;
+};
+
+App.UI.foodMarket.main = () => {
+	const frag = new DocumentFragment();
+
+	if (V.useTabs === 0) {
+		frag.append(App.UI.DOM.makeElement("h2", "The Food Market"));
+	}
+
+	frag.append(
+		App.UI.foodMarket.foodStorageDescription(),
+		App.UI.foodMarket.foodStorageUpgrades(),
+		App.UI.foodMarket.buyLinks(),
+		App.UI.foodMarket.sellLinks(),
+		remove(),
+	);
+
+	return frag;
+
 	function remove() {
 		const div = document.createElement("div");
 
diff --git a/src/facilities/farmyard/food/foodReport.js b/src/facilities/farmyard/food/foodReport.js
index cfea24055a188b25b5036ead0aea5ed7e220596d..495648347d0791fbbe95148d8ad894e2fb40c0e8 100644
--- a/src/facilities/farmyard/food/foodReport.js
+++ b/src/facilities/farmyard/food/foodReport.js
@@ -18,6 +18,11 @@ App.UI.foodReport = function() {
 
 		text.push(`${V.arcologies[0].name} produced ${massFormat(production)} of food this week.`);
 
+		if (V.mods.food.overstocked > 0) {
+			text.push(text.pop().replace(".", ","));
+			text.push(`of which ${massFormat(V.mods.food.overstocked)} were sold due to lack of storage space.`);
+		}
+
 		if (slaveAmount > 0) {
 			text.push(`${V.farmMenials ? capFirstChar(massFormat(slaveAmount)) : `All of it`} was produced by your ${num(farmhands)} farmhands`);
 		}
@@ -31,20 +36,23 @@ App.UI.foodReport = function() {
 	}
 
 	function consumption() {
+		if (V.mods.food.enabled === false || V.mods.food.market === false) {
+			return "";
+		}
 		const text = [];
 		const production = App.Facilities.Farmyard.foodProduction();
 		const consumption = App.Facilities.Farmyard.foodConsumption();
 		const deficit = Math.abs(consumption - production);
-		const cost = deficit * V.mods.food.cost;
-		const storage = V.mods.food.amount;
+		const cost = App.Facilities.Farmyard.foodBuyCost(deficit);
+		const storage = App.Facilities.Farmyard.foodAvailable();
 
 		if (production > consumption) {
-			text.push(`${capFirstChar(massFormat(consumption))} of it was consumed, with a spare ${massFormat(production - consumption)} moved into long-term storage.`);
+			text.push(`${capFirstChar(massFormat(consumption))} of it was consumed, with a spare ${massFormat(production - (consumption + V.mods.food.overstocked))} moved into long-term storage.`);
 		} else {
 			if (storage > deficit) {
-				text.push(`Unfortunately, this wasn't enough to cover needs of your hungry arcology, and ${massFormat(deficit)} had to be brought up from storage.`);
+				text.push(`Unfortunately, this wasn't enough to cover the needs of your hungry arcology, and ${massFormat(deficit)} had to be brought out of storage.`);
 			} else if (V.cash > cost) {
-				text.push(`Unfortunately, this wasn't enough to cover needs of your hungry arcology, and because you didn't have enough food in storage, you has to purchase and additional ${massFormat(deficit - storage)} for ${cashFormat()}.`);
+				text.push(`Unfortunately, this wasn't enough to cover the needs of your hungry arcology, and because you didn't have enough food in storage, you had to purchase an additional ${massFormat(deficit - storage)} for ${cashFormat(App.Facilities.Farmyard.foodBuyCost(deficit - storage))}.`);
 			}
 		}
 
diff --git a/src/facilities/statistics.js b/src/facilities/statistics.js
index beb40f78761ffe197311e1656ac1d2211dd94423..62a810a1215f9eb43dd7d259013bd11797beacba 100644
--- a/src/facilities/statistics.js
+++ b/src/facilities/statistics.js
@@ -500,22 +500,15 @@ App.Facilities.Farmyard.Stats = function(showDetails) {
 	}
 
 	const H = new App.Facilities.StatsHelper(["Revenue", "Expenses", "Food [kg]", "Net Income", "Rep. Change"]);
-	H.addValueRow("Total farmhand income", [
+	H.addValueRow("Farmhands", [
 		H.makeValueCell(b.whoreIncome, {type: "cash"}),
-		H.makeEmptyCell(),
-		H.makeEmptyCell(),
-		H.makeValueCell(b.whoreIncome, {type: "cash"}),
-		H.makeEmptyCell(),
-	]);
-	H.addValueRow("Total farmhand living costs", [
-		H.makeEmptyCell(),
 		H.makeValueCell(b.whoreCosts, {forceNeg: true, type: "cash"}),
 		H.makeEmptyCell(),
-		H.makeValueCell(b.whoreCosts, {forceNeg: true, showSign: true, type: "cash"}),
-		H.makeEmptyCell()
+		H.makeValueCell(b.whoreIncome - b.whoreCosts, {type: "cash"}),
+		H.makeEmptyCell(),
 	]);
 	if ( App.Entity.facilities.farmyard.employees().length !== 0) {
-		H.addValueRow("food produced by farmhands", [
+		H.addValueRow("Food produced by farmhands", [
 			H.makeEmptyCell(),
 			H.makeEmptyCell(),
 			H.makeValueCell(b.slaveFoodCounts, {type: "food"}),
@@ -524,7 +517,7 @@ App.Facilities.Farmyard.Stats = function(showDetails) {
 		]);
 	}
 	if (V.farmMenials) {
-		H.addValueRow("food produced by menials", [
+		H.addValueRow("Food produced by menials", [
 			H.makeEmptyCell(),
 			H.makeEmptyCell(),
 			H.makeValueCell(b.menialFoodCounts, {type: "food"}),
@@ -539,6 +532,15 @@ App.Facilities.Farmyard.Stats = function(showDetails) {
 		H.makeValueCell(b.menialFoodCounts + b.slaveFoodCounts, {type: "food"}),
 		H.makeEmptyCell()
 	]);
+	if (V.mods.food.overstocked > 0) {
+		H.addValueRow("Total food sold", [
+			H.makeEmptyCell(),
+			H.makeValueCell(App.Facilities.Farmyard.foodSellValue(V.mods.food.overstocked), {type: "cash"}),
+			H.makeValueCell(V.mods.food.overstocked, {type: "food", forceNeg: true}),
+			H.makeValueCell(App.Facilities.Farmyard.foodSellValue(V.mods.food.overstocked), {type: "cash"}),
+			H.makeEmptyCell()
+		]);
+	}
 	if (showDetails) {
 		H.startSlaveStatsSection("Farmhand details", ["Farmhand", "Revenue", "Expenses",
 			"Food [kg]", "Net Income", "Rep. Change"]);
diff --git a/src/js/economyJS.js b/src/js/economyJS.js
index 9cc92d21270496dc8711716173829159c3282442..d031d0f3960e426d45fc3d7814ba42f440b42bc7 100644
--- a/src/js/economyJS.js
+++ b/src/js/economyJS.js
@@ -815,7 +815,7 @@ globalThis.calculateCosts = (function() {
 
 	function getPCFoodCosts() {
 		const slimnessFoodMod = V.arcologies[0].FSSlimnessEnthusiastFoodLaw === 1 && !canEatFood(V.PC) ? 1.15 : 1;
-		const foodCost = V.mods.food.cost * slimnessFoodMod;
+		const foodCost = App.Facilities.Farmyard.foodBuyCost(slimnessFoodMod);
 		let costs = 0;
 		// Well this ought to be a mess.
 		// Basic food costs
@@ -1251,7 +1251,7 @@ globalThis.getSlaveCostArray = function(s) {
 	let t = "";
 	const slimnessFoodMod = V.arcologies[0].FSSlimnessEnthusiastFoodLaw === 1 ? 1.15 : 1;
 	const rulesCost = V.rulesCost;
-	const foodCost = V.mods.food.cost * slimnessFoodMod;
+	const foodCost = App.Facilities.Farmyard.foodBuyCost(slimnessFoodMod);
 	const drugsCost = V.drugsCost;
 
 	retval.push({text: "Living Expenses", value: getSlaveLivingExpenses(s)});
diff --git a/src/js/utilsMisc.js b/src/js/utilsMisc.js
index f03babf0d0e6f84e0cdb8f0a8019ec2339a70af0..c4f71ff87f30770c5947a2144a00f616773101fd 100644
--- a/src/js/utilsMisc.js
+++ b/src/js/utilsMisc.js
@@ -248,7 +248,7 @@ App.Utils.totalNetWorth = function() {
 		.filter(f => f.established)
 		.reduce((acc, cur) => acc + cur.value, 0);
 
-	total += Math.trunc(V.mods.food.amount * V.mods.food.cost);
+	total += Math.trunc(App.Facilities.Farmyard.foodSellValue(App.Facilities.Farmyard.foodAvailable()));
 
 	total += App.Mods.SF.totalNetWorth();
 	total -= App.Mods.SecExp.upkeep.cost();