Initial Push

This commit is contained in:
2026-06-14 20:45:06 +00:00
parent 733ea84025
commit 0365f4542d
4 changed files with 1528 additions and 0 deletions
+9
View File
@@ -0,0 +1,9 @@
version: "3"
services:
client:
image: nginx
ports:
- 82:80
volumes:
- ./:/usr/share/nginx/html
+732
View File
@@ -0,0 +1,732 @@
// ============================================
// GAME STATE & INITIALIZATION
// ============================================
let state = {
humans: 0,
prayers: 0,
grace: 0,
sacredVessels: 0,
holyScripture: 0,
blessings: 0,
manna: 0,
souls: 0,
wisdom: 0,
miracles: 0,
auras: 0,
sacredIcons: 0,
commonCount: 0,
principalityCount: 0,
powerCount: 0,
virtueCount: 0,
dominionCount: 0,
thronesCount: 0,
cherubCount: 0,
seraphCount: 0,
archangelCount: 0,
commonBaseCost: 50,
principalityBaseCost: 150,
powerBaseCost: 250,
virtueBaseCost: 400,
dominionBaseCost: 600,
thronesBaseCost: 800,
cherubBaseCost: 1000,
seraphBaseCost: 1500,
archangelCost: 500,
unlockRequirements: {
tier2: 50,
tier3: 100,
tier4: 150,
tier5: 200,
tier6: 250,
tier7: 300,
tier8: 350,
tier9: 0
},
costScalingFactor: 1.15,
globalMultiplier: 1.0,
ascensionCount: 0,
lastTick: Date.now()
};
let soundEnabled = true;
let audioCtx = null;
// ============================================
// SOUND FUNCTIONS
// ============================================
function initAudio() {
if (!audioCtx) {
audioCtx = new (window.AudioContext || window.webkitAudioContext)();
}
}
function playClickSound() {
if (!soundEnabled || !audioCtx) return;
const osc = audioCtx.createOscillator();
const gain = audioCtx.createGain();
osc.connect(gain);
gain.connect(audioCtx.destination);
osc.frequency.value = 440;
gain.gain.setValueAtTime(0.3, audioCtx.currentTime);
gain.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + 0.1);
osc.start();
osc.stop(audioCtx.currentTime + 0.1);
}
function playBuySound() {
if (!soundEnabled || !audioCtx) return;
const osc = audioCtx.createOscillator();
const gain = audioCtx.createGain();
osc.connect(gain);
gain.connect(audioCtx.destination);
osc.frequency.value = 523.25;
gain.gain.setValueAtTime(0.3, audioCtx.currentTime);
gain.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + 0.2);
osc.start();
osc.stop(audioCtx.currentTime + 0.2);
}
function playPrestigeSound() {
if (!soundEnabled || !audioCtx) return;
const notes = [523.25, 659.25, 783.99, 1046.50];
let time = audioCtx.currentTime;
notes.forEach((freq, i) => {
setTimeout(() => {
const osc = audioCtx.createOscillator();
const gain = audioCtx.createGain();
osc.connect(gain);
gain.connect(audioCtx.destination);
osc.frequency.value = freq;
gain.gain.setValueAtTime(0.3, time + i * 100 / 1000);
gain.gain.exponentialRampToValueAtTime(0.01, time + i * 100 / 1000 + 0.4);
osc.start(time + i * 100 / 1000);
osc.stop(time + i * 100 / 1000 + 0.4);
}, i * 100);
});
}
// ============================================
// SIDE PANEL FUNCTIONS
// ============================================
function toggleSidePanel() {
const panel = document.getElementById('sidePanel');
const overlay = document.getElementById('overlay');
const btn = document.querySelector('.hamburger-btn');
if (panel.classList.contains('open')) {
closeSidePanel();
} else {
panel.classList.add('open');
overlay.classList.add('active');
btn.classList.add('active');
}
}
function closeSidePanel() {
const panel = document.getElementById('sidePanel');
const overlay = document.getElementById('overlay');
const btn = document.querySelector('.hamburger-btn');
panel.classList.remove('open');
overlay.classList.remove('active');
btn.classList.remove('active');
}
// ============================================
// VISUAL EFFECTS
// ============================================
function createFloatingNumber(x, y, amount, color = '#ffd700') {
const floatNum = document.createElement('div');
floatNum.className = 'floating-number';
let textToDisplay = '+0';
if (amount && !isNaN(amount)) {
textToDisplay = '+' + Math.round(Math.abs(amount));
}
floatNum.textContent = textToDisplay;
const roundedAmount = amount ? Math.round(Math.abs(amount)) : 0;
floatNum.style.color = color;
floatNum.style.fontSize = (roundedAmount > 100 ? '2rem' : '1.5rem');
floatNum.style.left = (x - 30) + 'px';
floatNum.style.top = (y - 50) + 'px';
const offsetX = (Math.random() - 0.5) * 40;
floatNum.style.setProperty('--tx', offsetX + 'px');
document.body.appendChild(floatNum);
setTimeout(() => { floatNum.remove(); }, 1500);
}
function createParticleBurst(x, y, color = '#ffd700') {
const particleCount = 12;
for (let i = 0; i < particleCount; i++) {
const particle = document.createElement('div');
particle.className = 'particle';
const size = Math.random() * 8 + 4;
particle.style.width = size + 'px';
particle.style.height = size + 'px';
const colors = ['#ffd700', '#ffecb3', '#ffe082', '#fff59d', '#ffffff'];
particle.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];
particle.style.left = x + 'px';
particle.style.top = y + 'px';
const angle = Math.random() * 2 * Math.PI;
const distance = Math.random() * 80 + 40;
const tx = Math.cos(angle) * distance + 'px';
const ty = Math.sin(angle) * distance + 'px';
particle.style.setProperty('--tx', tx);
particle.style.setProperty('--ty', ty);
document.body.appendChild(particle);
setTimeout(() => { particle.remove(); }, 1000);
}
}
function createSparkle(x, y, color = '#ffd700') {
const sparkleCount = 8;
for (let i = 0; i < sparkleCount; i++) {
setTimeout(() => {
const sparkle = document.createElement('div');
sparkle.className = 'sparkle';
sparkle.style.width = '20px';
sparkle.style.height = '20px';
sparkle.style.background = color;
sparkle.style.left = x + 'px';
sparkle.style.top = y + 'px';
document.body.appendChild(sparkle);
setTimeout(() => { sparkle.remove(); }, 600);
}, i * 50);
}
}
// ============================================
// CALCULATION HELPERS
// ============================================
function calculatePrayerMultiplier() {
let multiplier = state.globalMultiplier;
if (state.commonCount > 0) multiplier *= (1 + (state.commonCount * 0.01));
if (state.principalityCount > 0) multiplier *= (1 + (state.principalityCount * 0.1));
if (state.powerCount > 0) multiplier *= (1 + (state.powerCount * 0.15));
if (state.virtueCount > 0) multiplier *= (1 + (state.virtueCount * 0.25));
if (state.dominionCount > 0) multiplier *= (1 + (state.dominionCount * 0.2));
if (state.thronesCount > 0) multiplier *= (1 + (state.thronesCount * 0.15));
if (state.cherubCount > 0) multiplier *= (1 + (state.cherubCount * 0.25));
if (state.seraphCount > 0) multiplier *= (1 + (state.seraphCount * 5));
if (state.archangelCount > 0) multiplier *= (10 + (state.archangelCount * 2));
return multiplier;
}
function calculateSoulsMultiplier() {
let multiplier = state.globalMultiplier;
if (state.commonCount > 0) multiplier *= (1 + (state.commonCount * 0.5));
if (state.principalityCount > 0) multiplier *= (1 + (state.principalityCount * 0.1));
if (state.powerCount > 0) multiplier *= (1 + (state.powerCount * 0.15));
return multiplier;
}
function getCostMultiplier() {
let costReduction = state.globalMultiplier;
if (state.cherubCount > 0) costReduction *= Math.pow(0.75, state.cherubCount);
return costReduction;
}
function getCurrentCost(baseCost, count) {
const currentCost = baseCost * Math.pow(state.costScalingFactor, count);
const finalCost = currentCost * getCostMultiplier();
return Math.round(finalCost);
}
// ============================================
// UI UPDATE FUNCTIONS
// ============================================
function showStatus(message) {
document.getElementById('status-display').textContent = message;
}
function updateUI() {
const currencies = [
{ name: 'humans', displayId: 'sidebar-humans-display' },
{ name: 'prayers', displayId: 'sidebar-prayers-display' },
{ name: 'grace', displayId: 'sidebar-grace-display' },
{ name: 'sacredVessels', displayId: 'sidebar-vessel-display' },
{ name: 'holyScripture', displayId: 'sidebar-scripture-display' },
{ name: 'blessings', displayId: 'sidebar-blessing-display' },
{ name: 'manna', displayId: 'sidebar-manna-display' },
{ name: 'souls', displayId: 'sidebar-souls-display' },
{ name: 'wisdom', displayId: 'sidebar-wisdom-display' },
{ name: 'miracles', displayId: 'sidebar-miracle-display' },
{ name: 'auras', displayId: 'sidebar-aura-display' },
{ name: 'sacredIcons', displayId: 'sidebar-icon-display' }
];
currencies.forEach(curr => {
const el = document.getElementById(curr.displayId);
if (el) el.textContent = Math.round(state[curr.name]);
});
const prayerMultiplier = calculatePrayerMultiplier();
const totalPrayerGenPerSec = state.humans * 0.5; // Base Human Prayer Rate
document.getElementById('prayer-click-rate').textContent = Math.round(totalPrayerGenPerSec * prayerMultiplier) + '/click';
document.getElementById('holy-power').textContent = Math.round(totalPrayerGenPerSec * prayerMultiplier);
const tierCounts = ['commonCount', 'principalityCount', 'powerCount', 'virtueCount',
'dominionCount', 'thronesCount', 'cherubCount', 'seraphCount', 'archangelCount'];
const countIds = ['common-count', 'principality-count', 'power-count', 'virtue-count',
'dominion-count', 'throness-count', 'cherub-count', 'seraph-count', 'archangel-count'];
tierCounts.forEach((countVar, i) => {
document.getElementById(countIds[i]).textContent = state[countVar];
const panelCountId = 'panel-' + countIds[i];
const panelEl = document.getElementById(panelCountId);
if (panelEl) panelEl.textContent = state[countVar];
});
document.getElementById('global-multiplier').textContent = state.globalMultiplier.toFixed(1);
document.getElementById('ascension-count').textContent = state.ascensionCount;
const costMult = getCostMultiplier();
const commonCost = getCurrentCost(state.commonBaseCost, state.commonCount);
const principalityCost = getCurrentCost(state.principalityBaseCost, state.principalityCount);
const powerCost = getCurrentCost(state.powerBaseCost, state.powerCount);
const virtueCost = getCurrentCost(state.virtueBaseCost, state.virtueCount);
const dominionCost = getCurrentCost(state.dominionBaseCost, state.dominionCount);
const thronesCost = getCurrentCost(state.thronesBaseCost, state.thronesCount);
const cherubCost = getCurrentCost(state.cherubBaseCost, state.cherubCount);
const seraphCost = getCurrentCost(state.seraphBaseCost, state.seraphCount);
updatePanelAngelButtonsWithBatch(commonCost, principalityCost, powerCost, virtueCost,
dominionCost, thronesCost, cherubCost, seraphCost, costMult);
const ascendCost = 1 * state.ascensionCount;
document.getElementById('ascend-btn').textContent = `Ascend to Heaven (Cost: ${ascendCost} Virtue Point${ascendCost > 1 ? 's' : ''})`;
updateTierUnlocks(costMult);
}
function getCurrencyNameForTier(tier) {
const mappings = {
'common': 'Prayers',
'principality': 'Grace',
'power': 'Sacred Vessels',
'virtue': 'Blessings',
'dominion': 'Souls',
'throne': 'Wisdom',
'cherub': 'Manna',
'seraph': 'Miracles',
'archangel': 'Sacred Icons'
};
return mappings[tier] || 'Resource';
}
function updatePanelAngelButtonsWithBatch(commonCost, principalityCost, powerCost, virtueCost,
dominionCost, thronesCost, cherubCost, seraphCost, costMult) {
const updateQuickBuyButtons = (tierCardId, currencyKey, costPerUnit, baseAmounts = [1, 5, 10, 100]) => {
const card = document.getElementById(tierCardId);
if (!card) return;
const currentCurrency = state[currencyKey];
const quickBuyBtns = card.querySelectorAll('.quick-buys .buy-option-btn');
for (let i = 0; i < baseAmounts.length && quickBuyBtns[i]; i++) {
const amountToBuy = baseAmounts[i] * costPerUnit;
quickBuyBtns[i].disabled = currentCurrency < amountToBuy;
}
};
updateQuickBuyButtons('common-angel-panel-card', 'prayers', commonCost);
// CORRECTED TIER 2: Checks Grace instead of Souls
if (state.grace >= state.unlockRequirements.tier2) {
const card = document.getElementById('principality-angel-panel-card');
if (card) card.classList.remove('locked');
updateQuickBuyButtons('principality-angel-panel-card', 'grace', principalityCost);
} else {
const card = document.getElementById('principality-angel-panel-card');
if (card) card.classList.add('locked');
}
if (state.sacredVessels >= state.unlockRequirements.tier3) {
const card = document.getElementById('power-angel-panel-card');
if (card) card.classList.remove('locked');
updateQuickBuyButtons('power-angel-panel-card', 'sacredVessels', powerCost);
} else {
const card = document.getElementById('power-angel-panel-card');
if (card) card.classList.add('locked');
}
if (state.manna >= state.unlockRequirements.tier4) {
const card = document.getElementById('virtue-angel-panel-card');
if (card) card.classList.remove('locked');
updateQuickBuyButtons('virtue-angel-panel-card', 'blessings', virtueCost);
} else {
const card = document.getElementById('virtue-angel-panel-card');
if (card) card.classList.add('locked');
}
if (state.wisdom >= state.unlockRequirements.tier5) {
const card = document.getElementById('dominion-angel-panel-card');
if (card) card.classList.remove('locked');
updateQuickBuyButtons('dominion-angel-panel-card', 'souls', dominionCost);
} else {
const card = document.getElementById('dominion-angel-panel-card');
if (card) card.classList.add('locked');
}
if (state.miracles >= state.unlockRequirements.tier6) {
const card = document.getElementById('throne-angel-panel-card');
if (card) card.classList.remove('locked');
updateQuickBuyButtons('throne-angel-panel-card', 'wisdom', thronesCost);
} else {
const card = document.getElementById('throne-angel-panel-card');
if (card) card.classList.add('locked');
}
if (state.auras >= state.unlockRequirements.tier7) {
const card = document.getElementById('cherub-angel-panel-card');
if (card) card.classList.remove('locked');
updateQuickBuyButtons('cherub-angel-panel-card', 'manna', cherubCost);
} else {
const card = document.getElementById('cherub-angel-panel-card');
if (card) card.classList.add('locked');
}
if (state.sacredIcons >= state.unlockRequirements.tier8) {
const card = document.getElementById('seraph-angel-panel-card');
if (card) card.classList.remove('locked');
updateQuickBuyButtons('seraph-angel-panel-card', 'miracles', seraphCost);
} else {
const card = document.getElementById('seraph-angel-panel-card');
if (card) card.classList.add('locked');
}
if (state.seraphCount > 0) {
const card = document.getElementById('archangel-angel-panel-card');
if (card) card.classList.remove('locked');
updateQuickBuyButtons('archangel-angel-panel-card', 'sacredIcons', state.archangelCost);
} else {
const card = document.getElementById('archangel-angel-panel-card');
if (card) card.classList.add('locked');
}
}
function updateTierUnlocks(costMult) {
const tierCards = [
{ id: 'tier-1-card', unlocked: true },
{ id: 'tier-2-card', unlocked: state.souls >= state.unlockRequirements.tier2 },
{ id: 'tier-3-card', unlocked: state.sacredVessels >= state.unlockRequirements.tier3 },
{ id: 'tier-4-card', unlocked: state.manna >= state.unlockRequirements.tier4 },
{ id: 'tier-5-card', unlocked: state.wisdom >= state.unlockRequirements.tier5 },
{ id: 'tier-6-card', unlocked: state.miracles >= state.unlockRequirements.tier6 },
{ id: 'tier-7-card', unlocked: state.auras >= state.unlockRequirements.tier7 },
{ id: 'tier-8-card', unlocked: state.sacredIcons >= state.unlockRequirements.tier8 },
{ id: 'tier-9-card', unlocked: state.seraphCount > 0 }
];
tierCards.forEach(tier => {
const card = document.getElementById(tier.id);
if (card) {
if (tier.unlocked) {
card.classList.remove('locked');
card.classList.add('unlocked');
} else {
card.classList.add('locked');
card.classList.remove('unlocked');
}
}
});
const tierIds = ['tier-2-card', 'tier-3-card', 'tier-4-card', 'tier-5-card',
'tier-6-card', 'tier-7-card', 'tier-8-card'];
const panelCardIds = ['principality-angel-panel-card', 'power-angel-panel-card', 'virtue-angel-panel-card',
'dominion-angel-panel-card', 'throne-angel-panel-card', 'cherub-angel-panel-card',
'seraph-angel-panel-card'];
tierIds.forEach((tierId, i) => {
const card = document.getElementById(panelCardIds[i]);
if (card) {
if (tierCards[i+1].unlocked) {
card.classList.remove('locked');
card.classList.add('unlocked');
} else {
card.classList.add('locked');
card.classList.remove('unlocked');
}
}
});
const archCard = document.getElementById('archangel-angel-panel-card');
if (archCard && tierCards[8].unlocked) {
archCard.classList.remove('locked');
archCard.classList.add('unlocked');
} else if (archCard) {
archCard.classList.add('locked');
archCard.classList.remove('unlocked');
}
}
// ============================================
// GAME LOGIC FUNCTIONS
// ============================================
function prayForAnswers(event) {
state.humans += 10;
updateUI();
const rect = event.target.getBoundingClientRect();
const x = rect.left + rect.width / 2;
const y = rect.top + rect.height / 2;
playClickSound();
createFloatingNumber(x, y, 10, '#E91E63');
createParticleBurst(x, y, '#E91E63');
createSparkle(x, y, '#E91E63');
}
function buyAngel(tier, quantity) {
let baseCost, currentCurrency, currencyName, countVar;
switch (tier) {
case 'common': baseCost = state.commonBaseCost; currentCurrency = 'prayers'; currencyName = 'Prayers'; countVar = 'commonCount'; break;
case 'principality': baseCost = state.principalityBaseCost; currentCurrency = 'grace'; currencyName = 'Grace'; countVar = 'principalityCount'; break;
case 'power': baseCost = state.powerBaseCost; currentCurrency = 'sacredVessels'; currencyName = 'Sacred Vessels'; countVar = 'powerCount'; break;
case 'virtue': baseCost = state.virtueBaseCost; currentCurrency = 'blessings'; currencyName = 'Blessings'; countVar = 'virtueCount'; break;
case 'dominion': baseCost = state.dominionBaseCost; currentCurrency = 'souls'; currencyName = 'Souls'; countVar = 'dominionCount'; break;
case 'throne': baseCost = state.thronesBaseCost; currentCurrency = 'wisdom'; currencyName = 'Wisdom'; countVar = 'thronesCount'; break;
case 'cherub': baseCost = state.cherubBaseCost; currentCurrency = 'manna'; currencyName = 'Manna'; countVar = 'cherubCount'; break;
case 'seraph': baseCost = state.seraphBaseCost; currentCurrency = 'miracles'; currencyName = 'Miracles'; countVar = 'seraphCount'; break;
case 'archangel': baseCost = state.archangelCost; currentCurrency = 'sacredIcons'; currencyName = 'Sacred Icons'; countVar = 'archangelCount'; break;
default: return;
}
const scaledBaseCost = getCurrentCost(baseCost, state[countVar]);
const costToPay = scaledBaseCost * quantity;
if (state[currentCurrency] >= costToPay) {
const eventTarget = document.activeElement;
playBuySound();
createFloatingNumber(eventTarget.getBoundingClientRect().left + 50, eventTarget.getBoundingClientRect().top, costToPay, '#4CAF50');
createParticleBurst(eventTarget.getBoundingClientRect().left + 100, eventTarget.getBoundingClientRect().top, '#4CAF50');
state[currentCurrency] -= costToPay;
state[countVar] += quantity;
showStatus(`Purchased ${quantity} x ${tier.toUpperCase()}!`);
updateUI();
} else {
const eventTarget = document.activeElement;
showStatus(`Not enough ${currencyName}! Need ${costToPay}`);
createParticleBurst(eventTarget.getBoundingClientRect().left, eventTarget.getBoundingClientRect().top, '#FF5722');
setTimeout(updateUI, 100);
}
}
function prestigeAscend(event) {
const ascendCost = 1 * state.ascensionCount;
if (state.virtuePoints >= ascendCost) {
state.virtuePoints -= ascendCost;
state.virtuePoints += 1;
state.ascensionCount++;
state.globalMultiplier *= 1.5;
state.humans = 0; state.prayers = 0; state.souls = 0;
state.commonCount = 0; state.principalityCount = 0; state.powerCount = 0;
state.virtueCount = 0; state.dominionCount = 0; state.thronesCount = 0;
state.cherubCount = 0; state.seraphCount = 0;
const rect = event.target.getBoundingClientRect();
playPrestigeSound();
createParticleBurst(rect.left + rect.width / 2, rect.top + rect.height / 2, '#ffd700');
createSparkle(rect.left + rect.width / 2, rect.top + rect.height / 2, '#ffd700');
showStatus(`🌟 ASCENDED! Tiers Ascended: ${state.ascensionCount} | Multiplier: ${state.globalMultiplier.toFixed(1)}x`);
updateUI();
} else {
const rect = event.target.getBoundingClientRect();
showStatus(`Not enough Virtue Points! Need ${ascendCost}`);
event.target.style.background = '#c62828';
setTimeout(() => event.target.style.background = '', 300);
}
}
function saveGame() {
localStorage.setItem('celestialHierarchySave', JSON.stringify(state));
showStatus('Game saved successfully!');
if (soundEnabled) playClickSound();
const rect = document.getElementById('save-btn').getBoundingClientRect();
createFloatingNumber(rect.left + 50, rect.top - 20, '💾', '#2E7D32');
}
function loadGame() {
const saved = localStorage.getItem('celestialHierarchySave');
if (saved) {
try {
const loadedState = JSON.parse(saved);
state = {...state, ...loadedState};
showStatus('Game loaded successfully!');
} catch (e) {
showStatus('Load failed: corrupted save data');
console.error(e);
}
} else {
showStatus('No save found. Starting new game!');
}
updateUI();
if (soundEnabled) playClickSound();
const rect = document.getElementById('load-btn').getBoundingClientRect();
createFloatingNumber(rect.left + 30, rect.top - 20, '📂', '#1976d2');
}
function newGame() {
if (confirm('Are you sure? All progress will be lost.')) {
localStorage.removeItem('celestialHierarchySave');
state = {
humans: 0, prayers: 0, grace: 0, sacredVessels: 0, holyScripture: 0, blessings: 0, manna: 0, souls: 0, wisdom: 0, miracles: 0, auras: 0, sacredIcons: 0,
commonCount: 0, principalityCount: 0, powerCount: 0, virtueCount: 0, dominionCount: 0, thronesCount: 0, cherubCount: 0, seraphCount: 0, archangelCount: 0,
commonBaseCost: 50, principalityBaseCost: 150, powerBaseCost: 250, virtueBaseCost: 400, dominionBaseCost: 600, thronesBaseCost: 800, cherubBaseCost: 1000, seraphBaseCost: 1500, archangelCost: 500,
unlockRequirements: { tier2: 50, tier3: 100, tier4: 150, tier5: 200, tier6: 250, tier7: 300, tier8: 350, tier9: 0 },
costScalingFactor: 1.15, globalMultiplier: 1.0, ascensionCount: 0, lastTick: Date.now()
};
showStatus('Starting new game!');
if (soundEnabled) playClickSound();
const rect = document.getElementById('new-btn').getBoundingClientRect();
createFloatingNumber(rect.left + 30, rect.top - 20, '🆕', '#c62828');
updateUI();
}
}
function toggleSound() {
soundEnabled = !soundEnabled;
document.getElementById('sound-status').textContent = soundEnabled ? 'ON' : 'OFF';
if (soundEnabled) playClickSound();
}
// ============================================
// GAME LOOP
// ============================================
function gameLoop() {
const now = Date.now();
const elapsed = Math.max((now - state.lastTick) / 1000, 0.01);
let virtueGain = 0;
if (state.virtueCount > 0) virtueGain += state.virtueCount * 0.1 * elapsed;
if (state.dominionCount > 0) virtueGain += state.dominionCount * 0.2 * elapsed;
if (state.archangelCount > 0) virtueGain += state.archangelCount * 1.0 * elapsed;
state.virtuePoints += virtueGain;
if (state.humans > 0) {
const prayerMultiplier = calculatePrayerMultiplier();
const prayerRateFromHumans = state.humans * 0.5;
state.prayers += (prayerRateFromHumans * elapsed * prayerMultiplier);
}
if (state.commonCount > 0) {
state.grace += (state.commonCount * 1 * elapsed);
}
if (state.principalityCount > 0) {
state.sacredVessels += (state.souls * 0.1 * elapsed);
}
if (state.powerCount > 0) {
state.holyScripture += (state.grace * 0.2 * elapsed);
}
if (state.virtueCount > 0) {
state.manna += (state.sacredVessels * 0.15 * elapsed);
if (state.commonCount > 0) {
const soulsMultiplier = calculateSoulsMultiplier();
state.souls += (state.prayers * 0.5 * elapsed * soulsMultiplier);
}
}
if (state.dominionCount > 0) {
state.wisdom += (state.manna * 0.2 * elapsed);
}
if (state.thronesCount > 0) {
state.miracles += (state.souls * 0.4 * elapsed);
}
if (state.cherubCount > 0) {
state.auras += (state.wisdom * 0.15 * elapsed);
}
if (state.seraphCount > 0) {
state.sacredIcons += (state.miracles * 0.25 * elapsed);
}
state.lastTick = now;
updateUI();
}
// ============================================
// INITIALIZATION
// ============================================
document.addEventListener('DOMContentLoaded', function() {
initAudio();
document.getElementById('prayer-btn').addEventListener('click', prayForAnswers);
const quickBuyButtons = document.querySelectorAll('.buy-option-btn');
quickBuyButtons.forEach(btn => {
const tier = btn.getAttribute('data-tier');
const qty = parseInt(btn.getAttribute('data-qty'));
if (tier && qty) {
btn.addEventListener('click', (e) => {
e.preventDefault();
buyAngel(tier, qty);
});
}
});
document.getElementById('ascend-btn').addEventListener('click', prestigeAscend);
document.getElementById('save-btn').addEventListener('click', saveGame);
document.getElementById('load-btn').addEventListener('click', loadGame);
document.getElementById('new-btn').addEventListener('click', newGame);
document.getElementById('sound-toggle-btn').addEventListener('click', toggleSound);
loadGame();
updateUI();
setInterval(gameLoop, 100);
});
+374
View File
@@ -0,0 +1,374 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Celestial Hierarchy - Human Engine</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- Hamburger Button -->
<button class="hamburger-btn" onclick="toggleSidePanel()">
<span></span><span></span><span></span>
</button>
<!-- Overlay -->
<div class="overlay" id="overlay" onclick="closeSidePanel()"></div>
<!-- Side Panel (Hamburger Menu) -->
<div class="side-panel" id="sidePanel">
<div class="panel-header">
<h2>👼 Angelic Summoning</h2>
<button class="close-panel-btn" onclick="closeSidePanel()">×</button>
</div>
<div style="text-align: center; color: #888; margin-bottom: 20px;">View currencies in the Left Sidebar</div>
<!-- Panel Angel Cards -->
<div id="panel-angels-container">
<!-- Tier 1: Common Angels -->
<div class="angel-card unlocked" id="common-angel-panel-card">
<div class="tier-badge tier-common">Tier 1</div>
<div class="angel-name">Common Angel</div>
<div class="angel-count" id="panel-common-count">0</div>
<div class="angel-cost" id="panel-common-cost">Cost: 50 Prayers</div>
<div class="angel-buff">+1 Grace/sec each</div>
<div class="quick-buys">
<button class="buy-option-btn" data-tier="common" data-qty="1">x1</button>
<button class="buy-option-btn" data-tier="common" data-qty="5">x5</button>
<button class="buy-option-btn" data-tier="common" data-qty="10">x10</button>
<button class="buy-option-btn" data-tier="common" data-qty="100">x100</button>
</div>
</div>
<!-- Tier 2: Principalities -->
<div class="angel-card locked" id="principality-angel-panel-card">
<div class="tier-badge tier-principalities">Tier 2</div>
<div class="angel-name">Principalities Angel</div>
<div class="angel-count" id="panel-principality-count">0</div>
<div class="angel-cost" id="panel-principality-cost">Cost: 150 Grace</div>
<!-- CORRECTED: Unlocks based on Grace now -->
<div class="unlock-req">Requires 150 Grace to unlock Tier 2</div>
<div class="angel-buff">+10% nearby bonus</div>
<div class="quick-buys">
<button class="buy-option-btn" data-tier="principality" data-qty="1">x1</button>
<button class="buy-option-btn" data-tier="principality" data-qty="5">x5</button>
<button class="buy-option-btn" data-tier="principality" data-qty="10">x10</button>
<button class="buy-option-btn" data-tier="principality" data-qty="100">x100</button>
</div>
</div>
<!-- Tier 3: Powers -->
<div class="angel-card locked" id="power-angel-panel-card">
<div class="tier-badge tier-powers">Tier 3</div>
<div class="angel-name">Power Angel</div>
<div class="angel-count" id="panel-power-count">0</div>
<div class="angel-cost" id="panel-power-cost">Cost: 250 Sacred Vessels</div>
<div class="unlock-req">Requires 100 Sacred Vessels to unlock Tier 3</div>
<div class="angel-buff">+15% resource collection</div>
<div class="quick-buys">
<button class="buy-option-btn" data-tier="power" data-qty="1">x1</button>
<button class="buy-option-btn" data-tier="power" data-qty="5">x5</button>
<button class="buy-option-btn" data-tier="power" data-qty="10">x10</button>
<button class="buy-option-btn" data-tier="power" data-qty="100">x100</button>
</div>
</div>
<!-- Tier 4: Virtues -->
<div class="angel-card locked" id="virtue-angel-panel-card">
<div class="tier-badge tier-virtues">Tier 4</div>
<div class="angel-name">Virtue Angel</div>
<div class="angel-count" id="panel-virtue-count">0</div>
<div class="angel-cost" id="panel-virtue-cost">Cost: 400 Blessings</div>
<div class="unlock-req">Requires 150 Manna to unlock Tier 4</div>
<div class="angel-buff">+25% miracle chance</div>
<div class="quick-buys">
<button class="buy-option-btn" data-tier="virtue" data-qty="1">x1</button>
<button class="buy-option-btn" data-tier="virtue" data-qty="5">x5</button>
<button class="buy-option-btn" data-tier="virtue" data-qty="10">x10</button>
<button class="buy-option-btn" data-tier="virtue" data-qty="100">x100</button>
</div>
</div>
<!-- Tier 5: Dominions -->
<div class="angel-card locked" id="dominion-angel-panel-card">
<div class="tier-badge tier-dominions">Tier 5</div>
<div class="angel-name">Dominion Angel</div>
<div class="angel-count" id="panel-dominion-count">0</div>
<div class="angel-cost" id="panel-dominion-cost">Cost: 600 Souls</div>
<div class="unlock-req">Requires 200 Wisdom to unlock Tier 5</div>
<div class="angel-buff">+20% all output</div>
<div class="quick-buys">
<button class="buy-option-btn" data-tier="dominion" data-qty="1">x1</button>
<button class="buy-option-btn" data-tier="dominion" data-qty="5">x5</button>
<button class="buy-option-btn" data-tier="dominion" data-qty="10">x10</button>
<button class="buy-option-btn" data-tier="dominion" data-qty="100">x100</button>
</div>
</div>
<!-- Tier 6: Thrones -->
<div class="angel-card locked" id="throne-angel-panel-card">
<div class="tier-badge tier-thrones">Tier 6</div>
<div class="angel-name">Throne Angel</div>
<div class="angel-count" id="panel-throne-count">0</div>
<div class="angel-cost" id="panel-throne-cost">Cost: 800 Wisdom</div>
<div class="unlock-req">Requires 250 Miracles to unlock Tier 6</div>
<div class="angel-buff">+15% efficiency</div>
<div class="quick-buys">
<button class="buy-option-btn" data-tier="throne" data-qty="1">x1</button>
<button class="buy-option-btn" data-tier="throne" data-qty="5">x5</button>
<button class="buy-option-btn" data-tier="throne" data-qty="10">x10</button>
<button class="buy-option-btn" data-tier="throne" data-qty="100">x100</button>
</div>
</div>
<!-- Tier 7: Cherubim -->
<div class="angel-card locked premium-angel" id="cherub-angel-panel-card">
<div class="tier-badge tier-cherubim">Tier 7</div>
<div class="angel-name">Cherubim Guardian</div>
<div class="angel-count" id="panel-cherub-count">0</div>
<div class="angel-cost" id="panel-cherub-cost">Cost: 1000 Manna</div>
<div class="unlock-req">Requires 300 Auras to unlock Tier 7</div>
<div class="angel-buff">-25% spawn costs</div>
<div class="quick-buys">
<button class="buy-option-btn" data-tier="cherub" data-qty="1">x1</button>
<button class="buy-option-btn" data-tier="cherub" data-qty="5">x5</button>
<button class="buy-option-btn" data-tier="cherub" data-qty="10">x10</button>
<button class="buy-option-btn" data-tier="cherub" data-qty="100">x100</button>
</div>
</div>
<!-- Tier 8: Seraphim -->
<div class="angel-card locked premium-angel" id="seraph-angel-panel-card">
<div class="tier-badge tier-seraphim">Tier 8</div>
<div class="angel-name">Seraphim Fire Angel</div>
<div class="angel-count" id="panel-seraph-count">0</div>
<div class="angel-cost" id="panel-seraph-cost">Cost: 1500 Miracles</div>
<div class="unlock-req">Requires 350 Sacred Icons to unlock Tier 8</div>
<div class="angel-buff">+5x Prayer generation</div>
<div class="quick-buys">
<button class="buy-option-btn" data-tier="seraph" data-qty="1">x1</button>
<button class="buy-option-btn" data-tier="seraph" data-qty="5">x5</button>
<button class="buy-option-btn" data-tier="seraph" data-qty="10">x10</button>
<button class="buy-option-btn" data-tier="seraph" data-qty="100">x100</button>
</div>
</div>
<!-- Tier 9: Arch-Angels -->
<div class="angel-card locked premium-angel" id="archangel-angel-panel-card">
<div class="tier-badge tier-archangels">Tier 9</div>
<div class="angel-name">Arch-Angel (Michael/Gabriel)</div>
<div class="angel-count" id="panel-archangel-count">0</div>
<div class="angel-cost" id="panel-archangel-cost">Cost: 500 Sacred Icons</div>
<div class="unlock-req">Requires Tier 8 to unlock Tier 9</div>
<div class="angel-buff">10x+ Multiplier! Ultimate!</div>
<div class="quick-buys">
<button class="buy-option-btn" data-tier="archangel" data-qty="1">x1</button>
<button class="buy-option-btn" data-tier="archangel" data-qty="5">x5</button>
<button class="buy-option-btn" data-tier="archangel" data-qty="10">x10</button>
<button class="buy-option-btn" data-tier="archangel" data-qty="100">x100</button>
</div>
</div>
</div>
</div>
<!-- Main Game Content Wrapper -->
<div class="main-layout">
<!-- LEFT SIDEBAR: All Currencies -->
<aside class="sidebar">
<div class="currency-frame">
<h3>💎 Divine Currencies</h3>
<div class="currency-row humans-currency">
<span class="currency-name">Humans</span>
<span class="currency-amount" id="sidebar-humans-display">0</span>
</div>
<div class="currency-row prayers-currency">
<span class="currency-name">Prayers</span>
<span class="currency-amount" id="sidebar-prayers-display">0</span>
</div>
<div class="currency-row grace-currency">
<span class="currency-name">Grace</span>
<span class="currency-amount" id="sidebar-grace-display">0</span>
</div>
<div class="currency-row vessel-currency">
<span class="currency-name">Vessels</span>
<span class="currency-amount" id="sidebar-vessel-display">0</span>
</div>
<div class="currency-row scripture-currency">
<span class="currency-name">Scripture</span>
<span class="currency-amount" id="sidebar-scripture-display">0</span>
</div>
<div class="currency-row blessing-currency">
<span class="currency-name">Blessings</span>
<span class="currency-amount" id="sidebar-blessing-display">0</span>
</div>
<div class="currency-row manna-currency">
<span class="currency-name">Manna</span>
<span class="currency-amount" id="sidebar-manna-display">0</span>
</div>
<div class="currency-row souls-currency">
<span class="currency-name">Souls</span>
<span class="currency-amount" id="sidebar-souls-display">0</span>
</div>
<div class="currency-row wisdom-currency">
<span class="currency-name">Wisdom</span>
<span class="currency-amount" id="sidebar-wisdom-display">0</span>
</div>
<div class="currency-row miracle-currency">
<span class="currency-name">Miracles</span>
<span class="currency-amount" id="sidebar-miracle-display">0</span>
</div>
<div class="currency-row aura-currency">
<span class="currency-name">Auras</span>
<span class="currency-amount" id="sidebar-aura-display">0</span>
</div>
<div class="currency-row icon-currency">
<span class="currency-name">Icons</span>
<span class="currency-amount" id="sidebar-icon-display">0</span>
</div>
</div>
<div class="production-info" style="margin-top: 20px;">
<h4>⚡ Metrics (per sec)</h4>
<div class="production-item">
<span>Prayers:</span>
<span id="prayer-click-rate">10.0</span>
</div>
<div class="production-item">
<span>Holy Power:</span>
<span id="holy-power">1000</span>
</div>
</div>
<!-- Sound Toggle -->
<div class="sound-toggle">
<button id="sound-toggle-btn" class="sound-btn">🔊 Sound: <span id="sound-status">ON</span></button>
</div>
</aside>
<!-- RIGHT GAME CONTENT -->
<main class="game-content">
<h1 style="color: #ffd700; text-align: center; margin-bottom: 10px;">🕊️ CELESTIAL HIERARCHY 🕊️</h1>
<p class="subtitle" style="text-align: center; color: #aaa; margin-bottom: 20px;">Ascend through the 9 Tiers of Heaven with 11 Currencies</p>
<!-- Tier Display Section -->
<div class="tier-display-section">
<h3>🌟 Angelic Tiers Unlocked</h3>
<div class="tiers-grid">
<div class="tier-card unlocked" id="tier-1-card">
<div class="tier-badge tier-common">Tier 1</div>
<div class="tier-name">Common Angels</div>
<div class="tier-count" id="common-count">0</div>
<div class="tier-desc">+1 Grace/sec | Cost: Prayers</div>
</div>
<div class="tier-card locked" id="tier-2-card">
<div class="tier-badge tier-principalities">Tier 2</div>
<div class="tier-name">Principalities</div>
<div class="tier-count" id="principality-count">0</div>
<div class="tier-desc">+10% bonus | Cost: Grace (150 Grace unlock)</div>
</div>
<div class="tier-card locked" id="tier-3-card">
<div class="tier-badge tier-powers">Tier 3</div>
<div class="tier-name">Powers</div>
<div class="tier-count" id="power-count">0</div>
<div class="tier-desc">+15% resource | Cost: Vessels (100 Vessels unlock)</div>
</div>
<div class="tier-card locked" id="tier-4-card">
<div class="tier-badge tier-virtues">Tier 4</div>
<div class="tier-name">Virtues</div>
<div class="tier-count" id="virtue-count">0</div>
<div class="tier-desc">+25% miracle | Cost: Blessings (150 Manna unlock)</div>
</div>
<div class="tier-card locked" id="tier-5-card">
<div class="tier-badge tier-dominions">Tier 5</div>
<div class="tier-name">Dominions</div>
<div class="tier-count" id="dominion-count">0</div>
<div class="tier-desc">+20% output | Cost: Souls (200 Wisdom unlock)</div>
</div>
<div class="tier-card locked" id="tier-6-card">
<div class="tier-badge tier-thrones">Tier 6</div>
<div class="tier-name">Thrones</div>
<div class="tier-count" id="throness-count">0</div>
<div class="tier-desc">+15% efficiency | Cost: Wisdom (250 Miracles unlock)</div>
</div>
<div class="tier-card locked" id="tier-7-card">
<div class="tier-badge tier-cherubim">Tier 7</div>
<div class="tier-name">Cherubim</div>
<div class="tier-count" id="cherub-count">0</div>
<div class="tier-desc">Cost Reduction | Cost: Manna (300 Auras unlock)</div>
</div>
<div class="tier-card locked" id="tier-8-card">
<div class="tier-badge tier-seraphim">Tier 8</div>
<div class="tier-name">Seraphim</div>
<div class="tier-count" id="seraph-count">0</div>
<div class="tier-desc">+5x Prayer | Cost: Miracles (350 Icons unlock)</div>
</div>
<div class="tier-card locked" id="tier-9-card">
<div class="tier-badge tier-archangels">Tier 9</div>
<div class="tier-name">Arch-Angels</div>
<div class="tier-count" id="archangel-count">0</div>
<div class="tier-desc">10x+ Multiplier | Cost: Sacred Icons (Tier 8 unlock)</div>
</div>
</div>
</div>
<!-- Prayer Section -->
<div class="prayer-section">
<h3>🙏 Human Summoning</h3>
<button id="prayer-btn" class="click-btn glow-btn">🔮 Pray for Humans (+10 Humans)</button>
</div>
<!-- Prestige Section -->
<div class="prestige-section">
<h3>🔯 Ascension (Prestige)</h3>
<p style="text-align: center; margin-bottom: 10px;">Reset progress for permanent bonuses!</p>
<button id="ascend-btn" class="buy-option-btn">Ascend to Heaven (Cost: 1 Virtue Point)</button>
<div class="multiplier-display">
✨ Global Bonus: <span id="global-multiplier">1.0</span>x
</div>
<div class="prestige-counter">
Ascensions: <span id="ascension-count">0</span>
</div>
</div>
<!-- Action Buttons -->
<div class="action-buttons">
<button id="save-btn" class="action-btn glow-btn save-btn">💾 Save</button>
<button id="load-btn" class="action-btn glow-btn load-btn">📂 Load</button>
<button id="new-btn" class="action-btn glow-btn new-btn">🆕 New Game</button>
</div>
<!-- Status -->
<div class="status-bar" id="status-display">Welcome to Celestial Hierarchy!</div>
</main>
</div>
<script src="game.js"></script>
</body>
</html>
+413
View File
@@ -0,0 +1,413 @@
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
color: #fff;
min-height: 100vh;
padding: 15px;
overflow-x: hidden;
}
/* Main Layout Grid */
.main-layout {
display: flex;
gap: 20px;
max-width: 1400px;
margin: 0 auto;
}
.sidebar {
width: 300px;
flex-shrink: 0;
}
.game-content {
flex-grow: 1;
min-width: 0;
}
/* Hamburger Button */
.hamburger-btn {
position: fixed;
top: 15px;
right: 280px;
background: linear-gradient(145deg, #7b1fa2, #4a148c);
border: none;
width: 50px;
height: 50px;
border-radius: 50%;
cursor: pointer;
z-index: 1001;
transition: all 0.3s ease;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
}
.hamburger-btn:hover { transform: scale(1.1); background: linear-gradient(145deg, #9c27b0, #6a1b9a); }
.hamburger-btn span {
display: block;
width: 24px;
height: 3px;
background: #fff;
margin: 5px auto;
border-radius: 3px;
transition: all 0.3s ease;
}
.hamburger-btn.active span:nth-child(1) { transform: rotate(45deg) translate(8px, 8px); }
.hamburger-btn.active span:nth-child(2) { opacity: 0; }
.hamburger-btn.active span:nth-child(3) { transform: rotate(-45deg) translate(7px, -6px); }
/* Side Panel */
.side-panel {
position: fixed;
top: 0;
right: -400px;
width: 380px;
height: 100vh;
background: linear-gradient(145deg, #2a2a4a, #1e1e3a);
box-shadow: -5px 0 15px rgba(0, 0, 0, 0.5);
z-index: 1000;
transition: right 0.4s ease-in-out;
overflow-y: auto;
padding: 20px;
}
.side-panel.open { right: 0; }
.panel-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding-bottom: 15px;
border-bottom: 2px solid #ffd700;
}
.panel-header h2 { color: #ffd700; font-size: 1.4rem; }
.close-panel-btn {
background: transparent;
border: none;
color: #fff;
font-size: 24px;
cursor: pointer;
transition: all 0.3s ease;
}
.close-panel-btn:hover { color: #ffd700; transform: rotate(90deg); }
/* Currency Sidebar */
.currency-frame {
background: linear-gradient(145deg, #2a2a4a, #1e1e3a);
border-radius: 10px;
padding: 15px;
margin-bottom: 20px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
}
.currency-frame h3 {
margin-bottom: 10px;
color: #ffd700;
font-size: 1.1rem;
text-align: center;
}
.currency-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 12px;
margin: 3px 0;
border-radius: 5px;
font-size: 0.9rem;
}
.currency-name {
color: #fff;
font-weight: 600;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 140px;
}
.currency-amount { font-weight: bold; font-size: 1.1rem; min-width: 60px; text-align: right; }
/* Currency Colors */
.humans-currency { background-color: #FCE4EC; color: #E91E63; }
.prayers-currency { background-color: #E8F5E9; color: #2E7D32; }
.grace-currency { background-color: #FFF3E0; color: #E65100; }
.vessel-currency { background-color: #E3F2FD; color: #1565C0; }
.scripture-currency { background-color: #F3E5F5; color: #7B1FA2; }
.blessing-currency { background-color: #FFECB3; color: #FF8F00; }
.manna-currency { background-color: #C8E6C9; color: #388E3C; }
.souls-currency { background-color: #FFCCBC; color: #D84315; }
.wisdom-currency { background-color: #BBDEFB; color: #0277BD; }
.miracle-currency { background-color: #FFE0B2; color: #E65100; }
.aura-currency { background-color: #E1BEE7; color: #8E24AA; }
.icon-currency { background-color: #FFF9C4; color: #FBC02D; box-shadow: 0 0 5px #FFD700; }
/* Tier Display */
.tier-badge {
display: inline-block;
padding: 3px 6px;
border-radius: 3px;
font-size: 0.65rem;
font-weight: bold;
margin-right: 4px;
}
.tier-common { background-color: #9E9E9E; color: white; }
.tier-principalities { background-color: #4CAF50; color: white; }
.tier-powers { background-color: #FF5722; color: white; }
.tier-virtues { background-color: #FFD700; color: black; }
.tier-dominions { background-color: #9C27B0; color: white; }
.tier-thrones { background-color: #03A9F4; color: white; }
.tier-cherubim { background-color: #8BC34A; color: black; }
.tier-seraphim { background-color: #E91E63; color: white; }
.tier-archangels { background-color: #FFD700; color: black; box-shadow: 0 0 15px #FFD700; }
/* Tier Display Section */
.tier-display-section {
background: linear-gradient(145deg, #2a2a4a, #1e1e3a);
border-radius: 10px;
padding: 15px;
margin-bottom: 20px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
}
.tier-display-section h3 {
color: #ffd700;
margin-bottom: 15px;
text-align: center;
}
.tiers-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 8px;
margin-top: 15px;
}
.tier-card {
background: rgba(255, 255, 255, 0.05);
padding: 8px;
border-radius: 6px;
text-align: center;
}
.tier-card.locked { opacity: 0.3; pointer-events: none; }
.tier-card.unlocked { opacity: 1; }
.tier-name { font-size: 0.85rem; color: #ffd700; margin-bottom: 4px; }
.tier-count { font-size: 1rem; color: #fff; margin-bottom: 3px; }
.tier-desc { font-size: 0.65rem; color: #aaa; line-height: 1.2; }
/* Prayer Section */
.prayer-section {
background: linear-gradient(145deg, #2a2a4a, #1e1e3a);
border-radius: 10px;
padding: 15px;
margin-bottom: 20px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
}
.prayer-section h3 { margin-bottom: 15px; color: #ffd700; text-align: center; font-size: 1.2rem; }
/* Click Button */
.click-btn {
display: block;
width: 90%;
margin: 20px auto;
padding: 15px 30px;
font-size: 1.1rem;
background: linear-gradient(145deg, #7b1fa2, #4a148c);
color: white;
border: none;
border-radius: 10px;
cursor: pointer;
transition: all 0.3s ease;
}
.click-btn:hover { background: linear-gradient(145deg, #9c27b0, #6a1b9a); transform: scale(1.02); }
.click-btn:active { transform: scale(0.98); }
/* Panel Angel Cards */
.angel-card {
background: rgba(255, 255, 255, 0.05);
padding: 15px;
border-radius: 8px;
margin-bottom: 15px;
transition: all 0.3s ease;
}
.angel-card.locked { opacity: 0.4; pointer-events: none; }
.angel-card.unlocked { opacity: 1; }
.premium-angel { border: 2px solid #ffd700; }
.angel-name { font-size: 1rem; color: #ffd700; margin-bottom: 5px; }
.angel-count { font-size: 1.2rem; color: #fff; margin-bottom: 5px; }
.angel-cost { font-size: 0.85rem; color: #aaa; margin-bottom: 3px; }
.angel-buff { font-size: 0.7rem; color: #4CAF50; line-height: 1.2; margin-top: 3px; }
/* Panel Angel Buttons */
.buy-option-btn {
background: linear-gradient(145deg, #7b1fa2, #4a148c);
border: none;
padding: 6px 10px;
color: white;
font-size: 0.8rem;
cursor: pointer;
transition: all 0.3s ease;
}
.buy-option-btn:hover:not(:disabled) { background: linear-gradient(145deg, #9c27b0, #6a1b9a); }
.buy-option-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.quick-buys { display: flex; gap: 5px; margin-top: 8px; justify-content: center; }
/* Panel Unlock Requirements */
.unlock-req { font-size: 0.7rem; color: #FFB300; margin-top: 4px; text-align: center; }
/* Prestige Section */
.prestige-section {
background: linear-gradient(145deg, #2a2a4a, #1e1e3a);
border-radius: 10px;
padding: 15px;
margin-bottom: 20px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
border: 2px solid #ffd700;
}
.prestige-section h3 {
color: #ffd700;
margin-bottom: 15px;
text-align: center;
font-size: 1.4rem;
}
/* Prestige Counter */
.prestige-counter {
text-align: center;
font-size: 2rem;
color: #ffd700;
margin-top: 15px;
text-shadow: 0 0 20px rgba(255, 215, 0, 0.8);
}
.multiplier-display {
text-align: center;
font-size: 1.2rem;
color: #ffd700;
margin-top: 10px;
}
/* Production Info */
.production-info {
background: linear-gradient(145deg, #2a2a4a, #1e1e3a);
border-radius: 10px;
padding: 15px;
margin-bottom: 20px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
font-size: 0.9rem;
}
.production-info h4 { color: #ffd700; margin-bottom: 10px; }
.production-item {
display: flex;
justify-content: space-between;
padding: 5px 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
/* Action Buttons */
.action-buttons { display: flex; justify-content: center; gap: 15px; margin: 15px 0; }
.action-btn {
padding: 12px 25px;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 1rem;
transition: all 0.3s ease;
}
.save-btn { background: linear-gradient(145deg, #2e7d32, #1b5e20); color: white; }
.load-btn { background: linear-gradient(145deg, #1976d2, #0d47a1); color: white; }
.new-btn { background: linear-gradient(145deg, #c62828, #b71c1c); color: white; }
.action-btn:hover { transform: translateY(-2px); box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3); }
/* Status */
.status-bar { text-align: center; padding: 10px; font-size: 1rem; color: #aaa; min-height: 24px; margin-bottom: 15px;}
/* Floating Numbers Animation */
.floating-number {
position: fixed;
pointer-events: none;
z-index: 1000;
font-weight: bold;
animation: floatUp 1.5s ease-out forwards;
}
@keyframes floatUp {
0% { opacity: 1; transform: translateY(0) scale(1); }
100% { opacity: 0; transform: translateY(-100px) scale(1.5); }
}
/* Particle Effects */
.particle {
position: fixed;
pointer-events: none;
z-index: 999;
border-radius: 50%;
animation: particleAnim 1s ease-out forwards;
}
@keyframes particleAnim {
0% { opacity: 1; transform: translate(0, 0) scale(1); }
100% { opacity: 0; transform: translate(var(--tx), var(--ty)) scale(0.2); }
}
/* Sparkle Effect */
.sparkle {
position: fixed;
pointer-events: none;
z-index: 998;
animation: sparkleAnim 0.6s ease-out forwards;
}
@keyframes sparkleAnim {
0% { opacity: 1; transform: scale(0); }
50% { opacity: 1; transform: scale(1.2); }
100% { opacity: 0; transform: scale(0); }
}
/* Sound Toggle */
.sound-toggle { text-align: center; margin-top: 10px; }
.sound-btn { background: #333; color: #fff; padding: 8px 20px; border-radius: 5px; cursor: pointer; font-size: 0.9rem; border: none;}
/* Backdrop overlay */
.overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
z-index: 999;
display: none;
}
.overlay.active { display: block; }
/* Responsive adjustments */
@media (max-width: 768px) {
.main-layout { flex-direction: column; }
.sidebar { width: 100%; }
.hamburger-btn { right: 15px; }
}