diff --git a/public/nodes.js b/public/nodes.js
index eda0367f..b3ceb6cd 100644
--- a/public/nodes.js
+++ b/public/nodes.js
@@ -119,7 +119,8 @@
body.innerHTML = `
${escapeHtml(n.name || '(unnamed)')}
-
${n.role} ${n.hash_size ? `${n.public_key.slice(0, n.hash_size * 2).toUpperCase()} ` : ''} ${n.hash_size_inconsistent ? '⚠️ hash mismatch ' : ''} ${statusLabel}
+
${n.role} ${n.hash_size ? `${n.public_key.slice(0, n.hash_size * 2).toUpperCase()} ` : ''} ${n.hash_size_inconsistent ? `⚠️ hash mismatch ` : ''} ${statusLabel}
+ ${n.hash_size_inconsistent ? `
This node has sent adverts with different hash sizes (${(n.hash_sizes_seen||[]).join('-byte, ')}-byte ). Likely a firmware bug in MeshCore versions before 1.14.1. Update firmware to fix.
` : ''}
${n.public_key}
📋 Copy URL
@@ -143,7 +144,7 @@
${stats.avgSnr != null ? `
Avg SNR ${stats.avgSnr.toFixed(1)} dB ` : ''}
${stats.avgHops ? `
Avg Hops ${stats.avgHops} ` : ''}
${hasLoc ? `
Location ${n.lat.toFixed(5)}, ${n.lon.toFixed(5)} ` : ''}
-
Hash Prefix ${n.hash_size ? '' + n.public_key.slice(0, n.hash_size * 2).toUpperCase() + ' (' + n.hash_size + '-byte)' : 'Unknown'}${n.hash_size_inconsistent ? ' ⚠️ inconsistent — possible firmware bug ' : ''}
+
Hash Prefix ${n.hash_size ? '' + n.public_key.slice(0, n.hash_size * 2).toUpperCase() + ' (' + n.hash_size + '-byte)' : 'Unknown'}${n.hash_size_inconsistent ? ' ⚠️ varies ' : ''}
${observers.length ? `
@@ -503,10 +504,11 @@
panel.innerHTML = `
${escapeHtml(n.name || '(unnamed)')}
-
${n.role} ${n.hash_size ? `
${n.public_key.slice(0, n.hash_size * 2).toUpperCase()} ` : ''} ${n.hash_size_inconsistent ? '
⚠️ hash mismatch ' : ''} ${statusLabel}
+
${n.role} ${n.hash_size ? `
${n.public_key.slice(0, n.hash_size * 2).toUpperCase()} ` : ''} ${n.hash_size_inconsistent ? `
⚠️ hash mismatch ` : ''} ${statusLabel}
🔍 Details
📊 Analytics
+ ${n.hash_size_inconsistent ? `
Adverts show hash sizes ${(n.hash_sizes_seen||[]).join('-byte, ')}-byte . Likely a firmware bug — update to MeshCore 1.14.1+.
` : ''}
${hasLoc ? `