Spaces:
Sleeping
Sleeping
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>🌧️ Rainwater Quest Adventure</title> | |
| <style> | |
| /* Import Google Fonts */ | |
| @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&family=Roboto:wght@300;400;500;700&display=swap'); | |
| @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;700&display=swap'); | |
| /* Main styling */ | |
| body { | |
| background: linear-gradient(135deg, #e0f2f7 0%, #b3e0f2 100%); /* Light blue gradient */ | |
| font-family: 'Roboto', sans-serif; | |
| margin: 0; | |
| padding: 0; | |
| color: #333; /* Default text color */ | |
| } | |
| .container { | |
| max-width: 1200px; | |
| margin: 20px auto; | |
| padding: 20px; | |
| } | |
| /* Header styling */ | |
| .game-header { | |
| background: linear-gradient(90deg, #FF6B6B, #4ECDC4, #45B7D1); | |
| background-size: 300% 300%; | |
| animation: gradientShift 3s ease infinite; | |
| color: white; | |
| text-align: center; | |
| padding: 20px; | |
| border-radius: 15px; | |
| margin-bottom: 20px; | |
| box-shadow: 0 8px 32px rgba(0,0,0,0.3); | |
| font-family: 'Orbitron', monospace; | |
| font-weight: 900; | |
| text-shadow: 2px 2px 4px rgba(0,0,0,0.5); | |
| } | |
| @keyframes gradientShift { | |
| 0% { background-position: 0% 50%; } | |
| 50% { background-position: 100% 50%; } | |
| 100% { background-position: 0% 50%; } | |
| } | |
| /* Game card styling */ | |
| .game-card { | |
| background: rgba(255, 255, 255, 0.95); | |
| border-radius: 20px; | |
| padding: 25px; | |
| margin: 15px 0; | |
| box-shadow: 0 15px 35px rgba(0,0,0,0.1); | |
| backdrop-filter: blur(10px); | |
| border: 2px solid rgba(255,255,255,0.18); | |
| transition: all 0.3s ease; | |
| } | |
| .game-card:hover { | |
| transform: translateY(-5px); | |
| box-shadow: 0 20px 40px rgba(0,0,0,0.15); | |
| } | |
| /* Progress bar styling */ | |
| .progress-container { | |
| background: rgba(255,255,255,0.2); | |
| border-radius: 25px; | |
| padding: 5px; | |
| margin: 20px 0; | |
| } | |
| .progress-bar { | |
| background: linear-gradient(90deg, #00C9FF, #92FE9D); | |
| height: 30px; | |
| border-radius: 20px; | |
| transition: width 0.5s ease; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| color: white; | |
| font-weight: bold; | |
| text-shadow: 1px 1px 2px rgba(0,0,0,0.5); | |
| min-width: 0; /* Allow it to be 0% width */ | |
| } | |
| /* XP and Level styling */ | |
| .stats-container { | |
| display: flex; | |
| justify-content: space-around; | |
| margin: 20px 0; | |
| flex-wrap: wrap; /* Allow wrapping on smaller screens */ | |
| gap: 10px; /* Space between items */ | |
| } | |
| .stat-item { | |
| background: linear-gradient(135deg, #667eea, #764ba2); | |
| color: white; | |
| padding: 15px 20px; | |
| border-radius: 15px; | |
| text-align: center; | |
| min-width: 120px; | |
| box-shadow: 0 5px 15px rgba(0,0,0,0.2); | |
| font-family: 'Orbitron', monospace; | |
| flex-grow: 1; /* Allow items to grow */ | |
| } | |
| .stat-value { | |
| font-size: 24px; | |
| font-weight: 900; | |
| margin-bottom: 5px; | |
| } | |
| .stat-label { | |
| font-size: 12px; | |
| opacity: 0.8; | |
| } | |
| /* General button styling */ | |
| .button-group { | |
| display: flex; | |
| gap: 10px; /* Space between buttons */ | |
| flex-wrap: wrap; | |
| justify-content: center; | |
| margin-top: 20px; | |
| } | |
| .button-group button, .button-full-width { | |
| background: linear-gradient(135deg, #667eea, #764ba2); | |
| color: white; | |
| border: none; | |
| border-radius: 15px; | |
| padding: 15px 25px; | |
| cursor: pointer; | |
| transition: all 0.3s ease; | |
| font-size: 16px; | |
| font-weight: 500; | |
| text-align: center; | |
| box-shadow: 0 5px 15px rgba(0,0,0,0.2); | |
| flex: 1; /* Make buttons grow to fill space */ | |
| min-width: 150px; /* Minimum width for buttons */ | |
| text-decoration: none; /* For anchor tags acting as buttons */ | |
| display: inline-block; | |
| } | |
| .button-full-width { | |
| width: 100%; | |
| } | |
| .button-group button:hover, .button-full-width:hover { | |
| transform: translateY(-3px); | |
| box-shadow: 0 8px 25px rgba(0,0,0,0.3); | |
| background: linear-gradient(135deg, #7b8cec, #8a5bb8); | |
| } | |
| /* Achievement badge */ | |
| .achievement { | |
| background: linear-gradient(45deg, #FFD700, #FFA500); | |
| color: #333; | |
| padding: 10px 20px; | |
| border-radius: 25px; | |
| display: inline-block; | |
| margin: 10px 5px; | |
| font-weight: bold; | |
| box-shadow: 0 5px 15px rgba(255, 215, 0, 0.3); | |
| animation: pulse 2s infinite; | |
| } | |
| @keyframes pulse { | |
| 0% { transform: scale(1); } | |
| 50% { transform: scale(1.05); } | |
| 100% { transform: scale(1); } | |
| } | |
| /* Welcome screen styling */ | |
| .welcome-container { | |
| text-align: center; | |
| padding: 50px; | |
| background: rgba(255,255,255,0.1); | |
| border-radius: 30px; | |
| backdrop-filter: blur(10px); | |
| margin: 20px auto; /* Centered */ | |
| max-width: 900px; | |
| box-shadow: 0 20px 40px rgba(0,0,0,0.1); | |
| } | |
| .welcome-title { | |
| font-size: 3.5em; | |
| font-family: 'Orbitron', monospace; | |
| font-weight: 900; | |
| background: linear-gradient(45deg, #FF6B6B, #4ECDC4, #45B7D1); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| margin-bottom: 20px; | |
| text-shadow: 2px 2px 4px rgba(0,0,0,0.3); | |
| } | |
| .welcome-text { | |
| font-size: 1.3em; | |
| color: #34495e; /* Darker text for readability */ | |
| margin: 30px 0; | |
| line-height: 1.6; | |
| } | |
| .welcome-text strong { | |
| color: #2c3e50; | |
| } | |
| .welcome-image { | |
| max-width: 100%; | |
| border-radius: 15px; | |
| margin-top: 30px; | |
| box-shadow: 0 10px 20px rgba(0,0,0,0.2); | |
| } | |
| /* Certificate styling */ | |
| .certificate { | |
| background: linear-gradient(135deg, #667eea, #764ba2); | |
| color: white; | |
| padding: 40px; | |
| border-radius: 20px; | |
| text-align: center; | |
| margin: 20px auto; | |
| max-width: 600px; | |
| box-shadow: 0 20px 40px rgba(0,0,0,0.3); | |
| border: 3px solid #FFD700; | |
| } | |
| /* Video container styling */ | |
| .video-container { | |
| border-radius: 20px; | |
| overflow: hidden; | |
| box-shadow: 0 15px 35px rgba(0,0,0,0.2); | |
| margin: 20px 0; | |
| width: 100%; /* Ensure video container takes full width */ | |
| } | |
| .video-container video { | |
| width: 100%; | |
| height: auto; | |
| display: block; | |
| } | |
| /* Question container styling */ | |
| .question-container { | |
| background: linear-gradient(135deg, #FF6B6B, #4ECDC4); | |
| color: white; | |
| padding: 25px; | |
| border-radius: 20px; | |
| margin: 20px 0; | |
| box-shadow: 0 10px 30px rgba(0,0,0,0.2); | |
| text-align: center; | |
| } | |
| /* Video watched indicator */ | |
| .video-watched { | |
| background: rgba(76, 175, 80, 0.1); | |
| border: 2px solid #4CAF50; | |
| border-radius: 10px; | |
| padding: 15px; | |
| margin: 10px 0; | |
| color: #2E7D32; | |
| font-weight: bold; | |
| text-align: center; | |
| } | |
| /* Feedback messages */ | |
| .feedback.success { | |
| background-color: #d4edda; | |
| color: #155724; | |
| border: 1px solid #badbcc; | |
| padding: 15px; | |
| margin: 15px 0; | |
| border-radius: 8px; | |
| text-align: center; | |
| } | |
| .feedback.error { | |
| background-color: #f8d7da; | |
| color: #721c24; | |
| border: 1px solid #f5c6cb; | |
| padding: 15px; | |
| margin: 15px 0; | |
| border-radius: 8px; | |
| text-align: center; | |
| } | |
| .feedback.info { | |
| background-color: #d1ecf1; | |
| color: #0c5460; | |
| border: 1px solid #bee5eb; | |
| padding: 15px; | |
| margin: 15px 0; | |
| border-radius: 8px; | |
| text-align: center; | |
| } | |
| /* Utility classes for layout */ | |
| .columns-3 { | |
| display: flex; | |
| justify-content: center; | |
| gap: 20px; | |
| margin-top: 20px; | |
| flex-wrap: wrap; /* Allow wrapping */ | |
| } | |
| .columns-3 > div { | |
| flex: 1; | |
| min-width: 250px; /* Ensure columns don't get too small */ | |
| } | |
| .columns-5 { | |
| display: flex; | |
| justify-content: space-around; | |
| gap: 10px; | |
| margin-top: 20px; | |
| flex-wrap: wrap; | |
| } | |
| .columns-5 > div { | |
| flex: 1; | |
| min-width: 150px; | |
| } | |
| h1, h2, h3, h4, h5, h6 { | |
| font-family: 'Orbitron', monospace; | |
| color: #34495e; | |
| } | |
| p { | |
| line-height: 1.6; | |
| } | |
| </style> | |
| </head> | |
| <body style="margin:0; padding:0; height:100vh; overflow:hidden; background:linear-gradient(135deg,#f8fafc 0%,#e0f7fa 100%);"> | |
| <div id="game-root" style="display:flex; flex-direction:column; height:100vh; width:100vw; justify-content:stretch; align-items:stretch; background:none;"> | |
| <!-- Top Bar: Stats & Progress --> | |
| <div style="flex:0 0 auto; background:rgba(255,255,255,0.95); color:#2c3e50; display:flex; align-items:center; justify-content:space-between; padding:0.5em 2vw; min-height:54px; box-shadow:0 2px 8px #b2ebf2; z-index:2;"> | |
| <div style="display:flex; gap:2vw; align-items:center;"> | |
| <span style="font-family:'Orbitron',sans-serif; font-weight:700;">Lv.{{ player_level }}</span> | |
| <span>XP: {{ xp_points }}</span> | |
| <span>Health: <span style="color:{{ health > 50 and '#43a047' or (health > 20 and '#fbc02d' or '#e53935') }}">{{ health }}%</span></span> | |
| <span>Streak: {{ streak }}</span> | |
| <span>Accuracy: {{ "%.0f" | format((quiz_correct_count / (quiz_attempts if quiz_attempts > 0 else 1)) * 100) }}%</span> | |
| </div> | |
| {% set progress_percentage = ((current_video_index + 1) / total_videos) * 100 %} | |
| <div style="flex:1; margin-left:2vw; margin-right:2vw;"> | |
| <div style="background:rgba(0,0,0,0.07); border-radius:8px; height:14px; width:100%; overflow:hidden;"> | |
| <div style="background:linear-gradient(90deg,#4fc3f7,#b2ebf2); height:100%; width:{{ progress_percentage }}%; border-radius:8px; transition:width 0.5s;"></div> | |
| </div> | |
| <div style="font-size:0.9em; color:#00bcd4; text-align:right;">Stage {{ current_video_index + 1 }}/{{ total_videos }}</div> | |
| </div> | |
| </div> | |
| <!-- Main Game Area: Centered, No Scroll, Light Colors --> | |
| <div style="flex:1 1 auto; display:flex; align-items:center; justify-content:center; min-height:0; min-width:0;"> | |
| <div style="background:rgba(255,255,255,0.98); border-radius:20px; box-shadow:0 8px 32px #b2ebf2, 0 2px 8px rgba(0,0,0,0.07); max-width:900px; width:99vw; max-height:68vh; min-height:320px; display:flex; flex-direction:column; align-items:center; justify-content:flex-start; padding:1.2vw 1.2vw 0.7vw 1.2vw; overflow:hidden; position:relative;"> | |
| <div style="width:100%; text-align:center; margin-bottom:0.4em;"> | |
| <h2 style="font-family:'Orbitron',sans-serif; color:#00bcd4; margin:0; font-size:1.6em;">🎯 Stage {{ current_video_index + 1 }}: {{ video_description }}</h2> | |
| </div> | |
| {% if message %} | |
| <div class="feedback info" style="margin-bottom:0.4em;">{{ message }}</div> | |
| {% endif %} | |
| <div style="flex:1 1 auto; width:100%; display:flex; flex-direction:column; align-items:center; justify-content:center; overflow:auto;"> | |
| {% if not video_watched %} | |
| <div style="width:100%; max-width:500px; margin:0 auto;"> | |
| {% if is_local_video and not local_file_exists %} | |
| <div class="feedback error">⚠️ Video file not found: {{ video_src }}. Please check the path or use an online URL.</div> | |
| <form action="{{ url_for('main_app') }}" method="post"> | |
| <button type="submit" name="mark_watched" class="button-full-width">Skip missing video</button> | |
| </form> | |
| {% else %} | |
| <form id="autoMarkWatchedForm" action="{{ url_for('main_app') }}" method="post" style="margin:0;"> | |
| <video id="gameVideo" controls src="{{ video_src }}" {% if is_local_video %} type="video/mp4" {% endif %} style="width:100%; max-height:180px; border-radius:12px; background:#e0f7fa;"></video> | |
| <input type="hidden" name="mark_watched" value="1"> | |
| </form> | |
| <script> | |
| document.addEventListener('DOMContentLoaded', function() { | |
| var video = document.getElementById('gameVideo'); | |
| if (video) { | |
| video.addEventListener('ended', function() { | |
| document.getElementById('autoMarkWatchedForm').submit(); | |
| }); | |
| } | |
| }); | |
| </script> | |
| {% endif %} | |
| </div> | |
| {% else %} | |
| <div class="video-watched" style="margin-bottom:0.4em; background:#e0f7fa; color:#388e3c; border:1px solid #b2ebf2;">✅ Video completed! Time for a challenge!</div> | |
| {% if current_scenario.choices and not question_answered %} | |
| <div class="question-container" style="margin-bottom:0.4em; background:linear-gradient(135deg,#b2ebf2,#e1f5fe); color:#0277bd;"> | |
| <h3 style="margin:0;">{{ current_scenario.question }}</h3> | |
| </div> | |
| <h3 style="margin:0.4em 0 0.15em 0; color:#00bcd4;">🎮 Choose Your Answer:</h3> | |
| <p style="margin:0 0 0.4em 0; font-size:1em; color:#00bcd4;">*Select the most effective water conservation strategy:*</p> | |
| <form action="{{ url_for('main_app') }}" method="post" class="button-group" style="width:100%; display:flex; flex-direction:column; gap:0.4em; align-items:center;"> | |
| {% for choice in current_scenario.choices %} | |
| <button type="submit" name="select_choice" value="{{ loop.index0 }}" title="{{ choice.description }}" style="width:100%; max-width:370px; font-size:1em; padding:0.7em 0; border-radius:12px; background:linear-gradient(90deg,#b2ebf2,#4fc3f7); color:#0277bd; font-family:'Orbitron',sans-serif; font-weight:700; box-shadow:0 2px 8px #b2ebf2;">{{ choice.action }}</button> | |
| {% endfor %} | |
| </form> | |
| {% endif %} | |
| {% if feedback and question_answered %} | |
| <div class="feedback {% if '✅' in feedback %}success{% else %}error{% endif %}" style="margin:0.4em 0; background:#e0f7fa; color:#388e3c; border:1px solid #b2ebf2;">{{ feedback }}</div> | |
| <form action="{{ url_for('main_app') }}" method="post" style="margin-top: 0.4em;"> | |
| <button type="submit" name="next_level" class="button-full-width" style="width:100%; max-width:370px; font-size:1em; border-radius:12px; background:linear-gradient(90deg,#b2ebf2,#4fc3f7); color:#0277bd; font-family:'Orbitron',sans-serif; font-weight:700; box-shadow:0 2px 8px #b2ebf2;">⏭️ Next Level</button> | |
| </form> | |
| {% elif video_watched and not current_scenario.choices and not question_answered %} | |
| <form action="{{ url_for('main_app') }}" method="post" style="margin-top: 0.4em;"> | |
| <button type="submit" name="continue_quest" class="button-full-width" style="width:100%; max-width:370px; font-size:1em; border-radius:12px; background:linear-gradient(90deg,#b2ebf2,#4fc3f7); color:#0277bd; font-family:'Orbitron',sans-serif; font-weight:700; box-shadow:0 2px 8px #b2ebf2;">⏭️ Continue Quest</button> | |
| </form> | |
| {% endif %} | |
| {% endif %} | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Bottom Bar: Controls & Achievements --> | |
| <div style="flex:0 0 auto; background:rgba(255,255,255,0.95); color:#2c3e50; display:flex; align-items:center; justify-content:space-between; padding:0.5em 2vw; min-height:54px; box-shadow:0 -2px 8px #b2ebf2; z-index:2;"> | |
| <div style="display:flex; gap:1vw; align-items:center;"> | |
| <form action="{{ url_for('main_app') }}" method="post" style="display:inline; margin:0;"> | |
| <button type="submit" name="replay_video" style="font-size:1em; border-radius:10px; background:linear-gradient(90deg,#b2ebf2,#4fc3f7); color:#0277bd; font-family:'Orbitron',sans-serif; font-weight:700; box-shadow:0 2px 8px #b2ebf2; padding:0.4em 1em;">🔄 Replay Video</button> | |
| </form> | |
| <form action="{{ url_for('main_app') }}" method="post" style="display:inline; margin:0;"> | |
| <button type="submit" name="main_menu" style="font-size:1em; border-radius:10px; background:linear-gradient(90deg,#b2ebf2,#4fc3f7); color:#0277bd; font-family:'Orbitron',sans-serif; font-weight:700; box-shadow:0 2px 8px #b2ebf2; padding:0.4em 1em;">🏠 Main Menu</button> | |
| </form> | |
| </div> | |
| {% if achievements %} | |
| <div style="display:flex; gap:0.5vw; align-items:center; flex-wrap:wrap;"> | |
| {% for achievement in achievements %} | |
| <span class="achievement" style="background:linear-gradient(45deg,#fffde7,#ffe082); color:#795548; padding:0.3em 0.8em; border-radius:12px; font-weight:700; font-size:0.95em; box-shadow:0 2px 8px #ffe08280; margin:0 0.15em;">{{ achievement.name }}</span> | |
| {% endfor %} | |
| </div> | |
| {% endif %} | |
| </div> | |
| </div> | |
| </body> | |
| </html> |