diff --git a/viz/index.html b/viz/index.html
index 04d22b0..81bb940 100644
--- a/viz/index.html
+++ b/viz/index.html
@@ -3153,8 +3153,11 @@
const vibeKnownDest = (k) => dests.has(k);
function sanitizeVibe(raw) { // trust boundary: user-pasted / URL data
if (!raw || typeof raw !== "object") return null;
- const name = (typeof raw.name === "string" && raw.name.trim()) ? raw.name.trim().slice(0, 48) : "shared vibe";
- const emoji = (typeof raw.emoji === "string" && raw.emoji) ? [...raw.emoji].slice(0, 2).join("") : "🎁";
+ const noMarkup = (s) => String(s).replace(/[<>&"'`]/g, ""); // strip markup chars — these strings hit innerHTML
+ const nm = (typeof raw.name === "string") ? noMarkup(raw.name).trim() : "";
+ const name = nm ? nm.slice(0, 48) : "shared vibe";
+ const em = (typeof raw.emoji === "string") ? noMarkup(raw.emoji) : "";
+ const emoji = em ? [...em].slice(0, 2).join("") : "🎁";
if (!Array.isArray(raw.routes)) return null;
const routes = [];
for (const r of raw.routes.slice(0, 32)) { // hard cap