diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 84a33fb8a964d1111a5d6f9d7d9c803db172e9dd..be5c421d4943c6eb5840d48431a297918cc87475 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -28,7 +28,7 @@ These tools are not required, but are suggested and will make working on FC easi
 4. Follow the install steps until you get to the `Welcome to FC development!...` menu and then select `Exit`
 5. Open the directory in your preferred editor/IDE
 
-**Make sure you have ESLint, TypeScript, and spell checking (preferably with cSpell compatiblity) support installed and enabled (if avaliable) in your preferred editor/IDE to catch formatting, type def, and spelling errors**
+**Make sure you have ESLint, TypeScript, and spell checking (preferably with cSpell compatibility) support installed and enabled (if available) in your preferred editor/IDE to catch formatting, type def, and spelling errors**
 
 <details><summary>Recommended editor/IDE plugins/extensions</summary>
 
diff --git a/cspell.json b/cspell.json
index b851f9b8a06a00cdfd64edf34a79d1d9ff070b6f..8877790d8037218caa6611d7f697fbb3a0089647 100644
--- a/cspell.json
+++ b/cspell.json
@@ -17,6 +17,7 @@
         "devTools/minify",
         "devTools/tweeGo",
         "devTools/types/tippy",
+        "js/001-lib/idb.js",
         "js/003-data/arcologyNames.js",
         "js/003-data/miscDataNames.js",
         "js/003-data/poses.js",
@@ -33,6 +34,7 @@
         "src/npc/databases/dSlavesDatabase.js",
         "src/npc/databases/ddSlavesDatabase.js",
         "src/npc/databases/cheatmodeDatabase.js",
+        "submodules",
         "*.min.js",
         "*.json",
         "*.svg",
@@ -221,6 +223,7 @@
         "fanbase",
         "façade",
         "fcfa",
+        "fchost",
         "fcnn",
         "fctv",
         "felidae",
@@ -337,6 +340,7 @@
         "preggos",
         "pregmod",
         "prereqs",
+        "prising",
         "progeria",
         "pudge",
         "qipao",
@@ -421,4 +425,4 @@
         "xochiquetzal",
         "école"
     ]
-}
\ No newline at end of file
+}
diff --git a/js/utils.js b/js/utils.js
index b2b46ec4bb7a5a21d09ba098c26a69ebe62a008c..0ba85550c549f20f2fb5f66ecbb162fe0ee65677 100644
--- a/js/utils.js
+++ b/js/utils.js
@@ -1,5 +1,5 @@
 /* eslint no-unused-vars: [2, { "vars": "local" }] */
-// cSpell:ignore yxxx
+// cSpell:ignore yxxx, ØSTER
 
 /* This file contains only JS functions without dependencies on FC specific variables/conventions and do not rely on
  * custom functions outside this file
diff --git a/src/events/RESS/desperateBreeder.js b/src/events/RESS/desperateBreeder.js
index 749d233fe3ce1cc2dc6391b96f71244f140f091c..0b745b17f85733cea94dac1081ce0cca6549c107 100644
--- a/src/events/RESS/desperateBreeder.js
+++ b/src/events/RESS/desperateBreeder.js
@@ -31,7 +31,7 @@ App.Events.RESSDesperateBreeder = class RESSDesperateBreeder extends App.Events.
 	execute(node) {
 		const [eventSlave] = this.actors.map(a => getSlave(a));
 		const {
-			He, he, His, his, him, himself, women, girl
+			He, he, His, his, him, himself, girl
 		} = getPronouns(eventSlave);
 		const {title: Master, say} = getEnunciation(eventSlave);
 		const {womenPC} = getPronouns(V.PC).appendSuffix("PC");
@@ -112,7 +112,7 @@ App.Events.RESSDesperateBreeder = class RESSDesperateBreeder extends App.Events.
 
 			t.push(`If ${he} wants to do all the work, then you'll just lie back and enjoy the show.`);
 			if (canTalk(eventSlave)) {
-				t.push(`${He} squeels with glee,`);
+				t.push(`${He} squeals with glee,`);
 				t.push(`"${Spoken(eventSlave, `Sure thing! That first load should be just about ready, so we'll definitely be going again. You don't mind that, right ${Master}?`)}"`);
 			} else {
 				t.push(`${He} smiles happily as ${he} begins riding your dick.`);
@@ -209,7 +209,7 @@ App.Events.RESSDesperateBreeder = class RESSDesperateBreeder extends App.Events.
 					} else {
 						t.push(`You can't help but notice ${his} limp dick flopping about and the precum being flung from its tip. You order ${him} to get it under control, but ${he} is too lost in ${his} growing pleasure to listen. Worse still, you're pinned under ${his} weight and have no chance of avoiding the coming ejaculation, nor any that follow it.`);
 						if (cumShot >= 1) {
-							t.push(`Like a loose firehose, ${he} sprays a jet semen hapazardly across you, ${himself} and ${his} surroundings, thoroughly soaking everything in range.`);
+							t.push(`Like a loose firehose, ${he} sprays a jet semen haphazardly across you, ${himself} and ${his} surroundings, thoroughly soaking everything in range.`);
 						} else if (cumShot >= .1) {
 							t.push(`You block most of ${his} cum from splashing across your face, but it still ends up all over the place.`);
 						} else {
@@ -279,7 +279,7 @@ App.Events.RESSDesperateBreeder = class RESSDesperateBreeder extends App.Events.
 			} else {
 				t.push(`${He} glares ferociously at you, obviously intending to take what ${he} came here for by force if necessary.`);
 			}
-			t.push(`As ${he} slames down on your erect dick, it becomes clear just how far ${he} planned this out; ${he} has been keeping you on edge so that just a few quick bounces are all it takes to bring you to climax.`);
+			t.push(`As ${he} slams down on your erect dick, it becomes clear just how far ${he} planned this out; ${he} has been keeping you on edge so that just a few quick bounces are all it takes to bring you to climax.`);
 			if (canTalk(eventSlave)) {
 				t.push(`${He} leans in close and whispers,`);
 				t.push(`"${Spoken(eventSlave, `Thank you, ${Master}, you're the best,`)}"`);
diff --git a/src/events/nonRandom/daughters/pCollaborationChoice.js b/src/events/nonRandom/daughters/pCollaborationChoice.js
index f1c00824e57f74f6ff3c93774327b831f423f04c..fedfb05b7c31ea5494573f22d2593253b1235e6e 100644
--- a/src/events/nonRandom/daughters/pCollaborationChoice.js
+++ b/src/events/nonRandom/daughters/pCollaborationChoice.js
@@ -58,7 +58,7 @@ App.Events.PCoupCollaborationChoice = class PCoupCollaborationChoice extends App
 						Spoken(traitorActor, `"Don't let them get you ${Master}! Show them who's boss!"`)
 					);
 				} else {
-					r.push(`${He} hastily gestures that they are coming for you and that nothing you can do will deter them. ${He} barely signs off a plea for you to prepare your defenses before being dragged offsceen.`);
+					r.push(`${He} hastily gestures that they are coming for you and that nothing you can do will deter them. ${He} barely signs off a plea for you to prepare your defenses before being dragged offscreen.`);
 				}
 				traitor.type = "hostage";
 			} else if (traitorActor.intelligence + traitorActor.intelligenceImplant < -50) {
diff --git a/src/gui/Encyclopedia/encyclopediaGuide.js b/src/gui/Encyclopedia/encyclopediaGuide.js
index 0f270e6ef2c141589331bebd16e5c30a03a1a203..f0765e598282d3391bce5cdf7e9c7f905b7f8ca6 100644
--- a/src/gui/Encyclopedia/encyclopediaGuide.js
+++ b/src/gui/Encyclopedia/encyclopediaGuide.js
@@ -384,7 +384,7 @@ App.Encyclopedia.addArticle("Design Your Master", function() {
 		}
 		r.push("Your starting slaves will have free");
 		r.push(App.Encyclopedia.link("trust", "Trust", "trust careful"));
-		r.push("available. Strength requirements impart a hightened starting musculature. Starts having already mastered");
+		r.push("available. Strength requirements impart a heightened starting musculature. Starts having already mastered");
 		r.push(App.UI.DOM.combineNodes(App.Encyclopedia.link("Warfare", "PC Skills"), "."));
 		App.Events.addNode(ul, r, "li");
 
diff --git a/src/gui/options/options.js b/src/gui/options/options.js
index 6eea3c4ef27f93f0afea768fdcc89b61058efcff..dc90d275dd20d5ec44694fb067fd9ec4de2ef028 100644
--- a/src/gui/options/options.js
+++ b/src/gui/options/options.js
@@ -1,4 +1,4 @@
-// cSpell:ignore SSAA
+// cSpell:ignore SSAA, Oobabooga
 
 App.UI.optionsPassage = function() {
 	const el = new DocumentFragment();
@@ -773,7 +773,7 @@ App.UI.optionsPassage = function() {
 
 		options.addOption("Experimental AI chat tab in slave interact is ", "aiChat")
 			.addValue("Enabled", 1).on().addValue("Disabled", 0).off()
-			.addComment("This will enable a chat tab in slave interact. It uses an LLM OpenAPI endpoint of your choice. (DONT USE OPENAI, use Oobabooga, KoboldCPP, etc)");
+			.addComment("This will enable a chat tab in slave interact. It uses an LLM OpenAPI endpoint of your choice. (DON'T USE OPENAI, use Oobabooga, KoboldCPP, etc)");
 
 		if (V.aiChat === 1){
 			options.addOption("API URL", "aiChatUrl").showTextBox().addComment("The URL of the OpenAI-compatible, self-hosted endpoint.");
diff --git a/src/gui/options/stableDiffusionInstallationGuide.js b/src/gui/options/stableDiffusionInstallationGuide.js
index 2c255c3239a768425676f8ceedab89a4fd501f11..518dec695313ef03d5ca6baca5c268bb74c5088e 100644
--- a/src/gui/options/stableDiffusionInstallationGuide.js
+++ b/src/gui/options/stableDiffusionInstallationGuide.js
@@ -111,7 +111,7 @@ Restart ComfyUI
 
 <h3>Setup FC for ComfyUI integration</h3>
 <p>Switch AI User Interface from A1111 to ComfyUI.</p>
-<p>Select your checkpoint model, sampling mathod, and scheduling method.</p>
+<p>Select your checkpoint model, sampling method, and scheduling method.</p>
 
 <h3>Confirm successful generation</h3>
 <p>If the preview image is not being generated and the preview is:</p>
diff --git a/src/interaction/slChat.js b/src/interaction/slChat.js
index 8c4c50ce806f528d93153c1a606246be25fb621b..6d588e2f6c197df4a33d579cac079ff7eb229c59 100644
--- a/src/interaction/slChat.js
+++ b/src/interaction/slChat.js
@@ -1,175 +1,180 @@
+// cspell:ignore Ooobabooga, KBCPP
+
 /**
  * @param {FC.SlaveState} slave
  * @returns {HTMLParagraphElement}
  */
 App.UI.SlaveInteract.chat = function(slave) {
-    const p = document.createElement("p");
-    p.id = "chat-tab";
-
-    // Inject the chatbox inside this tab
-    const chatContainer = document.createElement("div");
-    chatContainer.id = "chat-container";
-    chatContainer.style.width = "50%";
-    chatContainer.style.height = "50%";
-    chatContainer.style.background = "rgba(0,0,0,0.8)";
-    chatContainer.style.color = "white";
-    chatContainer.style.border = "1px solid white";
-    chatContainer.style.padding = "10px";
-    chatContainer.style.overflow = "hidden";
-    chatContainer.style.display = "flex";
-    chatContainer.style.flexDirection = "column";
-    chatContainer.style.zIndex = "9999";
-
-    // Create the chat history (scrollable)
-    const chatHistory = document.createElement("div");
-    chatHistory.id = "chat-history";
-    chatHistory.style.flexGrow = "1";
-    chatHistory.style.overflowY = "auto";
-    chatHistory.style.height = "80%";
-    chatHistory.style.padding = "5px";
-    chatHistory.style.borderBottom = "1px solid white";
-
-    // Create the chat input field
-    const chatInput = document.createElement("input");
-    chatInput.id = "chat-input";
-    chatInput.type = "text";
-    chatInput.style.width = "100%";
-    chatInput.style.marginTop = "5px";
-    chatInput.style.background = "black";
-    chatInput.style.color = "white";
-    chatInput.style.border = "1px solid white";
-    chatInput.style.padding = "5px";
-
-    // Append chat elements inside the tab
-    chatContainer.append(chatHistory, chatInput);
-    p.append(chatContainer);
-
-    // Extract and Store Description (Directly in Chat Tab)
-    let extractedSlaveDescription = "";
-    let extractedPlayerDescription = "";
-    let extractedFamilyDescription = "";
-
-    function extractSlaveDescription() {
-        let slaveLongDescription = App.Desc.longSlave(slave, {noArt: true, links: true});
-        if (slaveLongDescription instanceof DocumentFragment) {
-            let textParts = [];
-            slaveLongDescription.childNodes.forEach(node => {
-                if (node.nodeType === Node.TEXT_NODE) {
-                    textParts.push(node.textContent.trim());
-                } else if (node.nodeType === Node.ELEMENT_NODE) {
-                    textParts.push(node.innerText || node.textContent.trim());
-                }
-            });
-            extractedSlaveDescription = textParts.filter(text => text).join("\n");
-        } else if (typeof slaveLongDescription === "string") {
-            extractedSlaveDescription = slaveLongDescription.trim();
-        }
-    }
-
-    function extractPlayerDescription() {
-        let playerLongDescription = App.Desc.Player.longDescription(V.PC);
-        if (playerLongDescription instanceof DocumentFragment) {
-            let textParts = [];
-            playerLongDescription.childNodes.forEach(node => {
-                if (node.nodeType === Node.TEXT_NODE) {
-                    textParts.push(node.textContent.trim());
-                } else if (node.nodeType === Node.ELEMENT_NODE) {
-                    textParts.push(node.innerText || node.textContent.trim());
-                }
-            });
-            extractedPlayerDescription = textParts.filter(text => text).join("\n");
-        } else if (typeof playerLongDescription === "string") {
-            extractedPlayerDescription = playerLongDescription.trim();
-        }
-    }
-
-    function extractFamilyDescription() {
-        let familyLongDescription = App.Desc.family(V.PC, true);
-        if (familyLongDescription instanceof DocumentFragment) {
-            let textParts = [];
-            familyLongDescription.childNodes.forEach(node => {
-                if (node.nodeType === Node.TEXT_NODE) {
-                    textParts.push(node.textContent.trim());
-                } else if (node.nodeType === Node.ELEMENT_NODE) {
-                    textParts.push(node.innerText || node.textContent.trim());
-                }
-            });
-            extractedFamilyDescription = textParts.filter(text => text).join("\n");
-        } else if (typeof familyLongDescription === "string") {
-            extractedFamilyDescription = familyLongDescription.trim();
-        }
-    }
-
-
-    // Call extraction function on tab load
-    extractSlaveDescription();
-    extractPlayerDescription();
-    extractFamilyDescription();
-
-    // Chat Function
-    async function sendMessageToAI(userMessage) {
-        try {
-            const systemMessage = "(role:You are a system that takes user input, game variables, and uses smart sense of the context to write relevant stories to flesh out in-game actions. Immersion is key, do not mention stats or game design elements, only passages that flesh out the users' decisions and the results of their stats/rolls) (Perspective:Always write to the user in first-person, since this is a game in their perspective) (Style:Write one or two paragraphs, regardless of previous replies or user input. Be consistent in length. Sensory details, physical events, and dialogue should be the primary focus of the passages written) [RULES:You will be given details, stat or point increases, and actions the user has made. Write speech ONLY for NPCs, not the user. The user will be roleplaying themselves, do not do it for them! ALWAYS WRITE IN SECOND PERSON PERSPECTIVE ('you do x', 'she does this to you', 'as you x' etc.)]";
-            const playerDescriptionContext = extractedPlayerDescription ? `\n\nPlayer Description:\n${extractedPlayerDescription}` : "";
-            const familyDescriptionContext = extractedFamilyDescription ? `\n\nFamily Description:\n${extractedFamilyDescription}` : "";
-            const slaveDescriptionContext = extractedSlaveDescription ? `\n\nSlave Description:\n${extractedSlaveDescription}` : "";
-            const playerTitleContext = `On formal occasions, you are announced as ${PCTitle()}. By slaves, however, you prefer to be called ${properMaster()}.`;
-
-
-            const response = await fetch(V.aiChatUrl, {
-                method: "POST",
-                headers: {
-                    "Content-Type": "application/json"
-                },
-                body: JSON.stringify({
-                    model: "mistral-7b",
-                    messages: [
-                        { role: "system", content: familyDescriptionContext + playerDescriptionContext + playerTitleContext +  slaveDescriptionContext + systemMessage}, // Include extracted description
-                        { role: "user", content: userMessage }
-                    ],
-                    max_tokens: 1024,
-                    temperature: V.aiChatTemp,
-                    min_p: V.aiChatMinP,
-                    repetition_penalty: 1.1
-                })
-            });
-
-            const data = await response.json();
-            console.log("AI Response:", data);
-
-            if (data && data.choices && data.choices.length > 0) {
-                return data.choices[0].message.content.trim();
-            } else {
-                return "⚠️ AI response invalid! Check your self-hosted LLM backend (Ooobabooga, KBCPP) as well as your IP addresses/permissions";
-            }
-        } catch (error) {
-            console.error("Error communicating with AI:", error);
-            return "⚠️ Error connecting to AI! ⚠️ Check your self-hosted LLM backend (Ooobabooga, KBCPP) as well as your IP addresses/permissions";
-        }
-    }
-
-    // Attach event listener inside siChat.js
-    chatInput.addEventListener("keypress", async function (event) {
-        if (event.key === "Enter") {
-            let userMessage = chatInput.value.trim();
-            if (userMessage) {
-                let userMessageDiv = document.createElement("div");
-                userMessageDiv.textContent = "Player: " + userMessage;
-                chatHistory.append(userMessageDiv);
-                chatInput.value = "";
-                chatHistory.scrollTop = chatHistory.scrollHeight; // Auto-scroll
-
-                // Send message to AI using local function
-                let aiResponse = await sendMessageToAI(userMessage);
-
-                let aiMessageDiv = document.createElement("div");
-                aiMessageDiv.textContent = slave.slaveName + " " + slave.slaveSurname + ":" + aiResponse;
-                aiMessageDiv.style.color = "lightblue";
-                chatHistory.append(aiMessageDiv);
-                chatHistory.scrollTop = chatHistory.scrollHeight; // Auto-scroll
-            }
-        }
-    });
-
-    return p;
+	const p = document.createElement("p");
+	p.id = "chat-tab";
+
+	// Inject the chatbox inside this tab
+	const chatContainer = document.createElement("div");
+	chatContainer.id = "chat-container";
+	chatContainer.style.width = "50%";
+	chatContainer.style.height = "50%";
+	chatContainer.style.background = "rgba(0,0,0,0.8)";
+	chatContainer.style.color = "white";
+	chatContainer.style.border = "1px solid white";
+	chatContainer.style.padding = "10px";
+	chatContainer.style.overflow = "hidden";
+	chatContainer.style.display = "flex";
+	chatContainer.style.flexDirection = "column";
+	chatContainer.style.zIndex = "9999";
+
+	// Create the chat history (scrollable)
+	const chatHistory = document.createElement("div");
+	chatHistory.id = "chat-history";
+	chatHistory.style.flexGrow = "1";
+	chatHistory.style.overflowY = "auto";
+	chatHistory.style.height = "80%";
+	chatHistory.style.padding = "5px";
+	chatHistory.style.borderBottom = "1px solid white";
+
+	// Create the chat input field
+	const chatInput = document.createElement("input");
+	chatInput.id = "chat-input";
+	chatInput.type = "text";
+	chatInput.style.width = "100%";
+	chatInput.style.marginTop = "5px";
+	chatInput.style.background = "black";
+	chatInput.style.color = "white";
+	chatInput.style.border = "1px solid white";
+	chatInput.style.padding = "5px";
+
+	// Append chat elements inside the tab
+	chatContainer.append(chatHistory, chatInput);
+	p.append(chatContainer);
+
+	// Extract and Store Description (Directly in Chat Tab)
+	let extractedSlaveDescription = "";
+	let extractedPlayerDescription = "";
+	let extractedFamilyDescription = "";
+
+	function extractSlaveDescription() {
+		let slaveLongDescription = App.Desc.longSlave(slave, {noArt: true, links: true});
+		if (slaveLongDescription instanceof DocumentFragment) {
+			let textParts = [];
+			slaveLongDescription.childNodes.forEach(node => {
+				if (node.nodeType === Node.TEXT_NODE) {
+					textParts.push(node.textContent.trim());
+				} else if (node.nodeType === Node.ELEMENT_NODE) {
+					textParts.push(node.innerText || node.textContent.trim());
+				}
+			});
+			extractedSlaveDescription = textParts.filter(text => text).join("\n");
+		} else if (typeof slaveLongDescription === "string") {
+			extractedSlaveDescription = slaveLongDescription.trim();
+		}
+	}
+
+	function extractPlayerDescription() {
+		let playerLongDescription = App.Desc.Player.longDescription(V.PC);
+		if (playerLongDescription instanceof DocumentFragment) {
+			let textParts = [];
+			playerLongDescription.childNodes.forEach(node => {
+				if (node.nodeType === Node.TEXT_NODE) {
+					textParts.push(node.textContent.trim());
+				} else if (node.nodeType === Node.ELEMENT_NODE) {
+					textParts.push(node.innerText || node.textContent.trim());
+				}
+			});
+			extractedPlayerDescription = textParts.filter(text => text).join("\n");
+		} else if (typeof playerLongDescription === "string") {
+			extractedPlayerDescription = playerLongDescription.trim();
+		}
+	}
+
+	function extractFamilyDescription() {
+		let familyLongDescription = App.Desc.family(V.PC, true);
+		if (familyLongDescription instanceof DocumentFragment) {
+			let textParts = [];
+			familyLongDescription.childNodes.forEach(node => {
+				if (node.nodeType === Node.TEXT_NODE) {
+					textParts.push(node.textContent.trim());
+				} else if (node.nodeType === Node.ELEMENT_NODE) {
+					textParts.push(node.innerText || node.textContent.trim());
+				}
+			});
+			extractedFamilyDescription = textParts.filter(text => text).join("\n");
+		} else if (typeof familyLongDescription === "string") {
+			extractedFamilyDescription = familyLongDescription.trim();
+		}
+	}
+
+
+	// Call extraction function on tab load
+	extractSlaveDescription();
+	extractPlayerDescription();
+	extractFamilyDescription();
+
+	// Chat Function
+	async function sendMessageToAI(userMessage) {
+		try {
+			const systemMessage = "(role:You are a system that takes user input, game variables, and uses smart sense of the context to write relevant stories to flesh out in-game actions. Immersion is key, do not mention stats or game design elements, only passages that flesh out the users' decisions and the results of their stats/rolls) (Perspective:Always write to the user in first-person, since this is a game in their perspective) (Style:Write one or two paragraphs, regardless of previous replies or user input. Be consistent in length. Sensory details, physical events, and dialogue should be the primary focus of the passages written) [RULES:You will be given details, stat or point increases, and actions the user has made. Write speech ONLY for NPCs, not the user. The user will be roleplaying themselves, do not do it for them! ALWAYS WRITE IN SECOND PERSON PERSPECTIVE ('you do x', 'she does this to you', 'as you x' etc.)]";
+			const playerDescriptionContext = extractedPlayerDescription ? `\n\nPlayer Description:\n${extractedPlayerDescription}` : "";
+			const familyDescriptionContext = extractedFamilyDescription ? `\n\nFamily Description:\n${extractedFamilyDescription}` : "";
+			const slaveDescriptionContext = extractedSlaveDescription ? `\n\nSlave Description:\n${extractedSlaveDescription}` : "";
+			const playerTitleContext = `On formal occasions, you are announced as ${PCTitle()}. By slaves, however, you prefer to be called ${properMaster()}.`;
+
+
+			const response = await fetch(V.aiChatUrl, {
+				method: "POST",
+				headers: {
+					"Content-Type": "application/json"
+				},
+				body: JSON.stringify({
+					model: "mistral-7b",
+					messages: [
+						{
+							role: "system",
+							content: familyDescriptionContext + playerDescriptionContext + playerTitleContext + slaveDescriptionContext + systemMessage
+						}, // Include extracted description
+						{role: "user", content: userMessage}
+					],
+					max_tokens: 1024,
+					temperature: V.aiChatTemp,
+					min_p: V.aiChatMinP,
+					repetition_penalty: 1.1
+				})
+			});
+
+			const data = await response.json();
+			console.log("AI Response:", data);
+
+			if (data && data.choices && data.choices.length > 0) {
+				return data.choices[0].message.content.trim();
+			} else {
+				return "⚠️ AI response invalid! Check your self-hosted LLM backend (Ooobabooga, KBCPP) as well as your IP addresses/permissions";
+			}
+		} catch (error) {
+			console.error("Error communicating with AI:", error);
+			return "⚠️ Error connecting to AI! ⚠️ Check your self-hosted LLM backend (Ooobabooga, KBCPP) as well as your IP addresses/permissions";
+		}
+	}
+
+	// Attach event listener inside siChat.js
+	chatInput.addEventListener("keypress", async function(event) {
+		if (event.key === "Enter") {
+			let userMessage = chatInput.value.trim();
+			if (userMessage) {
+				let userMessageDiv = document.createElement("div");
+				userMessageDiv.textContent = "Player: " + userMessage;
+				chatHistory.append(userMessageDiv);
+				chatInput.value = "";
+				chatHistory.scrollTop = chatHistory.scrollHeight; // Auto-scroll
+
+				// Send message to AI using local function
+				let aiResponse = await sendMessageToAI(userMessage);
+
+				let aiMessageDiv = document.createElement("div");
+				aiMessageDiv.textContent = slave.slaveName + " " + slave.slaveSurname + ":" + aiResponse;
+				aiMessageDiv.style.color = "lightblue";
+				chatHistory.append(aiMessageDiv);
+				chatHistory.scrollTop = chatHistory.scrollHeight; // Auto-scroll
+			}
+		}
+	});
+
+	return p;
 };
diff --git a/src/js/utilsSlave.js b/src/js/utilsSlave.js
index e66ba8a8460c69ad3e6e61cf0141a9b7406dd48e..9b87863801160f91f33c6582c1e81f9610927f79 100644
--- a/src/js/utilsSlave.js
+++ b/src/js/utilsSlave.js
@@ -1,4 +1,4 @@
-// cSpell:ignore rapee, arousingly, Boobie, Fuckee, Unhearing, assed, GMILF, ress, Basotho, SHOX, tgirl
+// cSpell:ignore rapee, arousingly, Boobie, Fuckee, Unhearing, assed, GMILF, ress, Basotho, SHOX, tgirl, Koreas, istan, cabo, Eswatini, Leste, Côte d'Ivoire, Türkiye
 
 /**
  * Height.mean(nationality, race, genes, age) - returns the mean height for the given combination and age in years (>=2)
diff --git a/src/npc/slaveBot/generateSlaveBot.js b/src/npc/slaveBot/generateSlaveBot.js
index 8b0c60444c12fcb3dcfd383892aa80be481b181c..a8d83a639dda6642238cd0c79bb273df064b7216 100644
--- a/src/npc/slaveBot/generateSlaveBot.js
+++ b/src/npc/slaveBot/generateSlaveBot.js
@@ -1,5 +1,5 @@
 /* eslint-disable camelcase */
-// cSpell:ignore abilParts, chasParts
+// cSpell:ignore abilParts, chasParts, IHDR, IEND, IDAT
 
 /** @param {FC.SlaveState} slave */
 App.UI.SlaveInteract.SlaveBot.createSlaveBot = (slave) => {
@@ -1283,7 +1283,7 @@ App.UI.SlaveInteract.SlaveBot.Generate.lorebookFSContent = (fsType) => {
 		case "FSAztecRevivalist":
 			return (`${V.arcologies[0].name} is building itself into a new Aztec Empire, embracing its architectural and societal ideals, including human sacrifice.`);
 		case "FSEgyptianRevivalist":
-			return (`${V.arcologies[0].name} is building itself into Pharoah's Egypt, embracing its architectural and societal ideals.`);
+			return (`${V.arcologies[0].name} is building itself into Pharaoh's Egypt, embracing its architectural and societal ideals.`);
 		case "FSEdoRevivalist":
 			return (`${V.arcologies[0].name} is building itself into Edo Japan, embracing its architectural and societal ideals.`);
 		case "FSArabianRevivalist":
diff --git a/src/npc/slaveBot/slaveBotGreetings.js b/src/npc/slaveBot/slaveBotGreetings.js
index 8e728277fe57ccfa2b2b1ef746a64e2b269dbf59..87d500a768468c831d38250ae7e4ed8787a8d595 100644
--- a/src/npc/slaveBot/slaveBotGreetings.js
+++ b/src/npc/slaveBot/slaveBotGreetings.js
@@ -1,4 +1,5 @@
 /* eslint-disable no-unused-vars */
+// cspell:ignore anyth
 
 /**
  * @type {Array<{ prereqs: Array<actorPredicate>, getGreeting: (s: FC.SlaveState) => string }>}
@@ -346,7 +347,7 @@ App.UI.SlaveInteract.SlaveBotGreetings = [
 			return r.join(" ");
 		},
 		prereqs: [
-			// TESTING 
+			// TESTING
 			s => s.fetish !== Fetish.MINDBROKEN,
 			hasAnyArms,
 			hasAnyLegs,
@@ -2421,7 +2422,7 @@ App.UI.SlaveInteract.SlaveBotGreetings = [
 				He2,
 				he2, his2, him2, himself2
 			} = getPronouns(s).appendSuffix("2");
-			// SRC petsStewardessBeating 
+			// SRC petsStewardessBeating
 			let r = [];
 			r.push(`Poor ${s.slaveName} clearly isn't working as hard as ${he2} should. ${S.Stewardess.slaveName} has ${him2} bent over with ${his2} buttocks bare, and is administering a punishing spanking. ${s.slaveName}'s ${s.skin} skin is starting to show the force of the beating, and ${he2}'s begging desperately for mercy.`
 			);