diff --git a/basicswap/static/js/offerstable.js b/basicswap/static/js/offerstable.js
index cec3412..cfd8dd2 100644
--- a/basicswap/static/js/offerstable.js
+++ b/basicswap/static/js/offerstable.js
@@ -1264,7 +1264,7 @@ function getEmptyPriceData() {
 
 async function fetchLatestPrices() {
     const PRICES_CACHE_KEY = 'prices_coingecko';
-    const RETRY_DELAY = 2000;  // 2 sec
+    const RETRY_DELAY = 5000;
     const MAX_RETRIES = 3;
     
     const cachedData = CacheManager.get(PRICES_CACHE_KEY);
@@ -1651,30 +1651,23 @@ async function updateOffersTable() {
 
         const PRICES_CACHE_KEY = 'prices_coingecko';
         const cachedPrices = CacheManager.get(PRICES_CACHE_KEY);
-
-        if (!cachedPrices || !cachedPrices.remainingTime || cachedPrices.remainingTime < 80000) {
-            console.log('Fetching fresh price data...');
-            const priceData = await fetchLatestPrices();
-            if (priceData) {
-                latestPrices = priceData;
-            }
-        } else {
-            latestPrices = cachedPrices.value;
-        }
+        
+        latestPrices = cachedPrices?.value || getEmptyPriceData();
 
         const validOffers = getValidOffers();
-
-        if (!isSentOffers) {
-            const networkOffersSpan = document.querySelector('a[href="/offers"] span.inline-flex.justify-center');
-            if (networkOffersSpan) {
-                networkOffersSpan.textContent = validOffers.length;
-            }
-        }
-
         const startIndex = (currentPage - 1) * itemsPerPage;
         const endIndex = Math.min(startIndex + itemsPerPage, validOffers.length);
         const itemsToDisplay = validOffers.slice(startIndex, endIndex);
 
+        fetchLatestPrices().then(freshPrices => {
+            if (freshPrices) {
+                latestPrices = freshPrices;
+                updateProfitLossDisplays();
+            }
+        }).catch(error => {
+            console.warn('Price fetch failed:', error);
+        });
+
         const identityPromises = itemsToDisplay.map(offer =>
             offer.addr_from ? getIdentityData(offer.addr_from) : Promise.resolve(null)
         );
@@ -1682,10 +1675,6 @@ async function updateOffersTable() {
         const identities = await Promise.all(identityPromises);
 
         if (validOffers.length === 0) {
-            const existingRows = offersBody.querySelectorAll('tr');
-            existingRows.forEach(row => {
-                cleanupRow(row);
-            });
             handleNoOffersScenario();
             finishTableRender();
             return;
@@ -1725,25 +1714,47 @@ async function updateOffersTable() {
         });
 
         lastRefreshTime = Date.now();
-        if (newEntriesCountSpan) {
-            newEntriesCountSpan.textContent = validOffers.length;
-        }
-        if (lastRefreshTimeSpan) {
-            lastRefreshTimeSpan.textContent = new Date(lastRefreshTime).toLocaleTimeString();
-        }
-
+        updateLastRefreshTime();
+        
     } catch (error) {
         console.error('[Debug] Error in updateOffersTable:', error);
-        offersBody.innerHTML = `
-            <tr>
-                <td colspan="8" class="text-center py-4 text-red-500">
-                    An error occurred while updating the offers table. Please try again later.
-                </td>
-            </tr>`;
+        handleTableError();
         finishTableRender();
     }
 }
 
+function updateProfitLossDisplays() {
+    const rows = document.querySelectorAll('[data-offer-id]');
+    rows.forEach(row => {
+        const offerId = row.getAttribute('data-offer-id');
+        const offer = jsonData.find(o => o.offer_id === offerId);
+        if (!offer) return;
+
+        const fromAmount = parseFloat(offer.amount_from) || 0;
+        const toAmount = parseFloat(offer.amount_to) || 0;
+        updateProfitLoss(row, offer.coin_from, offer.coin_to, fromAmount, toAmount, offer.is_own_offer);
+
+        const rateTooltipId = `tooltip-rate-${offerId}`;
+        const rateTooltip = document.getElementById(rateTooltipId);
+        if (rateTooltip) {
+            const tooltipContent = createCombinedRateTooltip(offer, offer.coin_from, offer.coin_to, offer.is_own_offer);
+            rateTooltip.innerHTML = tooltipContent;
+        }
+    });
+}
+
+function handleTableError() {
+    offersBody.innerHTML = `
+        <tr>
+            <td colspan="8" class="text-center py-4 text-gray-500">
+                <div class="flex flex-col items-center justify-center gap-2">
+                    <span>An error occurred while updating the table.</span>
+                    <span class="text-sm">The table will continue to function with cached data.</span>
+                </div>
+            </td>
+        </tr>`;
+}
+
 async function getIdentityData(address) {
     try {
         const response = await fetch(`/json/identities/${address}`);
diff --git a/basicswap/static/js/pricechart.js b/basicswap/static/js/pricechart.js
index d1712d6..889df3d 100644
--- a/basicswap/static/js/pricechart.js
+++ b/basicswap/static/js/pricechart.js
@@ -487,6 +487,13 @@ const chartModule = {
   chart: null,
   currentCoin: 'BTC',
   loadStartTime: 0,
+  
+  cleanup: () => {
+    if (chartModule.chart) {
+      chartModule.chart.destroy();
+      chartModule.chart = null;
+    }
+  },
   verticalLinePlugin: {
     id: 'verticalLine',
     beforeDraw: (chart, args, options) => {
@@ -509,7 +516,7 @@ const chartModule = {
   },
 
   initChart: () => {
-    const ctx = document.getElementById('coin-chart').getContext('2d');
+    const ctx = document.getElementById('coin-chart')?.getContext('2d');
     if (!ctx) {
       logger.error('Failed to get chart context. Make sure the canvas element exists.');
       return;
@@ -568,7 +575,6 @@ const chartModule = {
               callback: function(value) {
                 const date = new Date(value);
                 if (config.currentResolution === 'day') {
-                  // Convert to AM/PM format
                   return date.toLocaleTimeString('en-US', {
                     hour: 'numeric',
                     minute: '2-digit',
@@ -668,13 +674,10 @@ const chartModule = {
       },
       plugins: [chartModule.verticalLinePlugin]
     });
-
-    //console.log('Chart initialized:', chartModule.chart);
   },
   
   prepareChartData: (coinSymbol, data) => {
     if (!data) {
-      //console.error(`No data received for ${coinSymbol}`);
       return [];
     }
 
@@ -733,7 +736,6 @@ const chartModule = {
           y: price
         }));
       } else {
-        //console.error(`Unexpected data structure for ${coinSymbol}:`, data);
         return [];
       }
 
@@ -742,7 +744,6 @@ const chartModule = {
         y: point.y
       }));
     } catch (error) {
-      //console.error(`Error preparing chart data for ${coinSymbol}:`, error);
       return [];
     }
   },
@@ -780,21 +781,17 @@ const chartModule = {
       
       if (cachedData && Object.keys(cachedData.value).length > 0) {
         data = cachedData.value;
-        //console.log(`Using cached data for ${coinSymbol} (${config.currentResolution})`);
       } else {
-        //console.log(`Fetching fresh data for ${coinSymbol} (${config.currentResolution})`);
         const allData = await api.fetchHistoricalDataXHR([coinSymbol]);
         data = allData[coinSymbol];
         if (!data || Object.keys(data).length === 0) {
           throw new Error(`No data returned for ${coinSymbol}`);
         }
-        //console.log(`Caching new data for ${cacheKey}`);
         cache.set(cacheKey, data, config.cacheTTL);
         cachedData = null;
       }
 
       const chartData = chartModule.prepareChartData(coinSymbol, data);
-      //console.log(`Prepared chart data for ${coinSymbol}:`, chartData.slice(0, 5));
 
       if (chartData.length === 0) {
         throw new Error(`No valid chart data for ${coinSymbol}`);
@@ -826,7 +823,6 @@ const chartModule = {
 
         chartModule.chart.update('active');
       } else {
-        //console.error('Chart object not initialized');
         throw new Error('Chart object not initialized');
       }
 
@@ -835,7 +831,6 @@ const chartModule = {
       ui.updateLoadTimeAndCache(loadTime, cachedData);
 
     } catch (error) {
-      //console.error(`Error updating chart for ${coinSymbol}:`, error);
       ui.displayErrorMessage(`Failed to update chart for ${coinSymbol}: ${error.message}`);
     } finally {
       chartModule.hideChartLoader();
@@ -847,7 +842,6 @@ const chartModule = {
     const chart = document.getElementById('coin-chart');
     
     if (!loader || !chart) {
-      //console.warn('Chart loader or chart container elements not found');
       return;
     }
     
@@ -860,49 +854,61 @@ const chartModule = {
     const chart = document.getElementById('coin-chart');
     
     if (!loader || !chart) {
-      //console.warn('Chart loader or chart container elements not found');
       return;
     }
     
     loader.classList.add('hidden');
     chart.classList.remove('hidden');    
-  },
+  }
 };
 
 Chart.register(chartModule.verticalLinePlugin);
 
-  const volumeToggle = {
-    isVisible: localStorage.getItem('volumeToggleState') === 'true',
-    init: () => {
-      const toggleButton = document.getElementById('toggle-volume');
-      if (toggleButton) {
-        toggleButton.addEventListener('click', volumeToggle.toggle);
-        volumeToggle.updateVolumeDisplay();
-      }
-    },
-    toggle: () => {
-      volumeToggle.isVisible = !volumeToggle.isVisible;
-      localStorage.setItem('volumeToggleState', volumeToggle.isVisible.toString());
-      volumeToggle.updateVolumeDisplay();
-    },
-    updateVolumeDisplay: () => {
-      const volumeDivs = document.querySelectorAll('[id$="-volume-div"]');
-      volumeDivs.forEach(div => {
-        div.style.display = volumeToggle.isVisible ? 'flex' : 'none';
-      });
-      const toggleButton = document.getElementById('toggle-volume');
-      if (toggleButton) {
-        updateButtonStyles(toggleButton, volumeToggle.isVisible, 'green');
-      }
+const volumeToggle = {
+  isVisible: localStorage.getItem('volumeToggleState') === 'true',
+  
+  cleanup: () => {
+    const toggleButton = document.getElementById('toggle-volume');
+    if (toggleButton) {
+      toggleButton.removeEventListener('click', volumeToggle.toggle);
     }
-  };
+  },
 
-  function updateButtonStyles(button, isActive, color) {
-    button.classList.toggle('text-' + color + '-500', isActive);
-    button.classList.toggle('text-gray-600', !isActive);
-    button.classList.toggle('dark:text-' + color + '-400', isActive);
-    button.classList.toggle('dark:text-gray-400', !isActive);
+  init: () => {
+    volumeToggle.cleanup();
+    
+    const toggleButton = document.getElementById('toggle-volume');
+    if (toggleButton) {
+      toggleButton.addEventListener('click', volumeToggle.toggle);
+      volumeToggle.updateVolumeDisplay();
+    }
+  },
+
+  toggle: () => {
+    volumeToggle.isVisible = !volumeToggle.isVisible;
+    localStorage.setItem('volumeToggleState', volumeToggle.isVisible.toString());
+    volumeToggle.updateVolumeDisplay();
+  },
+
+  updateVolumeDisplay: () => {
+    const volumeDivs = document.querySelectorAll('[id$="-volume-div"]');
+    volumeDivs.forEach(div => {
+      div.style.display = volumeToggle.isVisible ? 'flex' : 'none';
+    });
+
+    const toggleButton = document.getElementById('toggle-volume');
+    if (toggleButton) {
+      updateButtonStyles(toggleButton, volumeToggle.isVisible, 'green');
+    }
   }
+};
+
+function updateButtonStyles(button, isActive, color) {
+  button.classList.toggle('text-' + color + '-500', isActive);
+  button.classList.toggle('text-gray-600', !isActive);
+  button.classList.toggle('dark:text-' + color + '-400', isActive);
+  button.classList.toggle('dark:text-gray-400', !isActive);
+}
 
 const app = {
   btcPriceUSD: 0,
@@ -918,90 +924,175 @@ const app = {
   },
   cacheTTL: 5 * 60 * 1000, // 5 minutes
   minimumRefreshInterval: 60 * 1000, // 1 minute
+  eventListeners: new Map(),
+  visibilityCleanup: null,
+
+  cleanup: () => {
+    if (app.autoRefreshInterval) {
+      clearTimeout(app.autoRefreshInterval);
+      app.autoRefreshInterval = null;
+    }
+
+    if (app.updateNextRefreshTimeRAF) {
+      cancelAnimationFrame(app.updateNextRefreshTimeRAF);
+      app.updateNextRefreshTimeRAF = null;
+    }
+
+    if (typeof app.visibilityCleanup === 'function') {
+      app.visibilityCleanup();
+      app.visibilityCleanup = null;
+    }
+    
+    volumeToggle.cleanup();
+
+    app.removeEventListeners();
+
+    if (chartModule.chart) {
+      chartModule.chart.destroy();
+      chartModule.chart = null;
+    }
+
+    cache.clear();
+  },
+
+  removeEventListeners: () => {
+    app.eventListeners.forEach((listener, element) => {
+      if (element && typeof element.removeEventListener === 'function') {
+        element.removeEventListener(listener.type, listener.fn);
+      }
+    });
+    app.eventListeners.clear();
+  },
+
+  addEventListenerWithCleanup: (element, type, fn) => {
+    if (element && typeof element.addEventListener === 'function') {
+      element.addEventListener(type, fn);
+      app.eventListeners.set(element, { type, fn });
+    }
+  },
+
+  initResolutionButtons: () => {
+    const resolutionButtons = document.querySelectorAll('.resolution-button');
+    resolutionButtons.forEach(button => {
+      // Remove existing listeners first
+      const oldListener = button.getAttribute('data-resolution-listener');
+      if (oldListener && window[oldListener]) {
+        button.removeEventListener('click', window[oldListener]);
+        delete window[oldListener];
+      }
+      
+      const listener = () => {
+        const resolution = button.id.split('-')[1];
+        const currentCoin = chartModule.currentCoin;
+        
+        if (currentCoin !== 'WOW' || resolution === 'day') {
+          config.currentResolution = resolution;
+          chartModule.updateChart(currentCoin, true);
+          app.updateResolutionButtons(currentCoin);
+        }
+      };
+
+      const listenerName = `resolutionListener_${button.id}`;
+      window[listenerName] = listener;
+      button.setAttribute('data-resolution-listener', listenerName);
+      button.addEventListener('click', listener);
+    });
+  },
+
+  setupVisibilityHandler: () => {
+  const cleanup = () => {
+    if (window.visibilityHandler) {
+      document.removeEventListener('visibilitychange', window.visibilityHandler);
+      delete window.visibilityHandler;
+    }
+  };
+
+  cleanup();
+
+  window.visibilityHandler = () => {
+    if (!document.hidden && chartModule.chart) {
+      chartModule.updateChart(chartModule.currentCoin, true);
+    }
+  };
+
+  document.addEventListener('visibilitychange', window.visibilityHandler);
+  return cleanup;
+},
 
   init: () => {
     console.log('Initializing app...');
+    app.cleanup();
     window.addEventListener('load', app.onLoad);
     app.loadLastRefreshedTime();
     app.updateAutoRefreshButton();
+    app.initResolutionButtons();
+    app.setupVisibilityHandler();
     console.log('App initialized');
   },
-  
-  onLoad: async () => {
-  console.log('App onLoad event triggered');
-  ui.showLoader();
-  try {
-    volumeToggle.init();
-    await app.updateBTCPrice();
-    const chartContainer = document.getElementById('coin-chart');
-    if (chartContainer) {
-      chartModule.initChart();
-      chartModule.showChartLoader();
-    } else {
-      //console.warn('Chart container not found, skipping chart initialization');
-    }
-    
-    console.log('Loading all coin data...');
-    await app.loadAllCoinData();
-    
-    if (chartModule.chart) {
-      config.currentResolution = 'day';
-      await chartModule.updateChart('BTC');
-      app.updateResolutionButtons('BTC');
-    }
-    ui.setActiveContainer('btc-container');
-    
-    //console.log('Setting up event listeners and initializations...');
-    app.setupEventListeners();
-    app.initializeSelectImages();
-    app.initAutoRefresh();
-    
-  } catch (error) {
-    //console.error('Error during initialization:', error);
-    ui.displayErrorMessage('Failed to initialize the dashboard. Please try refreshing the page.');
-  } finally {
-    ui.hideLoader();
-    if (chartModule.chart) {
-      chartModule.hideChartLoader();
-    }
-    console.log('App onLoad completed');
-  }
-},
-  
-    loadAllCoinData: async () => {
-        //console.log('Loading data for all coins...');
-        try {
-            const allCoinData = await api.fetchCoinGeckoDataXHR();
-            if (allCoinData.error) {
-                throw new Error(allCoinData.error);
-            }
 
-            for (const coin of config.coins) {
-                const coinData = allCoinData[coin.symbol.toLowerCase()];
-                if (coinData) {
-                    coinData.displayName = coin.displayName || coin.symbol;
-                    ui.displayCoinData(coin.symbol, coinData);
-                    const cacheKey = `coinData_${coin.symbol}`;
-                    cache.set(cacheKey, coinData);
-                } else {
-                    //console.warn(`No data found for ${coin.symbol}`);
-                }
-            }
-        } catch (error) {
-            //console.error('Error loading all coin data:', error);
-            ui.displayErrorMessage('Failed to load coin data. Please try refreshing the page.');
-        } finally {
-            //console.log('All coin data loaded');
+  onLoad: async () => {
+    console.log('App onLoad event triggered');
+    ui.showLoader();
+    try {
+      volumeToggle.init();
+      await app.updateBTCPrice();
+      const chartContainer = document.getElementById('coin-chart');
+      if (chartContainer) {
+        chartModule.initChart();
+        chartModule.showChartLoader();
+      }
+      
+      console.log('Loading all coin data...');
+      await app.loadAllCoinData();
+      
+      if (chartModule.chart) {
+        config.currentResolution = 'day';
+        await chartModule.updateChart('BTC');
+        app.updateResolutionButtons('BTC');
+      }
+      ui.setActiveContainer('btc-container');
+      
+      app.setupEventListeners();
+      app.initializeSelectImages();
+      app.initAutoRefresh();
+      
+    } catch (error) {
+      ui.displayErrorMessage('Failed to initialize the dashboard. Please try refreshing the page.');
+    } finally {
+      ui.hideLoader();
+      if (chartModule.chart) {
+        chartModule.hideChartLoader();
+      }
+      console.log('App onLoad completed');
+    }
+  },
+
+  loadAllCoinData: async () => {
+    try {
+      const allCoinData = await api.fetchCoinGeckoDataXHR();
+      if (allCoinData.error) {
+        throw new Error(allCoinData.error);
+      }
+
+      for (const coin of config.coins) {
+        const coinData = allCoinData[coin.symbol.toLowerCase()];
+        if (coinData) {
+          coinData.displayName = coin.displayName || coin.symbol;
+          ui.displayCoinData(coin.symbol, coinData);
+          const cacheKey = `coinData_${coin.symbol}`;
+          cache.set(cacheKey, coinData);
         }
-    },
-  
+      }
+    } catch (error) {
+      ui.displayErrorMessage('Failed to load coin data. Please try refreshing the page.');
+    }
+  },
+
   loadCoinData: async (coin) => {
-    //console.log(`Loading data for ${coin.symbol}...`);
     const cacheKey = `coinData_${coin.symbol}`;
     let cachedData = cache.get(cacheKey);
     let data;
     if (cachedData) {
-      //console.log(`Using cached data for ${coin.symbol}`);
       data = cachedData.value;
     } else {
       try {
@@ -1014,11 +1105,9 @@ const app = {
         if (data.error) {
           throw new Error(data.error);
         }
-        //console.log(`Caching new data for ${coin.symbol}`);
         cache.set(cacheKey, data);
         cachedData = null;
       } catch (error) {
-        //console.error(`Error fetching ${coin.symbol} data:`, error.message);
         data = {
           error: error.message
         };
@@ -1028,16 +1117,13 @@ const app = {
     }
     ui.displayCoinData(coin.symbol, data);
     ui.updateLoadTimeAndCache(0, cachedData);
-    //console.log(`Data loaded for ${coin.symbol}`);
   },
-  
+
   setupEventListeners: () => {
-    //console.log('Setting up event listeners...');
     config.coins.forEach(coin => {
       const container = document.getElementById(`${coin.symbol.toLowerCase()}-container`);
       if (container) {
-        container.addEventListener('click', () => {
-          //console.log(`${coin.symbol} container clicked`);
+        app.addEventListenerWithCleanup(container, 'click', () => {
           ui.setActiveContainer(`${coin.symbol.toLowerCase()}-container`);
           if (chartModule.chart) {
             if (coin.symbol === 'WOW') {
@@ -1048,30 +1134,31 @@ const app = {
           }
         });
       }
-    });     
+    });
     
     const refreshAllButton = document.getElementById('refresh-all');
     if (refreshAllButton) {
-      refreshAllButton.addEventListener('click', app.refreshAllData);
+      app.addEventListenerWithCleanup(refreshAllButton, 'click', app.refreshAllData);
     }
     
     const headers = document.querySelectorAll('th');
     headers.forEach((header, index) => {
-      header.addEventListener('click', () => app.sortTable(index, header.classList.contains('disabled')));
+      app.addEventListenerWithCleanup(header, 'click', () => 
+        app.sortTable(index, header.classList.contains('disabled'))
+      );
     });
     
     const closeErrorButton = document.getElementById('close-error');
     if (closeErrorButton) {
-      closeErrorButton.addEventListener('click', ui.hideErrorMessage);
+      app.addEventListenerWithCleanup(closeErrorButton, 'click', ui.hideErrorMessage);
     }
-    //console.log('Event listeners set up');
   },
 
   initAutoRefresh: () => {
     console.log('Initializing auto-refresh...');
     const toggleAutoRefreshButton = document.getElementById('toggle-auto-refresh');
     if (toggleAutoRefreshButton) {
-      toggleAutoRefreshButton.addEventListener('click', app.toggleAutoRefresh);
+      app.addEventListenerWithCleanup(toggleAutoRefreshButton, 'click', app.toggleAutoRefresh);
       app.updateAutoRefreshButton();
     }
 
@@ -1100,7 +1187,6 @@ const app = {
             earliestExpiration = Math.min(earliestExpiration, cachedItem.expiresAt);
           }
         } catch (error) {
-          //console.error(`Error parsing cached item ${key}:`, error);
           localStorage.removeItem(key);
         }
       }
@@ -1125,67 +1211,58 @@ const app = {
     localStorage.setItem('nextRefreshTime', app.nextRefreshTime.toString());
     app.updateNextRefreshTime();
   },
-  
-    refreshAllData: async () => {
-        if (app.isRefreshing) {
-            console.log('Refresh already in progress, skipping...');
-            return;
+
+  refreshAllData: async () => {
+    if (app.isRefreshing) {
+      console.log('Refresh already in progress, skipping...');
+      return;
+    }
+
+    console.log('Refreshing all data...');
+    app.isRefreshing = true;
+    ui.showLoader();
+    chartModule.showChartLoader();
+    
+    try {
+      cache.clear();
+      await app.updateBTCPrice();
+      
+      const allCoinData = await api.fetchCoinGeckoDataXHR();
+      if (allCoinData.error) {
+        throw new Error(allCoinData.error);
+      }
+      
+      for (const coin of config.coins) {
+        const symbol = coin.symbol.toLowerCase();
+        const coinData = allCoinData[symbol];
+        if (coinData) {
+          coinData.displayName = coin.displayName || coin.symbol;
+          ui.displayCoinData(coin.symbol, coinData);
+          const cacheKey = `coinData_${coin.symbol}`;
+          cache.set(cacheKey, coinData);
         }
+      }
+      
+      if (chartModule.currentCoin) {
+        await chartModule.updateChart(chartModule.currentCoin, true);
+      }
+      
+      app.lastRefreshedTime = new Date();
+      localStorage.setItem('lastRefreshedTime', app.lastRefreshedTime.getTime().toString());
+      ui.updateLastRefreshedTime();
+      
+    } catch (error) {
+      ui.displayErrorMessage('Failed to refresh all data. Please try again.');
+    } finally {
+      ui.hideLoader();
+      chartModule.hideChartLoader();
+      app.isRefreshing = false;
+      if (app.isAutoRefreshEnabled) {
+        app.scheduleNextRefresh();
+      }
+    }
+  },
 
-        console.log('Refreshing all data...');
-        app.isRefreshing = true;
-        ui.showLoader();
-        chartModule.showChartLoader();
-        
-        try {
-
-            cache.clear();
-            
-            await app.updateBTCPrice();
-            
-            const allCoinData = await api.fetchCoinGeckoDataXHR();
-            if (allCoinData.error) {
-                throw new Error(allCoinData.error);
-            }
-            
-            for (const coin of config.coins) {
-                const symbol = coin.symbol.toLowerCase();
-                const coinData = allCoinData[symbol];
-                if (coinData) {
-                    coinData.displayName = coin.displayName || coin.symbol;
-
-                    ui.displayCoinData(coin.symbol, coinData);
-
-                    const cacheKey = `coinData_${coin.symbol}`;
-                    cache.set(cacheKey, coinData);
-                } else {
-                    //console.error(`No data found for ${coin.symbol}`);
-                }
-            }
-            
-            if (chartModule.currentCoin) {
-                await chartModule.updateChart(chartModule.currentCoin, true);
-            }
-            
-            app.lastRefreshedTime = new Date();
-            localStorage.setItem('lastRefreshedTime', app.lastRefreshedTime.getTime().toString());
-            ui.updateLastRefreshedTime();
-            
-            console.log('All data refreshed successfully');
-            
-        } catch (error) {
-            //console.error('Error refreshing all data:', error);
-            ui.displayErrorMessage('Failed to refresh all data. Please try again.');
-        } finally {
-            ui.hideLoader();
-            chartModule.hideChartLoader();
-            app.isRefreshing = false;
-            if (app.isAutoRefreshEnabled) {
-                app.scheduleNextRefresh();
-            }
-        }
-    },
-  
   updateNextRefreshTime: () => {
     console.log('Updating next refresh time display');
     const nextRefreshSpan = document.getElementById('next-refresh-time');
@@ -1215,6 +1292,7 @@ const app = {
             app.updateNextRefreshTimeRAF = requestAnimationFrame(updateDisplay);
           }
         };
+        
         updateDisplay();
       } else {
         labelElement.textContent = '';
@@ -1241,7 +1319,6 @@ const app = {
   },
 
   startSpinAnimation: () => {
-    //console.log('Starting spin animation on auto-refresh button');
     const svg = document.querySelector('#toggle-auto-refresh svg');
     if (svg) {
       svg.classList.add('animate-spin');
@@ -1252,7 +1329,6 @@ const app = {
   },
 
   stopSpinAnimation: () => {
-    //console.log('Stopping spin animation on auto-refresh button');
     const svg = document.querySelector('#toggle-auto-refresh svg');
     if (svg) {
       svg.classList.remove('animate-spin');
@@ -1260,14 +1336,13 @@ const app = {
   },
 
   updateLastRefreshedTime: () => {
-    //console.log('Updating last refreshed time');
     const lastRefreshedElement = document.getElementById('last-refreshed-time');
     if (lastRefreshedElement && app.lastRefreshedTime) {
       const formattedTime = app.lastRefreshedTime.toLocaleTimeString();
       lastRefreshedElement.textContent = `Last Refreshed: ${formattedTime}`;
     }
   },
-  
+
   loadLastRefreshedTime: () => {
     console.log('Loading last refreshed time from storage');
     const storedTime = localStorage.getItem('lastRefreshedTime');
@@ -1276,136 +1351,127 @@ const app = {
       ui.updateLastRefreshedTime();
     }
   },
-  
-    updateBTCPrice: async () => {
-        //console.log('Updating BTC price...');
-        try {
-            const priceData = await api.fetchCoinGeckoDataXHR();
-            if (priceData.error) {
-                //console.error('Error fetching BTC price:', priceData.error);
-                app.btcPriceUSD = 0;
-            } else if (priceData.btc && priceData.btc.current_price) {
 
-                app.btcPriceUSD = priceData.btc.current_price;
-            } else {
-                //console.error('Unexpected BTC data structure:', priceData);
-                app.btcPriceUSD = 0;
-            }
-        } catch (error) {
-            //console.error('Error fetching BTC price:', error);
-            app.btcPriceUSD = 0;
-        }
-        //console.log('Current BTC price:', app.btcPriceUSD);
-    },
-  
-sortTable: (columnIndex) => {
-  //console.log(`Sorting column: ${columnIndex}`);
-  const sortableColumns = [0, 5, 6, 7]; // 0: Time, 5: Rate, 6: Market +/-, 7: Trade
-  if (!sortableColumns.includes(columnIndex)) {
-    //console.log(`Column ${columnIndex} is not sortable`);
-    return;
-  }
-  const table = document.querySelector('table');
-  if (!table) {
-    //console.error("Table not found for sorting.");
-    return;
-  }
-  const rows = Array.from(table.querySelectorAll('tbody tr'));
-  console.log(`Found ${rows.length} rows to sort`);
-  const sortIcon = document.getElementById(`sort-icon-${columnIndex}`);
-  if (!sortIcon) {
-    //console.error("Sort icon not found.");
-    return;
-  }
-  const sortOrder = sortIcon.textContent === '↓' ? 1 : -1;
-  sortIcon.textContent = sortOrder === 1 ? '↑' : '↓';
-
-  const getSafeTextContent = (element) => element ? element.textContent.trim() : '';
-
-  rows.sort((a, b) => {
-    let aValue, bValue;
-    switch (columnIndex) {
-      case 1: // Time column
-        aValue = getSafeTextContent(a.querySelector('td:first-child .text-xs:first-child'));
-        bValue = getSafeTextContent(b.querySelector('td:first-child .text-xs:first-child'));
-        //console.log(`Comparing times: "${aValue}" vs "${bValue}"`);
-
-        const parseTime = (timeStr) => {
-          const [value, unit] = timeStr.split(' ');
-          const numValue = parseFloat(value);
-          switch(unit) {
-            case 'seconds': return numValue;
-            case 'minutes': return numValue * 60;
-            case 'hours': return numValue * 3600;
-            case 'days': return numValue * 86400;
-            default: return 0;
-          }
-        };
-        return (parseTime(bValue) - parseTime(aValue)) * sortOrder;
-      
-      case 5: // Rate
-      case 6: // Market +/-
-        aValue = getSafeTextContent(a.cells[columnIndex]);
-        bValue = getSafeTextContent(b.cells[columnIndex]);
-        //console.log(`Comparing values: "${aValue}" vs "${bValue}"`);
-
-        aValue = parseFloat(aValue.replace(/[^\d.-]/g, '') || '0');
-        bValue = parseFloat(bValue.replace(/[^\d.-]/g, '') || '0');
-        return (aValue - bValue) * sortOrder;
-      
-      case 7: // Trade
-        const aCell = a.cells[columnIndex];
-        const bCell = b.cells[columnIndex];
-        //console.log('aCell:', aCell ? aCell.outerHTML : 'null');
-        //console.log('bCell:', bCell ? bCell.outerHTML : 'null');
-        
-        aValue = getSafeTextContent(aCell.querySelector('a')) || 
-                 getSafeTextContent(aCell.querySelector('button')) || 
-                 getSafeTextContent(aCell);
-        bValue = getSafeTextContent(bCell.querySelector('a')) || 
-                 getSafeTextContent(bCell.querySelector('button')) || 
-                 getSafeTextContent(bCell);
-        
-        aValue = aValue.toLowerCase();
-        bValue = bValue.toLowerCase();
-        
-        //console.log(`Comparing trade actions: "${aValue}" vs "${bValue}"`);
-        
-        if (aValue === bValue) return 0;
-        if (aValue === "swap") return -1 * sortOrder;
-        if (bValue === "swap") return 1 * sortOrder;
-        return aValue.localeCompare(bValue) * sortOrder;
-      
-      default:
-        aValue = getSafeTextContent(a.cells[columnIndex]);
-        bValue = getSafeTextContent(b.cells[columnIndex]);
-        //console.log(`Comparing default values: "${aValue}" vs "${bValue}"`);
-        return aValue.localeCompare(bValue, undefined, {
-          numeric: true,
-          sensitivity: 'base'
-        }) * sortOrder;
+  updateBTCPrice: async () => {
+    try {
+      const priceData = await api.fetchCoinGeckoDataXHR();
+      if (priceData.error) {
+        app.btcPriceUSD = 0;
+      } else if (priceData.btc && priceData.btc.current_price) {
+        app.btcPriceUSD = priceData.btc.current_price;
+      } else {
+        app.btcPriceUSD = 0;
+      }
+    } catch (error) {
+      app.btcPriceUSD = 0;
     }
-  });
+  },
+
+  sortTable: (columnIndex) => {
+    const sortableColumns = [0, 5, 6, 7]; // 0: Time, 5: Rate, 6: Market +/-, 7: Trade
+    if (!sortableColumns.includes(columnIndex)) {
+      return;
+    }
+    
+    const table = document.querySelector('table');
+    if (!table) {
+      return;
+    }
+    
+    const rows = Array.from(table.querySelectorAll('tbody tr'));
+    const sortIcon = document.getElementById(`sort-icon-${columnIndex}`);
+    if (!sortIcon) {
+      return;
+    }
+    
+    const sortOrder = sortIcon.textContent === '↓' ? 1 : -1;
+    sortIcon.textContent = sortOrder === 1 ? '↑' : '↓';
+
+    const getSafeTextContent = (element) => element ? element.textContent.trim() : '';
+
+    rows.sort((a, b) => {
+      let aValue, bValue;
+      switch (columnIndex) {
+        case 1: // Time column
+          aValue = getSafeTextContent(a.querySelector('td:first-child .text-xs:first-child'));
+          bValue = getSafeTextContent(b.querySelector('td:first-child .text-xs:first-child'));
+
+          const parseTime = (timeStr) => {
+            const [value, unit] = timeStr.split(' ');
+            const numValue = parseFloat(value);
+            switch(unit) {
+              case 'seconds': return numValue;
+              case 'minutes': return numValue * 60;
+              case 'hours': return numValue * 3600;
+              case 'days': return numValue * 86400;
+              default: return 0;
+            }
+          };
+          return (parseTime(bValue) - parseTime(aValue)) * sortOrder;
+        
+        case 5: // Rate
+        case 6: // Market +/-
+          aValue = getSafeTextContent(a.cells[columnIndex]);
+          bValue = getSafeTextContent(b.cells[columnIndex]);
+
+          aValue = parseFloat(aValue.replace(/[^\d.-]/g, '') || '0');
+          bValue = parseFloat(bValue.replace(/[^\d.-]/g, '') || '0');
+          return (aValue - bValue) * sortOrder;
+        
+        case 7: // Trade
+          const aCell = a.cells[columnIndex];
+          const bCell = b.cells[columnIndex];
+          
+          aValue = getSafeTextContent(aCell.querySelector('a')) || 
+                   getSafeTextContent(aCell.querySelector('button')) || 
+                   getSafeTextContent(aCell);
+          bValue = getSafeTextContent(bCell.querySelector('a')) || 
+                   getSafeTextContent(bCell.querySelector('button')) || 
+                   getSafeTextContent(bCell);
+          
+          aValue = aValue.toLowerCase();
+          bValue = bValue.toLowerCase();
+          
+          if (aValue === bValue) return 0;
+          if (aValue === "swap") return -1 * sortOrder;
+          if (bValue === "swap") return 1 * sortOrder;
+          return aValue.localeCompare(bValue) * sortOrder;
+        
+        default:
+          aValue = getSafeTextContent(a.cells[columnIndex]);
+          bValue = getSafeTextContent(b.cells[columnIndex]);
+          return aValue.localeCompare(bValue, undefined, {
+            numeric: true,
+            sensitivity: 'base'
+          }) * sortOrder;
+      }
+    });
+
+    const tbody = table.querySelector('tbody');
+    if (tbody) {
+      const fragment = document.createDocumentFragment();
+      rows.forEach(row => fragment.appendChild(row));
+      tbody.appendChild(fragment);
+    }
+  },
 
-  const tbody = table.querySelector('tbody');
-  if (tbody) {
-    rows.forEach(row => tbody.appendChild(row));
-  } else {
-    //console.error("Table body not found.");
-  }
-  //console.log('Sorting completed');
-},
-  
   initializeSelectImages: () => {
     const updateSelectedImage = (selectId) => {
       const select = document.getElementById(selectId);
       const button = document.getElementById(`${selectId}_button`);
       if (!select || !button) {
-        //console.error(`Elements not found for ${selectId}`);
         return;
       }
+
+      const oldListener = select.getAttribute('data-change-listener');
+      if (oldListener && window[oldListener]) {
+        select.removeEventListener('change', window[oldListener]);
+        delete window[oldListener];
+      }
+
       const selectedOption = select.options[select.selectedIndex];
       const imageURL = selectedOption?.getAttribute('data-image');
+
       requestAnimationFrame(() => {
         if (imageURL) {
           button.style.backgroundImage = `url('${imageURL}')`;
@@ -1419,46 +1485,50 @@ sortTable: (columnIndex) => {
         button.style.minHeight = '25px';
       });
     };
-    const handleSelectChange = (event) => {
-      updateSelectedImage(event.target.id);
-    };
+
     ['coin_to', 'coin_from'].forEach(selectId => {
       const select = document.getElementById(selectId);
       if (select) {
-        select.addEventListener('change', handleSelectChange);
+
+        const listenerName = `selectChangeListener_${selectId}`;
+        window[listenerName] = () => updateSelectedImage(selectId);
+
+        select.setAttribute('data-change-listener', listenerName);
+
+        select.addEventListener('change', window[listenerName]);
+
         updateSelectedImage(selectId);
-      } else {
-        //console.error(`Select element not found for ${selectId}`);
       }
     });
   },
 
-updateResolutionButtons: (coinSymbol) => {
-  const resolutionButtons = document.querySelectorAll('.resolution-button');
-  resolutionButtons.forEach(button => {
-    const resolution = button.id.split('-')[1];
-    if (coinSymbol === 'WOW') {
-      if (resolution === 'day') {
-        button.classList.remove('text-gray-400', 'cursor-not-allowed', 'opacity-50', 'outline-none');
-        button.classList.add('active');
-        button.disabled = false;
+  updateResolutionButtons: (coinSymbol) => {
+    const resolutionButtons = document.querySelectorAll('.resolution-button');
+    resolutionButtons.forEach(button => {
+      const resolution = button.id.split('-')[1];
+      if (coinSymbol === 'WOW') {
+        if (resolution === 'day') {
+          button.classList.remove('text-gray-400', 'cursor-not-allowed', 'opacity-50', 'outline-none');
+          button.classList.add('active');
+          button.disabled = false;
+        } else {
+          button.classList.add('text-gray-400', 'cursor-not-allowed', 'opacity-50', 'outline-none');
+          button.classList.remove('active');
+          button.disabled = true;
+        }
       } else {
-        button.classList.add('text-gray-400', 'cursor-not-allowed', 'opacity-50', 'outline-none');
-        button.classList.remove('active');
-        button.disabled = true;
+        button.classList.remove('text-gray-400', 'cursor-not-allowed', 'opacity-50', 'outline-none');
+        button.classList.toggle('active', resolution === config.currentResolution);
+        button.disabled = false;
       }
-    } else {
-      button.classList.remove('text-gray-400', 'cursor-not-allowed', 'opacity-50', 'outline-none');
-      button.classList.toggle('active', resolution === config.currentResolution);
-      button.disabled = false;
-    }
-  });
-},
-  
- toggleAutoRefresh: () => {
+    });
+  },
+
+  toggleAutoRefresh: () => {
     console.log('Toggling auto-refresh');
     app.isAutoRefreshEnabled = !app.isAutoRefreshEnabled;
     localStorage.setItem('autoRefreshEnabled', app.isAutoRefreshEnabled.toString());
+    
     if (app.isAutoRefreshEnabled) {
       console.log('Auto-refresh enabled, scheduling next refresh');
       app.scheduleNextRefresh();
@@ -1471,31 +1541,18 @@ updateResolutionButtons: (coinSymbol) => {
       app.nextRefreshTime = null;
       localStorage.removeItem('nextRefreshTime');
     }
+    
     app.updateAutoRefreshButton();
     app.updateNextRefreshTime();
   }
 };
 
-const resolutionButtons = document.querySelectorAll('.resolution-button');
-resolutionButtons.forEach(button => {
-  button.addEventListener('click', () => {
-    const resolution = button.id.split('-')[1];
-    const currentCoin = chartModule.currentCoin;
-    
-    if (currentCoin !== 'WOW' || resolution === 'day') {
-      config.currentResolution = resolution;
-      chartModule.updateChart(currentCoin, true);
-      app.updateResolutionButtons(currentCoin);
-    }
-  });
-});
 
 // LOAD
 app.init();
+app.visibilityCleanup = app.setupVisibilityHandler();
 
-document.addEventListener('visibilitychange', () => {
-    if (!document.hidden && chartModule.chart) {
-        console.log('Page became visible, reinitializing chart');
-        chartModule.updateChart(chartModule.currentCoin, true);
-    }
+window.addEventListener('beforeunload', () => {
+  console.log('Page unloading, cleaning up...');
+  app.cleanup();
 });