mirror of
https://github.com/smittix/intercept.git
synced 2026-07-15 21:18:09 -07:00
Standardize all icons to uniform inline SVG format
Replace emojis throughout the codebase with inline SVG icons using the Icons utility. Remove decorative icons where text labels already describe the content. Add classification dot CSS for risk indicators. - Extend Icons utility with comprehensive SVG icon set - Update navigation, header stats, and action buttons - Update playback controls and volume icons - Remove decorative device type and panel header emojis - Clean up notifications and alert messages - Add CSS for classification status dots Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1354,6 +1354,28 @@
|
|||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Classification Dots - replaces emoji circles for risk levels */
|
||||||
|
.classification-dot {
|
||||||
|
display: inline-block;
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.classification-dot.high {
|
||||||
|
background-color: var(--accent-red);
|
||||||
|
}
|
||||||
|
|
||||||
|
.classification-dot.review {
|
||||||
|
background-color: var(--accent-orange);
|
||||||
|
}
|
||||||
|
|
||||||
|
.classification-dot.info {
|
||||||
|
background-color: var(--accent-green);
|
||||||
|
}
|
||||||
|
|
||||||
/* Device Indicators with Icons */
|
/* Device Indicators with Icons */
|
||||||
.device-indicator-icon {
|
.device-indicator-icon {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
|||||||
@@ -1072,22 +1072,19 @@ const SignalCards = (function() {
|
|||||||
const stats = getAddressStats('meter', msg.id);
|
const stats = getAddressStats('meter', msg.id);
|
||||||
const seenCount = stats ? stats.count : 1;
|
const seenCount = stats ? stats.count : 1;
|
||||||
|
|
||||||
// Determine meter type icon and color
|
// Determine meter type color
|
||||||
let meterIcon = '⚡';
|
|
||||||
let meterTypeClass = 'electric';
|
let meterTypeClass = 'electric';
|
||||||
const meterType = (msg.type || '').toLowerCase();
|
const meterType = (msg.type || '').toLowerCase();
|
||||||
if (meterType.includes('gas')) {
|
if (meterType.includes('gas')) {
|
||||||
meterIcon = '🔥';
|
|
||||||
meterTypeClass = 'gas';
|
meterTypeClass = 'gas';
|
||||||
} else if (meterType.includes('water')) {
|
} else if (meterType.includes('water')) {
|
||||||
meterIcon = '💧';
|
|
||||||
meterTypeClass = 'water';
|
meterTypeClass = 'water';
|
||||||
}
|
}
|
||||||
|
|
||||||
card.innerHTML = `
|
card.innerHTML = `
|
||||||
<div class="signal-card-header">
|
<div class="signal-card-header">
|
||||||
<div class="signal-card-badges">
|
<div class="signal-card-badges">
|
||||||
<span class="signal-proto-badge meter ${meterTypeClass}">${meterIcon} ${escapeHtml(msg.type || 'Meter')}</span>
|
<span class="signal-proto-badge meter ${meterTypeClass}">${escapeHtml(msg.type || 'Meter')}</span>
|
||||||
<span class="signal-freq-badge">ID: ${escapeHtml(msg.id || 'N/A')}</span>
|
<span class="signal-freq-badge">ID: ${escapeHtml(msg.id || 'N/A')}</span>
|
||||||
</div>
|
</div>
|
||||||
${status !== 'baseline' ? `
|
${status !== 'baseline' ? `
|
||||||
|
|||||||
@@ -730,16 +730,17 @@ const SignalTimeline = (function() {
|
|||||||
|
|
||||||
container.style.display = 'block';
|
container.style.display = 'block';
|
||||||
container.innerHTML = recentAnnotations.map(ann => {
|
container.innerHTML = recentAnnotations.map(ann => {
|
||||||
const icons = {
|
const iconFuncs = {
|
||||||
new: '🆕',
|
new: () => Icons.newBadge('icon--sm'),
|
||||||
burst: '⚡',
|
burst: () => Icons.meter('icon--sm'),
|
||||||
pattern: '🔄',
|
pattern: () => Icons.refresh('icon--sm'),
|
||||||
flagged: '🚩',
|
flagged: () => Icons.flag('icon--sm'),
|
||||||
gone: '📴'
|
gone: () => Icons.offline('icon--sm')
|
||||||
};
|
};
|
||||||
|
const iconHtml = iconFuncs[ann.type] ? iconFuncs[ann.type]() : Icons.sensor('icon--sm');
|
||||||
return `
|
return `
|
||||||
<div class="signal-timeline-annotation" data-type="${ann.type}">
|
<div class="signal-timeline-annotation" data-type="${ann.type}">
|
||||||
<span class="signal-timeline-annotation-icon">${icons[ann.type] || '📡'}</span>
|
<span class="signal-timeline-annotation-icon">${iconHtml}</span>
|
||||||
<span>${ann.message}</span>
|
<span>${ann.message}</span>
|
||||||
<span style="margin-left: auto; opacity: 0.6;">${formatTimeAgo(ann.timestamp)}</span>
|
<span style="margin-left: auto; opacity: 0.6;">${formatTimeAgo(ann.timestamp)}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ function isMuted() {
|
|||||||
function updateMuteButton() {
|
function updateMuteButton() {
|
||||||
const btn = document.getElementById('muteBtn');
|
const btn = document.getElementById('muteBtn');
|
||||||
if (btn) {
|
if (btn) {
|
||||||
btn.innerHTML = audioMuted ? '🔇 UNMUTE' : '🔊 MUTE';
|
btn.innerHTML = audioMuted ? Icons.volumeOff('icon--sm') + ' UNMUTE' : Icons.volumeOn('icon--sm') + ' MUTE';
|
||||||
btn.classList.toggle('muted', audioMuted);
|
btn.classList.toggle('muted', audioMuted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -226,7 +226,7 @@ function requestNotificationPermission() {
|
|||||||
Notification.requestPermission().then(permission => {
|
Notification.requestPermission().then(permission => {
|
||||||
notificationsEnabled = permission === 'granted';
|
notificationsEnabled = permission === 'granted';
|
||||||
if (notificationsEnabled && typeof showInfo === 'function') {
|
if (notificationsEnabled && typeof showInfo === 'function') {
|
||||||
showInfo('🔔 Desktop notifications enabled');
|
showInfo('Desktop notifications enabled');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
+144
-93
@@ -277,119 +277,170 @@ function mapRange(value, inMin, inMax, outMin, outMax) {
|
|||||||
// Designed for screenshot legibility - standard symbols only.
|
// Designed for screenshot legibility - standard symbols only.
|
||||||
|
|
||||||
const Icons = {
|
const Icons = {
|
||||||
/**
|
// ===== Signal Type Icons =====
|
||||||
* WiFi icon - standard arc/fan shape
|
|
||||||
*/
|
|
||||||
wifi: function(className) {
|
wifi: function(className) {
|
||||||
return `<span class="icon icon-wifi ${className || ''}" aria-label="WiFi">
|
return `<span class="icon icon-wifi ${className || ''}" aria-label="WiFi"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12.55a11 11 0 0 1 14.08 0"/><path d="M1.42 9a16 16 0 0 1 21.16 0"/><path d="M8.53 16.11a6 6 0 0 1 6.95 0"/><circle cx="12" cy="20" r="1" fill="currentColor" stroke="none"/></svg></span>`;
|
||||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
||||||
<path d="M5 12.55a11 11 0 0 1 14.08 0"/>
|
|
||||||
<path d="M1.42 9a16 16 0 0 1 21.16 0"/>
|
|
||||||
<path d="M8.53 16.11a6 6 0 0 1 6.95 0"/>
|
|
||||||
<circle cx="12" cy="20" r="1" fill="currentColor" stroke="none"/>
|
|
||||||
</svg>
|
|
||||||
</span>`;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Bluetooth icon - standard rune
|
|
||||||
*/
|
|
||||||
bluetooth: function(className) {
|
bluetooth: function(className) {
|
||||||
return `<span class="icon icon-bluetooth ${className || ''}" aria-label="Bluetooth">
|
return `<span class="icon icon-bluetooth ${className || ''}" aria-label="Bluetooth"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6.5 6.5 17.5 17.5 12 22 12 2 17.5 6.5 6.5 17.5"/></svg></span>`;
|
||||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
||||||
<polyline points="6.5 6.5 17.5 17.5 12 22 12 2 17.5 6.5 6.5 17.5"/>
|
|
||||||
</svg>
|
|
||||||
</span>`;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Cellular icon - ascending bars
|
|
||||||
*/
|
|
||||||
cellular: function(className) {
|
cellular: function(className) {
|
||||||
return `<span class="icon icon-cellular ${className || ''}" aria-label="Cellular">
|
return `<span class="icon icon-cellular ${className || ''}" aria-label="Cellular"><svg viewBox="0 0 24 24" fill="currentColor"><rect x="2" y="16" width="4" height="6" rx="1"/><rect x="8" y="12" width="4" height="10" rx="1"/><rect x="14" y="8" width="4" height="14" rx="1"/><rect x="20" y="4" width="4" height="18" rx="1" opacity="0.3"/></svg></span>`;
|
||||||
<svg viewBox="0 0 24 24" fill="currentColor">
|
},
|
||||||
<rect x="2" y="16" width="4" height="6" rx="1"/>
|
radio: function(className) {
|
||||||
<rect x="8" y="12" width="4" height="10" rx="1"/>
|
return `<span class="icon icon-radio ${className || ''}" aria-label="Radio"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 12c0-3 2-6 5-6s4 3 5 6c1 3 2 6 5 6s5-3 5-6"/></svg></span>`;
|
||||||
<rect x="14" y="8" width="4" height="14" rx="1"/>
|
|
||||||
<rect x="20" y="4" width="4" height="18" rx="1" opacity="0.3"/>
|
|
||||||
</svg>
|
|
||||||
</span>`;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
// ===== Mode Icons =====
|
||||||
* Unknown/RF signal - generic wave
|
pager: function(className) {
|
||||||
*/
|
return `<span class="icon icon-pager ${className || ''}" aria-label="Pager"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="5" width="16" height="14" rx="2"/><line x1="8" y1="10" x2="16" y2="10"/><line x1="8" y1="14" x2="12" y2="14"/></svg></span>`;
|
||||||
signalUnknown: function(className) {
|
},
|
||||||
return `<span class="icon icon-signal-unknown ${className || ''}" aria-label="Unknown signal">
|
sensor: function(className) {
|
||||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
|
return `<span class="icon icon-sensor ${className || ''}" aria-label="Sensor"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="2"/><path d="M16.24 7.76a6 6 0 0 1 0 8.49m-8.48-.01a6 6 0 0 1 0-8.49m11.31-2.82a10 10 0 0 1 0 14.14m-14.14 0a10 10 0 0 1 0-14.14"/></svg></span>`;
|
||||||
<path d="M2 12c0-3 2-6 5-6s4 3 5 6c1 3 2 6 5 6s5-3 5-6"/>
|
},
|
||||||
</svg>
|
aircraft: function(className) {
|
||||||
</span>`;
|
return `<span class="icon icon-aircraft ${className || ''}" aria-label="Aircraft"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 16v-2l-8-5V3.5a1.5 1.5 0 0 0-3 0V9l-8 5v2l8-2.5V19l-2 1.5V22l3.5-1 3.5 1v-1.5L13 19v-5.5l8 2.5z"/></svg></span>`;
|
||||||
|
},
|
||||||
|
satellite: function(className) {
|
||||||
|
return `<span class="icon icon-satellite ${className || ''}" aria-label="Satellite"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M13 7L9 3 5 7l4 4"/><path d="m17 11 4 4-4 4-4-4"/><path d="m8 12 4 4 6-6-4-4-6 6"/><path d="m16 8 3-3"/><path d="M9 21a6 6 0 0 0-6-6"/></svg></span>`;
|
||||||
|
},
|
||||||
|
location: function(className) {
|
||||||
|
return `<span class="icon icon-location ${className || ''}" aria-label="Location"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z"/><circle cx="12" cy="10" r="3"/></svg></span>`;
|
||||||
|
},
|
||||||
|
search: function(className) {
|
||||||
|
return `<span class="icon icon-search ${className || ''}" aria-label="Search"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg></span>`;
|
||||||
|
},
|
||||||
|
meter: function(className) {
|
||||||
|
return `<span class="icon icon-meter ${className || ''}" aria-label="Meter"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 12h-4l-3 9L9 3l-3 9H2"/></svg></span>`;
|
||||||
|
},
|
||||||
|
scanner: function(className) {
|
||||||
|
return `<span class="icon icon-scanner ${className || ''}" aria-label="Scanner"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"/><path d="M3 9h18"/><path d="M9 21V9"/></svg></span>`;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
// ===== Status Icons =====
|
||||||
* Recording indicator - filled circle
|
warning: function(className) {
|
||||||
*/
|
return `<span class="icon icon-warning ${className || ''}" aria-label="Warning"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg></span>`;
|
||||||
|
},
|
||||||
|
check: function(className) {
|
||||||
|
return `<span class="icon icon-check ${className || ''}" aria-label="Check"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></span>`;
|
||||||
|
},
|
||||||
|
x: function(className) {
|
||||||
|
return `<span class="icon icon-x ${className || ''}" aria-label="X"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></span>`;
|
||||||
|
},
|
||||||
recording: function(className) {
|
recording: function(className) {
|
||||||
return `<span class="icon icon-recording ${className || ''}" aria-label="Recording">
|
return `<span class="icon icon-recording ${className || ''}" aria-label="Recording"><svg viewBox="0 0 24 24" fill="currentColor"><circle cx="12" cy="12" r="8"/></svg></span>`;
|
||||||
<svg viewBox="0 0 24 24" fill="currentColor">
|
|
||||||
<circle cx="12" cy="12" r="8"/>
|
|
||||||
</svg>
|
|
||||||
</span>`;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Anomaly indicator - filled circle (amber by default via CSS)
|
|
||||||
*/
|
|
||||||
anomaly: function(className) {
|
anomaly: function(className) {
|
||||||
return `<span class="icon icon-anomaly ${className || ''}" aria-label="Anomaly">
|
return `<span class="icon icon-anomaly ${className || ''}" aria-label="Anomaly"><svg viewBox="0 0 24 24" fill="currentColor"><circle cx="12" cy="12" r="6"/></svg></span>`;
|
||||||
<svg viewBox="0 0 24 24" fill="currentColor">
|
},
|
||||||
<circle cx="12" cy="12" r="6"/>
|
flag: function(className) {
|
||||||
</svg>
|
return `<span class="icon icon-flag ${className || ''}" aria-label="Flag"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z"/><line x1="4" y1="22" x2="4" y2="15"/></svg></span>`;
|
||||||
</span>`;
|
},
|
||||||
|
newBadge: function(className) {
|
||||||
|
return `<span class="icon icon-new ${className || ''}" aria-label="New"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg></span>`;
|
||||||
|
},
|
||||||
|
offline: function(className) {
|
||||||
|
return `<span class="icon icon-offline ${className || ''}" aria-label="Offline"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="1" y1="1" x2="23" y2="23"/><path d="M16.72 11.06A10.94 10.94 0 0 1 19 12.55"/><path d="M5 12.55a10.94 10.94 0 0 1 5.17-2.39"/><path d="M10.71 5.05A16 16 0 0 1 22.58 9"/><path d="M1.42 9a15.91 15.91 0 0 1 4.7-2.88"/><path d="M8.53 16.11a6 6 0 0 1 6.95 0"/><line x1="12" y1="20" x2="12.01" y2="20"/></svg></span>`;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
// ===== Device Type Icons =====
|
||||||
* Export icon - arrow out of box
|
user: function(className) {
|
||||||
*/
|
return `<span class="icon icon-user ${className || ''}" aria-label="User"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg></span>`;
|
||||||
export: function(className) {
|
},
|
||||||
return `<span class="icon icon-export ${className || ''}" aria-label="Export">
|
drone: function(className) {
|
||||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
return `<span class="icon icon-drone ${className || ''}" aria-label="Drone"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 12m-3 0a3 3 0 1 0 6 0a3 3 0 1 0 -6 0"/><path d="M3 9a2 2 0 1 0 4 0a2 2 0 1 0 -4 0"/><path d="M17 9a2 2 0 1 0 4 0a2 2 0 1 0 -4 0"/><path d="M3 15a2 2 0 1 0 4 0a2 2 0 1 0 -4 0"/><path d="M17 15a2 2 0 1 0 4 0a2 2 0 1 0 -4 0"/><path d="M9 9l-4 -1"/><path d="M15 9l4 -1"/><path d="M9 15l-4 1"/><path d="M15 15l4 1"/></svg></span>`;
|
||||||
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
|
},
|
||||||
<polyline points="17 8 12 3 7 8"/>
|
military: function(className) {
|
||||||
<line x1="12" y1="3" x2="12" y2="15"/>
|
return `<span class="icon icon-military ${className || ''}" aria-label="Military"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg></span>`;
|
||||||
</svg>
|
},
|
||||||
</span>`;
|
handshake: function(className) {
|
||||||
|
return `<span class="icon icon-handshake ${className || ''}" aria-label="Handshake"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m11 17 2 2a1 1 0 1 0 3-3"/><path d="m14 14 2.5 2.5a1 1 0 1 0 3-3l-3.88-3.88a3 3 0 0 0-4.24 0l-.88.88a1 1 0 1 1-3-3l2.81-2.81a5.79 5.79 0 0 1 7.06-.87l.47.28a2 2 0 0 0 1.42.25L21 4"/><path d="m21 3 1 11h-2"/><path d="M3 3 2 14l6.5 6.5a1 1 0 1 0 3-3"/><path d="M3 4h8"/></svg></span>`;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
// ===== Action Icons =====
|
||||||
* Refresh icon - circular arrows
|
|
||||||
*/
|
|
||||||
refresh: function(className) {
|
refresh: function(className) {
|
||||||
return `<span class="icon icon-refresh ${className || ''}" aria-label="Refresh">
|
return `<span class="icon icon-refresh ${className || ''}" aria-label="Refresh"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="23 4 23 10 17 10"/><polyline points="1 20 1 14 7 14"/><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/></svg></span>`;
|
||||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
},
|
||||||
<polyline points="23 4 23 10 17 10"/>
|
download: function(className) {
|
||||||
<polyline points="1 20 1 14 7 14"/>
|
return `<span class="icon icon-download ${className || ''}" aria-label="Download"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg></span>`;
|
||||||
<path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/>
|
},
|
||||||
</svg>
|
export: function(className) {
|
||||||
</span>`;
|
return `<span class="icon icon-export ${className || ''}" aria-label="Export"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg></span>`;
|
||||||
|
},
|
||||||
|
copy: function(className) {
|
||||||
|
return `<span class="icon icon-copy ${className || ''}" aria-label="Copy"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></span>`;
|
||||||
|
},
|
||||||
|
link: function(className) {
|
||||||
|
return `<span class="icon icon-link ${className || ''}" aria-label="Link"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></span>`;
|
||||||
|
},
|
||||||
|
chart: function(className) {
|
||||||
|
return `<span class="icon icon-chart ${className || ''}" aria-label="Chart"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/></svg></span>`;
|
||||||
|
},
|
||||||
|
star: function(className) {
|
||||||
|
return `<span class="icon icon-star ${className || ''}" aria-label="Star"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg></span>`;
|
||||||
|
},
|
||||||
|
target: function(className) {
|
||||||
|
return `<span class="icon icon-target ${className || ''}" aria-label="Target"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="6"/><circle cx="12" cy="12" r="2"/></svg></span>`;
|
||||||
|
},
|
||||||
|
settings: function(className) {
|
||||||
|
return `<span class="icon icon-settings ${className || ''}" aria-label="Settings"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg></span>`;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
// ===== Playback Controls =====
|
||||||
* Get icon by signal type
|
play: function(className) {
|
||||||
* Maps protocol names to appropriate icons
|
return `<span class="icon icon-play ${className || ''}" aria-label="Play"><svg viewBox="0 0 24 24" fill="currentColor"><polygon points="5 3 19 12 5 21 5 3"/></svg></span>`;
|
||||||
*/
|
},
|
||||||
|
pause: function(className) {
|
||||||
|
return `<span class="icon icon-pause ${className || ''}" aria-label="Pause"><svg viewBox="0 0 24 24" fill="currentColor"><rect x="6" y="4" width="4" height="16"/><rect x="14" y="4" width="4" height="16"/></svg></span>`;
|
||||||
|
},
|
||||||
|
stop: function(className) {
|
||||||
|
return `<span class="icon icon-stop ${className || ''}" aria-label="Stop"><svg viewBox="0 0 24 24" fill="currentColor"><rect x="4" y="4" width="16" height="16" rx="2"/></svg></span>`;
|
||||||
|
},
|
||||||
|
headphones: function(className) {
|
||||||
|
return `<span class="icon icon-headphones ${className || ''}" aria-label="Headphones"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 18v-6a9 9 0 0 1 18 0v6"/><path d="M21 19a2 2 0 0 1-2 2h-1a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2h3zM3 19a2 2 0 0 0 2 2h1a2 2 0 0 0 2-2v-3a2 2 0 0 0-2-2H3z"/></svg></span>`;
|
||||||
|
},
|
||||||
|
volumeOn: function(className) {
|
||||||
|
return `<span class="icon icon-volume-on ${className || ''}" aria-label="Volume On"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/><path d="M19.07 4.93a10 10 0 0 1 0 14.14M15.54 8.46a5 5 0 0 1 0 7.07"/></svg></span>`;
|
||||||
|
},
|
||||||
|
volumeOff: function(className) {
|
||||||
|
return `<span class="icon icon-volume-off ${className || ''}" aria-label="Volume Off"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/><line x1="23" y1="9" x2="17" y2="15"/><line x1="17" y1="9" x2="23" y2="15"/></svg></span>`;
|
||||||
|
},
|
||||||
|
|
||||||
|
// ===== UI Icons =====
|
||||||
|
sun: function(className) {
|
||||||
|
return `<span class="icon icon-sun ${className || ''}" aria-label="Light mode"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></svg></span>`;
|
||||||
|
},
|
||||||
|
moon: function(className) {
|
||||||
|
return `<span class="icon icon-moon ${className || ''}" aria-label="Dark mode"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg></span>`;
|
||||||
|
},
|
||||||
|
arrowDown: function(className) {
|
||||||
|
return `<span class="icon icon-arrow-down ${className || ''}" aria-label="Arrow down"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></svg></span>`;
|
||||||
|
},
|
||||||
|
chevronDown: function(className) {
|
||||||
|
return `<span class="icon icon-chevron-down ${className || ''}" aria-label="Expand"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg></span>`;
|
||||||
|
},
|
||||||
|
chevronRight: function(className) {
|
||||||
|
return `<span class="icon icon-chevron-right ${className || ''}" aria-label="Right"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg></span>`;
|
||||||
|
},
|
||||||
|
chevronLeft: function(className) {
|
||||||
|
return `<span class="icon icon-chevron-left ${className || ''}" aria-label="Left"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg></span>`;
|
||||||
|
},
|
||||||
|
mail: function(className) {
|
||||||
|
return `<span class="icon icon-mail ${className || ''}" aria-label="Mail"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg></span>`;
|
||||||
|
},
|
||||||
|
loader: function(className) {
|
||||||
|
return `<span class="icon icon-loader ${className || ''}" aria-label="Loading"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="2" x2="12" y2="6"/><line x1="12" y1="18" x2="12" y2="22"/><line x1="4.93" y1="4.93" x2="7.76" y2="7.76"/><line x1="16.24" y1="16.24" x2="19.07" y2="19.07"/><line x1="2" y1="12" x2="6" y2="12"/><line x1="18" y1="12" x2="22" y2="12"/><line x1="4.93" y1="19.07" x2="7.76" y2="16.24"/><line x1="16.24" y1="7.76" x2="19.07" y2="4.93"/></svg></span>`;
|
||||||
|
},
|
||||||
|
bell: function(className) {
|
||||||
|
return `<span class="icon icon-bell ${className || ''}" aria-label="Notifications"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/></svg></span>`;
|
||||||
|
},
|
||||||
|
|
||||||
|
// ===== Helper function =====
|
||||||
forSignalType: function(type, className) {
|
forSignalType: function(type, className) {
|
||||||
const t = (type || '').toLowerCase();
|
const t = (type || '').toLowerCase();
|
||||||
if (t.includes('wifi') || t.includes('802.11')) {
|
if (t.includes('wifi') || t.includes('802.11')) return this.wifi(className);
|
||||||
return this.wifi(className);
|
if (t.includes('bluetooth') || t.includes('bt') || t.includes('ble')) return this.bluetooth(className);
|
||||||
}
|
if (t.includes('cellular') || t.includes('lte') || t.includes('gsm') || t.includes('5g')) return this.cellular(className);
|
||||||
if (t.includes('bluetooth') || t.includes('bt') || t.includes('ble')) {
|
return this.radio(className);
|
||||||
return this.bluetooth(className);
|
|
||||||
}
|
|
||||||
if (t.includes('cellular') || t.includes('lte') || t.includes('gsm') || t.includes('5g')) {
|
|
||||||
return this.cellular(className);
|
|
||||||
}
|
|
||||||
return this.signalUnknown(className);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -216,7 +216,7 @@ function startScanner() {
|
|||||||
// Update radio scan button to show STOP
|
// Update radio scan button to show STOP
|
||||||
const radioScanBtn = document.getElementById('radioScanBtn');
|
const radioScanBtn = document.getElementById('radioScanBtn');
|
||||||
if (radioScanBtn) {
|
if (radioScanBtn) {
|
||||||
radioScanBtn.innerHTML = '⏹ STOP';
|
radioScanBtn.innerHTML = Icons.stop('icon--sm') + ' STOP';
|
||||||
radioScanBtn.style.background = 'var(--accent-red)';
|
radioScanBtn.style.background = 'var(--accent-red)';
|
||||||
radioScanBtn.style.borderColor = 'var(--accent-red)';
|
radioScanBtn.style.borderColor = 'var(--accent-red)';
|
||||||
}
|
}
|
||||||
@@ -268,7 +268,7 @@ function stopScanner() {
|
|||||||
const pauseBtn = document.getElementById('scannerPauseBtn');
|
const pauseBtn = document.getElementById('scannerPauseBtn');
|
||||||
if (pauseBtn) {
|
if (pauseBtn) {
|
||||||
pauseBtn.disabled = true;
|
pauseBtn.disabled = true;
|
||||||
pauseBtn.textContent = '⏸ Pause';
|
pauseBtn.innerHTML = Icons.pause('icon--sm') + ' Pause';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update radio scan button
|
// Update radio scan button
|
||||||
@@ -338,7 +338,7 @@ function pauseScanner() {
|
|||||||
.then(data => {
|
.then(data => {
|
||||||
isScannerPaused = !isScannerPaused;
|
isScannerPaused = !isScannerPaused;
|
||||||
const pauseBtn = document.getElementById('scannerPauseBtn');
|
const pauseBtn = document.getElementById('scannerPauseBtn');
|
||||||
if (pauseBtn) pauseBtn.textContent = isScannerPaused ? '▶ Resume' : '⏸ Pause';
|
if (pauseBtn) pauseBtn.innerHTML = isScannerPaused ? Icons.play('icon--sm') + ' Resume' : Icons.pause('icon--sm') + ' Pause';
|
||||||
const statusText = document.getElementById('scannerStatusText');
|
const statusText = document.getElementById('scannerStatusText');
|
||||||
if (statusText) {
|
if (statusText) {
|
||||||
statusText.textContent = isScannerPaused ? 'PAUSED' : 'SCANNING';
|
statusText.textContent = isScannerPaused ? 'PAUSED' : 'SCANNING';
|
||||||
@@ -873,7 +873,7 @@ function startAudio() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('audioStartBtn').textContent = '⏹ Stop Audio';
|
document.getElementById('audioStartBtn').innerHTML = Icons.stop('icon--sm') + ' Stop Audio';
|
||||||
document.getElementById('audioStartBtn').classList.add('active');
|
document.getElementById('audioStartBtn').classList.add('active');
|
||||||
document.getElementById('audioTunedFreq').textContent = frequency.toFixed(2) + ' MHz (' + modulation.toUpperCase() + ')';
|
document.getElementById('audioTunedFreq').textContent = frequency.toFixed(2) + ' MHz (' + modulation.toUpperCase() + ')';
|
||||||
document.getElementById('audioDeviceStatus').textContent = 'SDR ' + device;
|
document.getElementById('audioDeviceStatus').textContent = 'SDR ' + device;
|
||||||
@@ -896,7 +896,7 @@ async function stopAudio() {
|
|||||||
await fetch('/listening/audio/stop', { method: 'POST' });
|
await fetch('/listening/audio/stop', { method: 'POST' });
|
||||||
if (typeof releaseDevice === 'function') releaseDevice('audio');
|
if (typeof releaseDevice === 'function') releaseDevice('audio');
|
||||||
isAudioPlaying = false;
|
isAudioPlaying = false;
|
||||||
document.getElementById('audioStartBtn').textContent = '▶ Play Audio';
|
document.getElementById('audioStartBtn').innerHTML = Icons.play('icon--sm') + ' Play Audio';
|
||||||
document.getElementById('audioStartBtn').classList.remove('active');
|
document.getElementById('audioStartBtn').classList.remove('active');
|
||||||
document.getElementById('audioStatus').textContent = 'STOPPED';
|
document.getElementById('audioStatus').textContent = 'STOPPED';
|
||||||
document.getElementById('audioStatus').style.color = 'var(--text-muted)';
|
document.getElementById('audioStatus').style.color = 'var(--text-muted)';
|
||||||
@@ -1741,7 +1741,7 @@ async function _startDirectListenInternal() {
|
|||||||
|
|
||||||
const listenBtn = document.getElementById('radioListenBtn');
|
const listenBtn = document.getElementById('radioListenBtn');
|
||||||
if (listenBtn) {
|
if (listenBtn) {
|
||||||
listenBtn.innerHTML = '⏳ TUNING...';
|
listenBtn.innerHTML = Icons.loader('icon--sm') + ' TUNING...';
|
||||||
listenBtn.style.background = 'var(--accent-orange)';
|
listenBtn.style.background = 'var(--accent-orange)';
|
||||||
listenBtn.style.borderColor = 'var(--accent-orange)';
|
listenBtn.style.borderColor = 'var(--accent-orange)';
|
||||||
}
|
}
|
||||||
@@ -1879,11 +1879,11 @@ function updateDirectListenUI(isPlaying, freq) {
|
|||||||
|
|
||||||
if (listenBtn) {
|
if (listenBtn) {
|
||||||
if (isPlaying) {
|
if (isPlaying) {
|
||||||
listenBtn.innerHTML = '⏹ STOP';
|
listenBtn.innerHTML = Icons.stop('icon--sm') + ' STOP';
|
||||||
listenBtn.style.background = 'var(--accent-red)';
|
listenBtn.style.background = 'var(--accent-red)';
|
||||||
listenBtn.style.borderColor = 'var(--accent-red)';
|
listenBtn.style.borderColor = 'var(--accent-red)';
|
||||||
} else {
|
} else {
|
||||||
listenBtn.innerHTML = '🎧 LISTEN';
|
listenBtn.innerHTML = Icons.headphones('icon--sm') + ' LISTEN';
|
||||||
listenBtn.style.background = 'var(--accent-purple)';
|
listenBtn.style.background = 'var(--accent-purple)';
|
||||||
listenBtn.style.borderColor = 'var(--accent-purple)';
|
listenBtn.style.borderColor = 'var(--accent-purple)';
|
||||||
}
|
}
|
||||||
|
|||||||
+165
-193
File diff suppressed because it is too large
Load Diff
@@ -9,7 +9,7 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<button class="preset-btn" onclick="refreshWifiInterfaces()" style="width: 100%;">
|
<button class="preset-btn" onclick="refreshWifiInterfaces()" style="width: 100%;">
|
||||||
🔄 Refresh Devices
|
<span class="icon icon--sm"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="23 4 23 10 17 10"/><polyline points="1 20 1 14 7 14"/><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/></svg></span> Refresh Devices
|
||||||
</button>
|
</button>
|
||||||
<div class="info-text" style="margin-top: 8px; display: grid; grid-template-columns: auto auto; gap: 4px 8px; align-items: center;" id="wifiToolStatus">
|
<div class="info-text" style="margin-top: 8px; display: grid; grid-template-columns: auto auto; gap: 4px 8px; align-items: center;" id="wifiToolStatus">
|
||||||
<span>airmon-ng:</span><span class="tool-status missing">Checking...</span>
|
<span>airmon-ng:</span><span class="tool-status missing">Checking...</span>
|
||||||
@@ -71,7 +71,7 @@
|
|||||||
<div class="section">
|
<div class="section">
|
||||||
<h3>Attack Options</h3>
|
<h3>Attack Options</h3>
|
||||||
<div class="info-text" style="color: var(--accent-red); margin-bottom: 10px;">
|
<div class="info-text" style="color: var(--accent-red); margin-bottom: 10px;">
|
||||||
⚠ Only use on authorized networks
|
<span class="icon icon--sm"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg></span> Only use on authorized networks
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>Target BSSID</label>
|
<label>Target BSSID</label>
|
||||||
@@ -92,7 +92,7 @@
|
|||||||
|
|
||||||
<!-- Handshake Capture Status Panel -->
|
<!-- Handshake Capture Status Panel -->
|
||||||
<div class="section" id="captureStatusPanel" style="display: none; border: 1px solid var(--accent-orange); border-radius: 4px; padding: 10px; background: rgba(255, 165, 0, 0.1);">
|
<div class="section" id="captureStatusPanel" style="display: none; border: 1px solid var(--accent-orange); border-radius: 4px; padding: 10px; background: rgba(255, 165, 0, 0.1);">
|
||||||
<h3 style="color: var(--accent-orange); margin: 0 0 8px 0;">🎯 Handshake Capture</h3>
|
<h3 style="color: var(--accent-orange); margin: 0 0 8px 0;"><span class="icon icon--sm"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="6"/><circle cx="12" cy="12" r="2"/></svg></span> Handshake Capture</h3>
|
||||||
<div style="font-size: 11px;">
|
<div style="font-size: 11px;">
|
||||||
<div style="margin-bottom: 4px;">
|
<div style="margin-bottom: 4px;">
|
||||||
<span style="color: var(--text-dim);">Target:</span>
|
<span style="color: var(--text-dim);">Target:</span>
|
||||||
@@ -123,7 +123,7 @@
|
|||||||
|
|
||||||
<!-- Beacon Flood Alert Panel -->
|
<!-- Beacon Flood Alert Panel -->
|
||||||
<div id="beaconFloodAlert" class="beacon-flood-alert" style="display: none;">
|
<div id="beaconFloodAlert" class="beacon-flood-alert" style="display: none;">
|
||||||
<h4 style="color: #ff4444; margin: 0 0 8px 0;">⚠️ BEACON FLOOD DETECTED</h4>
|
<h4 style="color: #ff4444; margin: 0 0 8px 0;"><span class="icon icon--sm"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg></span> BEACON FLOOD DETECTED</h4>
|
||||||
<div style="font-size: 11px;">
|
<div style="font-size: 11px;">
|
||||||
<div id="beaconFloodDetails">Multiple beacon frames detected from same channel</div>
|
<div id="beaconFloodDetails">Multiple beacon frames detected from same channel</div>
|
||||||
<div style="margin-top: 8px;">
|
<div style="margin-top: 8px;">
|
||||||
|
|||||||
Reference in New Issue
Block a user