From 0fc51eb0327da50b53770c89bebff5358378753c Mon Sep 17 00:00:00 2001 From: Phillip Tarrant Date: Wed, 19 Nov 2025 21:45:36 -0600 Subject: [PATCH] Improve UI design system and fix notification positioning - Overhaul CSS with comprehensive design tokens (shadows, transitions, radii) - Add hover effects and smooth transitions to cards, buttons, tables - Improve typography hierarchy and color consistency - Remove inline styles from 10 template files for better maintainability - Add global notification container to ensure toasts appear above modals - Update showNotification/showAlert functions to use centralized container - Add accessibility improvements (focus states, reduced motion support) - Improve responsive design and mobile styling - Add print styles --- app/web/static/css/styles.css | 971 ++++++++++++++++++++++--- app/web/templates/alert_rules.html | 10 +- app/web/templates/alerts.html | 8 +- app/web/templates/base.html | 3 + app/web/templates/configs.html | 58 +- app/web/templates/dashboard.html | 18 +- app/web/templates/scans.html | 31 +- app/web/templates/schedule_create.html | 10 +- app/web/templates/schedule_edit.html | 10 +- app/web/templates/schedules.html | 15 +- app/web/templates/setup.html | 145 ++-- app/web/templates/sites.html | 92 +-- app/web/templates/webhooks/list.html | 2 +- 13 files changed, 1004 insertions(+), 369 deletions(-) diff --git a/app/web/static/css/styles.css b/app/web/static/css/styles.css index f94d121..ff3ce6b 100644 --- a/app/web/static/css/styles.css +++ b/app/web/static/css/styles.css @@ -1,15 +1,28 @@ -/* CSS Variables */ +/* ============================================== + CSS Variables - Design System + ============================================== */ :root { - /* Custom Variables */ + /* Primary Colors */ --bg-primary: #0f172a; --bg-secondary: #1e293b; --bg-tertiary: #334155; --bg-quaternary: #475569; - --text-primary: #e2e8f0; + + /* Text Colors */ + --text-primary: #f1f5f9; --text-secondary: #94a3b8; --text-muted: #64748b; - --border-color: #334155; + + /* Accent Colors */ --accent-blue: #60a5fa; + --accent-blue-hover: #3b82f6; + --accent-blue-dark: #2563eb; + + /* Border Colors */ + --border-color: #334155; + --border-color-light: #475569; + + /* Status Colors */ --success-bg: #065f46; --success-text: #6ee7b7; --success-border: #10b981; @@ -23,25 +36,44 @@ --info-text: #93c5fd; --info-border: #3b82f6; + /* Shadows */ + --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.3); + --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.3), 0 2px 4px -1px rgba(0, 0, 0, 0.2); + --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.3), 0 4px 6px -2px rgba(0, 0, 0, 0.2); + --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.3), 0 10px 10px -5px rgba(0, 0, 0, 0.2); + + /* Transitions */ + --transition-fast: 150ms ease; + --transition-base: 200ms ease; + --transition-slow: 300ms ease; + + /* Border Radius */ + --radius-sm: 6px; + --radius-md: 8px; + --radius-lg: 12px; + --radius-xl: 16px; + /* Bootstrap 5 Variable Overrides for Dark Theme */ --bs-body-bg: #0f172a; - --bs-body-color: #e2e8f0; + --bs-body-color: #f1f5f9; --bs-border-color: #334155; --bs-border-color-translucent: rgba(51, 65, 85, 0.5); /* Table Variables */ --bs-table-bg: #1e293b; - --bs-table-color: #e2e8f0; + --bs-table-color: #f1f5f9; --bs-table-border-color: #334155; --bs-table-striped-bg: #1e293b; - --bs-table-striped-color: #e2e8f0; + --bs-table-striped-color: #f1f5f9; --bs-table-active-bg: #334155; - --bs-table-active-color: #e2e8f0; + --bs-table-active-color: #f1f5f9; --bs-table-hover-bg: #334155; - --bs-table-hover-color: #e2e8f0; + --bs-table-hover-color: #f1f5f9; } -/* Global Styles */ +/* ============================================== + Global Styles + ============================================== */ * { margin: 0; padding: 0; @@ -53,67 +85,445 @@ body { background-color: var(--bg-primary); color: var(--text-primary); line-height: 1.6; + min-height: 100vh; } -/* Navbar */ +/* Smooth scrolling */ +html { + scroll-behavior: smooth; +} + +/* Better focus styles for accessibility */ +:focus-visible { + outline: 2px solid var(--accent-blue); + outline-offset: 2px; +} + +/* ============================================== + Typography + ============================================== */ +h1, h2, h3, h4, h5, h6 { + color: var(--accent-blue); + font-weight: 600; + line-height: 1.3; +} + +h1 { font-size: 2rem; } +h2 { font-size: 1.75rem; } +h3 { font-size: 1.5rem; } +h4 { font-size: 1.25rem; } +h5 { font-size: 1.125rem; } +h6 { font-size: 1rem; } + +/* Page titles */ +.page-title { + color: var(--accent-blue); + font-size: 2rem; + font-weight: 600; + margin-bottom: 0; +} + +/* ============================================== + Navbar + ============================================== */ .navbar-custom { background: linear-gradient(135deg, var(--bg-secondary) 0%, var(--bg-tertiary) 100%); - border-bottom: 1px solid var(--bg-quaternary); - padding: 1rem 0; + border-bottom: 1px solid var(--border-color-light); + padding: 0.875rem 0; + box-shadow: var(--shadow-md); } .navbar-brand { font-size: 1.5rem; - font-weight: 600; + font-weight: 700; color: var(--accent-blue) !important; + letter-spacing: -0.5px; + transition: color var(--transition-fast); +} + +.navbar-brand:hover { + color: var(--accent-blue-hover) !important; } .nav-link { color: var(--text-secondary) !important; - transition: color 0.2s; + font-weight: 500; + padding: 0.5rem 1rem !important; + border-radius: var(--radius-sm); + transition: all var(--transition-fast); +} + +.nav-link:hover { + color: var(--text-primary) !important; + background-color: rgba(255, 255, 255, 0.05); } -.nav-link:hover, .nav-link.active { color: var(--accent-blue) !important; + background-color: rgba(96, 165, 250, 0.1); } -/* Container */ +/* Dropdown menus */ +.dropdown-menu { + background-color: var(--bg-secondary); + border: 1px solid var(--border-color); + border-radius: var(--radius-md); + box-shadow: var(--shadow-lg); + padding: 0.5rem; +} + +.dropdown-item { + color: var(--text-secondary); + padding: 0.5rem 1rem; + border-radius: var(--radius-sm); + transition: all var(--transition-fast); +} + +.dropdown-item:hover, +.dropdown-item:focus { + color: var(--text-primary); + background-color: var(--bg-tertiary); +} + +.dropdown-divider { + border-color: var(--border-color); +} + +/* Navbar toggler for mobile */ +.navbar-toggler { + border-color: var(--border-color); + padding: 0.5rem; +} + +.navbar-toggler-icon { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28148, 163, 184, 1%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); +} + +/* ============================================== + Container + ============================================== */ .container-fluid { max-width: 1400px; margin: 0 auto; - padding: 20px; + padding: 1.5rem; } -/* Cards */ +/* ============================================== + Cards + ============================================== */ .card { background-color: var(--bg-secondary); border: 1px solid var(--border-color); - border-radius: 12px; - margin-bottom: 25px; + border-radius: var(--radius-lg); + margin-bottom: 1.5rem; + box-shadow: var(--shadow-sm); + transition: box-shadow var(--transition-base); +} + +.card:hover { + box-shadow: var(--shadow-md); } .card-header { background-color: var(--bg-tertiary); - border-bottom: 1px solid var(--bg-quaternary); - padding: 15px 20px; - border-radius: 12px 12px 0 0 !important; + border-bottom: 1px solid var(--border-color); + padding: 1rem 1.5rem; + border-radius: var(--radius-lg) var(--radius-lg) 0 0 !important; +} + +.card-header h5, +.card-header .card-title { + color: var(--accent-blue); + margin-bottom: 0; + font-weight: 600; } .card-body { - padding: 25px; + padding: 1.5rem; } .card-title { color: var(--accent-blue); - font-size: 1.5rem; - margin-bottom: 15px; + font-size: 1.25rem; + font-weight: 600; + margin-bottom: 1rem; } -/* Badges */ +.card-footer { + background-color: var(--bg-tertiary); + border-top: 1px solid var(--border-color); + padding: 1rem 1.5rem; +} + +/* ============================================== + Stat Cards + ============================================== */ +.stat-card { + background-color: var(--bg-secondary); + padding: 1.5rem; + border-radius: var(--radius-lg); + border: 1px solid var(--border-color); + text-align: center; + transition: all var(--transition-base); + box-shadow: var(--shadow-sm); +} + +.stat-card:hover { + transform: translateY(-2px); + box-shadow: var(--shadow-md); + border-color: var(--accent-blue); +} + +.stat-value { + font-size: 2.5rem; + font-weight: 700; + color: var(--accent-blue); + line-height: 1.2; +} + +.stat-label { + color: var(--text-secondary); + font-size: 0.875rem; + text-transform: uppercase; + letter-spacing: 0.5px; + margin-top: 0.5rem; + font-weight: 500; +} + +/* ============================================== + Buttons + ============================================== */ +.btn { + font-weight: 500; + border-radius: var(--radius-md); + padding: 0.5rem 1rem; + transition: all var(--transition-fast); + border: 1px solid transparent; +} + +.btn:focus { + box-shadow: 0 0 0 0.2rem rgba(96, 165, 250, 0.25); +} + +/* Primary Button */ +.btn-primary { + background-color: var(--accent-blue-hover); + border-color: var(--accent-blue-hover); + color: #ffffff; +} + +.btn-primary:hover, +.btn-primary:focus { + background-color: var(--accent-blue-dark); + border-color: var(--accent-blue-dark); + color: #ffffff; +} + +.btn-primary:active { + background-color: #1d4ed8; + border-color: #1d4ed8; +} + +/* Secondary Button */ +.btn-secondary { + background-color: var(--bg-tertiary); + border-color: var(--border-color); + color: var(--text-primary); +} + +.btn-secondary:hover, +.btn-secondary:focus { + background-color: var(--bg-quaternary); + border-color: var(--border-color-light); + color: var(--text-primary); +} + +/* Success Button */ +.btn-success { + background-color: #22c55e; + border-color: #22c55e; + color: #ffffff; +} + +.btn-success:hover, +.btn-success:focus { + background-color: #16a34a; + border-color: #16a34a; + color: #ffffff; +} + +/* Danger Button */ +.btn-danger { + background-color: #dc2626; + border-color: #dc2626; + color: #ffffff; +} + +.btn-danger:hover, +.btn-danger:focus { + background-color: #b91c1c; + border-color: #b91c1c; + color: #ffffff; +} + +/* Warning Button */ +.btn-warning { + background-color: #f59e0b; + border-color: #f59e0b; + color: #000000; +} + +.btn-warning:hover, +.btn-warning:focus { + background-color: #d97706; + border-color: #d97706; + color: #000000; +} + +/* Info Button */ +.btn-info { + background-color: #0ea5e9; + border-color: #0ea5e9; + color: #ffffff; +} + +.btn-info:hover, +.btn-info:focus { + background-color: #0284c7; + border-color: #0284c7; + color: #ffffff; +} + +/* Outline Buttons */ +.btn-outline-primary { + color: var(--accent-blue); + border-color: var(--accent-blue-hover); +} + +.btn-outline-primary:hover, +.btn-outline-primary:focus { + background-color: var(--accent-blue-hover); + border-color: var(--accent-blue-hover); + color: #ffffff; +} + +.btn-outline-secondary { + color: var(--text-secondary); + border-color: var(--border-color); +} + +.btn-outline-secondary:hover, +.btn-outline-secondary:focus { + background-color: var(--bg-tertiary); + border-color: var(--border-color-light); + color: var(--text-primary); +} + +.btn-outline-success { + color: var(--success-border); + border-color: var(--success-border); +} + +.btn-outline-success:hover, +.btn-outline-success:focus { + background-color: var(--success-border); + border-color: var(--success-border); + color: #ffffff; +} + +.btn-outline-danger { + color: var(--danger-border); + border-color: var(--danger-border); +} + +.btn-outline-danger:hover, +.btn-outline-danger:focus { + background-color: var(--danger-border); + border-color: var(--danger-border); + color: #ffffff; +} + +/* Button Sizes */ +.btn-lg { + padding: 0.75rem 1.5rem; + font-size: 1.125rem; +} + +.btn-sm { + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + border-radius: var(--radius-sm); +} + +/* Button Groups */ +.btn-group .btn { + border-radius: 0; +} + +.btn-group .btn:first-child { + border-top-left-radius: var(--radius-md); + border-bottom-left-radius: var(--radius-md); +} + +.btn-group .btn:last-child { + border-top-right-radius: var(--radius-md); + border-bottom-right-radius: var(--radius-md); +} + +/* ============================================== + Tables + ============================================== */ +.table { + color: var(--text-primary); + border-color: var(--border-color); + margin-bottom: 0; +} + +.table thead { + background-color: var(--bg-tertiary); +} + +.table thead th { + color: var(--text-secondary); + font-weight: 600; + text-transform: uppercase; + font-size: 0.75rem; + letter-spacing: 0.5px; + padding: 1rem; + border-bottom: 2px solid var(--border-color); + white-space: nowrap; +} + +.table tbody tr, +.table tbody tr.scan-row, +.table tbody tr.schedule-row { + background-color: var(--bg-secondary) !important; + border-color: var(--border-color) !important; + transition: background-color var(--transition-fast); +} + +.table tbody tr:hover { + background-color: var(--bg-tertiary) !important; +} + +.table th, +.table td { + padding: 1rem; + border-color: var(--border-color); + vertical-align: middle; +} + +.table-responsive { + border-radius: var(--radius-md); + overflow: hidden; +} + +/* ============================================== + Badges + ============================================== */ .badge { - padding: 4px 12px; - border-radius: 12px; + padding: 0.35rem 0.75rem; + border-radius: 50px; font-size: 0.75rem; font-weight: 600; text-transform: uppercase; @@ -145,72 +555,40 @@ body { color: var(--info-text); } -/* Buttons */ -.btn-primary { - background-color: #3b82f6; - border-color: #3b82f6; - color: #ffffff; +/* Bootstrap badge overrides */ +.bg-success { + background-color: var(--success-border) !important; } -.btn-primary:hover { - background-color: #2563eb; - border-color: #2563eb; +.bg-danger { + background-color: var(--danger-border) !important; } -.btn-secondary { - background-color: var(--bg-tertiary); - border-color: var(--bg-tertiary); - color: var(--text-primary); +.bg-warning { + background-color: var(--warning-border) !important; + color: #000 !important; } -.btn-secondary:hover { - background-color: var(--bg-quaternary); - border-color: var(--bg-quaternary); +.bg-info { + background-color: var(--info-border) !important; } -.btn-danger { - background-color: var(--danger-bg); - border-color: var(--danger-bg); - color: var(--danger-text); +.bg-secondary { + background-color: var(--bg-quaternary) !important; } -.btn-danger:hover { - background-color: #991b1b; - border-color: #991b1b; +.bg-primary { + background-color: var(--accent-blue-hover) !important; } -/* Tables - Fix for dynamically created table rows (white row bug) */ -.table { - color: var(--text-primary); - border-color: var(--border-color); -} - -.table thead { - background-color: var(--bg-tertiary); - color: var(--text-secondary); -} - -.table tbody tr, -.table tbody tr.scan-row { - background-color: var(--bg-secondary) !important; - border-color: var(--border-color) !important; -} - -.table tbody tr:hover { - background-color: var(--bg-tertiary) !important; - cursor: pointer; -} - -.table th, -.table td { - padding: 12px; - border-color: var(--border-color); -} - -/* Alerts */ +/* ============================================== + Alerts + ============================================== */ .alert { - border-radius: 8px; + border-radius: var(--radius-md); border: 1px solid; + padding: 1rem 1.25rem; + margin-bottom: 1rem; } .alert-success { @@ -237,61 +615,217 @@ body { color: var(--info-text); } -/* Form Controls */ +.alert .btn-close { + filter: invert(1) brightness(0.8); +} + +.alert-link { + color: inherit; + text-decoration: underline; + font-weight: 600; +} + +/* ============================================== + Form Controls + ============================================== */ .form-control, .form-select { background-color: var(--bg-secondary); - border-color: var(--border-color); + border: 1px solid var(--border-color); color: var(--text-primary); + border-radius: var(--radius-md); + padding: 0.625rem 0.875rem; + transition: all var(--transition-fast); } .form-control:focus, .form-select:focus { - background-color: var(--bg-secondary); + background-color: var(--bg-primary); border-color: var(--accent-blue); color: var(--text-primary); box-shadow: 0 0 0 0.2rem rgba(96, 165, 250, 0.25); } +.form-control::placeholder { + color: var(--text-muted); +} + +.form-control:disabled, +.form-select:disabled { + background-color: var(--bg-tertiary); + opacity: 0.6; +} + +.form-control-lg { + padding: 0.75rem 1rem; + font-size: 1.125rem; +} + .form-label { color: var(--text-secondary); font-weight: 500; + margin-bottom: 0.5rem; } -/* Stats Cards */ -.stat-card { - background-color: var(--bg-primary); - padding: 20px; - border-radius: 8px; - border: 1px solid var(--border-color); - text-align: center; +.form-text { + color: var(--text-muted); + font-size: 0.875rem; } -.stat-value { - font-size: 2rem; - font-weight: 600; - color: var(--accent-blue); +.form-check-input { + background-color: var(--bg-secondary); + border-color: var(--border-color); } -.stat-label { +.form-check-input:checked { + background-color: var(--accent-blue-hover); + border-color: var(--accent-blue-hover); +} + +.form-check-input:focus { + box-shadow: 0 0 0 0.2rem rgba(96, 165, 250, 0.25); + border-color: var(--accent-blue); +} + +.form-check-label { color: var(--text-secondary); - font-size: 0.9rem; - text-transform: uppercase; - letter-spacing: 0.5px; - margin-top: 5px; } -/* Footer */ +/* Form switches */ +.form-switch .form-check-input { + width: 2.5rem; + height: 1.25rem; + margin-top: 0.125rem; +} + +/* Required field indicator */ +.text-danger { + color: var(--danger-border) !important; +} + +/* ============================================== + Modals + ============================================== */ +.modal-content { + background-color: var(--bg-secondary); + border: 1px solid var(--border-color); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-xl); +} + +.modal-header { + border-bottom: 1px solid var(--border-color); + padding: 1.25rem 1.5rem; +} + +.modal-title { + color: var(--accent-blue); + font-weight: 600; +} + +.modal-body { + padding: 1.5rem; +} + +.modal-footer { + border-top: 1px solid var(--border-color); + padding: 1rem 1.5rem; + gap: 0.5rem; +} + +.btn-close { + filter: invert(1) brightness(0.8); + opacity: 0.5; + transition: opacity var(--transition-fast); +} + +.btn-close:hover { + opacity: 1; +} + +.modal-backdrop { + background-color: rgba(0, 0, 0, 0.7); +} + +/* ============================================== + Pagination + ============================================== */ +.pagination { + --bs-pagination-bg: var(--bg-secondary); + --bs-pagination-border-color: var(--border-color); + --bs-pagination-hover-bg: var(--bg-tertiary); + --bs-pagination-hover-border-color: var(--border-color-light); + --bs-pagination-focus-bg: var(--bg-tertiary); + --bs-pagination-active-bg: var(--accent-blue-hover); + --bs-pagination-active-border-color: var(--accent-blue-hover); + --bs-pagination-disabled-bg: var(--bg-primary); + --bs-pagination-disabled-border-color: var(--border-color); + --bs-pagination-color: var(--text-secondary); + --bs-pagination-hover-color: var(--text-primary); + --bs-pagination-disabled-color: var(--text-muted); +} + +.page-link { + border-radius: var(--radius-sm); + margin: 0 0.125rem; + transition: all var(--transition-fast); +} + +.page-item.active .page-link { + color: #ffffff; +} + +/* ============================================== + Login Page + ============================================== */ +.login-card { + max-width: 420px; + margin: 5rem auto; + padding: 2.5rem; + background-color: var(--bg-secondary); + border-radius: var(--radius-xl); + border: 1px solid var(--border-color); + box-shadow: var(--shadow-xl); +} + +.brand-title { + font-size: 2.5rem; + font-weight: 700; + color: var(--accent-blue); + margin-bottom: 0.5rem; +} + +.brand-subtitle { + color: var(--text-muted); + font-size: 1rem; + margin-bottom: 0; +} + +/* ============================================== + Footer + ============================================== */ .footer { - margin-top: 40px; - padding: 20px 0; + margin-top: 3rem; + padding: 1.5rem 0; border-top: 1px solid var(--border-color); text-align: center; color: var(--text-muted); - font-size: 0.9rem; + font-size: 0.875rem; } -/* Utilities */ +.footer a { + color: var(--accent-blue); + text-decoration: none; + transition: color var(--transition-fast); +} + +.footer a:hover { + color: var(--accent-blue-hover); +} + +/* ============================================== + Utility Classes + ============================================== */ .text-muted { color: var(--text-secondary) !important; } @@ -313,22 +847,237 @@ body { } .mono { - font-family: 'Courier New', monospace; + font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Courier New', monospace; + font-size: 0.9em; } -/* Spinner for loading states */ -.spinner-border-sm { +code { + background-color: var(--bg-primary); + color: var(--accent-blue); + padding: 0.125rem 0.375rem; + border-radius: var(--radius-sm); + font-size: 0.875em; +} + +/* Border utilities */ +.border-bottom { + border-bottom: 1px solid var(--border-color) !important; +} + +/* ============================================== + Spinners / Loading States + ============================================== */ +.spinner-border { color: var(--accent-blue); } -/* Chart.js Dark Theme Styles */ +.spinner-border-sm { + width: 1rem; + height: 1rem; +} + +/* ============================================== + Charts + ============================================== */ .chart-container { position: relative; height: 300px; - margin: 20px 0; + margin: 1rem 0; } canvas { max-width: 100%; height: auto; } + +/* ============================================== + Empty States + ============================================== */ +.empty-state { + text-align: center; + padding: 3rem 1rem; +} + +.empty-state i { + font-size: 3rem; + color: var(--text-muted); + opacity: 0.5; + margin-bottom: 1rem; +} + +.empty-state h5 { + color: var(--text-secondary); +} + +.empty-state p { + color: var(--text-muted); +} + +/* ============================================== + Notifications (Toast-like) + ============================================== */ +.notification { + position: fixed; + top: 1.25rem; + right: 1.25rem; + z-index: 9999; + min-width: 300px; + animation: slideIn 0.3s ease; +} + +@keyframes slideIn { + from { + transform: translateX(100%); + opacity: 0; + } + to { + transform: translateX(0); + opacity: 1; + } +} + +/* ============================================== + Responsive Design + ============================================== */ +@media (max-width: 991.98px) { + .navbar-collapse { + background-color: var(--bg-secondary); + padding: 1rem; + border-radius: var(--radius-md); + margin-top: 1rem; + border: 1px solid var(--border-color); + } + + .navbar-nav { + gap: 0.25rem; + } +} + +@media (max-width: 767.98px) { + .container-fluid { + padding: 1rem; + } + + h1 { + font-size: 1.75rem; + } + + .stat-value { + font-size: 2rem; + } + + .card-body { + padding: 1rem; + } + + .card-header { + padding: 0.875rem 1rem; + } + + .table th, + .table td { + padding: 0.75rem; + } + + .btn-lg { + padding: 0.625rem 1.25rem; + font-size: 1rem; + } + + .login-card { + margin: 2rem 1rem; + padding: 1.5rem; + } + + .modal-dialog { + margin: 0.5rem; + } +} + +@media (max-width: 575.98px) { + .stat-card { + padding: 1rem; + } + + .stat-value { + font-size: 1.75rem; + } + + .stat-label { + font-size: 0.75rem; + } + + /* Stack action buttons on small screens */ + .btn-group { + flex-direction: column; + } + + .btn-group .btn { + border-radius: var(--radius-sm) !important; + margin-bottom: 0.25rem; + } +} + +/* ============================================== + Print Styles + ============================================== */ +@media print { + .navbar-custom, + .footer, + .btn, + .pagination { + display: none !important; + } + + body { + background: white; + color: black; + } + + .card { + border: 1px solid #ddd; + break-inside: avoid; + } +} + +/* ============================================== + Accessibility Improvements + ============================================== */ +/* Ensure sufficient contrast for links */ +a { + color: var(--accent-blue); + text-decoration: none; + transition: color var(--transition-fast); +} + +a:hover { + color: var(--accent-blue-hover); +} + +/* Skip to main content link (hidden by default) */ +.skip-link { + position: absolute; + top: -40px; + left: 0; + background: var(--accent-blue); + color: white; + padding: 0.5rem 1rem; + z-index: 100; + transition: top 0.3s; +} + +.skip-link:focus { + top: 0; +} + +/* Reduced motion preference */ +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + scroll-behavior: auto !important; + } +} diff --git a/app/web/templates/alert_rules.html b/app/web/templates/alert_rules.html index 4b15c31..eaa9e8c 100644 --- a/app/web/templates/alert_rules.html +++ b/app/web/templates/alert_rules.html @@ -5,7 +5,7 @@ {% block content %}
-

Alert Rules

+

Alert Rules

View Alerts @@ -23,7 +23,7 @@
Total Rules
-

{{ rules | length }}

+

{{ rules | length }}

@@ -42,7 +42,7 @@
-
Alert Rules Configuration
+
Alert Rules Configuration
{% if rules %} @@ -121,9 +121,9 @@ onchange="toggleRule({{ rule.id }}, this.checked)">
diff --git a/app/web/templates/alerts.html b/app/web/templates/alerts.html index 6ed1ee3..4d71640 100644 --- a/app/web/templates/alerts.html +++ b/app/web/templates/alerts.html @@ -5,7 +5,7 @@ {% block content %}
-

Alert History

+

Alert History

Manage Alert Rules @@ -18,7 +18,7 @@
Total Alerts
-

{{ pagination.total }}

+

{{ pagination.total }}

@@ -46,7 +46,7 @@
Unacknowledged
-

+

{{ alerts | rejectattr('acknowledged') | list | length }}

@@ -104,7 +104,7 @@
-
Alerts
+
Alerts
{% if alerts %} diff --git a/app/web/templates/base.html b/app/web/templates/base.html index 872f3f1..b811060 100644 --- a/app/web/templates/base.html +++ b/app/web/templates/base.html @@ -107,6 +107,9 @@
+ +
+ {% block scripts %}{% endblock %} diff --git a/app/web/templates/configs.html b/app/web/templates/configs.html index 81a3683..8e842bc 100644 --- a/app/web/templates/configs.html +++ b/app/web/templates/configs.html @@ -6,7 +6,7 @@
-

Scan Configurations

+

Scan Configurations

+
- @@ -146,12 +146,12 @@