Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>TriFocus - Cognitive Training App</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| @keyframes pulse { | |
| 0%, 100% { transform: scale(1); opacity: 1; } | |
| 50% { transform: scale(1.05); opacity: 0.9; } | |
| } | |
| .pulse-animation { | |
| animation: pulse 2s infinite; | |
| } | |
| .countdown { | |
| font-size: 5rem; | |
| font-weight: bold; | |
| color: #3b82f6; | |
| } | |
| .reaction-dot { | |
| width: 60px; | |
| height: 60px; | |
| border-radius: 50%; | |
| position: absolute; | |
| cursor: pointer; | |
| transition: transform 0.1s; | |
| } | |
| .reaction-dot:active { | |
| transform: scale(0.9); | |
| } | |
| .stroop-card { | |
| width: 200px; | |
| height: 120px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 24px; | |
| font-weight: bold; | |
| border-radius: 12px; | |
| margin: 10px; | |
| cursor: pointer; | |
| transition: all 0.2s; | |
| } | |
| .stroop-card:hover { | |
| transform: translateY(-5px); | |
| box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1); | |
| } | |
| .sequence-item { | |
| width: 70px; | |
| height: 70px; | |
| border-radius: 12px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 24px; | |
| font-weight: bold; | |
| margin: 10px; | |
| transition: all 0.2s; | |
| } | |
| .sequence-item:hover { | |
| transform: scale(1.05); | |
| } | |
| .progress-bar { | |
| height: 8px; | |
| border-radius: 4px; | |
| transition: width 0.3s ease; | |
| } | |
| .radial-progress { | |
| --value: 0; | |
| --size: 120px; | |
| --thickness: 12px; | |
| } | |
| .fade-in { | |
| animation: fadeIn 0.5s ease-in; | |
| } | |
| @keyframes fadeIn { | |
| from { opacity: 0; transform: translateY(20px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| .language-selector { | |
| position: relative; | |
| display: inline-block; | |
| } | |
| .language-dropdown { | |
| display: none; | |
| position: absolute; | |
| right: 0; | |
| background-color: white; | |
| min-width: 120px; | |
| box-shadow: 0 8px 16px 0 rgba(0,0,0,0.1); | |
| z-index: 1; | |
| border-radius: 8px; | |
| overflow: hidden; | |
| } | |
| .language-selector:hover .language-dropdown { | |
| display: block; | |
| } | |
| .language-option { | |
| padding: 10px 16px; | |
| display: flex; | |
| align-items: center; | |
| cursor: pointer; | |
| transition: background-color 0.2s; | |
| } | |
| .language-option:hover { | |
| background-color: #f3f4f6; | |
| } | |
| .language-flag { | |
| width: 20px; | |
| margin-right: 8px; | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-50 min-h-screen font-sans"> | |
| <!-- App Container --> | |
| <div class="container mx-auto px-4 py-8 max-w-4xl"> | |
| <!-- Header --> | |
| <header class="flex justify-between items-center mb-8"> | |
| <div class="flex items-center"> | |
| <div class="w-12 h-12 rounded-full bg-blue-500 flex items-center justify-center text-white font-bold text-xl mr-3">TF</div> | |
| <h1 class="text-3xl font-bold text-gray-800">TriFocus</h1> | |
| </div> | |
| <div class="flex space-x-4 items-center"> | |
| <!-- Language Selector --> | |
| <div class="language-selector"> | |
| <button class="p-2 rounded-full bg-gray-100 hover:bg-gray-200 text-gray-700 flex items-center"> | |
| <i class="fas fa-globe mr-1"></i> | |
| <span id="currentLanguage">EN</span> | |
| </button> | |
| <div class="language-dropdown mt-1"> | |
| <div class="language-option" onclick="changeLanguage('en')"> | |
| <img src="https://flagcdn.com/w20/gb.png" class="language-flag" alt="English"> | |
| <span>English</span> | |
| </div> | |
| <div class="language-option" onclick="changeLanguage('fr')"> | |
| <img src="https://flagcdn.com/w20/fr.png" class="language-flag" alt="Français"> | |
| <span>Français</span> | |
| </div> | |
| <div class="language-option" onclick="changeLanguage('ar')"> | |
| <img src="https://flagcdn.com/w20/sa.png" class="language-flag" alt="العربية"> | |
| <span>العربية</span> | |
| </div> | |
| </div> | |
| </div> | |
| <button id="historyBtn" class="p-2 rounded-full bg-gray-100 hover:bg-gray-200 text-gray-700"> | |
| <i class="fas fa-history"></i> | |
| </button> | |
| <button id="settingsBtn" class="p-2 rounded-full bg-gray-100 hover:bg-gray-200 text-gray-700"> | |
| <i class="fas fa-cog"></i> | |
| </button> | |
| </div> | |
| </header> | |
| <!-- Main Content Area --> | |
| <main id="mainContent"> | |
| <!-- Home Screen --> | |
| <section id="homeScreen" class="fade-in"> | |
| <div class="bg-white rounded-xl shadow-md p-6 mb-6"> | |
| <h2 class="text-2xl font-bold text-gray-800 mb-4" data-i18n="welcome">Welcome to TriFocus</h2> | |
| <p class="text-gray-600 mb-6" data-i18n="welcome_sub">Train your cognitive skills with our three specialized modules. Choose your training mode below.</p> | |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> | |
| <div class="bg-blue-50 rounded-lg p-6 border border-blue-100 hover:border-blue-300 transition-all cursor-pointer" onclick="startExpressSession()"> | |
| <div class="flex items-center mb-3"> | |
| <div class="w-10 h-10 rounded-full bg-blue-500 flex items-center justify-center text-white mr-3"> | |
| <i class="fas fa-bolt"></i> | |
| </div> | |
| <h3 class="text-lg font-semibold text-gray-800" data-i18n="express_session">Express Session</h3> | |
| </div> | |
| <p class="text-gray-600 text-sm" data-i18n="express_desc">Complete all 3 modules in sequence for a comprehensive cognitive assessment.</p> | |
| </div> | |
| <div class="bg-purple-50 rounded-lg p-6 border border-purple-100 hover:border-purple-300 transition-all cursor-pointer" onclick="showModuleSelection()"> | |
| <div class="flex items-center mb-3"> | |
| <div class="w-10 h-10 rounded-full bg-purple-500 flex items-center justify-center text-white mr-3"> | |
| <i class="fas fa-sliders-h"></i> | |
| </div> | |
| <h3 class="text-lg font-semibold text-gray-800" data-i18n="individual_module">Individual Module</h3> | |
| </div> | |
| <p class="text-gray-600 text-sm" data-i18n="individual_desc">Focus on one specific cognitive skill with a single module.</p> | |
| </div> | |
| </div> | |
| <div class="bg-gray-50 rounded-lg p-4"> | |
| <h4 class="font-medium text-gray-700 mb-2" data-i18n="last_session">Your last session score:</h4> | |
| <div class="flex items-center"> | |
| <div class="radial-progress text-blue-500" style="--value: 72; --size: 3rem; --thickness: 4px;">72</div> | |
| <div class="ml-4"> | |
| <p class="text-sm text-gray-600" data-i18n="score_was">Your focus score was <span class="font-semibold">72/100</span></p> | |
| <div class="w-full bg-gray-200 rounded-full h-2 mt-1"> | |
| <div class="bg-blue-500 h-2 rounded-full" style="width: 72%"></div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="bg-white rounded-xl shadow-md p-6"> | |
| <h2 class="text-xl font-bold text-gray-800 mb-4" data-i18n="your_progress">Your Progress</h2> | |
| <div class="grid grid-cols-3 gap-4 mb-4"> | |
| <div class="text-center"> | |
| <div class="radial-progress text-blue-500 mx-auto mb-2" style="--value: 85;">85</div> | |
| <p class="text-xs font-medium text-gray-600" data-i18n="reaction">Reaction</p> | |
| </div> | |
| <div class="text-center"> | |
| <div class="radial-progress text-purple-500 mx-auto mb-2" style="--value: 68;">68</div> | |
| <p class="text-xs font-medium text-gray-600" data-i18n="attention">Attention</p> | |
| </div> | |
| <div class="text-center"> | |
| <div class="radial-progress text-green-500 mx-auto mb-2" style="--value: 76;">76</div> | |
| <p class="text-xs font-medium text-gray-600" data-i18n="memory">Memory</p> | |
| </div> | |
| </div> | |
| <div class="flex justify-between items-center"> | |
| <div> | |
| <p class="text-sm font-medium text-gray-700" data-i18n="current_level">Current Level: <span class="font-bold">Novice</span></p> | |
| <div class="w-full bg-gray-200 rounded-full h-2 mt-1"> | |
| <div class="bg-yellow-500 h-2 rounded-full" style="width: 45%"></div> | |
| </div> | |
| </div> | |
| <div class="text-right"> | |
| <p class="text-xs text-gray-500" data-i18n="next_badge">Next badge at 100 points</p> | |
| <div class="inline-block bg-yellow-100 rounded-full p-1"> | |
| <i class="fas fa-medal text-yellow-500"></i> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Module Selection Screen --> | |
| <section id="moduleSelectionScreen" class="hidden fade-in"> | |
| <div class="bg-white rounded-xl shadow-md p-6 mb-6"> | |
| <div class="flex items-center mb-6"> | |
| <button onclick="backToHome()" class="mr-4 p-2 rounded-full bg-gray-100 hover:bg-gray-200 text-gray-700"> | |
| <i class="fas fa-arrow-left"></i> | |
| </button> | |
| <h2 class="text-2xl font-bold text-gray-800" data-i18n="select_module">Select a Module</h2> | |
| </div> | |
| <div class="grid grid-cols-1 gap-4"> | |
| <div class="bg-blue-50 rounded-lg p-6 border border-blue-100 hover:border-blue-300 transition-all cursor-pointer" onclick="startModule('reaction')"> | |
| <div class="flex items-center mb-3"> | |
| <div class="w-12 h-12 rounded-full bg-blue-500 flex items-center justify-center text-white mr-4"> | |
| <i class="fas fa-hand-pointer"></i> | |
| </div> | |
| <div> | |
| <h3 class="text-lg font-semibold text-gray-800" data-i18n="reaction_tap">Reaction Tap</h3> | |
| <p class="text-sm text-gray-600" data-i18n="reaction_desc">Test your reaction speed</p> | |
| </div> | |
| </div> | |
| <div class="flex justify-between items-center mt-4"> | |
| <div class="text-sm"> | |
| <span class="font-medium text-gray-700" data-i18n="best">Best: </span> | |
| <span class="font-bold text-blue-600">215ms</span> | |
| </div> | |
| <span class="bg-blue-100 text-blue-800 text-xs font-medium px-2.5 py-0.5 rounded" data-i18n="weight">30% weight</span> | |
| </div> | |
| </div> | |
| <div class="bg-purple-50 rounded-lg p-6 border border-purple-100 hover:border-purple-300 transition-all cursor-pointer" onclick="startModule('stroop')"> | |
| <div class="flex items-center mb-3"> | |
| <div class="w-12 h-12 rounded-full bg-purple-500 flex items-center justify-center text-white mr-4"> | |
| <i class="fas fa-palette"></i> | |
| </div> | |
| <div> | |
| <h3 class="text-lg font-semibold text-gray-800" data-i18n="color_match">Color Match</h3> | |
| <p class="text-sm text-gray-600" data-i18n="stroop_desc">Stroop test for selective attention</p> | |
| </div> | |
| </div> | |
| <div class="flex justify-between items-center mt-4"> | |
| <div class="text-sm"> | |
| <span class="font-medium text-gray-700" data-i18n="best">Best: </span> | |
| <span class="font-bold text-purple-600">92% accuracy</span> | |
| </div> | |
| <span class="bg-purple-100 text-purple-800 text-xs font-medium px-2.5 py-0.5 rounded" data-i18n="weight">40% weight</span> | |
| </div> | |
| </div> | |
| <div class="bg-green-50 rounded-lg p-6 border border-green-100 hover:border-green-300 transition-all cursor-pointer" onclick="startModule('sequence')"> | |
| <div class="flex items-center mb-3"> | |
| <div class="w-12 h-12 rounded-full bg-green-500 flex items-center justify-center text-white mr-4"> | |
| <i class="fas fa-brain"></i> | |
| </div> | |
| <div> | |
| <h3 class="text-lg font-semibold text-gray-800" data-i18n="sequence_recall">Sequence Recall</h3> | |
| <p class="text-sm text-gray-600" data-i18n="sequence_desc">Challenge your working memory</p> | |
| </div> | |
| </div> | |
| <div class="flex justify-between items-center mt-4"> | |
| <div class="text-sm"> | |
| <span class="font-medium text-gray-700" data-i18n="best">Best: </span> | |
| <span class="font-bold text-green-600">8 items</span> | |
| </div> | |
| <span class="bg-green-100 text-green-800 text-xs font-medium px-2.5 py-0.5 rounded" data-i18n="weight">30% weight</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Countdown Screen --> | |
| <section id="countdownScreen" class="hidden"> | |
| <div class="flex flex-col items-center justify-center h-64"> | |
| <h2 id="moduleTitle" class="text-2xl font-bold text-gray-800 mb-8"></h2> | |
| <div class="countdown" id="countdown">3</div> | |
| <p class="text-gray-600 mt-4" data-i18n="get_ready">Get ready...</p> | |
| </div> | |
| </section> | |
| <!-- Reaction Tap Game --> | |
| <section id="reactionGame" class="hidden"> | |
| <div class="bg-white rounded-xl shadow-md p-6 mb-6"> | |
| <h2 class="text-2xl font-bold text-gray-800 mb-2" data-i18n="reaction_tap">Reaction Tap</h2> | |
| <p class="text-gray-600 mb-4" data-i18n="tap_instruction">Tap the dot as soon as it appears</p> | |
| <div class="flex justify-between items-center mb-6"> | |
| <div> | |
| <span class="text-sm font-medium text-gray-700" data-i18n="trials">Trials: </span> | |
| <span id="reactionTrials" class="font-bold">0/10</span> | |
| </div> | |
| <div> | |
| <span class="text-sm font-medium text-gray-700" data-i18n="avg_reaction">Avg. reaction: </span> | |
| <span id="avgReaction" class="font-bold">-</span> | |
| </div> | |
| </div> | |
| <div class="relative bg-gray-100 rounded-lg h-64 w-full" id="reactionArea"> | |
| <div id="reactionDot" class="reaction-dot bg-blue-500 hidden"></div> | |
| </div> | |
| <div class="mt-6"> | |
| <div class="flex justify-between text-sm text-gray-600 mb-1"> | |
| <span data-i18n="progress">Progress</span> | |
| <span id="reactionProgressText">0%</span> | |
| </div> | |
| <div class="w-full bg-gray-200 rounded-full h-2"> | |
| <div id="reactionProgress" class="progress-bar bg-blue-500 h-2 rounded-full" style="width: 0%"></div> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Stroop Test Game --> | |
| <section id="stroopGame" class="hidden"> | |
| <div class="bg-white rounded-xl shadow-md p-6 mb-6"> | |
| <h2 class="text-2xl font-bold text-gray-800 mb-2" data-i18n="color_match">Color Match</h2> | |
| <p class="text-gray-600 mb-4" data-i18n="stroop_instruction">Select the color of the text, not the word itself</p> | |
| <div class="flex justify-between items-center mb-6"> | |
| <div> | |
| <span class="text-sm font-medium text-gray-700" data-i18n="questions">Questions: </span> | |
| <span id="stroopTrials" class="font-bold">0/12</span> | |
| </div> | |
| <div> | |
| <span class="text-sm font-medium text-gray-700" data-i18n="accuracy">Accuracy: </span> | |
| <span id="stroopAccuracy" class="font-bold">-</span> | |
| </div> | |
| </div> | |
| <div class="flex flex-col items-center mb-8"> | |
| <div id="stroopQuestion" class="stroop-card bg-white shadow-md text-3xl mb-8">WORD</div> | |
| <div class="grid grid-cols-2 gap-4"> | |
| <div class="stroop-card bg-red-500 text-white" onclick="checkStroopAnswer('red')" data-i18n="red">Red</div> | |
| <div class="stroop-card bg-blue-500 text-white" onclick="checkStroopAnswer('blue')" data-i18n="blue">Blue</div> | |
| <div class="stroop-card bg-green-500 text-white" onclick="checkStroopAnswer('green')" data-i18n="green">Green</div> | |
| <div class="stroop-card bg-yellow-500 text-white" onclick="checkStroopAnswer('yellow')" data-i18n="yellow">Yellow</div> | |
| </div> | |
| </div> | |
| <div class="mt-6"> | |
| <div class="flex justify-between text-sm text-gray-600 mb-1"> | |
| <span data-i18n="progress">Progress</span> | |
| <span id="stroopProgressText">0%</span> | |
| </div> | |
| <div class="w-full bg-gray-200 rounded-full h-2"> | |
| <div id="stroopProgress" class="progress-bar bg-purple-500 h-2 rounded-full" style="width: 0%"></div> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Sequence Recall Game --> | |
| <section id="sequenceGame" class="hidden"> | |
| <div class="bg-white rounded-xl shadow-md p-6 mb-6"> | |
| <h2 class="text-2xl font-bold text-gray-800 mb-2" data-i18n="sequence_recall">Sequence Recall</h2> | |
| <p class="text-gray-600 mb-4" data-i18n="sequence_instruction">Memorize and repeat the sequence</p> | |
| <div class="flex justify-between items-center mb-6"> | |
| <div> | |
| <span class="text-sm font-medium text-gray-700" data-i18n="level">Level: </span> | |
| <span id="sequenceLevel" class="font-bold">1</span> | |
| </div> | |
| <div> | |
| <span class="text-sm font-medium text-gray-700" data-i18n="best">Best: </span> | |
| <span id="sequenceBest" class="font-bold">5 items</span> | |
| </div> | |
| </div> | |
| <div id="sequenceDisplayArea" class="flex justify-center mb-8"> | |
| <!-- Sequence items will appear here --> | |
| </div> | |
| <div id="sequenceInputArea" class="grid grid-cols-3 gap-4 mb-8"> | |
| <!-- Input buttons will appear here --> | |
| </div> | |
| <div class="mt-6"> | |
| <div class="flex justify-between text-sm text-gray-600 mb-1"> | |
| <span data-i18n="progress">Progress</span> | |
| <span id="sequenceProgressText">0%</span> | |
| </div> | |
| <div class="w-full bg-gray-200 rounded-full h-2"> | |
| <div id="sequenceProgress" class="progress-bar bg-green-500 h-2 rounded-full" style="width: 0%"></div> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Results Screen --> | |
| <section id="resultsScreen" class="hidden fade-in"> | |
| <div class="bg-white rounded-xl shadow-md p-6 mb-6"> | |
| <div class="flex items-center mb-6"> | |
| <button onclick="backToHome()" class="mr-4 p-2 rounded-full bg-gray-100 hover:bg-gray-200 text-gray-700"> | |
| <i class="fas fa-arrow-left"></i> | |
| </button> | |
| <h2 class="text-2xl font-bold text-gray-800" data-i18n="session_results">Session Results</h2> | |
| </div> | |
| <div class="flex flex-col items-center mb-8"> | |
| <div class="radial-progress text-blue-500 mb-4" style="--value: 78;">78</div> | |
| <h3 class="text-xl font-bold text-gray-800 mb-2" data-i18n="focus_score">Your Focus Score</h3> | |
| <p class="text-gray-600 mb-6" data-i18n="better_than">Better than 65% of your previous sessions</p> | |
| <div class="w-full bg-gray-100 rounded-full h-4 mb-6"> | |
| <div class="bg-gradient-to-r from-blue-500 via-purple-500 to-green-500 h-4 rounded-full" style="width: 78%"></div> | |
| </div> | |
| </div> | |
| <div class="grid grid-cols-1 gap-6 mb-8"> | |
| <div class="bg-blue-50 rounded-lg p-4"> | |
| <div class="flex justify-between items-center mb-2"> | |
| <h4 class="font-medium text-gray-700" data-i18n="reaction_tap">Reaction Tap</h4> | |
| <span class="bg-blue-100 text-blue-800 text-xs font-medium px-2.5 py-0.5 rounded" data-i18n="weight">30%</span> | |
| </div> | |
| <div class="flex justify-between items-center"> | |
| <div> | |
| <p class="text-sm text-gray-600" data-i18n="avg_reaction">Avg. reaction: <span class="font-semibold">248ms</span></p> | |
| <p class="text-sm text-gray-600" data-i18n="accuracy">Accuracy: <span class="font-semibold">90%</span></p> | |
| </div> | |
| <div class="text-right"> | |
| <div class="text-lg font-bold text-blue-600">24/30</div> | |
| <p class="text-xs text-gray-500" data-i18n="score">Score</p> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="bg-purple-50 rounded-lg p-4"> | |
| <div class="flex justify-between items-center mb-2"> | |
| <h4 class="font-medium text-gray-700" data-i18n="color_match">Color Match</h4> | |
| <span class="bg-purple-100 text-purple-800 text-xs font-medium px-2.5 py-0.5 rounded" data-i18n="weight">40%</span> | |
| </div> | |
| <div class="flex justify-between items-center"> | |
| <div> | |
| <p class="text-sm text-gray-600" data-i18n="avg_time">Avg. time: <span class="font-semibold">1.8s</span></p> | |
| <p class="text-sm text-gray-600" data-i18n="accuracy">Accuracy: <span class="font-semibold">83%</span></p> | |
| </div> | |
| <div class="text-right"> | |
| <div class="text-lg font-bold text-purple-600">32/40</div> | |
| <p class="text-xs text-gray-500" data-i18n="score">Score</p> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="bg-green-50 rounded-lg p-4"> | |
| <div class="flex justify-between items-center mb-2"> | |
| <h4 class="font-medium text-gray-700" data-i18n="sequence_recall">Sequence Recall</h4> | |
| <span class="bg-green-100 text-green-800 text-xs font-medium px-2.5 py-0.5 rounded" data-i18n="weight">30%</span> | |
| </div> | |
| <div class="flex justify-between items-center"> | |
| <div> | |
| <p class="text-sm text-gray-600" data-i18n="max_sequence">Max sequence: <span class="font-semibold">6 items</span></p> | |
| <p class="text-sm text-gray-600" data-i18n="avg_time">Avg. time: <span class="font-semibold">3.2s</span></p> | |
| </div> | |
| <div class="text-right"> | |
| <div class="text-lg font-bold text-green-600">22/30</div> | |
| <p class="text-xs text-gray-500" data-i18n="score">Score</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="bg-yellow-50 rounded-lg p-4 border border-yellow-200"> | |
| <h4 class="font-medium text-gray-700 mb-2" data-i18n="recommendations">Recommendations</h4> | |
| <ul class="list-disc pl-5 text-sm text-gray-700 space-y-1"> | |
| <li data-i18n="recommendation1">Practice Color Match to improve your selective attention</li> | |
| <li data-i18n="recommendation2">Try morning sessions when your reaction time is typically faster</li> | |
| <li data-i18n="recommendation3">Take a 5-minute break between sessions for better focus</li> | |
| </ul> | |
| </div> | |
| </div> | |
| <div class="bg-white rounded-xl shadow-md p-6"> | |
| <h2 class="text-xl font-bold text-gray-800 mb-4" data-i18n="earned_badges">Earned Badges</h2> | |
| <div class="flex space-x-4"> | |
| <div class="text-center"> | |
| <div class="w-16 h-16 rounded-full bg-blue-100 flex items-center justify-center text-blue-500 mx-auto mb-2"> | |
| <i class="fas fa-bolt text-xl"></i> | |
| </div> | |
| <p class="text-xs font-medium text-gray-600" data-i18n="quick_reflexes">Quick Reflexes</p> | |
| </div> | |
| <div class="text-center"> | |
| <div class="w-16 h-16 rounded-full bg-purple-100 flex items-center justify-center text-purple-500 mx-auto mb-2"> | |
| <i class="fas fa-brain text-xl"></i> | |
| </div> | |
| <p class="text-xs font-medium text-gray-600" data-i18n="memory_builder">Memory Builder</p> | |
| </div> | |
| <div class="text-center opacity-40"> | |
| <div class="w-16 h-16 rounded-full bg-gray-100 flex items-center justify-center text-gray-400 mx-auto mb-2"> | |
| <i class="fas fa-trophy text-xl"></i> | |
| </div> | |
| <p class="text-xs font-medium text-gray-600" data-i18n="master_focus">Master Focus</p> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| </main> | |
| <!-- Footer --> | |
| <footer class="mt-12 text-center text-gray-500 text-sm"> | |
| <p>TriFocus © 2023 - Cognitive Training App</p> | |
| </footer> | |
| </div> | |
| <script> | |
| // Game state variables | |
| let currentModule = ''; | |
| let sessionType = ''; | |
| let reactionTimes = []; | |
| let stroopAnswers = []; | |
| let sequenceLevel = 1; | |
| let currentLanguage = 'en'; | |
| // Translation dictionary | |
| const translations = { | |
| en: { | |
| welcome: "Welcome to TriFocus", | |
| welcome_sub: "Train your cognitive skills with our three specialized modules. Choose your training mode below.", | |
| express_session: "Express Session", | |
| express_desc: "Complete all 3 modules in sequence for a comprehensive cognitive assessment.", | |
| individual_module: "Individual Module", | |
| individual_desc: "Focus on one specific cognitive skill with a single module.", | |
| last_session: "Your last session score:", | |
| score_was: "Your focus score was", | |
| your_progress: "Your Progress", | |
| reaction: "Reaction", | |
| attention: "Attention", | |
| memory: "Memory", | |
| current_level: "Current Level:", | |
| next_badge: "Next badge at 100 points", | |
| select_module: "Select a Module", | |
| reaction_tap: "Reaction Tap", | |
| reaction_desc: "Test your reaction speed", | |
| best: "Best:", | |
| weight: "weight", | |
| color_match: "Color Match", | |
| stroop_desc: "Stroop test for selective attention", | |
| sequence_recall: "Sequence Recall", | |
| sequence_desc: "Challenge your working memory", | |
| get_ready: "Get ready...", | |
| tap_instruction: "Tap the dot as soon as it appears", | |
| trials: "Trials:", | |
| avg_reaction: "Avg. reaction:", | |
| progress: "Progress", | |
| stroop_instruction: "Select the color of the text, not the word itself", | |
| questions: "Questions:", | |
| accuracy: "Accuracy:", | |
| red: "Red", | |
| blue: "Blue", | |
| green: "Green", | |
| yellow: "Yellow", | |
| sequence_instruction: "Memorize and repeat the sequence", | |
| level: "Level:", | |
| session_results: "Session Results", | |
| focus_score: "Your Focus Score", | |
| better_than: "Better than 65% of your previous sessions", | |
| recommendations: "Recommendations", | |
| recommendation1: "Practice Color Match to improve your selective attention", | |
| recommendation2: "Try morning sessions when your reaction time is typically faster", | |
| recommendation3: "Take a 5-minute break between sessions for better focus", | |
| earned_badges: "Earned Badges", | |
| quick_reflexes: "Quick Reflexes", | |
| memory_builder: "Memory Builder", | |
| master_focus: "Master Focus", | |
| score: "Score", | |
| avg_time: "Avg. time:", | |
| max_sequence: "Max sequence:" | |
| }, | |
| fr: { | |
| welcome: "Bienvenue sur TriFocus", | |
| welcome_sub: "Entraînez vos capacités cognitives avec nos trois modules spécialisés. Choisissez votre mode d'entraînement ci-dessous.", | |
| express_session: "Session Express", | |
| express_desc: "Complétez les 3 modules en séquence pour une évaluation cognitive complète.", | |
| individual_module: "Module Individuel", | |
| individual_desc: "Concentrez-vous sur une compétence cognitive spécifique avec un seul module.", | |
| last_session: "Votre score de la dernière session :", | |
| score_was: "Votre score de concentration était", | |
| your_progress: "Votre Progrès", | |
| reaction: "Réaction", | |
| attention: "Attention", | |
| memory: "Mémoire", | |
| current_level: "Niveau Actuel :", | |
| next_badge: "Prochain badge à 100 points", | |
| select_module: "Sélectionnez un Module", | |
| reaction_tap: "Tape Réaction", | |
| reaction_desc: "Testez votre vitesse de réaction", | |
| best: "Meilleur :", | |
| weight: "pondération", | |
| color_match: "Correspondance Couleur", | |
| stroop_desc: "Test Stroop pour l'attention sélective", | |
| sequence_recall: "Rappel de Séquence", | |
| sequence_desc: "Défiez votre mémoire de travail", | |
| get_ready: "Préparez-vous...", | |
| tap_instruction: "Tapez sur le point dès qu'il apparaît", | |
| trials: "Essais :", | |
| avg_reaction: "Moy. réaction :", | |
| progress: "Progression", | |
| stroop_instruction: "Sélectionnez la couleur du texte, pas le mot lui-même", | |
| questions: "Questions :", | |
| accuracy: "Précision :", | |
| red: "Rouge", | |
| blue: "Bleu", | |
| green: "Vert", | |
| yellow: "Jaune", | |
| sequence_instruction: "Mémorisez et répétez la séquence", | |
| level: "Niveau :", | |
| session_results: "Résultats de la Session", | |
| focus_score: "Votre Score de Concentration", | |
| better_than: "Mieux que 65% de vos sessions précédentes", | |
| recommendations: "Recommandations", | |
| recommendation1: "Pratiquez Correspondance Couleur pour améliorer votre attention sélective", | |
| recommendation2: "Essayez des sessions matinales lorsque votre temps de réaction est généralement plus rapide", | |
| recommendation3: "Prenez une pause de 5 minutes entre les sessions pour une meilleure concentration", | |
| earned_badges: "Badges Obtenus", | |
| quick_reflexes: "Réflexes Rapides", | |
| memory_builder: "Bâtisseur de Mémoire", | |
| master_focus: "Maître de la Concentration", | |
| score: "Score", | |
| avg_time: "Moy. temps :", | |
| max_sequence: "Séquence max :" | |
| }, | |
| ar: { | |
| welcome: "مرحبًا بكم في TriFocus", | |
| welcome_sub: "قم بتدريب مهاراتك المعرفية من خلال وحداتنا الثلاث المتخصصة. اختر نمط التدريب الخاص بك أدناه.", | |
| express_session: "جلسة سريعة", | |
| express_desc: "أكمل جميع الوحدات الثلاث بالتسلسل لتقييم معرفي شامل.", | |
| individual_module: "وحدة فردية", | |
| individual_desc: "ركز على مهارة معرفية محددة مع وحدة واحدة.", | |
| last_session: "نتيجة جلستك الأخيرة:", | |
| score_was: "كانت درجة تركيزك", | |
| your_progress: "تقدمك", | |
| reaction: "رد الفعل", | |
| attention: "الانتباه", | |
| memory: "الذاكرة", | |
| current_level: "المستوى الحالي:", | |
| next_badge: "الشارة التالية عند 100 نقطة", | |
| select_module: "اختر وحدة", | |
| reaction_tap: "النقر السريع", | |
| reaction_desc: "اختبر سرعة رد فعلك", | |
| best: "الأفضل:", | |
| weight: "الوزن", | |
| color_match: "مطابقة الألوان", | |
| stroop_desc: "اختبار ستروب للانتباه الانتقائي", | |
| sequence_recall: "تذكر التسلسل", | |
| sequence_desc: "تحدي ذاكرتك العاملة", | |
| get_ready: "استعد...", | |
| tap_instruction: "انقر على النقطة بمجرد ظهورها", | |
| trials: "المحاولات:", | |
| avg_reaction: "متوسط رد الفعل:", | |
| progress: "التقدم", | |
| stroop_instruction: "اختر لون النص وليس الكلمة نفسها", | |
| questions: "الأسئلة:", | |
| accuracy: "الدقة:", | |
| red: "أحمر", | |
| blue: "أزرق", | |
| green: "أخضر", | |
| yellow: "أصفر", | |
| sequence_instruction: "احفظ التسلسل وكرره", | |
| level: "المستوى:", | |
| session_results: "نتائج الجلسة", | |
| focus_score: "درجة تركيزك", | |
| better_than: "أفضل من 65% من جلساتك السابقة", | |
| recommendations: "التوصيات", | |
| recommendation1: "تدرب على مطابقة الألوان لتحسين انتباهك الانتقائي", | |
| recommendation2: "جرب الجلسات الصباحية عندما يكون وقت رد فعلك أسرع عادةً", | |
| recommendation3: "خذ استراحة لمدة 5 دقائق بين الجلسات لتحسين التركيز", | |
| earned_badges: "شارات مكتسبة", | |
| quick_reflexes: "ردود فعل سريعة", | |
| memory_builder: "باني الذاكرة", | |
| master_focus: "سيد التركيز", | |
| score: "النتيجة", | |
| avg_time: "متوسط الوقت:", | |
| max_sequence: "أقصى تسلسل:" | |
| } | |
| }; | |
| // DOM elements | |
| const homeScreen = document.getElementById('homeScreen'); | |
| const moduleSelectionScreen = document.getElementById('moduleSelectionScreen'); | |
| const countdownScreen = document.getElementById('countdownScreen'); | |
| const reactionGame = document.getElementById('reactionGame'); | |
| const stroopGame = document.getElementById('stroopGame'); | |
| const sequenceGame = document.getElementById('sequenceGame'); | |
| const resultsScreen = document.getElementById('resultsScreen'); | |
| const moduleTitle = document.getElementById('moduleTitle'); | |
| const countdown = document.getElementById('countdown'); | |
| // Navigation functions | |
| function showModuleSelection() { | |
| homeScreen.classList.add('hidden'); | |
| moduleSelectionScreen.classList.remove('hidden'); | |
| } | |
| function backToHome() { | |
| homeScreen.classList.remove('hidden'); | |
| moduleSelectionScreen.classList.add('hidden'); | |
| countdownScreen.classList.add('hidden'); | |
| reactionGame.classList.add('hidden'); | |
| stroopGame.classList.add('hidden'); | |
| sequenceGame.classList.add('hidden'); | |
| resultsScreen.classList.add('hidden'); | |
| } | |
| function startExpressSession() { | |
| sessionType = 'express'; | |
| startModule('reaction'); | |
| } | |
| function startModule(module) { | |
| currentModule = module; | |
| homeScreen.classList.add('hidden'); | |
| moduleSelectionScreen.classList.add('hidden'); | |
| countdownScreen.classList.remove('hidden'); | |
| // Set module title | |
| switch(module) { | |
| case 'reaction': | |
| moduleTitle.textContent = document.querySelector('[data-i18n="reaction_tap"]').textContent; | |
| break; | |
| case 'stroop': | |
| moduleTitle.textContent = document.querySelector('[data-i18n="color_match"]').textContent; | |
| break; | |
| case 'sequence': | |
| moduleTitle.textContent = document.querySelector('[data-i18n="sequence_recall"]').textContent; | |
| break; | |
| } | |
| // Start countdown | |
| let counter = 3; | |
| countdown.textContent = counter; | |
| const countdownInterval = setInterval(() => { | |
| counter--; | |
| countdown.textContent = counter; | |
| if (counter <= 0) { | |
| clearInterval(countdownInterval); | |
| startGame(); | |
| } | |
| }, 1000); | |
| } | |
| function startGame() { | |
| countdownScreen.classList.add('hidden'); | |
| switch(currentModule) { | |
| case 'reaction': | |
| setupReactionGame(); | |
| reactionGame.classList.remove('hidden'); | |
| break; | |
| case 'stroop': | |
| setupStroopGame(); | |
| stroopGame.classList.remove('hidden'); | |
| break; | |
| case 'sequence': | |
| setupSequenceGame(); | |
| sequenceGame.classList.remove('hidden'); | |
| break; | |
| } | |
| } | |
| function finishModule() { | |
| // Hide all game screens | |
| reactionGame.classList.add('hidden'); | |
| stroopGame.classList.add('hidden'); | |
| sequenceGame.classList.add('hidden'); | |
| if (sessionType === 'express') { | |
| // Move to next module in express session | |
| if (currentModule === 'reaction') { | |
| startModule('stroop'); | |
| } else if (currentModule === 'stroop') { | |
| startModule('sequence'); | |
| } else { | |
| // All modules completed, show results | |
| showResults(); | |
| } | |
| } else { | |
| // Single module mode, show results | |
| showResults(); | |
| } | |
| } | |
| function showResults() { | |
| resultsScreen.classList.remove('hidden'); | |
| } | |
| // Reaction Tap Game | |
| function setupReactionGame() { | |
| reactionTimes = []; | |
| document.getElementById('reactionTrials').textContent = '0/10'; | |
| document.getElementById('avgReaction').textContent = '-'; | |
| document.getElementById('reactionProgress').style.width = '0%'; | |
| document.getElementById('reactionProgressText').textContent = '0%'; | |
| const reactionDot = document.getElementById('reactionDot'); | |
| reactionDot.classList.add('hidden'); | |
| // Start first trial after a random delay | |
| setTimeout(startReactionTrial, Math.random() * 2000 + 1000); | |
| } | |
| function startReactionTrial() { | |
| const reactionArea = document.getElementById('reactionArea'); | |
| const reactionDot = document.getElementById('reactionDot'); | |
| // Position dot randomly within area | |
| const maxX = reactionArea.offsetWidth - reactionDot.offsetWidth; | |
| const maxY = reactionArea.offsetHeight - reactionDot.offsetHeight; | |
| const posX = Math.floor(Math.random() * maxX); | |
| const posY = Math.floor(Math.random() * maxY); | |
| reactionDot.style.left = `${posX}px`; | |
| reactionDot.style.top = `${posY}px`; | |
| // Show dot and start timer | |
| reactionDot.classList.remove('hidden'); | |
| reactionDot.startTime = Date.now(); | |
| // Set timeout for missed taps (1.5 seconds) | |
| reactionDot.timeout = setTimeout(() => { | |
| reactionDot.classList.add('hidden'); | |
| recordReactionTime(null); // null indicates a miss | |
| // Start next trial if not finished | |
| if (reactionTimes.length < 10) { | |
| setTimeout(startReactionTrial, Math.random() * 1000 + 500); | |
| } else { | |
| finishModule(); | |
| } | |
| }, 1500); | |
| } | |
| function recordReactionTime(time) { | |
| const reactionDot = document.getElementById('reactionDot'); | |
| clearTimeout(reactionDot.timeout); | |
| reactionDot.classList.add('hidden'); | |
| if (time !== null) { | |
| reactionTimes.push(time); | |
| } | |
| // Update UI | |
| const completedTrials = reactionTimes.length; | |
| document.getElementById('reactionTrials').textContent = `${completedTrials}/10`; | |
| // Calculate average reaction time (only for successful taps) | |
| const successfulTrials = reactionTimes.filter(t => t !== null); | |
| if (successfulTrials.length > 0) { | |
| const avg = Math.round(successfulTrials.reduce((a, b) => a + b, 0) / successfulTrials.length); | |
| document.getElementById('avgReaction').textContent = `${avg}ms`; | |
| } | |
| // Update progress | |
| const progress = (completedTrials / 10) * 100; | |
| document.getElementById('reactionProgress').style.width = `${progress}%`; | |
| document.getElementById('reactionProgressText').textContent = `${progress}%`; | |
| // Start next trial or finish | |
| if (completedTrials < 10) { | |
| setTimeout(startReactionTrial, Math.random() * 1000 + 500); | |
| } else { | |
| setTimeout(finishModule, 1000); | |
| } | |
| } | |
| // Add click event to reaction dot | |
| document.getElementById('reactionDot').addEventListener('click', function() { | |
| const reactionTime = Date.now() - this.startTime; | |
| recordReactionTime(reactionTime); | |
| }); | |
| // Stroop Test Game | |
| function setupStroopGame() { | |
| stroopAnswers = []; | |
| document.getElementById('stroopTrials').textContent = '0/12'; | |
| document.getElementById('stroopAccuracy').textContent = '-'; | |
| document.getElementById('stroopProgress').style.width = '0%'; | |
| document.getElementById('stroopProgressText').textContent = '0%'; | |
| // Start first question | |
| showStroopQuestion(); | |
| } | |
| const colorWords = ['RED', 'BLUE', 'GREEN', 'YELLOW']; | |
| const colors = ['red', 'blue', 'green', 'yellow']; | |
| function showStroopQuestion() { | |
| const questionElement = document.getElementById('stroopQuestion'); | |
| // Randomly select a word and color (different from word) | |
| const word = colorWords[Math.floor(Math.random() * colorWords.length)]; | |
| let color = colors[Math.floor(Math.random() * colors.length)]; | |
| // Ensure color is different from word (case-insensitive) | |
| while (color.toUpperCase() === word) { | |
| color = colors[Math.floor(Math.random() * colors.length)]; | |
| } | |
| // Store correct answer | |
| questionElement.dataset.correctAnswer = color; | |
| // Apply color to text | |
| questionElement.textContent = word; | |
| questionElement.style.color = color; | |
| // Start timer for this question | |
| questionElement.startTime = Date.now(); | |
| } | |
| function checkStroopAnswer(selectedColor) { | |
| const questionElement = document.getElementById('stroopQuestion'); | |
| const correctAnswer = questionElement.dataset.correctAnswer; | |
| const responseTime = Date.now() - questionElement.startTime; | |
| // Record answer | |
| stroopAnswers.push({ | |
| correct: selectedColor === correctAnswer, | |
| time: responseTime | |
| }); | |
| // Update UI | |
| const completedQuestions = stroopAnswers.length; | |
| document.getElementById('stroopTrials').textContent = `${completedQuestions}/12`; | |
| // Calculate accuracy | |
| const correctAnswers = stroopAnswers.filter(a => a.correct).length; | |
| const accuracy = Math.round((correctAnswers / completedQuestions) * 100); | |
| document.getElementById('stroopAccuracy').textContent = `${accuracy}%`; | |
| // Update progress | |
| const progress = (completedQuestions / 12) * 100; | |
| document.getElementById('stroopProgress').style.width = `${progress}%`; | |
| document.getElementById('stroopProgressText').textContent = `${progress}%`; | |
| // Show next question or finish | |
| if (completedQuestions < 12) { | |
| setTimeout(showStroopQuestion, 500); | |
| } else { | |
| setTimeout(finishModule, 1000); | |
| } | |
| } | |
| // Sequence Recall Game | |
| function setupSequenceGame() { | |
| sequenceLevel = 1; | |
| document.getElementById('sequenceLevel').textContent = '1'; | |
| document.getElementById('sequenceProgress').style.width = '0%'; | |
| document.getElementById('sequenceProgressText').textContent = '0%'; | |
| // Clear display and input areas | |
| const displayArea = document.getElementById('sequenceDisplayArea'); | |
| const inputArea = document.getElementById('sequenceInputArea'); | |
| displayArea.innerHTML = ''; | |
| inputArea.innerHTML = ''; | |
| // Create input buttons (1-9) | |
| for (let i = 1; i <= 9; i++) { | |
| const button = document.createElement('div'); | |
| button.className = 'sequence-item bg-gray-100 text-gray-800'; | |
| button.textContent = i; | |
| button.onclick = function() { checkSequenceInput(i); }; | |
| inputArea.appendChild(button); | |
| } | |
| // Start first level | |
| startSequenceLevel(); | |
| } | |
| function startSequenceLevel() { | |
| const displayArea = document.getElementById('sequenceDisplayArea'); | |
| displayArea.innerHTML = ''; | |
| // Generate random sequence | |
| const sequence = []; | |
| for (let i = 0; i < sequenceLevel; i++) { | |
| sequence.push(Math.floor(Math.random() * 9) + 1); | |
| } | |
| // Display sequence with delay between items | |
| let index = 0; | |
| const displayInterval = setInterval(() => { | |
| if (index >= sequence.length) { | |
| clearInterval(displayInterval); | |
| // After displaying all items, wait a bit then clear for user input | |
| setTimeout(() => { | |
| displayArea.innerHTML = ''; | |
| // Now waiting for user input | |
| }, 500); | |
| return; | |
| } | |
| const item = document.createElement('div'); | |
| item.className = 'sequence-item bg-blue-500 text-white'; | |
| item.textContent = sequence[index]; | |
| displayArea.appendChild(item); | |
| index++; | |
| }, 1000); | |
| // Store sequence and reset user input | |
| displayArea.dataset.sequence = sequence.join(','); | |
| displayArea.dataset.userInput = ''; | |
| } | |
| function checkSequenceInput(number) { | |
| const displayArea = document.getElementById('sequenceDisplayArea'); | |
| const sequence = displayArea.dataset.sequence.split(',').map(Number); | |
| let userInput = displayArea.dataset.userInput ? | |
| displayArea.dataset.userInput.split(',').map(Number) : []; | |
| // Add new input | |
| userInput.push(number); | |
| displayArea.dataset.userInput = userInput.join(','); | |
| // Check if input matches sequence so far | |
| for (let i = 0; i < userInput.length; i++) { | |
| if (userInput[i] !== sequence[i]) { | |
| // Incorrect - level failed | |
| levelFailed(); | |
| return; | |
| } | |
| } | |
| // Check if sequence complete | |
| if (userInput.length === sequence.length) { | |
| levelCompleted(); | |
| } | |
| } | |
| function levelCompleted() { | |
| // Update progress | |
| const progress = (sequenceLevel / 8) * 100; | |
| document.getElementById('sequenceProgress').style.width = `${progress}%`; | |
| document.getElementById('sequenceProgressText').textContent = `${Math.min(progress, 100)}%`; | |
| if (sequenceLevel < 8) { | |
| // Next level | |
| sequenceLevel++; | |
| document.getElementById('sequenceLevel').textContent = sequenceLevel; | |
| setTimeout(startSequenceLevel, 1000); | |
| } else { | |
| // Max level reached | |
| setTimeout(finishModule, 1000); | |
| } | |
| } | |
| function levelFailed() { | |
| // Show failure feedback | |
| const displayArea = document.getElementById('sequenceDisplayArea'); | |
| displayArea.innerHTML = '<div class="text-red-500 font-bold">Incorrect sequence</div>'; | |
| // After delay, show results | |
| setTimeout(() => { | |
| finishModule(); | |
| }, 1500); | |
| } | |
| // Language functions | |
| function changeLanguage(lang) { | |
| currentLanguage = lang; | |
| document.getElementById('currentLanguage').textContent = lang.toUpperCase(); | |
| translatePage(); | |
| } | |
| function translatePage() { | |
| const elements = document.querySelectorAll('[data-i18n]'); | |
| elements.forEach(element => { | |
| const key = element.getAttribute('data-i18n'); | |
| if (translations[currentLanguage] && translations[currentLanguage][key]) { | |
| if (element.tagName === 'INPUT' || element.tagName === 'TEXTAREA') { | |
| element.placeholder = translations[currentLanguage][key]; | |
| } else { | |
| element.textContent = translations[currentLanguage][key]; | |
| } | |
| } | |
| }); | |
| // RTL support for Arabic | |
| if (currentLanguage === 'ar') { | |
| document.body.setAttribute('dir', 'rtl'); | |
| document.body.style.textAlign = 'right'; | |
| } else { | |
| document.body.setAttribute('dir', 'ltr'); | |
| document.body.style.textAlign = 'left'; | |
| } | |
| } | |
| // Initialize with English | |
| changeLanguage('en'); | |
| </script> | |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=SaidAmchghal/trifocus" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |