Football Empire — Build Your Dynasty
by LunarGalaxy87625 lines23.1 KB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Football Empire — Build Your Dynasty</title>
<style>
:root{
--pitch-dark: #0b2818;
--pitch: #123a22;
--pitch-light: #1c5230;
--line: #ffffff;
--gold: #d4af37;
--gold-bright: #f4d968;
--ink: #eef7ee;
--ink-dim: #9db8a3;
--danger: #c0453a;
}
*{box-sizing:border-box; -webkit-tap-highlight-color:transparent;}
html,body{margin:0;padding:0;height:100%;overflow:hidden;background:var(--pitch-dark);}
body{
font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
color:var(--ink);
background:
repeating-linear-gradient(90deg, rgba(255,255,255,0.02) 0 2px, transparent 2px 40px),
linear-gradient(180deg, var(--pitch) 0%, var(--pitch-dark) 100%);
display:flex; flex-direction:column; height:100vh; height:100dvh;
user-select:none;
}
header{
padding:14px 16px 10px;
display:flex; flex-direction:column; gap:8px;
border-bottom:2px solid rgba(255,255,255,0.08);
background:rgba(0,0,0,0.15);
}
.titlebar{display:flex; justify-content:space-between; align-items:baseline;}
.club-name{
font-family: Georgia, 'Times New Roman', serif;
font-weight:700; font-size:20px; letter-spacing:0.5px;
color:var(--gold-bright);
}
.league{ font-size:11px; color:var(--ink-dim); text-transform:uppercase; letter-spacing:1.5px;}
.stats-row{ display:flex; gap:10px; }
.stat{
flex:1; background:rgba(255,255,255,0.05); border:1px solid rgba(255,255,255,0.08);
border-radius:10px; padding:8px 10px;
}
.stat-label{ font-size:10px; color:var(--ink-dim); text-transform:uppercase; letter-spacing:1px;}
.stat-value{ font-size:17px; font-weight:700; color:var(--ink); font-variant-numeric: tabular-nums;}
.stat-value.gold{ color:var(--gold-bright); }
.prestige-bar-wrap{ margin-top:2px;}
.prestige-bar-track{
height:6px; border-radius:4px; background:rgba(255,255,255,0.08); overflow:hidden;
}
.prestige-bar-fill{
height:100%; background:linear-gradient(90deg, var(--gold), var(--gold-bright));
transition:width 0.3s ease; border-radius:4px;
}
.prestige-label{ font-size:10px; color:var(--ink-dim); margin-top:4px; display:flex; justify-content:space-between;}
main{
flex:1; overflow-y:auto; -webkit-overflow-scrolling:touch;
padding:14px 16px 100px;
display:flex; flex-direction:column; gap:14px;
}
.pitch-zone{
position:relative;
height:150px;
border-radius:14px;
background:
repeating-linear-gradient(90deg, var(--pitch-light) 0 34px, var(--pitch) 34px 68px);
border:3px solid rgba(255,255,255,0.25);
overflow:hidden;
display:flex; align-items:center; justify-content:center;
flex-shrink:0;
}
.pitch-zone::before{
content:''; position:absolute; inset:8px; border:2px solid rgba(255,255,255,0.3); border-radius:8px;
}
.pitch-zone::after{
content:''; position:absolute; top:50%; left:50%; width:44px; height:44px;
border:2px solid rgba(255,255,255,0.3); border-radius:50%; transform:translate(-50%,-50%);
}
#ball{
width:56px; height:56px; border-radius:50%; cursor:pointer;
background: radial-gradient(circle at 32% 32%, #fff, #e8e8e8 45%, #ccc 100%);
box-shadow:0 6px 14px rgba(0,0,0,0.45), inset 0 -6px 10px rgba(0,0,0,0.15);
display:flex; align-items:center; justify-content:center;
font-size:24px;
transition:transform 0.08s ease;
position:relative; z-index:2;
touch-action: manipulation;
}
#ball:active{ transform:scale(0.88) rotate(20deg); }
#ball.kicked{ animation:kick 0.35s ease; }
@keyframes kick{
0%{ transform:scale(1); }
30%{ transform:scale(0.8) rotate(-15deg); }
100%{ transform:scale(1) rotate(0); }
}
.float-coin{
position:absolute; font-weight:700; font-size:14px; color:var(--gold-bright);
pointer-events:none; z-index:3;
animation: floatUp 0.9s ease-out forwards;
text-shadow:0 1px 3px rgba(0,0,0,0.6);
}
@keyframes floatUp{
0%{ opacity:1; transform:translateY(0) scale(1); }
100%{ opacity:0; transform:translateY(-60px) scale(1.2); }
}
.tap-hint{
position:absolute; bottom:8px; left:50%; transform:translateX(-50%);
font-size:10px; color:rgba(255,255,255,0.55); letter-spacing:0.5px; text-transform:uppercase;
}
.section-title{
font-size:13px; font-weight:700; color:var(--ink-dim); text-transform:uppercase; letter-spacing:1.5px;
margin:2px 0 -4px 2px; display:flex; align-items:center; gap:6px;
}
.card{
background:linear-gradient(160deg, rgba(255,255,255,0.06), rgba(255,255,255,0.02));
border:1px solid rgba(255,255,255,0.1);
border-radius:14px;
padding:12px 14px;
display:flex; align-items:center; gap:12px;
transition:transform 0.12s ease, border-color 0.12s ease;
}
.card:active{ transform:scale(0.98); }
.card.affordable{ border-color:rgba(212,175,55,0.5); }
.card.locked{ opacity:0.45; }
.card-icon{
width:42px; height:42px; border-radius:10px; flex-shrink:0;
display:flex; align-items:center; justify-content:center; font-size:22px;
background:rgba(0,0,0,0.25);
}
.card-body{ flex:1; min-width:0; }
.card-name{ font-weight:700; font-size:14px; }
.card-desc{ font-size:11px; color:var(--ink-dim); margin-top:1px; }
.card-owned{
font-size:10px; color:var(--gold-bright); margin-top:2px; font-weight:700;
letter-spacing:0.5px;
}
.buy-btn{
flex-shrink:0; border:none; border-radius:10px; padding:9px 12px;
background:linear-gradient(160deg, var(--gold-bright), var(--gold));
color:#1a1300; font-weight:800; font-size:12px; cursor:pointer;
display:flex; flex-direction:column; align-items:center; min-width:76px;
box-shadow:0 3px 0 #8a6d1f;
}
.buy-btn:active{ transform:translateY(2px); box-shadow:0 1px 0 #8a6d1f; }
.buy-btn:disabled{
background:rgba(255,255,255,0.08); color:var(--ink-dim); box-shadow:none; cursor:default;
}
.buy-btn .cost{ font-size:12px; }
.buy-btn .sub{ font-size:8px; opacity:0.75; text-transform:uppercase; }
.prestige-card{
background:linear-gradient(160deg, rgba(212,175,55,0.18), rgba(212,175,55,0.04));
border:1px solid rgba(212,175,55,0.35);
border-radius:14px; padding:14px; margin-top:4px;
}
.prestige-card h3{ margin:0 0 4px; font-size:15px; color:var(--gold-bright); font-family:Georgia, serif;}
.prestige-card p{ margin:0 0 10px; font-size:12px; color:var(--ink-dim); line-height:1.5;}
.prestige-btn{
width:100%; padding:12px; border:none; border-radius:10px;
background:linear-gradient(160deg, var(--gold-bright), var(--gold));
color:#1a1300; font-weight:800; font-size:13px; letter-spacing:0.5px; cursor:pointer;
}
.prestige-btn:disabled{ background:rgba(255,255,255,0.08); color:var(--ink-dim); }
footer{
position:fixed; bottom:0; left:0; right:0;
display:flex; background:rgba(6,20,12,0.92); backdrop-filter:blur(8px);
border-top:2px solid rgba(255,255,255,0.08);
padding:6px 6px calc(6px + env(safe-area-inset-bottom));
gap:4px; z-index:10;
}
.tab{
flex:1; background:none; border:none; color:var(--ink-dim); padding:8px 4px;
display:flex; flex-direction:column; align-items:center; gap:2px; font-size:10px;
border-radius:10px; cursor:pointer; font-weight:600; letter-spacing:0.3px;
}
.tab .ic{ font-size:19px; }
.tab.active{ color:var(--gold-bright); background:rgba(212,175,55,0.1); }
.toast{
position:fixed; top:14px; left:50%; transform:translateX(-50%);
background:rgba(0,0,0,0.85); border:1px solid var(--gold); color:var(--gold-bright);
padding:10px 18px; border-radius:10px; font-size:13px; font-weight:700;
z-index:100; opacity:0; pointer-events:none; transition:opacity 0.3s, top 0.3s;
text-align:center; max-width:80%;
}
.toast.show{ opacity:1; top:20px; }
.hidden{ display:none !important; }
::-webkit-scrollbar{ width:0; }
</style>
</head>
<body>
<header>
<div class="titlebar">
<div class="club-name" id="clubName">FC Origin</div>
<div class="league" id="leagueName">Sunday League</div>
</div>
<div class="stats-row">
<div class="stat">
<div class="stat-label">Club Funds</div>
<div class="stat-value gold" id="moneyDisplay">£0</div>
</div>
<div class="stat">
<div class="stat-label">Per Second</div>
<div class="stat-value" id="ppsDisplay">£0/s</div>
</div>
<div class="stat">
<div class="stat-label">Trophies</div>
<div class="stat-value" id="trophyDisplay">0</div>
</div>
</div>
<div class="prestige-bar-wrap">
<div class="prestige-bar-track"><div class="prestige-bar-fill" id="prestigeBar" style="width:0%"></div></div>
<div class="prestige-label"><span id="prestigeProgressLabel">Progress to promotion</span><span id="prestigePct">0%</span></div>
</div>
</header>
<main id="mainScroll">
<div id="tab-club" class="tab-content">
<div class="pitch-zone">
<div id="ball">⚽</div>
<div class="tap-hint">Tap the ball to train</div>
</div>
<div class="section-title">🏟️ Youth & Staff</div>
<div id="generatorList" style="display:flex; flex-direction:column; gap:8px;"></div>
</div>
<div id="tab-upgrades" class="tab-content hidden">
<div class="section-title">⭐ Upgrades</div>
<div id="upgradeList" style="display:flex; flex-direction:column; gap:8px;"></div>
</div>
<div id="tab-prestige" class="tab-content hidden">
<div class="prestige-card">
<h3 id="prestigeTitle">Seek Promotion</h3>
<p id="prestigeDesc">Reach £10,000 in club funds to earn promotion. Promoting resets your funds and staff, but grants permanent Trophies — each Trophy boosts all income forever.</p>
<button class="prestige-btn" id="prestigeBtn">Not enough funds yet</button>
</div>
<div class="section-title" style="margin-top:16px;">🏆 Trophy Bonuses</div>
<div class="card">
<div class="card-icon">📈</div>
<div class="card-body">
<div class="card-name">Legacy Income</div>
<div class="card-desc" id="trophyBonusDesc">Each trophy: +10% income, permanently.</div>
</div>
</div>
</div>
</main>
<footer>
<button class="tab active" data-tab="club"><span class="ic">⚽</span>Club</button>
<button class="tab" data-tab="upgrades"><span class="ic">⭐</span>Upgrades</button>
<button class="tab" data-tab="prestige"><span class="ic">🏆</span>Promotion</button>
</footer>
<div class="toast" id="toast"></div>
<script>
(function(){
"use strict";
// ---------- Config ----------
const SAVE_KEY = "footballEmpireSave_v1";
const LEAGUE_NAMES = [
"Sunday League", "County League", "Regional Division", "National League",
"Championship", "Premier League", "Champions League", "World Elite"
];
const GENERATORS = [
{ id:"scout", name:"Youth Scout", icon:"🔍", baseCost:15, baseRate:0.1, desc:"Finds raw local talent" },
{ id:"coach", name:"Academy Coach", icon:"🎽", baseCost:100, baseRate:1, desc:"Trains youth prospects" },
{ id:"striker", name:"Star Striker", icon:"🥅", baseCost:1100, baseRate:8, desc:"Scores, sells shirts" },
{ id:"stadium", name:"Stadium Upgrade",icon:"🏟️", baseCost:12000, baseRate:47, desc:"More seats, more gate revenue" },
{ id:"sponsor", name:"Kit Sponsor", icon:"💼", baseCost:130000, baseRate:260, desc:"Global sponsorship deal" },
{ id:"academy", name:"Global Academy", icon:"🌍", baseCost:1400000, baseRate:1400, desc:"Worldwide scouting network" },
];
const UPGRADES = [
{ id:"boots1", name:"Better Boots", icon:"👟", cost:500, desc:"Scouts +100% effective", target:"scout", mult:2 },
{ id:"tactics1",name:"Tactics Board", icon:"📋", cost:5000, desc:"Coaches +100% effective", target:"coach", mult:2 },
{ id:"boots2", name:"Pro Boots", icon:"👟", cost:20000, desc:"Scouts +200% effective (again)", target:"scout", mult:3 },
{ id:"jersey1", name:"Away Kit Launch", icon:"👕", cost:60000, desc:"Strikers +100% effective", target:"striker", mult:2 },
{ id:"lights1", name:"Floodlights", icon:"💡", cost:250000, desc:"Stadium +100% effective", target:"stadium", mult:2 },
{ id:"global1", name:"Global Deal", icon:"🌐", cost:900000, desc:"Sponsors +150% effective", target:"sponsor", mult:2.5 },
{ id:"clickup1",name:"Captain's Armband",icon:"🎖️", cost:2000, desc:"Ball tap earns 3x more", target:"click", mult:3 },
{ id:"clickup2",name:"Free Kick Master", icon:"🎯", cost:45000, desc:"Ball tap earns 5x more (again)", target:"click", mult:5 },
{ id:"allboost",name:"Champions Mentality",icon:"🔥",cost:750000,desc:"ALL income +50%", target:"all", mult:1.5 },
];
// ---------- State ----------
let state = {
money: 0,
trophies: 0,
clickValue: 1,
owned: {}, // generator id -> count
upgrades: {}, // upgrade id -> bool bought
lifetimeEarned: 0,
league: 0,
};
GENERATORS.forEach(g => state.owned[g.id] = 0);
// ---------- Save / Load ----------
function save(){
try{ localStorage.setItem(SAVE_KEY, JSON.stringify(state)); }catch(e){}
}
function load(){
try{
const raw = localStorage.getItem(SAVE_KEY);
if(raw){
const parsed = JSON.parse(raw);
state = Object.assign(state, parsed);
}
}catch(e){}
}
// ---------- Helpers ----------
function fmt(n){
if(n < 1000) return "£" + Math.floor(n).toLocaleString();
const units = ["", "K", "M", "B", "T", "Qa", "Qi"];
let u = 0;
while(n >= 1000 && u < units.length-1){ n /= 1000; u++; }
return "£" + n.toFixed(n < 10 ? 2 : 1) + units[u];
}
function trophyMultiplier(){
return 1 + state.trophies * 0.1;
}
function upgradeMultFor(target){
let mult = 1;
UPGRADES.forEach(u => {
if(state.upgrades[u.id] && u.target === target) mult *= u.mult;
});
// "all" upgrades apply to everything including click
UPGRADES.forEach(u => {
if(state.upgrades[u.id] && u.target === "all") mult *= u.mult;
});
return mult;
}
function generatorCost(g){
const n = state.owned[g.id];
return Math.ceil(g.baseCost * Math.pow(1.15, n));
}
function generatorRate(g){
return g.baseRate * state.owned[g.id] * upgradeMultFor(g.id);
}
function totalPerSecond(){
let total = 0;
GENERATORS.forEach(g => total += generatorRate(g));
return total * trophyMultiplier();
}
function clickPower(){
return state.clickValue * upgradeMultFor("click") * trophyMultiplier();
}
function promotionThreshold(){
return 10000 * Math.pow(6, state.league);
}
// ---------- Rendering ----------
const moneyDisplay = document.getElementById("moneyDisplay");
const ppsDisplay = document.getElementById("ppsDisplay");
const trophyDisplay = document.getElementById("trophyDisplay");
const clubName = document.getElementById("clubName");
const leagueName = document.getElementById("leagueName");
const prestigeBar = document.getElementById("prestigeBar");
const prestigePct = document.getElementById("prestigePct");
const generatorList = document.getElementById("generatorList");
const upgradeList = document.getElementById("upgradeList");
const prestigeBtn = document.getElementById("prestigeBtn");
const prestigeDesc = document.getElementById("prestigeDesc");
const trophyBonusDesc = document.getElementById("trophyBonusDesc");
function renderTopBar(){
moneyDisplay.textContent = fmt(state.money);
ppsDisplay.textContent = fmt(totalPerSecond()) + "/s";
trophyDisplay.textContent = state.trophies + " 🏆";
leagueName.textContent = LEAGUE_NAMES[Math.min(state.league, LEAGUE_NAMES.length-1)];
const threshold = promotionThreshold();
const pct = Math.min(100, (state.money / threshold) * 100);
prestigeBar.style.width = pct + "%";
prestigePct.textContent = Math.floor(pct) + "%";
}
function renderGenerators(){
generatorList.innerHTML = "";
GENERATORS.forEach(g => {
const cost = generatorCost(g);
const affordable = state.money >= cost;
const owned = state.owned[g.id];
const rate = generatorRate(g);
const card = document.createElement("div");
card.className = "card" + (affordable ? " affordable" : "");
card.innerHTML = `
<div class="card-icon">${g.icon}</div>
<div class="card-body">
<div class="card-name">${g.name}</div>
<div class="card-desc">${g.desc} · ${fmt(rate)}/s total</div>
${owned > 0 ? `<div class="card-owned">OWNED: ${owned}</div>` : ""}
</div>
<button class="buy-btn" ${affordable ? "" : "disabled"} data-buy="${g.id}">
<span class="cost">${fmt(cost)}</span>
<span class="sub">Buy</span>
</button>
`;
generatorList.appendChild(card);
});
}
function renderUpgrades(){
upgradeList.innerHTML = "";
UPGRADES.forEach(u => {
const bought = !!state.upgrades[u.id];
if(bought) return; // hide once bought to reduce clutter
const affordable = state.money >= u.cost;
const card = document.createElement("div");
card.className = "card" + (affordable ? " affordable" : "");
card.innerHTML = `
<div class="card-icon">${u.icon}</div>
<div class="card-body">
<div class="card-name">${u.name}</div>
<div class="card-desc">${u.desc}</div>
</div>
<button class="buy-btn" ${affordable ? "" : "disabled"} data-upgrade="${u.id}">
<span class="cost">${fmt(u.cost)}</span>
<span class="sub">Buy</span>
</button>
`;
upgradeList.appendChild(card);
});
if(upgradeList.children.length === 0){
upgradeList.innerHTML = `<div class="card"><div class="card-body"><div class="card-name">All upgrades purchased!</div><div class="card-desc">Check back after promoting — new tiers unlock as you grow.</div></div></div>`;
}
}
function renderPrestige(){
const threshold = promotionThreshold();
const ready = state.money >= threshold;
prestigeDesc.textContent = `Reach ${fmt(threshold)} in club funds to earn promotion to the next league. Promoting resets your funds, staff and upgrades — but grants a permanent Trophy that boosts ALL income forever.`;
prestigeBtn.disabled = !ready;
prestigeBtn.textContent = ready ? `Promote to ${LEAGUE_NAMES[Math.min(state.league+1, LEAGUE_NAMES.length-1)]} →` : `Need ${fmt(threshold)} (have ${fmt(state.money)})`;
trophyBonusDesc.textContent = `Each trophy: +10% income, permanently. Current bonus: +${Math.round((trophyMultiplier()-1)*100)}%`;
}
function renderAll(){
renderTopBar();
renderGenerators();
renderUpgrades();
renderPrestige();
}
// ---------- Toast ----------
let toastTimer = null;
function showToast(msg){
const t = document.getElementById("toast");
t.textContent = msg;
t.classList.add("show");
clearTimeout(toastTimer);
toastTimer = setTimeout(() => t.classList.remove("show"), 1800);
}
// ---------- Actions ----------
function buyGenerator(id){
const g = GENERATORS.find(x => x.id === id);
if(!g) return;
const cost = generatorCost(g);
if(state.money < cost) return;
state.money -= cost;
state.owned[id] += 1;
save();
renderTopBar(); renderGenerators(); renderPrestige();
}
function buyUpgrade(id){
const u = UPGRADES.find(x => x.id === id);
if(!u) return;
if(state.upgrades[id]) return;
if(state.money < u.cost) return;
state.money -= u.cost;
state.upgrades[id] = true;
save();
showToast(u.name + " purchased!");
renderTopBar(); renderGenerators(); renderUpgrades(); renderPrestige();
}
function doPrestige(){
const threshold = promotionThreshold();
if(state.money < threshold) return;
state.trophies += 1;
state.league += 1;
state.money = 0;
GENERATORS.forEach(g => state.owned[g.id] = 0);
state.upgrades = {};
state.clickValue = 1;
save();
showToast("Promoted! +1 Trophy 🏆");
renderAll();
switchTab("club");
}
const ball = document.getElementById("ball");
ball.addEventListener("click", (e) => {
const gain = clickPower();
state.money += gain;
state.lifetimeEarned += gain;
ball.classList.remove("kicked");
void ball.offsetWidth;
ball.classList.add("kicked");
const coin = document.createElement("div");
coin.className = "float-coin";
coin.textContent = "+" + fmt(gain);
const rect = ball.getBoundingClientRect();
const zoneRect = ball.parentElement.getBoundingClientRect();
coin.style.left = (rect.left - zoneRect.left + rect.width/2 + (Math.random()*30-15)) + "px";
coin.style.top = (rect.top - zoneRect.top) + "px";
ball.parentElement.appendChild(coin);
setTimeout(() => coin.remove(), 900);
renderTopBar(); renderGenerators(); renderPrestige();
});
generatorList.addEventListener("click", (e) => {
const btn = e.target.closest("[data-buy]");
if(btn) buyGenerator(btn.dataset.buy);
});
upgradeList.addEventListener("click", (e) => {
const btn = e.target.closest("[data-upgrade]");
if(btn) buyUpgrade(btn.dataset.upgrade);
});
prestigeBtn.addEventListener("click", doPrestige);
// ---------- Tabs ----------
function switchTab(name){
document.querySelectorAll(".tab").forEach(t => t.classList.toggle("active", t.dataset.tab === name));
document.getElementById("tab-club").classList.toggle("hidden", name !== "club");
document.getElementById("tab-upgrades").classList.toggle("hidden", name !== "upgrades");
document.getElementById("tab-prestige").classList.toggle("hidden", name !== "prestige");
document.getElementById("mainScroll").scrollTop = 0;
}
document.querySelectorAll(".tab").forEach(t => {
t.addEventListener("click", () => switchTab(t.dataset.tab));
});
// ---------- Game Loop ----------
let lastTick = Date.now();
function tick(){
const now = Date.now();
const dt = (now - lastTick) / 1000;
lastTick = now;
const gain = totalPerSecond() * dt;
if(gain > 0){
state.money += gain;
state.lifetimeEarned += gain;
}
renderTopBar();
}
setInterval(tick, 200);
// Slower full re-render for buy affordability states
setInterval(() => { renderGenerators(); renderUpgrades(); renderPrestige(); }, 1000);
// Offline progress
function applyOfflineProgress(){
try{
const lastSeen = localStorage.getItem(SAVE_KEY + "_lastSeen");
if(lastSeen){
const elapsed = Math.min((Date.now() - parseInt(lastSeen,10)) / 1000, 3600 * 8); // cap 8h
if(elapsed > 5){
const gain = totalPerSecond() * elapsed;
if(gain > 0){
state.money += gain;
showToast(`Welcome back! Earned ${fmt(gain)} while away.`);
}
}
}
}catch(e){}
}
window.addEventListener("beforeunload", () => {
try{ localStorage.setItem(SAVE_KEY + "_lastSeen", Date.now().toString()); }catch(e){}
save();
});
document.addEventListener("visibilitychange", () => {
if(document.visibilityState === "hidden"){ save(); try{ localStorage.setItem(SAVE_KEY + "_lastSeen", Date.now().toString()); }catch(e){} }
});
// ---------- Init ----------
load();
applyOfflineProgress();
renderAll();
// Autosave
setInterval(save, 5000);
})();
</script>
</body>
</html>
Game Source: Football Empire — Build Your Dynasty
Creator: LunarGalaxy87
Libraries: none
Complexity: complex (625 lines, 23.1 KB)
The full source code is displayed above on this page.
Remix Instructions
To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: football-empire-build-your-dynasty-lunargalaxy87" to link back to the original. Then publish at arcadelab.ai/publish.