Files
explorer-monorepo/frontend/public/index.html
defiQUG ed86d01e1d feat(frontend): explorer SPA and index updates; env verification report
- Expand explorer-spa.js and index.html for Chain 138 explorer UX
- Refresh ENV_VERIFICATION_REPORT.md

Made-with: Cursor
2026-03-24 18:11:08 -07:00

1303 lines
60 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<!-- CSP: unsafe-eval required by ethers.js v5 UMD from CDN (uses new Function for ABI). Our code avoids eval/string setTimeout. Can be removed when moving to ethers v6 build (no UMD eval). -->
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.jsdelivr.net https://unpkg.com https://cdnjs.cloudflare.com; style-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com; font-src 'self' https://cdnjs.cloudflare.com; img-src 'self' data: https:; connect-src 'self' https://explorer.d-bis.org https://rpc-http-pub.d-bis.org wss://rpc-ws-pub.d-bis.org http://192.168.11.221:8545 ws://192.168.11.221:8546;">
<title>SolaceScanScout | The Defi Oracle Meta Explorer | d-bis.org</title>
<meta name="description" content="SolaceScanScout - The Defi Oracle Meta Explorer. Comprehensive blockchain explorer for ChainID 138 with cross-chain bridge monitoring, WETH utilities, and real-time transaction tracking.">
<meta name="keywords" content="blockchain explorer, ChainID 138, CCIP bridge, WETH, DeFi Oracle, SolaceScanScout, blockchain, ethereum, blockscout">
<meta name="author" content="SolaceScanScout">
<meta name="application-name" content="SolaceScanScout">
<meta name="theme-color" content="#667eea">
<script>
(function(){function t(){var e=document.getElementById('navLinks'),n=document.getElementById('navToggle'),r=document.getElementById('navToggleIcon');if(e&&n){var o=e.classList.toggle('nav-open');n.setAttribute('aria-expanded',o?'true':'false');if(r)r.className=o?'fas fa-times':'fas fa-bars';}}function c(){var e=document.getElementById('navLinks'),n=document.getElementById('navToggle'),r=document.getElementById('navToggleIcon');if(e)e.classList.remove('nav-open');if(n)n.setAttribute('aria-expanded','false');if(r)r.className='fas fa-bars';}window.toggleNavMenu=t;window.closeNavMenu=c;})();
</script>
<!-- Open Graph / Facebook -->
<meta property="og:type" content="website">
<meta property="og:url" content="https://explorer.d-bis.org/">
<meta property="og:title" content="SolaceScanScout - The Defi Oracle Meta Explorer">
<meta property="og:description" content="Comprehensive blockchain explorer for ChainID 138 with cross-chain bridge monitoring and WETH utilities.">
<meta property="og:image" content="https://explorer.d-bis.org/og-image.png">
<meta property="og:site_name" content="SolaceScanScout">
<!-- Twitter -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:url" content="https://explorer.d-bis.org/">
<meta name="twitter:title" content="SolaceScanScout - The Defi Oracle Meta Explorer">
<meta name="twitter:description" content="Comprehensive blockchain explorer for ChainID 138 with cross-chain bridge monitoring and WETH utilities.">
<meta name="twitter:image" content="https://explorer.d-bis.org/og-image.png">
<!-- Favicon -->
<link rel="icon" type="image/x-icon" href="/favicon.ico">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<!-- Load ethers.js with multiple fallback CDNs -->
<script>
(function() {
var ethersLoaded = false;
var cdnIndex = 0;
var cdns = [
'https://cdn.jsdelivr.net/npm/ethers@5.7.2/dist/ethers.umd.min.js',
'https://unpkg.com/ethers@5.7.2/dist/ethers.umd.min.js',
'https://cdnjs.cloudflare.com/ajax/libs/ethers/5.7.2/ethers.umd.min.js'
];
function loadEthers() {
if (ethersLoaded || typeof ethers !== 'undefined') {
window.ethersReady = true;
console.log('✅ Ethers.js library loaded successfully');
window.dispatchEvent(new Event('ethersReady'));
return;
}
if (cdnIndex >= cdns.length) {
console.error('❌ All ethers.js CDNs failed to load');
// Try one more time with a different approach
setTimeout(function() {
if (typeof ethers === 'undefined') {
console.error('Ethers.js failed to load from all sources');
} else {
window.ethersReady = true;
window.dispatchEvent(new Event('ethersReady'));
}
}, 1000);
return;
}
var script = document.createElement('script');
script.src = cdns[cdnIndex];
script.async = false; // Load synchronously to ensure it's available
script.onload = function() {
// Double check after load
setTimeout(function() {
if (typeof ethers !== 'undefined') {
ethersLoaded = true;
window.ethersReady = true;
console.log('✅ Ethers.js loaded from:', cdns[cdnIndex]);
window.dispatchEvent(new Event('ethersReady'));
} else {
console.warn('Script loaded but ethers not defined, trying next CDN...');
cdnIndex++;
loadEthers();
}
}, 100);
};
script.onerror = function() {
console.warn('Failed to load from:', cdns[cdnIndex]);
cdnIndex++;
loadEthers();
};
document.head.appendChild(script);
}
// Start loading immediately
loadEthers();
// Also check periodically in case it loads via another method
var checkInterval = setInterval(function() {
if (typeof ethers !== 'undefined' && !ethersLoaded) {
clearInterval(checkInterval);
ethersLoaded = true;
window.ethersReady = true;
console.log('✅ Ethers.js detected');
window.dispatchEvent(new Event('ethersReady'));
}
}, 100);
// Clear interval after 20 seconds
setTimeout(function() {
clearInterval(checkInterval);
}, 20000);
})();
</script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
:root {
--primary: #667eea;
--secondary: #764ba2;
--success: #10b981;
--warning: #f59e0b;
--danger: #ef4444;
--bridge-blue: #3b82f6;
--dark: #1f2937;
--light: #f9fafb;
--border: #e5e7eb;
--text: #111827;
--text-light: #6b7280;
}
body.dark-theme {
--light: #111827;
--border: #374151;
--text: #f9fafb;
--text-light: #9ca3af;
background: #0f172a;
color: var(--text);
}
body.dark-theme .stat-card,
body.dark-theme .card,
body.dark-theme .block-card {
background: #1e293b;
box-shadow: 0 2px 8px rgba(0,0,0,0.3);
}
body.dark-theme .table th { background: #334155; color: var(--text); }
body.dark-theme .table tr:hover { background: #1e293b; }
body.dark-theme .skeleton { background: linear-gradient(90deg, #334155 25%, #475569 50%, #334155 75%); }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
background: var(--light);
color: var(--text);
line-height: 1.6;
}
.navbar {
background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%);
color: white;
padding: 1rem 2rem;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
position: sticky;
top: 0;
z-index: 1000;
}
.nav-container {
max-width: 1400px;
margin: 0 auto;
display: flex;
justify-content: space-between;
align-items: center;
}
.logo {
font-size: 1.5rem;
font-weight: bold;
display: flex;
align-items: center;
gap: 0.5rem;
}
.nav-links {
display: flex;
gap: 0.5rem;
list-style: none;
align-items: center;
}
.nav-links > li { position: relative; }
.nav-links a, .nav-dropdown-trigger {
color: white;
text-decoration: none;
transition: opacity 0.2s;
display: inline-flex;
align-items: center;
gap: 0.35rem;
}
.nav-links a:hover, .nav-dropdown-trigger:hover { opacity: 0.9; }
.nav-dropdown-trigger {
background: none;
border: none;
cursor: pointer;
font: inherit;
padding: 0.5rem 0.25rem;
}
.nav-dropdown-trigger i.fa-chevron-down {
font-size: 0.7rem;
transition: transform 0.2s;
}
.nav-dropdown.open .nav-dropdown-trigger i.fa-chevron-down { transform: rotate(180deg); }
.nav-dropdown-menu {
position: absolute;
top: 100%;
left: 0;
min-width: 200px;
background: rgba(30, 41, 59, 0.98);
border-radius: 8px;
box-shadow: 0 10px 40px rgba(0,0,0,0.25);
padding: 0.5rem 0;
list-style: none;
opacity: 0;
visibility: hidden;
transform: translateY(-6px);
transition: opacity 0.2s, transform 0.2s, visibility 0.2s;
z-index: 1001;
margin-top: 0.25rem;
}
.nav-dropdown.open .nav-dropdown-menu {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
.nav-dropdown-menu a {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.6rem 1rem;
color: rgba(255,255,255,0.95);
white-space: nowrap;
}
.nav-dropdown-menu a:hover {
background: rgba(255,255,255,0.1);
opacity: 1;
}
.nav-dropdown-menu li { margin: 0; }
.search-box {
flex: 1;
max-width: 600px;
margin: 0 2rem;
}
.search-input {
width: 100%;
padding: 0.75rem 1rem;
border: none;
border-radius: 8px;
font-size: 1rem;
background: rgba(255,255,255,0.2);
color: white;
backdrop-filter: blur(10px);
}
.search-input::placeholder { color: rgba(255,255,255,0.7); }
.search-input:focus {
outline: none;
background: rgba(255,255,255,0.3);
}
.container {
max-width: 1400px;
margin: 0 auto;
padding: 2rem;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1rem;
margin-bottom: 1rem;
}
.stat-card {
background: white;
padding: 1rem;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
transition: transform 0.2s, box-shadow 0.2s;
}
/* Block animation */
@keyframes blockPulse {
0%, 100% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.02); opacity: 0.95; }
}
@keyframes slideInFromTop {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.table tbody tr {
animation: slideInFromTop 0.3s ease-out;
}
.table tbody tr.new-block {
animation: blockPulse 1s ease-in-out;
background: rgba(74, 144, 226, 0.05);
}
.table tbody tr.new-transaction {
animation: slideInFromTop 0.5s ease-out;
background: rgba(74, 144, 226, 0.05);
}
/* Horizontal scrolling blocks */
.blocks-scroll-container {
display: flex;
overflow-x: hidden;
overflow-y: hidden;
gap: 1rem;
padding: 0.5rem 0;
scroll-behavior: smooth;
-webkit-overflow-scrolling: touch;
scrollbar-width: none;
position: relative;
width: 100%;
}
.blocks-scroll-container::-webkit-scrollbar {
display: none;
}
.blocks-scroll-content {
display: flex;
gap: 1rem;
will-change: transform;
}
.blocks-scroll-container::-webkit-scrollbar {
height: 8px;
}
.blocks-scroll-container::-webkit-scrollbar-track {
background: var(--light);
border-radius: 4px;
}
.blocks-scroll-container::-webkit-scrollbar-thumb {
background: var(--primary);
border-radius: 4px;
}
.blocks-scroll-container::-webkit-scrollbar-thumb:hover {
background: var(--primary-dark);
}
.block-card {
min-width: 200px;
max-width: 200px;
background: white;
border-radius: 8px;
padding: 1rem;
box-shadow: 0 2px 6px rgba(0,0,0,0.1);
cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s;
border: 2px solid transparent;
flex-shrink: 0;
}
.block-card:hover {
transform: translateY(-4px);
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
border-color: var(--primary);
}
.block-card.new-block {
animation: blockPulse 1s ease-in-out;
border-color: var(--primary);
background: rgba(74, 144, 226, 0.05);
}
.block-number {
font-size: 1.25rem;
font-weight: bold;
color: var(--primary);
margin-bottom: 0.5rem;
}
.block-hash {
font-size: 0.75rem;
color: var(--text-light);
font-family: monospace;
margin-bottom: 0.5rem;
word-break: break-all;
}
.block-info {
display: flex;
flex-direction: column;
gap: 0.25rem;
font-size: 0.875rem;
}
.block-info-item {
display: flex;
justify-content: space-between;
color: var(--text);
}
.block-info-label {
color: var(--text-light);
font-size: 0.75rem;
}
.block-info-value {
font-weight: 600;
color: var(--text);
}
.stat-card:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}
.stat-card.bridge-card {
border-left: 4px solid var(--bridge-blue);
}
.stat-label {
color: var(--text-light);
font-size: 0.875rem;
text-transform: uppercase;
letter-spacing: 0.5px;
margin-bottom: 0.5rem;
}
.stat-value {
font-size: 2rem;
font-weight: bold;
color: var(--primary);
}
.stat-value.bridge-value {
color: var(--bridge-blue);
}
.card {
background: white;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
padding: 1.25rem;
margin-bottom: 1rem;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 0.75rem;
padding-bottom: 0.75rem;
border-bottom: 2px solid var(--border);
}
.card-title {
font-size: 1.5rem;
font-weight: bold;
color: var(--text);
}
.tabs {
display: flex;
gap: 1rem;
margin-bottom: 1.5rem;
border-bottom: 2px solid var(--border);
flex-wrap: wrap;
}
.tab {
padding: 1rem 1.5rem;
background: none;
border: none;
cursor: pointer;
font-size: 1rem;
color: var(--text-light);
border-bottom: 3px solid transparent;
transition: all 0.2s;
}
.tab.active {
color: var(--primary);
border-bottom-color: var(--primary);
font-weight: 600;
}
.bridge-tab.active {
color: var(--bridge-blue);
border-bottom-color: var(--bridge-blue);
}
.weth-tab.active {
color: var(--success);
border-bottom-color: var(--success);
}
.table {
width: 100%;
border-collapse: collapse;
}
.table th {
text-align: left;
padding: 0.5rem 0.75rem;
background: var(--light);
font-weight: 600;
color: var(--text);
border-bottom: 2px solid var(--border);
font-size: 0.875rem;
}
.table td {
padding: 0.5rem 0.75rem;
border-bottom: 1px solid var(--border);
font-size: 0.875rem;
}
.table tr:hover { background: var(--light); }
.hash {
font-family: 'Courier New', monospace;
font-size: 0.875rem;
color: var(--primary);
word-break: break-all;
}
.hash:hover { text-decoration: underline; cursor: pointer; }
.badge {
display: inline-block;
padding: 0.25rem 0.75rem;
border-radius: 20px;
font-size: 0.875rem;
font-weight: 600;
}
.badge-success { background: #d1fae5; color: var(--success); }
.badge-warning { background: #fef3c7; color: var(--warning); }
.badge-danger { background: #fee2e2; color: var(--danger); }
.badge-chain {
background: #dbeafe;
color: var(--bridge-blue);
}
.loading {
text-align: center;
padding: 3rem;
color: var(--text-light);
}
.loading i {
font-size: 2rem;
animation: spin 1s linear infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
/* Skeleton Loaders */
.skeleton {
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: loading 1.5s ease-in-out infinite;
border-radius: 4px;
}
@keyframes loading {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
.skeleton-text {
height: 1em;
margin: 0.5rem 0;
}
.skeleton-title {
height: 1.5em;
width: 60%;
margin-bottom: 1rem;
}
.skeleton-table-row {
height: 3rem;
margin: 0.5rem 0;
}
/* Breadcrumb Navigation */
.breadcrumb {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 1rem 0;
margin-bottom: 1rem;
font-size: 0.9rem;
}
.breadcrumb a {
color: var(--primary);
text-decoration: none;
transition: opacity 0.2s;
}
.breadcrumb a:hover {
opacity: 0.7;
}
.breadcrumb-separator {
color: var(--text-light);
}
.breadcrumb-current {
color: var(--text);
font-weight: 600;
}
.error {
background: #fee2e2;
color: var(--danger);
padding: 1rem;
border-radius: 8px;
margin: 1rem 0;
}
.success {
background: #d1fae5;
color: var(--success);
padding: 1rem;
border-radius: 8px;
margin: 1rem 0;
}
.bridge-chain-card {
background: linear-gradient(135deg, #dbeafe 0%, #bfdbfe 100%);
padding: 1.5rem;
border-radius: 12px;
margin-bottom: 1rem;
}
.weth-card {
background: linear-gradient(135deg, #d1fae5 0%, #a7f3d0 100%);
padding: 1.5rem;
border-radius: 12px;
margin-bottom: 1.5rem;
}
.weth-form {
background: white;
padding: 1.5rem;
border-radius: 8px;
margin-top: 1rem;
}
.form-group {
margin-bottom: 1.5rem;
}
.form-label {
display: block;
margin-bottom: 0.5rem;
font-weight: 600;
color: var(--text);
}
.form-input {
width: 100%;
padding: 0.75rem;
border: 2px solid var(--border);
border-radius: 8px;
font-size: 1rem;
transition: border-color 0.2s;
}
.form-input:focus {
outline: none;
border-color: var(--primary);
}
.form-input-group {
display: flex;
gap: 0.5rem;
}
.form-input-group .form-input {
flex: 1;
}
.btn {
padding: 0.75rem 1.5rem;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 1rem;
font-weight: 600;
transition: all 0.2s;
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
.btn-primary {
background: var(--primary);
color: white;
}
.btn-primary:hover { background: var(--secondary); }
.btn-bridge {
background: var(--bridge-blue);
color: white;
}
.btn-bridge:hover { background: #2563eb; }
.btn-success {
background: var(--success);
color: white;
}
.btn-success:hover { background: #059669; }
.btn-warning {
background: var(--warning);
color: white;
}
.btn-warning:hover { background: #d97706; }
.btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.btn-add-token-wallet {
padding: 0.35rem 0.5rem;
margin-left: 0.35rem;
border: none;
border-radius: 6px;
background: var(--primary);
color: white;
cursor: pointer;
display: inline-flex;
align-items: center;
justify-content: center;
vertical-align: middle;
transition: background 0.2s;
}
.btn-add-token-wallet:hover {
background: var(--secondary);
}
.btn-add-token-wallet:focus {
outline: 2px solid var(--primary);
outline-offset: 2px;
}
.btn-add-token-wallet-prominent {
padding: 0.6rem 1rem;
font-size: 1rem;
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
.balance-display {
background: var(--light);
padding: 1rem;
border-radius: 8px;
margin-bottom: 1rem;
}
.balance-row {
display: flex;
justify-content: space-between;
padding: 0.5rem 0;
border-bottom: 1px solid var(--border);
}
.balance-row:last-child {
border-bottom: none;
}
.balance-label {
color: var(--text-light);
}
.balance-value {
font-weight: bold;
color: var(--text);
}
.chain-name {
font-size: 1.25rem;
font-weight: bold;
color: var(--bridge-blue);
margin-bottom: 0.5rem;
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
.chain-info {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 1rem;
margin-top: 1rem;
}
.chain-stat {
font-size: 0.875rem;
}
.chain-stat-label {
color: var(--text-light);
}
.chain-stat-value {
font-weight: bold;
color: var(--text);
margin-top: 0.25rem;
}
.detail-view {
display: none;
}
.detail-view.active { display: block; }
.info-row {
display: flex;
padding: 1rem;
border-bottom: 1px solid var(--border);
}
.info-label {
font-weight: 600;
min-width: 200px;
color: var(--text-light);
}
.info-value {
flex: 1;
word-break: break-all;
}
.metamask-status {
padding: 1rem;
border-radius: 8px;
margin-bottom: 1rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
.metamask-status.connected {
background: #d1fae5;
color: var(--success);
}
.metamask-status.disconnected {
background: #fee2e2;
color: var(--danger);
}
.nav-toggle { display: none; background: none; border: none; color: white; padding: 0.5rem; cursor: pointer; font-size: 1.5rem; }
.nav-toggle:focus { outline: 2px solid rgba(255,255,255,0.5); }
@media (max-width: 900px) {
.nav-toggle { display: block; }
.nav-links { display: none; flex-direction: column; align-items: stretch; position: absolute; top: 100%; left: 0; right: 0; background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%); padding: 1rem; gap: 0; box-shadow: 0 4px 12px rgba(0,0,0,0.15); z-index: 999; }
.nav-links.nav-open { display: flex; }
.nav-container { position: relative; flex-wrap: wrap; }
.nav-dropdown { position: static; }
.nav-dropdown-menu { position: static; opacity: 1; visibility: visible; transform: none; background: rgba(0,0,0,0.2); border-radius: 6px; margin: 0.25rem 0 0 0.5rem; padding: 0.25rem 0; max-height: 0; overflow: hidden; transition: max-height 0.2s; }
.nav-dropdown.open .nav-dropdown-menu { max-height: 400px; }
.nav-dropdown-trigger { width: 100%; justify-content: space-between; padding: 0.6rem 0.5rem; }
}
@media (max-width: 768px) {
.nav-container { flex-direction: column; gap: 1rem; align-items: stretch; }
.search-box { max-width: 100%; margin: 0; }
.nav-links { flex-wrap: wrap; justify-content: center; }
}
#gasNetworkContent { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
@media (max-width: 600px) {
#gasNetworkContent { grid-template-columns: 1fr; }
}
.btn-copy { background: none; border: none; cursor: pointer; padding: 0.25rem; margin-left: 0.35rem; color: var(--text-light); vertical-align: middle; }
.btn-copy:hover { color: var(--primary); }
</style>
</head>
<body>
<script>
(function() {
function doToggleNav() {
var links = document.getElementById('navLinks');
var btn = document.getElementById('navToggle');
var icon = document.getElementById('navToggleIcon');
if (!links || !btn) return;
var isOpen = links.classList.toggle('nav-open');
btn.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
if (icon) icon.className = isOpen ? 'fas fa-times' : 'fas fa-bars';
}
function doCloseNav() {
var links = document.getElementById('navLinks');
var btn = document.getElementById('navToggle');
var icon = document.getElementById('navToggleIcon');
if (links) links.classList.remove('nav-open');
if (btn) btn.setAttribute('aria-expanded', 'false');
if (icon) icon.className = 'fas fa-bars';
}
window.toggleNavMenu = doToggleNav;
window.closeNavMenu = doCloseNav;
document.addEventListener('click', function(e) {
if (e.target.closest('#navToggle')) { doToggleNav(); }
});
})();
</script>
<nav class="navbar">
<div class="nav-container">
<div class="logo">
<i class="fas fa-cube"></i>
<div style="display: flex; flex-direction: column; gap: 0.25rem;">
<span>SolaceScanScout</span>
<span style="font-size: 0.75rem; font-weight: normal; opacity: 0.9;">The Defi Oracle Meta Explorer</span>
</div>
</div>
<div class="search-box" style="display: flex; gap: 0.5rem;">
<label for="searchInput" class="sr-only">Search blockchain explorer</label>
<input type="text" class="search-input" id="searchInput" placeholder="Address, tx hash, block number, or token/contract name..." aria-label="Search blockchain explorer" aria-describedby="search-help-text" style="flex: 1;">
<button id="searchBtn" class="btn btn-primary" style="padding: 0.5rem 1rem; white-space: nowrap;" aria-label="Search">
<i class="fas fa-search"></i>
</button>
<span id="search-help-text" class="sr-only">Search by address (0x...40 hex), transaction hash (0x...64 hex), block number, or token/contract name</span>
</div>
<button type="button" class="nav-toggle" id="navToggle" aria-label="Toggle menu" aria-expanded="false"><i class="fas fa-bars" id="navToggleIcon"></i></button>
<ul class="nav-links" id="navLinks">
<li class="nav-dropdown" id="navDropdownExplore">
<button type="button" class="nav-dropdown-trigger" aria-expanded="false" aria-haspopup="true" aria-controls="navMenuExplore" id="navTriggerExplore"><i class="fas fa-compass" aria-hidden="true"></i> <span data-i18n="explore">Explore</span> <i class="fas fa-chevron-down" aria-hidden="true"></i></button>
<ul class="nav-dropdown-menu" id="navMenuExplore" role="menu">
<li role="none"><a href="/home" role="menuitem" onclick="event.preventDefault(); showHome(); updatePath('/home'); closeNavMenu();" aria-label="Navigate to home page"><i class="fas fa-home" aria-hidden="true"></i> <span data-i18n="home">Home</span></a></li>
<li role="none"><a href="/blocks" role="menuitem" onclick="event.preventDefault(); showBlocks(); updatePath('/blocks'); closeNavMenu();" aria-label="View all blocks"><i class="fas fa-cubes" aria-hidden="true"></i> <span data-i18n="blocks">Blocks</span></a></li>
<li role="none"><a href="/transactions" role="menuitem" onclick="event.preventDefault(); showTransactions(); updatePath('/transactions'); closeNavMenu();" aria-label="View all transactions"><i class="fas fa-exchange-alt" aria-hidden="true"></i> <span data-i18n="transactions">Transactions</span></a></li>
</ul>
</li>
<li class="nav-dropdown" id="navDropdownTools">
<button type="button" class="nav-dropdown-trigger" aria-expanded="false" aria-haspopup="true" aria-controls="navMenuTools" id="navTriggerTools"><i class="fas fa-tools" aria-hidden="true"></i> <span data-i18n="tools">Tools</span> <i class="fas fa-chevron-down" aria-hidden="true"></i></button>
<ul class="nav-dropdown-menu" id="navMenuTools" role="menu">
<li role="none"><a href="/bridge" role="menuitem" onclick="event.preventDefault(); showBridgeMonitoring(); updatePath('/bridge'); closeNavMenu();" aria-label="View bridge monitoring"><i class="fas fa-bridge" aria-hidden="true"></i> <span data-i18n="bridge">Bridge</span></a></li>
<li role="none"><a href="/weth" role="menuitem" onclick="event.preventDefault(); showWETHUtilities(); updatePath('/weth'); closeNavMenu();" aria-label="View WETH utilities"><i class="fas fa-coins" aria-hidden="true"></i> <span data-i18n="weth">WETH</span></a></li>
<li role="none"><a href="/tokens" role="menuitem" onclick="event.preventDefault(); if(typeof showTokensList==='function')showTokensList();else focusSearchWithHint('token'); updatePath('/tokens'); closeNavMenu();" aria-label="View token list"><i class="fas fa-tag" aria-hidden="true"></i> <span data-i18n="tokens">Tokens</span></a></li>
<li role="none"><a href="/pools" role="menuitem" onclick="event.preventDefault(); showPools(); updatePath('/pools'); closeNavMenu();" aria-label="View pools"><i class="fas fa-water" aria-hidden="true"></i> <span data-i18n="pools">Pools</span></a></li>
<li role="none"><a href="/watchlist" role="menuitem" onclick="event.preventDefault(); showWatchlist(); updatePath('/watchlist'); closeNavMenu();" aria-label="Watchlist"><i class="fas fa-star" aria-hidden="true"></i> <span data-i18n="watchlist">Watchlist</span></a></li>
</ul>
</li>
<li><a href="/snap/" target="_self" rel="noopener" aria-label="Chain 138 MetaMask Snap"><i class="fas fa-wallet" aria-hidden="true"></i> <span>MetaMask Snap</span></a></li>
<li role="none"><a href="/more" role="menuitem" onclick="event.preventDefault(); showMore(); updatePath('/more'); closeNavMenu();" aria-label="View more pages"><i class="fas fa-ellipsis-h" aria-hidden="true"></i> <span data-i18n="more">More</span></a></li>
</ul>
<div style="display: flex; align-items: center; gap: 0.75rem;">
<select id="localeSelect" onchange="setLocale(this.value)" style="padding: 0.35rem 0.5rem; border-radius: 6px; background: rgba(255,255,255,0.2); color: white; border: 1px solid rgba(255,255,255,0.3); font-size: 0.875rem;" aria-label="Language">
<option value="en">EN</option>
<option value="de">DE</option>
<option value="fr">FR</option>
</select>
<button id="themeToggle" type="button" class="btn btn-primary" onclick="toggleDarkMode()" style="padding: 0.5rem 0.75rem; background: rgba(255,255,255,0.2);" aria-label="Toggle dark mode" title="Toggle dark/light theme"><i class="fas fa-moon" id="themeIcon"></i></button>
<div id="walletConnect" style="display: flex; align-items: center; gap: 0.5rem;">
<button id="walletConnectBtn" class="btn btn-primary" onclick="connectWallet()" style="display: none;" aria-label="Connect wallet">Connect Wallet</button>
<div id="walletStatus" style="display: none; padding: 0.5rem 1rem; background: var(--success); color: white; border-radius: 8px; font-size: 0.875rem;">
<i class="fas fa-wallet"></i> <span id="walletAddress"></span>
</div>
</div>
</div>
</div>
</nav>
<div id="explorerLiveRegion" aria-live="polite" aria-atomic="true" class="sr-only" role="status"></div>
<div class="container" id="mainContent">
<!-- Home View -->
<div id="homeView">
<div class="stats-grid" id="statsGrid">
<!-- Stats loaded dynamically -->
</div>
<div class="card" id="gasNetworkCard" style="margin-bottom: 1rem;">
<div class="card-header">
<h2 class="card-title"><i class="fas fa-gas-pump"></i> Gas &amp; Network</h2>
<button type="button" class="btn btn-secondary" onclick="loadGasAndNetworkStats()" aria-label="Refresh gas and network"><i class="fas fa-sync-alt"></i> Refresh</button>
</div>
<div id="gasNetworkContent">
<div>
<div style="font-size: 0.875rem; color: var(--text-light); margin-bottom: 0.25rem;">Current base fee</div>
<div id="gasCurrentValue" style="font-size: 1.5rem; font-weight: 600;"></div>
<div style="margin-top: 0.75rem; font-size: 0.875rem;">TPS: <span id="gasTpsValue"></span></div>
<div style="font-size: 0.875rem;">Block time: <span id="gasBlockTimeValue"></span></div>
<div style="font-size: 0.875rem; margin-top: 0.25rem;">Failed (recent): <span id="gasFailedRateValue"></span></div>
</div>
<div>
<div style="font-size: 0.875rem; color: var(--text-light); margin-bottom: 0.5rem;">Gas history (last 10 blocks)</div>
<div id="gasHistoryBars" style="display: flex; align-items: flex-end; gap: 4px; height: 60px;"></div>
</div>
</div>
</div>
<div class="card">
<div class="card-header">
<h2 class="card-title">Latest Blocks</h2>
<button class="btn btn-primary" onclick="showBlocks()" aria-label="View all blocks">View All</button>
</div>
<div id="latestBlocks">
<div class="loading"><i class="fas fa-spinner"></i> Loading blocks...</div>
</div>
</div>
<div class="card">
<div class="card-header">
<h2 class="card-title">Latest Transactions</h2>
<button class="btn btn-primary" onclick="showTransactions()" aria-label="View all transactions">View All</button>
</div>
<div id="latestTransactions">
<div class="loading"><i class="fas fa-spinner"></i> Loading transactions...</div>
</div>
</div>
</div>
<!-- WETH Utilities View -->
<div id="wethView" class="detail-view">
<div class="card">
<div class="card-header">
<h2 class="card-title"><i class="fas fa-coins"></i> WETH9 & WETH10 Utilities</h2>
<button class="btn btn-success" onclick="refreshWETHBalances()" aria-label="Refresh WETH balances"><i class="fas fa-sync-alt" aria-hidden="true"></i> Refresh</button>
</div>
<!-- MetaMask Connection Status -->
<div id="metamaskStatus" class="metamask-status disconnected">
<i class="fas fa-wallet"></i>
<span>MetaMask not connected</span>
<button class="btn btn-success" onclick="connectMetaMask()" style="margin-left: auto;" aria-label="Connect MetaMask wallet">Connect MetaMask</button>
</div>
<div class="tabs">
<button class="tab weth-tab active" onclick="showWETHTab('weth9', this)" aria-label="Switch to WETH9 tab" role="tab" aria-selected="true">WETH9</button>
<button class="tab weth-tab" onclick="showWETHTab('weth10', this)" aria-label="Switch to WETH10 tab" role="tab" aria-selected="false">WETH10</button>
<button class="tab weth-tab" onclick="showWETHTab('info', this)" aria-label="Switch to information tab" role="tab" aria-selected="false">Information</button>
</div>
<!-- WETH9 Tab -->
<div id="weth9Tab" class="weth-tab-content">
<div class="weth-card">
<div class="chain-name">WETH9 Token</div>
<div style="color: var(--text-light); margin-bottom: 1rem;">
Contract: <span class="hash" onclick="showAddressDetail('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2')" style="cursor: pointer;">0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2</span>
<button type="button" class="btn-add-token-wallet" onclick="event.stopPropagation(); window.addTokenToWallet && window.addTokenToWallet('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', 'WETH', 18, 'Wrapped Ether');" aria-label="Add WETH9 to wallet" title="Add to wallet"><i class="fas fa-wallet" aria-hidden="true"></i></button>
</div>
<div class="balance-display" id="weth9Balance">
<div class="balance-row">
<span class="balance-label">ETH Balance:</span>
<span class="balance-value" id="weth9EthBalance">-</span>
</div>
<div class="balance-row">
<span class="balance-label">WETH9 Balance:</span>
<span class="balance-value" id="weth9TokenBalance">-</span>
</div>
</div>
<div class="weth-form">
<h3 style="margin-bottom: 1rem;">Wrap ETH → WETH9</h3>
<div class="form-group">
<label for="weth9WrapAmount" class="form-label">Amount (ETH or wei)</label>
<div class="form-input-group">
<input type="text" inputmode="decimal" class="form-input" id="weth9WrapAmount" placeholder="e.g. 100 or 100000000000000000000 (wei)" aria-label="WETH9 wrap amount in ETH or wei">
<button class="btn btn-primary" onclick="setMaxWETH9('wrap')" aria-label="Set maximum WETH9 wrap amount">MAX</button>
</div>
</div>
<button class="btn btn-success" onclick="wrapWETH9()" id="weth9WrapBtn" disabled aria-label="Wrap ETH to WETH9">
<i class="fas fa-arrow-right"></i> Wrap ETH to WETH9
</button>
</div>
<div class="weth-form">
<h3 style="margin-bottom: 1rem;">Unwrap WETH9 → ETH</h3>
<div class="form-group">
<label for="weth9UnwrapAmount" class="form-label">Amount (WETH9 in ETH or wei)</label>
<div class="form-input-group">
<input type="text" inputmode="decimal" class="form-input" id="weth9UnwrapAmount" placeholder="e.g. 100 or 100000000000000000000 (wei)" aria-label="WETH9 unwrap amount in ETH or wei">
<button class="btn btn-primary" onclick="setMaxWETH9('unwrap')" aria-label="Set maximum WETH9 unwrap amount">MAX</button>
</div>
</div>
<button class="btn btn-warning" onclick="unwrapWETH9()" id="weth9UnwrapBtn" disabled aria-label="Unwrap WETH9 to ETH">
<i class="fas fa-arrow-left"></i> Unwrap WETH9 to ETH
</button>
</div>
</div>
</div>
<!-- WETH10 Tab -->
<div id="weth10Tab" class="weth-tab-content" style="display: none;">
<div class="weth-card">
<div class="chain-name">WETH10 Token</div>
<div style="color: var(--text-light); margin-bottom: 1rem;">
Contract: <span class="hash" onclick="showAddressDetail('0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f')" style="cursor: pointer;">0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f</span>
<button type="button" class="btn-add-token-wallet" onclick="event.stopPropagation(); window.addTokenToWallet && window.addTokenToWallet('0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f', 'WETH', 18, 'Wrapped Ether v10');" aria-label="Add WETH10 to wallet" title="Add to wallet"><i class="fas fa-wallet" aria-hidden="true"></i></button>
</div>
<div class="balance-display" id="weth10Balance">
<div class="balance-row">
<span class="balance-label">ETH Balance:</span>
<span class="balance-value" id="weth10EthBalance">-</span>
</div>
<div class="balance-row">
<span class="balance-label">WETH10 Balance:</span>
<span class="balance-value" id="weth10TokenBalance">-</span>
</div>
</div>
<div class="weth-form">
<h3 style="margin-bottom: 1rem;">Wrap ETH → WETH10</h3>
<div class="form-group">
<label for="weth10WrapAmount" class="form-label">Amount (ETH or wei)</label>
<div class="form-input-group">
<input type="text" inputmode="decimal" class="form-input" id="weth10WrapAmount" placeholder="e.g. 100 or 100000000000000000000 (wei)" aria-label="WETH10 wrap amount in ETH or wei">
<button class="btn btn-primary" onclick="setMaxWETH10('wrap')" aria-label="Set maximum WETH10 wrap amount">MAX</button>
</div>
</div>
<button class="btn btn-success" onclick="wrapWETH10()" id="weth10WrapBtn" disabled aria-label="Wrap ETH to WETH10">
<i class="fas fa-arrow-right"></i> Wrap ETH to WETH10
</button>
</div>
<div class="weth-form">
<h3 style="margin-bottom: 1rem;">Unwrap WETH10 → ETH</h3>
<div class="form-group">
<label for="weth10UnwrapAmount" class="form-label">Amount (WETH10 in ETH or wei)</label>
<div class="form-input-group">
<input type="text" inputmode="decimal" class="form-input" id="weth10UnwrapAmount" placeholder="e.g. 100 or 100000000000000000000 (wei)" aria-label="WETH10 unwrap amount in ETH or wei">
<button class="btn btn-primary" onclick="setMaxWETH10('unwrap')" aria-label="Set maximum WETH10 unwrap amount">MAX</button>
</div>
</div>
<button class="btn btn-warning" onclick="unwrapWETH10()" id="weth10UnwrapBtn" disabled aria-label="Unwrap WETH10 to ETH">
<i class="fas fa-arrow-left"></i> Unwrap WETH10 to ETH
</button>
</div>
</div>
</div>
<!-- Information Tab -->
<div id="wethInfoTab" class="weth-tab-content" style="display: none;">
<div class="card">
<h3>About WETH9 and WETH10</h3>
<div style="margin-top: 1rem; line-height: 1.8;">
<p><strong>WETH9</strong> and <strong>WETH10</strong> are wrapped versions of native ETH (Ether) that allow you to use ETH in smart contracts and DeFi protocols.</p>
<h4 style="margin-top: 1.5rem; margin-bottom: 0.5rem;">What is Wrapping?</h4>
<p>Wrapping ETH converts your native ETH into an ERC-20 token (WETH9 or WETH10) that can be used in DeFi applications, smart contracts, and cross-chain bridging.</p>
<h4 style="margin-top: 1.5rem; margin-bottom: 0.5rem;">Contract Addresses</h4>
<ul style="margin-left: 2rem; margin-top: 0.5rem;">
<li><strong>WETH9:</strong> <span class="hash" onclick="showAddressDetail('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2')" style="cursor: pointer;">0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2</span> <button type="button" class="btn-add-token-wallet" onclick="event.stopPropagation(); window.addTokenToWallet && window.addTokenToWallet('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', 'WETH', 18);" aria-label="Add WETH9 to wallet" title="Add to wallet"><i class="fas fa-wallet"></i></button></li>
<li><strong>WETH10:</strong> <span class="hash" onclick="showAddressDetail('0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f')" style="cursor: pointer;">0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f</span> <button type="button" class="btn-add-token-wallet" onclick="event.stopPropagation(); window.addTokenToWallet && window.addTokenToWallet('0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f', 'WETH', 18);" aria-label="Add WETH10 to wallet" title="Add to wallet"><i class="fas fa-wallet"></i></button></li>
</ul>
<h4 style="margin-top: 1.5rem; margin-bottom: 0.5rem;">How to Use</h4>
<ol style="margin-left: 2rem; margin-top: 0.5rem;">
<li>Connect your MetaMask wallet</li>
<li>Select WETH9 or WETH10 tab</li>
<li>Enter the amount to wrap or unwrap</li>
<li>Confirm the transaction in MetaMask</li>
</ol>
<h4 style="margin-top: 1.5rem; margin-bottom: 0.5rem;">Cross-Chain Bridging</h4>
<p>Both WETH9 and WETH10 can be bridged to other chains using the CCIP bridge contracts:</p>
<ul style="margin-left: 2rem; margin-top: 0.5rem;">
<li><strong>WETH9 Bridge:</strong> <span class="hash">0x971cD9D156f193df8051E48043C476e53ECd4693</span></li>
<li><strong>WETH10 Bridge:</strong> <span class="hash">0xe0E93247376aa097dB308B92e6Ba36bA015535D0</span></li>
</ul>
</div>
</div>
</div>
</div>
</div>
<!-- Bridge Monitoring View -->
<div id="bridgeView" class="detail-view">
<div class="card">
<div class="card-header">
<h2 class="card-title"><i class="fas fa-bridge"></i> Bridge Monitoring</h2>
<button class="btn btn-primary" onclick="refreshBridgeData()" aria-label="Refresh bridge data"><i class="fas fa-sync-alt" aria-hidden="true"></i> Refresh</button>
</div>
<div id="bridgeContent">
<div class="loading"><i class="fas fa-spinner"></i> Loading bridge data...</div>
</div>
</div>
</div>
<!-- Other views -->
<div id="blocksView" class="detail-view">
<div class="card">
<div class="card-header">
<h2 class="card-title">All Blocks</h2>
<button type="button" class="btn btn-primary" onclick="exportBlocksCSV()" style="padding: 0.5rem 1rem;"><i class="fas fa-file-csv"></i> Export CSV</button>
</div>
<div id="blocksList">
<div class="loading"><i class="fas fa-spinner"></i> Loading blocks...</div>
</div>
</div>
</div>
<div id="transactionsView" class="detail-view">
<div class="card">
<div class="card-header">
<h2 class="card-title">All Transactions</h2>
<button type="button" class="btn btn-primary" onclick="exportTransactionsListCSV()" style="padding: 0.5rem 1rem;"><i class="fas fa-file-csv"></i> Export CSV</button>
</div>
<div id="transactionsList">
<div class="loading"><i class="fas fa-spinner"></i> Loading transactions...</div>
</div>
</div>
</div>
<div id="blockDetailView" class="detail-view">
<div class="breadcrumb" id="blockDetailBreadcrumb"></div>
<div class="card">
<div class="card-header">
<button class="btn btn-secondary" onclick="showBlocks()" aria-label="Go back to blocks view"><i class="fas fa-arrow-left" aria-hidden="true"></i> Back</button>
<h2 class="card-title">Block Details</h2>
</div>
<div id="blockDetail"></div>
</div>
</div>
<div id="transactionDetailView" class="detail-view">
<div class="breadcrumb" id="transactionDetailBreadcrumb"></div>
<div class="card">
<div class="card-header">
<button class="btn btn-secondary" onclick="showTransactions()" aria-label="Go back to transactions view"><i class="fas fa-arrow-left" aria-hidden="true"></i> Back</button>
<h2 class="card-title">Transaction Details</h2>
</div>
<div id="transactionDetail"></div>
</div>
</div>
<div id="addressDetailView" class="detail-view">
<div class="breadcrumb" id="addressDetailBreadcrumb"></div>
<div class="card">
<div class="card-header">
<button class="btn btn-secondary" onclick="showHome()" aria-label="Go back to home page"><i class="fas fa-arrow-left" aria-hidden="true"></i> Back</button>
<h2 class="card-title">Address Details</h2>
</div>
<div id="addressDetail"></div>
</div>
</div>
<div id="tokenDetailView" class="detail-view">
<div class="breadcrumb" id="tokenDetailBreadcrumb"></div>
<div class="card">
<div class="card-header">
<button class="btn btn-secondary" onclick="showHome()" aria-label="Go back"><i class="fas fa-arrow-left"></i> Back</button>
<h2 class="card-title">Token</h2>
</div>
<div id="tokenDetail"></div>
</div>
</div>
<div id="nftDetailView" class="detail-view">
<div class="breadcrumb" id="nftDetailBreadcrumb"></div>
<div class="card">
<div class="card-header">
<button class="btn btn-secondary" onclick="showHome()" aria-label="Go back"><i class="fas fa-arrow-left"></i> Back</button>
<h2 class="card-title">NFT</h2>
</div>
<div id="nftDetail"></div>
</div>
</div>
<div id="searchResultsView" class="detail-view">
<div class="card">
<div class="card-header">
<button class="btn btn-secondary" onclick="showHome()" aria-label="Go back"><i class="fas fa-arrow-left"></i> Back</button>
<h2 class="card-title">Search results</h2>
</div>
<div id="searchResultsContent"></div>
</div>
</div>
<div id="tokensView" class="detail-view">
<div class="card">
<div class="card-header">
<button class="btn btn-secondary" onclick="showHome()" aria-label="Go back"><i class="fas fa-arrow-left"></i> Back</button>
<h2 class="card-title"><i class="fas fa-coins"></i> Tokens</h2>
</div>
<div id="tokensListContent">
<div class="loading"><i class="fas fa-spinner"></i> Loading...</div>
</div>
</div>
</div>
<div id="watchlistView" class="detail-view">
<div class="breadcrumb" id="watchlistBreadcrumb"><a href="/home">Home</a><span class="breadcrumb-separator">/</span><span class="breadcrumb-current">Watchlist</span></div>
<div class="card">
<div class="card-header">
<button class="btn btn-secondary" onclick="showHome()" aria-label="Go back"><i class="fas fa-arrow-left"></i> Back</button>
<h2 class="card-title"><i class="fas fa-star"></i> Watchlist</h2>
</div>
<div id="watchlistContent">
<p style="color: var(--text-light);">Add addresses from their detail page to track them here.</p>
</div>
</div>
</div>
<div id="poolsView" class="detail-view">
<div class="breadcrumb" id="poolsBreadcrumb"><a href="/home">Home</a><span class="breadcrumb-separator">/</span><span class="breadcrumb-current">Pools</span></div>
<div class="card">
<div class="card-header">
<button class="btn btn-secondary" onclick="showHome()" aria-label="Go back to home page"><i class="fas fa-arrow-left" aria-hidden="true"></i> Back</button>
<h2 class="card-title"><i class="fas fa-water"></i> Pools</h2>
</div>
<div id="poolsContent">
<div class="loading"><i class="fas fa-spinner"></i> Loading pools...</div>
</div>
</div>
</div>
<div id="moreView" class="detail-view">
<div class="breadcrumb" id="moreBreadcrumb"><a href="/home">Home</a><span class="breadcrumb-separator">/</span><span class="breadcrumb-current">More</span></div>
<div class="card">
<div class="card-header">
<button class="btn btn-secondary" onclick="showHome()" aria-label="Go back to home page"><i class="fas fa-arrow-left" aria-hidden="true"></i> Back</button>
<h2 class="card-title"><i class="fas fa-ellipsis-h"></i> More</h2>
</div>
<div id="moreContent">
<div class="loading"><i class="fas fa-spinner"></i> Loading more pages...</div>
</div>
</div>
</div>
<div id="analyticsView" class="detail-view">
<div class="card">
<div class="card-header">
<button class="btn btn-secondary" onclick="showHome()" aria-label="Go back"><i class="fas fa-arrow-left"></i> Back</button>
<h2 class="card-title"><i class="fas fa-chart-line"></i> Analytics Dashboard</h2>
</div>
<div id="analyticsContent">
<p style="color: var(--text-light);">Analytics dashboard (Track 3). Network stats, flow tracking, and bridge analytics coming soon.</p>
</div>
</div>
</div>
<div id="operatorView" class="detail-view">
<div class="card">
<div class="card-header">
<button class="btn btn-secondary" onclick="showHome()" aria-label="Go back"><i class="fas fa-arrow-left"></i> Back</button>
<h2 class="card-title"><i class="fas fa-cog"></i> Operator Panel</h2>
</div>
<div id="operatorContent">
<p style="color: var(--text-light);">Operator panel (Track 4). Configuration and operational controls coming soon.</p>
</div>
</div>
</div>
</div>
<script src="/explorer-spa.js?v=16"></script>
</body>
</html>