diff --git a/public/analytics.js b/public/analytics.js index b1d44b24..db4b4de1 100644 --- a/public/analytics.js +++ b/public/analytics.js @@ -648,33 +648,33 @@ const maxCount = Math.max(d[1] || 0, d[2] || 0, d[3] || 0, 1); el.innerHTML = ` -
-

Hash Size Distribution

-

${total.toLocaleString()} packets with path hops

-
- ${[1, 2, 3].map(size => { - const count = d[size] || 0; - const width = Math.max((count / maxCount) * 100, count ? 2 : 0); - const colors = { 1: '#ef4444', 2: '#22c55e', 3: '#3b82f6' }; - return `
+
+
+

Hash Size Distribution

+

${total.toLocaleString()} packets with path hops

+
+ ${[1, 2, 3].map(size => { + const count = d[size] || 0; + const width = Math.max((count / maxCount) * 100, count ? 2 : 0); + const colors = { 1: '#ef4444', 2: '#22c55e', 3: '#3b82f6' }; + return `
${size}-byte (${size * 8}-bit, ${Math.pow(256, size).toLocaleString()} IDs)
${count.toLocaleString()} (${pct(count)}%)
`; - }).join('')} + }).join('')} +
-
- -

📈 Hash Size Over Time

${renderHashTimeline(data.hourly)}
-
-

Multi-Byte Hash Adopters

-

Nodes advertising with 2+ byte hash paths

+
+
+

Multi-Byte Hash Adopters

+

Nodes advertising with 2+ byte hash paths

${data.multiByteNodes.length ? ` @@ -688,10 +688,10 @@
NodeHash SizeAdvertsLast Seen
` : '
No multi-byte adopters found
'} -
+
-
-

Top Path Hops

+
+

Top Path Hops

@@ -706,6 +706,7 @@ }).join('')}
HopNodeBytesAppearances
+
`; } diff --git a/public/style.css b/public/style.css index d75c5958..c6247bbf 100644 --- a/public/style.css +++ b/public/style.css @@ -998,10 +998,13 @@ button.ch-item.ch-item-encrypted .ch-badge { filter: grayscale(0.6); } .node-activity-time { color: var(--text-muted); white-space: nowrap; min-width: 70px; font-size: 12px; } /* Analytics page */ -.analytics-page { padding: 16px; max-width: 900px; margin: 0 auto; overflow-y: auto; height: 100%; } +.analytics-page { padding: 16px 24px; max-width: 1600px; margin: 0 auto; overflow-y: auto; height: 100%; } .analytics-header { margin-bottom: 20px; } .analytics-header h2 { margin: 0 0 4px; } .analytics-card { background: var(--card-bg); border: 1px solid var(--border); border-radius: 8px; padding: 16px; margin-bottom: 16px; } +.analytics-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); gap: 16px; margin-bottom: 16px; } +.analytics-grid .analytics-card { margin-bottom: 0; } +.analytics-full { grid-column: 1 / -1; } .analytics-card h3 { margin: 0 0 8px; font-size: 15px; } .analytics-table { width: 100%; border-collapse: collapse; font-size: 13px; } .analytics-table th { text-align: left; padding: 8px; border-bottom: 2px solid var(--border); font-size: 12px; text-transform: uppercase; color: var(--text-muted); }