f0ab1323a5
Visual unification:
- New :root design tokens + .lb-* component classes in style.css
(cards, buttons, badges, section headers, hash display, empty
state, animated grid backdrop, critical-state pulse).
- holygrail.html and byovd_info.html lose their cyber-themed inline
<style> blocks (567 + 164 lines) and the cyber-card / cyber-chip /
cyber-button / verdict-* classes; both pages now draw from the
shared lb-* vocabulary. The cyber-glow accent is preserved but
applied only on critical/severe states instead of page-wide.
- Templates swept to use component classes: file_info, summary,
results, dynamic_info, static_info, doppelganger, error, upload,
partials/_macros. JS renderers in results/tools.js,
results/renderers.js, and the holygrail/byovd/upload core.js
modules updated to emit the new classes. Risk-level 4-way
conditional in file_info.html collapsed to a single
lb-badge-{{ risk_level|lower }} lookup.
- Bug fix: duplicate .logo-wrapper rule in style.css merged.
Self-contained report (report.html rewritten):
- Drops the https://cdn.tailwindcss.com runtime-JIT dependency and
the inline tailwind.config script. No <script> tags anywhere.
- All CSS inlined in a single <style> block: design tokens, the
subset of lb-* component classes the report uses, and only the
layout rules the report itself needs.
- Hand-written typography and layout: tabular-numeric risk scores,
restrained pill badges, severity-coded detection chips,
generous whitespace, dedicated @media print.
- Status icons use locked SVG dimensions so the green checkmark on
clean scans no longer renders at default-huge size.
- The LitterBox logo is embedded as a base64 PNG data URI so the
brand strip displays correctly when the file is downloaded and
opened offline. Logo sized at 64x64 in the brand strip.
CHANGELOG.md: v4.2.0 entry extended with "UI design system &
visual unification" and "Fully self-contained downloadable report"
sections.
No backend or API changes. Setup story unchanged. No new
dependencies; deploy stays Python-only with the precompiled
tailwind.min.css.
691 lines
17 KiB
CSS
691 lines
17 KiB
CSS
/* app/static/css/style.css
|
|
*
|
|
* NOTE: Tailwind in this project is precompiled (tailwind.min.css is shipped
|
|
* as a static asset; there is no Node/PostCSS build pipeline). That means
|
|
* `@apply` directives DO NOT work here — browsers silently ignore them.
|
|
* Always write raw CSS in this file. Use Tailwind utility classes directly
|
|
* in templates when you want utility behavior.
|
|
*
|
|
* The "lb-*" prefix marks the unified design system introduced in the
|
|
* Phase R UI redesign. Templates use these component classes instead of
|
|
* the long inline Tailwind chains they previously composed by hand.
|
|
*
|
|
* Design tokens come first, then component classes, then existing layout
|
|
* rules (sidebar/topbar/nav). Add new design-system pieces near the top;
|
|
* leave the layout rules at the bottom alone.
|
|
*/
|
|
|
|
/* =============================================================
|
|
* Design tokens
|
|
* ============================================================= */
|
|
:root {
|
|
/* Brand accent (red) */
|
|
--lb-accent: #ef4444; /* red-500 — primary brand */
|
|
--lb-accent-soft: #f87171; /* red-400 */
|
|
--lb-accent-deep: #b91c1c; /* red-700 */
|
|
|
|
/* Severity (semantic) */
|
|
--lb-sev-critical: #ef4444; /* red-500 */
|
|
--lb-sev-high: #f97316; /* orange-500 */
|
|
--lb-sev-medium: #eab308; /* yellow-500 */
|
|
--lb-sev-low: #22c55e; /* green-500 */
|
|
--lb-sev-clean: #22c55e;
|
|
--lb-sev-info: #6b7280; /* gray-500 */
|
|
|
|
/* Surfaces (grayscale, dark) */
|
|
--lb-bg: #000000;
|
|
--lb-surface-1: rgb(17 24 39 / 0.6); /* gray-900/60 — page panels */
|
|
--lb-surface-2: rgb(17 24 39 / 0.3); /* gray-900/30 — sub-panels */
|
|
--lb-surface-3: rgb(31 41 55 / 0.5); /* gray-800/50 — list items */
|
|
|
|
/* Borders */
|
|
--lb-border: rgb(31 41 55 / 1); /* gray-800 */
|
|
--lb-border-soft: rgb(31 41 55 / 0.5);
|
|
--lb-border-accent: rgb(127 29 29 / 0.3); /* red-900/30 */
|
|
|
|
/* Text */
|
|
--lb-text: #f3f4f6; /* gray-100 */
|
|
--lb-text-muted: #9ca3af; /* gray-400 */
|
|
--lb-text-faint: #6b7280; /* gray-500 */
|
|
|
|
/* Radii */
|
|
--lb-radius-sm: 0.375rem;
|
|
--lb-radius-md: 0.5rem;
|
|
--lb-radius-lg: 0.75rem;
|
|
--lb-radius-xl: 1rem;
|
|
--lb-radius-2xl: 1.25rem;
|
|
|
|
/* Shadows */
|
|
--lb-shadow-sm: 0 1px 2px rgb(0 0 0 / 0.3);
|
|
--lb-shadow-md: 0 4px 12px rgb(0 0 0 / 0.4);
|
|
--lb-shadow-lg: 0 12px 28px -8px rgb(0 0 0 / 0.5);
|
|
|
|
/* Cyber-accent glows (used ONLY on critical/severe states) */
|
|
--lb-glow-critical: 0 0 0 1px rgb(239 68 68 / 0.4),
|
|
0 0 24px -4px rgb(239 68 68 / 0.35);
|
|
--lb-glow-high: 0 0 0 1px rgb(249 115 22 / 0.35),
|
|
0 0 18px -6px rgb(249 115 22 / 0.3);
|
|
|
|
/* Motion */
|
|
--lb-transition-fast: 150ms ease;
|
|
--lb-transition: 200ms ease;
|
|
--lb-transition-slow: 300ms ease;
|
|
|
|
/* Sidebar / layout (kept here so all tokens live in one place) */
|
|
--sidebar-width-expanded: 250px;
|
|
--sidebar-width-collapsed: 72px;
|
|
--transition-speed: 0.3s;
|
|
}
|
|
|
|
/* =============================================================
|
|
* Component classes (lb-*)
|
|
*
|
|
* Templates and JS renderers should prefer these over re-typing
|
|
* long Tailwind utility chains. Add new components below; do not
|
|
* fold them into the layout-rules section at the bottom.
|
|
* ============================================================= */
|
|
|
|
/* --- Cards / panels -------------------------------------------- */
|
|
.lb-card {
|
|
background-color: var(--lb-surface-2);
|
|
border: 1px solid var(--lb-border);
|
|
border-radius: var(--lb-radius-lg);
|
|
padding: 1rem;
|
|
}
|
|
|
|
.lb-card-elevated {
|
|
background-color: var(--lb-surface-1);
|
|
backdrop-filter: blur(8px);
|
|
-webkit-backdrop-filter: blur(8px);
|
|
border: 1px solid var(--lb-border);
|
|
border-radius: var(--lb-radius-xl);
|
|
padding: 1.5rem;
|
|
box-shadow: var(--lb-shadow-md);
|
|
}
|
|
|
|
.lb-card-critical {
|
|
background-color: var(--lb-surface-2);
|
|
border: 1px solid rgb(239 68 68 / 0.4);
|
|
border-radius: var(--lb-radius-lg);
|
|
padding: 1rem;
|
|
box-shadow: var(--lb-glow-critical);
|
|
}
|
|
|
|
.lb-card-high {
|
|
background-color: var(--lb-surface-2);
|
|
border: 1px solid rgb(249 115 22 / 0.35);
|
|
border-radius: var(--lb-radius-lg);
|
|
padding: 1rem;
|
|
box-shadow: var(--lb-glow-high);
|
|
}
|
|
|
|
/* --- Buttons --------------------------------------------------- */
|
|
.lb-btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
padding: 0.5rem 1rem;
|
|
border-radius: var(--lb-radius-md);
|
|
font-size: 0.9375rem;
|
|
font-weight: 500;
|
|
line-height: 1.25;
|
|
transition: background-color var(--lb-transition),
|
|
color var(--lb-transition),
|
|
border-color var(--lb-transition);
|
|
cursor: pointer;
|
|
border: 1px solid transparent;
|
|
background: transparent;
|
|
text-decoration: none;
|
|
}
|
|
.lb-btn:disabled,
|
|
.lb-btn[disabled] {
|
|
opacity: 0.5;
|
|
cursor: not-allowed;
|
|
}
|
|
|
|
.lb-btn-primary {
|
|
color: var(--lb-accent-soft);
|
|
border-color: var(--lb-border-accent);
|
|
background-color: rgb(239 68 68 / 0.08);
|
|
}
|
|
.lb-btn-primary:hover {
|
|
background-color: rgb(239 68 68 / 0.18);
|
|
color: #fca5a5;
|
|
}
|
|
|
|
.lb-btn-secondary {
|
|
color: #60a5fa; /* blue-400 */
|
|
border-color: rgb(30 58 138 / 0.3); /* blue-900/30 */
|
|
background-color: rgb(59 130 246 / 0.08);
|
|
}
|
|
.lb-btn-secondary:hover {
|
|
background-color: rgb(59 130 246 / 0.18);
|
|
color: #93c5fd;
|
|
}
|
|
|
|
.lb-btn-ghost {
|
|
color: var(--lb-text-muted);
|
|
}
|
|
.lb-btn-ghost:hover {
|
|
background-color: var(--lb-surface-3);
|
|
color: var(--lb-text);
|
|
}
|
|
|
|
/* --- Severity badges ------------------------------------------- */
|
|
.lb-badge {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.375rem;
|
|
padding: 0.25rem 0.75rem;
|
|
border-radius: var(--lb-radius-md);
|
|
font-size: 0.875rem;
|
|
font-weight: 500;
|
|
line-height: 1.25;
|
|
border: 1px solid transparent;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.lb-badge-critical {
|
|
color: var(--lb-sev-critical);
|
|
background-color: rgb(239 68 68 / 0.1);
|
|
border-color: rgb(239 68 68 / 0.3);
|
|
}
|
|
.lb-badge-high {
|
|
color: var(--lb-sev-high);
|
|
background-color: rgb(249 115 22 / 0.1);
|
|
border-color: rgb(249 115 22 / 0.3);
|
|
}
|
|
.lb-badge-medium {
|
|
color: var(--lb-sev-medium);
|
|
background-color: rgb(234 179 8 / 0.1);
|
|
border-color: rgb(234 179 8 / 0.3);
|
|
}
|
|
.lb-badge-low,
|
|
.lb-badge-clean {
|
|
color: var(--lb-sev-low);
|
|
background-color: rgb(34 197 94 / 0.1);
|
|
border-color: rgb(34 197 94 / 0.3);
|
|
}
|
|
.lb-badge-info {
|
|
color: var(--lb-text-muted);
|
|
background-color: var(--lb-surface-3);
|
|
border-color: var(--lb-border);
|
|
}
|
|
|
|
/* --- Section header (used at the top of cards / sections) ------- */
|
|
.lb-section-header {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.75rem;
|
|
margin-bottom: 1rem;
|
|
padding-bottom: 0.75rem;
|
|
border-bottom: 1px solid var(--lb-border-soft);
|
|
color: var(--lb-text);
|
|
font-size: 1.125rem;
|
|
font-weight: 600;
|
|
}
|
|
.lb-section-header > svg {
|
|
flex-shrink: 0;
|
|
width: 1.25rem;
|
|
height: 1.25rem;
|
|
color: var(--lb-text-muted);
|
|
}
|
|
|
|
/* --- Hash / monospace value display ----------------------------- */
|
|
.lb-hash-display {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
background-color: var(--lb-surface-3);
|
|
border: 1px solid var(--lb-border);
|
|
border-radius: var(--lb-radius-md);
|
|
padding: 0.5rem 0.75rem;
|
|
font-family: 'JetBrains Mono', monospace;
|
|
font-size: 0.8125rem;
|
|
color: var(--lb-text);
|
|
word-break: break-all;
|
|
}
|
|
.lb-hash-display .lb-hash-copy {
|
|
flex-shrink: 0;
|
|
margin-left: auto;
|
|
padding: 0.25rem 0.5rem;
|
|
border-radius: var(--lb-radius-sm);
|
|
color: var(--lb-text-muted);
|
|
transition: all var(--lb-transition-fast);
|
|
cursor: pointer;
|
|
background: transparent;
|
|
border: none;
|
|
}
|
|
.lb-hash-display .lb-hash-copy:hover {
|
|
color: var(--lb-text);
|
|
background-color: rgb(255 255 255 / 0.05);
|
|
}
|
|
|
|
/* --- Empty / clean / threat states ------------------------------ */
|
|
.lb-empty-state {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 2rem 1rem;
|
|
text-align: center;
|
|
border-radius: var(--lb-radius-lg);
|
|
border: 1px solid transparent;
|
|
}
|
|
.lb-empty-state-icon {
|
|
width: 3rem;
|
|
height: 3rem;
|
|
margin-bottom: 0.75rem;
|
|
}
|
|
.lb-empty-state-title {
|
|
font-weight: 600;
|
|
margin-bottom: 0.25rem;
|
|
}
|
|
.lb-empty-state-subtext {
|
|
font-size: 0.875rem;
|
|
color: var(--lb-text-muted);
|
|
}
|
|
.lb-empty-state-clean {
|
|
background-color: rgb(34 197 94 / 0.08);
|
|
border-color: rgb(34 197 94 / 0.2);
|
|
color: var(--lb-sev-clean);
|
|
}
|
|
.lb-empty-state-threats {
|
|
background-color: rgb(239 68 68 / 0.08);
|
|
border-color: rgb(239 68 68 / 0.2);
|
|
color: var(--lb-sev-critical);
|
|
}
|
|
|
|
/* --- Cyber-accent grid background (opt-in only) ----------------- */
|
|
.lb-grid-bg {
|
|
position: relative;
|
|
}
|
|
.lb-grid-bg::before {
|
|
content: '';
|
|
position: absolute;
|
|
inset: 0;
|
|
background-image:
|
|
linear-gradient(to right, rgba(239, 68, 68, 0.04) 1px, transparent 1px),
|
|
linear-gradient(to bottom, rgba(239, 68, 68, 0.04) 1px, transparent 1px);
|
|
background-size: 50px 50px;
|
|
animation: grid-move 30s linear infinite;
|
|
pointer-events: none;
|
|
z-index: 0;
|
|
}
|
|
.lb-grid-bg > * {
|
|
position: relative;
|
|
z-index: 1;
|
|
}
|
|
|
|
/* --- Cyber-accent: animated border pulse for critical states ---- */
|
|
.lb-pulse-critical {
|
|
animation: pulse-critical 2.5s ease-in-out infinite;
|
|
}
|
|
|
|
/* --- New keyframes used by the design system -------------------- */
|
|
@keyframes grid-move {
|
|
0% { background-position: 0 0; }
|
|
100% { background-position: 50px 50px; }
|
|
}
|
|
|
|
@keyframes pulse-critical {
|
|
0%, 100% {
|
|
box-shadow: 0 0 0 1px rgb(239 68 68 / 0.4),
|
|
0 0 24px -4px rgb(239 68 68 / 0.35);
|
|
}
|
|
50% {
|
|
box-shadow: 0 0 0 1px rgb(239 68 68 / 0.6),
|
|
0 0 30px -2px rgb(239 68 68 / 0.55);
|
|
}
|
|
}
|
|
|
|
/* =============================================================
|
|
* Existing rules (base, scrollbar, layout, sidebar) — unchanged.
|
|
* ============================================================= */
|
|
|
|
/* Base Styles */
|
|
body {
|
|
background: linear-gradient(to bottom right, #000000, #1a0000);
|
|
}
|
|
|
|
/* Scrollbar Styling */
|
|
::-webkit-scrollbar {
|
|
width: 8px;
|
|
height: 8px;
|
|
}
|
|
|
|
::-webkit-scrollbar-track {
|
|
background: rgba(0, 0, 0, 0.2);
|
|
border-radius: 4px;
|
|
}
|
|
|
|
::-webkit-scrollbar-thumb {
|
|
background: rgba(220, 38, 38, 0.3);
|
|
border-radius: 4px;
|
|
}
|
|
|
|
::-webkit-scrollbar-thumb:hover {
|
|
background: rgba(220, 38, 38, 0.5);
|
|
}
|
|
|
|
/* Upload Zone Styles
|
|
* Equivalent to Tailwind's `border-red-500 bg-red-500/5` plus a subtle scale.
|
|
* Written as raw CSS because @apply does not work without a build step.
|
|
*/
|
|
.drag-over {
|
|
border-color: rgb(239 68 68);
|
|
background-color: rgb(239 68 68 / 0.05);
|
|
transform: scale(1.01);
|
|
transition: all 0.2s ease;
|
|
}
|
|
|
|
/* Cards Hover Effect */
|
|
.analysis-card {
|
|
transition: all 0.2s ease;
|
|
}
|
|
|
|
.analysis-card:hover {
|
|
transform: translateY(-2px);
|
|
}
|
|
|
|
/* Monospace Font for Technical Data */
|
|
.font-mono {
|
|
font-family: 'JetBrains Mono', monospace;
|
|
}
|
|
|
|
/* Animations */
|
|
@keyframes pulse-red {
|
|
0%, 100% {
|
|
background-color: rgba(239, 68, 68, 0.1);
|
|
}
|
|
50% {
|
|
background-color: rgba(239, 68, 68, 0.2);
|
|
}
|
|
}
|
|
|
|
.animate-pulse-red {
|
|
animation: pulse-red 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
|
}
|
|
|
|
/* Loading Spinner */
|
|
.loading-spinner {
|
|
border: 3px solid rgba(239, 68, 68, 0.1);
|
|
border-top-color: rgb(239, 68, 68);
|
|
border-radius: 50%;
|
|
width: 24px;
|
|
height: 24px;
|
|
animation: spin 1s linear infinite;
|
|
}
|
|
|
|
@keyframes spin {
|
|
to {
|
|
transform: rotate(360deg);
|
|
}
|
|
}
|
|
|
|
/* Form Controls Dark Theme Override */
|
|
select,
|
|
input {
|
|
background-color: rgb(17 24 39 / 0.3) !important;
|
|
-webkit-appearance: none;
|
|
-moz-appearance: none;
|
|
appearance: none;
|
|
}
|
|
|
|
/* Custom Select Dropdown Arrow */
|
|
select {
|
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
|
|
background-position: right 0.5rem center;
|
|
background-repeat: no-repeat;
|
|
background-size: 1.5em 1.5em;
|
|
padding-right: 2.5rem;
|
|
}
|
|
|
|
.logo-wrapper {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 1rem;
|
|
margin-bottom: 0.5rem;
|
|
cursor: pointer;
|
|
text-decoration: none;
|
|
transition: opacity 0.2s;
|
|
}
|
|
|
|
.logo-wrapper:hover {
|
|
opacity: 0.8;
|
|
}
|
|
|
|
/* Autofill Style Override */
|
|
input:-webkit-autofill,
|
|
input:-webkit-autofill:hover,
|
|
input:-webkit-autofill:focus,
|
|
input:-webkit-autofill:active {
|
|
-webkit-box-shadow: 0 0 0 30px rgb(17 24 39 / 0.3) inset !important;
|
|
-webkit-text-fill-color: rgb(209 213 219) !important;
|
|
}
|
|
/* Simple fade animation for popover */
|
|
@keyframes fadeIn {
|
|
from { opacity: 0; transform: translateY(10px); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
.fade-in {
|
|
animation: fadeIn 0.2s ease-out;
|
|
}
|
|
|
|
/* Sidebar Base Styles */
|
|
.app-sidebar {
|
|
width: var(--sidebar-width-expanded);
|
|
transition: width var(--transition-speed) ease-in-out;
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
height: 100vh;
|
|
z-index: 50;
|
|
}
|
|
|
|
.app-sidebar.collapsed {
|
|
width: var(--sidebar-width-collapsed);
|
|
}
|
|
|
|
/* Main Content */
|
|
.app-content {
|
|
margin-left: var(--sidebar-width-expanded);
|
|
transition: margin-left var(--transition-speed) ease-in-out;
|
|
}
|
|
|
|
.app-content.sidebar-collapsed {
|
|
margin-left: var(--sidebar-width-collapsed);
|
|
}
|
|
|
|
/* Top Bar */
|
|
.app-topbar {
|
|
left: var(--sidebar-width-expanded);
|
|
transition: left var(--transition-speed) ease-in-out;
|
|
}
|
|
|
|
.app-topbar.sidebar-collapsed {
|
|
left: var(--sidebar-width-collapsed);
|
|
}
|
|
|
|
/* Sidebar Content Sections */
|
|
.sidebar-header {
|
|
padding: 1rem 1.25rem 0.5rem;
|
|
}
|
|
|
|
.app-sidebar.collapsed .sidebar-header {
|
|
padding: 1rem 0.5rem;
|
|
}
|
|
|
|
.sidebar-nav {
|
|
padding: 0 1.5rem;
|
|
transition: padding var(--transition-speed) ease-in-out;
|
|
}
|
|
|
|
.app-sidebar.collapsed .sidebar-nav {
|
|
padding: 0 0.5rem;
|
|
}
|
|
|
|
.sidebar-footer {
|
|
padding: 1rem 1.5rem;
|
|
transition: padding var(--transition-speed) ease-in-out;
|
|
}
|
|
|
|
.app-sidebar.collapsed .sidebar-footer {
|
|
padding: 1rem 0.5rem;
|
|
}
|
|
|
|
/* Logo Section — base .logo-wrapper rules live near the top of this file */
|
|
.app-sidebar.collapsed .logo-wrapper {
|
|
justify-content: center;
|
|
gap: 0;
|
|
}
|
|
|
|
.logo-text {
|
|
transition: opacity var(--transition-speed) ease-in-out;
|
|
}
|
|
|
|
.app-sidebar.collapsed .logo-text {
|
|
opacity: 0;
|
|
width: 0;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.logo-icon {
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
/* Navigation Items */
|
|
.nav-item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.75rem;
|
|
padding: 0.75rem 1rem;
|
|
margin-bottom: 0.5rem;
|
|
border-radius: 0.5rem;
|
|
transition: all 0.2s ease;
|
|
position: relative;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.app-sidebar.collapsed .nav-item {
|
|
justify-content: center;
|
|
padding: 0.75rem;
|
|
gap: 0;
|
|
}
|
|
|
|
.nav-icon {
|
|
width: 1.25rem;
|
|
height: 1.25rem;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.nav-text {
|
|
font-weight: 500;
|
|
transition: opacity var(--transition-speed) ease-in-out;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.app-sidebar.collapsed .nav-text {
|
|
opacity: 0;
|
|
width: 0;
|
|
overflow: hidden;
|
|
}
|
|
|
|
/* Tooltips for collapsed state */
|
|
.nav-tooltip {
|
|
position: absolute;
|
|
left: calc(100% + 0.5rem);
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
background: rgba(0, 0, 0, 0.9);
|
|
color: white;
|
|
padding: 0.5rem 0.75rem;
|
|
border-radius: 0.375rem;
|
|
font-size: 0.875rem;
|
|
white-space: nowrap;
|
|
opacity: 0;
|
|
visibility: hidden;
|
|
transition: opacity 0.2s, visibility 0.2s;
|
|
z-index: 1000;
|
|
border: 1px solid rgba(55, 65, 81, 0.5);
|
|
pointer-events: none;
|
|
}
|
|
|
|
.app-sidebar.collapsed .nav-item:hover .nav-tooltip {
|
|
opacity: 1;
|
|
visibility: visible;
|
|
}
|
|
|
|
/* Toggle Button */
|
|
.sidebar-toggle {
|
|
position: absolute;
|
|
top: 1rem;
|
|
right: -0.75rem;
|
|
width: 1.5rem;
|
|
height: 1.5rem;
|
|
background: rgba(0, 0, 0, 0.8);
|
|
border: 1px solid rgba(55, 65, 81, 0.5);
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
cursor: pointer;
|
|
transition: all 0.2s ease;
|
|
z-index: 60;
|
|
}
|
|
|
|
.sidebar-toggle:hover {
|
|
background: rgba(239, 68, 68, 0.2);
|
|
border-color: rgba(239, 68, 68, 0.3);
|
|
}
|
|
|
|
.sidebar-toggle svg {
|
|
width: 0.75rem;
|
|
height: 0.75rem;
|
|
transition: transform var(--transition-speed) ease;
|
|
}
|
|
|
|
.app-sidebar.collapsed .sidebar-toggle svg {
|
|
transform: rotate(180deg);
|
|
}
|
|
|
|
/* Status Section */
|
|
.status-wrapper {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.75rem;
|
|
}
|
|
|
|
.app-sidebar.collapsed .status-wrapper {
|
|
justify-content: center;
|
|
gap: 0;
|
|
}
|
|
|
|
.status-indicator {
|
|
width: 0.75rem;
|
|
height: 0.75rem;
|
|
border-radius: 50%;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.status-text {
|
|
font-size: 0.875rem;
|
|
transition: opacity var(--transition-speed) ease-in-out;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.app-sidebar.collapsed .status-text {
|
|
opacity: 0;
|
|
width: 0;
|
|
overflow: hidden;
|
|
}
|
|
|
|
/* Hover Effects */
|
|
.nav-item:hover {
|
|
background-color: rgba(239, 68, 68, 0.1);
|
|
color: white;
|
|
}
|
|
|
|
.nav-item:hover .nav-icon {
|
|
color: white;
|
|
} |