Auto-Guardian-Core / index.html
AbdulElahGwaith's picture
Upload folder using huggingface_hub
7270c96 verified
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Auto-Guardian Dashboard</title>
<meta name="google-site-verification" content="google7cceda004d653872" />
<meta name="description" content="Auto-Guardian: A comprehensive security and monitoring system dashboard for modern infrastructure. Automated security monitoring and protection core system." />
<meta name="keywords" content="security, monitoring, automation, guardian, dashboard, infrastructure, protection" />
<meta name="author" content="Abdulelah Othman Gwaith" />
<meta property="og:title" content="Auto-Guardian Dashboard" />
<meta property="og:description" content="Automated security monitoring and protection core system." />
<meta property="og:url" content="https://abdulelahothmangwaith.github.io/Auto-Guardian-Core/" />
<meta property="og:type" content="website" />
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "SoftwareApplication",
"name": "Auto-Guardian-Core",
"operatingSystem": "Linux, Windows, macOS",
"applicationCategory": "SecurityApplication",
"offers": {
"@type": "Offer",
"price": "0",
"priceCurrency": "USD"
},
"author": {
"@type": "Person",
"name": "Abdulelah Othman Gwaith"
},
"description": "An automated security monitoring and protection core system designed for modern infrastructure.",
"url": "https://abdulelahothmangwaith.github.io/Auto-Guardian-Core/"
}
</script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--primary: #0F172A;
--secondary: #3B82F6;
--success: #10B981;
--danger: #EF4444;
--warning: #F59E0B;
--bg: #F8FAFC;
--card-bg: #FFFFFF;
--text: #1E293B;
--text-muted: #64748B;
--border: #E2E8F0;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: var(--bg);
color: var(--text);
min-height: 100vh;
overflow-x: hidden;
}
.dashboard {
display: flex;
flex-direction: row;
min-height: 100vh;
width: 100%;
}
/* Sidebar */
.sidebar {
background: var(--primary);
color: white;
padding: 20px 0;
width: 240px;
height: 100vh;
overflow-y: auto;
flex-shrink: 0;
position: sticky;
top: 0;
}
.logo {
padding: 20px;
text-align: center;
border-bottom: 1px solid rgba(255,255,255,0.1);
margin-bottom: 20px;
}
.logo h1 {
font-size: 20px;
font-weight: 700;
color: var(--secondary);
}
.logo span {
font-size: 12px;
color: var(--text-muted);
}
.nav-menu {
list-style: none;
}
.nav-item {
padding: 12px 20px;
display: flex;
align-items: center;
gap: 12px;
cursor: pointer;
transition: all 0.3s ease;
border-right: 3px solid transparent;
}
.nav-item:hover, .nav-item.active {
background: rgba(59, 130, 246, 0.1);
border-right-color: var(--secondary);
}
.nav-item svg {
width: 20px;
height: 20px;
}
.nav-item span {
font-size: 14px;
}
/* Main Content */
.main-content {
flex: 1;
padding: 20px 30px;
min-width: 0;
overflow-x: hidden;
}
/* Header */
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30px;
flex-wrap: wrap;
gap: 15px;
}
.header h2 {
font-size: 24px;
font-weight: 600;
}
.header-actions {
display: flex;
gap: 12px;
align-items: center;
}
.search-box {
display: flex;
align-items: center;
background: var(--card-bg);
border: 1px solid var(--border);
border-radius: 8px;
padding: 8px 16px;
gap: 8px;
position: relative;
}
.search-box:hover {
border-color: var(--secondary);
}
.search-box input {
border: none;
outline: none;
font-size: 14px;
width: 150px;
background: transparent;
flex: 1;
min-width: 100px;
}
.search-results {
display: none;
position: absolute;
top: 100%;
left: 0;
right: 0;
background: white;
border: 1px solid var(--border);
border-radius: 8px;
margin-top: 8px;
max-height: 300px;
overflow-y: auto;
box-shadow: 0 4px 20px rgba(0,0,0,0.1);
z-index: 100;
}
.search-results.active {
display: block;
}
.search-result-item {
padding: 12px 16px;
border-bottom: 1px solid var(--border);
cursor: pointer;
transition: background 0.3s ease;
}
.search-result-item:hover {
background: var(--bg);
}
.search-result-item:last-child {
border-bottom: none;
}
.notification-btn {
position: relative;
background: var(--card-bg);
border: 1px solid var(--border);
border-radius: 8px;
padding: 8px 12px;
cursor: pointer;
transition: all 0.3s ease;
}
.notification-btn:hover {
border-color: var(--secondary);
}
.notification-badge {
position: absolute;
top: -5px;
right: -5px;
background: var(--danger);
color: white;
font-size: 10px;
padding: 2px 6px;
border-radius: 10px;
}
/* Settings Panel */
.settings-panel {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.5);
z-index: 1000;
justify-content: center;
align-items: center;
}
.settings-panel.active {
display: flex;
}
.settings-content {
background: white;
border-radius: 16px;
padding: 30px;
width: 90%;
max-width: 500px;
max-height: 80vh;
overflow-y: auto;
}
.settings-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24px;
}
.settings-header h3 {
font-size: 20px;
}
.close-btn {
background: none;
border: none;
font-size: 24px;
cursor: pointer;
color: var(--text-muted);
}
.setting-item {
margin-bottom: 20px;
}
.setting-label {
display: block;
font-size: 14px;
font-weight: 500;
margin-bottom: 8px;
}
.setting-description {
font-size: 12px;
color: var(--text-muted);
margin-bottom: 8px;
}
.setting-input {
width: 100%;
padding: 10px 14px;
border: 1px solid var(--border);
border-radius: 8px;
font-size: 14px;
transition: all 0.3s ease;
}
.setting-input:focus {
outline: none;
border-color: var(--secondary);
}
.setting-select {
width: 100%;
padding: 10px 14px;
border: 1px solid var(--border);
border-radius: 8px;
font-size: 14px;
background: white;
cursor: pointer;
}
.setting-toggle {
display: flex;
align-items: center;
gap: 12px;
cursor: pointer;
}
.toggle-switch {
position: relative;
width: 50px;
height: 26px;
background: var(--border);
border-radius: 13px;
transition: all 0.3s ease;
}
.toggle-switch.active {
background: var(--secondary);
}
.toggle-switch::after {
content: '';
position: absolute;
width: 22px;
height: 22px;
background: white;
border-radius: 50%;
top: 2px;
left: 2px;
transition: all 0.3s ease;
}
.toggle-switch.active::after {
left: 26px;
}
.save-btn {
width: 100%;
padding: 12px;
background: var(--secondary);
color: white;
border: none;
border-radius: 8px;
font-size: 14px;
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
}
.save-btn:hover {
background: var(--primary);
}
/* Stats Grid */
.stats-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20px;
margin-bottom: 30px;
}
.stat-card {
background: var(--card-bg);
border-radius: 12px;
padding: 20px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
transition: transform 0.3s ease, box-shadow 0.3s ease;
cursor: pointer;
}
.stat-card:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}
.stat-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 12px;
}
.stat-icon {
width: 40px;
height: 40px;
border-radius: 10px;
display: flex;
align-items: center;
justify-content: center;
}
.stat-icon.blue { background: rgba(59, 130, 246, 0.1); color: var(--secondary); }
.stat-icon.green { background: rgba(16, 185, 129, 0.1); color: var(--success); }
.stat-icon.red { background: rgba(239, 68, 68, 0.1); color: var(--danger); }
.stat-icon.yellow { background: rgba(245, 158, 11, 0.1); color: var(--warning); }
.stat-trend {
font-size: 12px;
display: flex;
align-items: center;
gap: 4px;
}
.stat-trend.up { color: var(--success); }
.stat-trend.down { color: var(--danger); }
.stat-value {
font-size: 28px;
font-weight: 700;
margin-bottom: 4px;
}
.stat-label {
font-size: 13px;
color: var(--text-muted);
}
/* Charts Section */
.charts-section {
display: grid;
grid-template-columns: 2fr 1fr;
gap: 20px;
margin-bottom: 30px;
}
.chart-card {
background: var(--card-bg);
border-radius: 12px;
padding: 20px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
.chart-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.chart-title {
font-size: 16px;
font-weight: 600;
}
.chart-tabs {
display: flex;
gap: 8px;
}
.chart-tab {
padding: 6px 12px;
border-radius: 6px;
font-size: 12px;
cursor: pointer;
background: var(--bg);
border: none;
transition: all 0.3s ease;
}
.chart-tab.active {
background: var(--secondary);
color: white;
}
.chart-tab:hover:not(.active) {
background: var(--border);
}
/* Area Chart */
.area-chart {
height: 250px;
position: relative;
}
.chart-svg {
width: 100%;
height: 100%;
}
/* Donut Chart */
.donut-chart {
display: flex;
align-items: center;
justify-content: center;
gap: 30px;
}
.donut-svg {
width: 180px;
height: 180px;
}
.donut-legend {
display: flex;
flex-direction: column;
gap: 12px;
}
.legend-item {
display: flex;
align-items: center;
gap: 8px;
}
.legend-color {
width: 12px;
height: 12px;
border-radius: 3px;
}
.legend-label {
font-size: 13px;
color: var(--text-muted);
}
.legend-value {
font-size: 14px;
font-weight: 600;
margin-right: auto;
}
/* Activity Section */
.activity-section {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
}
.activity-card {
background: var(--card-bg);
border-radius: 12px;
padding: 20px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
.activity-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
}
.activity-title {
font-size: 16px;
font-weight: 600;
}
.view-all {
font-size: 13px;
color: var(--secondary);
cursor: pointer;
}
.view-all:hover {
text-decoration: underline;
}
/* Issues List */
.issues-list {
display: flex;
flex-direction: column;
gap: 12px;
}
.issue-item {
display: flex;
align-items: center;
gap: 12px;
padding: 12px;
background: var(--bg);
border-radius: 8px;
transition: all 0.3s ease;
cursor: pointer;
}
.issue-item:hover {
background: rgba(59, 130, 246, 0.05);
}
.issue-icon {
width: 32px;
height: 32px;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
}
.issue-content {
flex: 1;
}
.issue-title {
font-size: 13px;
font-weight: 500;
margin-bottom: 2px;
}
.issue-meta {
font-size: 11px;
color: var(--text-muted);
}
.issue-badge {
padding: 4px 10px;
border-radius: 20px;
font-size: 11px;
font-weight: 500;
}
.badge-critical { background: rgba(239, 68, 68, 0.1); color: var(--danger); }
.badge-warning { background: rgba(245, 158, 11, 0.1); color: var(--warning); }
.badge-info { background: rgba(59, 130, 246, 0.1); color: var(--secondary); }
.badge-success { background: rgba(16, 185, 129, 0.1); color: var(--success); }
/* Repositories List */
.repos-list {
display: flex;
flex-direction: column;
gap: 12px;
}
.repo-item {
display: flex;
align-items: center;
gap: 12px;
padding: 12px;
background: var(--bg);
border-radius: 8px;
transition: all 0.3s ease;
cursor: pointer;
}
.repo-item:hover {
background: rgba(59, 130, 246, 0.05);
}
.repo-icon {
width: 36px;
height: 36px;
border-radius: 8px;
background: var(--primary);
display: flex;
align-items: center;
justify-content: center;
color: white;
}
.repo-content {
flex: 1;
}
.repo-name {
font-size: 13px;
font-weight: 500;
margin-bottom: 2px;
}
.repo-stats {
display: flex;
gap: 12px;
font-size: 11px;
color: var(--text-muted);
}
.repo-status {
display: flex;
align-items: center;
gap: 4px;
font-size: 12px;
}
.status-dot {
width: 8px;
height: 8px;
border-radius: 50%;
}
.status-dot.active { background: var(--success); }
.status-dot.warning { background: var(--warning); }
.status-dot.error { background: var(--danger); }
/* Toast Notifications */
.toast-container {
position: fixed;
top: 20px;
left: 50%;
transform: translateX(-50%);
z-index: 2000;
display: flex;
flex-direction: column;
gap: 10px;
}
.toast {
padding: 14px 20px;
background: var(--primary);
color: white;
border-radius: 10px;
box-shadow: 0 4px 20px rgba(0,0,0,0.2);
display: flex;
align-items: center;
gap: 10px;
animation: slideIn 0.3s ease, fadeOut 0.3s ease 2.7s;
}
.toast.success { background: var(--success); }
.toast.error { background: var(--danger); }
.toast.warning { background: var(--warning); }
.toast.info { background: var(--secondary); }
@keyframes slideIn {
from { transform: translateY(-20px); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
@keyframes fadeOut {
from { opacity: 1; }
to { opacity: 0; }
}
/* Responsive */
@media (max-width: 1200px) {
.stats-grid {
grid-template-columns: repeat(2, 1fr);
}
.charts-section {
grid-template-columns: 1fr;
}
.activity-section {
grid-template-columns: 1fr;
}
}
@media (max-width: 992px) {
.sidebar {
position: fixed;
right: -240px;
top: 0;
z-index: 1000;
transition: right 0.3s ease;
box-shadow: -4px 0 20px rgba(0,0,0,0.1);
}
.sidebar.active {
right: 0;
}
.sidebar-overlay {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.5);
z-index: 999;
}
.sidebar-overlay.active {
display: block;
}
.main-content {
width: 100%;
padding: 15px 20px;
}
.mobile-menu-btn {
display: flex !important;
}
.header-actions {
gap: 8px;
}
.search-box {
min-width: 120px;
}
.search-box input {
width: 80px;
}
}
@media (max-width: 768px) {
.dashboard {
flex-direction: column;
}
.stats-grid {
grid-template-columns: 1fr;
gap: 12px;
}
.stat-card {
padding: 15px;
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
}
.stat-header {
margin-bottom: 0;
width: auto;
}
.stat-value {
font-size: 24px;
text-align: left;
}
.stat-label {
text-align: left;
width: 100%;
}
.charts-section {
gap: 15px;
margin-bottom: 20px;
}
.chart-card {
padding: 15px;
}
.area-chart {
height: 200px;
}
.donut-chart {
flex-direction: column;
gap: 15px;
}
.donut-svg {
width: 150px;
height: 150px;
}
.activity-section {
gap: 15px;
}
.activity-card {
padding: 15px;
}
.header {
margin-bottom: 20px;
}
.header h2 {
font-size: 20px;
width: 100%;
}
.header-actions {
width: 100%;
justify-content: space-between;
}
.search-box {
flex: 1;
min-width: 0;
}
.search-box input {
width: 100%;
}
.notification-btn {
padding: 8px;
}
}
@media (max-width: 480px) {
.stat-card {
padding: 12px;
}
.stat-icon {
width: 36px;
height: 36px;
}
.stat-value {
font-size: 20px;
}
.stat-label {
font-size: 12px;
}
.chart-title {
font-size: 14px;
}
.chart-tabs {
gap: 4px;
}
.chart-tab {
padding: 4px 8px;
font-size: 11px;
}
.issue-item, .repo-item {
padding: 10px;
}
.issue-icon {
width: 28px;
height: 28px;
}
.issue-title {
font-size: 12px;
}
.issue-meta {
font-size: 10px;
}
}
/* Mobile Menu Button */
.mobile-menu-btn {
display: none;
position: fixed;
bottom: 20px;
left: 20px;
width: 50px;
height: 50px;
border-radius: 50%;
background: var(--secondary);
color: white;
border: none;
cursor: pointer;
z-index: 1001;
box-shadow: 0 4px 15px rgba(59, 130, 246, 0.4);
align-items: center;
justify-content: center;
transition: all 0.3s ease;
}
.mobile-menu-btn:hover {
transform: scale(1.1);
background: var(--primary);
}
.mobile-menu-btn svg {
width: 24px;
height: 24px;
}
/* Sidebar Overlay */
.sidebar-overlay {
display: none;
}
</style>
</head>
<body>
<div class="dashboard">
<!-- Sidebar Overlay -->
<div class="sidebar-overlay" id="sidebarOverlay" onclick="toggleMobileMenu()"></div>
<!-- Sidebar -->
<aside class="sidebar" id="sidebar">
<div class="logo">
<h1>Auto-Guardian</h1>
<span>Security Dashboard</span>
</div>
<ul class="nav-menu">
<li class="nav-item active" data-view="dashboard">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z"/>
</svg>
<span>لوحة التحكم</span>
</li>
<li class="nav-item" data-view="protection">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"/>
</svg>
<span>الحماية</span>
</li>
<li class="nav-item" data-view="analysis">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-3 7h3m-3 4h3m-6-4h.01M9 16h.01"/>
</svg>
<span>الفحص والتحليل</span>
</li>
<li class="nav-item" data-view="reports">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"/>
</svg>
<span>التقارير</span>
</li>
<li class="nav-item" data-view="settings" id="settingsNavItem">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
</svg>
<span>الإعدادات</span>
</li>
<li class="nav-item" data-view="help">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.228 9c.549-1.165 2.03-2 3.772-2 2.21 0 4 1.343 4 3 0 1.4-1.278 2.575-3.006 2.907-.542.104-.994.54-.994 1.093m0 3h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
<span>المساعدة</span>
</li>
</ul>
</aside>
<!-- Mobile Menu Button -->
<button class="mobile-menu-btn" id="mobileMenuBtn" onclick="toggleMobileMenu()">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/>
</svg>
</button>
<!-- Main Content -->
<main class="main-content">
<!-- Header -->
<header class="header">
<h2>لوحة تحكم Auto-Guardian</h2>
<div class="header-actions">
<div class="search-box" id="searchBox">
<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/>
</svg>
<input type="text" placeholder="بحث..." id="searchInput">
<div class="search-results" id="searchResults"></div>
</div>
<button class="notification-btn" id="notificationBtn">
<svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9"/>
</svg>
<span class="notification-badge" id="notificationBadge">5</span>
</button>
</div>
</header>
<!-- Stats Grid -->
<div class="stats-grid">
<div class="stat-card" onclick="filterIssues('critical')">
<div class="stat-header">
<div class="stat-icon blue">
<svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"/>
</svg>
</div>
<span class="stat-trend up" id="trendCritical">↑ 12%</span>
</div>
<div class="stat-value" id="statThreats">1,247</div>
<div class="stat-label">التهديدات المحظورة</div>
</div>
<div class="stat-card">
<div class="stat-header">
<div class="stat-icon green">
<svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
</div>
<span class="stat-trend up" id="trendSuccess">↑ 8%</span>
</div>
<div class="stat-value" id="statSuccess">99.9%</div>
<div class="stat-label">معدل النجاح</div>
</div>
<div class="stat-card" onclick="filterIssues('open')">
<div class="stat-header">
<div class="stat-icon red">
<svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
</div>
<span class="stat-trend down" id="trendOpen">↓ 3%</span>
</div>
<div class="stat-value" id="statOpen">23</div>
<div class="stat-label">المشكلات المفتوحة</div>
</div>
<div class="stat-card">
<div class="stat-header">
<div class="stat-icon yellow">
<svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"/>
</svg>
</div>
<span class="stat-trend up" id="trendResponse">↑ 15%</span>
</div>
<div class="stat-value" id="statResponse">0.3s</div>
<div class="stat-label">زمن الاستجابة</div>
</div>
</div>
<!-- Charts Section -->
<div class="charts-section">
<div class="chart-card">
<div class="chart-header">
<h3 class="chart-title">نشاط الفحص والأمان</h3>
<div class="chart-tabs">
<button class="chart-tab" data-period="day" onclick="changePeriod('day')">24 ساعة</button>
<button class="chart-tab active" data-period="week" onclick="changePeriod('week')">أسبوع</button>
<button class="chart-tab" data-period="month" onclick="changePeriod('month')">شهر</button>
</div>
</div>
<div class="area-chart">
<svg class="chart-svg" viewBox="0 0 800 250" id="mainChart">
<!-- Grid lines -->
<line x1="50" y1="30" x2="750" y2="30" stroke="#E2E8F0" stroke-width="1"/>
<line x1="50" y1="80" x2="750" y2="80" stroke="#E2E8F0" stroke-width="1"/>
<line x1="50" y1="130" x2="750" y2="130" stroke="#E2E8F0" stroke-width="1"/>
<line x1="50" y1="180" x2="750" y2="180" stroke="#E2E8F0" stroke-width="1"/>
<!-- Area gradient -->
<defs>
<linearGradient id="areaGradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#3B82F6;stop-opacity:0.3"/>
<stop offset="100%" style="stop-color:#3B82F6;stop-opacity:0.05"/>
</linearGradient>
</defs>
<!-- Area path -->
<path d="M50,180 L100,150 L150,160 L200,120 L250,140 L300,100 L350,110 L400,70 L450,90 L500,60 L550,80 L600,50 L650,65 L700,40 L750,55 L750,180 Z" fill="url(#areaGradient)"/>
<!-- Line -->
<path d="M50,180 L100,150 L150,160 L200,120 L250,140 L300,100 L350,110 L400,70 L450,90 L500,60 L550,80 L600,50 L650,65 L700,40 L750,55" fill="none" stroke="#3B82F6" stroke-width="3" stroke-linecap="round"/>
<!-- Data points -->
<circle cx="100" cy="150" r="5" fill="#3B82F6" class="chart-point" data-value="45"/>
<circle cx="200" cy="120" r="5" fill="#3B82F6" class="chart-point" data-value="60"/>
<circle cx="300" cy="100" r="5" fill="#3B82F6" class="chart-point" data-value="70"/>
<circle cx="400" cy="70" r="5" fill="#3B82F6" class="chart-point" data-value="85"/>
<circle cx="500" cy="60" r="5" fill="#3B82F6" class="chart-point" data-value="90"/>
<circle cx="600" cy="50" r="5" fill="#3B82F6" class="chart-point" data-value="95"/>
<circle cx="700" cy="40" r="5" fill="#3B82F6" class="chart-point" data-value="100"/>
<!-- Labels -->
<text x="50" y="200" fill="#64748B" font-size="11">السبت</text>
<text x="150" y="200" fill="#64748B" font-size="11">الأحد</text>
<text x="250" y="200" fill="#64748B" font-size="11">الاثنين</text>
<text x="350" y="200" fill="#64748B" font-size="11">الثلاثاء</text>
<text x="450" y="200" fill="#64748B" font-size="11">الأربعاء</text>
<text x="550" y="200" fill="#64748B" font-size="11">الخميس</text>
<text x="650" y="200" fill="#64748B" font-size="11">الجمعة</text>
<!-- Y-axis labels -->
<text x="45" y="35" text-anchor="end" fill="#64748B" font-size="10">100</text>
<text x="45" y="85" text-anchor="end" fill="#64748B" font-size="10">75</text>
<text x="45" y="135" text-anchor="end" fill="#64748B" font-size="10">50</text>
<text x="45" y="185" text-anchor="end" fill="#64748B" font-size="10">25</text>
</svg>
</div>
</div>
<div class="chart-card">
<div class="chart-header">
<h3 class="chart-title">توزيع المشكلات</h3>
</div>
<div class="donut-chart">
<svg class="donut-svg" viewBox="0 0 180 180">
<circle cx="90" cy="90" r="70" fill="none" stroke="#E2E8F0" stroke-width="25"/>
<circle cx="90" cy="90" r="70" fill="none" stroke="#EF4444" stroke-width="25" stroke-dasharray="110 308" stroke-dashoffset="0" transform="rotate(-90 90 90)"/>
<circle cx="90" cy="90" r="70" fill="none" stroke="#F59E0B" stroke-width="25" stroke-dasharray="88 308" stroke-dashoffset="-110" transform="rotate(-90 90 90)"/>
<circle cx="90" cy="90" r="70" fill="none" stroke="#3B82F6" stroke-width="25" stroke-dasharray="66 308" stroke-dashoffset="-198" transform="rotate(-90 90 90)"/>
<circle cx="90" cy="90" r="70" fill="none" stroke="#10B981" stroke-width="25" stroke-dasharray="44 308" stroke-dashoffset="-264" transform="rotate(-90 90 90)"/>
<text x="90" y="85" text-anchor="middle" font-size="24" font-weight="bold" fill="#0F172A" id="donutTotal">23</text>
<text x="90" y="105" text-anchor="middle" font-size="12" fill="#64748B">إجمالي</text>
</svg>
<div class="donut-legend">
<div class="legend-item">
<div class="legend-color" style="background:#EF4444"></div>
<span class="legend-label">حرجة</span>
<span class="legend-value" id="legendCritical">5</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background:#F59E0B"></div>
<span class="legend-label">عالية</span>
<span class="legend-value" id="legendHigh">7</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background:#3B82F6"></div>
<span class="legend-label">متوسطة</span>
<span class="legend-value" id="legendMedium">6</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background:#10B981"></div>
<span class="legend-label">منخفضة</span>
<span class="legend-value" id="legendLow">5</span>
</div>
</div>
</div>
</div>
</div>
<!-- Activity Section -->
<div class="activity-section">
<div class="activity-card">
<div class="activity-header">
<h3 class="activity-title">أحدث المشكلات</h3>
<span class="view-all" onclick="filterIssues('all')">عرض الكل →</span>
</div>
<div class="issues-list" id="issuesList">
<!-- Issues will be populated by JavaScript -->
</div>
</div>
<div class="activity-card">
<div class="activity-header">
<h3 class="activity-title">المستودعات النشطة</h3>
<span class="view-all">عرض الكل →</span>
</div>
<div class="repos-list" id="reposList">
<!-- Repositories will be populated by JavaScript -->
</div>
</div>
</div>
</main>
</div>
<!-- Settings Panel -->
<div class="settings-panel" id="settingsPanel">
<div class="settings-content">
<div class="settings-header">
<h3>⚙️ الإعدادات</h3>
<button class="close-btn" onclick="closeSettings()">&times;</button>
</div>
<div class="setting-item">
<label class="setting-label">اسم المستخدم</label>
<input type="text" class="setting-input" id="settingUsername" placeholder="أدخل اسم المستخدم">
</div>
<div class="setting-item">
<label class="setting-label">البريد الإلكتروني</label>
<input type="email" class="setting-input" id="settingEmail" placeholder="أدخل البريد الإلكتروني">
</div>
<div class="setting-item">
<label class="setting-label">لغة الواجهة</label>
<select class="setting-select" id="settingLanguage">
<option value="ar">العربية</option>
<option value="en">English</option>
</select>
</div>
<div class="setting-item">
<label class="setting-label">السمة</label>
<select class="setting-select" id="settingTheme">
<option value="light">فاتحة</option>
<option value="dark">داكنة</option>
<option value="auto">تلقائي</option>
</select>
</div>
<div class="setting-item">
<label class="setting-label">فحص تلقائي عند الحفظ</label>
<div class="setting-toggle" onclick="toggleSetting('autoScan')">
<div class="toggle-switch" id="toggleAutoScan"></div>
<span>تشغيل</span>
</div>
<p class="setting-description">إجراء فحص تلقائي للكود عند حفظ الملفات</p>
</div>
<div class="setting-item">
<label class="setting-label">إشعارات المشاكل الحرجة</label>
<div class="setting-toggle" onclick="toggleSetting('criticalAlerts')">
<div class="toggle-switch" id="toggleCriticalAlerts"></div>
<span>تشغيل</span>
</div>
<p class="setting-description">إرسال إشعارات فورية للمشاكل الأمنية الحرجة</p>
</div>
<div class="setting-item">
<label class="setting-label">الإصلاح التلقائي الآمن</label>
<div class="setting-toggle" onclick="toggleSetting('autoFix')">
<div class="toggle-switch" id="toggleAutoFix"></div>
<span>تشغيل</span>
</div>
<p class="setting-description">إصلاح المشاكل الآمنة تلقائياً دون تدخل</p>
</div>
<button class="save-btn" onclick="saveSettings()">💾 حفظ الإعدادات</button>
</div>
</div>
<!-- Toast Container -->
<div class="toast-container" id="toastContainer"></div>
<script>
// Data
let currentData = {
threats: 1247,
successRate: 99.9,
openIssues: 23,
responseTime: 0.3,
issues: [],
repos: []
};
let settings = {
username: '',
email: '',
language: 'ar',
theme: 'light',
autoScan: true,
criticalAlerts: true,
autoFix: true
};
// Sample Data
const sampleIssues = [
{ id: 1, title: 'ثغرة أمنية في وحدة المصادقة', file: 'auth-module.py', time: 'قبل 5 دقائق', severity: 'critical' },
{ id: 2, title: 'فشل في اختبارات الأداء', file: 'performance_test.py', time: 'قبل 23 دقيقة', severity: 'warning' },
{ id: 3, title: 'تحذير في تنسيق الكود', file: 'main_controller.dart', time: 'قبل ساعة', severity: 'info' },
{ id: 4, title: 'تم إصلاح مشكلة التنسيق تلقائياً', file: 'utils_helper.js', time: 'قبل ساعتين', severity: 'success' },
{ id: 5, title: 'مشكلة في اتصال قاعدة البيانات', file: 'db_connection.java', time: 'قبل ساعتين', severity: 'critical' },
{ id: 6, title: 'تحذير: استخدام دالة قديمة', file: 'legacy_code.py', time: 'قبل 3 ساعات', severity: 'warning' }
];
const sampleRepos = [
{ id: 1, name: 'auto-guardian-system', stars: 124, pullRequests: 45, bugs: 3, status: 'active' },
{ id: 2, name: 'payment-gateway-api', stars: 89, pullRequests: 32, bugs: 5, status: 'warning' },
{ id: 3, name: 'user-management-service', stars: 56, pullRequests: 18, bugs: 1, status: 'active' },
{ id: 4, name: 'data-analytics-platform', stars: 234, pullRequests: 67, bugs: 8, status: 'error' }
];
// Initialize
document.addEventListener('DOMContentLoaded', function() {
loadSettings();
loadData();
renderIssues();
renderRepos();
setupEventListeners();
setupMobileMenu();
showToast('🎉 مرحباً بك في Auto-Guardian!', 'success');
});
// Setup Mobile Menu
function setupMobileMenu() {
const mobileMenuBtn = document.getElementById('mobileMenuBtn');
if (mobileMenuBtn) {
// Show/hide mobile menu button based on screen size
const checkScreenSize = () => {
if (window.innerWidth <= 992) {
mobileMenuBtn.style.display = 'flex';
} else {
mobileMenuBtn.style.display = 'none';
closeMobileMenu();
}
};
checkScreenSize();
window.addEventListener('resize', checkScreenSize);
}
}
// Toggle Mobile Menu
function toggleMobileMenu() {
const sidebar = document.getElementById('sidebar');
const overlay = document.getElementById('sidebarOverlay');
if (sidebar && overlay) {
sidebar.classList.toggle('active');
overlay.classList.toggle('active');
}
}
// Close Mobile Menu
function closeMobileMenu() {
const sidebar = document.getElementById('sidebar');
const overlay = document.getElementById('sidebarOverlay');
if (sidebar) {
sidebar.classList.remove('active');
}
if (overlay) {
overlay.classList.remove('active');
}
}
// Load Settings from LocalStorage
function loadSettings() {
const saved = localStorage.getItem('autoGuardianSettings');
if (saved) {
settings = JSON.parse(saved);
}
// Update UI
document.getElementById('settingUsername').value = settings.username || '';
document.getElementById('settingEmail').value = settings.email || '';
document.getElementById('settingLanguage').value = settings.language || 'ar';
document.getElementById('settingTheme').value = settings.theme || 'light';
updateToggle('toggleAutoScan', settings.autoScan);
updateToggle('toggleCriticalAlerts', settings.criticalAlerts);
updateToggle('toggleAutoFix', settings.autoFix);
}
// Save Settings to LocalStorage
function saveSettings() {
settings.username = document.getElementById('settingUsername').value;
settings.email = document.getElementById('settingEmail').value;
settings.language = document.getElementById('settingLanguage').value;
settings.theme = document.getElementById('settingTheme').value;
localStorage.setItem('autoGuardianSettings', JSON.stringify(settings));
closeSettings();
showToast('✅ تم حفظ الإعدادات بنجاح!', 'success');
}
// Update toggle UI
function updateToggle(id, value) {
const toggle = document.getElementById(id);
if (value) {
toggle.classList.add('active');
} else {
toggle.classList.remove('active');
}
}
// Toggle setting
function toggleSetting(setting) {
settings[setting] = !settings[setting];
updateToggle('toggle' + setting.charAt(0).toUpperCase() + setting.slice(1), settings[setting]);
showToast(`⚙️ تم ${settings[setting] ? 'تفعيل' : 'تعطيل'} ${setting}`, 'info');
}
// Load Data
function loadData() {
currentData.issues = sampleIssues;
currentData.repos = sampleRepos;
// Randomize some values
currentData.threats = Math.floor(Math.random() * 2000) + 500;
currentData.openIssues = Math.floor(Math.random() * 30) + 10;
currentData.responseTime = (Math.random() * 0.5 + 0.1).toFixed(1);
updateStatsUI();
}
// Update Stats UI
function updateStatsUI() {
document.getElementById('statThreats').textContent = currentData.threats.toLocaleString();
document.getElementById('statSuccess').textContent = currentData.successRate + '%';
document.getElementById('statOpen').textContent = currentData.openIssues;
document.getElementById('statResponse').textContent = currentData.responseTime + 's';
// Update legend
const critical = currentData.issues.filter(i => i.severity === 'critical').length;
const warning = currentData.issues.filter(i => i.severity === 'warning').length;
const info = currentData.issues.filter(i => i.severity === 'info').length;
const success = currentData.issues.filter(i => i.severity === 'success').length;
document.getElementById('legendCritical').textContent = critical;
document.getElementById('legendHigh').textContent = warning;
document.getElementById('legendMedium').textContent = info;
document.getElementById('legendLow').textContent = success;
document.getElementById('donutTotal').textContent = currentData.issues.length;
}
// Render Issues
function renderIssues(issues = currentData.issues) {
const container = document.getElementById('issuesList');
container.innerHTML = '';
issues.forEach(issue => {
const severityClass = issue.severity === 'critical' ? 'badge-critical' :
issue.severity === 'warning' ? 'badge-warning' :
issue.severity === 'info' ? 'badge-info' : 'badge-success';
const severityLabel = issue.severity === 'critical' ? 'حرجة' :
issue.severity === 'warning' ? 'عالية' :
issue.severity === 'info' ? 'متوسطة' : 'تم الإصلاح';
const iconSvg = issue.severity === 'critical' ?
'<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"/></svg>' :
issue.severity === 'warning' ?
'<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>' :
issue.severity === 'success' ?
'<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>' :
'<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>';
const html = `
<div class="issue-item" onclick="showIssueDetails(${issue.id})">
<div class="issue-icon" style="background: rgba(${issue.severity === 'critical' ? '239, 68, 68' : issue.severity === 'warning' ? '245, 158, 11' : issue.severity === 'success' ? '16, 185, 129' : '59, 130, 246'}, 0.1); color: ${issue.severity === 'critical' ? '#EF4444' : issue.severity === 'warning' ? '#F59E0B' : issue.severity === 'success' ? '#10B981' : '#3B82F6'};">
${iconSvg}
</div>
<div class="issue-content">
<div class="issue-title">${issue.title}</div>
<div class="issue-meta">${issue.file}${issue.time}</div>
</div>
<span class="issue-badge ${severityClass}">${severityLabel}</span>
</div>
`;
container.innerHTML += html;
});
}
// Render Repositories
function renderRepos(repos = currentData.repos) {
const container = document.getElementById('reposList');
container.innerHTML = '';
repos.forEach(repo => {
const statusClass = repo.status === 'active' ? 'active' : repo.status === 'warning' ? 'warning' : 'error';
const statusLabel = repo.status === 'active' ? 'نشط' : repo.status === 'warning' ? 'يحتاج مراجعة' : 'مشاكل';
const statusColor = repo.status === 'active' ? '#10B981' : repo.status === 'warning' ? '#F59E0B' : '#EF4444';
const html = `
<div class="repo-item">
<div class="repo-icon">
<svg width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z"/>
</svg>
</div>
<div class="repo-content">
<div class="repo-name">${repo.name}</div>
<div class="repo-stats">
<span>⭐ ${repo.stars}</span>
<span>🔀 ${repo.pullRequests}</span>
<span>🐛 ${repo.bugs}</span>
</div>
</div>
<div class="repo-status">
<span class="status-dot ${statusClass}"></span>
<span style="color: ${statusColor};">${statusLabel}</span>
</div>
</div>
`;
container.innerHTML += html;
});
}
// Filter Issues
function filterIssues(type) {
let filtered = currentData.issues;
if (type === 'critical') {
filtered = currentData.issues.filter(i => i.severity === 'critical');
showToast(`🔍 عرض ${filtered.length} مشكلة حرجة`, 'info');
} else if (type === 'open') {
filtered = currentData.issues.filter(i => i.severity !== 'success');
showToast(`🔍 عرض ${filtered.length} مشكلة مفتوحة`, 'info');
} else if (type === 'all') {
showToast(`🔍 عرض ${filtered.length} مشكلة`, 'info');
}
renderIssues(filtered);
}
// Show Issue Details
function showIssueDetails(id) {
const issue = currentData.issues.find(i => i.id === id);
if (issue) {
showToast(`📋 ${issue.title} - ${issue.file}`, 'info');
}
}
// Change Chart Period
function changePeriod(period) {
// Update active tab
document.querySelectorAll('.chart-tab').forEach(tab => {
tab.classList.remove('active');
if (tab.dataset.period === period) {
tab.classList.add('active');
}
});
// Update chart data based on period
showToast(`📊 عرض بيانات ${period === 'day' ? '24 ساعة' : period === 'week' ? 'أسبوع' : 'شهر'}`, 'info');
// Simulate data update
const randomFactor = period === 'day' ? 1 : period === 'week' ? 7 : 30;
currentData.threats = Math.floor(Math.random() * 2000 * randomFactor) + 500;
updateStatsUI();
}
// Search Functionality
function setupEventListeners() {
// Navigation
document.querySelectorAll('.nav-item').forEach(item => {
item.addEventListener('click', function() {
const view = this.dataset.view;
document.querySelectorAll('.nav-item').forEach(i => i.classList.remove('active'));
this.classList.add('active');
// Close mobile menu when navigating
closeMobileMenu();
if (view === 'settings') {
openSettings();
} else if (view === 'help') {
showToast('📖 المساعدة: استخدم القائمة للتنقل بين الأقسام', 'info');
} else {
showToast(`📂 الانتقال إلى ${this.querySelector('span').textContent}`, 'info');
}
});
});
// Search
const searchInput = document.getElementById('searchInput');
const searchResults = document.getElementById('searchResults');
searchInput.addEventListener('input', function() {
const query = this.value.toLowerCase();
if (query.length < 2) {
searchResults.classList.remove('active');
return;
}
// Search in issues and repos
const results = [];
currentData.issues.forEach(issue => {
if (issue.title.toLowerCase().includes(query) || issue.file.toLowerCase().includes(query)) {
results.push({ type: 'issue', title: issue.title, subtitle: issue.file });
}
});
currentData.repos.forEach(repo => {
if (repo.name.toLowerCase().includes(query)) {
results.push({ type: 'repo', title: repo.name, subtitle: `⭐ ${repo.stars} | 🔀 ${repo.pullRequests}` });
}
});
if (results.length > 0) {
searchResults.innerHTML = results.map(r => `
<div class="search-result-item">
<div style="font-weight: 500;">${r.title}</div>
<div style="font-size: 12px; color: var(--text-muted);">${r.subtitle}</div>
</div>
`).join('');
searchResults.classList.add('active');
} else {
searchResults.innerHTML = '<div class="search-result-item">لا توجد نتائج</div>';
searchResults.classList.add('active');
}
});
searchInput.addEventListener('blur', function() {
setTimeout(() => {
searchResults.classList.remove('active');
}, 200);
});
searchInput.addEventListener('focus', function() {
if (this.value.length >= 2) {
searchResults.classList.add('active');
}
});
// Notification button
document.getElementById('notificationBtn').addEventListener('click', function() {
showToast('🔔 الإشعارات: 5 إشعارات جديدة', 'info');
document.getElementById('notificationBadge').textContent = '0';
});
}
// Settings Panel
function openSettings() {
document.getElementById('settingsPanel').classList.add('active');
}
function closeSettings() {
document.getElementById('settingsPanel').classList.remove('active');
}
// Toast Notifications
function showToast(message, type = 'info') {
const container = document.getElementById('toastContainer');
const toast = document.createElement('div');
toast.className = `toast ${type}`;
toast.innerHTML = message;
container.appendChild(toast);
setTimeout(() => {
toast.remove();
}, 3000);
}
// Close settings on outside click
document.getElementById('settingsPanel').addEventListener('click', function(e) {
if (e.target === this) {
closeSettings();
}
});
</script>
</body>
</html>