diff --git a/public/hop-display.js b/public/hop-display.js
index 543582e..86da802 100644
--- a/public/hop-display.js
+++ b/public/hop-display.js
@@ -81,9 +81,13 @@ window.HopDisplay = (function() {
const regionalConflicts = conflicts.filter(c => c.regional);
const badgeCount = regionalConflicts.length > 0 ? regionalConflicts.length : (globalFallback ? conflicts.length : 0);
const conflictData = escapeHtml(JSON.stringify({ h, conflicts, globalFallback }));
- const warnBadge = badgeCount > 1
+ const conflictBadge = badgeCount > 1
? ` `
: '';
+ const unreliableBadge = unreliable
+ ? ' '
+ : '';
+ const warnBadge = conflictBadge + unreliableBadge;
const cls = [
'hop',
diff --git a/public/style.css b/public/style.css
index 70f6181..db9c5d7 100644
--- a/public/style.css
+++ b/public/style.css
@@ -1437,7 +1437,9 @@ button.ch-item.ch-item-encrypted .ch-badge { filter: grayscale(0.6); }
.hop-conflict-name { font-weight: 600; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hop-conflict-dist { font-size: 11px; color: var(--text-muted); font-family: var(--mono); white-space: nowrap; }
.hop-conflict-pk { font-size: 10px; color: var(--text-muted); font-family: var(--mono); }
-.hop-unreliable { opacity: 0.5; text-decoration: line-through; }
+.hop-unreliable { opacity: 0.85; }
+.hop-unreliable-btn { background: none; border: none; color: var(--status-yellow, #f59e0b); font-size: 13px;
+ cursor: help; vertical-align: middle; margin-left: 2px; padding: 0 2px; line-height: 1; }
.hop-global-fallback { border-bottom: 1px dashed var(--status-red); }
.hop-current { font-weight: 700 !important; color: var(--accent) !important; }
diff --git a/test-frontend-helpers.js b/test-frontend-helpers.js
index 8327df5..3c06ba9 100644
--- a/test-frontend-helpers.js
+++ b/test-frontend-helpers.js
@@ -6198,6 +6198,62 @@ console.log('\n=== analytics.js: renderCollisionsFromServer collision table ==='
});
}
+// ===== #872 — hop-display unreliable badge =====
+{
+ console.log('\n--- #872: hop-display unreliable warning badge ---');
+
+ function makeHopDisplaySandbox() {
+ const sb = {
+ window: { addEventListener: () => {}, dispatchEvent: () => {} },
+ document: {
+ readyState: 'complete',
+ createElement: () => ({ id: '', textContent: '', innerHTML: '' }),
+ head: { appendChild: () => {} },
+ getElementById: () => null,
+ addEventListener: () => {},
+ querySelectorAll: () => [],
+ querySelector: () => null,
+ },
+ console,
+ Date, Math, Array, Object, String, Number, JSON, RegExp, Map, Set,
+ encodeURIComponent, parseInt, parseFloat, isNaN, Infinity, NaN, undefined,
+ setTimeout: () => {}, setInterval: () => {}, clearTimeout: () => {}, clearInterval: () => {},
+ };
+ sb.window.document = sb.document;
+ sb.self = sb.window;
+ sb.globalThis = sb.window;
+ const ctx = vm.createContext(sb);
+ const hopSrc = fs.readFileSync(__dirname + '/public/hop-display.js', 'utf8');
+ vm.runInContext(hopSrc, ctx);
+ return ctx;
+ }
+
+ const hopCtx = makeHopDisplaySandbox();
+
+ test('#872: unreliable hop renders warning badge, not strikethrough', () => {
+ const html = hopCtx.window.HopDisplay.renderHop('AABB', {
+ name: 'TestNode', pubkey: 'pk123', unreliable: true,
+ ambiguous: false, conflicts: [], globalFallback: false,
+ }, {});
+ // Must contain unreliable warning badge button
+ assert.ok(html.includes('hop-unreliable-btn'), 'should have unreliable badge button');
+ assert.ok(html.includes('⚠️'), 'should have ⚠️ icon');
+ assert.ok(html.includes('Unreliable name resolution'), 'should have tooltip text');
+ // Must NOT contain line-through in inline style (CSS class no longer has it)
+ assert.ok(!html.includes('line-through'), 'should not contain line-through');
+ // Should still have hop-unreliable class for subtle styling
+ assert.ok(html.includes('hop-unreliable'), 'should have hop-unreliable class');
+ });
+
+ test('#872: reliable hop does NOT render unreliable badge', () => {
+ const html = hopCtx.window.HopDisplay.renderHop('CCDD', {
+ name: 'GoodNode', pubkey: 'pk456', unreliable: false,
+ ambiguous: false, conflicts: [], globalFallback: false,
+ }, {});
+ assert.ok(!html.includes('hop-unreliable-btn'), 'should not have unreliable badge');
+ });
+}
+
// ===== SUMMARY =====
Promise.allSettled(pendingTests).then(() => {
console.log(`\n${'═'.repeat(40)}`);