diff --git a/src/003-assets/CSS/arcologyBuilding.css b/src/003-assets/CSS/arcologyBuilding.css
index 454882e38f22d141cd6da8551bf7fdf21efd0b1d..7e478d34e2d7e88f1485a524b4af891edb1d84cf 100644
--- a/src/003-assets/CSS/arcologyBuilding.css
+++ b/src/003-assets/CSS/arcologyBuilding.css
@@ -1,30 +1,36 @@
-div.building {
+.building {
 	display: flex;
 	flex-direction: column;
 	width: 100%;
 }
 
-div.building.basement {
+.building.basement {
 	border-top: solid 1px #333333;
 	margin-top: -1px;
 	background-image: repeating-linear-gradient(135deg, transparent, transparent 20px, #333333 20px, #333333 30px);
 }
 
-div.building div.row {
+.building .row {
 	display: flex;
 	flex-direction: row;
-	width: 70%;
+	width: 95%;
 	margin: 0 auto;
 	justify-content: center;
 }
 
-div.building div.outerCell {
+@media only screen and (min-width: 1600px) {
+	.building .row {
+		width: 70%;
+	}
+}
+
+.building .outerCell {
 	/* fill cell fully, part 1: trick to fill the full height even if content is smaller */
 	display: flex;
 	flex-direction: row;
 }
 
-div.building div.innerCell {
+.building .innerCell {
 	margin: 3px;
 	border: 5px solid;
 	padding: 2px;
@@ -35,7 +41,7 @@ div.building div.innerCell {
 	background-color: #111;
 }
 
-div.building div.decorative {
+.building .decorative {
 	outline: white solid 5px;
 	outline-offset: -8px;
 	height: 2em;
@@ -43,133 +49,133 @@ div.building div.decorative {
 
 /* introduction special formatting */
 /* makes all links unusable */
-.intro div.building a {
+.intro .building a {
 	color: white;
 	pointer-events: none;
 	cursor: default;
 }
 
-.intro div.building .hotkey {
+.intro .building .hotkey {
 	display: none;
 }
 
 /* penthouse formatting */
-div.building div.gridWrapper {
+.building .gridWrapper {
 	display: grid;
 }
 
-div.building div.gridWrapper.grid1 {
+.building .gridWrapper.grid1 {
 	grid-template-columns: 100%;
 }
 
-div.building div.gridWrapper.grid2 {
+.building .gridWrapper.grid2 {
 	grid-template-columns: repeat(2, 50%);
 }
 
-div.building div.gridWrapper.grid3 {
+.building .gridWrapper.grid3 {
 	grid-template-columns: repeat(3, 33.3%);
 }
 
-div.building div.gridWrapper div {
+.building .gridWrapper div {
 	display: inline flow-root;
 	line-height: 1.1;
 	padding-bottom: 0.3em;
 }
 
-div.building div.collapsed {
+.building .collapsed {
 	display: inline flow-root;
 	margin: 0 0.2em;
 }
 
 /* border color for each cell */
-div.building div.row div.apartments {
+.building .row .apartments {
 	border-color: limegreen;
 }
 
-div.building div.row div.arcade {
+.building .row .arcade {
 	border-color: deeppink;
 }
 
-div.building div.row div.brothel {
+.building .row .brothel {
 	border-color: violet;
 }
 
-div.building div.row div.barracks {
+.building .row .barracks {
 	border-color: olivedrab;
 }
 
-div.building div.row div.club {
+.building .row .club {
 	border-color: orchid;
 }
 
-div.building div.row div.corporateMarket {
+.building .row .corporateMarket {
 	border-color: purple;
 }
 
-div.building div.row div.dairy {
+.building .row .dairy {
 	border-color: white;
 }
 
-div.building div.row div.denseApartments {
+.building .row .denseApartments {
 	border-color: seagreen;
 }
 
-div.building div.row div.empty {
+.building .row .empty {
 	border-color: lightgray;
 }
 
-div.building div.row div.farmyard {
+.building .row .farmyard {
 	border-color: brown;
 }
 
-div.building div.row div.fsShops {
+.building .row .fsShops {
 	border-color: mediumpurple;
 }
 
-div.building div.row div.manufacturing {
+.building .row .manufacturing {
 	border-color: slategray;
 }
 
-div.building div.row div.markets {
+.building .row .markets {
 	border-color: mediumorchid;
 }
 
-div.building div.row div.nursery {
+.building .row .nursery {
 	border-color: deepskyblue;
 }
 
-div.building div.row div.luxuryApartments {
+.building .row .luxuryApartments {
 	border-color: palegreen;
 }
 
-div.building div.row div.pens {
+.building .row .pens {
 	border-color: goldenrod;
 }
 
-div.building div.row div.penthouse {
+.building .row .penthouse {
 	border-color: teal;
 }
 
-div.building div.row div.pit {
+.building .row .pit {
 	border-color: orangered;
 }
 
-div.building div.row div.private {
+.building .row .private {
 	border-color: red;
 }
 
-div.building div.row div.shops {
+.building .row .shops {
 	border-color: thistle;
 }
 
-div.building div.row div.sweatshops {
+.building .row .sweatshops {
 	border-color: gray;
 }
 
-div.building div.row div.transportHub {
+.building .row .transportHub {
 	border-color: magenta;
 }
 
-div.building div.row div.weaponsManufacturing {
+.building .row .weaponsManufacturing {
 	border-color: springgreen;
 }
diff --git a/src/arcologyBuilding/base.js b/src/arcologyBuilding/base.js
index 4100bda35e4855c8f9136b4c983256d6a679fea3..72f5005883418f8523a65fe9ada5e0636f4e679d 100644
--- a/src/arcologyBuilding/base.js
+++ b/src/arcologyBuilding/base.js
@@ -66,7 +66,6 @@ App.Arcology.facilityCellContent = function(facility, passageName, statsStr) {
 	const report = facility.occupancyReport(false);
 	if (report !== "") {
 		const stats = document.createElement("span");
-		stats.style.whiteSpace = "nowrap";
 		stats.textContent = ` (${report})`;
 		res.append(stats);
 	}
diff --git a/src/events/RECI/butthole.js b/src/events/RECI/butthole.js
index 515c3a21161a12bfa712d58eb5803691caca6d57..0b9bc576b51e6f9ac058e2439c27cba1893a35b0 100644
--- a/src/events/RECI/butthole.js
+++ b/src/events/RECI/butthole.js
@@ -518,7 +518,7 @@ App.Events.RECIButthole = class RECIButthole extends App.Events.BaseEvent {
 			eventSlave.devotion += 2;
 			partnerSlave.devotion += 2;
 
-			return [container];
+			return container;
 		}
 
 		function talk() {
@@ -688,7 +688,7 @@ App.Events.RECIButthole = class RECIButthole extends App.Events.BaseEvent {
 			eventSlave.trust += 4;
 			App.Events.addParagraph(container, t);
 
-			return [container];
+			return container;
 		}
 
 		function assFuck() {
diff --git a/src/events/RESS/moistPussy.js b/src/events/RESS/moistPussy.js
index bdc38648f481e53e57e3c83fdac6950bfc8b8b89..296f40ee3b3755d3182e50a41460f7dbb56348f3 100644
--- a/src/events/RESS/moistPussy.js
+++ b/src/events/RESS/moistPussy.js
@@ -159,7 +159,7 @@ App.Events.RESSMoistPussy = class RESSMoistPussy extends App.Events.BaseEvent {
 			eventSlave.devotion += 5;
 			App.Events.addParagraph(container, t);
 
-			return [container];
+			return container;
 		}
 
 		function pound() {
diff --git a/src/events/RESS/muscles.js b/src/events/RESS/muscles.js
index a109c897f3ff91e951b4ff5cb0133a23669270d5..5e0a0ea033f65a6283a00f323208f7969632e78d 100644
--- a/src/events/RESS/muscles.js
+++ b/src/events/RESS/muscles.js
@@ -184,7 +184,7 @@ App.Events.RESSMuscles = class RESSMuscles extends App.Events.BaseEvent {
 		}
 
 		function compliment() {
-			return [`${He} finishes posing with an impressive display of ${his} obliques. ${He} walks powerfully to the shower, ${his} ripped buttocks delineating each step. The shower is glass-walled. As ${he} washes, several of your other slaves are waking up and starting their days. They can't help but stare as ${eventSlave.slaveName} soaps ${himself}. ${eventSlave.slaveName} enjoys the attention.`];
+			return `${He} finishes posing with an impressive display of ${his} obliques. ${He} walks powerfully to the shower, ${his} ripped buttocks delineating each step. The shower is glass-walled. As ${he} washes, several of your other slaves are waking up and starting their days. They can't help but stare as ${eventSlave.slaveName} soaps ${himself}. ${eventSlave.slaveName} enjoys the attention.`;
 		}
 	}
 };
diff --git a/src/events/RESS/retchingCum.js b/src/events/RESS/retchingCum.js
index b91252c2016b36ca0767640e017cfdcf58ee2c84..05c48157f205fa4be9eb31488645922bc6458b1d 100644
--- a/src/events/RESS/retchingCum.js
+++ b/src/events/RESS/retchingCum.js
@@ -78,20 +78,20 @@ App.Events.RESSRetchingCum = class RESSRetchingCum extends App.Events.BaseEvent
 			eventSlave.devotion -= 5;
 			eventSlave.trust += 5;
 			eventSlave.dietCum = 0;
-			return [`You see how ${eventSlave.slaveName} is suffering and you decide to reconsider ${his} dietary prescription. You instruct ${V.assistant.name} to change ${eventSlave.slaveName}'s diet to exclude cum for now. Slaves who can't eat are unhealthy, and unhealthy slaves are unprofitable slaves. ${He} is now <span class="mediumorchid">more confident that ${he} can resist you and get ${his} way,</span> ${he} also <span class="mediumaquamarine">trusts you a little more</span> to look after ${his} well being.`];
+			return `You see how ${eventSlave.slaveName} is suffering and you decide to reconsider ${his} dietary prescription. You instruct ${V.assistant.name} to change ${eventSlave.slaveName}'s diet to exclude cum for now. Slaves who can't eat are unhealthy, and unhealthy slaves are unprofitable slaves. ${He} is now <span class="mediumorchid">more confident that ${he} can resist you and get ${his} way,</span> ${he} also <span class="mediumaquamarine">trusts you a little more</span> to look after ${his} well being.`;
 		}
 		function heavy() {
 			eventSlave.devotion -= 3;
 			eventSlave.trust -= 3;
 			eventSlave.dietCum = 2;
-			return [`You instruct ${V.assistant.name} to double down on ${eventSlave.slaveName}'s cum diet. Ungrateful little sluts who retch up their expensive food sometimes need tough love. Making ${his} cum-food thicker and more concentrated might help ${him} to learn that no matter how bad things seem, you can always make them worse. Initially ${his} new heavy cum diet makes no difference in ${his} ability to keep it down, but you tell ${him} to give it some time. Eventually ${he} will learn to appreciate cum as the primary ingredient in everything ${he} ingests. All of your future cumsluts do, sooner or later. ${His} pathetic tears reveal how <span class="gold">helpless ${he} feels,</span> but they don't hide the <span class="mediumorchid">streak of rebelliousness</span> that remains burning inside ${him}.`];
+			return `You instruct ${V.assistant.name} to double down on ${eventSlave.slaveName}'s cum diet. Ungrateful little sluts who retch up their expensive food sometimes need tough love. Making ${his} cum-food thicker and more concentrated might help ${him} to learn that no matter how bad things seem, you can always make them worse. Initially ${his} new heavy cum diet makes no difference in ${his} ability to keep it down, but you tell ${him} to give it some time. Eventually ${he} will learn to appreciate cum as the primary ingredient in everything ${he} ingests. All of your future cumsluts do, sooner or later. ${His} pathetic tears reveal how <span class="gold">helpless ${he} feels,</span> but they don't hide the <span class="mediumorchid">streak of rebelliousness</span> that remains burning inside ${him}.`;
 		}
 
 		function reduce() {
 			eventSlave.devotion += 2;
 			eventSlave.trust += 2;
 			eventSlave.dietCum = 1;
-			return [`${eventSlave.slaveName} is on a very heavy cum diet, and it's possible you're forcing ${him} to take too much, too soon. You decide to give ${him} a break and instruct ${V.assistant.name} to reduce, but not eliminate the amount of cum in ${his} diet. Although it doesn't immediately make ${him} hate cum any less, <span class="hotpink">${he} appreciates your willingness</span> to make things a little less unpleasant for ${him}. <span class="mediumaquamarine">${He} is a little less afraid of you too,</span> although not as much as if you'd taken ${him} off ${his} cum diet altogether.`];
+			return `${eventSlave.slaveName} is on a very heavy cum diet, and it's possible you're forcing ${him} to take too much, too soon. You decide to give ${him} a break and instruct ${V.assistant.name} to reduce, but not eliminate the amount of cum in ${his} diet. Although it doesn't immediately make ${him} hate cum any less, <span class="hotpink">${he} appreciates your willingness</span> to make things a little less unpleasant for ${him}. <span class="mediumaquamarine">${He} is a little less afraid of you too,</span> although not as much as if you'd taken ${him} off ${his} cum diet altogether.`;
 		}
 
 		function double() {
diff --git a/src/events/RESS/waistlineWoes.js b/src/events/RESS/waistlineWoes.js
index b6fc1244d05d07e893106e62301fd8d70accd2eb..2dfa25fe0a388743e871623384b9a86af8803025 100644
--- a/src/events/RESS/waistlineWoes.js
+++ b/src/events/RESS/waistlineWoes.js
@@ -402,7 +402,7 @@ App.Events.RESSWaistlineWoes = class RESSWaistlineWoes extends App.Events.BaseEv
 			eventSlave.weight -= 5;
 			App.Events.addParagraph(frag, t);
 
-			return [frag];
+			return frag;
 		}
 
 		function shoo() {
diff --git a/src/events/debugEvent.js b/src/events/debugEvent.js
new file mode 100644
index 0000000000000000000000000000000000000000..8af32bffca568150ba04abb0c00402a6e0740b21
--- /dev/null
+++ b/src/events/debugEvent.js
@@ -0,0 +1,79 @@
+/** @param {string} eventName
+ * @returns {DocumentFragment}
+ */
+App.Events.debugEvent = function(eventName) {
+	const frag = document.createDocumentFragment();
+	/** @type {App.Events.BaseEvent} */
+	const event = eval(`new ${eventName}`);
+
+	function makeCastList() {
+		const cast = document.createDocumentFragment();
+		const actorReqs = event.actorPrerequisites();
+		let missingCast = false;
+		for (let i = 0; i < actorReqs.length; ++i) {
+			if (!event.actors[i]) {
+				missingCast = true;
+			}
+			App.UI.DOM.appendNewElement("div", cast, `Actor ${i}: ${event.actors[i] ? SlaveFullName(getSlave(event.actors[i])) : 'not yet cast'}`);
+		}
+		if (!missingCast) {
+			App.UI.DOM.appendNewElement("div", cast, App.UI.DOM.link('Run event now', (evt) => { V.event = evt; }, [event], "JS Random Event"));
+		} else {
+			App.UI.DOM.appendNewElement("div", cast, "All actors must be cast to run event.", "note");
+		}
+		return cast;
+	}
+
+	function castSlave(slave, index) {
+		event.actors[index] = slave.ID;
+		$('#castList').empty().append(makeCastList());
+	}
+
+	function testPredicate(outDiv, p, ...args) {
+		let passed = false;
+		try {
+			passed = p(...args);
+		} catch (ex) {
+			App.UI.DOM.appendNewElement("div", outDiv, p.name || p.toString() + ": Exception: " + ex.toString(), "major-warning");
+		}
+		return passed;
+	}
+
+	const prereqs = App.UI.DOM.appendNewElement("div", frag);
+	App.UI.DOM.appendNewElement("span", prereqs, `${eventName} - Global Prerequisites:`, "note");
+	if (event instanceof App.Events.BaseEvent) {
+		let anyFailed = false;
+		for (const p of event.eventPrerequisites()) {
+			let passed = testPredicate(prereqs, p);
+			anyFailed = anyFailed || !passed;
+			App.UI.DOM.appendNewElement("div", prereqs, p.name || p.toString(), passed ? "green" : "red");
+		}
+		if (!anyFailed) { // actor casting
+			App.UI.DOM.appendNewElement("div", frag, "All global prerequisites passed, proceeding to casting...", "green");
+			App.UI.DOM.appendNewElement("hr", frag);
+			const castList = App.UI.DOM.appendNewElement("div", frag, makeCastList());
+			castList.id = "castList";
+			App.UI.DOM.appendNewElement("hr", frag);
+			const actorReqs = event.actorPrerequisites();
+			for (let i = 0; i < actorReqs.length; ++i) {
+				let tab = App.UI.DOM.appendNewElement("div", frag); // TODO: put these in tabs?
+				for (const slave of V.slaves) {
+					let slaveDiv = App.UI.DOM.appendNewElement("div", tab, App.UI.DOM.makeElement("span", SlaveFullName(slave), "slave-name"));
+					let slaveFails = false;
+					for (const p of actorReqs[i]) {
+						let passed = testPredicate(slaveDiv, p, slave);
+						slaveFails = slaveFails || !passed;
+						App.UI.DOM.appendNewElement("div", slaveDiv, p.name || p.toString(), [passed ? "green" : "red", "indent"]);
+					}
+					if (!slaveFails) {
+						App.UI.DOM.appendNewElement("div", slaveDiv, App.UI.DOM.link("Choose this slave", castSlave, [slave, i]), "indent");
+					}
+					App.UI.DOM.appendNewElement("hr", tab);
+				}
+			}
+		}
+	} else {
+		App.UI.DOM.appendNewElement("div", prereqs, "Specified name does not resolve to an event.", "major-warning");
+	}
+	return frag;
+};
diff --git a/src/events/eventUtils.js b/src/events/eventUtils.js
index cbc83be5fb51a3c6dc802004e62b55b6f71a3185..141c1e108f7f068f0ed205496264df48ab480b09 100644
--- a/src/events/eventUtils.js
+++ b/src/events/eventUtils.js
@@ -143,9 +143,9 @@ App.Events.addParagraph = function(node, sentences) {
 	node.appendChild(para);
 };
 
-/** result handler callback - process the result and return an array of mixed strings and DOM nodes
+/** result handler callback - process the result and return an array of mixed strings and DOM nodes, or a single string or DOM node
  * @callback resultHandler
- * @returns {Array<string|HTMLElement|DocumentFragment>}
+ * @returns {Array<string|HTMLElement|DocumentFragment>|string|HTMLElement|DocumentFragment}
  */
 /** a response to an event, and its result */
 App.Events.Result = class {
@@ -165,7 +165,12 @@ App.Events.Result = class {
 	 */
 	handle(resultSpanID) {
 		let frag = document.createDocumentFragment();
-		$(frag).append(...App.Events.spaceSentences(this.handler()));
+		let contents = this.handler();
+		if (Array.isArray(contents)) {
+			$(frag).append(...App.Events.spaceSentences(contents));
+		} else {
+			$(frag).append(contents);
+		}
 		App.UI.DOM.replace(`#${resultSpanID}`, frag);
 	}
 
diff --git a/src/events/randomEvent.js b/src/events/randomEvent.js
index 9638ea3f89f4a136063c4f83794b3b10fc75fbd6..929702590a8a3403a14a66a75118f2b335963854 100644
--- a/src/events/randomEvent.js
+++ b/src/events/randomEvent.js
@@ -3,11 +3,10 @@
  * Nonindividual events are not provided any event slave and should cast one themselves.
  */
 
-/** get a list of possible individual event based on a given available main actor
- * @param {App.Entity.SlaveState} slave
+/** get a list of possible individual events
  * @returns {Array<App.Events.BaseEvent>}
  */
-App.Events.getIndividualEvents = function(slave) {
+App.Events.getIndividualEvents = function() {
 	return [
 		// instantiate all possible random individual events here
 		// example: new App.Events.TestEvent(),
@@ -21,9 +20,7 @@ App.Events.getIndividualEvents = function(slave) {
 		new App.Events.RECIButthole(),
 		new App.Events.RECIFuta(),
 		new App.Events.RECIOrientation(),
-	]
-	.filter(e => (e.eventPrerequisites().every(p => p()) && e.castActors(slave)))
-	.reduce((res, cur) => res.concat(Array(cur.weight).fill(cur)), []);
+	];
 };
 
 /** get a list of possible nonindividual events
@@ -35,11 +32,21 @@ App.Events.getNonindividualEvents = function() {
 		// example: new App.Events.TestEvent(),
 		new App.Events.REDevotees(),
 		new App.Events.RERelativeRecruiter(),
-	]
-	.filter(e => (e.eventPrerequisites().every(p => p()) && e.castActors(null)))
-	.reduce((res, cur) => res.concat(Array(cur.weight).fill(cur)), []);
+	];
 };
 
+/** choose a valid, castable event from the given event list
+ * @param {Array<App.Events.BaseEvent>} eventList - list of events to filter
+ * @param {App.Entity.SlaveState} [slave] - event slave (mandatory to cast in first actor slot).  omit for nonindividual events.
+ * @returns {Array<App.Events.BaseEvent>}
+ */
+App.Events.getValidEvents = function(eventList, slave) {
+	return eventList
+		.filter(e => (e.eventPrerequisites().every(p => p()) && e.castActors(slave)))
+		.reduce((res, cur) => res.concat(Array(cur.weight).fill(cur)), []);
+};
+
+
 /* --- below here is a bunch of workaround crap because we have to somehow persist event selection through multiple twine passages. ---
  * eventually all this should go away, and we should use just one simple passage for both selection and execution, so everything can be kept in object form instead of being continually serialized and deserialized.
  * we need to be able to serialize/deserialize the active event anyway so that saves work right, so this mechanism just piggybacks on that capability so the event passages don't need to be reworked all at once
@@ -47,13 +54,13 @@ App.Events.getNonindividualEvents = function() {
 
 /** get a stringified list of possible individual events as fake passage names - TODO: kill me */
 App.Events.getIndividualEventsPassageList = function(slave) {
-	const events = App.Events.getIndividualEvents(slave);
+	const events = App.Events.getValidEvents(App.Events.getIndividualEvents(), slave);
 	return events.map(e => `JSRE ${e.eventName}:${JSON.stringify(e.toJSON())}`);
 };
 
 /** get a stringified list of possible individual events as fake passage names - TODO: kill me */
 App.Events.getNonindividualEventsPassageList = function() {
-	const events = App.Events.getNonindividualEvents();
+	const events = App.Events.getValidEvents(App.Events.getNonindividualEvents());
 	return events.map(e => `JSRE ${e.eventName}:${JSON.stringify(e.toJSON())}`);
 };
 
diff --git a/src/facilities/nursery/widgets/children/childSummary.js b/src/facilities/nursery/widgets/children/childSummary.js
index 8a0322fc34b2e2eb20ad11c4b6e8ee667c2c7f5e..0ba86b5aa61596fb29fb5444472f39a49df9921b 100644
--- a/src/facilities/nursery/widgets/children/childSummary.js
+++ b/src/facilities/nursery/widgets/children/childSummary.js
@@ -133,13 +133,11 @@ App.Facilities.Nursery.ChildSummary = function(child) {
 			}
 			r += `</span> `;
 		} else if (abbreviate.hormoneBalance === 2) {
-			r += `<span class=`;
 			if (child.hormoneBalance <= -21) {
-				r += `"deepskyblue"`;
+				r += `<span class="deepskyblue"> `;
 			} else {
-				r += `"pink"`;
+				r += `<span class="pink"> `;
 			}
-			r += `> `;
 			if (child.hormoneBalance < -400) {
 				r += `Overwhelmingly masculine`;
 			} else if (child.hormoneBalance <= -300) {
diff --git a/src/uncategorized/randomEventSelect.tw b/src/uncategorized/randomEventSelect.tw
index e1cb5f31aeff0100cd470b2429a35adef1120e81..18efed7f362b4816d571d74d13ac6429f62ee922 100644
--- a/src/uncategorized/randomEventSelect.tw
+++ b/src/uncategorized/randomEventSelect.tw
@@ -34,3 +34,15 @@
 DEBUG:
 <br>
 [[RE no event]] | <<print "[[Go back to previous passage: '" + previous() + "'|previous()][$activeSlave = 0, $eventSlave = 0]] | [[Go all the way back to Scheduled Event|Scheduled Event][$activeSlave = 0, $eventSlave = 0]]">>
+<br><br>
+
+Or enter a fully qualified event name to debug a specific unlisted JS event:<br>
+<<textbox "_evtName" "" autofocus>>
+<<link "Check Prerequisites and Casting">>
+	<<script>>$('#debugOut').empty().append(App.Events.debugEvent(State.temporary.evtName));<</script>>
+<</link>><br>
+//(for example, "App.Events.RESSMuscles")//<br><br>
+
+<span id="debugOut">
+	/* results gets populated here by jQuery */
+</span>