1<!doctype html> 2<html lang="en"> 3 <head> 4 <meta charset="utf-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1"> 6 <title>Millionaire Play Host</title> 7 <link rel="stylesheet" href="./style.css?v=18"> 8 <link rel="stylesheet" href="../ui.css?v=1"> 9 </head> 10 <body> 11 <main class="host-shell"> 12 <!-- Auth screen (shown before login) --> 13 <div id="auth-screen" class="auth-screen active"> 14 <a class="auth-home-link" href="/">Home</a> 15 <div class="auth-tabs"> 16 <button id="auth-tab-login" class="nav-tab active">Log In</button> 17 <button id="auth-tab-register" class="nav-tab">Register to host</button> 18 </div> 19 20 <form id="login-form" class="auth-form active"> 21 <p class="eyebrow">Millionaire Play</p> 22 <h1>Welcome back</h1> 23 <input id="login-username" type="text" placeholder="Username or email" required autocomplete="username"> 24 <input id="login-password" type="password" placeholder="Password" required autocomplete="current-password"> 25 <button type="submit">Log In</button> 26 <p id="login-message" class="message"></p> 27 </form> 28 29 <form id="register-form" class="auth-form"> 30 <p class="eyebrow">Millionaire Play</p> 31 <h1>Register to host</h1> 32 <input id="reg-username" type="text" placeholder="Username" maxlength="32" required autocomplete="username"> 33 <input id="reg-email" type="email" placeholder="Email" required autocomplete="email"> 34 <input id="reg-phone" type="tel" placeholder="Phone number (optional)" maxlength="32" autocomplete="tel"> 35 <input id="reg-password" type="password" placeholder="Password (min 6 chars)" minlength="6" required autocomplete="new-password"> 36 <div id="host-register-turnstile" class="cf-turnstile turnstile-slot" data-action="turnstile-spin-v2"></div> 37 <button type="submit">Create host account</button> 38 <p id="register-message" class="message"></p> 39 </form> 40 </div> 41 42 <!-- Main app (shown after login) --> 43 <div id="app-shell" class="app-shell"> 44 <div class="user-bar"> 45 <span id="user-greeting"></span> 46 <button id="logout-btn" class="text-btn">Log out</button> 47 </div> 48 49 <nav class="host-nav"> 50 <a class="nav-home" href="/">Home</a> 51 <button id="nav-play" class="nav-tab active">Play</button> 52 <button id="nav-editor" class="nav-tab">My Quizzes</button> 53 <button id="nav-brand" class="nav-tab">Brand Page</button> 54 <button id="nav-schedule" class="nav-tab">Schedule</button> 55 <button id="nav-history" class="nav-tab">History</button> 56 <button id="nav-predictor" class="nav-tab nav-tab-predictor">Predictor</button> 57 <button id="nav-admin" class="nav-tab" style="display:none">Users</button> 58 </nav> 59 60 <div id="play-mode" class="mode active"> 61 <section id="setup-screen" class="screen active"> 62 <div> 63 <p class="eyebrow">Millionaire Play Host</p> 64 <h1>Start a live quiz</h1> 65 </div> 66 <div class="setup-row"> 67 <label for="quiz-select">Quiz</label> 68 <select id="quiz-select"></select> 69 <label class="setup-check"> 70 <input id="require-login" type="checkbox"> 71 <span>Require players to log in</span> 72 </label> 73 <button id="create-game">Create Game</button> 74 </div> 75 <button id="open-schedule" class="button-link muted" type="button">Schedule future play</button> 76 <section class="live-games-panel" aria-label="Running quizzes"> 77 <div class="history-card-head"> 78 <div> 79 <p class="eyebrow">Running now</p> 80 <h2>Active quizzes</h2> 81 </div> 82 <button id="refresh-live-games" class="text-btn" type="button">Refresh</button> 83 </div> 84 <div id="live-games-list" class="live-games-list"></div> 85 </section> 86 <p id="setup-message" class="message"></p> 87 </section> 88 89 <section id="lobby-screen" class="screen"> 90 <div class="pin-panel"> 91 <p>Game PIN</p> 92 <strong id="game-pin">------</strong> 93 </div> 94 <div class="lobby-grid"> 95 <div> 96 <h2>Players</h2> 97 <p id="player-count">0 joined</p> 98 <div id="player-list" class="player-list"></div> 99 </div> 100 <div class="host-game-actions"> 101 <button id="start-game" disabled>Start Game</button> 102 <button id="end-game-lobby" class="text-btn danger" type="button">End Game</button> 103 </div> 104 </div> 105 </section> 106 107 <section id="question-screen" class="screen"> 108 <div class="question-meta">
109 <span id="question-progress">Question</span> 110 <span id="answer-count">0 answered</span> 111 </div> 112 <button id="end-game-question" class="text-btn danger host-end-floating" type="button">End Game</button> 113 <div class="timer-track"> 114 <div id="timer-bar" class="timer-bar"></div> 115 <span id="timer-seconds" class="timer-seconds">20</span> 116 </div> 117 <h1 id="question-text"></h1> 118 <div id="host-question-media" class="host-question-media"></div> 119 <div id="host-advert-media" class="host-advert-media"></div> 120 </section> 121 122 <section id="results-screen" class="screen"> 123 <p class="eyebrow" id="results-eyebrow">Correct Answer</p> 124 <h1 id="correct-answer"></h1> 125 <h2 id="leaderboard-title">Leaderboard</h2> 126 <ol id="leaderboard" class="leaderboard"></ol> 127 <button id="spin-slot" class="spin-slot-btn" type="button" hidden>Spin</button> 128 <button id="next-question">Next Question</button> 129 <button id="end-game-results" class="text-btn danger" type="button">End Game</button> 130 </section> 131 132 <section id="final-screen" class="screen"> 133 <p class="eyebrow">Final Results</p> 134 <h1 id="winner-name">Winner</h1> 135 <ol id="final-leaderboard" class="leaderboard"></ol> 136 <a class="button-link" href="/host/">New Game</a> 137 </section> 138 </div> 139 140 <div id="editor-mode" class="mode"> 141 <section id="quiz-list-screen" class="screen active"> 142 <div> 143 <p class="eyebrow">Millionaire Play Editor</p> 144 <h1>My Quizzes</h1> 145 </div> 146 <button id="new-quiz-btn">+ Create New Quiz</button> 147 <div id="quiz-list" class="quiz-list"></div> 148 <p id="editor-message" class="message"></p> 149 </section> 150 151 <section id="quiz-form-screen" class="screen"> 152 <div class="editor-topbar"> 153 <button id="back-to-list" class="text-btn">← Back</button> 154 <p class="eyebrow" id="form-title-label">New Quiz</p> 155 </div> 156 <form id="quiz-form" class="quiz-form"> 157 <label> 158 Title 159 <input id="quiz-title" type="text" maxlength="200" placeholder="e.g. Geography Bee" required> 160 </label> 161 <label> 162 Description (optional) 163 <input id="quiz-description" type="text" maxlength="500" placeholder="Brief description"> 164 </label> 165 <div id="questions-container" class="questions-container"></div> 166 <button type="button" id="add-question" class="secondary-btn">+ Add Question</button> 167 <button type="button" id="add-advert" class="secondary-btn advert-btn">+ Add an Advert</button> 168 <button type="button" id="add-slot-spin" class="secondary-btn slot-btn">+ Add Slot Spin</button> 169 <div class="form-actions"> 170 <button type="submit" id="save-quiz">Save Quiz</button> 171 <button type="button" id="cancel-form" class="text-btn">Cancel</button> 172 </div> 173 </form> 174 <p id="form-message" class="message"></p> 175 </section> 176 </div> 177 178 <!-- Admin mode --> 179 <div id="brand-mode" class="mode"> 180 <section id="brand-screen" class="screen active"> 181 <div> 182 <p class="eyebrow">Public Page</p> 183 <h1>Brand Page</h1> 184 </div> 185 <form id="brand-form" class="brand-form"> 186 <label> 187 Page URL 188 <div class="slug-row"> 189 <span>/u/</span> 190 <input id="profile-slug" type="text" maxlength="40" placeholder="your-page" required> 191 </div> 192 </label> 193 <label> 194 Display name 195 <input id="profile-display-name" type="text" maxlength="80" placeholder="e.g. Lagos Quiz Night"> 196 </label> 197 <label> 198 About 199 <textarea id="profile-about" maxlength="800" rows="5" placeholder="Tell players what your games are about."></textarea> 200 </label> 201 <label> 202 Play schedule 203 <textarea id="profile-play-schedule" maxlength="500" rows="3" placeholder="e.g. Fridays at 7pm, school assembly mornings, monthly trivia nights."></textarea> 204 </label> 205 <label> 206 Logo URL 207 <input id="profile-logo-url" type="url" maxlength="500" placeholder="https://example.com/logo.png"> 208 </label> 209 <label> 210 Hero image URL 211 <input id="profile-hero-image-url" type="url" maxlength="500" placeholder="https://example.com/hero.jpg"> 212 </label> 213 <label> 214 YouTube live/video URL 215 <input id="profile-youtube-url" type="url" maxlength="500" placeholder="https://www.youtube.com/watch?v=..."> 216 </label> 217 <label> 218 Contact text 219 <input id="profile-contact-text" type="text" maxlength="300" placeholder="Bookings, WhatsApp, email, or venue details"> 220 </label> 221 <label class="checkbox-row"> 222 <input id="profile-is-public" type="checkbox" checked>
223 <span>Make this page public</span> 224 </label> 225 <div class="form-actions"> 226 <button type="submit">Save Brand Page</button> 227 <a id="profile-public-link" class="button-link muted" href="/u/" target="_blank" rel="noopener">View page</a> 228 </div> 229 </form> 230 <p id="brand-message" class="message"></p> 231 232 <section id="scheduled-play-panel" class="scheduled-play-panel"> 233 <div> 234 <p class="eyebrow">Featured play</p> 235 <h2>Schedule a game countdown</h2> 236 </div> 237 <form id="scheduled-play-form" class="scheduled-play-form"> 238 <label> 239 Quiz 240 <select id="scheduled-play-quiz"></select> 241 </label> 242 <label> 243 Display title 244 <input id="scheduled-play-title" type="text" maxlength="120" placeholder="e.g. Friday Trivia Night"> 245 </label> 246 <label> 247 Start time 248 <input id="scheduled-play-start" type="datetime-local" required> 249 </label> 250 <label class="checkbox-row"> 251 <input id="scheduled-play-featured" type="checkbox" checked> 252 <span>Show this play on my public page</span> 253 </label> 254 <button type="submit">Schedule Play</button> 255 </form> 256 <div id="scheduled-play-list" class="scheduled-play-list"></div> 257 <p id="scheduled-play-message" class="message"></p> 258 </section> 259 </section> 260 </div> 261 262 <div id="admin-mode" class="mode"> 263 <section id="admin-screen" class="screen active"> 264 <p class="eyebrow">Admin Panel</p> 265 <h1>User Management</h1> 266 <div class="admin-user-toolbar"> 267 <input id="admin-user-search" type="search" placeholder="Search email, user ID, username, or phone"> 268 <select id="admin-user-account-type"> 269 <option value="">All account types</option> 270 <option value="host">Hosts</option> 271 <option value="player">Players</option> 272 </select> 273 <select id="admin-user-role"> 274 <option value="">All roles</option> 275 <option value="admin">Admins</option> 276 <option value="user">Users</option> 277 </select> 278 <select id="admin-user-status"> 279 <option value="">All statuses</option> 280 <option value="active">Active</option> 281 <option value="banned">Banned</option> 282 <option value="disabled">Disabled</option> 283 <option value="deleted">Soft deleted</option> 284 </select> 285 <input id="admin-user-created-from" type="date" title="Created from"> 286 <input id="admin-user-created-to" type="date" title="Created to"> 287 <select id="admin-user-page-size"> 288 <option value="25">25 rows</option> 289 <option value="50">50 rows</option> 290 <option value="100">100 rows</option> 291 </select> 292 <button id="admin-user-filter-apply" class="text-btn" type="button">Filter</button> 293 <button id="admin-user-filter-reset" class="text-btn" type="button">Reset</button> 294 </div> 295 <div class="admin-user-actions"> 296 <button id="admin-user-export-csv" class="text-btn" type="button">Export CSV</button> 297 <button id="admin-user-export-json" class="text-btn" type="button">Export JSON</button> 298 </div> 299 <div class="admin-user-table-wrap"> 300 <table class="admin-user-table"> 301 <thead> 302 <tr> 303 <th>User</th> 304 <th>Type</th> 305 <th>Status</th> 306 <th>Registered</th> 307 <th>Subscription</th> 308 <th>Actions</th> 309 </tr> 310 </thead> 311 <tbody id="admin-user-list"></tbody> 312 </table> 313 </div> 314 <div class="admin-user-pagination"> 315 <button id="admin-user-prev" class="text-btn" type="button">Previous</button>
316 <span id="admin-user-page-info"></span> 317 <button id="admin-user-next" class="text-btn" type="button">Next</button> 318 </div> 319 <p id="admin-message" class="message"></p> 320 321 <section class="admin-log-panel"> 322 <div class="history-card-head"> 323 <div> 324 <p class="eyebrow">Security</p> 325 <h2>Login attempts</h2> 326 </div> 327 <div class="history-export"> 328 <input id="admin-auth-log-search" type="search" placeholder="Search login, email, IP"> 329 <select id="admin-auth-log-success"> 330 <option value="">All attempts</option> 331 <option value="false">Failed only</option> 332 <option value="true">Successful only</option> 333 </select> 334 <button id="admin-auth-log-refresh" class="text-btn" type="button">Refresh</button> 335 </div> 336 </div> 337 <div id="admin-auth-log-list" class="admin-log-list"></div> 338 </section> 339 340 <section class="admin-log-panel"> 341 <div class="history-card-head"> 342 <div> 343 <p class="eyebrow">Audit</p> 344 <h2>Admin mutations</h2> 345 </div> 346 <div class="history-export"> 347 <button id="admin-audit-refresh" class="text-btn" type="button">Refresh</button> 348 </div> 349 </div> 350 <div id="admin-audit-log-list" class="admin-log-list"></div> 351 </section> 352 353 <section id="rate-limit-panel" class="rate-limit-panel" hidden> 354 <div class="history-card-head"> 355 <div> 356 <p class="eyebrow">Traffic Protection</p> 357 <h2>Rate limits</h2> 358 </div> 359 <div class="history-export"> 360 <button id="rate-limit-refresh" class="text-btn" type="button">Refresh</button> 361 <button id="rate-limit-clear-logs" class="text-btn danger" type="button">Clear logs</button> 362 </div> 363 </div> 364 <div id="rate-limit-list" class="rate-limit-list"></div> 365 <h3>Recent blocks</h3> 366 <div id="rate-limit-log-list" class="rate-limit-log-list"></div> 367 <p id="rate-limit-message" class="message"></p> 368 </section> 369 </section> 370 </div> 371 372 <div id="history-mode" class="mode"> 373 <section id="history-screen" class="screen active"> 374 <div> 375 <p class="eyebrow">Play History</p> 376 <h1>Finished games</h1> 377 </div> 378 <div class="history-tabs" aria-label="History filters"> 379 <button id="history-tab-finished" class="history-tab active" type="button">Finished games</button> 380 <button id="history-tab-archived" class="history-tab" type="button">Archive</button> 381 </div> 382 <div id="host-history-list" class="history-list"></div> 383 <p id="host-history-message" class="message"></p> 384 </section> 385 </div> 386 387 <div id="predictor-mode" class="mode"> 388 <section id="predictor-history-screen" class="screen active"> 389 <div class="history-card-head"> 390 <div> 391 <p class="eyebrow">Predictor History</p> 392 <h1>Predictor draws</h1> 393 </div> 394 <div class="history-export"> 395 <label> 396 Sort by date 397 <select id="predictor-history-sort"> 398 <option value="newest">Newest first</option> 399 <option value="oldest">Oldest first</option> 400 </select> 401 </label> 402 <button id="predictor-history-refresh" class="text-btn" type="button">Refresh</button> 403 </div> 404 </div> 405 <div class="history-tabs" aria-label="Predictor history filters"> 406 <button id="predictor-tab-active" class="history-tab active" type="button">Active history</button> 407 <button id="predictor-tab-archived" class="history-tab" type="button">Archive</button> 408 </div> 409 <div id="predictor-history-list" class="history-list"></div> 410 <p id="predictor-history-message" class="message"></p> 411 </section> 412 </div> 413 </div> 414 </main> 415 416 <div id="countdown-overlay" class="countdown-overlay"> 417 <div id="countdown-number" class="countdown-number"></div> 418 </div> 419 420
420<script src="/socket.io/socket.io.js"></script>
420 421
421<script src="/sounds.js?v=2"></script>
421 422
422<script src="./app.js?v=17"></script>
422 423 </body> 424</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.