@@ -354,6 +354,67 @@ function getRank(lvl) {
354354 return rank ;
355355}
356356
357+
358+ const consoleContainer = document . getElementById ( 'matrix-console-container' ) ;
359+ const consoleOutput = document . getElementById ( 'matrix-console-output' ) ;
360+
361+ function minimizeConsole ( ) {
362+ // Toggles the height of the output area
363+ if ( consoleOutput . style . display === 'none' ) {
364+ consoleOutput . style . display = 'block' ;
365+ consoleContainer . style . width = '20rem' ; // w-80
366+ } else {
367+ consoleOutput . style . display = 'none' ;
368+ consoleContainer . style . width = '150px' ; // Compact view
369+ }
370+ }
371+
372+ function maximizeConsole ( ) {
373+ // Toggles a full-screen-ish mode
374+ consoleContainer . classList . toggle ( 'console-maximized' ) ;
375+
376+ // Adjust height when maximized
377+ if ( consoleContainer . classList . contains ( 'console-maximized' ) ) {
378+ consoleOutput . style . height = '70vh' ;
379+ consoleOutput . style . display = 'block' ;
380+ } else {
381+ consoleOutput . style . height = '12rem' ; // h-48
382+ }
383+ }
384+
385+ function closeConsole ( ) {
386+ const container = document . getElementById ( 'matrix-console-container' ) ;
387+ const reopenBtn = document . getElementById ( 'reopen-console-btn' ) ;
388+
389+ // Hide the console
390+ container . style . opacity = '0' ;
391+ container . style . transform = 'translateY(20px)' ;
392+
393+ setTimeout ( ( ) => {
394+ container . classList . add ( 'hidden' ) ;
395+ // Show the small reopen button
396+ if ( reopenBtn ) reopenBtn . classList . remove ( 'hidden' ) ;
397+ } , 300 ) ;
398+ }
399+
400+ function reopenConsole ( ) {
401+ const container = document . getElementById ( 'matrix-console-container' ) ;
402+ const reopenBtn = document . getElementById ( 'reopen-console-btn' ) ;
403+
404+ // Show the console
405+ container . classList . remove ( 'hidden' ) ;
406+
407+ // Trigger reflow for animation
408+ void container . offsetWidth ;
409+
410+ container . style . opacity = '1' ;
411+ container . style . transform = 'translateY(0)' ;
412+
413+ // Hide the reopen button
414+ if ( reopenBtn ) reopenBtn . classList . add ( 'hidden' ) ;
415+ }
416+
417+
357418let isProcessingXP = false ;
358419
359420// Ensure this is in the GLOBAL scope (not hidden inside another function)
@@ -884,6 +945,69 @@ function renderXP(value) {
884945 // console.log(`XP: ${currentXPNum}, Percent: ${percentage}%`);
885946}
886947
948+ function showLevelUpToast ( rank ) {
949+ // 1. Create the container
950+ const toast = document . createElement ( 'div' ) ;
951+ toast . className = 'level-up-toast' ;
952+
953+ // 2. Build the inner content
954+ // We use the rank color for the name and emoji to make it feel custom
955+ toast . innerHTML = `
956+ <div class="toast-content">
957+ <span class="toast-emoji">${ rank . emoji } </span>
958+ <div class="toast-text">
959+ <p class="toast-title">LEVEL UP!</p>
960+ <p class="toast-rank" style="color: ${ rank . color } ">${ rank . name } </p>
961+ </div>
962+ </div>
963+ ` ;
964+
965+ document . body . appendChild ( toast ) ;
966+
967+ // 3. Auto-remove after animation
968+ setTimeout ( ( ) => {
969+ toast . classList . add ( 'fade-out' ) ;
970+ setTimeout ( ( ) => toast . remove ( ) , 500 ) ;
971+ } , 2500 ) ;
972+ }
973+
974+
975+ function matrixConsoleLog ( level ) {
976+ const rank = getRank ( level ) ;
977+
978+ // This looks awesome in the F12 Dev Console
979+ console . log (
980+ `%c [SYSTEM] %c LEVEL UP: %c ${ rank . name . toUpperCase ( ) } %c [LVL ${ level } ] ` ,
981+ "color: #10b981; font-weight: bold; background: #064e3b; padding: 2px;" ,
982+ "color: #ffffff; background: #1e293b; padding: 2px;" ,
983+ `color: ${ rank . color } ; font-weight: 900; background: #1e293b; padding: 2px;` ,
984+ "color: #94a3b8; background: #1e293b; padding: 2px;"
985+ ) ;
986+
987+ // 3. If you have an on-screen Matrix Console element, push there too:
988+ const matrixConsole = document . getElementById ( 'matrix-console-output' ) ;
989+ if ( matrixConsole ) {
990+ const line = document . createElement ( 'p' ) ;
991+ line . className = 'matrix-line text-xs font-mono mb-1' ;
992+ line . innerHTML = `<span class="text-green-500">>></span> Rank Updated: <span style="color: ${ rank . color } ">${ rank . name } </span>` ;
993+ matrixConsole . appendChild ( line ) ;
994+ // Auto-scroll to bottom
995+ matrixConsole . scrollTop = matrixConsole . scrollHeight ;
996+ }
997+ }
998+
999+ document . addEventListener ( 'keydown' , ( e ) => {
1000+ // Check if user pressed 'L' (for Log) and isn't typing in an input field
1001+ if ( e . key . toLowerCase ( ) === 'l' && e . target . tagName !== 'INPUT' && e . target . tagName !== 'TEXTAREA' ) {
1002+ const container = document . getElementById ( 'matrix-console-container' ) ;
1003+ if ( container . classList . contains ( 'hidden' ) ) {
1004+ reopenConsole ( ) ;
1005+ } else {
1006+ closeConsole ( ) ;
1007+ }
1008+ }
1009+ } ) ;
1010+
8871011async function addExperience ( amount ) {
8881012 // 1. Force strict numeric types to prevent "1" + "1" = "11"
8891013 let xpToAdd = Number ( amount ) || 0 ;
@@ -898,14 +1022,29 @@ async function addExperience(amount) {
8981022 // Using a while loop ensures that if you gain 100 XP,
8991023 // it processes Level 1, then Level 2, with the remainder left over.
9001024 while ( currentXP >= XP_THRESHOLD && currentLevel < 200 ) {
901- currentXP -= XP_THRESHOLD ; // Subtract exactly the cost of one level
1025+ currentXP -= XP_THRESHOLD ;
9021026 currentLevel ++ ;
1027+ // 1. Trigger the Visual Toast (Top of screen)
1028+ if ( typeof showLevelUpToast === 'function' ) {
1029+ showLevelUpToast ( getRank ( currentLevel ) ) ;
1030+ }
9031031
904- // Safety: Ensure we don't end up with negative XP from rounding
905- currentXP = Math . max ( 0 , currentXP ) ;
1032+ // 2. Trigger the "Matrix" Console Log
1033+ matrixConsoleLog ( currentLevel ) ;
1034+
1035+ // --- THE POPUP TRIGGER ---
1036+ const badge = document . getElementById ( 'level-badge' ) ;
1037+ if ( badge ) {
1038+ // Remove the class if it exists (to reset animation)
1039+ badge . classList . remove ( 'animate-badge-pop' ) ;
1040+ // Trigger a "reflow" (magic trick to allow re-animation)
1041+ void badge . offsetWidth ;
1042+ // Re-add the class
1043+ badge . classList . add ( 'animate-badge-pop' ) ;
1044+ }
1045+ // --------------------------
9061046
907- // Optional: Trigger level-up specific effects here
908- console . log ( `Leveled Up! Now Level: ${ currentLevel } ` ) ;
1047+ console . log ( `Leveled Up to ${ currentLevel } !` ) ;
9091048 }
9101049
9111050 // 4. Persistence: Save clean numbers
0 commit comments