commit 4754d2487090265d5ffd2c7e38308efcfc02ca1f Author: Lumerel Deploy Date: Wed Feb 18 18:12:33 2026 +0000 Deploy from Lumerel diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..17896fe --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +.git +Dockerfile +.dockerignore diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..3bce86c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,23 @@ +FROM webdevops/php-nginx:8.3-alpine +ENV WEB_DOCUMENT_ROOT=/app +ARG CACHE_BUST=1771438353 +COPY . /app +RUN echo "index index.php index.html index.htm;" > /opt/docker/etc/nginx/vhost.common.d/01-index.conf \ + && echo "add_header Cache-Control 'no-cache, no-store, must-revalidate';" > /opt/docker/etc/nginx/vhost.common.d/02-no-cache.conf +RUN set -e; if [ -f /app/composer.json ]; then \ + echo ">>> composer.json found, installing dependencies..."; \ + curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer; \ + cd /app && composer install --no-dev --no-interaction --optimize-autoloader; \ + ls -la /app/vendor/autoload.php; \ + else \ + echo ">>> No composer.json found, skipping composer install"; \ + fi +RUN set -e; if [ -f /app/package.json ]; then \ + echo ">>> package.json found, installing node dependencies..."; \ + apk add --no-cache nodejs npm; \ + cd /app && npm install --production; \ + else \ + echo ">>> No package.json found, skipping npm install"; \ + fi + +RUN chown -R application:application /app \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..5f02014 --- /dev/null +++ b/index.html @@ -0,0 +1,89 @@ + + + + + + Mind Reader + + + +
+ +
+
+

Mind Reader

+

Think of a number between 1 and 63

+

I will read your mind by asking you 6 simple questions.

+ +
+
+ + +
+
+
+

Card 1 of 6

+

Does your number appear on this card?

+
+
+ +
+
+ + +
+
+
+ + +
+
+

Analyzing brainwaves…

+ +
+ + + + + + + + + + + + +
+ + +
+
+
+
+
+
+
+
+ + +

Reading signals…

+ + +
+
+
+
+
+ + +
+
+

Your number is 42

+ +
+
+
+ + + + diff --git a/script.js b/script.js new file mode 100644 index 0000000..2fa4917 --- /dev/null +++ b/script.js @@ -0,0 +1,159 @@ +// Game state +const gameState = { + currentCard: 0, + sum: 0, + cardValues: [1, 2, 4, 8, 16, 32], +}; + +// DOM elements +const welcomeScreen = document.getElementById('welcomeScreen'); +const cardScreen = document.getElementById('cardScreen'); +const analysisScreen = document.getElementById('analysisScreen'); +const resultScreen = document.getElementById('resultScreen'); + +const startBtn = document.getElementById('startBtn'); +const yesBtn = document.getElementById('yesBtn'); +const noBtn = document.getElementById('noBtn'); +const restartBtn = document.getElementById('restartBtn'); + +const cardNumber = document.getElementById('cardNumber'); +const cardGrid = document.getElementById('cardGrid'); +const statusMessage = document.getElementById('statusMessage'); +const progressBar = document.getElementById('progressBar'); +const resultNumber = document.getElementById('resultNumber'); + +// Card values and their corresponding binary values +const cardValues = [1, 2, 4, 8, 16, 32]; + +// Generate numbers for a specific card +function generateCardNumbers(cardValue) { + const numbers = []; + for (let n = 1; n <= 63; n++) { + if ((n & cardValue) !== 0) { + numbers.push(n); + } + } + return numbers; +} + +// Display a card +function displayCard(cardIndex) { + const cardValue = cardValues[cardIndex]; + const numbers = generateCardNumbers(cardValue); + + cardNumber.textContent = `Card ${cardIndex + 1} of 6`; + cardGrid.innerHTML = ''; + + numbers.forEach((num) => { + const numberDiv = document.createElement('div'); + numberDiv.className = 'card-number'; + numberDiv.textContent = num; + cardGrid.appendChild(numberDiv); + }); +} + +// Handle Yes response +function handleYes() { + gameState.sum += gameState.cardValues[gameState.currentCard]; + nextCard(); +} + +// Handle No response +function handleNo() { + nextCard(); +} + +// Move to the next card +function nextCard() { + gameState.currentCard++; + + if (gameState.currentCard < 6) { + displayCard(gameState.currentCard); + } else { + // Move to analysis screen + showAnalysisScreen(); + } +} + +// Show analysis screen with animations +function showAnalysisScreen() { + switchScreen(analysisScreen); + animateAnalysis(); +} + +// Animate the analysis screen +function animateAnalysis() { + const messages = [ + 'Reading signals…', + 'Matching pattern…', + 'Locking onto your thought…', + 'Decoding brainwaves…', + 'Final verification…', + ]; + + let messageIndex = 0; + let progressValue = 0; + + // Cycle through messages + const messageInterval = setInterval(() => { + statusMessage.textContent = messages[messageIndex % messages.length]; + messageIndex++; + }, 400); + + // Simulate progress + const progressInterval = setInterval(() => { + progressValue += Math.random() * 15; + if (progressValue > 100) progressValue = 100; + progressBar.style.width = progressValue + '%'; + + if (progressValue >= 100) { + clearInterval(progressInterval); + } + }, 200); + + // Reveal result after 2 seconds + setTimeout(() => { + clearInterval(messageInterval); + clearInterval(progressInterval); + revealResult(); + }, 2000); +} + +// Reveal the result +function revealResult() { + resultNumber.textContent = `Your number is ${gameState.sum}`; + switchScreen(resultScreen); +} + +// Switch between screens +function switchScreen(targetScreen) { + document.querySelectorAll('.screen').forEach((screen) => { + screen.classList.remove('active'); + }); + targetScreen.classList.add('active'); +} + +// Reset game +function resetGame() { + gameState.currentCard = 0; + gameState.sum = 0; + switchScreen(welcomeScreen); + progressBar.style.width = '0%'; +} + +// Event listeners +startBtn.addEventListener('click', () => { + gameState.currentCard = 0; + gameState.sum = 0; + displayCard(0); + switchScreen(cardScreen); +}); + +yesBtn.addEventListener('click', handleYes); +noBtn.addEventListener('click', handleNo); +restartBtn.addEventListener('click', resetGame); + +// Initialize +window.addEventListener('load', () => { + switchScreen(welcomeScreen); +}); diff --git a/styles.css b/styles.css new file mode 100644 index 0000000..05ab02c --- /dev/null +++ b/styles.css @@ -0,0 +1,445 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + background: linear-gradient(135deg, #0a0e27 0%, #1a1f4b 50%, #0f1a3f 100%); + color: #e0e0e0; + min-height: 100vh; + display: flex; + justify-content: center; + align-items: center; + overflow: hidden; +} + +.container { + width: 100%; + height: 100vh; + position: relative; + display: flex; + justify-content: center; + align-items: center; +} + +/* Screen Management */ +.screen { + position: absolute; + width: 100%; + height: 100%; + display: flex; + justify-content: center; + align-items: center; + opacity: 0; + pointer-events: none; + transition: opacity 0.6s ease-in-out; +} + +.screen.active { + opacity: 1; + pointer-events: auto; +} + +/* Welcome Screen */ +#welcomeScreen { + background: linear-gradient(135deg, #0a0e27 0%, #1a1f4b 50%, #0f1a3f 100%); +} + +.welcome-content { + text-align: center; + animation: fadeInScale 0.8s ease-out; +} + +.title { + font-size: 4rem; + font-weight: 700; + background: linear-gradient(135deg, #00ff88 0%, #00ccff 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + margin-bottom: 1rem; + text-shadow: 0 0 30px rgba(0, 255, 136, 0.3); +} + +.subtitle { + font-size: 1.5rem; + color: #00ff88; + margin-bottom: 0.5rem; + text-shadow: 0 0 20px rgba(0, 255, 136, 0.2); +} + +.instruction { + font-size: 1rem; + color: #b0b0b0; + margin-bottom: 2rem; +} + +/* Buttons */ +.btn { + padding: 0.75rem 2rem; + font-size: 1rem; + border: none; + border-radius: 50px; + cursor: pointer; + font-weight: 600; + transition: all 0.3s ease; + text-transform: uppercase; + letter-spacing: 1px; +} + +.btn-primary { + background: linear-gradient(135deg, #00ff88 0%, #00ccff 100%); + color: #0a0e27; + box-shadow: 0 0 20px rgba(0, 255, 136, 0.4); +} + +.btn-primary:hover { + transform: translateY(-3px); + box-shadow: 0 0 30px rgba(0, 255, 136, 0.6), 0 10px 20px rgba(0, 255, 136, 0.2); +} + +.btn-primary:active { + transform: translateY(-1px); +} + +.btn-yes { + background: linear-gradient(135deg, #00ff88 0%, #00dd77 100%); + color: #0a0e27; + box-shadow: 0 0 15px rgba(0, 255, 136, 0.3); + flex: 1; + margin-right: 0.5rem; +} + +.btn-yes:hover { + transform: translateY(-2px); + box-shadow: 0 0 25px rgba(0, 255, 136, 0.5); +} + +.btn-no { + background: linear-gradient(135deg, #ff3366 0%, #ff1155 100%); + color: #fff; + box-shadow: 0 0 15px rgba(255, 51, 102, 0.3); + flex: 1; + margin-left: 0.5rem; +} + +.btn-no:hover { + transform: translateY(-2px); + box-shadow: 0 0 25px rgba(255, 51, 102, 0.5); +} + +/* Card Screen */ +#cardScreen { + background: linear-gradient(135deg, #0a0e27 0%, #1a1f4b 50%, #0f1a3f 100%); +} + +.card-container { + background: rgba(26, 31, 75, 0.4); + backdrop-filter: blur(20px); + border: 1px solid rgba(0, 255, 136, 0.2); + border-radius: 20px; + padding: 2rem; + max-width: 600px; + width: 90%; + box-shadow: 0 8px 32px rgba(0, 255, 136, 0.1), inset 0 0 20px rgba(0, 255, 136, 0.05); + animation: slideInUp 0.6s ease-out; +} + +.card-header { + text-align: center; + margin-bottom: 2rem; +} + +#cardNumber { + font-size: 1.5rem; + color: #00ff88; + margin-bottom: 0.5rem; +} + +#cardQuestion { + font-size: 1.1rem; + color: #b0b0b0; +} + +.card-grid { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 1rem; + margin-bottom: 2rem; + animation: fadeIn 0.6s ease-out 0.2s backwards; +} + +.card-number { + background: linear-gradient(135deg, rgba(0, 255, 136, 0.1) 0%, rgba(0, 204, 255, 0.1) 100%); + border: 1px solid rgba(0, 255, 136, 0.3); + border-radius: 12px; + padding: 1rem; + text-align: center; + font-size: 1.3rem; + font-weight: 600; + color: #00ff88; + cursor: default; + transition: all 0.3s ease; + box-shadow: 0 0 10px rgba(0, 255, 136, 0.2); +} + +.card-number:hover { + background: linear-gradient(135deg, rgba(0, 255, 136, 0.2) 0%, rgba(0, 204, 255, 0.2) 100%); + box-shadow: 0 0 20px rgba(0, 255, 136, 0.4); + transform: scale(1.05); +} + +.card-actions { + display: flex; + gap: 1rem; + animation: fadeIn 0.6s ease-out 0.4s backwards; +} + +/* Analysis Screen */ +#analysisScreen { + background: linear-gradient(135deg, #0a0e27 0%, #1a1f4b 50%, #0f1a3f 100%); +} + +.analysis-container { + text-align: center; + animation: fadeIn 0.8s ease-out; +} + +.analysis-title { + font-size: 2rem; + color: #00ff88; + margin-bottom: 2rem; + text-shadow: 0 0 20px rgba(0, 255, 136, 0.3); + animation: pulse 2s ease-in-out infinite; +} + +.scanner { + position: relative; + width: 200px; + height: 200px; + margin: 0 auto 2rem; +} + +.scanner-ring { + width: 100%; + height: 100%; + animation: rotatePulse 3s ease-in-out infinite; + filter: drop-shadow(0 0 20px rgba(0, 255, 136, 0.4)); +} + +.scan-line { + position: absolute; + top: 50%; + left: 50%; + width: 160px; + height: 2px; + background: linear-gradient(90deg, transparent, #00ff88, transparent); + transform: translateX(-50%) translateY(-50%); + animation: scan 2s ease-in-out infinite; + box-shadow: 0 0 10px rgba(0, 255, 136, 0.6); +} + +.particles { + position: absolute; + width: 100%; + height: 100%; + top: 0; + left: 0; +} + +.particle { + position: absolute; + width: 4px; + height: 4px; + background: #00ccff; + border-radius: 50%; + animation: drift 4s ease-in-out infinite; + opacity: 0.6; +} + +.particle:nth-child(1) { top: 20%; left: 20%; animation-delay: 0s; } +.particle:nth-child(2) { top: 80%; left: 30%; animation-delay: 0.5s; } +.particle:nth-child(3) { top: 40%; left: 80%; animation-delay: 1s; } +.particle:nth-child(4) { top: 70%; left: 70%; animation-delay: 1.5s; } +.particle:nth-child(5) { top: 30%; left: 60%; animation-delay: 2s; } + +.status-message { + font-size: 1.1rem; + color: #00ccff; + margin: 2rem 0; + height: 1.5rem; + animation: fadeInOut 2s ease-in-out infinite; +} + +.progress-container { + width: 200px; + height: 4px; + background: rgba(0, 255, 136, 0.1); + border-radius: 2px; + margin: 0 auto; + overflow: hidden; + box-shadow: 0 0 10px rgba(0, 255, 136, 0.2); +} + +#progressBar { + height: 100%; + background: linear-gradient(90deg, #00ff88 0%, #00ccff 100%); + width: 0%; + animation: progress 2s ease-in-out forwards; + box-shadow: 0 0 10px rgba(0, 255, 136, 0.6); +} + +/* Result Screen */ +#resultScreen { + background: linear-gradient(135deg, #0a0e27 0%, #1a1f4b 50%, #0f1a3f 100%); +} + +.result-container { + text-align: center; + animation: fadeIn 0.6s ease-out; +} + +.result-number { + font-size: 3.5rem; + font-weight: 700; + background: linear-gradient(135deg, #00ff88 0%, #00ccff 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + margin-bottom: 2rem; + text-shadow: 0 0 40px rgba(0, 255, 136, 0.4); + animation: revealResult 0.8s cubic-bezier(0.34, 1.56, 0.64, 1); +} + +/* Animations */ +@keyframes fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@keyframes fadeInScale { + from { + opacity: 0; + transform: scale(0.95); + } + to { + opacity: 1; + transform: scale(1); + } +} + +@keyframes slideInUp { + from { + opacity: 0; + transform: translateY(30px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes rotatePulse { + 0% { + transform: rotate(0deg) scale(1); + opacity: 1; + } + 50% { + transform: rotate(180deg) scale(1.1); + } + 100% { + transform: rotate(360deg) scale(1); + } +} + +@keyframes scan { + 0% { + top: 0%; + } + 50% { + top: 100%; + } + 100% { + top: 0%; + } +} + +@keyframes drift { + 0%, 100% { + transform: translate(0, 0); + opacity: 0.6; + } + 50% { + transform: translate(20px, -20px); + opacity: 0.3; + } +} + +@keyframes fadeInOut { + 0%, 100% { + opacity: 0; + } + 50% { + opacity: 1; + } +} + +@keyframes progress { + from { + width: 0%; + } + to { + width: 100%; + } +} + +@keyframes pulse { + 0%, 100% { + opacity: 1; + } + 50% { + opacity: 0.7; + } +} + +@keyframes revealResult { + 0% { + opacity: 0; + transform: scale(0.5) rotateY(90deg); + } + 100% { + opacity: 1; + transform: scale(1) rotateY(0deg); + } +} + +/* Responsive */ +@media (max-width: 768px) { + .title { + font-size: 2.5rem; + } + + .subtitle { + font-size: 1.2rem; + } + + .card-grid { + grid-template-columns: repeat(3, 1fr); + gap: 0.8rem; + } + + .card-number { + font-size: 1.1rem; + padding: 0.8rem; + } + + .result-number { + font-size: 2.5rem; + } +}