/* GuardDog Nexus — Web UI styles */ /* ------------------------------------------------------------------ */ /* Status / severity colours */ /* ------------------------------------------------------------------ */ .flagged { color: var(--pico-color-red-400); font-weight: bold; } .clean { color: var(--pico-color-green-400); } .status-pending { color: var(--pico-color-yellow-400); } .status-scanning { color: var(--pico-color-blue-400); animation: pulse 1.5s ease-in-out infinite; } .status-completed { color: var(--pico-color-green-400); } .status-failed { color: var(--pico-color-red-400); } .severity-WARNING { color: var(--pico-color-yellow-400); } .severity-ERROR { color: var(--pico-color-red-400); } /* ------------------------------------------------------------------ */ /* Dashboard mini-bar */ /* ------------------------------------------------------------------ */ .stat-minibar { display: flex; gap: 1.5rem; padding: 0.6rem 0; margin-bottom: 1.5rem; border-bottom: 1px solid var(--pico-color-gray-500); font-size: 0.9rem; opacity: 0.9; } /* Dashboard block grid (2 cols → 1 on mobile) */ .dashboard-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-bottom: 1rem; } .dash-block { padding: 1rem; margin-bottom: 0; } .dash-block h3 { margin-top: 0; font-size: 0.95rem; } .dash-block-warn { border-left: 3px solid var(--pico-color-red-400); } /* ------------------------------------------------------------------ */ /* Tables */ /* ------------------------------------------------------------------ */ table { font-size: 0.9rem; } table.compact { font-size: 0.82rem; } table.compact th, table.compact td { padding: 0.35rem 0.5rem; } /* ------------------------------------------------------------------ */ /* Heatmap */ /* ------------------------------------------------------------------ */ .heatmap { display: flex; align-items: flex-end; gap: 2px; height: 40px; margin: 0.4rem 0 0 0; } .heatmap-day { flex: 1; display: flex; flex-direction: column; justify-content: flex-end; position: relative; } .heatmap-day .bar { border-radius: 2px 2px 0 0; opacity: 0.8; transition: height 0.3s ease, opacity 0.2s; } .heatmap-day:hover .bar { opacity: 1; } .heatmap-day .tooltip { display: none; position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%); background: var(--pico-color-gray-700); color: var(--pico-color-white); padding: 0.25rem 0.5rem; border-radius: 4px; font-size: 0.7rem; white-space: nowrap; z-index: 10; margin-bottom: 4px; } .heatmap-day:hover .tooltip { display: block; } /* ------------------------------------------------------------------ */ /* Scan info block (detail page) */ /* ------------------------------------------------------------------ */ .scan-info-block { padding: 1rem 1.25rem; margin-bottom: 1.5rem; } .scan-info-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 0.6rem 1.5rem; } .sha256 { font-size: 0.72rem; word-break: break-all; } .scan-error { margin-top: 0.75rem; padding: 0.5rem 0.75rem; background: rgba(var(--pico-color-red-400), 0.1); border-left: 3px solid var(--pico-color-red-400); border-radius: 4px; font-size: 0.85rem; } /* ------------------------------------------------------------------ */ /* Finding blocks (replaces accordion details/summary) */ /* ------------------------------------------------------------------ */ .finding-block { margin-bottom: 0.75rem; border: 1px solid var(--pico-color-gray-600); border-radius: 6px; overflow: hidden; } .finding-summary { display: flex; align-items: center; gap: 0.5rem; padding: 0.5rem 0.75rem; background: var(--pico-color-gray-650); font-size: 0.9rem; border-bottom: 1px solid var(--pico-color-gray-600); } .finding-body { padding: 0.75rem; } .finding-body p { margin-bottom: 0.5rem; } .finding-body pre { background: var(--pico-color-gray-700); padding: 0.5rem; border-radius: 4px; overflow-x: auto; font-size: 0.8rem; margin-bottom: 0; } .finding-header-row { display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.75rem; } .finding-header-row h2 { margin-bottom: 0; } /* ------------------------------------------------------------------ */ /* LLM report — verdict-based colour scheme */ /* ------------------------------------------------------------------ */ .llm-report { margin-top: 0.75rem; padding: 0.8rem 1rem; border-radius: 6px; font-size: 0.85rem; line-height: 1.55; border-left: 4px solid var(--pico-color-gray-500); background: var(--pico-color-gray-750); } .llm-header { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.5rem; } .llm-badge { display: inline-block; padding: 0.1rem 0.5rem; border-radius: 3px; font-size: 0.75rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; } .llm-badge-safe { background: #1a5c2a; color: #4ade80; } .llm-badge-suspicious { background: #5c4a1a; color: #facc15; } .llm-badge-malicious { background: #5c1a1a; color: #f87171; } .llm-safe { border-left-color: var(--pico-color-green-400); background: rgba(74,222,128,0.06); } .llm-suspicious { border-left-color: var(--pico-color-yellow-400); background: rgba(250,204,21,0.06); } .llm-malicious { border-left-color: var(--pico-color-red-400); background: rgba(248,113,113,0.08); } .llm-severity { font-size: 0.72rem; opacity: 0.6; text-transform: uppercase; letter-spacing: 0.04em; } .llm-summary { font-style: italic; margin-bottom: 0.4rem; color: var(--pico-color-zinc-300); } .llm-analysis { margin-bottom: 0; white-space: pre-line; } .llm-actions { margin-top: 0.5rem; } .llm-actions button { font-size: 0.8rem; } .llm-disclaimer { margin-top: 0.6rem; font-size: 0.72rem; opacity: 0.5; font-style: italic; border-top: 1px solid var(--pico-color-gray-600); padding-top: 0.4rem; } /* ------------------------------------------------------------------ */ /* Shared controls */ /* ------------------------------------------------------------------ */ .code-toolbar { display: flex; justify-content: flex-end; margin-bottom: 0.25rem; } .copy-btn { cursor: pointer; background: none; border: 1px solid var(--pico-color-gray-500); padding: 0.15rem 0.5rem; font-size: 0.7rem; border-radius: 3px; color: var(--pico-color-gray-300); transition: background 0.2s; } .copy-btn:hover { background: var(--pico-color-gray-600); } .copy-btn.copied { color: var(--pico-color-green-400); border-color: var(--pico-color-green-400); } .toggle-all-btn { font-size: 0.8rem; cursor: pointer; background: none; border: 1px solid var(--pico-color-gray-500); padding: 0.2rem 0.6rem; border-radius: 3px; color: var(--pico-color-gray-300); } .toggle-all-btn:hover { background: var(--pico-color-gray-600); } .htmx-indicator { display: inline; } /* ------------------------------------------------------------------ */ /* Nav / breadcrumbs / empty state */ /* ------------------------------------------------------------------ */ nav { margin-bottom: 1rem; } nav.sticky { position: sticky; top: 0; z-index: 100; background: var(--pico-color-dark); padding: 0.5rem 0; border-bottom: 1px solid var(--pico-color-gray-500); } .breadcrumbs { margin-bottom: 1rem; font-size: 0.85rem; opacity: 0.7; } .breadcrumbs a { text-decoration: none; } .breadcrumbs .separator { margin: 0 0.5rem; opacity: 0.5; } .empty-state { text-align: center; padding: 2rem 1rem; opacity: 0.5; font-style: italic; } /* ------------------------------------------------------------------ */ /* Filter bar / sortable cols */ /* ------------------------------------------------------------------ */ .filter-bar { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 1rem; align-items: center; } .filter-bar input[type="text"], .filter-bar select { margin-bottom: 0; } th.sortable { cursor: pointer; user-select: none; } th.sortable:hover { background: var(--pico-color-gray-600); } th.sortable .sort-icon { margin-left: 0.25rem; opacity: 0.3; } th.sortable.active .sort-icon { opacity: 1; } /* ------------------------------------------------------------------ */ /* Spinner / animations */ /* ------------------------------------------------------------------ */ .spinner { display: inline-block; width: 12px; height: 12px; border: 2px solid var(--pico-color-blue-400); border-top-color: transparent; border-radius: 50%; animation: spin 0.8s linear infinite; margin-right: 0.25rem; vertical-align: middle; } @keyframes spin { to { transform: rotate(360deg); } } @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } } /* ------------------------------------------------------------------ */ /* Responsive */ /* ------------------------------------------------------------------ */ @media (max-width: 768px) { .dashboard-grid { grid-template-columns: 1fr; } .scan-info-grid { grid-template-columns: 1fr 1fr; } .stat-minibar { flex-wrap: wrap; gap: 0.75rem; } .filter-bar { flex-direction: column; align-items: stretch; } nav ul { flex-wrap: wrap; } table, table.compact { font-size: 0.78rem; } th, td { padding: 0.3rem 0.4rem; } } @media (max-width: 480px) { .scan-info-grid { grid-template-columns: 1fr; } .stat-minibar { font-size: 0.8rem; } } /* ------------------------------------------------------------------ */ /* Print */ /* ------------------------------------------------------------------ */ @media print { nav, .filter-bar, .copy-btn, .toggle-all-btn, nav.sticky, .llm-actions, .breadcrumbs { display: none !important; } body { background: white; color: black; } .llm-report { border: 1px solid #ccc; background: none; } }