diff --git a/js/003-data/gameVariableData.js b/js/003-data/gameVariableData.js
index 12cbec347487303d3c991fecc5293561c4b25db7..fee41a5b8c3144c5d6ad33450f27a8c314356d5c 100644
--- a/js/003-data/gameVariableData.js
+++ b/js/003-data/gameVariableData.js
@@ -225,6 +225,9 @@ App.Data.defaultGameStateVariables = {
 	retirementAge: 45,
 	customRetirementAge: 45,
 	customMenialRetirementAge: 65,
+	idealAge: 18,
+	targetIdealAge: 18,
+	idealAgeAdoption: 0,
 	sortIncubatorList: "Unsorted",
 	AgeEffectOnTrainerPricingPC: 1,
 	AgeEffectOnTrainerEffectivenessPC: 1,
@@ -366,6 +369,7 @@ App.Data.resetOnNGPlus = {
 		},
 
 		childProtectionAct: 1,
+		idealAge: 0,
 		culturalOpenness: 0,
 		proRefugees: 0,
 		publicFuckdolls: 0,
diff --git a/js/003-data/policiesData.js b/js/003-data/policiesData.js
index f3985991e1f125432d61a92f41ecf1e9404784af..b2b82cd5f2334eb50eea68f07bc43a377c019faa 100644
--- a/js/003-data/policiesData.js
+++ b/js/003-data/policiesData.js
@@ -312,6 +312,61 @@ App.Data.Policies.Selection = {
 				get hide() { return (V.extremeUnderage === 1) ? {button: 0} : {button: 1}; } // CPA is complicated. It inits to "on". Make sure button is hidden if extreme underage is OFF. If a player enables extreme underage, then we can let them control it.
 			}
 		],
+		"policies.idealAge": [
+			{
+				title: "Ideal Age Of Sexual Appeal",
+				get text() {
+					const el = new DocumentFragment;
+					if(V.idealAge === 18) {
+						el.append(`most consider the ideal age of sexual appeal to be the old world default of 18. You will use your influence to change the sexually ideal age to `);
+					}
+					else {
+						el.append(`most consider the ideal age of sexual appeal to be ${V.idealAge}. You will use your influence to change the sexually ideal age to `);
+					}
+					el.append(
+						App.UI.DOM.makeElement(
+							"div",
+							App.UI.DOM.makeTextBox(
+								V.targetIdealAge,
+								v => {
+									let minAge = V.minimumSlaveAge;
+									let maxAge = V.retirementAge - 1 > 60 ? 60 : V.retirementAge - 1;/* problems do occur if idealAge can be set to over 60 */
+									if(V.arcologies[0].FSMaturityPreferentialist !== "unset") {
+										minAge = 30;
+									}
+									if(V.arcologies[0].FSYouthPreferentialist !== "unset") {
+										maxAge = 29;
+									}
+									V.targetIdealAge = Math.clamp(v, minAge, maxAge);
+									App.UI.reload();
+								},
+								true
+							),
+							["indent"]
+						)
+					);
+					return el;
+				},
+				get activatedText() {
+					return `you are using your personal influence to make ${V.targetIdealAge} the most sexually appealing age. The current percieved ideal age of sexual appeal is ${V.idealAge}.`;
+				},
+				onRepeal: function() { 
+					if(V.arcologies[0].FSMaturityPreferentialist !== "unset") {
+						if(V.idealAge < 30) {
+							V.idealAge = 30;
+						}
+						V.targetIdealAge = 30;
+					}
+					else {
+						if(V.idealAge >= 30) {
+							V.idealAge = 29;
+						}
+						V.targetIdealAge = 18;
+					}
+				},
+				get note() { return `Will cost ${cashFormat(1500)} weekly until the target age is reached; high reputation will accelerate adoption.`}
+			}
+		],
 		"arcologies[0].FSEgyptianRevivalistIncestPolicy": [
 			{
 				title: "Incest Encouragement",
@@ -746,6 +801,9 @@ App.Data.Policies.Selection = {
 									const age = Math.clamp(v, 20, 120);
 									V.customRetirementAge = age;
 									V.retirementAge = age;
+									if (V.idealAge >= V.retirementAge) {
+										V.idealAge = V.retirementAge - 1;
+									}
 									App.UI.reload();
 								},
 								true
@@ -776,6 +834,9 @@ App.Data.Policies.Selection = {
 									const age = Math.clamp(v, 20, 120);
 									V.customRetirementAge = age;
 									V.retirementAge = age;
+									if(V.idealAge >= V.retirementAge) {
+										V.idealAge = V.retirementAge - 1;
+									}
 									App.UI.reload();
 								},
 								true
diff --git a/src/cheats/cheatEditArcology.js b/src/cheats/cheatEditArcology.js
index 9f2c6640eabfc41ce47ba93c87060d45511440b3..3fa3fdac49e45869b02236da396b9da5f41f71f0 100644
--- a/src/cheats/cheatEditArcology.js
+++ b/src/cheats/cheatEditArcology.js
@@ -15,6 +15,29 @@ App.UI.Cheat.arcology = function(num) {
 		el.append(tabBar.render());
 	}
 
+	if(num === 0) {
+		if(arc.FSMaturityPreferentialist !== "unset") {
+			if(V.idealAge < 30) {
+				V.idealAge = 30;
+			}
+			if(V.targetIdealAge < 30) {
+				V.targetIdealAge = 30;
+			}
+			V.policies.idealAge = 1;
+		} 
+		else if(arc.FSYouthPreferentialist !== "unset") {
+			if(V.idealAge >= 30) {
+				V.idealAge = 29;
+			} 
+			if(V.targetIdealAge >= 30) {
+				V.targetIdealAge = 29;
+			}
+			if(V.targetIdealAge !== 18) {
+				V.policies.idealAge = 1;
+			} 
+		} 
+	}
+
 	return el;
 
 	function cheat() {
@@ -134,7 +157,7 @@ App.UI.Cheat.arcology = function(num) {
 						option.addValue(capRace, race);
 					}
 				}
-			}
+ 			}
 		}
 		el.append(options.render());
 		return el;
diff --git a/src/data/backwardsCompatibility/policiesBC.js b/src/data/backwardsCompatibility/policiesBC.js
index af28db08ccd7df11a64bc1ea017a14a3784a9805..1cf9125656d27e98753d1d0f84fe05131618039e 100644
--- a/src/data/backwardsCompatibility/policiesBC.js
+++ b/src/data/backwardsCompatibility/policiesBC.js
@@ -13,13 +13,10 @@ App.Update.policies = function() {
 		}
 	}
 
-	if (V.policies.gumjobFetishism == null) {
-		V.policies.gumjobFetishism = 0;
-	}
-
-	if (V.policies.gumjobFetishismSMR == null) {
-		V.policies.gumjobFetishismSMR = 0;
-	}
+	App.Update.setNonexistentProperties(V.policies, {
+		gumjobFetishism: 0,
+		gumjobFetishismSMR: 0
+	});	
 
 	// Spelling fixes:
 	V.policies.sexualOpenness = V.policies.sexualOpenness || V.policies.sexualOpeness || 0;
diff --git a/src/endWeek/economics/arcmgmt.js b/src/endWeek/economics/arcmgmt.js
index a52cdb25d9fd7b8012546aeb05853d8d71c6c7bb..bee0102dc008097f693ddd45e512d1825f886dc7 100644
--- a/src/endWeek/economics/arcmgmt.js
+++ b/src/endWeek/economics/arcmgmt.js
@@ -1058,6 +1058,41 @@ App.EndWeek.arcManagement = function() {
 	function policiesImpact() {
 		const el = new DocumentFragment();
 		const r = [];
+		if(V.policies.idealAge) {
+			if(V.targetIdealAge !== V.idealAge) {
+				r.push(`You spend <span class="yellow">${cashFormat(1500)}</span> and use your personal influence to shift the percieved ideal age of sexual appeal.`);
+				V.idealAgeAdoption += V.rep / 100;
+				if(V.idealAgeAdoption > 100) {
+					const adoptionModifier = Math.floor(V.idealAgeAdoption / 100);
+					if(V.targetIdealAge > V.idealAge) {
+						V.idealAge = Math.clamp(Math.floor(V.idealAge + adoptionModifier),V.idealAge,V.targetIdealAge);
+					} else {
+						V.idealAge = Math.clamp(Math.floor(V.idealAge - adoptionModifier),V.idealAge,V.targetIdealAge);
+					}
+					if(adoptionModifier > 1) {
+						r.push(`Your peerless reptutation <span class="green">rapidly accelerates</span> the adoption of your proposed ideal age of sexual appeal, and most now consider it to be ${V.idealAge}.`);
+					} else {
+						r.push(`The percieved ideal age of sexual appeal has shifted ${V.idealAge === V.targetIdealAge ? "to" : "toward"} ${V.targetIdealAge}${V.idealAge !== V.targetIdealAge ? ", and most now consider the ideal age to be " + V.idealAge : ""}.`);
+					}
+					if(V.targetIdealAge === V.idealAge) {
+						r.push(`The percieved ideal age of sexual appeal has <span class="green">reached your intended target.</span>`);
+					}
+					V.idealAgeAdoption = V.idealAgeAdoption - (100 * adoptionModifier);
+				}
+				else {
+					if(V.idealAgeAdoption <= 0) {
+						r.push(`Unfortunately, your efforts <span class="red">had no effect</span> on the perceived ideal age of sexual appeal, and it remains ${V.idealAge}.`);
+					}
+					else {
+						r.push(`You have made <span class="yellow">partial progress</span> in shifting the perceived ideal age of sexual appeal, but for now, it remains ${V.idealAge}.`);
+					}
+				}
+			} else {
+				r.push(`Most continue to consider the ideal age of sexual appeal to be ${V.idealAge}.`);
+			}
+		} else {
+			r.push(`Most consider the ideal age of sexual appeal to be ${V.idealAge}.`);
+		}
 		if (V.policies.retirement.menial2Citizen === 1) {
 			slaveDemandU *= 0.8;
 			slaveDemandT *= 0.75;
diff --git a/src/events/intro/introSummary.js b/src/events/intro/introSummary.js
index dcf7e99ff8802c00569c7165b78fbe19e46f266a..f72206639a9929d774233191868f72c6a26cce8c 100644
--- a/src/events/intro/introSummary.js
+++ b/src/events/intro/introSummary.js
@@ -10,6 +10,19 @@ App.Intro.summary = function() {
 
 	V.minimumSlaveAge = variableAsNumber(V.minimumSlaveAge, 3, 18, 18);
 	V.retirementAge = variableAsNumber(V.retirementAge, 25, 120, 45);
+	let minAge = V.minimumSlaveAge;
+	let maxAge = V.retirementAge - 1 > 60 ? 60 : V.retirementAge - 1;
+	let defaultAge = 18;
+	if(V.targetArcology.fs === "FSMaturityPreferentialist") {
+		minAge = 30;
+		defaultAge = 30;
+	}
+	else if(V.targetArcology.fs === "FSYouthPreferentialist") {
+		maxAge = 29;
+	}
+	V.idealAge = variableAsNumber(V.idealAge, minAge, maxAge, defaultAge);
+	V.targetIdealAge = V.idealAge;
+
 	V.fertilityAge = variableAsNumber(V.fertilityAge, 3, 18, 13);
 	V.potencyAge = variableAsNumber(V.potencyAge, 3, 18, 13);
 	V.PC.mother = Number(V.PC.mother);
@@ -609,6 +622,10 @@ App.Intro.summary = function() {
 		options.addOption("Initial retirement age will be at", "retirementAge")
 			.addComment("May cause issues with New Game and initial slaves if set below 45.").showTextBox();
 
+		V.idealAge = Math.clamp(V.idealAge, minAge, maxAge);
+		options.addOption("Initial ideal age of sexual appeal will be", "idealAge")
+			.addComment("Percieved beauty will decrease the farther (younger or older) a body is visually from this age.").showTextBox();
+
 		V.fertilityAge = Math.clamp(V.fertilityAge, 3, 18);
 		options.addOption("Girls will not be able to become pregnant if their age is under", "fertilityAge").showTextBox();
 
diff --git a/src/futureSocieties/fsPassage.js b/src/futureSocieties/fsPassage.js
index 31e77af51fb4d8151f6d1c534f2ce13526773951..86cb4b40626ed879a404c703efbb8f560c3f2aa6 100644
--- a/src/futureSocieties/fsPassage.js
+++ b/src/futureSocieties/fsPassage.js
@@ -718,6 +718,15 @@ App.UI.fsPassage = function() {
 							"Youth Preferentialism",
 							() => {
 								arc.FSYouthPreferentialist = 4;
+								if(V.idealAge >= 30) {
+									V.idealAge = 29;
+								}
+								if(V.targetIdealAge >= 30) {
+									V.targetIdealAge = 29;
+								}
+								if(V.targetIdealAge !== 18) {
+									V.policies.idealAge = 1;
+								} 
 								App.UI.reload();
 							}
 						)
@@ -742,6 +751,13 @@ App.UI.fsPassage = function() {
 							"Maturity Preferentialism",
 							() => {
 								arc.FSMaturityPreferentialist = 4;
+								if(V.idealAge < 30) {
+									V.idealAge = 30;
+								}
+								if(V.targetIdealAge < 30) {
+									V.targetIdealAge = 30;
+								}
+								V.policies.idealAge = 1;
 								App.UI.reload();
 							}
 						)
diff --git a/src/js/economyJS.js b/src/js/economyJS.js
index ac2907a22aa8314a4b3446e5ea2cbeaa96685297..d23112d09e4451d7047fdb84cb1706adee01a54c 100644
--- a/src/js/economyJS.js
+++ b/src/js/economyJS.js
@@ -751,6 +751,9 @@ globalThis.calculateCosts = (function() {
 
 	function getPolicyCosts() {
 		let costs = 0;
+		if (V.policies.idealAge && (V.targetIdealAge !== V.idealAge)) {
+			costs += 1500;
+		}
 		if (V.policies.alwaysSubsidizeGrowth === 1) {
 			costs += policies.cost();
 		}
diff --git a/src/js/slaveCostJS.js b/src/js/slaveCostJS.js
index bb1999bf6eb4b2caf942022a87eeba2e471e1aae..d080e0bebeee1b20813dd850c3fa8a492a409a43 100644
--- a/src/js/slaveCostJS.js
+++ b/src/js/slaveCostJS.js
@@ -431,12 +431,12 @@ globalThis.BeautyArray = (function() {
 			adjustBeauty("Skilled: Slave Professionalism", ((arcology.FSSlaveProfessionalism / 50) * ((slave.skill.entertainment + slave.skill.whoring + slave.skill.oral + slave.skill.anal + slave.skill.vaginal) / 100))); /* 10 */
 		}
 		if (arcology.FSYouthPreferentialist !== "unset") {
-			if (V.retirementAge <= 60) {
-				adjustBeauty("Age: Youth Preferentialist", ((30 - slave.visualAge) / (30 - V.minimumSlaveAge) * ((arcology.FSYouthPreferentialist / 2) + (arcology.FSYouthPreferentialistLaw * 10)))); /* max 60 */
+			if(slave.visualAge < 30) {
+				adjustBeauty("Age: Youth Preferentialist", Math.clamp(((arcology.FSYouthPreferentialist / 2) + (arcology.FSYouthPreferentialistLaw * 10)) - Math.round(Math.abs(slave.visualAge - V.idealAge) * 2.222),0,60)); /* max 60 */
 			}
 		} else if (arcology.FSMaturityPreferentialist !== "unset") {
-			if (V.retirementAge.isBetween(30, 60, true)) {
-				adjustBeauty("Age: Maturity Preferentialist", ((30 - slave.visualAge) / (30 - V.retirementAge) * ((arcology.FSMaturityPreferentialist / 2) + (arcology.FSMaturityPreferentialistLaw * 10)))); /* max 60, problems if retirementAge is 30 or under */
+			if(slave.visualAge >= 30 && slave.visualAge < 60) {
+				adjustBeauty("Age: Maturity Preferentialist", Math.clamp(((arcology.FSMaturityPreferentialist / 2) + (arcology.FSMaturityPreferentialistLaw * 10)) - Math.round(Math.abs(slave.visualAge - V.idealAge) * 2.222),0,60)); /* max 60 */
 			}
 		}
 		if (arcology.FSBodyPurist > 20) {
@@ -500,7 +500,8 @@ globalThis.BeautyArray = (function() {
 		adjustBeauty(`Voice Pitch`, (slave.voice));
 		adjustBeauty(`Skill: Entertainment (${slave.skill.entertainment})`, (slave.skill.entertainment / 10));
 		adjustBeauty(`Skill: Whoring (${slave.skill.whoring})`, (slave.skill.whoring / 10));
-		adjustBeauty(`Age: Visual Age (${slave.visualAge})`, -(3 * slave.visualAge));
+		const ageBeautyPenaltyOffset = slave.visualAge - V.idealAge === 0 ? 0 : 9;
+		adjustBeauty(`Age: Visual Age (${slave.visualAge})`, -((3 * Math.abs(slave.visualAge - V.idealAge)) + ageBeautyPenaltyOffset));
 		if (App.Data.Careers.General.entertainment.includes(slave.career)) {
 			adjustBeauty("Career: Entertainment", (20));
 		} else if (V.week - slave.weekAcquired >= 20 && slave.skill.entertainment >= 100) {
diff --git a/src/npc/descriptions/descriptionWidgets.js b/src/npc/descriptions/descriptionWidgets.js
index 49d7996376f16bb95937030c682ecceac456bf0a..9afaef4b7424b581f3ebefa96144a163e6d38ceb 100644
--- a/src/npc/descriptions/descriptionWidgets.js
+++ b/src/npc/descriptions/descriptionWidgets.js
@@ -468,7 +468,25 @@ App.Desc.ageAndHealth = function(slave) {
 		}
 		age = slave.actualAge + 1;
 		r += ` ${He} `;
-		if (slave.birthWeek >= 52 && V.seeAge) {
+		if(slave.actualAge === V.idealAge || (slave.actualAge === V.idealAge - 1 && slave.birthWeek >= 52 && V.seeAge)) {
+			if(slave.birthWeek >= 52 && V.seeAge) {
+				r += `is going to turn ${age} this week`;
+				if (V.showAgeDetail && V.seeAge !== 0 && slave.actualAge !== V.idealAge) {
+					r += `, and people are looking forward to ${his} birthday with great interest.`;
+				} else {
+					r += `.`;
+				}
+			}
+			else if(!slave.birthWeek && V.seeAge) {
+				r += `just turned ${num(slave.actualAge)} this week, which many citizens find especially appealing.`;
+			}
+			else if (slave.birthWeek < 4 && V.seeAge) {
+				r += `only turned ${num(slave.actualAge)} this month. `;
+			} else {
+				r += `is ${num(slave.actualAge)} years old${birthday}. `;
+			}
+		}
+		else if (slave.birthWeek >= 52 && V.seeAge) {
 			r += `is going to turn ${age} this week,`;
 		} else if (slave.actualAge < 3) {
 			r += `is an infant, only `;
@@ -513,21 +531,9 @@ App.Desc.ageAndHealth = function(slave) {
 		} else if (slave.actualAge < 17) {
 			r += `is young and fresh at ${num(slave.actualAge)}${birthday}. `;
 		} else if (slave.actualAge < 18) {
-			r += `is young, fresh, and nearly 18${birthday}`;
-			if (V.showAgeDetail && V.seeAge !== 0) {
-				if (V.seeAge) {
-					r += ` and people are already beginning to eye ${him}`;
-				}
-			}
-			r += `. `;
+			r += `is young, fresh, and nearly 18${birthday}.`;
 		} else if (slave.actualAge < 19) {
-			if (!slave.birthWeek && V.seeAge) {
-				r += `just turned ${num(slave.actualAge)} this week, which many citizens find especially appealing. `;
-			} else if (slave.birthWeek < 4 && V.seeAge) {
-				r += `only turned ${num(slave.actualAge)} this month. `;
-			} else {
-				r += `is ${num(slave.actualAge)} years old${birthday}. `;
-			}
+			r += `is ${num(slave.actualAge)} years old${birthday}. `;
 		} else if (slave.actualAge < 20) {
 			r += `is in ${his} final year as a teenager at age 19${birthday}. `;
 		} else if (slave.actualAge < 26) {
diff --git a/src/npc/descriptions/longSlave.js b/src/npc/descriptions/longSlave.js
index 46a519fab8e814a16e6205867d1747ea5045f70c..a996c0e7265408bb25d351c59080969a609ac91e 100644
--- a/src/npc/descriptions/longSlave.js
+++ b/src/npc/descriptions/longSlave.js
@@ -293,6 +293,38 @@ App.Desc.longSlave = function(slave, {descType, market = 0, prisonCrime, noArt}
 		r.push(`bimbo by societal trends.`);
 	}
 
+	if(slave.visualAge === V.idealAge) {
+		if(slave.actualAge === V.idealAge) {
+			r.push(`${He} is ${slave.actualAge}, `);
+		} else {
+			r.push(`${He} appears to be ${slave.visualAge}, `);
+		}
+		if(V.idealAge === 18) {
+			r.push(`and many still find this age especially attractive due to old world tradition.`);
+		} else {
+			r.push(`and many in the arcology find this age especially attractive.`);
+		}
+	} else if (slave.visualAge !== slave.actualAge && slave.visualAge === V.idealAge - 1) {
+		r.push(`${He} appears to be ${slave.visualAge}, which is nearly the ideal, but as ${he} is actually ${slave.actualAge}, this can sometimes be cause for confusion regarding the appropriate level of enthusiasm society should have for ${him}.`);
+	} else if(slave.visualAge === V.idealAge - 1) {
+		if(slave.actualAge === V.idealAge - 1) {
+			r.push(`${He} is ${slave.actualAge}, `);
+		} else {
+			r.push(`${He} appears to be ${slave.visualAge}, `);
+		}
+		if(V.idealAge === 18) {
+			r.push(`and many are already looking forward to ${his} birthday with great anticipation due to old world tradition.`);
+		} else {
+			r.push(`and many in the arcology are already looking forward to ${his} birthday with great anticipation.`);
+		}
+	} else if(slave.actualAge === V.idealAge && slave.visualAge !== V.idealAge) {
+		r.push(`${He} is ${slave.actualAge}, a fact that many in the arcology find appealing `);
+		if(V.idealAge === 18) {
+			r.push(`because of old world tradition, `);
+		}
+		r.push(`but due to ${his} appearing to be ${slave.visualAge}, there is less enthusiasm for ${him} than there might otherwise be.`);
+	}
+
 	$(p).append(r.join(" "));
 
 	if (V.showScores !== 0) {