diff --git a/src/Mods/SecExp/authorityReport.tw b/src/Mods/SecExp/authorityReport.tw
index 915e68490185c872ac7ba6603df9c0c89d7d3409..2a243fa2ac115f8a2fff2ca8fc13730bdae55a97 100644
--- a/src/Mods/SecExp/authorityReport.tw
+++ b/src/Mods/SecExp/authorityReport.tw
@@ -153,9 +153,9 @@ Your authority is
 	<<set _authGrowth += (15 * $SecExp.buildings.propHub.secretService)>>
 <</if>>
 
-<<if App.SecExp.upkeep('edictsAuth') > 0>>
+<<if App.SecExp.upkeep.edictsAuth() > 0>>
 	Some of your authority is spent maintaining your edicts.
-	<<set _authGrowth -= App.SecExp.upkeep('edictsAuth')>>
+	<<set _authGrowth -= App.SecExp.upkeep.edictsAuth()>>
 <</if>>
 
 This week
diff --git a/src/Mods/SecExp/js/secExp.js b/src/Mods/SecExp/js/secExp.js
index bdf41b43f2b7b2f97e2ae8319f34d155cb4d8e17..f9990832ae055f19d27b654916bc40638efaddc8 100644
--- a/src/Mods/SecExp/js/secExp.js
+++ b/src/Mods/SecExp/js/secExp.js
@@ -2,114 +2,137 @@ globalThis.SecExpBase = function() {
 	return new App.SecExp.SecurityExpansionState();
 };
 
-App.SecExp.upkeep = function(input = '') {
-	let value = 0;
-	if (input === 'edictsCash') {
+App.SecExp.upkeep = (function() {
+	return {
+		edictsCash,
+		edictsAuth,
+		SF,
+		buildings
+	};
+
+	/** Upkeep cost of edicts, in cash
+	 * @returns {number}
+	 */
+	function edictsCash() {
+		let value = 0;
 		const vars = ['slaveWatch', 'subsidyChurch', 'martialSchool',
-		'legionTradition', 'pharaonTradition', 'eagleWarriors', 'ronin',
-		'mamluks', 'sunTzu', 'tradeLegalAid', 'propCampaignBoost'];
-			for(let i = 0; i < vars.length; i++) {
-				if (jsDef(V[vars[i]]) && V[vars[i]] > 0) {
-					value += 1000;
-				}
-			}
-		} else if (input === 'edictsAuth') {
-			if(V.enslavementRights > 0) {
-				value += 10;
-			}
-			if (V.sellData === 1) {
-				value += 10;
-			}
-			if (V.slaveSoldierPrivilege === 1) {
-				value += 10;
-			}
-			if (V.weaponsLaw === 0) {
-				value += 30;
-			} else if (V.weaponsLaw === 2) {
-				value += 10;
-			} else if (V.weaponsLaw === 1) {
-				value += 20;
+			'legionTradition', 'pharaonTradition', 'eagleWarriors', 'ronin',
+			'mamluks', 'sunTzu', 'tradeLegalAid', 'propCampaignBoost'];
+		for(let i = 0; i < vars.length; i++) {
+			if (jsDef(V[vars[i]]) && V[vars[i]] > 0) {
+				value += 1000;
 			}
-			if (V.slavesOfficers === 1) {
-				value += 10;
+		}
+		return value;
+	}
+
+	/** Upkeep cost of edicts, in authority
+	 * @returns {number}
+	 */
+	function edictsAuth() {
+		let value = 0;
+		if (V.enslavementRights > 0) {
+			value += 10;
+		}
+		if (V.sellData === 1) {
+			value += 10;
+		}
+		if (V.slaveSoldierPrivilege === 1) {
+			value += 10;
+		}
+		if (V.weaponsLaw === 0) {
+			value += 30;
+		} else if (V.weaponsLaw === 1) {
+			value += 20;
+		} else if (V.weaponsLaw === 2) {
+			value += 10;
+		}
+		if (V.slavesOfficers === 1) {
+			value += 10;
+		}
+		return value;
+	}
+
+	/** Upkeep cost of Special Forces (why is this here? who knows!)
+	 * @returns {number}
+	 */
+	function SF() {
+		let value = 0;
+		if (V.SFSupportLevel >= 1) {
+			value += 1000;
+		}
+		if (V.SFSupportLevel >= 2) {
+			value += 2000;
+		}
+		if (V.SFSupportLevel >= 3) {
+			value += 3000;
+		}
+		if (V.SFSupportLevel >= 4) {
+			value += 3000;
+		}
+		if (V.SFSupportLevel >= 5) {
+			value += 4000;
+		}
+		return value;
+	}
+
+	/** Upkeep cost of buildings (in cash)
+	 * @returns {number}
+	 */
+	function buildings() {
+		let value = 0;
+		const base = V.facilityCost * 5, upgrade = 50;
+		if (V.SecExp.buildings.propHub.active > 0) {
+			value += base;
+			let buildingUgradePool = [];
+			buildingUgradePool.push(V.SecExp.buildings.propHub.campaign);
+			buildingUgradePool.push(V.SecExp.buildings.propHub.miniTruth);
+			buildingUgradePool.push(V.SecExp.buildings.propHub.fakeNews);
+			buildingUgradePool.push(V.SecExp.buildings.propHub.controlLeaks);
+			buildingUgradePool.push(V.SecExp.buildings.propHub.secretService);
+			buildingUgradePool.push(V.SecExp.buildings.propHub.blackOps);
+			buildingUgradePool.push(V.SecExp.buildings.propHub.marketInfiltration);
+			for(let i = 0; i < buildingUgradePool.length; i++) {
+				value += upgrade*buildingUgradePool[i];
+			}
+		}
+		if (V.secHQ > 0) {
+			value += base + 20 * V.secMenials;
+			let buildingUgradePool = [];
+			buildingUgradePool.push(...Object.values(V.secUpgrades));
+			buildingUgradePool.push(...Object.values(V.crimeUpgrades));
+			buildingUgradePool.push(...Object.values(V.readinessUpgrades));
+			buildingUgradePool.push(...Object.values(V.intelUpgrades));
+			for(let i = 0; i < buildingUgradePool.length; i++) {
+				value += upgrade*buildingUgradePool[i];
 			}
-		} else if(input === 'SF') {
-			if(V.SFSupportLevel >= 1) {
+			if (V.SFSupportLevel >= 5) {
 				value += 1000;
 			}
-			if (V.SFSupportLevel >= 2) {
-				value += 2000;
+		}
+		if (V.SecExp.buildings.barracks.active > 0) {
+			value += base;
+			let buildingUgradePool = Object.values(V.SecExp.buildings.barracks.upgrades);
+			for(let i = 0; i < buildingUgradePool.length; i++) {
+				value += upgrade*buildingUgradePool[i];
+			}
+		}
+		if (V.riotCenter > 0) {
+			value += base;
+			let buildingUgradePool = Object.values(V.riotUpgrades);
+			for(let i = 0; i < buildingUgradePool.length; i++) {
+				value += upgrade*buildingUgradePool[i];
 			}
-			if (V.SFSupportLevel >= 3) {
-				value += 3000;
+			if (V.brainImplant < 106 && V.brainImplantProject > 0) {
+				value += 5000*V.brainImplantProject;
 			}
-			if (V.SFSupportLevel >= 4) {
-				value += 3000;
+			if (V.SF.Toggle && V.SF.Active >= 1 && V.SFGear > 0) {
+				value += 15000;
 			}
-			if (V.SFSupportLevel >= 5) {
-				value += 4000;
-			}
-		} else if (input === 'buildings') {
-				const base = V.facilityCost * 5, upgrade = 50;
-				let buildingUgradePool = [];
-				if (V.propHub > 0) {
-					value += base;
-					buildingUgradePool.push(V.SecExp.buildings.propHub.campaign);
-					buildingUgradePool.push(V.SecExp.buildings.propHub.miniTruth);
-					buildingUgradePool.push(V.SecExp.buildings.propHub.fakeNews);
-					buildingUgradePool.push(V.SecExp.buildings.propHub.controlLeaks);
-					buildingUgradePool.push(V.SecExp.buildings.propHub.secretService);
-					buildingUgradePool.push(V.SecExp.buildings.propHub.blackOps);
-					buildingUgradePool.push(V.SecExp.buildings.propHub.marketInfiltration);
-					for(let i = 0; i < buildingUgradePool; i++) {
-						if(i > 0) {
-							value += upgrade*buildingUgradePool[i];
-						}
-					}
-				}
-				if (V.secHQ > 0) {
-					value += base + 20 * V.secMenials;
-					buildingUgradePool.push(V.secUpgrades);
-					buildingUgradePool.push(V.crimeUpgrades);
-					buildingUgradePool.push(V.readinessUpgrades);
-					buildingUgradePool.push(V.intelUpgrades);
-					for(let i = 0; i < buildingUgradePool; i++) {
-						if(i > 0) {
-							value += upgrade*buildingUgradePool[i];
-						}
-					}
-					if(V.SFSupportLevel >= 5) {
-						value += 1000;
-					}
-				}
-				if (V.secBarracks > 0) {
-					value += base;
-					buildingUgradePool.push(V.SecExp.buildings.barracks.upgrades);
-					for(let i = 0; i < buildingUgradePool; i++) {
-						if(i > 0) {
-							value += upgrade*buildingUgradePool[i];
-						}
-					}
-				}
-				if (V.riotCenter > 0) {
-					value += base;
-					buildingUgradePool.push(V.riotUpgrades);
-					for(let i = 0; i < buildingUgradePool; i++) {
-						if(i > 0) {
-							value += upgrade*buildingUgradePool[i];
-						}
-					}
-					if(V.brainImplant < 106 && V.brainImplantProject > 0) {
-						value += 5000*V.brainImplantProject;
-					}
-					if (V.SF.Toggle && V.SF.Active >= 1 && V.SFGear > 0) {
-						value += 15000;
-					}
-				}
 		}
-			// break;
 		return value;
-}; // Closes upkeep function.
+	}
+})();
 
 App.SecExp.conflict = (function() {
 	"use strict";
@@ -118,6 +141,10 @@ App.SecExp.conflict = (function() {
 		troopCount:troopCount,
 	};
 
+	/** Get count of deployed/active units for a particular battle
+	 * @param {string} [input] unit type to measure; if omitted, count all types
+	 * @returns {number} unit count
+	 */
 	function deployedUnits(input = '') {
 		let bots = 0, militiaC = 0, slavesC = 0, mercsC = 0, init = 0;
 		if(V.slaveRebellion !== 1 && V.citizenRebellion !== 1) {
@@ -211,6 +238,9 @@ App.SecExp.conflict = (function() {
 		}
 	}
 
+	/** Get total troop count of deployed/active units for a particular battle
+	 * @returns {number} troop count
+	 */
 	function troopCount() {
 		let troops = 0;
 
@@ -277,6 +307,9 @@ App.SecExp.battle = (function() {
 		bribeCost:bribeCost,
 	};
 
+	/** Get mobilization readiness (in *pairs* of units) given upgrades
+	 * @returns {number} readiness
+	 */
 	function deploySpeed() {
 		let init = 1;
 		if(V.readinessUpgrades.pathways > 0) {
@@ -297,6 +330,9 @@ App.SecExp.battle = (function() {
 		return init;
 	}
 
+	/** Get remaining deployable units (mobilization in units minus units already deployed)
+	 * @returns {number}
+	 */
 	function deployableUnits() {
 		let init = 2 * App.SecExp.battle.deploySpeed();
 		if(V.secBots.isDeployed > 0) {
@@ -330,10 +366,16 @@ App.SecExp.battle = (function() {
 		return init;
 	}
 
+	/** Get total active units
+	 * @returns {number}
+	 */
 	function activeUnits() {
-		return V.secBots.isDeployed + V.militiaUnits.length + V.slaveUnits.length + V.mercUnits.length;
+		return V.secBots.active + V.militiaUnits.length + V.slaveUnits.length + V.mercUnits.length;
 	}
 
+	/** Get maximum active units
+	 * @returns {number}
+	 */
 	function maxUnits() {
 		let max = 8 + (V.SecExp.buildings.barracks.upgrades.size * 2);
 		if(App.SecExp.battle.deploySpeed() === 10) {
@@ -342,6 +384,9 @@ App.SecExp.battle = (function() {
 		return max;
 	}
 
+	/** Get recon score (scale 0-4)
+	 * @returns {number}
+	 */
 	function recon() {
 		let recon = 0;
 		if (V.intelUpgrades.sensors > 0) {
@@ -356,6 +401,9 @@ App.SecExp.battle = (function() {
 		return recon;
 	}
 
+	/** Get bribe cost for an attacker to go away
+	 * @returns {number}
+	 */
 	function bribeCost() {
 		let cost; const baseBribePerAttacker = 5;
 		if (V.week <= 30) {
@@ -368,6 +416,8 @@ App.SecExp.battle = (function() {
 			cost = 20000 + baseBribePerAttacker * V.attackTroops;
 		} else if (V.week <= 70) {
 			cost = 25000 + baseBribePerAttacker * V.attackTroops;
+		} else {
+			cost = 30000 + baseBribePerAttacker * V.attackTroops;
 		}
 		if (V.majorBattle > 0) {
 			cost *= 3;
@@ -730,13 +780,13 @@ App.SecExp.unit = (function() {
 			}
 
 			if (unitType !== "Bots") {
-					if(input.battlesFought > 1) {
-						r += `has participated in ${input.battlesFought} battles and is ready to face the enemy once more at your command. `;
-					} else if (input.battlesFought === 1) {
-						r += `is ready to face the enemy once more at your command. `;
-					} else {
-						r += `is ready to face the enemy in battle. `;
-					}
+				if(input.battlesFought > 1) {
+					r += `has participated in ${input.battlesFought} battles and is ready to face the enemy once more at your command. `;
+				} else if (input.battlesFought === 1) {
+					r += `is ready to face the enemy once more at your command. `;
+				} else {
+					r += `is ready to face the enemy in battle. `;
+				}
 				r += `\nIt's ${input.troops} men and women are `;
 
 				if(unitType === "Militia") {
@@ -744,7 +794,7 @@ App.SecExp.unit = (function() {
 				} else if (unitType === "Slaves") {
 					r += `slaves in your possession, tasked with the protection of their owner and their arcology. `;
 				} else if (unitType === "Mercs") {
-				r += `mercenaries contracted to defend the arcology against external threats. `;
+					r += `mercenaries contracted to defend the arcology against external threats. `;
 				}
 			} else {
 				r += `All of which are assembled in an ordered formation in front of you, absolutely silent and ready to receive their orders. `;
@@ -779,8 +829,8 @@ App.SecExp.unit = (function() {
 			if(unitType !== "Bots") {
 				if(input.training <= 33) {
 					r += `They lack the experience to be considered professionals, but `;
-				if (input === "Militia") {
-					r += `their eagerness to defend the arcology makes up for it. `;
+					if (input === "Militia") {
+						r += `their eagerness to defend the arcology makes up for it. `;
 					} else if (unitType === "Slaves") {
 						r += `their eagerness to prove themselves makes up for it. `;
 					} else if (unitType === "Mercs") {
@@ -851,16 +901,16 @@ App.SecExp.unit = (function() {
 			if (jsDef(input.loyalty)) {
 				r += `Loyalty: `;
 				if(input.loyalty < 10) {
-						r += `extremely disloyal. `;
-					} else if (input.loyalty < 33) {
-						r += `low. `;
-					} else if (input.loyalty < 66) {
-						r += `medium. `;
-					} else if (input.loyalty < 90) {
-						r += `high. `;
-					} else {
-						r += `fanatical. `;
-					}
+					r += `extremely disloyal. `;
+				} else if (input.loyalty < 33) {
+					r += `low. `;
+				} else if (input.loyalty < 66) {
+					r += `medium. `;
+				} else if (input.loyalty < 90) {
+					r += `high. `;
+				} else {
+					r += `fanatical. `;
+				}
 			}
 			if (jsDef(input.cyber) && input.cyber > 0) {
 				r += `\nHave been cyberaugmentated. `;
diff --git a/src/js/economyJS.js b/src/js/economyJS.js
index e60d79d0c282784df75eb9090e8806c3a9a62090..2a69dedbfb8e7db762914802a3ad200d40a5d9e1 100644
--- a/src/js/economyJS.js
+++ b/src/js/economyJS.js
@@ -571,9 +571,9 @@ globalThis.calculateCosts = (function() {
 	function getSecurityExpansionCost() {
 		let secExpCost = 0, soldierMod = 0;
 		if (V.secExpEnabled > 0) {
-			secExpCost += App.SecExp.upkeep('edictsCash');
-			secExpCost += App.SecExp.upkeep('SF');
-			secExpCost += App.SecExp.upkeep('buildings');
+			secExpCost += App.SecExp.upkeep.edictsCash();
+			secExpCost += App.SecExp.upkeep.SF();
+			secExpCost += App.SecExp.upkeep.buildings();
 			if (V.soldierWages === 0) {
 				soldierMod = 1;
 			} else if (V.soldierWages === 1) {