Use PNG icon assets + Windows 11 WinUI3 native design
- Download 27 fluency-style PNG icons (shield, cpu, monitor, wifi, etc.) - Replace Lucide CDN with embedded PNG <img> tags throughout UI - Redesign CSS with Windows 11 Mica/Acrylic dark theme: - WinUI3 color palette (Segoe UI Variable font) - NavigationView-style toolbar tabs with accent indicator bar - Subtle borders matching Win11 material layering - Accent button style (#0078d4) matching Windows 11 controls - Card/surface hierarchy matching WinUI3 specs - Add IMTAQIN credit in footer with link to https://imtaqin.id - Fix embed directive for flat icon layout (no subdirectories) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
111
ui/app.js
@@ -1,6 +1,5 @@
|
|||||||
/* ============================================================
|
/* ============================================================
|
||||||
Driver Booster Pro - Application Logic
|
Driver Booster Pro - PNG Icons Edition
|
||||||
Driver Navigator Style: tabs, driver rows, action buttons
|
|
||||||
============================================================ */
|
============================================================ */
|
||||||
|
|
||||||
var App = {
|
var App = {
|
||||||
@@ -10,16 +9,9 @@ var App = {
|
|||||||
this.setupTabs();
|
this.setupTabs();
|
||||||
this.setupFilters();
|
this.setupFilters();
|
||||||
this.refreshSysInfo();
|
this.refreshSysInfo();
|
||||||
this.refreshIcons();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
refreshIcons: function() {
|
|
||||||
if (window.lucide) lucide.createIcons();
|
|
||||||
},
|
|
||||||
|
|
||||||
// ---- Tab Navigation ----
|
|
||||||
setupTabs: function() {
|
setupTabs: function() {
|
||||||
var self = this;
|
|
||||||
document.querySelectorAll('.toolbar-tab').forEach(function(tab) {
|
document.querySelectorAll('.toolbar-tab').forEach(function(tab) {
|
||||||
tab.addEventListener('click', function() {
|
tab.addEventListener('click', function() {
|
||||||
var id = tab.dataset.tab;
|
var id = tab.dataset.tab;
|
||||||
@@ -32,7 +24,6 @@ var App = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// ---- Filter Pills ----
|
|
||||||
setupFilters: function() {
|
setupFilters: function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
document.querySelectorAll('.pill').forEach(function(btn) {
|
document.querySelectorAll('.pill').forEach(function(btn) {
|
||||||
@@ -54,17 +45,15 @@ var App = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// ---- Loading ----
|
|
||||||
showLoading: function(text) {
|
showLoading: function(text) {
|
||||||
document.getElementById('loading-text').textContent = text;
|
document.getElementById('loading-text').textContent = text;
|
||||||
document.getElementById('loading-overlay').style.display = 'flex';
|
document.getElementById('loading-overlay').style.display = 'flex';
|
||||||
this.refreshIcons();
|
|
||||||
},
|
},
|
||||||
hideLoading: function() {
|
hideLoading: function() {
|
||||||
document.getElementById('loading-overlay').style.display = 'none';
|
document.getElementById('loading-overlay').style.display = 'none';
|
||||||
},
|
},
|
||||||
|
|
||||||
// ---- System Info ----
|
// System Info
|
||||||
refreshSysInfo: function() {
|
refreshSysInfo: function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
this.showLoading('Collecting system information...');
|
this.showLoading('Collecting system information...');
|
||||||
@@ -72,10 +61,7 @@ var App = {
|
|||||||
self.state.sysInfo = info;
|
self.state.sysInfo = info;
|
||||||
self.renderSysInfo(info);
|
self.renderSysInfo(info);
|
||||||
self.hideLoading();
|
self.hideLoading();
|
||||||
}).catch(function(e) {
|
}).catch(function(e) { console.error(e); self.hideLoading(); });
|
||||||
console.error(e);
|
|
||||||
self.hideLoading();
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
renderSysInfo: function(d) {
|
renderSysInfo: function(d) {
|
||||||
@@ -100,17 +86,15 @@ var App = {
|
|||||||
if(db) db.style.width = (d.diskPercent||0)+'%';
|
if(db) db.style.width = (d.diskPercent||0)+'%';
|
||||||
},
|
},
|
||||||
|
|
||||||
// ---- Driver Scan ----
|
// Driver Scan
|
||||||
scanDrivers: function() {
|
scanDrivers: function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
this.showLoading('Scanning drivers... This may take a moment.');
|
this.showLoading('Scanning drivers...');
|
||||||
// Switch to drivers tab
|
// Switch to drivers tab
|
||||||
document.querySelectorAll('.toolbar-tab').forEach(function(t){ t.classList.remove('active'); });
|
document.querySelectorAll('.toolbar-tab').forEach(function(t){ t.classList.remove('active'); });
|
||||||
document.querySelector('[data-tab="drivers"]').classList.add('active');
|
document.querySelector('[data-tab="drivers"]').classList.add('active');
|
||||||
document.querySelectorAll('.tab-page').forEach(function(p){ p.classList.remove('active'); });
|
document.querySelectorAll('.tab-page').forEach(function(p){ p.classList.remove('active'); });
|
||||||
document.getElementById('tab-drivers').classList.add('active');
|
document.getElementById('tab-drivers').classList.add('active');
|
||||||
|
|
||||||
// Update steps
|
|
||||||
this.setStep(2);
|
this.setStep(2);
|
||||||
|
|
||||||
fetch('/api/drivers/scan').then(function(r){ return r.json(); }).then(function(result) {
|
fetch('/api/drivers/scan').then(function(r){ return r.json(); }).then(function(result) {
|
||||||
@@ -118,10 +102,7 @@ var App = {
|
|||||||
self.renderDrivers(result);
|
self.renderDrivers(result);
|
||||||
self.updateScanStats(result);
|
self.updateScanStats(result);
|
||||||
self.hideLoading();
|
self.hideLoading();
|
||||||
}).catch(function(e) {
|
}).catch(function(e) { console.error(e); self.hideLoading(); });
|
||||||
console.error(e);
|
|
||||||
self.hideLoading();
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
updateScanStats: function(r) {
|
updateScanStats: function(r) {
|
||||||
@@ -139,8 +120,7 @@ var App = {
|
|||||||
|
|
||||||
var list = document.getElementById('driver-list');
|
var list = document.getElementById('driver-list');
|
||||||
if (!result.drivers || result.drivers.length === 0) {
|
if (!result.drivers || result.drivers.length === 0) {
|
||||||
list.innerHTML = '<div class="placeholder-msg"><i data-lucide="search-x"></i><p>No drivers found</p></div>';
|
list.innerHTML = '<div class="placeholder-msg"><img src="icon-scan.png" class="placeholder-img"><p>No drivers found</p></div>';
|
||||||
this.refreshIcons();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,32 +130,31 @@ var App = {
|
|||||||
if (d.needsUpdate) cls.push('outdated');
|
if (d.needsUpdate) cls.push('outdated');
|
||||||
if (d.status === 'Error' || d.status === 'Degraded') cls.push('error');
|
if (d.status === 'Error' || d.status === 'Degraded') cls.push('error');
|
||||||
|
|
||||||
var icon = self.driverIcon(d.deviceClass);
|
var iconFile = self.driverIconFile(d.deviceClass);
|
||||||
var barClass = d.needsUpdate ? 'warn' : (d.status === 'Error' ? 'err' : 'ok');
|
var barClass = d.needsUpdate ? 'warn' : (d.status === 'Error' ? 'err' : 'ok');
|
||||||
|
|
||||||
var signBadge = d.isSigned
|
var signBadge = d.isSigned
|
||||||
? '<span class="drv-badge signed"><i data-lucide="shield-check"></i> Signed</span>'
|
? '<span class="drv-badge signed"><img src="icon-shield.png" class="drv-badge-img" style="width:10px;height:10px"> Signed</span>'
|
||||||
: '<span class="drv-badge unsigned"><i data-lucide="shield-x"></i></span>';
|
: '<span class="drv-badge unsigned">Unsigned</span>';
|
||||||
|
|
||||||
var actionBtn = d.needsUpdate
|
var actionBtn = d.needsUpdate
|
||||||
? '<button class="drv-btn install-btn"><i data-lucide="download"></i> Download</button>' +
|
? '<button class="drv-btn install-btn"><img src="icon-download.png" style="width:13px;height:13px"> Download</button>' +
|
||||||
'<button class="drv-btn"><i data-lucide="play"></i> Install</button>'
|
'<button class="drv-btn"><img src="icon-install.png" style="width:13px;height:13px"> Install</button>'
|
||||||
: '<button class="drv-btn installed-btn"><i data-lucide="circle-check"></i> Up to date</button>';
|
: '<button class="drv-btn ok-btn"><img src="icon-checkmark.png" style="width:13px;height:13px"> Up to date</button>';
|
||||||
|
|
||||||
return '<div class="' + cls.join(' ') + '" data-signed="' + d.isSigned + '">' +
|
return '<div class="' + cls.join(' ') + '" data-signed="' + d.isSigned + '">' +
|
||||||
'<div class="drv-icon"><i data-lucide="' + icon + '"></i></div>' +
|
'<div class="drv-icon"><img src="icon-' + iconFile + '" class="drv-icon-img"></div>' +
|
||||||
'<div class="drv-info">' +
|
'<div class="drv-info">' +
|
||||||
'<div class="drv-name">' + self.esc(d.deviceName) + '</div>' +
|
'<div class="drv-name">' + self.esc(d.deviceName) + '</div>' +
|
||||||
'<div class="drv-meta">' + self.esc(d.manufacturer||'Unknown') + ' · v' + self.esc(d.driverVersion||'?') + ' · ' + self.esc(d.driverDate) + ' ' + signBadge + '</div>' +
|
'<div class="drv-meta">' + self.esc(d.manufacturer||'Unknown') +
|
||||||
'</div>' +
|
' · v' + self.esc(d.driverVersion||'?') +
|
||||||
'<div class="drv-progress">' +
|
' · ' + self.esc(d.driverDate) + ' ' + signBadge + '</div>' +
|
||||||
'<div class="drv-bar"><div class="drv-bar-fill ' + barClass + '"></div></div>' +
|
|
||||||
'</div>' +
|
'</div>' +
|
||||||
|
'<div class="drv-progress"><div class="drv-bar"><div class="drv-bar-fill ' + barClass + '"></div></div></div>' +
|
||||||
'<div class="drv-actions">' + actionBtn + '</div>' +
|
'<div class="drv-actions">' + actionBtn + '</div>' +
|
||||||
'</div>';
|
'</div>';
|
||||||
}).join('');
|
}).join('');
|
||||||
|
|
||||||
// Show CTA if there are outdated drivers
|
|
||||||
var cta = document.getElementById('cta-update-all');
|
var cta = document.getElementById('cta-update-all');
|
||||||
if (result.outdatedCount > 0) {
|
if (result.outdatedCount > 0) {
|
||||||
cta.style.display = 'flex';
|
cta.style.display = 'flex';
|
||||||
@@ -183,30 +162,27 @@ var App = {
|
|||||||
} else {
|
} else {
|
||||||
cta.style.display = 'none';
|
cta.style.display = 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
this.refreshIcons();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
driverIcon: function(cls) {
|
driverIconFile: function(cls) {
|
||||||
if (!cls) return 'package';
|
if (!cls) return 'package.png';
|
||||||
var u = cls.toUpperCase();
|
var u = cls.toUpperCase();
|
||||||
var m = {
|
var m = {
|
||||||
'DISPLAY':'monitor','MEDIA':'volume-2','AUDIO':'volume-2','SOUND':'volume-2',
|
'DISPLAY':'monitor.png','MEDIA':'speaker.png','AUDIO':'speaker.png','SOUND':'speaker.png',
|
||||||
'NET':'wifi','NETWORK':'wifi','USB':'usb','HID':'mouse','KEYBOARD':'keyboard',
|
'NET':'wifi.png','NETWORK':'wifi.png','USB':'usb.png','HID':'mouse.png',
|
||||||
'DISK':'hard-drive','STORAGE':'hard-drive','PROCESSOR':'cpu','SYSTEM':'settings',
|
'KEYBOARD':'keyboard.png','DISK':'harddrive.png','STORAGE':'harddrive.png',
|
||||||
'BLUETOOTH':'bluetooth','CAMERA':'camera','IMAGE':'camera','PRINT':'printer',
|
'PROCESSOR':'cpu.png','SYSTEM':'settings.png','BLUETOOTH':'bluetooth.png',
|
||||||
'BATTERY':'battery-charging','FIRMWARE':'circuit-board','SECURITY':'shield',
|
'CAMERA':'camera.png','IMAGE':'camera.png','PRINT':'printer.png',
|
||||||
'SENSOR':'thermometer'
|
'BATTERY':'battery.png'
|
||||||
};
|
};
|
||||||
for (var k in m) { if (u.indexOf(k) !== -1) return m[k]; }
|
for (var k in m) { if (u.indexOf(k) !== -1) return m[k]; }
|
||||||
return 'package';
|
return 'package.png';
|
||||||
},
|
},
|
||||||
|
|
||||||
// ---- Windows Update ----
|
// Windows Update
|
||||||
checkUpdates: function() {
|
checkUpdates: function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
this.showLoading('Checking for Windows updates...');
|
this.showLoading('Checking for Windows updates...');
|
||||||
// Switch to updates tab
|
|
||||||
document.querySelectorAll('.toolbar-tab').forEach(function(t){ t.classList.remove('active'); });
|
document.querySelectorAll('.toolbar-tab').forEach(function(t){ t.classList.remove('active'); });
|
||||||
document.querySelector('[data-tab="updates"]').classList.add('active');
|
document.querySelector('[data-tab="updates"]').classList.add('active');
|
||||||
document.querySelectorAll('.tab-page').forEach(function(p){ p.classList.remove('active'); });
|
document.querySelectorAll('.tab-page').forEach(function(p){ p.classList.remove('active'); });
|
||||||
@@ -216,24 +192,18 @@ var App = {
|
|||||||
self.state.updates = result;
|
self.state.updates = result;
|
||||||
self.renderUpdates(result);
|
self.renderUpdates(result);
|
||||||
self.hideLoading();
|
self.hideLoading();
|
||||||
}).catch(function(e) {
|
}).catch(function(e) { console.error(e); self.hideLoading(); });
|
||||||
console.error(e);
|
|
||||||
self.hideLoading();
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
renderUpdates: function(result) {
|
renderUpdates: function(result) {
|
||||||
var list = document.getElementById('update-list');
|
var list = document.getElementById('update-list');
|
||||||
|
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
list.innerHTML = '<div class="placeholder-msg"><i data-lucide="alert-circle"></i><p style="color:var(--red)">' + this.esc(result.error) + '</p></div>';
|
list.innerHTML = '<div class="placeholder-msg"><img src="icon-error.png" class="placeholder-img"><p style="color:var(--red)">' + this.esc(result.error) + '</p></div>';
|
||||||
this.refreshIcons();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result.updates || result.updates.length === 0) {
|
if (!result.updates || result.updates.length === 0) {
|
||||||
list.innerHTML = '<div class="placeholder-msg"><i data-lucide="circle-check"></i><p>Your system is fully up to date!</p></div>';
|
list.innerHTML = '<div class="placeholder-msg"><img src="icon-checkmark.png" class="placeholder-img"><p>Your system is fully up to date!</p></div>';
|
||||||
this.refreshIcons();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,32 +213,28 @@ var App = {
|
|||||||
var html = '';
|
var html = '';
|
||||||
|
|
||||||
if (pending.length > 0) {
|
if (pending.length > 0) {
|
||||||
html += '<div class="upd-section pend"><i data-lucide="download"></i> Pending (' + pending.length + ')</div>';
|
html += '<div class="upd-section pend"><img src="icon-download.png" style="width:16px;height:16px"> Pending (' + pending.length + ')</div>';
|
||||||
html += pending.map(function(u) {
|
html += pending.map(function(u) {
|
||||||
return '<div class="upd-row pending">' +
|
return '<div class="upd-row pending">' +
|
||||||
'<div class="upd-title">' + self.esc(u.title) + '</div>' +
|
'<div class="upd-title">' + self.esc(u.title) + '</div>' +
|
||||||
'<div class="upd-meta">' +
|
'<div class="upd-meta">' +
|
||||||
(u.kbArticle ? '<span class="upd-tag"><i data-lucide="file-text"></i> '+self.esc(u.kbArticle)+'</span>' : '') +
|
(u.kbArticle ? '<span class="upd-tag"><img src="icon-info.png" style="width:12px;height:12px"> '+self.esc(u.kbArticle)+'</span>' : '') +
|
||||||
(u.category ? '<span class="upd-tag"><i data-lucide="folder"></i> '+self.esc(u.category)+'</span>' : '') +
|
(u.category ? '<span class="upd-tag"><img src="icon-package.png" style="width:12px;height:12px"> '+self.esc(u.category)+'</span>' : '') +
|
||||||
(u.size ? '<span class="upd-tag"><i data-lucide="hard-drive"></i> '+self.esc(u.size)+'</span>' : '') +
|
(u.size ? '<span class="upd-tag"><img src="icon-harddrive.png" style="width:12px;height:12px"> '+self.esc(u.size)+'</span>' : '') +
|
||||||
(u.severity && u.severity !== 'Unspecified' ? '<span class="upd-tag"><i data-lucide="alert-triangle"></i> '+self.esc(u.severity)+'</span>' : '') +
|
(u.severity && u.severity !== 'Unspecified' ? '<span class="upd-tag"><img src="icon-warning.png" style="width:12px;height:12px"> '+self.esc(u.severity)+'</span>' : '') +
|
||||||
'</div>' +
|
'</div></div>';
|
||||||
'</div>';
|
|
||||||
}).join('');
|
}).join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (installed.length > 0) {
|
if (installed.length > 0) {
|
||||||
html += '<div class="upd-section inst"><i data-lucide="check-circle"></i> Recently Installed (' + installed.length + ')</div>';
|
html += '<div class="upd-section inst"><img src="icon-checkmark.png" style="width:16px;height:16px"> Recently Installed (' + installed.length + ')</div>';
|
||||||
html += installed.map(function(u) {
|
html += installed.map(function(u) {
|
||||||
return '<div class="upd-row done"><div class="upd-title">' + self.esc(u.title) + '</div></div>';
|
return '<div class="upd-row done"><div class="upd-title">' + self.esc(u.title) + '</div></div>';
|
||||||
}).join('');
|
}).join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
list.innerHTML = html;
|
list.innerHTML = html;
|
||||||
this.refreshIcons();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// ---- Step bar ----
|
|
||||||
setStep: function(n) {
|
setStep: function(n) {
|
||||||
for (var i = 1; i <= 3; i++) {
|
for (var i = 1; i <= 3; i++) {
|
||||||
var el = document.getElementById('step-' + i);
|
var el = document.getElementById('step-' + i);
|
||||||
@@ -279,7 +245,6 @@ var App = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// ---- Helpers ----
|
|
||||||
set: function(id, val) {
|
set: function(id, val) {
|
||||||
var el = document.getElementById(id);
|
var el = document.getElementById(id);
|
||||||
if (el) el.textContent = (val != null && val !== '') ? val : '--';
|
if (el) el.textContent = (val != null && val !== '') ? val : '--';
|
||||||
|
|||||||
BIN
ui/icon-battery.png
Normal file
|
After Width: | Height: | Size: 731 B |
BIN
ui/icon-bluetooth.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
ui/icon-camera.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
ui/icon-checkmark.png
Normal file
|
After Width: | Height: | Size: 776 B |
BIN
ui/icon-cloud.png
Normal file
|
After Width: | Height: | Size: 755 B |
BIN
ui/icon-cpu.png
Normal file
|
After Width: | Height: | Size: 925 B |
BIN
ui/icon-download.png
Normal file
|
After Width: | Height: | Size: 762 B |
BIN
ui/icon-error.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
ui/icon-harddrive.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
ui/icon-help.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
ui/icon-info.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
ui/icon-install.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
ui/icon-keyboard.png
Normal file
|
After Width: | Height: | Size: 861 B |
BIN
ui/icon-laptop.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
ui/icon-monitor.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
ui/icon-mouse.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
ui/icon-package.png
Normal file
|
After Width: | Height: | Size: 934 B |
BIN
ui/icon-printer.png
Normal file
|
After Width: | Height: | Size: 464 B |
BIN
ui/icon-ram.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
ui/icon-refresh.png
Normal file
|
After Width: | Height: | Size: 846 B |
BIN
ui/icon-scan.png
Normal file
|
After Width: | Height: | Size: 891 B |
BIN
ui/icon-settings.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
ui/icon-shield.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
ui/icon-speaker.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
ui/icon-usb.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
ui/icon-warning.png
Normal file
|
After Width: | Height: | Size: 1022 B |
BIN
ui/icon-wifi.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
116
ui/index.html
@@ -5,23 +5,20 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Driver Booster Pro</title>
|
<title>Driver Booster Pro</title>
|
||||||
<link rel="stylesheet" href="style.css">
|
<link rel="stylesheet" href="style.css">
|
||||||
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.min.js"></script>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="app">
|
<div class="app">
|
||||||
<!-- Title Bar -->
|
<!-- Title Bar -->
|
||||||
<div class="titlebar">
|
<div class="titlebar">
|
||||||
<div class="titlebar-left">
|
<div class="titlebar-left">
|
||||||
<div class="app-logo">
|
<img src="icon-shield.png" class="app-logo-img" alt="">
|
||||||
<i data-lucide="shield-check"></i>
|
|
||||||
</div>
|
|
||||||
<div class="app-title">
|
<div class="app-title">
|
||||||
<span class="app-name">DRIVER BOOSTER</span>
|
<span class="app-name">DRIVER BOOSTER</span>
|
||||||
<span class="app-edition">PRO</span>
|
<span class="app-edition">PRO</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="titlebar-right">
|
<div class="titlebar-right">
|
||||||
<div class="sys-status" id="sys-status">
|
<div class="sys-status">
|
||||||
<div class="status-led"></div>
|
<div class="status-led"></div>
|
||||||
<span>System Protected</span>
|
<span>System Protected</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -31,27 +28,19 @@
|
|||||||
<!-- Toolbar Tabs -->
|
<!-- Toolbar Tabs -->
|
||||||
<div class="toolbar">
|
<div class="toolbar">
|
||||||
<button class="toolbar-tab active" data-tab="scan">
|
<button class="toolbar-tab active" data-tab="scan">
|
||||||
<div class="tab-icon-wrap scan-icon-wrap">
|
<img src="icon-scan.png" class="tab-img" alt="">
|
||||||
<i data-lucide="scan-search"></i>
|
|
||||||
</div>
|
|
||||||
<span>Scan</span>
|
<span>Scan</span>
|
||||||
</button>
|
</button>
|
||||||
<button class="toolbar-tab" data-tab="drivers">
|
<button class="toolbar-tab" data-tab="drivers">
|
||||||
<div class="tab-icon-wrap drivers-icon-wrap">
|
<img src="icon-cpu.png" class="tab-img" alt="">
|
||||||
<i data-lucide="cpu"></i>
|
|
||||||
</div>
|
|
||||||
<span>Drivers</span>
|
<span>Drivers</span>
|
||||||
</button>
|
</button>
|
||||||
<button class="toolbar-tab" data-tab="updates">
|
<button class="toolbar-tab" data-tab="updates">
|
||||||
<div class="tab-icon-wrap updates-icon-wrap">
|
<img src="icon-download.png" class="tab-img" alt="">
|
||||||
<i data-lucide="download-cloud"></i>
|
|
||||||
</div>
|
|
||||||
<span>Download</span>
|
<span>Download</span>
|
||||||
</button>
|
</button>
|
||||||
<button class="toolbar-tab" data-tab="system">
|
<button class="toolbar-tab" data-tab="system">
|
||||||
<div class="tab-icon-wrap settings-icon-wrap">
|
<img src="icon-settings.png" class="tab-img" alt="">
|
||||||
<i data-lucide="monitor-cog"></i>
|
|
||||||
</div>
|
|
||||||
<span>System</span>
|
<span>System</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -63,72 +52,35 @@
|
|||||||
<div class="tab-page active" id="tab-scan">
|
<div class="tab-page active" id="tab-scan">
|
||||||
<div class="scan-hero">
|
<div class="scan-hero">
|
||||||
<div class="scan-illustration">
|
<div class="scan-illustration">
|
||||||
<!-- Computer SVG Illustration -->
|
<img src="icon-monitor.png" class="hero-img" alt="">
|
||||||
<svg viewBox="0 0 200 180" class="computer-svg">
|
<img src="icon-shield.png" class="hero-shield" alt="">
|
||||||
<defs>
|
|
||||||
<linearGradient id="screen-grad" x1="0" y1="0" x2="0" y2="1">
|
|
||||||
<stop offset="0%" stop-color="#1e40af"/>
|
|
||||||
<stop offset="100%" stop-color="#3b82f6"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="body-grad" x1="0" y1="0" x2="0" y2="1">
|
|
||||||
<stop offset="0%" stop-color="#e2e8f0"/>
|
|
||||||
<stop offset="100%" stop-color="#cbd5e1"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="shield-grad" x1="0" y1="0" x2="1" y2="1">
|
|
||||||
<stop offset="0%" stop-color="#10b981"/>
|
|
||||||
<stop offset="100%" stop-color="#059669"/>
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
<!-- Monitor -->
|
|
||||||
<rect x="30" y="10" width="140" height="100" rx="8" fill="url(#body-grad)" stroke="#94a3b8" stroke-width="2"/>
|
|
||||||
<rect x="38" y="18" width="124" height="76" rx="4" fill="url(#screen-grad)"/>
|
|
||||||
<!-- Screen content lines -->
|
|
||||||
<rect x="50" y="34" width="60" height="4" rx="2" fill="rgba(255,255,255,0.3)"/>
|
|
||||||
<rect x="50" y="44" width="80" height="4" rx="2" fill="rgba(255,255,255,0.2)"/>
|
|
||||||
<rect x="50" y="54" width="45" height="4" rx="2" fill="rgba(255,255,255,0.3)"/>
|
|
||||||
<rect x="50" y="64" width="70" height="4" rx="2" fill="rgba(255,255,255,0.2)"/>
|
|
||||||
<rect x="50" y="74" width="55" height="4" rx="2" fill="rgba(255,255,255,0.3)"/>
|
|
||||||
<!-- Check marks -->
|
|
||||||
<circle cx="46" cy="36" r="3" fill="#10b981"/>
|
|
||||||
<circle cx="46" cy="46" r="3" fill="#10b981"/>
|
|
||||||
<circle cx="46" cy="56" r="3" fill="#10b981"/>
|
|
||||||
<circle cx="46" cy="66" r="3" fill="#f59e0b"/>
|
|
||||||
<circle cx="46" cy="76" r="3" fill="#ef4444"/>
|
|
||||||
<!-- Stand -->
|
|
||||||
<rect x="85" y="110" width="30" height="12" rx="2" fill="#94a3b8"/>
|
|
||||||
<rect x="70" y="120" width="60" height="6" rx="3" fill="#94a3b8"/>
|
|
||||||
<!-- Shield overlay -->
|
|
||||||
<path d="M145 55 L145 35 C145 35 155 30 165 35 C175 30 185 35 185 35 L185 55 C185 70 165 82 165 82 C165 82 145 70 145 55Z" fill="url(#shield-grad)" opacity="0.9"/>
|
|
||||||
<polyline points="157,55 163,62 175,48" fill="none" stroke="white" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
</svg>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="scan-info">
|
<div class="scan-info">
|
||||||
<h2>Scan Your System</h2>
|
<h2>Scan Your System</h2>
|
||||||
<p>Detect outdated, missing, and faulty drivers. Keep your PC running at peak performance.</p>
|
<p>Detect outdated, missing, and faulty drivers. Keep your PC running at peak performance.</p>
|
||||||
<div class="scan-stats" id="scan-stats">
|
<div class="scan-stats">
|
||||||
<div class="mini-stat">
|
<div class="mini-stat">
|
||||||
<i data-lucide="cpu"></i>
|
<img src="icon-cpu.png" class="mini-icon" alt="">
|
||||||
<span id="scan-stat-total">--</span>
|
<span id="scan-stat-total">--</span>
|
||||||
<label>Drivers</label>
|
<label>Drivers</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="mini-stat warn">
|
<div class="mini-stat warn">
|
||||||
<i data-lucide="alert-triangle"></i>
|
<img src="icon-warning.png" class="mini-icon" alt="">
|
||||||
<span id="scan-stat-outdated">--</span>
|
<span id="scan-stat-outdated">--</span>
|
||||||
<label>Outdated</label>
|
<label>Outdated</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="mini-stat danger">
|
<div class="mini-stat danger">
|
||||||
<i data-lucide="x-circle"></i>
|
<img src="icon-error.png" class="mini-icon" alt="">
|
||||||
<span id="scan-stat-errors">--</span>
|
<span id="scan-stat-errors">--</span>
|
||||||
<label>Errors</label>
|
<label>Errors</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button class="big-scan-btn" id="btn-scan" onclick="App.scanDrivers()">
|
<button class="big-scan-btn" onclick="App.scanDrivers()">
|
||||||
<i data-lucide="scan-search"></i>
|
<img src="icon-scan.png" class="btn-icon" alt="">
|
||||||
<span>SCAN NOW</span>
|
<span>SCAN NOW</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Step Indicator -->
|
<!-- Step Indicator -->
|
||||||
<div class="step-bar">
|
<div class="step-bar">
|
||||||
<div class="step active" id="step-1">
|
<div class="step active" id="step-1">
|
||||||
@@ -152,7 +104,7 @@
|
|||||||
<div class="tab-page" id="tab-drivers">
|
<div class="tab-page" id="tab-drivers">
|
||||||
<div class="tab-header">
|
<div class="tab-header">
|
||||||
<div class="tab-header-left">
|
<div class="tab-header-left">
|
||||||
<h2><i data-lucide="cpu"></i> Installed Drivers</h2>
|
<h2><img src="icon-cpu.png" class="h2-icon" alt=""> Installed Drivers</h2>
|
||||||
<div class="result-count" id="driver-result-count" style="display:none">
|
<div class="result-count" id="driver-result-count" style="display:none">
|
||||||
<span id="drv-total-2">0</span> found •
|
<span id="drv-total-2">0</span> found •
|
||||||
<span class="warn-text" id="drv-outdated-2">0</span> outdated •
|
<span class="warn-text" id="drv-outdated-2">0</span> outdated •
|
||||||
@@ -160,25 +112,25 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button class="header-btn" onclick="App.scanDrivers()">
|
<button class="header-btn" onclick="App.scanDrivers()">
|
||||||
<i data-lucide="refresh-cw"></i> Rescan
|
<img src="icon-refresh.png" class="hdr-icon" alt=""> Rescan
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="filter-strip" id="driver-filter-strip" style="display:none">
|
<div class="filter-strip" id="driver-filter-strip" style="display:none">
|
||||||
<button class="pill active" data-filter="all">All</button>
|
<button class="pill active" data-filter="all">All</button>
|
||||||
<button class="pill" data-filter="outdated"><i data-lucide="alert-triangle"></i> Outdated</button>
|
<button class="pill" data-filter="outdated"><img src="icon-warning.png" class="pill-icon" alt=""> Outdated</button>
|
||||||
<button class="pill" data-filter="error"><i data-lucide="x-circle"></i> Errors</button>
|
<button class="pill" data-filter="error"><img src="icon-error.png" class="pill-icon" alt=""> Errors</button>
|
||||||
<button class="pill" data-filter="signed"><i data-lucide="shield-check"></i> Signed</button>
|
<button class="pill" data-filter="signed"><img src="icon-shield.png" class="pill-icon" alt=""> Signed</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="driver-scroll" id="driver-list">
|
<div class="driver-scroll" id="driver-list">
|
||||||
<div class="placeholder-msg">
|
<div class="placeholder-msg">
|
||||||
<i data-lucide="scan-search"></i>
|
<img src="icon-scan.png" class="placeholder-img" alt="">
|
||||||
<p>Click <strong>Scan</strong> to detect your drivers</p>
|
<p>Click <strong>Scan</strong> to detect your drivers</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- Update All CTA -->
|
<!-- Update All CTA -->
|
||||||
<div class="cta-bar" id="cta-update-all" style="display:none">
|
<div class="cta-bar" id="cta-update-all" style="display:none">
|
||||||
<button class="cta-btn" onclick="App.scanDrivers()">
|
<button class="cta-btn" onclick="App.scanDrivers()">
|
||||||
<i data-lucide="download"></i>
|
<img src="icon-install.png" class="cta-icon" alt="">
|
||||||
<span>Update All Drivers</span>
|
<span>Update All Drivers</span>
|
||||||
<span class="cta-count" id="cta-count">0</span>
|
<span class="cta-count" id="cta-count">0</span>
|
||||||
</button>
|
</button>
|
||||||
@@ -189,15 +141,15 @@
|
|||||||
<div class="tab-page" id="tab-updates">
|
<div class="tab-page" id="tab-updates">
|
||||||
<div class="tab-header">
|
<div class="tab-header">
|
||||||
<div class="tab-header-left">
|
<div class="tab-header-left">
|
||||||
<h2><i data-lucide="download-cloud"></i> Windows Update</h2>
|
<h2><img src="icon-cloud.png" class="h2-icon" alt=""> Windows Update</h2>
|
||||||
</div>
|
</div>
|
||||||
<button class="header-btn" onclick="App.checkUpdates()">
|
<button class="header-btn" onclick="App.checkUpdates()">
|
||||||
<i data-lucide="refresh-cw"></i> Check Now
|
<img src="icon-refresh.png" class="hdr-icon" alt=""> Check Now
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="driver-scroll" id="update-list">
|
<div class="driver-scroll" id="update-list">
|
||||||
<div class="placeholder-msg">
|
<div class="placeholder-msg">
|
||||||
<i data-lucide="cloud-download"></i>
|
<img src="icon-cloud.png" class="placeholder-img" alt="">
|
||||||
<p>Click <strong>Check Now</strong> to search for updates</p>
|
<p>Click <strong>Check Now</strong> to search for updates</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -207,15 +159,15 @@
|
|||||||
<div class="tab-page" id="tab-system">
|
<div class="tab-page" id="tab-system">
|
||||||
<div class="tab-header">
|
<div class="tab-header">
|
||||||
<div class="tab-header-left">
|
<div class="tab-header-left">
|
||||||
<h2><i data-lucide="monitor-cog"></i> System Information</h2>
|
<h2><img src="icon-settings.png" class="h2-icon" alt=""> System Information</h2>
|
||||||
</div>
|
</div>
|
||||||
<button class="header-btn" onclick="App.refreshSysInfo()">
|
<button class="header-btn" onclick="App.refreshSysInfo()">
|
||||||
<i data-lucide="refresh-cw"></i> Refresh
|
<img src="icon-refresh.png" class="hdr-icon" alt=""> Refresh
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="sys-grid">
|
<div class="sys-grid">
|
||||||
<div class="sys-card">
|
<div class="sys-card">
|
||||||
<div class="sys-card-head"><i data-lucide="laptop"></i> Computer</div>
|
<div class="sys-card-head"><img src="icon-laptop.png" class="sys-head-icon" alt=""> Computer</div>
|
||||||
<div class="sys-row"><span>Name</span><span id="sys-name">--</span></div>
|
<div class="sys-row"><span>Name</span><span id="sys-name">--</span></div>
|
||||||
<div class="sys-row"><span>OS</span><span id="sys-os">--</span></div>
|
<div class="sys-row"><span>OS</span><span id="sys-os">--</span></div>
|
||||||
<div class="sys-row"><span>Version</span><span id="sys-version">--</span></div>
|
<div class="sys-row"><span>Version</span><span id="sys-version">--</span></div>
|
||||||
@@ -223,12 +175,12 @@
|
|||||||
<div class="sys-row"><span>Arch</span><span id="sys-arch">--</span></div>
|
<div class="sys-row"><span>Arch</span><span id="sys-arch">--</span></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="sys-card">
|
<div class="sys-card">
|
||||||
<div class="sys-card-head"><i data-lucide="cpu"></i> Processor</div>
|
<div class="sys-card-head"><img src="icon-cpu.png" class="sys-head-icon" alt=""> Processor</div>
|
||||||
<div class="sys-row"><span>CPU</span><span id="sys-cpu">--</span></div>
|
<div class="sys-row"><span>CPU</span><span id="sys-cpu">--</span></div>
|
||||||
<div class="sys-row"><span>Cores</span><span id="sys-cores">--</span></div>
|
<div class="sys-row"><span>Cores</span><span id="sys-cores">--</span></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="sys-card">
|
<div class="sys-card">
|
||||||
<div class="sys-card-head"><i data-lucide="memory-stick"></i> Memory</div>
|
<div class="sys-card-head"><img src="icon-ram.png" class="sys-head-icon" alt=""> Memory</div>
|
||||||
<div class="sys-row"><span>Total</span><span id="sys-ram-total">--</span></div>
|
<div class="sys-row"><span>Total</span><span id="sys-ram-total">--</span></div>
|
||||||
<div class="sys-row"><span>Used</span><span id="sys-ram-used">--</span></div>
|
<div class="sys-row"><span>Used</span><span id="sys-ram-used">--</span></div>
|
||||||
<div class="sys-row"><span>Free</span><span id="sys-ram-free">--</span></div>
|
<div class="sys-row"><span>Free</span><span id="sys-ram-free">--</span></div>
|
||||||
@@ -238,7 +190,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="sys-card">
|
<div class="sys-card">
|
||||||
<div class="sys-card-head"><i data-lucide="hard-drive"></i> Storage (C:)</div>
|
<div class="sys-card-head"><img src="icon-harddrive.png" class="sys-head-icon" alt=""> Storage (C:)</div>
|
||||||
<div class="sys-row"><span>Total</span><span id="sys-disk-total">--</span></div>
|
<div class="sys-row"><span>Total</span><span id="sys-disk-total">--</span></div>
|
||||||
<div class="sys-row"><span>Used</span><span id="sys-disk-used">--</span></div>
|
<div class="sys-row"><span>Used</span><span id="sys-disk-used">--</span></div>
|
||||||
<div class="sys-row"><span>Free</span><span id="sys-disk-free">--</span></div>
|
<div class="sys-row"><span>Free</span><span id="sys-disk-free">--</span></div>
|
||||||
@@ -253,10 +205,10 @@
|
|||||||
|
|
||||||
<!-- Footer -->
|
<!-- Footer -->
|
||||||
<div class="app-footer">
|
<div class="app-footer">
|
||||||
<span>Driver Booster Pro v1.0.0</span>
|
<span>Driver Booster Pro v1.0.0 — Made by <a href="https://imtaqin.id" class="credit-link" target="_blank">IMTAQIN</a></span>
|
||||||
<span class="footer-right">
|
<span class="footer-right">
|
||||||
<button class="footer-btn" onclick="App.refreshSysInfo()"><i data-lucide="info"></i> About</button>
|
<button class="footer-btn" onclick="App.refreshSysInfo()"><img src="icon-info.png" class="footer-icon" alt=""> About</button>
|
||||||
<button class="footer-btn"><i data-lucide="life-buoy"></i> Help</button>
|
<button class="footer-btn"><img src="icon-help.png" class="footer-icon" alt=""> Help</button>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -266,7 +218,7 @@
|
|||||||
<div class="loading-card">
|
<div class="loading-card">
|
||||||
<div class="loading-spinner">
|
<div class="loading-spinner">
|
||||||
<div class="spinner-ring"></div>
|
<div class="spinner-ring"></div>
|
||||||
<i data-lucide="shield-check" class="spinner-icon"></i>
|
<img src="icon-shield.png" class="spinner-img" alt="">
|
||||||
</div>
|
</div>
|
||||||
<p class="loading-title" id="loading-text">Scanning...</p>
|
<p class="loading-title" id="loading-text">Scanning...</p>
|
||||||
<div class="loading-dots"><span></span><span></span><span></span></div>
|
<div class="loading-dots"><span></span><span></span><span></span></div>
|
||||||
|
|||||||
763
ui/style.css
@@ -1,613 +1,388 @@
|
|||||||
/* ============================================================
|
/* ============================================================
|
||||||
Driver Booster Pro - Driver Navigator Style
|
Driver Booster Pro - Windows 11 WinUI3 + PNG Icons
|
||||||
Toolbar tabs + driver list + Download/Install buttons
|
Mica/Acrylic materials, rounded corners, native look
|
||||||
============================================================ */
|
============================================================ */
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--bg: linear-gradient(180deg, #0a1628 0%, #0f1d32 50%, #0a1628 100%);
|
/* Windows 11 Dark Mica palette */
|
||||||
--surface: #111d33;
|
--bg: #202020;
|
||||||
--surface-light: #162442;
|
--mica: #2c2c2c;
|
||||||
--surface-hover: #1a2d50;
|
--surface: #2d2d2d;
|
||||||
--border: rgba(255,255,255,0.07);
|
--surface-light: #383838;
|
||||||
--border-accent: rgba(59,130,246,0.3);
|
--surface-hover: #3a3a3a;
|
||||||
|
--card: #323232;
|
||||||
|
--border: rgba(255,255,255,0.0578);
|
||||||
|
--border-light: rgba(255,255,255,0.0837);
|
||||||
|
--border-top: rgba(255,255,255,0.093);
|
||||||
|
|
||||||
--text: #e8edf5;
|
--text: #ffffffde;
|
||||||
--text-sec: #8899b4;
|
--text-sec: #ffffffa0;
|
||||||
--text-dim: #56687e;
|
--text-dim: #ffffff60;
|
||||||
|
|
||||||
--accent: #3b82f6;
|
/* Windows 11 accent (Blue) */
|
||||||
--accent-light: #60a5fa;
|
--accent: #60cdff;
|
||||||
--accent-dark: #2563eb;
|
--accent-bg: #0078d4;
|
||||||
--accent-glow: rgba(59,130,246,0.25);
|
--accent-hover: #429ce3;
|
||||||
|
--accent-press: #005a9e;
|
||||||
|
--accent-subtle: rgba(96,205,255,0.08);
|
||||||
|
|
||||||
--green: #10b981;
|
--green: #6ccb5f;
|
||||||
--green-bg: rgba(16,185,129,0.12);
|
--green-bg: rgba(108,203,95,0.1);
|
||||||
--yellow: #f59e0b;
|
--yellow: #fce100;
|
||||||
--yellow-bg: rgba(245,158,11,0.12);
|
--yellow-bg: rgba(252,225,0,0.1);
|
||||||
--red: #ef4444;
|
--red: #ff99a4;
|
||||||
--red-bg: rgba(239,68,68,0.12);
|
--red-bg: rgba(255,153,164,0.1);
|
||||||
--cyan: #06b6d4;
|
|
||||||
|
|
||||||
--r: 10px;
|
--radius: 8px;
|
||||||
--r-sm: 6px;
|
--radius-lg: 12px;
|
||||||
|
--radius-sm: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
* { margin:0; padding:0; box-sizing:border-box; }
|
*{margin:0;padding:0;box-sizing:border-box}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: 'Segoe UI Variable','Segoe UI',-apple-system,BlinkMacSystemFont,sans-serif;
|
font-family:'Segoe UI Variable Display','Segoe UI Variable','Segoe UI',-apple-system,sans-serif;
|
||||||
background: var(--bg);
|
background:var(--bg);
|
||||||
background-attachment: fixed;
|
color:var(--text);
|
||||||
color: var(--text);
|
height:100vh;overflow:hidden;
|
||||||
height: 100vh;
|
font-size:14px;
|
||||||
overflow: hidden;
|
-webkit-font-smoothing:antialiased;
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---- Shared icon sizes ---- */
|
||||||
|
.app-logo-img { width:24px; height:24px; }
|
||||||
|
.tab-img { width:32px; height:32px; }
|
||||||
|
.h2-icon { width:20px; height:20px; vertical-align:middle; margin-right:6px; }
|
||||||
|
.hdr-icon { width:14px; height:14px; vertical-align:middle; }
|
||||||
|
.pill-icon { width:12px; height:12px; vertical-align:middle; }
|
||||||
|
.mini-icon { width:20px; height:20px; }
|
||||||
|
.btn-icon { width:20px; height:20px; }
|
||||||
|
.placeholder-img { width:48px; height:48px; opacity:.35; }
|
||||||
|
.sys-head-icon { width:16px; height:16px; vertical-align:middle; }
|
||||||
|
.footer-icon { width:12px; height:12px; vertical-align:middle; }
|
||||||
|
.cta-icon { width:20px; height:20px; }
|
||||||
|
.drv-icon-img { width:24px; height:24px; }
|
||||||
|
.spinner-img { width:24px; height:24px; position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); }
|
||||||
|
|
||||||
/* ---- App Shell ---- */
|
/* ---- App Shell ---- */
|
||||||
.app {
|
.app { display:flex; flex-direction:column; height:100vh; background:var(--mica); }
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
height: 100vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---- Title Bar ---- */
|
/* ---- Title Bar (Win11 style) ---- */
|
||||||
.titlebar {
|
.titlebar {
|
||||||
display: flex;
|
display:flex; justify-content:space-between; align-items:center;
|
||||||
justify-content: space-between;
|
padding:10px 16px;
|
||||||
align-items: center;
|
background:var(--bg);
|
||||||
padding: 14px 24px 10px;
|
border-bottom:1px solid var(--border);
|
||||||
border-bottom: 1px solid var(--border);
|
flex-shrink:0;
|
||||||
background: rgba(10,22,40,0.8);
|
-webkit-app-region:drag;
|
||||||
backdrop-filter: blur(12px);
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.titlebar-left { display:flex; align-items:center; gap:12px; }
|
|
||||||
|
|
||||||
.app-logo {
|
|
||||||
width: 36px; height: 36px;
|
|
||||||
background: linear-gradient(135deg, var(--accent), var(--cyan));
|
|
||||||
border-radius: 10px;
|
|
||||||
display: flex; align-items:center; justify-content:center;
|
|
||||||
box-shadow: 0 2px 12px var(--accent-glow);
|
|
||||||
}
|
|
||||||
.app-logo svg { width:20px; height:20px; color:white; }
|
|
||||||
|
|
||||||
.app-title { display:flex; align-items:baseline; gap:6px; }
|
|
||||||
.app-name {
|
|
||||||
font-size: 18px; font-weight: 800;
|
|
||||||
letter-spacing: 2px;
|
|
||||||
background: linear-gradient(90deg, #fff, #94a3b8);
|
|
||||||
-webkit-background-clip: text; -webkit-text-fill-color: transparent;
|
|
||||||
}
|
}
|
||||||
|
.titlebar-left { display:flex; align-items:center; gap:10px; -webkit-app-region:no-drag; }
|
||||||
|
.app-title { display:flex; align-items:center; gap:8px; }
|
||||||
|
.app-name { font-size:13px; font-weight:600; color:var(--text); letter-spacing:.3px; }
|
||||||
.app-edition {
|
.app-edition {
|
||||||
font-size: 11px; font-weight: 700;
|
font-size:10px; font-weight:600; color:var(--accent);
|
||||||
color: var(--cyan);
|
background:var(--accent-subtle); padding:1px 6px;
|
||||||
background: rgba(6,182,212,0.15);
|
border-radius:var(--radius-sm); letter-spacing:.5px;
|
||||||
padding: 2px 8px; border-radius: 4px;
|
|
||||||
letter-spacing: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sys-status {
|
|
||||||
display:flex; align-items:center; gap:6px;
|
|
||||||
font-size: 12px; color: var(--text-sec);
|
|
||||||
}
|
}
|
||||||
|
.sys-status { display:flex; align-items:center; gap:6px; font-size:12px; color:var(--text-sec); }
|
||||||
.status-led {
|
.status-led {
|
||||||
width:8px; height:8px; border-radius:50%;
|
width:8px; height:8px; border-radius:50%;
|
||||||
background: var(--green);
|
background:var(--green); box-shadow:0 0 6px var(--green);
|
||||||
box-shadow: 0 0 8px var(--green);
|
animation:pulse 2.5s ease-in-out infinite;
|
||||||
animation: pulse 2s ease-in-out infinite;
|
|
||||||
}
|
}
|
||||||
@keyframes pulse { 0%,100%{opacity:1} 50%{opacity:.4} }
|
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.4}}
|
||||||
|
|
||||||
/* ---- Toolbar ---- */
|
/* ---- Toolbar (Win11 Tabs / NavigationView) ---- */
|
||||||
.toolbar {
|
.toolbar {
|
||||||
display: flex;
|
display:flex; gap:2px; padding:6px 12px;
|
||||||
gap: 4px;
|
background:var(--mica);
|
||||||
padding: 12px 24px;
|
border-bottom:1px solid var(--border);
|
||||||
border-bottom: 1px solid var(--border);
|
flex-shrink:0;
|
||||||
background: rgba(10,22,40,0.5);
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.toolbar-tab {
|
.toolbar-tab {
|
||||||
display: flex; flex-direction: column;
|
display:flex; flex-direction:column; align-items:center; gap:4px;
|
||||||
align-items: center; gap: 6px;
|
padding:8px 20px;
|
||||||
padding: 12px 28px;
|
border:none; border-radius:var(--radius);
|
||||||
border: 1px solid transparent;
|
background:transparent; color:var(--text-sec);
|
||||||
border-radius: var(--r);
|
font-size:11px; font-weight:500;
|
||||||
background: transparent;
|
cursor:pointer; transition:all .15s ease; font-family:inherit;
|
||||||
color: var(--text-sec);
|
position:relative;
|
||||||
font-size: 11.5px; font-weight: 600;
|
|
||||||
letter-spacing: 0.5px;
|
|
||||||
text-transform: uppercase;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all .2s ease;
|
|
||||||
font-family: inherit;
|
|
||||||
position: relative;
|
|
||||||
}
|
}
|
||||||
|
.toolbar-tab:hover { background:var(--surface-hover); color:var(--text); }
|
||||||
.toolbar-tab:hover { background: var(--surface); color: var(--text); }
|
|
||||||
|
|
||||||
.toolbar-tab.active {
|
.toolbar-tab.active {
|
||||||
background: linear-gradient(180deg, var(--surface-light), var(--surface));
|
background:var(--surface);
|
||||||
border-color: var(--border-accent);
|
color:var(--text);
|
||||||
color: var(--accent-light);
|
border:1px solid var(--border-light);
|
||||||
box-shadow: 0 2px 12px var(--accent-glow), inset 0 1px 0 rgba(255,255,255,0.05);
|
border-top:1px solid var(--border-top);
|
||||||
|
}
|
||||||
|
.toolbar-tab.active::after {
|
||||||
|
content:'';
|
||||||
|
position:absolute; bottom:4px; left:50%; transform:translateX(-50%);
|
||||||
|
width:16px; height:3px; border-radius:2px;
|
||||||
|
background:var(--accent);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-icon-wrap {
|
/* ---- Content ---- */
|
||||||
width: 44px; height: 44px;
|
.content-area { flex:1; overflow:hidden; position:relative; }
|
||||||
border-radius: 12px;
|
.tab-page { display:none; height:100%; animation:fadeUp .25s ease; }
|
||||||
display: flex; align-items:center; justify-content:center;
|
.tab-page.active { display:flex; flex-direction:column; }
|
||||||
transition: all .2s ease;
|
@keyframes fadeUp{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}
|
||||||
}
|
|
||||||
|
|
||||||
.tab-icon-wrap svg { width: 22px; height: 22px; }
|
|
||||||
|
|
||||||
.scan-icon-wrap { background: rgba(59,130,246,0.1); color: var(--accent); }
|
|
||||||
.drivers-icon-wrap { background: rgba(6,182,212,0.1); color: var(--cyan); }
|
|
||||||
.updates-icon-wrap { background: rgba(16,185,129,0.1); color: var(--green); }
|
|
||||||
.settings-icon-wrap { background: rgba(245,158,11,0.1); color: var(--yellow); }
|
|
||||||
|
|
||||||
.toolbar-tab.active .scan-icon-wrap { background: rgba(59,130,246,0.2); }
|
|
||||||
.toolbar-tab.active .drivers-icon-wrap { background: rgba(6,182,212,0.2); }
|
|
||||||
.toolbar-tab.active .updates-icon-wrap { background: rgba(16,185,129,0.2); }
|
|
||||||
.toolbar-tab.active .settings-icon-wrap { background: rgba(245,158,11,0.2); }
|
|
||||||
|
|
||||||
/* ---- Content Area ---- */
|
|
||||||
.content-area {
|
|
||||||
flex: 1;
|
|
||||||
overflow: hidden;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-page {
|
|
||||||
display: none;
|
|
||||||
height: 100%;
|
|
||||||
animation: fadeUp .3s ease;
|
|
||||||
}
|
|
||||||
.tab-page.active { display: flex; flex-direction: column; }
|
|
||||||
|
|
||||||
@keyframes fadeUp {
|
|
||||||
from { opacity:0; transform:translateY(8px); }
|
|
||||||
to { opacity:1; transform:translateY(0); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---- Scan Hero ---- */
|
/* ---- Scan Hero ---- */
|
||||||
.scan-hero {
|
.scan-hero {
|
||||||
flex: 1;
|
flex:1; display:flex; align-items:center; justify-content:center;
|
||||||
display: flex;
|
gap:48px; padding:32px;
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
gap: 60px;
|
|
||||||
padding: 40px;
|
|
||||||
}
|
}
|
||||||
|
.scan-illustration { position:relative; flex-shrink:0; }
|
||||||
.scan-illustration { flex-shrink:0; }
|
.hero-img { width:120px; height:120px; filter:drop-shadow(0 4px 16px rgba(0,0,0,0.3)); }
|
||||||
.computer-svg { width: 220px; height: 200px; }
|
.hero-shield {
|
||||||
|
width:48px; height:48px; position:absolute; bottom:-6px; right:-12px;
|
||||||
.scan-info { max-width: 380px; }
|
filter:drop-shadow(0 2px 8px rgba(108,203,95,0.4));
|
||||||
.scan-info h2 { font-size: 28px; font-weight: 800; margin-bottom: 10px; letter-spacing:-0.5px; }
|
animation:shieldBob 3s ease-in-out infinite;
|
||||||
.scan-info p { color: var(--text-sec); font-size: 14px; line-height: 1.6; margin-bottom: 24px; }
|
|
||||||
|
|
||||||
.scan-stats {
|
|
||||||
display: flex; gap: 20px;
|
|
||||||
margin-bottom: 28px;
|
|
||||||
}
|
}
|
||||||
|
@keyframes shieldBob{0%,100%{transform:translateY(0)}50%{transform:translateY(-5px)}}
|
||||||
|
|
||||||
|
.scan-info { max-width:360px; }
|
||||||
|
.scan-info h2 { font-size:28px; font-weight:600; margin-bottom:8px; }
|
||||||
|
.scan-info p { color:var(--text-sec); font-size:14px; line-height:1.5; margin-bottom:20px; }
|
||||||
|
|
||||||
|
.scan-stats { display:flex; gap:10px; margin-bottom:24px; }
|
||||||
.mini-stat {
|
.mini-stat {
|
||||||
display: flex; align-items:center; gap: 8px;
|
display:flex; align-items:center; gap:8px;
|
||||||
background: var(--surface);
|
background:var(--surface); border:1px solid var(--border);
|
||||||
border: 1px solid var(--border);
|
border-radius:var(--radius); padding:10px 14px;
|
||||||
border-radius: var(--r);
|
|
||||||
padding: 10px 16px;
|
|
||||||
}
|
}
|
||||||
.mini-stat svg { width:16px; height:16px; color: var(--accent-light); }
|
.mini-stat span { font-size:18px; font-weight:700; }
|
||||||
.mini-stat span { font-size:20px; font-weight:700; }
|
.mini-stat label { font-size:10px; color:var(--text-dim); text-transform:uppercase; letter-spacing:.4px; }
|
||||||
.mini-stat label { font-size:11px; color:var(--text-dim); text-transform:uppercase; letter-spacing:.5px; }
|
.mini-stat.warn span { color:var(--yellow); }
|
||||||
.mini-stat.warn svg { color: var(--yellow); }
|
.mini-stat.danger span { color:var(--red); }
|
||||||
.mini-stat.warn span { color: var(--yellow); }
|
|
||||||
.mini-stat.danger svg { color: var(--red); }
|
|
||||||
.mini-stat.danger span { color: var(--red); }
|
|
||||||
|
|
||||||
|
/* Win11 accent button */
|
||||||
.big-scan-btn {
|
.big-scan-btn {
|
||||||
display: flex; align-items:center; gap:12px;
|
display:flex; align-items:center; gap:10px;
|
||||||
padding: 16px 48px;
|
padding:12px 40px;
|
||||||
background: linear-gradient(135deg, var(--accent-dark), var(--accent));
|
background:var(--accent-bg); border:none;
|
||||||
border: none; border-radius: 12px;
|
border-radius:var(--radius); color:white;
|
||||||
color: white; font-size: 16px; font-weight: 700;
|
font-size:14px; font-weight:600;
|
||||||
letter-spacing: 2px;
|
cursor:pointer; transition:all .15s ease; font-family:inherit;
|
||||||
cursor: pointer;
|
|
||||||
transition: all .25s ease;
|
|
||||||
font-family: inherit;
|
|
||||||
box-shadow: 0 4px 20px var(--accent-glow);
|
|
||||||
}
|
}
|
||||||
.big-scan-btn svg { width:22px; height:22px; }
|
.big-scan-btn:hover { background:var(--accent-hover); }
|
||||||
.big-scan-btn:hover {
|
.big-scan-btn:active { background:var(--accent-press); transform:scale(0.98); }
|
||||||
transform: translateY(-2px);
|
|
||||||
box-shadow: 0 6px 30px rgba(59,130,246,0.4);
|
|
||||||
}
|
|
||||||
.big-scan-btn:active { transform:translateY(0); }
|
|
||||||
|
|
||||||
/* ---- Step Bar ---- */
|
/* ---- Step Bar ---- */
|
||||||
.step-bar {
|
.step-bar {
|
||||||
display: flex; align-items:center; justify-content:center;
|
|
||||||
gap: 0;
|
|
||||||
padding: 18px 24px;
|
|
||||||
border-top: 1px solid var(--border);
|
|
||||||
background: rgba(10,22,40,0.5);
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.step {
|
|
||||||
display:flex; align-items:center; gap:8px;
|
|
||||||
font-size: 12px; color: var(--text-dim);
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
.step.active { color: var(--accent-light); }
|
|
||||||
.step.done { color: var(--green); }
|
|
||||||
|
|
||||||
.step-num {
|
|
||||||
width:24px; height:24px;
|
|
||||||
border-radius:50%;
|
|
||||||
border: 2px solid var(--text-dim);
|
|
||||||
display:flex; align-items:center; justify-content:center;
|
display:flex; align-items:center; justify-content:center;
|
||||||
font-size: 11px; font-weight:700;
|
padding:12px 16px;
|
||||||
|
border-top:1px solid var(--border); background:var(--bg);
|
||||||
|
flex-shrink:0;
|
||||||
}
|
}
|
||||||
.step.active .step-num { border-color: var(--accent); background: var(--accent); color:white; }
|
.step { display:flex; align-items:center; gap:6px; font-size:12px; color:var(--text-dim); font-weight:500; }
|
||||||
.step.done .step-num { border-color: var(--green); background: var(--green); color:white; }
|
.step.active { color:var(--accent); }
|
||||||
|
.step.done { color:var(--green); }
|
||||||
.step-line {
|
.step-num {
|
||||||
width: 60px; height: 2px;
|
width:22px; height:22px; border-radius:50%;
|
||||||
background: var(--text-dim);
|
border:2px solid var(--text-dim);
|
||||||
margin: 0 12px;
|
display:flex; align-items:center; justify-content:center;
|
||||||
opacity: 0.3;
|
font-size:11px; font-weight:600;
|
||||||
}
|
}
|
||||||
|
.step.active .step-num { border-color:var(--accent-bg); background:var(--accent-bg); color:white; }
|
||||||
|
.step.done .step-num { border-color:var(--green); background:var(--green); color:#000; }
|
||||||
|
.step-line { width:48px; height:1px; background:var(--text-dim); margin:0 10px; opacity:.3; }
|
||||||
|
|
||||||
/* ---- Tab Headers ---- */
|
/* ---- Tab Header ---- */
|
||||||
.tab-header {
|
.tab-header {
|
||||||
display: flex; justify-content:space-between; align-items:center;
|
display:flex; justify-content:space-between; align-items:center;
|
||||||
padding: 18px 24px;
|
padding:14px 20px; border-bottom:1px solid var(--border); flex-shrink:0;
|
||||||
border-bottom: 1px solid var(--border);
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
}
|
||||||
.tab-header-left h2 {
|
.tab-header-left h2 { font-size:16px; font-weight:600; display:flex; align-items:center; }
|
||||||
font-size: 16px; font-weight: 700;
|
.result-count { font-size:12px; color:var(--text-dim); margin-top:2px; }
|
||||||
display:flex; align-items:center; gap:8px;
|
.warn-text { color:var(--yellow); }
|
||||||
}
|
|
||||||
.tab-header-left h2 svg { width:20px; height:20px; color:var(--accent-light); }
|
|
||||||
.result-count { font-size:12px; color:var(--text-dim); margin-top:3px; }
|
|
||||||
.warn-text { color: var(--yellow); }
|
|
||||||
|
|
||||||
|
/* Win11 subtle button */
|
||||||
.header-btn {
|
.header-btn {
|
||||||
display:flex; align-items:center; gap:6px;
|
|
||||||
padding: 8px 18px;
|
|
||||||
background: var(--surface);
|
|
||||||
border: 1px solid var(--border);
|
|
||||||
border-radius: var(--r-sm);
|
|
||||||
color: var(--text-sec);
|
|
||||||
font-size: 12.5px; font-weight:600;
|
|
||||||
cursor:pointer;
|
|
||||||
transition: all .2s ease;
|
|
||||||
font-family: inherit;
|
|
||||||
}
|
|
||||||
.header-btn svg { width:14px; height:14px; }
|
|
||||||
.header-btn:hover { border-color: var(--accent); color: var(--accent-light); background: var(--surface-light); }
|
|
||||||
|
|
||||||
/* ---- Filter Strip ---- */
|
|
||||||
.filter-strip {
|
|
||||||
display:flex; gap:6px;
|
|
||||||
padding: 12px 24px;
|
|
||||||
border-bottom: 1px solid var(--border);
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pill {
|
|
||||||
display:flex; align-items:center; gap:5px;
|
display:flex; align-items:center; gap:5px;
|
||||||
padding: 5px 14px;
|
padding:6px 14px; background:var(--surface);
|
||||||
border:1px solid var(--border);
|
border:1px solid var(--border); border-radius:var(--radius);
|
||||||
border-radius:20px;
|
color:var(--text-sec); font-size:12px; font-weight:500;
|
||||||
background:transparent;
|
cursor:pointer; transition:all .15s ease; font-family:inherit;
|
||||||
color: var(--text-dim);
|
|
||||||
font-size:12px; font-weight:500;
|
|
||||||
cursor:pointer;
|
|
||||||
transition: all .15s ease;
|
|
||||||
font-family:inherit;
|
|
||||||
}
|
}
|
||||||
.pill svg { width:12px; height:12px; }
|
.header-btn:hover { background:var(--surface-hover); color:var(--text); }
|
||||||
.pill:hover { border-color: var(--accent); color: var(--accent-light); }
|
|
||||||
.pill.active { background:var(--accent); border-color:var(--accent); color:white; }
|
|
||||||
|
|
||||||
/* ---- Driver Scroll List ---- */
|
/* ---- Filter ---- */
|
||||||
.driver-scroll {
|
.filter-strip { display:flex; gap:4px; padding:8px 20px; border-bottom:1px solid var(--border); flex-shrink:0; }
|
||||||
flex: 1;
|
.pill {
|
||||||
overflow-y: auto;
|
display:flex; align-items:center; gap:4px;
|
||||||
padding: 12px 24px;
|
padding:4px 12px; border:1px solid var(--border); border-radius:var(--radius);
|
||||||
|
background:transparent; color:var(--text-dim);
|
||||||
|
font-size:12px; font-weight:500; cursor:pointer;
|
||||||
|
transition:all .12s ease; font-family:inherit;
|
||||||
}
|
}
|
||||||
.driver-scroll::-webkit-scrollbar { width:5px; }
|
.pill:hover { background:var(--surface-hover); color:var(--text); }
|
||||||
.driver-scroll::-webkit-scrollbar-track { background:transparent; }
|
.pill.active { background:var(--accent-bg); border-color:var(--accent-bg); color:white; }
|
||||||
.driver-scroll::-webkit-scrollbar-thumb { background:var(--border); border-radius:3px; }
|
|
||||||
|
|
||||||
/* Placeholder */
|
/* ---- Driver Scroll ---- */
|
||||||
.placeholder-msg {
|
.driver-scroll { flex:1; overflow-y:auto; padding:8px 20px; }
|
||||||
text-align:center;
|
.driver-scroll::-webkit-scrollbar{width:6px}
|
||||||
padding: 80px 20px;
|
.driver-scroll::-webkit-scrollbar-track{background:transparent}
|
||||||
color: var(--text-dim);
|
.driver-scroll::-webkit-scrollbar-thumb{background:rgba(255,255,255,0.1);border-radius:3px}
|
||||||
}
|
.driver-scroll::-webkit-scrollbar-thumb:hover{background:rgba(255,255,255,0.15)}
|
||||||
.placeholder-msg svg { width:48px; height:48px; margin-bottom:12px; opacity:.3; }
|
|
||||||
.placeholder-msg p { font-size:14px; }
|
|
||||||
|
|
||||||
/* ---- Driver Row (like Driver Navigator) ---- */
|
.placeholder-msg { text-align:center; padding:64px 20px; color:var(--text-dim); }
|
||||||
|
.placeholder-msg p { font-size:14px; margin-top:8px; }
|
||||||
|
|
||||||
|
/* ---- Driver Row (WinUI3 ListItem) ---- */
|
||||||
.drv-row {
|
.drv-row {
|
||||||
display: flex;
|
display:flex; align-items:center; gap:12px;
|
||||||
align-items: center;
|
padding:10px 14px;
|
||||||
gap: 14px;
|
background:var(--card); border:1px solid var(--border);
|
||||||
padding: 14px 18px;
|
border-radius:var(--radius); margin-bottom:4px;
|
||||||
background: var(--surface);
|
transition:background .12s ease;
|
||||||
border: 1px solid var(--border);
|
|
||||||
border-radius: var(--r);
|
|
||||||
margin-bottom: 8px;
|
|
||||||
transition: all .2s ease;
|
|
||||||
}
|
}
|
||||||
.drv-row:hover { border-color: rgba(59,130,246,0.2); background: var(--surface-hover); }
|
.drv-row:hover { background:var(--surface-hover); }
|
||||||
.drv-row.outdated { border-left: 3px solid var(--yellow); }
|
.drv-row.outdated { border-left:3px solid var(--yellow); }
|
||||||
.drv-row.error { border-left: 3px solid var(--red); }
|
.drv-row.error { border-left:3px solid var(--red); }
|
||||||
|
|
||||||
.drv-icon {
|
.drv-icon {
|
||||||
width:40px; height:40px;
|
width:36px; height:36px; border-radius:var(--radius);
|
||||||
border-radius: 10px;
|
display:flex; align-items:center; justify-content:center; flex-shrink:0;
|
||||||
display:flex; align-items:center; justify-content:center;
|
background:var(--accent-subtle);
|
||||||
flex-shrink:0;
|
|
||||||
background: rgba(59,130,246,0.1);
|
|
||||||
color: var(--accent-light);
|
|
||||||
}
|
}
|
||||||
.drv-icon svg { width:20px; height:20px; }
|
|
||||||
|
|
||||||
.drv-info { flex:1; min-width:0; }
|
.drv-info { flex:1; min-width:0; }
|
||||||
.drv-name {
|
.drv-name { font-size:13px; font-weight:600; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
|
||||||
font-size: 13.5px; font-weight:600;
|
.drv-meta { font-size:11px; color:var(--text-dim); margin-top:1px; display:flex; align-items:center; gap:4px; flex-wrap:wrap; }
|
||||||
white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
|
|
||||||
}
|
|
||||||
.drv-meta { font-size:11.5px; color:var(--text-dim); margin-top:2px; }
|
|
||||||
|
|
||||||
/* Progress bar per driver */
|
.drv-progress { width:100px; flex-shrink:0; }
|
||||||
.drv-progress {
|
.drv-bar { height:3px; background:rgba(255,255,255,0.06); border-radius:2px; overflow:hidden; }
|
||||||
width: 120px;
|
.drv-bar-fill { height:100%; border-radius:2px; transition:width .5s ease; }
|
||||||
flex-shrink: 0;
|
.drv-bar-fill.ok { background:var(--green); width:100%; }
|
||||||
display: flex;
|
.drv-bar-fill.warn { background:var(--yellow); width:60%; }
|
||||||
flex-direction: column;
|
.drv-bar-fill.err { background:var(--red); width:30%; }
|
||||||
gap: 3px;
|
|
||||||
}
|
|
||||||
.drv-bar {
|
|
||||||
height:4px;
|
|
||||||
background: rgba(255,255,255,0.05);
|
|
||||||
border-radius:2px;
|
|
||||||
overflow:hidden;
|
|
||||||
}
|
|
||||||
.drv-bar-fill {
|
|
||||||
height:100%;
|
|
||||||
border-radius:2px;
|
|
||||||
transition: width .6s ease;
|
|
||||||
}
|
|
||||||
.drv-bar-fill.ok { background: var(--green); width:100%; }
|
|
||||||
.drv-bar-fill.warn { background: var(--yellow); width:60%; }
|
|
||||||
.drv-bar-fill.err { background: var(--red); width:30%; }
|
|
||||||
.drv-size { font-size:10px; color:var(--text-dim); text-align:right; }
|
|
||||||
|
|
||||||
/* Action buttons per driver */
|
|
||||||
.drv-actions {
|
|
||||||
display:flex; gap:6px; flex-shrink:0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
.drv-actions { display:flex; gap:4px; flex-shrink:0; }
|
||||||
.drv-btn {
|
.drv-btn {
|
||||||
display:flex; align-items:center; gap:5px;
|
display:flex; align-items:center; gap:4px;
|
||||||
padding: 6px 14px;
|
padding:5px 10px; border-radius:var(--radius);
|
||||||
border-radius: var(--r-sm);
|
border:1px solid var(--border); background:var(--surface);
|
||||||
border: 1px solid var(--border);
|
color:var(--text-sec); font-size:11px; font-weight:500;
|
||||||
background: var(--surface-light);
|
cursor:pointer; transition:all .12s ease; font-family:inherit;
|
||||||
color: var(--text-sec);
|
|
||||||
font-size: 11.5px; font-weight:600;
|
|
||||||
cursor:pointer;
|
|
||||||
transition: all .15s ease;
|
|
||||||
font-family:inherit;
|
|
||||||
}
|
}
|
||||||
.drv-btn svg { width:13px; height:13px; }
|
.drv-btn img { width:13px; height:13px; }
|
||||||
.drv-btn:hover { border-color: var(--accent); color: var(--accent-light); }
|
.drv-btn:hover { background:var(--surface-hover); color:var(--text); }
|
||||||
|
|
||||||
.drv-btn.install-btn {
|
.drv-btn.install-btn {
|
||||||
background: linear-gradient(135deg, var(--accent-dark), var(--accent));
|
background:var(--accent-bg); border-color:var(--accent-bg); color:white;
|
||||||
border-color: var(--accent);
|
|
||||||
color: white;
|
|
||||||
}
|
}
|
||||||
.drv-btn.install-btn:hover { box-shadow: 0 2px 8px var(--accent-glow); }
|
.drv-btn.install-btn:hover { background:var(--accent-hover); }
|
||||||
|
|
||||||
.drv-btn.installed-btn {
|
.drv-btn.ok-btn {
|
||||||
background: var(--green-bg);
|
background:var(--green-bg); border-color:rgba(108,203,95,0.2);
|
||||||
border-color: rgba(16,185,129,0.3);
|
color:var(--green); cursor:default;
|
||||||
color: var(--green);
|
|
||||||
cursor: default;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Status badges */
|
|
||||||
.drv-badge {
|
.drv-badge {
|
||||||
font-size:10px; font-weight:600;
|
font-size:10px; font-weight:500; padding:1px 6px; border-radius:var(--radius-sm);
|
||||||
padding: 2px 8px; border-radius:12px;
|
|
||||||
display:inline-flex; align-items:center; gap:3px;
|
display:inline-flex; align-items:center; gap:3px;
|
||||||
}
|
}
|
||||||
.drv-badge svg { width:10px; height:10px; }
|
|
||||||
.drv-badge.signed { background:var(--green-bg); color:var(--green); }
|
.drv-badge.signed { background:var(--green-bg); color:var(--green); }
|
||||||
.drv-badge.unsigned { background:var(--red-bg); color:var(--red); }
|
.drv-badge.unsigned { background:var(--red-bg); color:var(--red); }
|
||||||
|
|
||||||
/* ---- CTA Bar (Download All) ---- */
|
/* ---- CTA Bar ---- */
|
||||||
.cta-bar {
|
.cta-bar {
|
||||||
padding: 16px 24px;
|
padding:12px 20px; border-top:1px solid var(--border);
|
||||||
border-top: 1px solid var(--border);
|
background:var(--bg); display:flex; justify-content:center; flex-shrink:0;
|
||||||
background: rgba(10,22,40,0.8);
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.cta-btn {
|
.cta-btn {
|
||||||
display:flex; align-items:center; gap:10px;
|
display:flex; align-items:center; gap:8px;
|
||||||
padding: 14px 48px;
|
padding:10px 36px;
|
||||||
background: linear-gradient(135deg, #059669, var(--green));
|
background:var(--accent-bg); border:none;
|
||||||
border:none; border-radius:12px;
|
border-radius:var(--radius); color:white;
|
||||||
color:white; font-size:15px; font-weight:700;
|
font-size:14px; font-weight:600;
|
||||||
letter-spacing:1px;
|
cursor:pointer; transition:all .15s ease; font-family:inherit;
|
||||||
cursor:pointer;
|
|
||||||
transition: all .25s ease;
|
|
||||||
font-family:inherit;
|
|
||||||
box-shadow: 0 4px 20px rgba(16,185,129,0.3);
|
|
||||||
}
|
}
|
||||||
.cta-btn svg { width:20px; height:20px; }
|
.cta-btn:hover { background:var(--accent-hover); }
|
||||||
.cta-btn:hover { transform:translateY(-2px); box-shadow:0 6px 30px rgba(16,185,129,0.4); }
|
.cta-btn:active { background:var(--accent-press); transform:scale(.98); }
|
||||||
|
.cta-count { background:rgba(255,255,255,0.15); padding:2px 8px; border-radius:var(--radius-sm); font-size:11px; }
|
||||||
|
|
||||||
.cta-count {
|
/* ---- Update Rows ---- */
|
||||||
background: rgba(255,255,255,0.2);
|
|
||||||
padding: 2px 10px; border-radius:10px;
|
|
||||||
font-size:12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---- Update Card ---- */
|
|
||||||
.upd-row {
|
.upd-row {
|
||||||
padding: 14px 18px;
|
padding:10px 14px; background:var(--card); border:1px solid var(--border);
|
||||||
background: var(--surface);
|
border-radius:var(--radius); margin-bottom:4px; transition:background .12s ease;
|
||||||
border: 1px solid var(--border);
|
|
||||||
border-radius: var(--r);
|
|
||||||
margin-bottom: 8px;
|
|
||||||
transition: all .2s ease;
|
|
||||||
}
|
}
|
||||||
.upd-row:hover { border-color: rgba(59,130,246,0.2); }
|
.upd-row:hover { background:var(--surface-hover); }
|
||||||
.upd-row.pending { border-left: 3px solid var(--accent); }
|
.upd-row.pending { border-left:3px solid var(--accent-bg); }
|
||||||
.upd-row.done { opacity:.5; }
|
.upd-row.done { opacity:.45; }
|
||||||
|
.upd-title { font-size:13px; font-weight:600; margin-bottom:3px; }
|
||||||
.upd-title { font-size:13.5px; font-weight:600; margin-bottom:5px; }
|
.upd-meta { display:flex; gap:12px; flex-wrap:wrap; font-size:11px; color:var(--text-dim); }
|
||||||
.upd-meta {
|
.upd-tag { display:flex; align-items:center; gap:3px; }
|
||||||
display:flex; gap:14px; flex-wrap:wrap;
|
.upd-tag img { width:12px; height:12px; }
|
||||||
font-size:11.5px; color:var(--text-dim);
|
.upd-section { font-size:12px; font-weight:600; margin:12px 0 6px; display:flex; align-items:center; gap:6px; }
|
||||||
}
|
.upd-section img { width:14px; height:14px; }
|
||||||
.upd-tag { display:flex; align-items:center; gap:4px; }
|
.upd-section.pend { color:var(--accent); }
|
||||||
.upd-tag svg { width:12px; height:12px; }
|
|
||||||
.upd-section {
|
|
||||||
font-size:12px; font-weight:700; text-transform:uppercase;
|
|
||||||
letter-spacing:.5px; margin:16px 0 8px;
|
|
||||||
display:flex; align-items:center; gap:6px;
|
|
||||||
}
|
|
||||||
.upd-section svg { width:14px; height:14px; }
|
|
||||||
.upd-section.pend { color:var(--accent-light); }
|
|
||||||
.upd-section.inst { color:var(--green); }
|
.upd-section.inst { color:var(--green); }
|
||||||
|
|
||||||
/* ---- System Grid ---- */
|
/* ---- System Grid ---- */
|
||||||
.sys-grid {
|
.sys-grid { display:grid; grid-template-columns:1fr 1fr; gap:8px; padding:12px 20px; overflow-y:auto; flex:1; }
|
||||||
display:grid;
|
.sys-card { background:var(--card); border:1px solid var(--border); border-radius:var(--radius); overflow:hidden; }
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
gap: 14px;
|
|
||||||
padding: 20px 24px;
|
|
||||||
overflow-y: auto;
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sys-card {
|
|
||||||
background: var(--surface);
|
|
||||||
border: 1px solid var(--border);
|
|
||||||
border-radius: var(--r);
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sys-card-head {
|
.sys-card-head {
|
||||||
display:flex; align-items:center; gap:8px;
|
display:flex; align-items:center; gap:6px;
|
||||||
padding: 12px 18px;
|
padding:10px 14px; background:rgba(255,255,255,0.02);
|
||||||
background: rgba(255,255,255,0.02);
|
border-bottom:1px solid var(--border);
|
||||||
border-bottom: 1px solid var(--border);
|
font-size:12px; font-weight:600; color:var(--text-sec);
|
||||||
font-size: 12px; font-weight:700;
|
|
||||||
text-transform:uppercase; letter-spacing:.5px;
|
|
||||||
color: var(--text-sec);
|
|
||||||
}
|
|
||||||
.sys-card-head svg { width:16px; height:16px; color:var(--accent-light); }
|
|
||||||
|
|
||||||
.sys-row {
|
|
||||||
display:flex; justify-content:space-between;
|
|
||||||
padding: 10px 18px;
|
|
||||||
font-size: 12.5px;
|
|
||||||
border-bottom: 1px solid rgba(255,255,255,0.03);
|
|
||||||
}
|
}
|
||||||
|
.sys-row { display:flex; justify-content:space-between; padding:7px 14px; font-size:12px; border-bottom:1px solid var(--border); }
|
||||||
.sys-row:last-of-type { border-bottom:none; }
|
.sys-row:last-of-type { border-bottom:none; }
|
||||||
.sys-row span:first-child { color:var(--text-dim); }
|
.sys-row span:first-child { color:var(--text-dim); }
|
||||||
.sys-row span:last-child { font-weight:600; max-width:55%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
|
.sys-row span:last-child { font-weight:600; max-width:55%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
|
||||||
|
.sys-bar-wrap { padding:6px 14px 10px; }
|
||||||
.sys-bar-wrap { padding:8px 18px 14px; }
|
.sys-bar { height:4px; background:rgba(255,255,255,0.06); border-radius:2px; overflow:hidden; }
|
||||||
.sys-bar { height:6px; background:rgba(255,255,255,0.05); border-radius:3px; overflow:hidden; }
|
.sys-bar-fill { height:100%; border-radius:2px; transition:width .8s ease; }
|
||||||
.sys-bar-fill { height:100%; border-radius:3px; transition:width .8s ease; }
|
.ram-bar { background:linear-gradient(90deg,var(--green),#6ccb5f); }
|
||||||
.ram-bar { background: linear-gradient(90deg, var(--green), #34d399); }
|
.disk-bar { background:linear-gradient(90deg,var(--accent-bg),var(--accent)); }
|
||||||
.disk-bar { background: linear-gradient(90deg, var(--accent), var(--accent-light)); }
|
|
||||||
|
|
||||||
/* ---- Footer ---- */
|
/* ---- Footer ---- */
|
||||||
.app-footer {
|
.app-footer {
|
||||||
display:flex; justify-content:space-between; align-items:center;
|
display:flex; justify-content:space-between; align-items:center;
|
||||||
padding: 8px 24px;
|
padding:6px 16px; border-top:1px solid var(--border);
|
||||||
border-top: 1px solid var(--border);
|
background:var(--bg); font-size:11px; color:var(--text-dim); flex-shrink:0;
|
||||||
background: rgba(10,22,40,0.6);
|
|
||||||
font-size: 11px; color: var(--text-dim);
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
}
|
||||||
.footer-right { display:flex; gap:4px; }
|
.footer-right { display:flex; gap:2px; }
|
||||||
.footer-btn {
|
.footer-btn {
|
||||||
display:flex; align-items:center; gap:4px;
|
display:flex; align-items:center; gap:4px; padding:3px 8px;
|
||||||
padding:4px 12px;
|
background:transparent; border:1px solid transparent; border-radius:var(--radius-sm);
|
||||||
background:transparent; border:1px solid transparent;
|
color:var(--text-dim); font-size:11px; cursor:pointer;
|
||||||
border-radius:4px;
|
font-family:inherit; transition:all .12s ease;
|
||||||
color:var(--text-dim); font-size:11px;
|
|
||||||
cursor:pointer;
|
|
||||||
font-family:inherit;
|
|
||||||
transition: all .15s ease;
|
|
||||||
}
|
}
|
||||||
.footer-btn svg { width:12px; height:12px; }
|
.footer-btn:hover { color:var(--text-sec); background:var(--surface-hover); }
|
||||||
.footer-btn:hover { color:var(--text-sec); border-color:var(--border); }
|
.credit-link { color:var(--accent); text-decoration:none; font-weight:600; }
|
||||||
|
.credit-link:hover { text-decoration:underline; }
|
||||||
|
|
||||||
/* ---- Loading ---- */
|
/* ---- Loading ---- */
|
||||||
.loading-overlay {
|
.loading-overlay {
|
||||||
position:fixed; inset:0;
|
position:fixed; inset:0;
|
||||||
background: rgba(8,12,24,0.92);
|
background:rgba(32,32,32,0.85); backdrop-filter:blur(20px);
|
||||||
backdrop-filter: blur(6px);
|
display:flex; align-items:center; justify-content:center; z-index:1000;
|
||||||
display:flex; align-items:center; justify-content:center;
|
|
||||||
z-index:1000;
|
|
||||||
}
|
}
|
||||||
.loading-card {
|
.loading-card {
|
||||||
text-align:center;
|
text-align:center; padding:36px 48px;
|
||||||
padding: 44px 56px;
|
background:var(--card); border:1px solid var(--border-light);
|
||||||
background: var(--surface);
|
border-radius:var(--radius-lg);
|
||||||
border:1px solid var(--border);
|
box-shadow:0 8px 32px rgba(0,0,0,.5);
|
||||||
border-radius:16px;
|
|
||||||
box-shadow: 0 16px 48px rgba(0,0,0,.5);
|
|
||||||
}
|
|
||||||
.loading-spinner {
|
|
||||||
width:64px; height:64px;
|
|
||||||
margin:0 auto 20px;
|
|
||||||
position:relative;
|
|
||||||
}
|
}
|
||||||
|
.loading-spinner { width:56px; height:56px; margin:0 auto 16px; position:relative; }
|
||||||
.spinner-ring {
|
.spinner-ring {
|
||||||
position:absolute; inset:0;
|
position:absolute; inset:0;
|
||||||
border:3px solid var(--border);
|
border:3px solid var(--border);
|
||||||
border-top-color: var(--accent);
|
border-top-color:var(--accent-bg);
|
||||||
border-radius:50%;
|
border-radius:50%; animation:spin .9s linear infinite;
|
||||||
animation: spin 1s linear infinite;
|
|
||||||
}
|
}
|
||||||
@keyframes spin { to{transform:rotate(360deg)} }
|
@keyframes spin{to{transform:rotate(360deg)}}
|
||||||
.spinner-icon { position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); color:var(--accent-light); }
|
.loading-title { font-size:14px; font-weight:600; margin-bottom:10px; }
|
||||||
.spinner-icon svg { width:24px; height:24px; }
|
.loading-dots { display:flex; justify-content:center; gap:4px; }
|
||||||
.loading-title { font-size:15px; font-weight:700; margin-bottom:14px; }
|
|
||||||
.loading-dots { display:flex; justify-content:center; gap:5px; }
|
|
||||||
.loading-dots span {
|
.loading-dots span {
|
||||||
width:5px; height:5px; border-radius:50%;
|
width:4px; height:4px; border-radius:50%; background:var(--accent-bg);
|
||||||
background:var(--accent);
|
animation:dotPulse 1.4s ease-in-out infinite;
|
||||||
animation: dotPulse 1.4s ease-in-out infinite;
|
|
||||||
}
|
}
|
||||||
.loading-dots span:nth-child(2){animation-delay:.2s}
|
.loading-dots span:nth-child(2){animation-delay:.2s}
|
||||||
.loading-dots span:nth-child(3){animation-delay:.4s}
|
.loading-dots span:nth-child(3){animation-delay:.4s}
|
||||||
@keyframes dotPulse {
|
@keyframes dotPulse{0%,80%,100%{opacity:.3;transform:scale(.8)}40%{opacity:1;transform:scale(1)}}
|
||||||
0%,80%,100%{opacity:.3;transform:scale(.8)}
|
|
||||||
40%{opacity:1;transform:scale(1)}
|
|
||||||
}
|
|
||||||
|
|||||||