diff --git a/index.html b/index.html
index ea3b80a..f7d9cdb 100644
--- a/index.html
+++ b/index.html
@@ -96,6 +96,8 @@ body{background:var(--bg);color:var(--text);font-family:'SF Mono','Cascadia Code
@keyframes toast-in{from{transform:translateX(40px);opacity:0}to{transform:translateX(0);opacity:0.95}}
@keyframes toast-out{from{opacity:0.95;transform:translateX(0)}to{opacity:0;transform:translateX(40px)}}
@keyframes res-pulse{0%{transform:scale(1)}50%{transform:scale(1.18);color:#80d0ff}100%{transform:scale(1)}}
+.particle{position:fixed;pointer-events:none;z-index:150;border-radius:50%;animation:particle-fly 0.6s ease-out forwards}
+@keyframes particle-fly{0%{opacity:1;transform:translate(0,0) scale(1)}100%{opacity:0;transform:translate(var(--px),var(--py)) scale(0.2)}}
@keyframes res-shake{0%,100%{transform:translateX(0)}20%{transform:translateX(-3px)}40%{transform:translateX(3px)}60%{transform:translateX(-2px)}80%{transform:translateX(2px)}}
.r-val.pulse{animation:res-pulse 0.35s ease-out}
.r-val.shake{animation:res-shake 0.3s ease-out;color:var(--red)!important}
diff --git a/js/engine.js b/js/engine.js
index 361f1aa..a0e6048 100644
--- a/js/engine.js
+++ b/js/engine.js
@@ -303,6 +303,12 @@ function buyBuilding(id) {
updateRates();
const label = qty > 1 ? `x${qty}` : '';
log(`Built ${def.name} ${label} (total: ${G.buildings[id]})`);
+ // Particle burst on purchase
+ const btn = document.querySelector('[onclick="buyBuilding(\'' + id + '\')"]');
+ if (btn) {
+ const rect = btn.getBoundingClientRect();
+ spawnParticles(rect.left + rect.width / 2, rect.top + rect.height / 2, '#4a9eff', 10);
+ }
render();
}
@@ -329,6 +335,12 @@ function buyProject(id) {
}
updateRates();
+ // Gold particle burst on project completion
+ const pBtn = document.querySelector('[onclick="buyProject(\'' + id + '\')"]');
+ if (pBtn) {
+ const rect = pBtn.getBoundingClientRect();
+ spawnParticles(rect.left + rect.width / 2, rect.top + rect.height / 2, '#ffd700', 16);
+ }
render();
}
diff --git a/js/utils.js b/js/utils.js
index d8828d2..f973830 100644
--- a/js/utils.js
+++ b/js/utils.js
@@ -285,6 +285,31 @@ function getClickPower() {
return (1 + Math.floor(G.buildings.autocoder * 0.5) + Math.max(0, (G.phase - 1)) * 2) * G.codeBoost;
}
+/**
+ * Spawns a burst of particles at (x, y) for visual feedback.
+ * @param {number} x - Center X in viewport pixels.
+ * @param {number} y - Center Y in viewport pixels.
+ * @param {string} color - Particle color (CSS value).
+ * @param {number} [count=12] - Number of particles.
+ */
+function spawnParticles(x, y, color, count) {
+ count = count || 12;
+ for (let i = 0; i < count; i++) {
+ const el = document.createElement('div');
+ el.className = 'particle';
+ const size = 3 + Math.random() * 4;
+ const angle = (Math.PI * 2 * i / count) + (Math.random() - 0.5) * 0.5;
+ const dist = 30 + Math.random() * 40;
+ const px = Math.cos(angle) * dist;
+ const py = Math.sin(angle) * dist;
+ el.style.cssText =
+ 'left:' + x + 'px;top:' + y + 'px;width:' + size + 'px;height:' + size +
+ 'px;background:' + color + ';--px:' + px + 'px;--py:' + py + 'px';
+ document.body.appendChild(el);
+ setTimeout(function() { el.remove(); }, 650);
+ }
+}
+
/**
* Calculates production rates for all resources based on buildings and boosts.
*/
\ No newline at end of file