diff --git a/wssshd2/templates/index.html b/wssshd2/templates/index.html
index 078b174..46f4ebe 100644
--- a/wssshd2/templates/index.html
+++ b/wssshd2/templates/index.html
@@ -90,6 +90,7 @@ function updateClients() {
             if (data.count === 0) {
                 clientListHtml = '<div class="text-center py-5"><i class="fas fa-server fa-4x text-muted mb-3"></i><h4 class="text-muted">No clients registered</h4><p class="text-muted">Clients will appear here when they register.</p></div>';
             } else {
+                clientListHtml = '<div class="row">';
                 for (const [clientId, clientData] of Object.entries(data.clients)) {
                     const statusIcon = clientData.status === 'connected' ? 'fa-desktop text-success' : 'fa-server text-warning';
                     const statusText = clientData.status === 'connected' ? 'Connected' : 'Registered';
@@ -114,6 +115,7 @@ function updateClients() {
                             </div>
                         </div>`;
                 }
+                clientListHtml += '</div>';
             }
 
             // Update client list only if changed
diff --git a/wssshd2/templates/novnc/input/util.js b/wssshd2/templates/novnc/input/util.js
index c6951ff..d19112a 100644
--- a/wssshd2/templates/novnc/input/util.js
+++ b/wssshd2/templates/novnc/input/util.js
@@ -185,3 +185,9 @@ function getKeysym(evt) {
 }
 window.getKeycode = getKeycode;
 window.getKeysym = getKeysym;
+
+// Create KeyboardUtil object for compatibility
+window.KeyboardUtil = {
+    getKeycode: getKeycode,
+    getKeysym: getKeysym
+};
diff --git a/wssshd2/templates/novnc/rfb.js b/wssshd2/templates/novnc/rfb.js
index 9a1d561..68a3545 100644
--- a/wssshd2/templates/novnc/rfb.js
+++ b/wssshd2/templates/novnc/rfb.js
@@ -175,7 +175,6 @@ class RFB extends EventTargetMixin {
 
         // main setup
         Log.Debug(">> RFB.constructor");
-        console.log("[VNC-CLIENT] RFB constructor called");
 
         // Create DOM elements
         this._screen = document.createElement('div');
@@ -192,10 +191,6 @@ class RFB extends EventTargetMixin {
         this._canvas.height = 0;
         this._canvas.tabIndex = -1;
         this._screen.appendChild(this._canvas);
-        console.log("[VNC-CLIENT] DOM elements created, canvas size:", this._canvas.width, "x", this._canvas.height);
-        console.log("[VNC-CLIENT] Canvas element:", this._canvas);
-        console.log("[VNC-CLIENT] Screen element:", this._screen);
-        console.log("[VNC-CLIENT] Target element:", this._target);
 
         // Cursor
         this._cursor = new Cursor();
@@ -224,16 +219,12 @@ class RFB extends EventTargetMixin {
         // NB: nothing that needs explicit teardown should be done
         // before this point, since this can throw an exception
         try {
-            console.log("[VNC-CLIENT] Creating Display object with canvas:", this._canvas);
             this._display = new Display(this._canvas);
-            console.log("[VNC-CLIENT] Display object created successfully:", this._display);
         } catch (exc) {
-            console.error("[VNC-CLIENT] Display exception:", exc);
             Log.Error("Display exception: " + exc);
             throw exc;
         }
         this._display.onflush = this._onFlush.bind(this);
-        console.log("[VNC-CLIENT] Display onflush handler set");
 
         this._keyboard = new Keyboard(this._canvas);
         this._keyboard.onkeyevent = this._handleKeyEvent.bind(this);
@@ -610,17 +601,11 @@ class RFB extends EventTargetMixin {
     }
 
     _socketOpen() {
-        console.log("[VNC-CLIENT] WebSocket opened, connectionState:", this._rfbConnectionState, "initState:", this._rfbInitState);
-        // console.log("[VNC-DEBUG] WebSocket opened, starting VNC handshake");
         if ((this._rfbConnectionState === 'connecting') &&
             (this._rfbInitState === '')) {
             this._rfbInitState = 'ProtocolVersion';
             Log.Debug("Starting VNC handshake");
-            console.log("[VNC-CLIENT] Starting VNC handshake, set init state to ProtocolVersion");
-            // console.log("[VNC-DEBUG] Set init state to ProtocolVersion");
         } else {
-            console.log("[VNC-CLIENT] Unexpected socket open - connectionState:", this._rfbConnectionState, "initState:", this._rfbInitState);
-            // console.log("[VNC-DEBUG] Unexpected socket open - connectionState:", this._rfbConnectionState, "initState:", this._rfbInitState);
             this._fail("Unexpected server connection while " +
                         this._rfbConnectionState);
         }
@@ -887,7 +872,6 @@ class RFB extends EventTargetMixin {
                 break;
 
             case 'connected':
-                console.log("[VNC-CLIENT] Connection state changed to CONNECTED");
                 this.dispatchEvent(new CustomEvent("connect", { detail: {} }));
                 break;
 
@@ -944,7 +928,6 @@ class RFB extends EventTargetMixin {
     }
 
     _handleMessage() {
-        console.log("[VNC-MESSAGE] _handleMessage called, rQlen:", this._sock.rQlen, "connectionState:", this._rfbConnectionState, "initState:", this._rfbInitState);
         if (this._sock.rQlen === 0) {
             Log.Warn("handleMessage called on an empty receive queue");
             return;
@@ -955,37 +938,21 @@ class RFB extends EventTargetMixin {
                 Log.Error("Got data while disconnected");
                 break;
             case 'connected':
-                console.log("[VNC-MESSAGE] Processing messages in connected state");
-                let msgCount = 0;
                 while (true) {
                     if (this._flushing) {
-                        console.log("[VNC-MESSAGE] Flushing, breaking message loop");
                         break;
                     }
-                    console.log("[VNC-MESSAGE] Calling _normalMsg, rQlen before:", this._sock.rQlen);
-                    const result = this._normalMsg();
-                    console.log("[VNC-MESSAGE] _normalMsg returned:", result, "rQlen after:", this._sock.rQlen);
-                    if (!result) {
-                        console.log("[VNC-MESSAGE] _normalMsg returned false, breaking");
+                    if (!this._normalMsg()) {
                         break;
                     }
                     if (this._sock.rQlen === 0) {
-                        console.log("[VNC-MESSAGE] No more data in queue");
-                        break;
-                    }
-                    msgCount++;
-                    if (msgCount > 10) { // Prevent infinite loops
-                        console.log("[VNC-MESSAGE] Too many messages processed, breaking to prevent infinite loop");
                         break;
                     }
                 }
                 break;
             case 'connecting':
-                console.log("[VNC-MESSAGE] Processing messages in connecting state");
                 while (this._rfbConnectionState === 'connecting') {
-                    console.log("[VNC-MESSAGE] Calling _initMsg, initState:", this._rfbInitState);
                     if (!this._initMsg()) {
-                        console.log("[VNC-MESSAGE] _initMsg returned false, breaking");
                         break;
                     }
                 }
@@ -1350,29 +1317,23 @@ class RFB extends EventTargetMixin {
     // Message Handlers
 
     _negotiateProtocolVersion() {
-        console.log("[VNC-DEBUG] _negotiateProtocolVersion called");
         if (this._sock.rQwait("version", 12)) {
-            console.log("[VNC-DEBUG] Waiting for version data");
             return false;
         }
 
         const versionStr = this._sock.rQshiftStr(12);
-        console.log("[VNC-DEBUG] Received version string:", versionStr);
         const sversion = versionStr.substr(4, 7);
         Log.Info("Server ProtocolVersion: " + sversion);
         let isRepeater = 0;
         switch (sversion) {
             case "000.000":  // UltraVNC repeater
-                console.log("[VNC-DEBUG] Detected UltraVNC repeater");
                 isRepeater = 1;
                 break;
             case "003.003":
             case "003.006":  // UltraVNC
-                console.log("[VNC-DEBUG] Setting RFB version to 3.3");
                 this._rfbVersion = 3.3;
                 break;
             case "003.007":
-                console.log("[VNC-DEBUG] Setting RFB version to 3.7");
                 this._rfbVersion = 3.7;
                 break;
             case "003.008":
@@ -1380,11 +1341,9 @@ class RFB extends EventTargetMixin {
             case "004.000":  // Intel AMT KVM
             case "004.001":  // RealVNC 4.6
             case "005.000":  // RealVNC 5.3
-                console.log("[VNC-DEBUG] Setting RFB version to 3.8");
                 this._rfbVersion = 3.8;
                 break;
             default:
-                console.log("[VNC-DEBUG] Invalid server version:", sversion);
                 return this._fail("Invalid server version " + sversion);
         }
 
@@ -2058,16 +2017,13 @@ class RFB extends EventTargetMixin {
     }
 
     _negotiateServerInit() {
-        console.log("[VNC-DEBUG] _negotiateServerInit called");
         if (this._sock.rQwait("server initialization", 24)) {
-            console.log("[VNC-DEBUG] Waiting for server initialization data");
             return false;
         }
 
         /* Screen size */
         const width = this._sock.rQshift16();
         const height = this._sock.rQshift16();
-        console.log("[VNC-DEBUG] Server screen size:", width, "x", height);
 
         /* PIXEL_FORMAT */
         const bpp         = this._sock.rQshift8();
@@ -2083,8 +2039,6 @@ class RFB extends EventTargetMixin {
         const blueShift  = this._sock.rQshift8();
         this._sock.rQskipBytes(3);  // padding
 
-        console.log("[VNC-DEBUG] Server pixel format - bpp:", bpp, "depth:", depth, "trueColor:", trueColor);
-
         // NB(directxman12): we don't want to call any callbacks or print messages until
         //                   *after* we're past the point where we could backtrack
 
@@ -2133,13 +2087,11 @@ class RFB extends EventTargetMixin {
 
         // we're past the point where we could backtrack, so it's safe to call this
         this._setDesktopName(name);
-        console.log("[VNC-CLIENT] Server init complete - screen:", width, "x", height, "name:", name);
         this._resize(width, height);
 
         if (!this._viewOnly) { this._keyboard.grab(); }
 
         this._fbDepth = 24;
-        console.log("[VNC-CLIENT] Keyboard grabbed, fbDepth set to 24");
 
         if (this._fbName === "Intel(r) AMT KVM") {
             Log.Warn("Intel AMT KVM only supports 8/16 bit depths. Using low color mode.");
@@ -2493,13 +2445,12 @@ class RFB extends EventTargetMixin {
             msgType = 0;
         } else {
             if (this._sock.rQlen < 1) {
-                console.log("[VNC-MESSAGE] Not enough data for message type, rQlen:", this._sock.rQlen);
                 return false;
             }
             msgType = this._sock.rQshift8();
         }
 
-        console.log("[VNC-MESSAGE] Processing message type:", msgType, "FBU.rects:", this._FBU.rects, "rQlen:", this._sock.rQlen);
+        // console.log("[VNC-MESSAGE] Processing message type:", msgType, "FBU.rects:", this._FBU.rects, "rQlen:", this._sock.rQlen);
 
         let first, ret;
         switch (msgType) {
@@ -2569,24 +2520,15 @@ class RFB extends EventTargetMixin {
             this._sock.rQskipBytes(1);  // Padding
             this._FBU.rects = this._sock.rQshift16();
 
-            console.log("[VNC-CLIENT] FramebufferUpdate header - rects:", this._FBU.rects);
-
-            // Debug: check if we have enough data for the rectangles
-            const expectedBytes = this._FBU.rects * 12; // Each rect header is 12 bytes
-            console.log("[VNC-DEBUG] Expected bytes for rect headers:", expectedBytes, "available rQlen:", this._sock.rQlen);
-
             // Validate rectangle count - should be reasonable (not 65534 or similar corruption)
             if (this._FBU.rects > 10000 || this._FBU.rects < 0) {
-                console.log("[VNC-DEBUG] Invalid rectangle count:", this._FBU.rects, "- likely corrupted data, skipping message");
                 Log.Warn("Invalid rectangle count in FramebufferUpdate (" + this._FBU.rects + "), skipping corrupted message");
                 // Skip the entire FramebufferUpdate message by consuming all remaining data for this message
                 // We need to skip past all the rectangle data
                 const skipBytes = this._FBU.rects * 12; // Each rectangle header is 12 bytes
                 if (this._sock.rQlen >= skipBytes) {
                     this._sock.rQskipBytes(skipBytes);
-                    console.log("[VNC-DEBUG] Skipped", skipBytes, "bytes of corrupted rectangle data");
                 } else {
-                    console.log("[VNC-DEBUG] Not enough data to skip, waiting for more data");
                     return false; // Wait for more data
                 }
                 this._FBU.rects = 0; // Reset for next message
@@ -2605,7 +2547,6 @@ class RFB extends EventTargetMixin {
         while (this._FBU.rects > 0) {
             if (this._FBU.encoding === null) {
                 if (this._sock.rQwait("rect header", 12)) {
-                    console.log("[VNC-DEBUG] Waiting for rectangle header data");
                     return false;
                 }
                 /* New FramebufferUpdate */
@@ -2617,13 +2558,9 @@ class RFB extends EventTargetMixin {
                 this._FBU.height   = (hdr[6] << 8) + hdr[7];
                 this._FBU.encoding = parseInt((hdr[8] << 24) + (hdr[9] << 16) +
                                               (hdr[10] << 8) + hdr[11], 10);
-                console.log("[VNC-DEBUG] Processing rectangle:", this._FBU.x, this._FBU.y, this._FBU.width, "x", this._FBU.height, "encoding:", this._FBU.encoding);
             }
 
-            const rectResult = this._handleRect();
-            console.log("[VNC-DEBUG] _handleRect returned:", rectResult, "remaining rects:", this._FBU.rects - 1);
-            if (!rectResult) {
-                console.log("[VNC-DEBUG] Rectangle processing waiting for more data");
+            if (!this._handleRect()) {
                 return false;
             }
 
@@ -2917,7 +2854,6 @@ class RFB extends EventTargetMixin {
     _handleDataRect() {
         let decoder = this._decoders[this._FBU.encoding];
         if (!decoder) {
-            console.log("[VNC-DEBUG] Unsupported encoding:", this._FBU.encoding, "- skipping rectangle data");
             Log.Warn("Unsupported encoding (encoding: " +
                         this._FBU.encoding + "), skipping rectangle");
 
@@ -2929,9 +2865,7 @@ class RFB extends EventTargetMixin {
                 // Skip a reasonable amount of data for this rectangle
                 const skipSize = Math.min(minDataSize, this._sock.rQlen);
                 this._sock.rQskipBytes(skipSize);
-                console.log("[VNC-DEBUG] Skipped", skipSize, "bytes for unsupported encoding");
             } else {
-                console.log("[VNC-DEBUG] Not enough data to skip rectangle, waiting for more data");
                 return false; // Wait for more data
             }
             return true;
@@ -2943,14 +2877,12 @@ class RFB extends EventTargetMixin {
                                       this._sock, this._display,
                                       this._fbDepth);
         } catch (err) {
-            console.log("[VNC-DEBUG] Error decoding rect:", err, "- skipping corrupted rectangle");
             Log.Warn("Error decoding rect: " + err + " - skipping corrupted rectangle");
             // For decoding errors, also skip data to avoid getting stuck
             const minDataSize = this._FBU.width * this._FBU.height;
             if (this._sock.rQlen >= minDataSize) {
                 const skipSize = Math.min(minDataSize, this._sock.rQlen);
                 this._sock.rQskipBytes(skipSize);
-                console.log("[VNC-DEBUG] Skipped", skipSize, "bytes after decode error");
             }
             return true; // Continue processing instead of failing
         }
@@ -2964,13 +2896,10 @@ class RFB extends EventTargetMixin {
     }
 
     _resize(width, height) {
-        console.log("[VNC-CLIENT] Resizing display to", width, "x", height);
-        console.log("[VNC-CLIENT] Canvas before resize:", this._canvas.width, "x", this._canvas.height);
         this._fbWidth = width;
         this._fbHeight = height;
 
         this._display.resize(this._fbWidth, this._fbHeight);
-        console.log("[VNC-CLIENT] Display resized, canvas after:", this._canvas.width, "x", this._canvas.height);
 
         // Adjust the visible viewport based on the new dimensions
         this._updateClip();
@@ -2980,7 +2909,6 @@ class RFB extends EventTargetMixin {
 
         // Keep this size until browser client size changes
         this._saveExpectedClientSize();
-        console.log("[VNC-CLIENT] Resize complete, final canvas size:", this._canvas.width, "x", this._canvas.height);
     }
 
     _xvpOp(ver, op) {
diff --git a/wssshd2/templates/novnc/websock.js b/wssshd2/templates/novnc/websock.js
index 7755ddd..b1e0031 100644
--- a/wssshd2/templates/novnc/websock.js
+++ b/wssshd2/templates/novnc/websock.js
@@ -338,16 +338,8 @@ class Websock {
     }
 
     _recvMessage(e) {
-        console.log("[VNC-WS] Received WebSocket message, data length:", e.data.byteLength || e.data.length);
-        // Log first 32 bytes for debugging
-        const dataArray = new Uint8Array(e.data);
-        const hexData = Array.from(dataArray.slice(0, Math.min(32, dataArray.length))).map(b => b.toString(16).padStart(2, '0')).join(' ');
-        console.log("[VNC-WS] First 32 bytes (hex):", hexData);
-
         this._DecodeMessage(e.data);
 
-        console.log("[VNC-WS] After decode, rQlen:", this.rQlen, "rQi:", this._rQi);
-
         if (this.rQlen > 0) {
             this._eventHandlers.message();
             if (this._rQlen == this._rQi) {
diff --git a/wssshd2/templates/vnc.html b/wssshd2/templates/vnc.html
index c471702..63d9687 100644
--- a/wssshd2/templates/vnc.html
+++ b/wssshd2/templates/vnc.html
@@ -63,6 +63,15 @@
             overflow: hidden;
             position: relative;
         }
+        .vnc-container.full-size {
+            overflow: auto;
+            max-height: none;
+            height: auto;
+        }
+        .vnc-container.full-size #noVNC_screen {
+            min-width: fit-content;
+            min-height: fit-content;
+        }
         /* GNOME-like window decorations */
         .vnc-window {
             border: 1px solid #ccc;
@@ -127,6 +136,19 @@
         .minimize-btn:hover {
             background: #ffad2c;
         }
+        .zoom-btn {
+            background: #17a2b8;
+            color: white;
+        }
+        .zoom-btn:hover {
+            background: #138496;
+        }
+        .zoom-btn.active {
+            background: #007bff;
+        }
+        .zoom-btn.active:hover {
+            background: #0056b3;
+        }
         .window-content {
             background: #1e1e1e;
             padding: 8px;
@@ -180,6 +202,9 @@
                     <button id="disconnectBtn" class="btn btn-danger btn-sm me-1" disabled style="height: 24px; font-size: 12px; padding: 0 8px;">
                         <i class="fas fa-stop"></i> Disconnect
                     </button>
+                    <button class="window-btn zoom-btn" title="Toggle Zoom (Scale/Fit)" id="zoomBtn">
+                        <i class="fas fa-search-plus"></i>
+                    </button>
                     <button class="window-btn minimize-btn" title="Exit Fullscreen">_</button>
                     <button class="window-btn maximize-btn" title="Fullscreen"><span class="maximize-icon">□</span></button>
                     <button class="window-btn close-btn" title="Disconnect">×</button>
@@ -189,6 +214,15 @@
                 <div id="vnc" class="vnc-container w-100">
                     <div id="noVNC_screen">
                         <div id="noVNC_status">Click Connect to start VNC session</div>
+                        <div id="noVNC_loading" style="display: none; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; color: #f8f8f2;">
+                            <div class="spinner-border text-primary mb-2" role="status">
+                                <span class="visually-hidden">Loading...</span>
+                            </div>
+                            <div>Connecting to VNC server...</div>
+                            <button id="cancelConnectBtn" class="btn btn-outline-danger btn-sm mt-2" style="display: none;">
+                                <i class="fas fa-times"></i> Cancel
+                            </button>
+                        </div>
                     </div>
                 </div>
             </div>
@@ -199,15 +233,10 @@
 
 <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
 <script>
-console.log('VNC page loaded');
-
 // Check if Base64 is loaded
 setTimeout(function() {
-    console.log('[VNC-DEBUG] Checking if Base64 is defined:', typeof window.Base64);
     if (typeof window.Base64 === 'undefined') {
-        console.error('[VNC-DEBUG] Base64 is not defined! This will cause JPEG decoding to fail.');
-    } else {
-        console.log('[VNC-DEBUG] Base64 is properly defined');
+        console.error('[VNC-ERROR] Base64 is not defined! This will cause JPEG decoding to fail.');
     }
 }, 100);
 
@@ -217,11 +246,13 @@ let socketFrameSeq = 0;
 
 document.getElementById('connectBtn').addEventListener('click', connect);
 document.getElementById('disconnectBtn').addEventListener('click', disconnect);
+document.getElementById('cancelConnectBtn').addEventListener('click', cancelConnect);
 
 // Window control buttons
 document.querySelector('.close-btn').addEventListener('click', disconnect);
 document.querySelector('.maximize-btn').addEventListener('click', toggleFullscreen);
 document.querySelector('.minimize-btn').addEventListener('click', toggleFullscreen);
+document.getElementById('zoomBtn').addEventListener('click', toggleZoom);
 
 function showNotification(message, type = 'info') {
     const notificationArea = document.getElementById('notification-area');
@@ -254,95 +285,93 @@ function toggleFullscreen() {
     }
 }
 
+function toggleZoom() {
+    if (!rfb || !connected) return;
+
+    const zoomBtn = document.getElementById('zoomBtn');
+    const zoomIcon = zoomBtn.querySelector('i');
+    const vncContainer = document.getElementById('vnc');
+
+    if (zoomBtn.classList.contains('active')) {
+        // Switch to scaled view (fit to window)
+        zoomBtn.classList.remove('active');
+        zoomBtn.title = 'Toggle Zoom (Scale/Fit)';
+        zoomIcon.className = 'fas fa-search-plus';
+        vncContainer.classList.remove('full-size');
+
+        // Enable scaling, disable clipping
+        rfb.scaleViewport = true;
+        rfb.clipViewport = false;
+
+        showNotification('Switched to scaled view (fit to window)', 'info');
+    } else {
+        // Switch to full-size view with scrollbars
+        zoomBtn.classList.add('active');
+        zoomBtn.title = 'Toggle Zoom (Actual Size)';
+        zoomIcon.className = 'fas fa-search-minus';
+        vncContainer.classList.add('full-size');
+
+        // Disable scaling, enable clipping
+        rfb.scaleViewport = false;
+        rfb.clipViewport = true;
+
+        // Force a resize to ensure canvas is properly sized for scrolling
+        setTimeout(() => {
+            const canvas = document.querySelector('#noVNC_screen canvas');
+            if (canvas) {
+                console.log('Canvas size after zoom toggle:', canvas.width, 'x', canvas.height);
+                console.log('Container size:', vncContainer.clientWidth, 'x', vncContainer.clientHeight);
+            }
+        }, 100);
+
+        showNotification('Switched to actual size view with scrollbars', 'info');
+    }
+}
+
 function connect() {
-    console.log('Connect button clicked');
     if (connected) return;
 
+    // Hide the status text and show loading message
+    document.getElementById('noVNC_status').style.display = 'none';
+    document.getElementById('noVNC_loading').style.display = 'block';
+    document.getElementById('cancelConnectBtn').style.display = 'inline-block';
+
     const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
     const wsUrl = wsProtocol + '//' + window.location.host + '/vnc/%s/ws';
-    console.log('Connecting VNC to:', wsUrl);
 
     try {
         rfb = new RFB(document.getElementById('noVNC_screen'), wsUrl, {
             credentials: {},
             shared: true,
-            repeaterID: '',
-            wsProtocols: ['binary']
+            repeaterID: ''
         });
 
         rfb.addEventListener('connect', () => {
-            console.log('[VNC-DEBUG] VNC connected event fired');
-            console.log('[VNC-DEBUG] Connection state:', rfb._rfbConnectionState);
-            console.log('[VNC-DEBUG] Init state:', rfb._rfbInitState);
             connected = true;
             document.getElementById('connectBtn').disabled = true;
             document.getElementById('disconnectBtn').disabled = false;
+            // Hide loading message
+            document.getElementById('noVNC_loading').style.display = 'none';
             showNotification('VNC session connected', 'success');
 
-            // Override WebSocket onmessage after connection to intercept messages
-            const originalOnMessage = rfb._sock.onmessage;
-            rfb._sock.onmessage = function(event) {
-                // Debug VNC socket data logging with base64 encoding and sequence numbers (first 20 frames only)
-                if (socketFrameSeq < 20) {
-                    const bytes = event.data.byteLength || event.data.length;
-                    const uint8 = new Uint8Array(event.data);
-                    let binary = '';
-                    for (let i = 0; i < uint8.length; i++) {
-                        binary += String.fromCharCode(uint8[i]);
-                    }
-                    const b64Data = btoa(binary);
-                    console.log(`[VNC-SOCKET-SERVER] Frame ${socketFrameSeq}: ${bytes} bytes -> base64: ${b64Data}`);
-                    socketFrameSeq++;
-                }
-
-                // Call original handler
-                return originalOnMessage.call(this, event);
-            };
+            // Reset frame sequence for new connection
+            socketFrameSeq = 0;
         });
 
-        // Add debug logging for WebSocket messages
-        const originalSend = rfb._sock.send;
-        rfb._sock.send = function(data) {
-            console.log('[VNC-DEBUG] JavaScript sending data to WebSocket:', data.length, 'bytes');
-            if (data.length <= 32) {
-                const hex = Array.from(new Uint8Array(data)).map(b => b.toString(16).padStart(2, '0')).join(' ');
-                console.log('[VNC-DEBUG] Data (hex):', hex);
-            } else {
-                const hex = Array.from(new Uint8Array(data.slice(0, 32))).map(b => b.toString(16).padStart(2, '0')).join(' ');
-                console.log('[VNC-DEBUG] Data (first 32 bytes hex):', hex + '...');
-            }
-
-            // Log VNC message types
-            if (data.length > 0) {
-                const msgType = new Uint8Array(data)[0];
-                console.log('[VNC-DEBUG] JavaScript message type:', msgType);
-                switch (msgType) {
-                    case 0: console.log('[VNC-DEBUG] -> SetPixelFormat'); break;
-                    case 2: console.log('[VNC-DEBUG] -> SetEncodings'); break;
-                    case 3: console.log('[VNC-DEBUG] -> FramebufferUpdateRequest'); break;
-                    case 4: console.log('[VNC-DEBUG] -> KeyEvent'); break;
-                    case 5: console.log('[VNC-DEBUG] -> PointerEvent'); break;
-                    case 6: console.log('[VNC-DEBUG] -> ClientCutText'); break;
-                    default: console.log('[VNC-DEBUG] -> Unknown message type'); break;
-                }
-            }
-
-            return originalSend.call(this, data);
-        };
 
 
         rfb.addEventListener('disconnect', () => {
-            console.log('[VNC-DEBUG] VNC disconnected event fired');
-            console.log('[VNC-DEBUG] Connection state:', rfb._rfbConnectionState);
-            console.log('[VNC-DEBUG] Init state:', rfb._rfbInitState);
             connected = false;
             document.getElementById('connectBtn').disabled = false;
             document.getElementById('disconnectBtn').disabled = true;
+            // Reset UI to initial state
+            document.getElementById('noVNC_status').style.display = 'block';
+            document.getElementById('noVNC_loading').style.display = 'none';
+            document.getElementById('cancelConnectBtn').style.display = 'none';
             showNotification('VNC session disconnected', 'info');
         });
 
         rfb.addEventListener('credentialsrequired', (e) => {
-            console.log('VNC credentials required');
             // For now, assume no credentials needed
         });
 
@@ -352,7 +381,7 @@ function connect() {
         });
 
         rfb.addEventListener('clipboard', (e) => {
-            console.log('VNC clipboard:', e.detail.text);
+            // Handle clipboard data if needed
         });
 
     } catch (e) {
@@ -369,10 +398,29 @@ function disconnect() {
     connected = false;
     document.getElementById('connectBtn').disabled = false;
     document.getElementById('disconnectBtn').disabled = true;
+    // Reset UI to initial state
+    document.getElementById('noVNC_status').style.display = 'block';
+    document.getElementById('noVNC_loading').style.display = 'none';
+    document.getElementById('cancelConnectBtn').style.display = 'none';
     setTimeout(() => {
         location.reload();
     }, 3000);
 }
+
+function cancelConnect() {
+    if (rfb) {
+        rfb.disconnect();
+        rfb = null;
+    }
+    connected = false;
+    document.getElementById('connectBtn').disabled = false;
+    document.getElementById('disconnectBtn').disabled = true;
+    // Reset UI to initial state
+    document.getElementById('noVNC_status').style.display = 'block';
+    document.getElementById('noVNC_loading').style.display = 'none';
+    document.getElementById('cancelConnectBtn').style.display = 'none';
+    showNotification('VNC connection cancelled', 'warning');
+}
 </script>
 </body>
 </html>
