diff --git a/devNotes/colorCSS.txt b/devNotes/colorCSS.txt
index b0f4d786f71727202a8bdcb26d1ec7eed6c0bbd8..64f6398d673e407a86100861e0bcac5374aa6c8d 100644
--- a/devNotes/colorCSS.txt
+++ b/devNotes/colorCSS.txt
@@ -3,7 +3,7 @@ class names that are not final are marked, this list is NOT exhaustive and subje
 Note for mass replacing: The following cases have to be checked:
 	@@.trust.inc;
 	<span class="trust inc">
-	App.UI.DOM.makeSpan('string', ['trust', 'inc']);
+	App.UI.DOM.makeElement('string', 'string', ['trust', 'inc']);
 
 CLASS         -   COLOR
 
diff --git a/src/004-base/arcologyBuilding.js b/src/004-base/arcologyBuilding.js
index c9999c606dab850173f65cc273de6843755683d5..262d9d94a5795cbd6f0a091ade74d7c6d1fedf02 100644
--- a/src/004-base/arcologyBuilding.js
+++ b/src/004-base/arcologyBuilding.js
@@ -155,7 +155,7 @@ App.Arcology.Cell.BaseCell = class extends App.Entity.Serializable {
 		if (cost > 0 || note === undefined) {
 			note = ` Costs ${cashFormat(cost)}${note !== undefined ? ` ${note}` : ""}.`;
 		}
-		div.append(App.UI.DOM.makeSpan(note, "detail"));
+		App.UI.DOM.appendNewElement("span", note, div, "detail");
 
 		if (domNote !== undefined) {
 			div.append(domNote); // this only exists for the farmyard, remove once that is out of alpha
diff --git a/src/arcologyBuilding/manufacturing.js b/src/arcologyBuilding/manufacturing.js
index a29724021cff2704e75e4ca57b6e6f61fa761278..545bb65e7e5c2f98876d2da271f22c9b4cb5953f 100644
--- a/src/arcologyBuilding/manufacturing.js
+++ b/src/arcologyBuilding/manufacturing.js
@@ -65,7 +65,7 @@ App.Arcology.Cell.Manufacturing = class extends App.Arcology.Cell.BaseCell {
 			case "Weapon Manufacturing":
 				return App.UI.DOM.passageLink("Weapons Manufacturing", "weaponsManufacturing");
 			default:
-				return App.UI.DOM.makeSpan(`ERROR: invalid type: ${this.type}`, "error");
+				return App.UI.DOM.makeElement("span", `ERROR: invalid type: ${this.type}`, "error");
 		}
 	}
 
@@ -138,8 +138,8 @@ App.Arcology.Cell.Manufacturing = class extends App.Arcology.Cell.BaseCell {
 
 			const paragraph = document.createElement("p");
 
-			paragraph.append(App.UI.DOM.makeDiv(MenialPopCap()),
-				App.UI.DOM.makeDiv(`In total you are able to personally house a total of ${num(V.PopCap)} menial slaves.`));
+			paragraph.append(App.UI.DOM.makeElement("div", MenialPopCap()),
+				App.UI.DOM.makeElement("div", `In total you are able to personally house a total of ${num(V.PopCap)} menial slaves.`));
 
 			if (V.menials + V.menialBioreactors + V.fuckdolls > 0) {
 				let r = "You own ";
@@ -205,7 +205,7 @@ App.Arcology.Cell.Manufacturing = class extends App.Arcology.Cell.BaseCell {
 							thisCell.type = "Farmyard";
 						}, cost, "and will incur upkeep costs",
 						// this only exists for the farmyard, remove feature once that is out of alpha
-						App.UI.DOM.makeSpan("Alpha Content!", "warning")
+						App.UI.DOM.makeElement("span", "Alpha Content!", "warning")
 					));
 				}
 			}
diff --git a/src/arcologyBuilding/markets.js b/src/arcologyBuilding/markets.js
index 35bb94ba69f89b5cb950def07a38bccb62b81ba4..ac6c74bb9edc24a1d94c12b653ffb10b7c2d6332 100644
--- a/src/arcologyBuilding/markets.js
+++ b/src/arcologyBuilding/markets.js
@@ -53,7 +53,7 @@ App.Arcology.Cell.Market = class extends App.Arcology.Cell.BaseCell {
 			case "Corporate Market":
 				return App.UI.DOM.passageLink("Corporate Market", "Corporate Market");
 			default:
-				return App.UI.DOM.makeSpan("ERROR: invalid type: " + this.type, "error");
+				return App.UI.DOM.makeElement("span", "ERROR: invalid type: " + this.type, "error");
 		}
 	}
 
diff --git a/src/arcologyBuilding/penthouse.js b/src/arcologyBuilding/penthouse.js
index bf7fb1923eafdc6e2b570ad21005ed040b8bb04f..458774aa974367fab4843b798a1e286b6cc5b00f 100644
--- a/src/arcologyBuilding/penthouse.js
+++ b/src/arcologyBuilding/penthouse.js
@@ -25,7 +25,7 @@ App.Arcology.Cell.Penthouse = class extends App.Arcology.Cell.BaseCell {
 		const fragment = document.createDocumentFragment();
 
 		const link = App.UI.DOM.passageLink("Penthouse", "Manage Penthouse");
-		const hotkey = App.UI.DOM.makeSpan("[P]", "hotkey");
+		const hotkey = App.UI.DOM.makeElement("span", "[P]", "hotkey");
 		if (V.verticalizeArcologyLinks === 0) {
 			const div = document.createElement("div");
 			div.append(link, " ", hotkey);
@@ -96,7 +96,7 @@ App.Arcology.Cell.Penthouse = class extends App.Arcology.Cell.BaseCell {
 			const desc = `(${numberWithPluralOne(V.incubator - V.tanks.length, "empty tank")})`;
 
 			if (V.readySlaves > 0) {
-				wrapper.append(createFacilityDiv(link, desc, App.UI.DOM.makeSpan("[!]", "noteworthy")));
+				wrapper.append(createFacilityDiv(link, desc, App.UI.DOM.makeElement("span", "[!]", "noteworthy")));
 			} else {
 				wrapper.append(createFacilityDiv(link, desc));
 			}
diff --git a/src/arcologyBuilding/shops.js b/src/arcologyBuilding/shops.js
index b420082eddebcec7a74d260c6e44c2d171f5b95a..3d2d7cd3da8f08a2b206997cbaab4bf3a68c38f7 100644
--- a/src/arcologyBuilding/shops.js
+++ b/src/arcologyBuilding/shops.js
@@ -188,7 +188,7 @@ App.Arcology.Cell.Shop = class extends App.Arcology.Cell.BaseCell {
 				break;
 			case "Roman Revivalist":
 				fragment.append("dedicated to Roman Revivalism. Since the forums are out on the arcology's plazas, there are fewer stores here. There are eateries, from which the sharp smell of ",
-					App.UI.DOM.makeSpan("garum", "note"),
+					App.UI.DOM.makeElement("span", "garum", "note"),
 					" is distinctly identifiable, but most of the space is occupied by hypocaust baths, which are free to enter but include various concession stands run by slaves.",
 					App.UI.DOM.linkReplace("Clean yourself",
 						"A good Roman trip to the baths serves to cleanse, but it's a social experience, too. After being oiled down by a skilled slave, you work out in the proper nude, and then have the oil and any dirt scraped off your skin with by another slave. Then you make your way across the heated floor through a set of baths of varying temperatures, ending in a large and egalitarian space where many naked citizens of the new Rome are sharing the news of the day. You're welcomed with surprise, but also with comradeship, and made to feel welcome."));
@@ -205,11 +205,11 @@ App.Arcology.Cell.Shop = class extends App.Arcology.Cell.BaseCell {
 				break;
 			case "Edo Revivalist":
 				fragment.append("dedicated to Edo Revivalism. There are strict restrictions on the establishments' décor here, so ",
-					App.UI.DOM.makeSpan("tatami", "note"),
+					App.UI.DOM.makeElement("span", "tatami", "note"),
 					" mats and paper partitions are ubiquitous. There are handsome ",
-					App.UI.DOM.makeSpan("sake", "note"),
+					App.UI.DOM.makeElement("span", "sake", "note"),
 					" shops and tea rooms offering the traditional ceremony, and ",
-					App.UI.DOM.makeSpan("kabuki", "note"),
+					App.UI.DOM.makeElement("span", "kabuki", "note"),
 					" theaters offering the traditional performance, with modern plots and themes. ",
 					App.UI.DOM.linkReplace("See a show",
 						"As soon as you enter a theater, the play stops, and refined slave attendants usher you forward to the place of honor. None of the citizens present resent the interruption; having you here is a great addition to the performance. The actors bow deeply to you and resume. The classical dance drama is almost impenetrable to outsiders, and the modernity of the characters and events would not be at all decipherable. Once you catch the thread, though, the richness of the allegory towards Free Cities personages and events is quite enjoyable."));
@@ -293,7 +293,7 @@ App.Arcology.Cell.Shop = class extends App.Arcology.Cell.BaseCell {
 				}
 				break;
 			default:
-				fragment.append(App.UI.DOM.makeSpan(`ERROR: bad shop type: ${this.type}`, "error"));
+				App.UI.DOM.appendNewElement("span", `ERROR: bad shop type: ${this.type}`, fragment, "error");
 		}
 
 		if (this.owner === 1 && this.type === "Shops") {
diff --git a/src/js/main.js b/src/js/main.js
index c817c75707eec6c8c924fff53825075fe130e436..99f8ed023c0953de566467663fdf8afc5419f950 100644
--- a/src/js/main.js
+++ b/src/js/main.js
@@ -25,7 +25,7 @@ App.MainView.useGuard = function() {
 		return outerDiv;
 	}
 
-	outerDiv.append(App.UI.DOM.makeSpan(App.Interact.guardPose(guard), "scene-intro"));
+	App.UI.DOM.appendNewElement("span", App.Interact.guardPose(guard), outerDiv, "scene-intro");
 
 	function setEnvironment() {
 		V.activeSlave = guard;
diff --git a/src/js/slaveListing.js b/src/js/slaveListing.js
index 4c9bd8e53b6aac555648479cdb34302eb43534b3..9e67529d96a1e51ff738758598ec8010786ced52 100644
--- a/src/js/slaveListing.js
+++ b/src/js/slaveListing.js
@@ -462,16 +462,16 @@ App.UI.SlaveList.Decoration = {};
  */
 App.UI.SlaveList.Decoration.penthousePositions = (slave) => {
 	if (App.Data.Facilities.headGirlSuite.manager.assignment === slave.assignment) {
-		return App.UI.DOM.makeSpan('HG', ['lightcoral', 'strong']);
+		return App.UI.DOM.makeElement("span", 'HG', ['lightcoral', 'strong']);
 	}
 	if (App.Data.Facilities.penthouse.manager.assignment === slave.assignment) {
-		return App.UI.DOM.makeSpan('RC', ['lightcoral', 'strong']);
+		return App.UI.DOM.makeElement("span", 'RC', ['lightcoral', 'strong']);
 	}
 	if (App.Data.Facilities.armory.manager.assignment === slave.assignment) {
-		return App.UI.DOM.makeSpan('BG', ['lightcoral', 'strong']);
+		return App.UI.DOM.makeElement("span", 'BG', ['lightcoral', 'strong']);
 	}
 	if (Array.isArray(State.variables.personalAttention) && State.variables.personalAttention.findIndex(s => s.ID === slave.ID) !== -1) {
-		return App.UI.DOM.makeSpan('PA', ['lightcoral', 'strong']);
+		return App.UI.DOM.makeElement("span", 'PA', ['lightcoral', 'strong']);
 	}
 	return null;
 };
@@ -1187,11 +1187,11 @@ App.UI.SlaveList.slaveSelectionList = function() {
 		const listPostNote = options.expCheck ?
 			(options.postNote ?
 				(s, i) => options.expCheck(s) ? App.UI.DOM.combineNodes(
-					App.UI.DOM.makeSpan("Has applicable career experience.", "lime"),
+					App.UI.DOM.makeElement("span", "Has applicable career experience.", "lime"),
 					document.createElement("br"),
 					options.postNote(s, i)
 				) : options.postNote(s, i) :
-				(s) => options.expCheck(s) ? App.UI.DOM.makeSpan("Has applicable career experience.", "lime") : null) :
+				(s) => options.expCheck(s) ? App.UI.DOM.makeElement("span", "Has applicable career experience.", "lime") : null) :
 			options.postNote ?
 				(s, i) => options.postNote(s, i) :
 				() => null;
diff --git a/src/js/utilsDOM.js b/src/js/utilsDOM.js
index 9a1469dfc5bf94eda201d03c1bdd1219fef8cdd4..033c063ab4c407032a8bb7e8c1ba93222214c84f 100644
--- a/src/js/utilsDOM.js
+++ b/src/js/utilsDOM.js
@@ -123,30 +123,35 @@ App.UI.DOM.disabledLink = function(link, reasons) {
 };
 
 /**
- * @param {string} text
- * @param {string|string[]} [classNames]
+ * @param {string} tag - valid HTML tag
+ * @param {string|Node} content
+ * @param {string|Array<string>} [classNames]
+ * @returns {HTMLElement}
  */
-App.UI.DOM.makeSpan = function makeSpan(text, classNames) {
-	let r = document.createElement("span");
+App.UI.DOM.makeElement = function(tag, content, classNames) {
+	const element = document.createElement(tag);
 	if (classNames !== undefined) {
 		if (Array.isArray(classNames)) {
-			r.classList.add(...classNames);
+			element.classList.add(...classNames);
 		} else {
-			r.classList.add(classNames);
+			element.classList.add(classNames);
 		}
 	}
-	r.innerHTML = text;
-	return r;
+	element.append(content);
+	return element;
 };
 
 /**
- * @param {Node|string} content
- * @returns {HTMLDivElement}
+ * @param {string} tag - valid HTML tag
+ * @param {string|Node} content
+ * @param {ParentNode} parent
+ * @param {string|Array<string>} [classNames]
+ * @returns {HTMLElement}
  */
-App.UI.DOM.makeDiv = function(content) {
-	const div = document.createElement("div");
-	div.append(content);
-	return div;
+App.UI.DOM.appendNewElement = function(tag, content, parent, classNames) {
+	const element = App.UI.DOM.makeElement(tag, content, classNames);
+	parent.append(element);
+	return element;
 };
 
 /**