{} @import url('https://fonts.googleapis.com/css2?family=Cinzel:wght@400;700;900&family=Inter:wght@300;400;500;600&family=JetBrains+Mono:wght@400;500&display=swap'); #holy-grail-game * { margin: 0; padding: 0; box-sizing: border-box; } #holy-grail-game { font-family: 'Inter', sans-serif; background: linear-gradient(145deg, #1a1510 0%, #0d0b08 40%, #1a1510 100%); color: #e0d6c2; max-width: 500px; margin: 0 auto; padding: 24px 20px; min-height: 100vh; position: relative; overflow: hidden; } #holy-grail-game::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px; background: linear-gradient(90deg, transparent, #d4af37, transparent); } /* ---------- SCREENS ---------- */ .grail-screen { display: none; } .grail-screen.active { display: flex; flex-direction: column; align-items: center; } /* ---------- INTRO SCREEN ---------- */ .grail-ornament { font-size: 14px; letter-spacing: 12px; color: #d4af37; opacity: 0.5; margin: 4px 0; } .grail-title { font-family: 'Cinzel', serif; font-weight: 900; font-size: 32px; letter-spacing: 4px; text-transform: uppercase; background: linear-gradient(180deg, #f5e6a3 0%, #d4af37 40%, #a8872a 70%, #d4af37 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; text-align: center; line-height: 1.1; margin: 16px 0 4px; } .grail-subtitle { font-family: 'Inter', sans-serif; font-size: 11px; font-weight: 300; letter-spacing: 4px; text-transform: uppercase; color: #8a7d6b; margin-bottom: 24px; } .grail-description { font-size: 13px; line-height: 1.6; color: #b0a68e; text-align: center; max-width: 380px; margin-bottom: 24px; } .grail-rules { background: rgba(212, 175, 55, 0.06); border: 1px solid rgba(212, 175, 55, 0.15); border-radius: 4px; padding: 14px 16px; margin-bottom: 24px; width: 100%; max-width: 400px; } .grail-rules h3 { font-family: 'Cinzel', serif; font-size: 12px; color: #d4af37; letter-spacing: 2px; text-transform: uppercase; margin-bottom: 8px; } .grail-rules ul { list-style: none; padding: 0; } .grail-rules li { font-size: 11.5px; color: #b0a68e; padding: 3px 0; padding-left: 16px; position: relative; } .grail-rules li::before { content: '◆'; position: absolute; left: 0; color: #d4af37; opacity: 0.4; font-size: 8px; top: 5px; } /* ---------- BUTTONS ---------- */ .grail-btn { font-family: 'Cinzel', serif; font-weight: 700; font-size: 14px; letter-spacing: 3px; text-transform: uppercase; color: #1a1510; background: linear-gradient(180deg, #f5e6a3, #d4af37, #a8872a); border: none; padding: 14px 40px; cursor: pointer; transition: all 0.2s ease; width: 100%; max-width: 300px; } .grail-btn:hover { filter: brightness(1.15); transform: translateY(-1px); } .grail-btn:active { transform: translateY(1px); filter: brightness(0.95); } .grail-btn-secondary { background: transparent; color: #d4af37; border: 1px solid rgba(212, 175, 55, 0.3); font-size: 12px; padding: 10px 24px; margin-top: 10px; } .grail-btn-secondary:hover { background: rgba(212, 175, 55, 0.1); border-color: rgba(212, 175, 55, 0.5); } /* ---------- QUESTION SCREEN ---------- */ .grail-progress { display: flex; gap: 8px; margin-bottom: 20px; justify-content: center; } .grail-progress-dot { width: 12px; height: 12px; border-radius: 50%; border: 1px solid rgba(212, 175, 55, 0.3); transition: all 0.3s ease; } .grail-progress-dot.pass { background: #d4af37; border-color: #d4af37; } .grail-progress-dot.fail { background: #8b2020; border-color: #8b2020; } .grail-progress-dot.current { border-color: #d4af37; animation: pulse 1.5s infinite; } @keyframes pulse { 0%, 100% { box-shadow: 0 0 0 0 rgba(212, 175, 55, 0.4); } 50% { box-shadow: 0 0 0 6px rgba(212, 175, 55, 0); } } .grail-difficulty { font-family: 'JetBrains Mono', monospace; font-size: 10px; letter-spacing: 2px; text-transform: uppercase; color: #8a7d6b; margin-bottom: 8px; } .grail-question-number { font-family: 'Cinzel', serif; font-size: 11px; color: #d4af37; letter-spacing: 2px; text-transform: uppercase; margin-bottom: 16px; } .grail-question-text { font-size: 16px; line-height: 1.5; color: #e0d6c2; text-align: center; margin-bottom: 24px; min-height: 60px; display: flex; align-items: center; justify-content: center; } .grail-answers { display: flex; flex-direction: column; gap: 10px; width: 100%; max-width: 400px; } .grail-answer-btn { font-family: 'Inter', sans-serif; font-size: 13px; font-weight: 400; color: #c8bda6; background: rgba(212, 175, 55, 0.06); border: 1px solid rgba(212, 175, 55, 0.15); padding: 12px 16px; cursor: pointer; transition: all 0.2s ease; text-align: left; border-radius: 3px; } .grail-answer-btn:hover { background: rgba(212, 175, 55, 0.12); border-color: rgba(212, 175, 55, 0.35); color: #e0d6c2; } .grail-answer-btn:active { transform: scale(0.98); } .grail-answer-btn.correct { background: rgba(46, 125, 50, 0.3); border-color: #4caf50; color: #a5d6a7; } .grail-answer-btn.wrong { background: rgba(139, 32, 32, 0.3); border-color: #8b2020; color: #ef9a9a; } .grail-answer-btn:disabled { cursor: default; opacity: 0.6; } /* ---------- RESULT SCREEN ---------- */ .grail-result-icon { font-size: 48px; margin-bottom: 8px; } .grail-result-title { font-family: 'Cinzel', serif; font-weight: 900; font-size: 24px; letter-spacing: 3px; text-transform: uppercase; margin-bottom: 8px; } .grail-result-title.pass { background: linear-gradient(180deg, #f5e6a3, #d4af37); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; } .grail-result-title.fail { color: #c0392b; -webkit-text-fill-color: #c0392b; } .grail-result-description { font-size: 13px; color: #b0a68e; text-align: center; margin-bottom: 16px; line-height: 1.5; } .grail-drink-command { background: rgba(139, 32, 32, 0.2); border: 1px solid rgba(192, 57, 43, 0.4); border-radius: 4px; padding: 16px; text-align: center; margin-bottom: 20px; width: 100%; max-width: 350px; } .grail-drink-command .drink-label { font-family: 'JetBrains Mono', monospace; font-size: 10px; letter-spacing: 2px; text-transform: uppercase; color: #8a7d6b; margin-bottom: 6px; } .grail-drink-command .drink-text { font-family: 'Cinzel', serif; font-size: 20px; font-weight: 700; color: #ef5350; letter-spacing: 2px; } .grail-drink-command .drink-sub { font-size: 12px; color: #b0a68e; margin-top: 4px; } .grail-safe-text { font-family: 'Cinzel', serif; font-size: 18px; color: #d4af37; text-align: center; margin-bottom: 20px; letter-spacing: 2px; } /* ---------- DRINK COUNTER ---------- */ .grail-drink-counter { position: fixed; top: 12px; right: 12px; background: rgba(26, 21, 16, 0.95); border: 1px solid rgba(212, 175, 55, 0.2); border-radius: 4px; padding: 8px 12px; z-index: 100; display: none; } .grail-drink-counter.visible { display: block; } .grail-drink-counter .counter-label { font-family: 'JetBrains Mono', monospace; font-size: 9px; letter-spacing: 1px; text-transform: uppercase; color: #8a7d6b; } .grail-drink-counter .counter-value { font-family: 'Cinzel', serif; font-size: 18px; color: #d4af37; text-align: center; } .grail-drink-counter .counter-sub { font-size: 9px; color: #6b6255; text-align: center; } /* ---------- END SCREEN ---------- */ .grail-rank-badge { font-family: 'Cinzel', serif; font-size: 28px; font-weight: 900; letter-spacing: 4px; text-transform: uppercase; background: linear-gradient(180deg, #f5e6a3 0%, #d4af37 40%, #a8872a 70%, #d4af37 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; margin: 12px 0; } .grail-stats { background: rgba(212, 175, 55, 0.06); border: 1px solid rgba(212, 175, 55, 0.15); border-radius: 4px; padding: 14px 16px; margin: 16px 0; width: 100%; max-width: 350px; } .grail-stats-row { display: flex; justify-content: space-between; padding: 4px 0; border-bottom: 1px solid rgba(212, 175, 55, 0.08); } .grail-stats-row:last-child { border-bottom: none; } .grail-stats-label { font-size: 11px; color: #8a7d6b; text-transform: uppercase; letter-spacing: 1px; } .grail-stats-value { font-family: 'JetBrains Mono', monospace; font-size: 12px; color: #d4af37; } .grail-quote { font-style: italic; font-size: 12px; color: #6b6255; text-align: center; margin: 16px 0; line-height: 1.5; } /* ---------- LOADING ---------- */ .grail-loading { display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 200px; } .grail-loading .spinner { width: 32px; height: 32px; border: 3px solid rgba(212, 175, 55, 0.2); border-top-color: #d4af37; border-radius: 50%; animation: spin 0.8s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } .grail-loading p { margin-top: 12px; font-size: 12px; color: #8a7d6b; letter-spacing: 2px; text-transform: uppercase; } Drinks 0 0 sips · 0 finishes ◆ ◇ ◆ The Bridge of Death Holy Grail Trials · Trial I Three questions stand between you and the Grail. Answer wisely, or drink from the cup of consequence. Rules Answer 3 questions of increasing difficulty Pass 2 or more: The Grail spares you Fail 2 or more: Drink from the Grail Critical fail (0 correct): Finish your glass Cross the Bridge Easy Question 1 of 3 Loading... Answer A Answer B Answer C Answer D ⚔️ Correct The Grail smiles upon you. Drink from the Grail SIP Take a sip of the Holy Grail The Grail spares you Next Question ◆ ◇ ◆ Trial Complete The Bridge of Death Grail Knight "You have crossed the bridge wisely." Questions Passed 0 Questions Failed 0 Total Drinks 0 Sips 0 Finishes 0 Play Again Return to Bridge Consulting the Grail... var HolyGrail = { gameId: null, currentQuestion: 0, totalQuestions: 3, questions: [], correctIndex: null, results: [], totalDrinks: 0, totalSips: 0, totalFinishes: 0, trialsPassed: 0, trialsFailed: 0, difficulties: ['easy', 'medium', 'hard'], ajaxUrl: '/ajax-game.php', // ---------- SCREEN MANAGEMENT ---------- showScreen: function(screenId) { var screens = document.querySelectorAll('#holy-grail-game .grail-screen'); for (var i = 0; i < screens.length; i++) { screens[i].classList.remove('active'); } document.getElementById(screenId).classList.add('active'); }, showLoading: function() { this.showScreen('screen-loading'); }, showIntro: function() { document.getElementById('drink-counter').classList.remove('visible'); this.showScreen('screen-intro'); }, // ---------- GAME FLOW ---------- startGame: function() { var self = this; self.currentQuestion = 0; self.results = []; self.totalDrinks = 0; self.totalSips = 0; self.totalFinishes = 0; self.trialsPassed = 0; self.trialsFailed = 0; self.questions = []; self.showLoading(); // Create game in database self.ajax('new_game', {}, function(response) { if (response.success) { self.gameId = response.data.game_id; document.getElementById('drink-counter').classList.add('visible'); self.updateDrinkCounter(); self.loadQuestion(); } else { alert('Error starting game: ' + response.message); self.showIntro(); } }); }, loadQuestion: function() { var self = this; var difficulty = self.difficulties[self.currentQuestion]; self.showLoading(); self.ajax('get_question', { difficulty: difficulty }, function(response) { if (response.success) { self.questions[self.currentQuestion] = response.data; self.correctIndex = response.data.correct_index; self.showQuestion(); } else { alert('Error loading question: ' + response.message); self.showIntro(); } }); }, showQuestion: function() { var q = this.questions[this.currentQuestion]; // Update progress dots for (var i = 0; i < 3; i++) { var dot = document.getElementById('dot-' + (i + 1)); dot.className = 'grail-progress-dot'; if (i < this.currentQuestion) { dot.classList.add(this.results[i] ? 'pass' : 'fail'); } else if (i === this.currentQuestion) { dot.classList.add('current'); } } // Update question text document.getElementById('difficulty-label').textContent = this.difficulties[this.currentQuestion].toUpperCase(); document.getElementById('question-number').textContent = 'Question ' + (this.currentQuestion + 1) + ' of ' + this.totalQuestions; document.getElementById('question-text').textContent = q.question; // Update answer buttons var container = document.getElementById('answers-container'); var buttons = container.querySelectorAll('.grail-answer-btn'); for (var i = 0; i < buttons.length; i++) { buttons[i].textContent = q.answers[i]; buttons[i].className = 'grail-answer-btn'; buttons[i].disabled = false; buttons[i].setAttribute('data-index', i); } this.showScreen('screen-question'); }, submitAnswer: function(answerIndex) { var self = this; var isCorrect = (answerIndex === self.correctIndex); // Disable all buttons and highlight correct/wrong var buttons = document.querySelectorAll('#answers-container .grail-answer-btn'); for (var i = 0; i < buttons.length; i++) { buttons[i].disabled = true; if (i === self.correctIndex) { buttons[i].classList.add('correct'); } if (i === answerIndex && !isCorrect) { buttons[i].classList.add('wrong'); } } // Determine drink tier var drinkTier = 'none'; var drinksOwed = 0; if (!isCorrect) { // Will determine final drink tier at end based on total score drinkTier = 'sip'; drinksOwed = 1; } // Save result self.results[self.currentQuestion] = isCorrect; if (isCorrect) { self.trialsPassed++; } else { self.trialsFailed++; self.totalDrinks++; self.totalSips++; } // Save to database var responseData = JSON.stringify({ question_id: self.questions[self.currentQuestion].id, selected: answerIndex, correct: self.correctIndex }); self.ajax('save_trial', { game_id: self.gameId, trial_number: self.currentQuestion + 1, trial_type: 'trivia', passed: isCorrect ? 1 : 0, drink_tier: drinkTier, response_data: responseData }, function(response) { // Show result after brief delay setTimeout(function() { self.showResult(isCorrect); }, 800); }); }, showResult: function(isCorrect) { var self = this; if (isCorrect) { document.getElementById('result-icon').textContent = '⚔️'; document.getElementById('result-title').textContent = 'Correct'; document.getElementById('result-title').className = 'grail-result-title pass'; document.getElementById('result-description').textContent = 'The Grail smiles upon you.'; document.getElementById('result-drink').style.display = 'none'; document.getElementById('result-safe').style.display = 'block'; } else { document.getElementById('result-icon').textContent = '💀'; document.getElementById('result-title').textContent = 'Wrong'; document.getElementById('result-title').className = 'grail-result-title fail'; document.getElementById('result-description').textContent = 'The bridge demands its toll.'; document.getElementById('result-drink').style.display = 'block'; document.getElementById('result-safe').style.display = 'none'; document.getElementById('drink-tier').textContent = 'SIP'; document.getElementById('drink-sub').textContent = 'Take a sip of the Holy Grail'; } // Update next button text var nextBtn = document.getElementById('result-next-btn'); if (self.currentQuestion < self.totalQuestions - 1) { nextBtn.textContent = 'NEXT QUESTION'; } else { nextBtn.textContent = 'SEE YOUR FATE'; } self.showScreen('screen-result'); }, nextQuestion: function() { this.currentQuestion++; if (this.currentQuestion >= this.totalQuestions) { this.endGame(); } else { this.loadQuestion(); } }, endGame: function() { var self = this; // Determine final drink penalty based on total score var passCount = self.results.filter(function(r) { return r; }).length; // Critical fail: 0 correct = finish your glass if (passCount === 0) { self.totalFinishes++; self.totalDrinks += 2; // finish = 3 sips worth, already counted 1 per fail } // Determine rank var rank, quote; if (passCount === 3) { rank = 'Grail Knight'; quote = '"You have crossed the bridge wisely."'; } else if (passCount === 2) { rank = 'Seeker'; quote = '"The Grail tests you, but you prevail."'; } else if (passCount === 1) { rank = 'Fallen Crusader'; quote = '"You stumbled, but the bridge remains."'; } else { rank = 'Grail Wretch'; quote = '"The bridge has claimed you entirely."'; } // End game in database self.ajax('end_game', { game_id: self.gameId }, function(response) { // Update stats display document.getElementById('rank-title').textContent = rank; document.getElementById('rank-quote').textContent = quote; document.getElementById('stat-passed').textContent = self.trialsPassed; document.getElementById('stat-failed').textContent = self.trialsFailed; document.getElementById('stat-drinks').textContent = self.totalDrinks; document.getElementById('stat-sips').textContent = self.totalSips; document.getElementById('stat-finishes').textContent = self.totalFinishes; self.showScreen('screen-end'); }); }, updateDrinkCounter: function() { document.getElementById('drink-count').textContent = this.totalDrinks; document.getElementById('drink-detail').textContent = this.totalSips + ' sips · ' + this.totalFinishes + ' finishes'; }, // ---------- AJAX HELPER ---------- ajax: function(action, data, callback) { var params = 'action=' + encodeURIComponent(action); for (var key in data) { if (data.hasOwnProperty(key)) { params += '&' + encodeURIComponent(key) + '=' + encodeURIComponent(data[key]); } } var xhr = new XMLHttpRequest(); xhr.open('POST', this.ajaxUrl, true); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.onload = function() { if (xhr.status === 200) { try { var response = JSON.parse(xhr.responseText); callback(response); } catch (e) { callback({ success: false, message: 'Parse error' }); } } else { callback({ success: false, message: 'Server error: ' + xhr.status }); } }; xhr.onerror = function() { callback({ success: false, message: 'Network error' }); }; xhr.send(params); } }; {}