1+ // Variables
2+ let isResizing = false ;
3+ let resizeDirection = "" ;
4+ let resizeStartX = 0 ;
5+ let resizeStartY = 0 ;
6+ let resizeStartWidth = 0 ;
7+ let resizeStartOutputHeight = 0 ;
8+ let resizeStartLeft = 0 ;
9+ let resizeStartTop = 0 ;
10+ // Load saved level or start at 0
11+ let currentLevel = Number ( localStorage . getItem ( "userLevel" ) ) || 0 ;
12+
13+ // Load saved XP or start at 0
14+ let currentXP = parseInt ( localStorage . getItem ( "userXP" ) ) || 0 ;
15+
16+ let isSurging = false ;
17+
18+ let audioCtx ;
19+
20+ let unlockedEggs = JSON . parse ( localStorage . getItem ( "unlockedEggs" ) ) || [ ] ;
21+ let surpriseClickCount = 0 ;
22+ let matrixActive = false ;
23+ let destructInterval ;
24+
25+ let isDragging = false ;
26+ let offsetLeft = 0 ;
27+ let offsetTop = 0 ;
28+
29+ // Const Variables
30+ const MIN_CONSOLE_WIDTH = 200 ;
31+ const MIN_OUTPUT_HEIGHT = 50 ;
132const XP_PER_LEVEL = 45 ;
233
334// XP rewards for events and secrets
@@ -13,13 +44,6 @@ const XP_FOOTER_SURGE = 1000; // Footer surge secret
1344const XP_BADGE_CLICK = 45 ; // Badge click reward
1445
1546const NUM_LEVELS = LEVELS . length ;
16- // Load saved level or start at 0
17- let currentLevel = Number ( localStorage . getItem ( "userLevel" ) ) || 0 ;
18-
19- // Load saved XP or start at 0
20- let currentXP = parseInt ( localStorage . getItem ( "userXP" ) ) || 0 ;
21-
22- let isSurging = false ;
2347
2448function getContrastYIQ ( hexcolor ) {
2549 hexcolor = hexcolor . replace ( "#" , "" ) ;
@@ -29,11 +53,10 @@ function getContrastYIQ(hexcolor) {
2953 var yiq = ( r * 299 + g * 587 + b * 114 ) / 1000 ;
3054 return yiq >= 128 ? "black" : "white" ;
3155}
56+
3257/**
3358 * 1. RETRO SOUND ENGINE
3459 */
35- let audioCtx ;
36-
3760function initAudio ( ) {
3861 try {
3962 if ( ! audioCtx ) {
@@ -104,11 +127,6 @@ function playSound(type) {
104127 }
105128}
106129
107- let unlockedEggs = JSON . parse ( localStorage . getItem ( "unlockedEggs" ) ) || [ ] ;
108- let surpriseClickCount = 0 ;
109- let matrixActive = false ;
110- let destructInterval ;
111-
112130function getRank ( lvl ) {
113131 const numericLevel = Number ( lvl ) || 0 ;
114132
@@ -132,10 +150,6 @@ const consoleOutput = document.getElementById("matrix-console-output");
132150const dragContainer = document . getElementById ( "matrix-console-container" ) ;
133151const dragHeader = dragContainer . querySelector ( ".bg-green-500\\/10" ) ; // Selects the header bar
134152
135- let isDragging = false ;
136- let offsetLeft = 0 ;
137- let offsetTop = 0 ;
138-
139153dragHeader . addEventListener ( "mousedown" , ( e ) => {
140154 // Prevent dragging when clicking the minimize/close buttons
141155 if ( e . target . tagName === "BUTTON" ) return ;
@@ -154,15 +168,12 @@ dragHeader.addEventListener("mousedown", (e) => {
154168document . addEventListener ( "mousemove" , ( e ) => {
155169 if ( ! isDragging ) return ;
156170
157- // Calculate new position
158171 let x = e . clientX - offsetLeft ;
159172 let y = e . clientY - offsetTop ;
160173
161- // Boundary Check (Optional: keeps it inside the screen)
162174 x = Math . max ( 0 , Math . min ( x , window . innerWidth - dragContainer . offsetWidth ) ) ;
163175 y = Math . max ( 0 , Math . min ( y , window . innerHeight - dragContainer . offsetHeight ) ) ;
164176
165- // Apply position and remove Tailwind's 'bottom' and 'right' so they don't fight the 'top'/'left'
166177 dragContainer . style . bottom = "auto" ;
167178 dragContainer . style . right = "auto" ;
168179 dragContainer . style . left = `${ x } px` ;
@@ -174,8 +185,81 @@ document.addEventListener("mouseup", () => {
174185 dragHeader . style . cursor = "grab" ;
175186} ) ;
176187
188+ dragContainer . querySelectorAll ( ".resize-handle" ) . forEach ( ( handle ) => {
189+ handle . addEventListener ( "mousedown" , ( e ) => {
190+ e . preventDefault ( ) ;
191+ e . stopPropagation ( ) ;
192+
193+ isResizing = true ;
194+
195+ resizeDirection =
196+ [ ...handle . classList ]
197+ . find ( ( c ) => c . startsWith ( "resize-handle-" ) && c !== "resize-handle" )
198+ ?. replace ( "resize-handle-" , "" ) || "se" ;
199+
200+ const rect = dragContainer . getBoundingClientRect ( ) ;
201+ resizeStartX = e . clientX ;
202+ resizeStartY = e . clientY ;
203+ resizeStartWidth = rect . width ;
204+ resizeStartLeft = rect . left ;
205+ resizeStartTop = rect . top ;
206+ resizeStartOutputHeight = consoleOutput . offsetHeight ;
207+
208+ dragContainer . style . bottom = "auto" ;
209+ dragContainer . style . right = "auto" ;
210+ dragContainer . style . left = `${ rect . left } px` ;
211+ dragContainer . style . top = `${ rect . top } px` ;
212+
213+ dragContainer . classList . remove (
214+ "transition-all" ,
215+ "duration-300" ,
216+ "ease-in-out" ,
217+ ) ;
218+ document . body . style . userSelect = "none" ;
219+ document . body . style . cursor = handle . style . cursor ;
220+ } ) ;
221+ } ) ;
222+
223+ document . addEventListener ( "mousemove" , ( e ) => {
224+ if ( ! isResizing ) return ;
225+
226+ const dx = e . clientX - resizeStartX ;
227+ const dy = e . clientY - resizeStartY ;
228+ const dir = resizeDirection ;
229+
230+ if ( dir . includes ( "e" ) ) {
231+ dragContainer . style . width = `${ Math . max ( MIN_CONSOLE_WIDTH , resizeStartWidth + dx ) } px` ;
232+ }
233+ if ( dir . includes ( "w" ) ) {
234+ const newW = resizeStartWidth - dx ;
235+ if ( newW >= MIN_CONSOLE_WIDTH ) {
236+ dragContainer . style . width = `${ newW } px` ;
237+ dragContainer . style . left = `${ resizeStartLeft + dx } px` ;
238+ }
239+ }
240+
241+ if ( dir . includes ( "s" ) ) {
242+ consoleOutput . style . height = `${ Math . max ( MIN_OUTPUT_HEIGHT , resizeStartOutputHeight + dy ) } px` ;
243+ }
244+ if ( dir . includes ( "n" ) ) {
245+ const newH = resizeStartOutputHeight - dy ;
246+ if ( newH >= MIN_OUTPUT_HEIGHT ) {
247+ consoleOutput . style . height = `${ newH } px` ;
248+ dragContainer . style . top = `${ resizeStartTop + dy } px` ;
249+ }
250+ }
251+ } ) ;
252+
253+ document . addEventListener ( "mouseup" , ( ) => {
254+ if ( ! isResizing ) return ;
255+ isResizing = false ;
256+ resizeDirection = "" ;
257+ document . body . style . userSelect = "" ;
258+ document . body . style . cursor = "" ;
259+ dragContainer . classList . add ( "transition-all" , "duration-300" , "ease-in-out" ) ;
260+ } ) ;
261+
177262function minimizeConsole ( ) {
178- // Toggles the height of the output area
179263 if ( consoleOutput . style . display === "none" ) {
180264 consoleOutput . style . display = "block" ;
181265 consoleContainer . style . width = "20rem" ; // w-80
@@ -186,10 +270,8 @@ function minimizeConsole() {
186270}
187271
188272function maximizeConsole ( ) {
189- // Toggles a full-screen-ish mode
190273 consoleContainer . classList . toggle ( "console-maximized" ) ;
191274
192- // Adjust height when maximized
193275 if ( consoleContainer . classList . contains ( "console-maximized" ) ) {
194276 consoleOutput . style . height = "70vh" ;
195277 consoleOutput . style . display = "block" ;
@@ -217,16 +299,13 @@ function reopenConsole() {
217299 const container = document . getElementById ( "matrix-console-container" ) ;
218300 const reopenBtn = document . getElementById ( "reopen-console-btn" ) ;
219301
220- // Show the console
221302 container . classList . remove ( "hidden" ) ;
222303
223- // Trigger reflow for animation
224304 void container . offsetWidth ;
225305
226306 container . style . opacity = "1" ;
227307 container . style . transform = "translateY(0)" ;
228308
229- // Hide the reopen button
230309 if ( reopenBtn ) reopenBtn . classList . add ( "hidden" ) ;
231310}
232311
0 commit comments