code:
:: Previous Child In Line

<<silently>>

<<set $i = $cribs.findIndex(function(c) { return c.ID === $activeChild.ID; })>>
<<set $cribs[$i] = $activeChild>> /* save changes before switching */
<<if $i == 0>>
	<<set $activeChild = $cribs[$cribs.length - 1]>>
	<<if $activeChild.actualAge < 3>>
		<<goto "Infant Interact">>
	<<else>>
		<<goto "Child Interact">>
	<</if>>
<<else>>
	<<set $activeChild = $cribs[$i-1]>>
	<<if $activeChild.actualAge < 3>>
		<<goto "Infant Interact">>
	<<else>>
		<<goto "Child Interact">>
	<</if>>
<</if>>

<</silently>>


code:
App.Facilities.Nursery.fChildOral = function fChildOral(child) {
	"use strict";

	let r = ``;

	actX(child, "oral");// TODO: will this counts towards the total count?

	// TODO: all of this

	return r;
};

App.Facilities.Nursery.fChildVaginal = function fChildVaginal(child) {
	"use strict";

	let r = ``;

	actX(child, "vaginal");// TODO: will this counts towards the total count?

	// TODO: all of this

	return r;
};

App.Facilities.Nursery.fChildAnal = function fChildAnal(child) {
	"use strict";

	let r = ``;

	actX(child, "anal");

	// TODO: all of this

	return r;
};

App.Facilities.Nursery.fChildImpreg = function fChildImpreg(child) {
	const bonus = jsRandom(6, 20);

	let r = ``;

	if (child.mpreg) {
		actX(child, "anal", (bonus + 1));
	} else {
		actX(child, "vaginal", (bonus + 1));
	}

	// TODO: all of this

	return r;
};

repo_name: Nithhogg/fc

license: mit


code:
/**
 * Displays a list of the children in the Nursery
 * @returns {DocumentFragment}
 */
App.Facilities.Nursery.childList = function childList() {
	let frag = document.createDocumentFragment();
	let r = [];

	if (V.nurseryChildren) {
		App.UI.DOM.appendNewElement("h3", frag, `Children in ${V.nurseryName}`, "indent");

		const list = App.UI.DOM.appendNewElement("p", frag, '', "indent");

		for (const child of getInfants().values()) {
			const weeksOwned = V.week - child.weekAcquired;
			const weeksLeft = (V.targetAgeNursery * 52) - weeksOwned;
			const {he, him, He} = getPronouns(child);

			list.appendChild(App.UI.sectionBreak());

			if (child.actualAge < 3) {
				$(list).append(App.UI.DOM.link(SlaveFullName(child), (id) => V.activeChild = getInfant(id), [child.ID], "Infant Interact"));
				$(list).append(App.Facilities.Nursery.InfantSummary(child));
			} else {
				$(list).append(App.UI.DOM.link(SlaveFullName(child), (id) => V.activeChild = getInfant(id), [child.ID], "Child Interact"));
				$(list).append(App.Facilities.Nursery.ChildSummary(child));
			}

			if (weeksLeft <= 0 || child.actualAge >= V.targetAgeNursery) {
				const targetText = child.targetLocation === "slavery" ? `Introduce ${him} to life as a slave` : `Set ${him} free`;

				list.appendChild(document.createElement("br"));

				r.push(` ${He} is ready to leave ${V.nurseryName} and ${child.targetLocation === "slavery" ? `join your ménage` : `become a free citizen`}.`);
				$(list).append(App.UI.DOM.passageLink(targetText, "Nursery Retrieval Workaround", () => {
					V.temp.AS = child.ID;
					deleteProps(child, "targetLocation");
					// TODO: FIXME: handle `targetLocation` in `App.UI.facilityRetrievalWorkaround("Nursery")` or remove it and all references to it completely from `InfantState`
					V.nurseryChildren--;
				}));
			} else {
				list.appendChild(document.createElement("br"));

				r.push(`${He} is to continue staying in ${V.nurseryName} for another ${years(child.growTime)}. ${He} is destined for ${child.targetLocation} once ${he} is of age.`);
			}

			$(list).append(r.join(' '));

			r = [];	// reset for next child
		}
	}

	return frag;
};

/**
 * Converts the infant object into a new child object
 * @param {object} child
 * @returns {object}
 */
App.Facilities.Nursery.infantToChild = function infantToChild(child) {
	child.boobShape = jsEither(["normal", "normal", "normal", "perky", "perky", "perky", "torpedo-shaped", "downward-facing", "wide-set"]);
	child.boobs = jsRandom(200, 500);
	child.butt = jsRandom(0, 3);
	child.clit = jsRandom(0, 2);
	child.devotion = 40;
	child.oldDevotion = 40;
	child.energy = 0;
	child.fertKnown = 1;
	child.fetishStrength = 0;
	child.hLength = jsRandom(30, 70);
	setHealth(child, jsRandom(80, 100), 0, 0, 0, 0);
	child.intelligence = 100;
	child.labia = jsRandom(0, 2);
	child.lips = jsRandom(10, 30);
	child.rules.living = "normal";
	child.muscles = jsRandom(-10, 10);
	if (child.boobs > 500 || child.weight > 95) {
		child.nipples = jsEither(["cute", "puffy", "partially inverted", "inverted", "tiny"]);
	} else {
		child.nipples = jsEither(["cute", "cute", "cute", "tiny"]);
	}
	child.origRace = child.race;
	if (child.eyeColor) {
		child.eye.origColor = child.eyeColor;
	}
	child.origSkin = child.skin;
	child.ovaries = child.genes === "XX" ? 1 : 0;
	child.ovaryAge = child.actualAge;
	child.physicalAge = child.actualAge;
	child.teeth = "baby";
	child.vagina = child.genes === "XX" ? 0 : -1;
	child.visualAge = child.actualAge;
	child.weight = jsRandom(-10, 10);
	resetEyeColor(child, "both");
	generatePronouns(child);
	child.height = Height.forAge(child.natural.height, child);

	return child;
};

/**
 * Allows the player to name the infant
 * FIXME: Does not currently work
 * @param {object} child
 * @returns {string}
 */
App.Facilities.Nursery.nameChild = function nameChild(child) {
	const PC = V.PC;
	const arcology = V.arcologies[0];
	const girl = child.genes === "XX" ? "girl" : "boy";

	let r = ``;
	/** @type {FC.Zeroable<FC.HumanState>} */
	let father = 0;
	/** @type {FC.Zeroable<FC.HumanState>} */
	let mother = 0;

	const {him, his, he} = getPronouns(child);

	if (child.father === SID.PC && child.mother === SID.PC) {
		father = PC;
		mother = PC;
	} else {
		if (child.father === SID.PC) {
			father = PC;
			mother = getSlave(child.mother);
		} else if (child.mother === SID.PC) {
			father = getSlave(child.father);
			mother = PC;
		} else {
			father = getSlave(child.father);
			mother = getSlave(child.mother);
		}
	}

	function newChildName(child) {
		child.birthName = generateName(child.nationality, child.race, child.genes === "XY");

		if (child.genes === "XY" && !V.allowMaleSlaveNames && isMaleName(child.birthName, child.nationality, child.race)) {
			child.slaveName = generateName(child.nationality, child.race, false);
		} else {
			child.slaveName = child.birthName;
		}
	}

	r += `You can name the new child, if you so desire. `;

	r += `<br><<textbox "${child.slaveName}" ${child.slaveName}>>`;
	r += App.UI.passageLink("Commit name", "Nursery Workaround", `${child.birthName = child.slaveName}, ${App.UI.replace("#naming", `You instruct ${V.assistant.name} to register the new ${girl} as "${child.slaveName}" in the slave registry.`)}`);
	r += `<br>`;
	r += App.UI.passageLink(`Have your PA assign ${him} a random name`, "Nursery Workaround", `${App.UI.replace("#naming", `${newChildName(child)}
${V.assistant.name} registers the new ${girl} as "${child.slaveName}" in your registry.`)}`);

	if (FutureSocieties.isActive('FSPastoralist', arcology)) {
		if (child.lactation > 0) {
			r += `

			<<link "Have your PA assign ${him} a random cow name">>
			<<replace "#naming">>`;
			child.slaveName = App.Data.misc.cowSlaveNames.random();
			child.birthName = child.slaveName;
			r += `${V.assistant.name} registers the new ${girl} as "${child.slaveName}" in your registry.
			<</replace>>
			<</link>>`;
		}
	}
	if (child.race === "catgirl") {
		r += `

		<<link "Have your PA assign ${him} a random cat name">>
		<<replace "#naming">>`;
		child.slaveName = App.Data.misc.catSlaveNames.random();
		child.birthName = child.slaveName;
		r += `${V.assistant.name} registers the new ${girl} as "${child.slaveName}" in your registry.
		<</replace>>
		<</link>>`;
	}
	if (FutureSocieties.isActive('FSChattelReligionist', arcology)) {
		r += `

		<<link "Have your PA assign ${him} a random devotional name">>
			<<replace "#naming">>`;
		child.slaveName = App.Data.misc.chattelReligionistSlaveNames.random();
		child.birthName = child.slaveName;
		r += `${V.assistant.name} registers the new ${girl} as "${child.slaveName}" in your registry.
			<</replace>>
		<</link>>`;
	}
	if (FutureSocieties.isActive('FSRomanRevivalist', arcology)) {
		r += `

		<<link "Have your PA assign ${him} a random Roman name">>
			<<replace "#naming">>`;
		child.slaveName = App.Data.misc.romanSlaveNames.random();
		child.birthName = child.slaveName;
		r += `${V.assistant.name} registers the new ${girl} as "${child.slaveName}" in your registry.
			<</replace>>
		<</link>>`;
	} else if (FutureSocieties.isActive('FSAztecRevivalist', arcology)) {
		r += `

		<<link "Have your PA assign ${him} a random Aztec name">>
			<<replace "#naming">>`;
		child.slaveName = App.Data.misc.aztecSlaveNames.random();
		child.birthName = child.slaveName;
		r += `${V.assistant.name} registers the new ${girl} as "${child.slaveName}" in your registry.
			<</replace>>
		<</link>>`;
	} else if (FutureSocieties.isActive('FSEgyptianRevivalist', arcology)) {
		r += `

		<<link "Have your PA assign ${him} a random ancient Egyptian name">>
			<<replace "#naming">>`;
		child.slaveName = App.Data.misc.ancientEgyptianSlaveNames.random();
		child.birthName = child.slaveName;
		r += `${V.assistant.name} registers the new ${girl} as "${child.slaveName}" in your registry.
			<</replace>>
		<</link>>`;
	} else if (FutureSocieties.isActive('FSEdoRevivalist', arcology)) {
		r += `

		<<link "Have your PA assign ${him} a random feudal Japanese name">>
			<<replace "#naming">>`;
		child.slaveName = App.Data.misc.edoSlaveNames.random();
		child.birthName = child.slaveName;
		r += `${V.assistant.name} registers the new ${girl} as "${child.slaveName}" in your registry.
			<</replace>>
		<</link>>`;
	}
	if (FutureSocieties.isActive('FSDegradationist', arcology)) {
		r += `

		<<link "Have your PA assign ${him} a degrading name">>
			<<replace "#naming">>`;
		DegradingName(child);
		child.birthName = child.slaveName;
		r += `${V.assistant.name} registers the new ${girl} as "${child.slaveName}" in your registry.
			<</replace>>
		<</link>>`;
	}
	if (mother !== PC && mother !== 0) {
		const {He2, he2, his2} = getPronouns(mother).appendSuffix('2');
		if (mother.ID === V.ConcubineID) {
			r += `

			<<link "Permit your Concubine to name ${his2} daughter">>
				<<replace "#naming">>`;
			parentNames(mother, child);
			child.birthName = child.slaveName;
			r += `After some careful consideration, ${mother.slaveName} picks a name ${he2} thinks you might find attractive; from now on ${his2} daughter will be known as "${child.slaveName}".
				<</replace>>
			<</link>>`;
		} else if (mother.relationship === -3 && mother.devotion >= -20) {
			r += `

			<<link "Permit your wife to name ${his2} daughter">>
				<<replace "#naming">>`;
			parentNames(mother, child);
			child.birthName = child.slaveName;
			r += `After some careful consideration, ${mother.slaveName} picks a name suitable for your daughter; from now on ${he2} will be known as "${child.slaveName}".
				<</replace>>
			<</link>>`;
		} else if (mother.ID === V.BodyguardID) {
			r += `

			<<link "Permit your bodyguard to name ${his2} daughter">>
				<<replace "#naming">>`;
			parentNames(mother, child);
			child.birthName = child.slaveName;
			r += `After some careful consideration, ${mother.slaveName} decides on "${child.slaveName}" for ${his2} daughter. ${He2} hopes you'll find it fitting ${his} station.
				<</replace>>
			<</link>>`;
		} else if (mother.ID === V.HeadGirlID) {
			r += `

			<<link "Permit your Head Girl to name ${his2} daughter">>
				<<replace "#naming">>`;
			parentNames(mother, child);
			child.birthName = child.slaveName;
			r += `After some careful consideration, ${mother.slaveName} decides on "${child.slaveName}" for ${his2} daughter, and hopes it will be a name your other slaves will learn to respect.
				<</replace>>
			<</link>>`;
		} else if (mother.devotion > 50 && mother.trust > 50) {
			r += `

			<<link "Permit ${his} devoted mother to name ${his2} daughter">>
				<<replace "#naming">>`;
			parentNames(mother, child);
			child.birthName = child.slaveName;
			r += `After some careful consideration, ${mother.slaveName} picks a name ${he2} hopes you'll like; from now on ${his2} daughter will be known as "${child.slaveName}".
				<</replace>>
			<</link>>`;
		}
	}
	if (father !== PC && father !== 0 && father !== mother) {
		const {He2, he2, his2} = getPronouns(father).appendSuffix('2');
		if (father.ID === V.ConcubineID) {
			r += `

			<<link "Permit your Concubine to name ${his2} daughter">>
				<<replace "#naming">>`;
			parentNames(father, child);
			child.birthName = child.slaveName;
			r += `After some careful consideration, ${father.slaveName} picks a name ${he2} thinks you might find attractive; from now on ${his2} daughter will be known as "${child.slaveName}".
				<</replace>>
			<</link>>`;
		} else if (father.relationship === -3 && father.devotion >= -20) {
			r += `

			<<link "Permit your wife to name ${his2} daughter">>
				<<replace "#naming">>`;
			parentNames(father, child);
			child.birthName = child.slaveName;
			r += `After some careful consideration, ${father.slaveName} picks a name suitable for your daughter; from now on ${he} will be known as "${child.slaveName}".
				<</replace>>
			<</link>>`;
		} else if (father.ID === V.BodyguardID) {
			r += `

			<<link "Permit your bodyguard to name ${his2} daughter">>
				<<replace "#naming">>`;
			parentNames(father, child);
			child.birthName = child.slaveName;
			r += `After some careful consideration, ${father.slaveName} decides on "${child.slaveName}" for ${his2} daughter. ${He2} hopes you'll find it fitting ${his} station.
				<</replace>>
			<</link>>`;
		} else if (father.ID === V.HeadGirlID) {
			r += `

			<<link "Permit your Head Girl to name ${his2} daughter">>
				<<replace "#naming">>`;
			parentNames(father, child);
			child.birthName = child.slaveName;
			r += `After some careful consideration, ${father.slaveName} decides on "${child.slaveName}" for ${his2} daughter, and hopes it will be a name your other slaves will learn to respect.
				<</replace>>
			<</link>>`;
		} else if (father.devotion > 50 && father.trust > 50) {
			r += `

			<<link "Permit ${his} devoted father to name ${his2} daughter">>
				<<replace "#naming">>`;
			parentNames(father, child);
			child.birthName = child.slaveName;
			r += `After some careful consideration, ${father.slaveName} picks a name ${he2} hopes you'll like; from now on ${his2} daughter will be known as "${child.slaveName}".
				<</replace>>
			<</link>>`;
		}
	}

	return r;
};

/**
 * Adds an infant to the cribs
 * @param {FC.InfantState} child
 */
App.Facilities.Nursery.newChild = function newChild(child) {
	child.ID = generateSlaveID();

	child.actualAge = 0;
	child.ovaryAge = 0;
	child.physicalAge = 0;
	child.visualAge = 0;
	child.birthWeek = 0;

	if (child.overrideRace !== 1) {
		child.origRace = child.race;
	}

	if (child.overrideHColor !== 1) {
		child.hColor = getGeneticHairColor(child);
	}
	if (child.overrideArmHColor !== 1) {
		child.underArmHColor = getGeneticHairColor(child);
	}
	if (child.overridePubicHColor !== 1) {
		child.pubicHColor = getGeneticHairColor(child);
	}
	if (child.overrideBrowHColor !== 1) {
		child.eyebrowHColor = getGeneticHairColor(child);
	}
	if (child.overrideSkin !== 1) {
		child.origSkin = getGeneticSkinColor(child);
	}
	child.overrideRace = 0;
	child.overrideHColor = 0;
	child.overrideArmHColor = 0;
	child.overridePubicHColor = 0;
	child.overrideBrowHColor = 0;
	child.overrideSkin = 0;
	child.overrideEyeColor = 0;

	child.arm = {
		left: new App.Entity.ArmState(),
		right: new App.Entity.ArmState()
	};
	child.leg = {
		left: new App.Entity.LegState(),
		right: new App.Entity.LegState()
	};

	if (V.surnamesForbidden === 1) {
		child.slaveSurname = 0;
	}

	if (child.clone !== 0) {
		child.canRecruit = 0;
	}
	generatePronouns(child);
	const {He} = getPronouns(child);
	child.origin = `${He} was born and raised in your arcology. `;
	child.targetLocation = "slavery";
	child.growTime = V.targetAgeNursery * 52;
	addInfant(child);
	V.nurseryChildren++;
};

/**
 * Displays a list of slaves with children eligible for the Nursery
 * FIXME: Does not currently work
 * @returns {string}
 */
App.Facilities.Nursery.nurserySort = function nurserySort() {
	const PC = V.PC;
	const arcology = V.arcologies[0];
	const freeCribs = (V.nurseryCribs - infantCount());

	let r = ``;
	let eligibility = 0;
	let sortNurseryList = V.sortNurseryList || "Unsorted";
	let nurseryHasReservedChildren = false;
	let reservedChildrenNursery = FetusGlobalReserveCount("nursery");

	r += `<br><i>Sorting:</i> <b><span id="ql-nursery-sort">${sortNurseryList}.</span></b> `;
	r += `${App.UI.passageLink("Sort by Name", "Nursery", `${sortNurseryList = "Name"}, ${App.UI.replace(`#ql-nursery-sort`, sortNurseryList)}, ${byName()}`)} | `;
	r += `${App.UI.passageLink("Sort by Reserved Nursery Spots", "Nursery", `${sortNurseryList = "Reserved Nursery Spots"}, ${App.UI.replace(`#ql-nursery-sort`, sortNurseryList)}, ${byReservedSpots()}`)} | `;
	r += `${App.UI.passageLink("Sort by Pregnancy Week", "Nursery", `${sortNurseryList = "Pregnancy Week"}, ${App.UI.replace(`#ql-nursery-sort`, sortNurseryList)}, ${byPregnancyWeek()}`)} | `;
	r += `${App.UI.passageLink("Sort by Number of Children", "Nursery", `${sortNurseryList = "Number of Children"}, ${App.UI.replace(`#ql-nursery-sort`, sortNurseryList)}, ${byPregnancyCount()}`)}`;
	r += `<br>`;

	r += `<div id="ql-nursery">`;

	for (const slave of getSlaves().values()) {
		const {His, his} = getPronouns(slave);

		if (slave.preg > 0 && !slave.broodmother && slave.pregKnown && slave.eggType === "human") {
			if (slave.assignment !== Job.DAIRY && V.dairyPregSetting <= 0) {
				const slaveID = "slave-" + slave.ID;
				const WL = slave.womb.length;
				const reservedNursery = WombReserveCount(slave, "nursery");
				const reservedIncubator = WombReserveCount(slave, "incubator");
				const pregWeek = slave.pregWeek;
				const slaveName = SlaveFullName(slave);

				r += `<div class="possible" @id="${slaveID}" @data-preg-count="${WL}" @data-reserved-spots="${reservedNursery}" @data-preg-week="${pregWeek}" @data-name="${slaveName}">`;

				r += `${App.UI.SlaveDescriptionDialog(slave)} is ${pregWeek} weeks pregnant with `;

				switch (slave.pregSource) {
					case SID.GENERIC:
						r += `someone's${slave.preg <= 5 ? `, though it is too early to tell whose,` : ``}`;
						break;
					case SID.PC:
						r += `your`;
						break;
					case SID.CITIZEN:
						r += `a citizen's`;
						break;
					case SID.FORMERMASTER:
						r += `your Master's`;
						break;
					case SID.ARCOWNER:
						r += `another arcology owner's`;
						break;
					case SID.CLIENT:
						r += `your client's`;
						break;
					case SID.ELITE:
						r += `the Societal Elite's`;
						break;
					case SID.LAB:
						r += `the lab's`;
						break;
					case SID.FUTA:
						r += `the Futanari Sister's`;
						break;
					case SID.RAPIST:
						r += `your rapist`;
						break;
					default:
						if (slave.preg <= 5) {
							r += `someone's, though it is too early to tell whose,`;
						} else {
							let source = getSlave(slave.pregSource);
							if (source !== undefined) {
								r += `${source.slaveName}'s`;
							}
						}
						break;
				}
				r += ` ${WL > 1 ? `babies` : `baby`}. `;

				if (reservedNursery > 0) {
					nurseryHasReservedChildren = true;
					if (WL === 1) {
						r += `${His} child will be placed in ${V.nurseryName}. `;
					} else if (reservedNursery < WL) {
						r += `${reservedNursery} of ${his} children will be placed in ${V.nurseryName}. `;
					} else if (WL === 2) {
						r += `Both of ${his} children will be placed in ${V.nurseryName}. `;
					} else {
						r += `All ${reservedNursery} of ${his} children will be placed in ${V.nurseryName}. `;
					}

					if ((reservedIncubator + reservedNursery < WL) && (reservedChildrenNursery < freeCribs)) {
						r += `<br>    `;
						r += App.UI.passageLink("Keep another child", "Nursery", `${WombAddToGenericReserve(slave, "nursery", 1)}`);
						if (reservedNursery > 0) {
							r += ` | ${App.UI.passageLink("Keep one less child", "Nursery", `${WombCleanGenericReserve(slave, "nursery", 1)}`)}`;
						}
						if (reservedNursery > 1) {
							r += ` | ${App.UI.passageLink(`Keep none of ${his} children`, "Nursery", `${WombCleanGenericReserve(slave, "nursery", 9999)}`)}`;
						}
						if (reservedChildrenNursery + WL - reservedNursery <= freeCribs) {
							r += ` | ${App.UI.passageLink(`Keep the rest of ${his} children`, "Nursery", `${WombAddToGenericReserve(slave, "nursery", 9999)}`)}`;
						}
					} else if (reservedNursery === WL || reservedChildrenNursery === freeCribs || reservedIncubator + reservedNursery === WL) {
						r += `<br>    `;
						r += App.UI.passageLink("Keep one less child", "Nursery", `${WombCleanGenericReserve(slave, "nursery", 1)}`);
						if (reservedNursery > 1) {
							r += ` | ${App.UI.passageLink(`Keep none of ${his} children`, "Nursery", `${WombCleanGenericReserve(slave, "nursery", 9999)}`)}`;
						}
					}
				} else if (reservedChildrenNursery < freeCribs && freeCribs > WL) {
					if (WL - reservedIncubator === 0) {
						r += `<i>${His} children are already reserved for ${V.incubator.name}</i>`;
						r += `<br>    `;
						r += App.UI.passageLink(`Keep ${his} child${WL > 1 ? `ren` : ``} here instead`, "Nursery", `${WombAddToGenericReserve(slave, "nursery", 1)}`);
					} else {
						r += `You have ${freeCribs === 1 ? `an ` : ``}available room${freeCribs > 1 ? `s` : ``}. `;
						r += `<br>    `;
						r += App.UI.passageLink(`Keep ${WL > 1 ? `a` : `the`} child`, "Nursery", `${WombAddToGenericReserve(slave, "nursery", 1)}`);
						if (WL > 1 && (reservedChildrenNursery + WL - reservedNursery <= freeCribs)) {
							r += ` | ${App.UI.passageLink(`Keep all of ${his} children`, "Nursery", `${WombAddToGenericReserve(slave, "nursery", 9999)}`)}`;
						}
					}
				} else if (reservedChildrenNursery === freeCribs) {
					r += `<br>    `;
					r += `You have <span class="red">no room for ${his} offspring.</span> `;
				}

				eligibility = 1;
				r += `</div>`;
			}
		}
	}

	r += `</div>`;

	$('div#ql-nursery').ready(byPreviousSort);

	if (!eligibility) {
		r += `<br>`;
		r += `<i>You have no pregnant slave bearing eligible children</i>`;
	}

	if (PC.pregKnown && (!FutureSocieties.isActive('FSRestart', arcology) || V.eugenicsFullControl || (PC.pregSource !== SID.PC && PC.pregSource !== SID.ELITE))) {
		const WL = PC.womb.length;

		let reservedIncubator = WombReserveCount(PC, "incubator");
		let reservedNursery = WombReserveCount(PC, "nursery");

		r += `<br><b><span class="pink">You're pregnant</span></b> and going to have ${WL === 1 ? `a baby. ` : pregNumberName(WL, 1)} `;

		if (reservedNursery > 0) {
			nurseryHasReservedChildren = true;
			if (WL === 1) {
				r += `Your child will be placed in ${V.nurseryName}.`;
			} else if (reservedNursery < WL) {
				r += `${reservedNursery} of your children will be placed in ${V.nurseryName}.`;
			} else if (WL === 2) {
				r += `Both of your children will be placed in ${V.nurseryName}.`;
			} else {
				r += `All ${reservedNursery} of your children will be placed in ${V.nurseryName}.`;
			}

			if (reservedNursery < WL && reservedChildrenNursery < freeCribs && reservedNursery - reservedIncubator > 0) {
				r += `<br>    `;
				r += App.UI.passageLink("Keep another child", "Nursery", `${reservedNursery += 1}, ${reservedChildrenNursery += 1}`);
				if (reservedNursery > 0) {
					r += ` | ${App.UI.passageLink("Keep one less child", "Nursery", `${reservedNursery -= 1}, ${reservedChildrenNursery -= 1}`)}`;
				}

				if (reservedNursery > 1) {
					r += ` | ${App.UI.passageLink("Keep none of your children", "Nursery", `${reservedChildrenNursery -= reservedNursery}, ${reservedChildrenNursery = 0}`)}`;
				}

				if (reservedChildrenNursery + WL - reservedNursery <= freeCribs) {
					r += ` | ${App.UI.passageLink("Keep the rest of your children", "Nursery", `${reservedChildrenNursery += (WL - reservedNursery)}, ${reservedNursery += (WL - reservedNursery)}`)}`;
				}
			} else if (reservedNursery === WL || reservedChildrenNursery === freeCribs || reservedNursery - reservedIncubator >= 0) {
				r += `<br>    `;
				r += App.UI.passageLink("Keep one less child", "Nursery", `${reservedNursery -= 1}, ${reservedChildrenNursery -= 1}`);
				if (reservedNursery > 1) {
					r += App.UI.passageLink("Keep none of your children", "Nursery", `${reservedChildrenNursery -= reservedNursery}, ${reservedNursery = 0}`);
				}
			}
		} else if (reservedChildrenNursery < freeCribs) {
			if (WL - reservedIncubator === 0) {
				r += `<i>Your child${WL > 1 ? `ren are` : ` is`} already reserved for ${V.incubator.name}</i>`;
				r += App.UI.passageLink(`Keep your child${WL > 1 ? `ren` : ``} here instead`, "Nursery", `${reservedNursery += WL}, ${reservedIncubator = 0}`);
			} else {
				r += `You have ${freeCribs === 1 ? `an ` : ``}available room${freeCribs > 1 ? `s` : ``}. `;
				r += `<br>    `;
				r += App.UI.passageLink(`Keep ${WL > 1 ? `a` : `your`} child`, "Nursery", `${reservedNursery += 1}, ${reservedChildrenNursery += 1}`);
				if (WL > 1 && (reservedChildrenNursery + WL - reservedNursery <= freeCribs)) {
					r += ` | ${App.UI.passageLink("Keep all of your children", "Nursery", `${reservedChildrenNursery += WL}, ${reservedNursery += WL}`)}`;
				}
			}
		} else if (reservedChildrenNursery === freeCribs) {
			r += `<br>    `;
			r += `You have <span class="red">no room for your offspring.</span> `;
		}
	}

	if (reservedChildrenNursery || nurseryHasReservedChildren) {
		r += `<br>`;
		r += App.UI.passageLink("Clear all reserved children", "Nursery", `${getSlaves().forEach((slave) => WombCleanGenericReserve(slave, "nursery", 9999))}, ${WombCleanGenericReserve(PC, "nursery", 9999)}`);
	}

	function byName() {
		let sortedNurseryPossibles = $('#ql-nursery div.possible').detach();
		sortedNurseryPossibles = sortDomObjects(sortedNurseryPossibles, 'data-name');
		$(sortedNurseryPossibles).appendTo($('#ql-nursery'));
	}

	function byReservedSpots() {
		let sortedNurseryPossibles = $('#ql-nursery div.possible').detach();
		sortedNurseryPossibles = sortDomObjects(sortedNurseryPossibles, 'data-reserved-spots');
		$(sortedNurseryPossibles).appendTo($('#ql-nursery'));
	}

	function byPregnancyWeek() {
		let sortedNurseryPossibles = $('#ql-nursery div.possible').detach();
		sortedNurseryPossibles = sortDomObjects(sortedNurseryPossibles, 'data-preg-week');
		$(sortedNurseryPossibles).appendTo($('#ql-nursery'));
	}

	function byPregnancyCount() {
		let sortedNurseryPossibles = $('#ql-nursery div.possible').detach();
		sortedNurseryPossibles = sortDomObjects(sortedNurseryPossibles, 'data-preg-count');
		$(sortedNurseryPossibles).appendTo($('#ql-nursery'));
	}

	function byPreviousSort() {
		let sort = V.sortNurseryList;
		if (sort !== 'unsorted') {
			if (sort === 'Name') {
				sortNurseryPossiblesByName();
			} else if (sort === 'Reserved Nursery Spots') {
				sortNurseryPossiblesByReservedSpots();
			} else if (sort === 'Pregnancy Week') {
				sortNurseryPossiblesByPregnancyWeek();
			} else if (sort === 'Number of Children') {
				sortNurseryPossiblesByPregnancyCount();
			}
		}
	}

	return r;
};


code:
App.UI.organFarm = function() {
	const node = new DocumentFragment();
	const PCSkillCheck = Math.min(V.upgradeMultiplierMedicine, V.HackingSkillMultiplier);

	App.UI.DOM.appendNewElement("h1", node, "The Organ Farm");

	const status = {
		1: "The organ farm is running smoothly. It can grow tailored organs for implantation in slaves. It can easily produce altered variants should you obtain the data necessary to create them.",
		2: "The organ farm is running smoothly. It can quickly grow tailored organs for implantation in slaves, though there will be side-effects. It can easily produce altered variants should you obtain the data necessary to create them.",
		3: "The organ farm is running smoothly. It can rapidly grow tailored organs for implantation in slaves. It can easily produce altered variants should you obtain the data necessary to create them."
	};

	App.UI.DOM.appendNewElement('div', node, App.Ratings.numeric(status, V.organFarmUpgrade), ['scene-intro']);

	/**
	 * @param {string} note
	 * @param {ParentNode} parentNode
	 */
	const appendNote = (note, parentNode) => {
		App.UI.DOM.appendNewElement("div", parentNode, note, "note");
	};

	/**
	 * @param {string} message
	 * @param {ParentNode} [parentNode]
	 */
	const upgradeImpossible = (message, parentNode) => {
		appendNote(message, parentNode ?? node);
	};

	/**
	 * @param {ParentNode} node
	 * @param {number} reputationReqBase
	 * @param {string} label
	 * @param {string[]} notes
	 * @param {number} costsBase
	 * @param {function(): void} handler
	 * @param {string} lackRepSubject
	 */
	const upgradeOption = (node, reputationReqBase, label, notes, costsBase, handler, lackRepSubject = '') => {
		if (V.rep < reputationReqBase * PCSkillCheck) {
			upgradeImpossible(`You lack the reputation to ${lackRepSubject}.`, node);
		} else {
			node.appendChild(makePurchase(label, costsBase * PCSkillCheck, "capEx", {
				notes,
				handler,
			}));
		}
	};

	if (V.organFarmUpgrade < 3 && V.rep <= 10000 * PCSkillCheck) {
		upgradeImpossible("You lack the reputation to access experimental organ farm parts.");
	} else if (V.dispensary === 0 && V.organFarmUpgrade === 2) {
		upgradeImpossible("An upgraded pharmaceutical fabricator is required by the perfected organ farm.");
	} else if (V.dispensary === 0 && V.organFarmUpgrade === 1) {
		upgradeImpossible("A pharmaceutical fabricator is required to produce the chemicals for the accelerated organ farm.");
	} else if (V.dispensaryUpgrade === 0 && V.organFarmUpgrade === 2) {
		upgradeImpossible("The pharmaceutical fabricator must be upgraded in order to produce the drugs required by the perfected organ farm.");
	} else if (V.organs.length > 0) {
		upgradeImpossible("The organ farm cannot be upgraded while it is use.");
	} else if (V.rep > 10000 * PCSkillCheck) {
		if (V.organFarmUpgrade === 2) {
			upgradeOption(node, 10_000, "Upgrade the organ farm to the cutting edge model",
				["will allow the organ farm to rapidly grow organs without risk to the implantee's health."],
				150_000, () => { V.organFarmUpgrade = 3; },
				""
			);
		} else if (V.organFarmUpgrade === 1) {
			upgradeOption(node, 10_000, "Upgrade the organ farm with an experimental growth accelerator",
				["will allow the organ farm to quickly grow organs. Implanted organs may cause health issues."],
				75_000, () => { V.organFarmUpgrade = 2; },
				""
			);
		}
	}

	if (V.youngerOvaries > 0) {
		App.UI.DOM.appendNewElement("div", node, "The organ farm is capable of growing fertile ovaries for postmenopausal slaves.");
	} else {
		upgradeOption(node, 10_000, "Purchase designs for cloning fertile ovaries for menopausal slaves",
			["will allow the growth of younger, fertile ovaries for menopausal slaves. Restored fertility will only last for a couple years at most."],
			30_000, () => { V.youngerOvaries = 1; },
			"access designs for cloning fertile ovaries for menopausal slaves"
		);
	}

	if (V.immortalOvaries > 0) {
		App.UI.DOM.appendNewElement("div", node, "The organ farm is capable of growing genetically modified ovaries that will never undergo menopause.");
	} else if (V.immortalityFormula > 0 && V.youngerOvaries > 0) {
		upgradeOption(node, 10_000, "Fund research into applying the immortality formula to ovaries",
			["will allow the growth of genetically modified ovaries that continually regenerate their ovarian follicles, thus never undergoing menopause. As long as the body remains young, it shall remain fertile."],
			1_000_000, () => { V.immortalOvaries = 1; },
			"fund additional fertility-focused research into the immortality project"
		);
	} else if (V.immortalityFormula > 0) {
		appendNote("You must acquire the designs to clone younger ovaries before you can research ovary immortality.", node);
	} // invisible without immortality formula

	if (V.asexualReproduction === 1) {
		App.UI.DOM.appendNewElement("div", node, "The organ farm is capable of growing modified ovary pairs capable of self-fertilization.");
	}

	if (V.seePreg !== 0 && V.seeBestiality === 1 && V.experimental.animalOvaries === 1) {
		if (V.animalOvaries < 1) {
			appendNote("You lack the required designs for cloning animal ovaries for slaves.", node);
		} else {
			App.UI.DOM.appendNewElement('div', node, "The organ farm is capable of growing animal ovaries for slaves.");
		}

		if (V.animalTesticles < 1) {
			appendNote("You lack the required designs for cloning animal testicles for slaves.", node);
		} else {
			App.UI.DOM.appendNewElement("div", node, "The organ farm is capable of growing animal testicles for slaves.");
		}

		if (V.arcologies[0].FSGenderRadicalistResearch === 1) {
			if (V.animalMpreg < 1) {
				appendNote("You lack the required designs for cloning animal anal wombs and ovaries for slaves.", node);
			} else {
				App.UI.DOM.appendNewElement("div", node, "The organ farm is capable of growing animal anal wombs and ovaries for slaves.");
			}
		}
	}

	App.UI.DOM.appendNewElement("h2", node, "Organ Production");
	App.UI.DOM.appendNewElement("p", node, App.Medicine.OrganFarm.currentlyGrowing());

	App.UI.DOM.appendNewElement("h2", node, "Future Societies Research");

	if (V.seePreg !== 0) {
		if (V.arcologies[0].FSGenderRadicalistDecoration === 100) {
			if (V.arcologies[0].FSGenderRadicalistResearch === 0) {
				upgradeOption(node, 10_000, "Fund research into developing male pregnancy methods",
					["will allow cloning and production of anal uteri and ovaries."],
					50_000, () => { V.arcologies[0].FSGenderRadicalistResearch = 1; },
					"access the research necessary to develop anal uteri and ovaries"
				);
			} else {
				App.UI.DOM.appendNewElement("div", node, "The organ farm has been upgraded with schematics for modified uteri and ovaries.");
			}
		} else {
			appendNote("Gender Radicalist focused research unavailable.", node);
		}
	}
	return node;
};


code:
App.Facilities.HGSelect = function() {
	let div = document.createElement("div");
	const f = document.createDocumentFragment();
	let r = [];
	let links = [];

	App.UI.DOM.appendNewElement("h1", f, "Head Girl Management");

	if (S.HeadGirl) {
		const HGName = SlaveFullName(S.HeadGirl);
		const {
			His, He, he,
			his, him, himself
		} = getPronouns(S.HeadGirl);

		f.append(`${SlaveFullName(S.HeadGirl)} is working as your HeadGirl`);
		if (V.arcologies[0].FSEgyptianRevivalistLaw === 1) {
			f.append(`/Consort; serving and providing comfort, in addition to performing normal Head Girl duties`);
		}
		f.append(`. `);
		if (V.HGSuite) {
			f.append(`Currently living in ${capFirstChar(V.HGSuiteName)}. `);
		}
		f.append(App.UI.DOM.link("Remove HeadGirl", () => {
			removeJob(S.HeadGirl, Job.HEADGIRL);
		},
		[], "Main"
		));

		App.UI.DOM.appendNewElement("h2", f, `Slave training`);
		App.UI.DOM.appendNewElement("div", f, `${HGName} will prioritize enabled items in the following order`, "note");

		div.append(App.UI.DOM.makeCheckbox("headGirlTrainsHealth"), " Health");
		App.UI.DOM.appendNewElement("div", f, div, "indent");

		div = document.createElement("div");
		div.append(App.UI.DOM.makeCheckbox("headGirlTrainsParaphilias"), " Paraphilias");
		App.UI.DOM.appendNewElement("div", f, div, "indent");

		if (V.headGirlTrainsFlaws) {
			r.push(`${HGName} will remove flaws.`,);
		} else if (V.headGirlSoftensFlaws) {
			r.push(`${HGName} will soften flaws into quirks.`);
		} else if (V.headGirlOverridesQuirks) {
			r.push(`${HGName} will override quirks.`);
		} else {
			r.push(`${HGName} will ignore flaws.`);
		}

		links.push(App.UI.DOM.link("Override quirks", () => {
			V.headGirlTrainsFlaws = 0;
			V.headGirlSoftensFlaws = 0;
			V.headGirlOverridesQuirks = 1;
			App.UI.reload();
		}));
		links.push(App.UI.DOM.link("Soften flaws", () => {
			V.headGirlTrainsFlaws = 0;
			V.headGirlSoftensFlaws = 1;
			V.headGirlOverridesQuirks = 0;
			App.UI.reload();
		}));
		links.push(App.UI.DOM.link("Remove flaws", () => {
			V.headGirlTrainsFlaws = 1;
			V.headGirlSoftensFlaws = 0;
			V.headGirlOverridesQuirks = 0;
			App.UI.reload();
		}));

		links.push(App.UI.DOM.link("Ignore flaws", () => {
			V.headGirlTrainsFlaws = 0;
			V.headGirlSoftensFlaws = 0;
			V.headGirlOverridesQuirks = 0;
			App.UI.reload();
		}));

		r.push(App.UI.DOM.generateLinksStrip(links));
		App.Events.addNode(f, r, "div", "indent");

		div = document.createElement("div");
		div.append(App.UI.DOM.makeCheckbox("headGirlTrainsObedience"), " Obedience");
		App.UI.DOM.appendNewElement("div", f, div, "indent");

		div = document.createElement("div");
		div.append(App.UI.DOM.makeCheckbox("headGirlTrainsSkills"), " Skills");
		App.UI.DOM.appendNewElement("div", f, div, "indent");

		App.UI.DOM.appendNewElement("h2", f, "Training methods");

		r = [];
		if (V.HGSeverity === 1) {
			r.push(`${HGName} will be <span class="bold">aggressive</span> when punishing, with rape strongly encouraged.`);
			r.push(App.UI.DOM.link("Moderate", () => {
				V.HGSeverity = 0;
				App.UI.reload();
			}));
		} else if (V.HGSeverity === 0) {
			links = [];
			r.push(`${HGName} will be <span class="bold">moderate</span> when punishing, carefully selecting appropriate consequences.`);
			links.push(App.UI.DOM.link("Be aggressive", () => {
				V.HGSeverity = 1;
				App.UI.reload();
			}));
			links.push(App.UI.DOM.link(`Apply restrictions`, () => {
				V.HGSeverity = -1;
				App.UI.reload();
			}));
			r.push(App.UI.DOM.generateLinksStrip(links));
		} else if (V.HGSeverity === -1) {
			r.push(`${HGName} will be <span class="bold">respectful</span> when punishing, treating slaves decently.`);
			r.push(App.UI.DOM.link("Be stricter", () => {
				V.HGSeverity = 0;
				App.UI.reload();
			}));
		}
		App.Events.addNode(f, r, "div", "indent");

		r = [];
		if (V.HGPiercings === 1) {
			r.push(`${HGName} is <span class="bold">allowed</span> to use piercings as a tool to improve slaves' attitudes.`);
			r.push(App.UI.DOM.link("Disallow", () => {
				V.HGPiercings = 0;
				App.UI.reload();
			}));
		} else {
			r.push(`${HGName} is <span class="bold">not allowed</span> to use piercings as a tool to improve slaves' attitudes.`);
			r.push(App.UI.DOM.link("Allow", () => {
				V.HGPiercings = 1;
				App.UI.reload();
			}));
		}
		App.Events.addNode(f, r, "div", "indent");

		r = [];
		App.UI.DOM.appendNewElement("h2", f, "Behavior");
		if (V.HGFormality === 1) {
			r.push(`${HGName} will be <span class="bold">formal:</span> you will always be called ${getWrittenTitle(S.HeadGirl)}, just like any other slave.`);
			r.push(App.UI.DOM.link("Allow private informality", () => {
				V.HGFormality = 0;
				App.UI.reload();
			}));
		} else {
			r.push(`${HGName} is allowed to be <span class="bold">informal:</span> in private, you can be called ${properTitle()}.`);
			r.push(App.UI.DOM.link("Maintain complete formality", () => {
				V.HGFormality = 1;
				App.UI.reload();
			}));
		}
		App.Events.addNode(f, r, "div", "indent");

		r = [];
		if (V.seePreg !== 0) {
			if (V.universalRulesImpregnation === "HG") {
				App.UI.DOM.appendNewElement("div", f, `${HGName} is responsible for impregnating fertile slaves.`);
				if (canPenetrate(S.HeadGirl) && S.HeadGirl.pubertyXY === 1) {
					App.UI.DOM.appendNewElement("div", f, `To maximize the chances of impregnation, ${he} will fuck fertile pussies frequently during the week. ${S.HeadGirl.slaveName} can service ${resetHGCum(S.HeadGirl)} slaves this way.`);
					if (S.HeadGirl.devotion > 95) {
						App.UI.DOM.appendNewElement("div", f, `${He} loves you so much ${he}'ll fuck them until ${he}'s sore.`);
					} else {
						App.UI.DOM.appendNewElement("div", f, `If ${he} were more devoted to you, ${he} might be able to drive ${himself} to get hard and service one more.`);
					}
					if (S.HeadGirl.balls >= 120) {
						App.UI.DOM.appendNewElement("div", f, `${His} unreal balls produce nearly an endless supply of semen; ${his} ability to impregnate is almost limitless.`);
					} else if (S.HeadGirl.balls >= 80) {
						App.UI.DOM.appendNewElement("div", f, `${His} inhuman balls produce so much semen ${he} can easily impregnate twenty girls in one sitting.`);
					} else if (S.HeadGirl.balls >= 50) {
						App.UI.DOM.appendNewElement("div", f, `${His} giant balls produce so much semen ${he} can easily impregnate twelve girls in one sitting.`);
					} else if (S.HeadGirl.balls >= 25) {
						App.UI.DOM.appendNewElement("div", f, `${His} oversized balls produce so much semen ${he} can cum repeatedly in a single session.`);
					} else if (S.HeadGirl.balls >= 5) {
						App.UI.DOM.appendNewElement("div", f, `${His} big balls produce so much semen ${he} can cum more before ${he}'s drained.`);
					} else {
						App.UI.DOM.appendNewElement("div", f, `Bigger balls would let ${him} cum more before ${he}'s drained.`);
					}
					if (S.HeadGirl.health.condition > 95) {
						App.UI.DOM.appendNewElement("div", f, `${His} wonderful health lets ${him} get hard and stay hard all the time.`);
					} else {
						App.UI.DOM.appendNewElement("div", f, `If ${his} health were perfect, ${he} might be able to get hard more often.`);
					}
					if (S.HeadGirl.energy > 95) {
						App.UI.DOM.appendNewElement("div", f, `${His} nymphomania drives ${him} to go above and beyond in this.`);
					} else {
						App.UI.DOM.appendNewElement("div", f, `A more powerful sex drive could reduce ${his} refractory period.`);
					}
				} else {
					App.UI.DOM.appendNewElement("div", f, `However, ${S.HeadGirl.slaveName} cannot perform this duty.`);
				}
				r.push(App.UI.DOM.link(`Rescind ${his} impregnation responsibility`, () => {
					V.universalRulesImpregnation = "none";
					App.UI.reload();
				}));
				r.push(App.UI.DOM.link(`See to it yourself`, () => {
					V.universalRulesImpregnation = "PC";
					App.UI.reload();
				}));
				f.append(' ', App.UI.DOM.generateLinksStrip(r));
			} else {
				if (canPenetrate(S.HeadGirl) && S.HeadGirl.pubertyXY === 1) {
					App.UI.DOM.appendNewElement("div", f, `${HGName} is capable of impregnating slaves, but it's not part of ${his} responsibilities. `).append(
						App.UI.DOM.link(`Assign ${him} to impregnate`, () => {
							V.universalRulesImpregnation = "HG";
							App.UI.reload();
						}));
				}
			}
		}
	} else {
		f.append(`No HeadGirl assigned, appoint one from your devoted slaves.`);
	}

	f.append(App.UI.SlaveList.facilityManagerSelection(App.Entity.facilities.headGirlSuite, "Head Girl Select"));
	return f;
};


code:
/**
 * Builds the Recruiter Management UI
 * @returns {DocumentFragment}
 */
App.Facilities.RecruiterSelect = function() {
	const f = document.createDocumentFragment();
	const recruiterCap = document.createDocumentFragment();
	let specializations = document.createElement("div");
	let r = [];

	App.UI.DOM.appendNewElement("h1", f, "Recruiter Management");
	if (S.Recruiter) {
		const {He, he, his} = getPronouns(S.Recruiter);

		// Recruiter target
		App.UI.DOM.appendNewElement("span", f, `${SlaveFullName(S.Recruiter)} is working as your Recruiter, currently ${V.recruiterTarget !== "other arcologies" ? 'recruiting girls. ' : 'acting as a sexual Ambassador'}`);
		if (V.recruiterTarget === "other arcologies") {
			const externalArcology = V.arcologies.find(s => s.direction === V.arcologies[0].influenceTarget);
			if (!externalArcology) {
				App.UI.DOM.appendNewElement("span", f, `. `);
				App.UI.DOM.appendNewElement("span", f, `Since you have not selected another arcology to influence, your recruiter's talents are going to waste. Select an influence target to apply them. `, "red");
			} else {
				App.UI.DOM.appendNewElement("span", f, ` to ${externalArcology.name}. `);
			}
		}
		f.append(App.UI.DOM.link("Remove Recruiter", () => {
			removeJob(S.Recruiter, Job.RECRUITER);
		},
		[], "Main"
		));

		App.UI.DOM.appendNewElement("p", f);
		f.append(`Your recruiter will target ${V.recruiterTarget}, `);
		if (V.recruiterTarget === "desperate whores") {
			f.append("they will be skilled but unhealthy. ");
		} else if (V.recruiterTarget === "young migrants") {
			f.append("they will be young and inexperienced but unhealthy. ");
		} else if (V.recruiterTarget === "recent divorcees") {
			f.append("they will be mature. ");
		} else if (V.recruiterTarget === "expectant mothers") {
			f.append("they will be pregnant and likely unhealthy. ");
		} else if (V.recruiterTarget === "dissolute sissies") {
			f.append("they will be born male and have some experience. ");
		} else if (V.recruiterTarget === "reassignment candidates") {
			f.append("they will be born male. ");
		} else if (V.recruiterTarget === "other arcologies") {
			f.append("they will appoint the Recruiter to be a sexual Ambassador. ");
		}

		r.push(App.UI.DOM.link(`Desperate whores`, () => {
			V.recruiterTarget = "desperate whores";
			App.UI.reload();
		}));
		r.push(App.UI.DOM.link("Young migrants", () => {
			V.recruiterTarget = "young migrants";
			App.UI.reload();
		}));
		r.push(App.UI.DOM.link("Recent divorcees", () => {
			V.recruiterTarget = "recent divorcees";
			App.UI.reload();
		}));

		if (V.seeDicks !== 100 && V.seePreg !== 0) {
			r.push(App.UI.DOM.link("Expectant mothers", () => {
				V.recruiterTarget = "expectant mothers";
				App.UI.reload();
			}));
		}
		if (V.seeDicks !== 0) {
			r.push(App.UI.DOM.link("Dissolute sissies", () => {
				V.recruiterTarget = "dissolute sissies";
				App.UI.reload();
			}));
			r.push(App.UI.DOM.link("Reassignment candidates", () => {
				V.recruiterTarget = "reassignment candidates";
				App.UI.reload();
			}));
		}
		if (V.arcologies.length > 1) {
			r.push(App.UI.DOM.link("Other arcologies' cultures", () => {
				V.oldRecruiterTarget = V.recruiterTarget;
				V.recruiterTarget = "other arcologies";
				App.UI.reload();
			}));
		}
		App.UI.DOM.appendNewElement("div", f, App.UI.DOM.generateLinksStrip(r));
		App.UI.DOM.appendNewElement("p", f);

		// Recruiter specializations
		App.UI.DOM.appendNewElement("div", specializations, `Recruiters of any skill level can take advantage of eugenics SMRs to target specific individuals.`);
		App.UI.DOM.appendNewElement("div", specializations, `More skilled recruiters can also specialize in what individuals they target, independent of eugenics SMRs.`);
		App.UI.DOM.appendNewElement("p", specializations);

		const allowedSpecializations = getMaxRecruiterSpecializations();
		if (allowedSpecializations === 0) {
			App.UI.DOM.appendNewElement("div", specializations, `${S.Recruiter.slaveName} is not skilled enough to specialize, but ${he} ${policies.countEugenicsSMRs() > 0 ? 'can' : 'could'} use eugenics SMRs to guide ${his} work.`, ["note"]);
		} else {
			App.UI.DOM.appendNewElement("div", specializations, `${S.Recruiter.slaveName} is skilled enough to apply ${allowedSpecializations} specialization${allowedSpecializations > 1 ? 's' : ''}.`, ["note"]);
		}

		const eugenicsCheckbox = App.UI.DOM.makeCheckbox("recruiterEugenics");
		const eugenicsLabel = App.UI.DOM.makeElement("label", " Target only individuals that can pass eugenics SMRs.");
		eugenicsLabel.htmlFor = eugenicsCheckbox.id = "recruiterEugenics";
		specializations.append(eugenicsCheckbox);
		specializations.append(eugenicsLabel);

		App.UI.DOM.appendNewElement("div", specializations, ` ${He} will only recruit slaves that are`);
		let checkboxes = [];
		// Only allow specializations based on recruiter skill, and display eugenics SMR selections
		const updateCheckboxes = () => {
			// Reset all checkboxes to start fresh each time
			checkboxes
				.forEach(checkbox => {
					checkbox.disabled = false;
					checkbox.checked = V.recruiterSpecializations[checkbox.value] !== 0;
				});

			// Disable boxes with eugenics SMR applied if we're using them
			if (eugenicsCheckbox.checked) { // Hasn't updated V.recruiterEugenics yet
				checkboxes
					.filter(checkbox => checkbox.dataset.smrActive)
					.forEach(checkbox => {
						checkbox.disabled = true;
						checkbox.checked = true;
					});
			}

			// Disable and maybe uncheck boxes if recruiter isn't skilled enough
			const chosenSpecs = checkboxes.filter((checkbox) => {
				if (!checkbox.checked) {
					return false;
				}
				if (eugenicsCheckbox.checked && checkbox.dataset.smrActive) { // Hasn't updated V.recruiterEugenics yet
					return false;
				}
				return checkbox.checked;
			});
			const numChosenSpecs = chosenSpecs.length;
			if (numChosenSpecs >= allowedSpecializations) {
				if (numChosenSpecs > allowedSpecializations) {
					// Too many are checked so uncheck some of them
					let checkedSoFar = 0;
					chosenSpecs.forEach((checkbox) => {
						if (checkbox.checked) {
							checkedSoFar++;
							if (checkedSoFar > allowedSpecializations) {
								checkbox.checked = false;
								checkbox.onchange();
							}
						}
					});
				}

				// Disable unchecked boxes
				checkboxes
					.filter(checkbox => checkbox.checked === false)
					.forEach(checkbox => checkbox.disabled = true);
			}
		};
		eugenicsCheckbox.onclick = updateCheckboxes;

		const availableSpecializations = [
			["beauty", "Beautiful", "faceSMR"],
			["height", "Tall", "heightSMR"],
			["intelligence", "Intelligent", "intelligenceSMR"],
		];

		for (const [spec, label, smrName] of availableSpecializations) {
			const field = App.UI.DOM.appendNewElement("div", specializations, "", ["indent"]);
			const checkbox = Object.assign(document.createElement("input"), {
				type: "checkbox",
				value: spec,
				checked: V.recruiterSpecializations[spec],
				onchange: function() {
					V.recruiterSpecializations[spec] = this.checked ? 1 : 0;
					updateCheckboxes();
				},
				id: `recruiter-specialization-${spec}`
			});
			if (V.policies.SMR.eugenics[smrName] === 1) {
				checkbox.dataset.smrActive = 'true';
			}
			checkboxes.push(checkbox);
			field.append(checkbox);

			field.append(Object.assign(document.createElement("label"), {
				htmlFor: `recruiter-specialization-${spec}`,
				textContent: ` ${label}`
			}));

			specializations.append(field);
		}
		App.UI.DOM.appendNewElement("div", specializations, `Targeting more specific individuals will increase time it takes to recruit, depending on how many aspects are targeted.`, ["note"]);

		updateCheckboxes();
		App.UI.DOM.appendNewElement("div", f, specializations);
		App.UI.DOM.appendNewElement("p", f);

		// Recruiter idle rule
		f.append("Suspend active recruiting and focus on publicity when: ");
		if (V.recruiterIdleRule === "number") {
			f.append(`${V.recruiterIdleNumber} sex slaves owned`);
		} else if (V.recruiterIdleRule === "facility") {
			const idleTarget = App.Utils.recruiterFacilitySpace();
			f.append(`match facility expansion, `);
			if (idleTarget > 20) {
				f.append(`${idleTarget} positions.`);
			} else {
				f.append("20 positions (rule minimum).");
			}
		} else {
			f.append("always recruit");
		}

		r = [];
		r.push(App.UI.DOM.link("Always recruit", () => {
			V.recruiterIdleRule = "always";
			App.UI.reload();
		}));
		r.push(App.UI.DOM.link("Facilities & leadership", () => {
			V.recruiterIdleRule = "facility";
			App.UI.reload();
		}));
		recruiterCap.append(App.UI.DOM.link("Set to this many slaves ", () => {
			V.recruiterIdleRule = "number";
			App.UI.reload();
		}));
		if (V.recruiterIdleRule === "number") {
			recruiterCap.append(App.UI.DOM.makeTextBox(V.recruiterIdleNumber, (v) => {
				V.recruiterIdleNumber = v;
				Engine.play(passage());
			}, true));
		}
		r.push(recruiterCap);
		App.UI.DOM.appendNewElement("div", f, App.UI.DOM.generateLinksStrip(r));
		App.UI.DOM.appendNewElement("div", f, "'Facilities' doesn't include training slots in cellblock, schoolroom, spa, clinic (but does include those leaders)");

		V.recruiterIdleNumber = Math.max(Math.trunc(Number(V.recruiterIdleNumber) || 20), 20);
	} else {
		f.append(`No Recruiter assigned, appoint one from your devoted slaves.`);
	}

	f.append(App.UI.SlaveList.facilityManagerSelection(App.Entity.facilities.penthouse, "Recruiter Select"));
	return f;
};


code:
/**
 * UI for managing Penthouse Refreshes without refreshing the passage.
 */
App.UI.managePenthouse = function() {
	const container = document.createElement("span");
	container.append(createPage());
	return container;

	function createPage() {
		const el = new DocumentFragment();
		el.append(intro());
		el.append(capacity());
		el.append(major());
		el.append(minor());
		el.append(upgrades());
		el.append(blackMarket());
		return el;
	}

	function intro() {
		const el = new DocumentFragment();
		if (V.cheatMode === 1) {
			App.UI.DOM.appendNewElement("div", el,
				App.UI.DOM.passageLink("Cheat Edit Arcology", "MOD_Edit Arcology Cheat"),
				["cheat-menu"]);
		}
		App.UI.DOM.appendNewElement("h1", el, "Penthouse");
		App.UI.DOM.appendNewElement("div", el, App.Desc.officeDescription(V.PC.career === "mercenary" ? "You look back at the rifle. It could never hold a zero, and would fail to feed if it wasn't given just the right amount of lubricant. But sometimes, you'd give anything for one more mission with that shitty old rifle." : ""), "scene-intro");
		if (V.SF.Toggle && V.SF.Active >= 1) {
			App.UI.DOM.appendNewElement("div", el,
				App.UI.DOM.passageLink(
					`Take your express elevator down to ${V.SF.Lower}`,
					"Firebase"
				)
			);
		} else if (V.SF.FS.Tension > 100) {
			App.UI.DOM.appendNewElement("div", el, App.Mods.SF.fsIntegration.crisis()[0]);
		}
		return el;
	}

	function capacity() {
		const el = new DocumentFragment();
		let r = [];
		App.UI.DOM.appendNewElement("h2", el, "Penthouse Capacity");

		// Dorms
		const dormCost = Math.trunc(V.dormitory * 1000 * V.upgradeMultiplierArcology);
		r.push(`The main penthouse dormitory, which houses slaves who aren't living in a facility and aren't granted a luxurious standard of living, has a capacity of`);
		r.push(App.UI.DOM.makeElement("span", JSON.stringify(V.dormitory), ["bold"]));
		r.push(`slaves.`);
		r.push(
			makePurchase(`Expand the dormitory`, dormCost, "capEx", {
				handler: () => {
					V.dormitory += 10;
					V.PC.skill.engineering += .1;
				}
			})
		);
		r.push(App.UI.DOM.makeElement("div", `Exceeding this limit is bad for slaves' health, devotion and trust.`, ["detail", "indent"]));
		App.Events.addNode(el, r, "div");

		// Luxury rooms
		r = [];
		const luxuryCost = Math.trunc(V.rooms * 1000 * V.upgradeMultiplierArcology);
		r.push(`The penthouse also features little individual rooms, which house slaves who do enjoy a luxurious standard of living. They have a capacity of`);
		r.push(App.UI.DOM.makeElement("span", JSON.stringify(V.rooms), ["bold"]));
		r.push(`slaves.`);
		r.push(
			makePurchase(`Expand the rooms`, luxuryCost, "capEx", {
				handler: () => {
					V.rooms += 5;
					V.PC.skill.engineering += .1;
				}
			})
		);
		r.push(App.UI.DOM.makeElement("div", `The number of rooms determines the number of slaves that can be granted luxury.`, ["detail", "indent"]));
		App.Events.addNode(el, r, "div");
		return el;
	}

	function major() {
		const el = new DocumentFragment();
		App.UI.DOM.appendNewElement("h2", el, "Major Penthouse Facilities");

		if (V.masterSuite === 0) {
			App.UI.DOM.appendNewElement("div", el, makeLink("Improve your master bedroom to house a harem of personal toys", () => { V.masterSuite = 1; }));
		} else {
			App.UI.DOM.appendNewElement("div", el, `Your penthouse is capped by a master suite with room for an entire harem of personal toys.`);
		}

		if (!App.Entity.facilities.servantsQuarters.established) {
			App.UI.DOM.appendNewElement("div", el, makeLink("Build a dormitory to house large numbers of house servants", () => {
				App.Entity.facilities.servantsQuarters.capacity = 5;
			}));
		} else {
			App.UI.DOM.appendNewElement("div", el, `Your penthouse includes a dormitory to house large numbers of house servants.`);
		}

		if (V.schoolroom === 0) {
			App.UI.DOM.appendNewElement("div", el, makeLink("Build a schoolroom where slaves can be educated", () => { V.schoolroom = 5; }));
		} else {
			App.UI.DOM.appendNewElement("div", el, `Your penthouse includes a schoolroom where slaves can be educated.`);
		}

		if (V.spa === 0) {
			App.UI.DOM.appendNewElement("div", el, makeLink("Install open baths to provide relaxation space for resting slaves", () => { V.spa = 5; }));
		} else {
			App.UI.DOM.appendNewElement("div", el, `The penthouse includes a fully appointed spa where slaves can rest and recuperate.`);
		}

		if (V.seePreg !== 0) {
			if (V.experimental.nursery === 1) {
				if (V.nursery === 0) {
					App.UI.DOM.appendNewElement("div", el, makeLink("Build a nursery to raise children from birth", () => {
						V.nursery = 1;
						V.nurseryCribs = 5;
					}));
				} else {
					App.UI.DOM.appendNewElement("div", el, `The penthouse has a nursery built where infants can be brought up.`);
				}
			}
		}

		if (V.clinic === 0) {
			App.UI.DOM.appendNewElement("div", el, makeLink("Expand the surgical recovery area to accommodate patients and a nurse", () => { V.clinic = 5; }));
		} else {
			App.UI.DOM.appendNewElement("div", el, `The surgical recovery area has been expanded to take in more unhealthy slaves and be staffed by a nurse.`);
		}

		if (V.cellblock === 0) {
			App.UI.DOM.appendNewElement("div", el, makeLink("Construct cells to properly confine disobedient slaves", () => { V.cellblock = 5; }));
		} else {
			App.UI.DOM.appendNewElement("div", el, `The lower level of the penthouse includes a hallway of cells to confine slaves in.`);
		}

		if (V.seePreg !== 0) {
			if (V.arcologyUpgrade.grid === 1) {
				if (V.incubator.capacity === 0) {
					App.UI.DOM.appendNewElement("div", el, makeLink("Install an incubation chamber to rapidly age children", () => {
						App.Facilities.Incubator.init('install');
					}));
				} else {
					App.UI.DOM.appendNewElement("div", el, `The penthouse has a specialized facility dedicated to rapidly aging children.`);
				}
			} else {
				App.UI.DOM.appendNewElement("div", el, App.UI.DOM.makeElement("span", "Installation of a child aging facility will require the arcology's electrical infrastructure to be overhauled.", ["note"]));
			}
		}

		return el;
	}

	function minor() {
		const el = new DocumentFragment();
		let r = [];
		App.UI.DOM.appendNewElement("h2", el, "Minor Penthouse Facilities");

		if (V.HGSuite !== 1) {
			r.push(makeLink("Build a small suite for a Head Girl to live in", () => { V.HGSuite = 1; }));
		} else {
			r.push(`There is a small but handsome suite next to yours reserved for the Head Girl.`);
		}
		App.Events.addNode(el, r, "div");

		r = [];
		if (V.dojo === 0) {
			r.push(makeLink("Set up a personal armory to support a bodyguard", () => { V.dojo = 1; }));
		} else if (V.dojo === 1) {
			r.push(`There is a small armory next to your office that can support a bodyguard.`);
			r.push(makeLink("Upgrade the armory with a private room for the bodyguard", () => { V.dojo = 2; }));
		} else {
			r.push(`There is a small armory next to your office that can support a bodyguard, with a little room for them to rest in when off duty.`);
		}
		App.Events.addNode(el, r, "div");

		r = [];
		if (!V.toyShop) {
			r.push(makeLink("Install a workshop for making custom toys", () => { V.toyShop = true; }));
		} else {
			r.push(`There is a`);
			r.push(App.UI.DOM.passageLink("workshop", "Toy Shop"));
			r.push(`for making custom toys.`);
		}
		App.Events.addNode(el, r, "div");

		r = [];
		if (V.surgeryUpgrade === 0) {
			if (V.rep > 10000) {
				r.push(makeLink("Upgrade the remote surgery", () => { V.surgeryUpgrade = 1; }, 50000));
			} else {
				r.push(App.UI.DOM.makeElement("span", "You lack the reputation to secure rare surgery upgrades.", ["note"]));
			}
		} else {
			r.push(`Your remote surgery has been heavily upgraded and customized.`);
		}
		App.Events.addNode(el, r, "div");

		r = [];
		if (V.dispensary === 0) {
			if (V.rep > 2000) {
				r.push(makeLink("Install a pharmaceutical fabricator", () => {
					V.dispensary = 1;
					V.drugsCost = V.drugsCost * .75;
				}, 20000));
			} else {
				r.push(App.UI.DOM.makeElement("span", "You lack the reputation to obtain cutting-edge pharmaceutical technology.", ["note"]));
			}
		} else {
			r.push(`There is a`);
			r.push(App.UI.DOM.passageLink("pharmaceutical fabricator", "Dispensary"));
			r.push(`attached to the surgery.`);
		}
		App.Events.addNode(el, r, "div");

		r = [];
		if (V.ImplantProductionUpgrade === 0) {
			if (V.rep > 2000) {
				r.push(makeLink("Install an implant manufactory", () => { V.ImplantProductionUpgrade = 1; }, 20000));
			} else {
				r.push(App.UI.DOM.makeElement("span", "You lack the reputation to obtain cutting-edge implant fabrication technology.", ["note"]));
			}
		} else {
			r.push(`There is a`);
			r.push(App.UI.DOM.passageLink("implant manufactory", "Implant Manufactory"));
			r.push(`attached to the surgery.`);
		}
		App.Events.addNode(el, r, "div");

		r = [];
		if (V.organFarmUpgrade === 0) {
			if (V.rep > 10000) {
				r.push(makeLink("Install an experimental organ farm", () => { V.organFarmUpgrade = 1; }, 70000));
			} else {
				r.push(App.UI.DOM.makeElement("span", "You lack the reputation to obtain an experimental organ fabricator.", ["note"]));
			}
		} else {
			r.push(`There is a`);
			r.push(App.UI.DOM.passageLink("organ farm", "Organ Farm"));
			r.push(`attached to the surgery.`);
		}
		App.Events.addNode(el, r, "div");

		r = [];
		if (V.geneticMappingUpgrade >= 2) {
			r.push(`There is a`);
			r.push(App.UI.DOM.passageLink("genetic sequencer", "Gene Lab"));
			r.push(`attached to the surgery.`);
		} else if (V.geneticMappingUpgrade >= 0) {
			if (V.rep > 14000) {
				r.push(makeLink("Install a cutting-edge genetic sequencer", () => { V.geneticMappingUpgrade = 2; }, 120000));
			} else {
				r.push(App.UI.DOM.makeElement("span", "You lack the reputation to purchase a cutting-edge genetic sequencer.", ["note"]));
			}
		}
		if (V.geneticMappingUpgrade === 1) {
			r.push(`There is an aged genetic sequencer, no doubt liberated from some old-world lab, residing in the surgery.`);
		} else if (V.geneticMappingUpgrade === 0) {
			if (V.rep > 5000) {
				r.push(makeLink("Acquire a basic genetic sequencer", () => { V.geneticMappingUpgrade = 1; }, 30000));
			} else {
				r.push(App.UI.DOM.makeElement("span", "You lack the reputation to purchase a cheap genetic sequencer.", ["note"]));
			}
		}
		App.Events.addNode(el, r, "div");

		r = [];
		switch (V.prostheticsUpgrade) {
			case 0:
				if (V.rep > 8000) {
					r.push(makeLink("Install basic equipment for attaching and maintenance of prosthetics", () => { V.prostheticsUpgrade = 1; }, 120000));
				} else {
					r.push(App.UI.DOM.makeElement("span", "You lack the reputation to buy basic equipment for attaching and maintenance of prosthetics.", ["note"]));
				}
				break;
			case 1:
				r.push(`You have basic equipment for attaching and maintenance of prosthetics.`);
				if (V.rep > 12000) {
					r.push(makeLink("Buy a contract for advanced prosthetics", () => { V.prostheticsUpgrade = 2; }, 100000));
				} else {
					r.push(App.UI.DOM.makeElement("span", "You lack the reputation to get a contract for advanced prosthetics.", ["note"]));
				}
				break;
			case 2:
				r.push(`You have basic equipment for attaching and maintenance of prosthetics and a contract to guarantee the availability of advanced prosthetics.`);
				if (V.rep > 16000) {
					r.push(makeLink("Buy a contract for high-tech prosthetics", () => { V.prostheticsUpgrade = 3; }, 100000));
				} else {
					r.push(App.UI.DOM.makeElement("span", "You lack the reputation to get a contract for high-tech prosthetics.", ["note"]));
				}
				break;
			case 3:
				r.push(`You have advanced equipment for attaching and maintenance of prosthetics and a contract to guarantee the availability of high-tech prosthetics.`);
				if (V.rep > 18000) {
					r.push(makeLink("Buy a contract for quadruped prosthetics", () => { V.prostheticsUpgrade = 4; }, 100000));
				} else {
					r.push(App.UI.DOM.makeElement("span", "You lack the reputation to get a contract for quadruped prosthetics.", ["note"]));
				}
				break;
			case 4:
				r.push(`You have advanced equipment for attaching and maintenance of prosthetics and a contract to guarantee the availability of quadruped prosthetics.`);
		}
		App.Events.addNode(el, r, "div");

		r = [];
		if (V.prostheticsUpgrade > 0) {
			if (V.researchLab.level > 0) {
				r.push(`Your penthouse is equipped with an advanced prosthetic lab.`);
			} else {
				r.push(makeLink("Clear out one of the floors and install equipment to construct prosthetics yourself", () => {
					V.researchLab.level = 1;
					V.researchLab.maxSpace = 5;
				}, 150000));
				r.push(App.UI.DOM.makeElement("div", `Buying the equipment to construct prosthetics yourself is expensive but if you plan to construct many prosthetics it will pay out in the long run.`, "indent"));
			}
		}
		App.Events.addNode(el, r, "div");

		r = [];
		if (V.seePreg === 1) {
			if (V.pregnancyMonitoringUpgrade === 0) {
				if (V.rep > 10000) {
					r.push(makeLink("Upgrade the pregnancy monitoring systems", () => { V.pregnancyMonitoringUpgrade = 1; }, 30000));
				} else {
					r.push(App.UI.DOM.makeElement("span", "You lack the reputation to purchase improved pregnancy monitoring systems.", ["note"]));
				}
			} else {
				r.push(`Your pregnancy monitoring systems have been heavily upgraded.`);
			}
		}
		App.Events.addNode(el, r, "div");

		return el;
	}

	function upgrades() {
		const el = new DocumentFragment();
		let r = [];
		App.UI.DOM.appendNewElement("h2", el, "Penthouse Upgrades");

		if (V.servantMilkers !== 1) {
			r.push("Your penthouse is equipped with basic milkers for lactating slaves.");
			r.push(makeLink("Install more and tie them into the liquid systems", () => { V.servantMilkers = 1; }, 25000));
		} else {
			r.push(`Every room in the penthouse is equipped with milkers tied into the liquid systems, letting slaves with full udders drain them anywhere.`);
		}
		App.Events.addNode(el, r, "div");

		r = [];
		if (V.boobAccessibility !== 1) {
			if (V.pregAccessibility === 1 || V.ballsAccessibility || V.buttAccessibility) {
				r.push(`Your penthouse has already been widened for overly wide slaves but there are no special accommodations for slaves with enormous breasts.`);
				r.push(makeLink("Remodel for accessibility", () => { V.boobAccessibility = 1; }, 20000));
			} else {
				r.push(`Your penthouse has no special accessibility provisions for slaves with enormous breasts.`);
				r.push(makeLink("Remodel for accessibility", () => { V.boobAccessibility = 1; }, 50000));
			}
		} else {
			r.push(`The entire penthouse has been remodeled to make life with enormous breasts easier. The doorways have been widened, and tables, sinks, and other items now have two levels: one at shoulder height for slaves to use, and another at waist height for them to rest their tits on while they do.`);
		}
		App.Events.addNode(el, r, "div");

		r = [];
		if (V.seeHyperPreg === 1) {
			if (V.pregAccessibility !== 1) {
				if (V.boobAccessibility === 1 || V.ballsAccessibility || V.buttAccessibility) {
					r.push(`Your penthouse has already been widened to make life for overly wide slaves easier but there are no special accommodations for slaves with enormous pregnancies.`);
					r.push(makeLink("Remodel for accessibility", () => { V.pregAccessibility = 1; }, 20000));
				} else {
					r.push(`Your penthouse has no special accessibility provisions for slaves with enormous pregnancies.`);
					r.push(makeLink("Remodel for accessibility", () => { V.pregAccessibility = 1; }, 50000));
				}
			} else {
				r.push(`The entire penthouse has been remodeled to make life with enormous pregnancies easier. The doorways have been widened, and tables, sinks, and other items are now designed to work around a massively distended belly.`);
			}
		}
		App.Events.addNode(el, r, "div");

		if (V.arcologies[0].FSAssetExpansionistResearch === 1) {
			r = [];
			if (V.dickAccessibility !== 1) {
				r.push(`Your penthouse has no special accessibility provisions for slaves with enormous dicks.`);
				r.push(makeLink("Remodel for accessibility", () => { V.dickAccessibility = 1; }, 20000));
			} else {
				r.push(`The entire penthouse has been remodeled to make life with enormous dicks easier. Carts, slings and harnesses are available to keep things from dragging and there is now plenty of room for huge genitals to occupy when a slave must use appliances, tables and seats.`);
			}
			App.Events.addNode(el, r, "div");

			r = [];
			if (V.ballsAccessibility !== 1) {
				if (V.boobAccessibility === 1 || V.buttAccessibility || V.pregAccessibility) {
					r.push(`Your penthouse has already been widened to make life for overly wide slaves easier but there are no special accommodations for slaves with enormous testicles.`);
					r.push(makeLink("Remodel for accessibility", () => { V.ballsAccessibility = 1; }, 20000));
				} else {
					r.push(`Your penthouse has no special accessibility provisions for slaves with enormous testicles.`);
					r.push(makeLink("Remodel for accessibility", () => { V.ballsAccessibility = 1; }, 50000));
				}
			} else {
				r.push(`The entire penthouse has been remodeled to make life with enormous testicles easier. The doorways have been widened, tables, sinks, and other items are now designed to fit over giant balls, drains have been widened to allow excessive cum to flow easier, and seats have been specially altered to allow plenty of ball room for seated slaves.`);
			}
			App.Events.addNode(el, r, "div");

			r = [];
			if (V.buttAccessibility !== 1) {
				if (V.boobAccessibility === 1 || V.dickAccessibility || V.ballsAccessibility) {
					r.push(`Your penthouse has already been widened to make life for overly wide slaves easier but there are no special accommodations for slaves with gigantic posteriors.`);
					r.push(makeLink("Remodel for accessibility", () => { V.buttAccessibility = 1; }, 20000));
				} else {
					r.push(`Your penthouse has no special accessibility provisions for slaves with enormous posteriors.`);
					r.push(makeLink("Remodel for accessibility", () => { V.buttAccessibility = 1; }, 50000));
				}
			} else {
				r.push(`The entire penthouse has been remodeled to make life with enormous rears easier. The doorways have been widened, and anything that can be sat on is now extra, extra wide and reinforced to allow even the heaviest, biggest asses to comfortably rest upon it.`);
			}
			App.Events.addNode(el, r, "div");
		}

		r = [];
		if (V.boobAccessibility > 0 || V.pregAccessibility > 0 || V.dickAccessibility > 0 || V.ballsAccessibility > 0 || V.buttAccessibility > 0) {
			const removeCost = Math.trunc((5000 * (V.boobAccessibility + V.pregAccessibility + V.dickAccessibility + V.ballsAccessibility + V.buttAccessibility)) * V.upgradeMultiplierArcology);
			el.append(makePurchase(`Remove the accessibility renovations`, removeCost, "capEx", {
				handler: () => {
					V.boobAccessibility = 0;
					V.pregAccessibility = 0;
					V.dickAccessibility = 0;
					V.ballsAccessibility = 0;
					V.buttAccessibility = 0;
				}
			}));
		}
		App.Events.addNode(el, r, "div");

		r = [];
		if (V.feeder === 0) {
			r.push(makeLink("Upgrade the kitchen's nutritional sensing systems", () => { V.feeder = 1; }));
		} else {
			r.push(`The kitchen mounts sensors to refine diets in real time.`);
		}
		App.Events.addNode(el, r, "div");

		r = [];
		if (V.cockFeeder === 0) {
			r.push(makeLink("Enhance the feeding system with faux phalli", () => { V.cockFeeder = 1; }));
		} else {
			r.push(`The kitchen dispenses food from phalli slaves must suck off in order to eat.`);
			r.push(makeLink("Remove them", () => { V.cockFeeder = 0; }, 0));
		}
		App.Events.addNode(el, r, "div");

		r = [];
		if (V.suppository === 0) {
			r.push(makeLink("Replace the drug dispensers with reciprocating dildo suppositories", () => { V.suppository = 1; }));
		} else {
			r.push(`The kitchen applies drugs that can be absorbed rectally by assfucking slaves with dildos that cum the pharmaceuticals.`);
			r.push(makeLink("Remove them", () => { V.suppository = 0; }, 0));
		}
		App.Events.addNode(el, r, "div");

		r = [];
		if (V.dairy !== 0) {
			if (V.dairyPiping === 0) {
				r.push(makeLink("Install pipes connecting the Dairy to the rest of your penthouse for use in enema play", () => { V.dairyPiping = 1; }));
			} else {
				r.push(`Various taps around the penthouse supply product from ${V.dairyName} for use in enema play and force-feeding.`);
			}
		} else if (V.dairyPiping === 1) {
			r.push(`Various taps around the penthouse supply product from ${V.dairyName} for use in enema play and force-feeding. With no dairy to draw from, they are currently unused.`);
		}
		App.Events.addNode(el, r, "div");

		if (V.seePee === 1) {
			r = [];
			if (V.wcPiping === 0) {
				r.push(makeLink("Install pipes connecting the slave bathrooms to the rest of your penthouse for use in watersports", () => { V.wcPiping = 1; }, 10000));
			} else {
				r.push(`The plumbing underneath the slave bathrooms connects to various taps throughout the penthouse that can dispense its contents when needed.`);
			}
			App.Events.addNode(el, r, "div");
		}

		r = [];
		if (V.studio === 0) {
			r.push(makeLink("Install a media hub to convert slave video feeds into pornography", () => { V.studio = 1; }, 10000));
		} else {
			r.push(`The arcology's video systems are connected to a`, App.UI.DOM.passageLink("media hub", "Media Studio"), `that can convert slave video feeds into pornography.`);
		}
		App.Events.addNode(el, r, "div");

		return el;
	}

	function blackMarket() {
		const el = new DocumentFragment();
		App.UI.DOM.appendNewElement("h2", el, "Black Market");
		const rep = 10000;

		App.UI.DOM.appendNewElement(
			"div",
			el,
			(V.rep >= rep)
				? App.UI.DOM.passageLink("Visit the market", "The Black Market")
				: `You lack the ${num(rep)} reputation to be invited to the underground Black Market.`
		);
		return el;
	}

	/**
	 * Creates a new link to purchase a facility.
	 *
	 * @param {string} title
	 * @param {function(void):void} handler
	 * @param {number} [cost]
	 * @returns {DocumentFragment}
	 */
	function makeLink(title, handler, cost = 5000) {
		const el = new DocumentFragment();
		cost = Math.trunc(cost * V.upgradeMultiplierArcology);
		el.append(makePurchase(title, cost, "capEx", {
			handler: () => {
				handler();

				V.PC.skill.engineering += .1;
				jQuery(container).empty().append(createPage());
			}
		}));

		return el;
	}
};


code:
/** @type {FC.FacilityFramework} */
App.Data.Facilities.penthouse = {
	baseName: "penthouse",
	genericName: "Penthouse",
	jobs: {
		rest: {
			position: "Rest",
			assignment: Job.REST,
			publicSexUse: false,
			fuckdollAccepted: true
		},
		chooseOwn: {
			position: "Choose own",
			assignment: Job.CHOICE,
			publicSexUse: false,
			fuckdollAccepted: false
		},
		fucktoy: {
			position: "Fucktoy",
			assignment: Job.FUCKTOY,
			publicSexUse: false,
			fuckdollAccepted: true
		},
		classes: {
			position: "Classes",
			assignment: Job.CLASSES,
			publicSexUse: false,
			fuckdollAccepted: false
		},
		houseServant: {
			position: "House Servant",
			assignment: Job.HOUSE,
			publicSexUse: false,
			fuckdollAccepted: false
		},
		whore: {
			position: "Whore",
			assignment: Job.WHORE,
			publicSexUse: true,
			fuckdollAccepted: false
		},
		publicServant: {
			position: "Public Servant",
			assignment: Job.PUBLIC,
			publicSexUse: true,
			fuckdollAccepted: false
		},
		subordinateSlave: {
			position: "Subordinate slave",
			assignment: Job.SUBORDINATE,
			publicSexUse: false,
			fuckdollAccepted: false
		},
		cow: {
			position: "Milked",
			assignment: Job.MILKED,
			publicSexUse: false,
			fuckdollAccepted: false
		},
		gloryhole: {
			position: "Gloryhole",
			assignment: Job.GLORYHOLE,
			publicSexUse: false,
			fuckdollAccepted: true
		},
		confinement: {
			position: "Confinement",
			assignment: Job.CONFINEMENT,
			publicSexUse: false,
			fuckdollAccepted: true
		}
	},
	defaultJob: "rest",
	manager: {
		position: "Recruiter",
		assignment: Job.RECRUITER,
		careers: App.Data.Careers.Leader.recruiter,
		skill: "recruiter",
		publicSexUse: false,
		fuckdollAccepted: false,
		broodmotherAccepted: false,
		shouldWalk: true,
		shouldHold: false,
		shouldSee: true,
		shouldHear: true,
		shouldTalk: true,
		shouldThink: true,
		requiredDevotion: 51
	},
	decorated: false,
	penthouseFacility: true
};

App.Entity.Facilities.PenthouseJobs = {
	Classes: class extends App.Entity.Facilities.Job {
		checkRequirements(slave) {
			let r = super.checkRequirements(slave);
			if (slave.intelligenceImplant >= 15) {
				r.push(`${slave.slaveName} already has a basic education.`);
			}
			if (!App.Entity.Facilities.Job._isBrokenEnough(slave, -20, -50, -20, -51)) {
				r.push(`${slave.slaveName} is too resistant to learn.`);
			}

			if (slave.fetish === Fetish.MINDBROKEN) {
				r.push(`${slave.slaveName}'s mind is fundamentally broken and can't learn.`);
			}
			return r;
		}
	},
	HouseServant: class extends App.Entity.Facilities.Job {
		checkRequirements(slave) {
			let r = super.checkRequirements(slave);

			if (!App.Entity.Facilities.Job._isBrokenEnough(slave, -20, -50, -19, -51)) {
				r.push(App.Entity.Facilities.Job._stdBreakageMessage(slave));
			}

			if (!canWalk(slave)) {
				r.push(`${slave.slaveName} can't walk and would be unable to properly clean.`);
			} else if (!canHold(slave)) {
				r.push(`${slave.slaveName} has no hands and would be unable to properly clean.`);
			}
			if (!canSee(slave)) {
				r.push(`${slave.slaveName} is blind and would be unable to properly clean.`);
			}

			return r;
		}
	},

	SubordinateSlave: class extends App.Entity.Facilities.Job {
		checkRequirements(slave) {
			let r = super.checkRequirements(slave);
			if (!App.Entity.Facilities.Job._isBrokenEnough(slave, -20, -50, -19, -51)) {
				r.push(App.Entity.Facilities.Job._stdBreakageMessage(slave));
			}
			return r;
		}

		assignmentLinkElement(ID, passage, callback, linkText) {
			linkText = linkText || this.desc.position;
			return App.UI.DOM.assignmentLink(getSlave(ID), this.desc.assignment, "Subordinate Targeting",
				(slave, assignment) => {
					if (callback) {
						callback(slave, assignment);
					}
					V.temp.AS = ID;
					V.returnTo = passage;
				}, linkText);
		}
	},
	Cow: class extends App.Entity.Facilities.Job {
		/**
		 * @param {FC.SlaveState} slave
		 */
		checkRequirements(slave) {
			let r = super.checkRequirements(slave);
			const cumMilkingBlocked = App.Facilities.Dairy.cumMilkingBlocked(slave);
			const {his} = getPronouns(slave);
			if (slave.lactation === 0 && (slave.balls === 0 || cumMilkingBlocked)) {
				r.push(`${slave.slaveName} is not lactating` + ((V.seeDicks > 0 && slave.balls === 0) ? ' or producing semen.' : '.'));
				if (cumMilkingBlocked) {
					if (slave.dick > 0) {
						r.push(`${slave.slaveName}'s ${dickDesc(slave, true)} is blocked by a chastity cage and cannot be properly milked`);
					} else {
						r.push(`${slave.slaveName} lacks access to ${his} ${anusDesc(slave, true)} in order to properly milk ${his} dickless balls.`);
					}
				}
			}
			return r;
		}
	},
};

App.Entity.Facilities.Penthouse = class extends App.Entity.Facilities.Facility {
	constructor() {
		super(App.Data.Facilities.penthouse, {
			classes: new App.Entity.Facilities.PenthouseJobs.Classes(),
			houseServant: new App.Entity.Facilities.PenthouseJobs.HouseServant(),
			subordinateSlave: new App.Entity.Facilities.PenthouseJobs.SubordinateSlave(),
			cow: new App.Entity.Facilities.PenthouseJobs.Cow(),
		});
	}

	/** Facility slave capacity
	 * Note that slaves in a relationship may share luxury rooms, so actual capacity is slightly larger (@see penthouseCensus)
	 * @override
	 * @returns {number} */
	get capacity() {
		return V.dormitory + V.rooms;
	}

	/** Penthouse can be overcrowded, so it always has free space
	 * @override
	 * @returns {boolean} */
	get hasFreeSpace() {
		return true;
	}

	/** Not meaningful */
	occupancyReport() {
		return "";
	}
};

App.Entity.facilities.penthouse = new App.Entity.Facilities.Penthouse();