App.EndWeek.servantsQuartersReport = function() {
	let frag = document.createDocumentFragment();

	const slaves = App.Utils.sortedEmployees(App.Entity.facilities.servantsQuarters);
	const devBonus = (V.servantsQuartersDecoration !== "standard") ? 1 : 0;
	let stewardessBonus = 0;

	function stewardessText() {
		let r = [];
		let FLsFetish = 0;
		let stewardessImpregnated = 0;

		if (S.Stewardess) {
			S.Stewardess.devotion += devBonus;
			if (S.Stewardess.health.condition < -80) {
				improveCondition(S.Stewardess, 20);
			} else if ((S.Stewardess.health.condition < -40)) {
				improveCondition(S.Stewardess, 15);
			} else if ((S.Stewardess.health.condition < 0)) {
				improveCondition(S.Stewardess, 10);
			} else if ((S.Stewardess.health.condition < 90)) {
				improveCondition(S.Stewardess, 7);
			}
			if (S.Stewardess.devotion <= 60) {
				S.Stewardess.devotion++;
			}
			if (S.Stewardess.trust < 60) {
				S.Stewardess.trust++;
			}
			if (S.Stewardess.fetishStrength <= 95) {
				if (S.Stewardess.fetish !== "dom") {
					if (fetishChangeChance(S.Stewardess) > jsRandom(0, 100)) {
						FLsFetish = 1;
						S.Stewardess.fetishKnown = 1;
						S.Stewardess.fetish = "dom";
					}
				} else if (S.Stewardess.fetishKnown === 0) {
					FLsFetish = 1;
					S.Stewardess.fetishKnown = 1;
				} else {
					FLsFetish = 2;
					S.Stewardess.fetishStrength += 4;
				}
			}
			if (S.Stewardess.rules.living !== "luxurious") {
				S.Stewardess.rules.living = "luxurious";
			}

			const {He, he, His, his, him, wife} = getPronouns(S.Stewardess);
			r.push(`${SlaveFullName(S.Stewardess)} is serving as your Stewardess.`);
			if (S.Stewardess.relationship === -3 && S.Stewardess.devotion > 50) {
				r.push(`${He} does ${his} best to be your perfect lovely house${wife}.`);
			}
			if (V.stewardessImpregnates === 1 && canPenetrate(S.Stewardess) && S.Stewardess.pubertyXY === 1) {
				for (const slave of slaves) {
					if (canImpreg(slave, S.Stewardess)) { // FIXME: assumes vaginal pregnancy without check
						seX(S.Stewardess, "penetrative", slave, "vaginal", 10);
						r.push(knockMeUp(slave, 100, 2, S.Stewardess.ID));
						if (slave.vagina === 0) {
							slave.vagina = 1; // FIXME: silent virginity loss?
						}
						stewardessImpregnated++;
						slave.need = 0;
					}
				}
				if (stewardessImpregnated > 0) {
					r.push(`It's ${his} responsibility to keep ${his} charges pregnant, so`);
					if (stewardessImpregnated === 1) {
						r.push(`${he} cums in the only fertile slave's pussy all week.`);
					} else {
						r.push(`${he} ensures the ${stewardessImpregnated} fertile servants are full of ${his} cum at all times.`);
					}
					if (S.Stewardess.career === "a breeding bull") {
						r.push(`${He} was conditioned to fill empty wombs, so ${he} takes a <span class="hotpink">deep pleasure</span> in ${his} job.`);
						S.Stewardess.devotion++;
					}
					S.Stewardess.need = 0;
				}
			}
			if (FLsFetish === 1) {
				r.push(`${He}'s allowed and even expected to use ${his} charges for ${his} own gratification, and sometimes they'll even instigate submissive sex with ${him} just to ingratiate themselves. ${He} becomes comfortable with the role of a <span class="lightcoral">sexual dominant.</span>`);
			} else if (FLsFetish === 2) {
				r.push(`Having a legion of servants jumping to obey ${his} daily commands <span class="lightsalmon">makes ${him} more dominant.</span>`);
			}
			if (S.Stewardess.health.condition < 10) {
				r.push(`Though ${he} tries to watch the servants, ${his} lack of good health inhibits ${him}.`);
			} else if (S.Stewardess.health.condition < 80) {
				stewardessBonus += 50;
				r.push(`${His} good health allows ${him} to work long hours and <span class="yellowgreen">drive</span> the servants hard.`);
			} else {
				stewardessBonus += 75;
				r.push(`${His} perfect health allows ${him} to work exhaustive hours and <span class="yellowgreen">drive</span> the servants very hard.`);
			}
			if (setup.stewardessCareers.includes(S.Stewardess.career)) {
				stewardessBonus += 25;
				r.push(`${He} has applicable experience with daily sums and organizational trifles from ${his} life before ${he} was a slave.`);
			} else if (S.Stewardess.skill.stewardess >= V.masteredXP) {
				stewardessBonus += 25;
				r.push(`${He} has applicable experience with daily sums and organizational trifles from working for you.`);
			} else {
				S.Stewardess.skill.stewardess += jsRandom(1, Math.ceil((S.Stewardess.intelligence + S.Stewardess.intelligenceImplant) / 15) + 8);
			}
			if (S.Stewardess.actualAge > 35) {
				stewardessBonus += 25;
				r.push(`${His} age and experience give ${him} added effectiveness.`);
			} else if (V.AgePenalty === 0) {
				stewardessBonus +=25;
			}
			if (S.Stewardess.intelligence + S.Stewardess.intelligenceImplant > 15) {
				stewardessBonus += S.Stewardess.intelligence + S.Stewardess.intelligenceImplant;
				r.push(`${He}'s smart enough that ${he} misses very little.`);
			}
			const bonusToggle = S.Stewardess.energy > 95 || (S.Stewardess.fetishKnown === 1 && S.Stewardess.fetish === "dom");
			for (const slave of slaves) {
				const {he2, him2, his2} = getPronouns(slave).appendSuffix('2');
				if (S.Stewardess.rivalryTarget === slave.ID) {
					r.push(`${He} bears down on ${his} ${rivalryTerm(S.Stewardess)}, ${slave.slaveName}, forcing ${him2} to work extra hard or suffer punishment.`);
					slave.devotion--;
					slave.trust--;
					if (jsRandom(1, 100) > 65) {
						S.Stewardess.rivalry++;
						slave.rivalry++;
					}
				} else if (S.Stewardess.relationshipTarget === slave.ID) {
					r.push(`${He} dotes over ${his} ${relationshipTerm(S.Stewardess)}}, _${slave.slaveName}, making sure ${he2} knows how to do a good job and keeping ${him2} well stocked with everything ${he2} needs.`);
					slave.devotion++;
				} else if (areRelated(S.Stewardess, slave)) {
					r.push(`${He} pays special attention to ${his} ${relativeTerm(S.Stewardess, slave)}, ${slave.slaveName}, making sure ${he2} doesn't slack off just because they are related.`);
					slave.trust++;
				}
				switch (slave.prestigeDesc) {
					case "$He is a famed Free Cities whore, and commands top prices.":
						r.push(`${He} does ${his} best to motivate the famous whore, ${slave.slaveName}, though ${he} is uncertain why ${he2} is here.`);
						break;
					case "$He is a famed Free Cities slut, and can please anyone.":
						r.push(`${He} ignores ${his} duties in order the fawn over the famous entertainer, ${slave.slaveName}.`);
						break;
					case "$He is remembered for winning best in show as a cockmilker.":
						if ((slave.dick !== 0) && (slave.balls !== 0) && (slave.prostate > 1)) {
							r.push(`${slave.slaveName} leaves a trail of cum wherever ${he2} goes and frequently stops to masturbate, greatly annoying ${S.Stewardess.slaveName}.`);
							if (jsRandom(1, 100) > 90 && S.Stewardess.rivalry === 0 && slave.rivalry === 0) {
								S.Stewardess.rivalryTarget = slave.ID;
								S.Stewardess.rivalry++;
								slave.rivalryTarget = S.Stewardess.ID;
								slave.rivalry++;
							}
						}
						break;
					case "$He is remembered for winning best in show as a dairy cow.":
						if ((slave.lactation > 0) && ((slave.boobs-slave.boobsImplant) > 6000)) {
							r.push(`${slave.slaveName}'s huge breasts frequently get in the way of ${his2} work and ${he2} leaks milk everywhere, greatly annoying ${S.Stewardess.slaveName}.`);
							if (jsRandom(1, 100) > 90 && S.Stewardess.rivalry === 0 && slave.rivalry === 0) {
								S.Stewardess.rivalryTarget = slave.ID;
								S.Stewardess.rivalry++;
								slave.rivalryTarget = S.Stewardess.ID;
								slave.rivalry++;
							}
						}
						break;
					case "$He is remembered for winning best in show as a breeder.":
						if (slave.bellyPreg >= 10000) {
							r.push(`${slave.slaveName}'s big pregnant belly frequently gets in the way of ${his2} work. However, ${S.Stewardess.slaveName} is willing to overlook it, as well as allow ${him2} easy jobs, due to how valuable ${his2} womb is.`);
						}
						break;
				}
				if (bonusToggle && slave.devotion < 45) {
					slave.devotion += 5;
				}
			}
			if (slaves.length > 0) {
				if (S.Stewardess.fetishKnown === 1 && S.Stewardess.fetish === "dom") {
					r.push(`${He} walks among the cowering servants as a queen among peasants, playing the role of a dominant to perfection and increasing ${his} charges' <span class="hotpink">obedience.</span>`);
				} else if (S.Stewardess.energy > 95) {
					r.push(`${He} walks among the cowering servants looking for an excuse to extract sex from shirkers as <span class="hotpink">punishment.</span>`);
				}
				cashX(stewardessBonus * slaves.length, "servantsQuarters", S.Stewardess);
			}
			if (V.arcologies[0].FSRestart !== "unset" && stewardessImpregnated > 0 && V.eugenicsFullControl !== 1) {
				r.push(`<br>The Societal Elite know you've ordered ${S.Stewardess.slaveName} to impregnate your maids. <span class="red">They are not amused by your disinterest in eugenics.</span>`);
				V.failedElite += 10;
			}
		}
		return r.join(' ');
	}

	/** Generate (and return, if not silent) the "standard" part of the slave report
	 * @param {App.Entity.SlaveState} slave
	 * @param {boolean} silent
	 * @returns {HTMLElement|null}
	 */
	function standardSlaveReport(slave, silent) {
		const clothes = App.SlaveAssignment.choosesOwnClothes(slave);
		tired(slave);
		const rules = App.UI.DOM.renderPassage("SA rules");
		const diet = App.UI.DOM.renderPassage("SA diet");
		const ltEffects = App.UI.DOM.renderPassage("SA long term effects");
		const drugs = App.SlaveAssignment.drugs(slave);
		const relationships = App.UI.DOM.renderPassage("SA relationships");
		const rivalries = App.UI.DOM.renderPassage("SA rivalries");
		const devotion = App.UI.DOM.renderPassage("SA devotion");
		if (!silent) {
			const content = App.UI.DOM.makeElement("div", '', "indent");
			$(content).append(clothes, rules, diet, ltEffects, drugs, relationships, rivalries, document.createElement('br'), devotion);
			return content;
		}
	}

	const stewardessEffects = App.UI.DOM.appendNewElement("p", frag, '', "indent");
	$(stewardessEffects).append(stewardessText());

	if (slaves.length > 0) {
		const intro = App.UI.DOM.appendNewElement("p", frag, '', "indent");
		let r = [];
		if (slaves.length > 1) {
			r.push(`<strong>There are ${slaves.length} slaves working out of the servants' quarters.</strong> They work to`);
		} else {
			const {He} = getPronouns(slaves[0]);
			r.push(`<strong>There is one slave working out of the servants' quarters.</strong> ${He} works to`);
		}
		r.push(`<span class="yellowgreen">reduce</span> your household expenses; having a well-staffed house slightly <span class="green">increases</span> your reputation.`);
		$(intro).append(r.join(' '));
	}

	if (S.Stewardess) {
		/** @type {App.Entity.SlaveState} */
		const slave = S.Stewardess;
		V.i = V.slaveIndices[slave.ID];
		App.Utils.setLocalPronouns(slave); // need this for the includes
		/* apply following SA passages to facility leader */
		if (V.showEWD !== 0) {
			const stewardessEntry = App.UI.DOM.appendNewElement("div", frag, '', "slave-report");
			if (V.seeImages && V.seeReportImages) {
				App.UI.DOM.appendNewElement("div", stewardessEntry, App.Art.SlaveArtElement(slave, 0, 0), ["imageRef", "tinyImg"]);
			}
			$(stewardessEntry).append(`<span class='slave-name'>${SlaveFullName(slave)}</span> is serving as your Stewardess.`);
			$(stewardessEntry).append(standardSlaveReport(slave, false));
		} else {
			standardSlaveReport(slave, true);
		}
	}

	V.servantMilkersMultiplier = 0.5;
	let SQMilk = 0;
	let SQMilkSale = 0;

	for (const slave of slaves) {
		V.i = V.slaveIndices[slave.ID];
		slave.devotion += devBonus;
		if (slave.devotion <= 20 && slave.trust >= -20) {
			slave.devotion -= 5;
			slave.trust -= 5;
		} else if (slave.devotion <= 10) {
			slave.devotion += 2;
		} else if (slave.devotion >= 80) {
			slave.devotion -= 2;
		}
		if (slave.devotion < -20) {
			slave.trust += 3;
		} else if (slave.trust < -50) {
			slave.trust += 2;
		} else if (slave.trust < -30) {
			slave.trust += 1;
		}
		if (slave.health.condition < -80) {
			improveCondition(slave, 20);
		} else if (slave.health.condition < -40) {
			improveCondition(slave, 10);
		} else if (slave.health.condition < 0) {
			improveCondition(slave, 7);
		} else if (slave.health.condition < 90) {
			improveCondition(slave, 3);
		}
		switch (V.servantsQuartersDecoration) {
			case "Arabian Revivalist":
			case "Aztec Revivalist":
			case "Chattel Religionist":
			case "Chinese Revivalist":
			case "Degradationist":
			case "Edo Revivalist":
			case "Egyptian Revivalist":
			case "Roman Revivalist":
			case "Subjugationist":
			case "Supremacist":
				slave.rules.living = "spare";
				break;
			case "Slave Professionalism":
				if (slave.intelligence+slave.intelligenceImplant > 15) {
					slave.rules.living = "normal";
				} else {
					slave.rules.living = "spare";
				}
				break;
			case "Petite Admiration":
			case "Statuesque Glorification":
				if (heightPass(slave)) {
					slave.rules.living = "normal";
				} else {
					slave.rules.living = "spare";
				}
				break;
			default:
				slave.rules.living = "normal";
		}

		App.Utils.setLocalPronouns(slave); // need this for the includes
		if (V.showEWD !== 0) {
			const {He} = getPronouns(slave);
			const slaveEntry = App.UI.DOM.appendNewElement("div", frag, '', "slave-report");
			if (V.seeImages && V.seeReportImages) {
				App.UI.DOM.appendNewElement("div", slaveEntry, App.Art.SlaveArtElement(slave, 0, 0), ["imageRef", "tinyImg"]);
			}
			$(slaveEntry).append(`<span class='slave-name'>${SlaveFullName(slave)}</span> `);
			if (slave.choosesOwnAssignment === 2) {
				$(slaveEntry).append(App.UI.DOM.renderPassage("SA chooses own job"));
			} else {
				$(slaveEntry).append(`is working out of ${V.servantsQuartersName}.`);
			}
			const servantContent = App.UI.DOM.appendNewElement("div", slaveEntry, '', "indent");
			$(servantContent).append(`${He} ${App.SlaveAssignment.servant(slave, stewardessBonus)}`);
			if ((V.servantMilkers === 1) && (slave.lactation > 0)) {
				const milkContent = App.UI.DOM.appendNewElement("div", slaveEntry, '', "indent");
				$(milkContent).append(`${He} ${App.SlaveAssignment.getMilked(slave)}`);
				SQMilk += V.milk;
				SQMilkSale += V.milkSale;
			}
			$(slaveEntry).append(standardSlaveReport(slave, false));
		} else {
			// discard return values silently
			App.SlaveAssignment.servant(slave, stewardessBonus);
			if ((V.servantMilkers === 1) && (slave.lactation > 0)) {
				App.SlaveAssignment.getMilked(slave);
				SQMilk += V.milk;
				SQMilkSale += V.milkSale;
			}
			standardSlaveReport(slave, true);
		}
	}

	if (SQMilk > 0) {
		const milkEffects = App.UI.DOM.appendNewElement("p", frag, '', "indent");
		$(milkEffects).append(`Since your lactating servants spend most of their time working in the penthouse, they use the milkers there, giving ${SQMilk} liters of milk over the week, which is sold for <span class="yellowgreen">${cashFormat(SQMilkSale)}.</span>`);
	}

	if (V.servantsQuartersDecoration !== "standard") {
		const decorationEffects = App.UI.DOM.appendNewElement("p", frag, '', "indent");
		$(decorationEffects).append(`${V.servantsQuartersNameCaps}'s ${V.servantsQuartersDecoration} atmosphere <span class="hotpink">has a minor impact on your servants.</span>`);
	}

	V.servantMilkersMultiplier = 1;
	repX(slaves.length * 20, "servantsQuarters");

	return frag;
};

src/endWeek/servantsQuartersReport.js