/* Custom scrollbar */ ::-webkit-scrollbar { width: 6px; height: 6px; } ::-webkit-scrollbar-track { background: #0f172a; } ::-webkit-scrollbar-thumb { background: #334155; border-radius: 3px; } ::-webkit-scrollbar-thumb:hover { background: #475569; } /* Camera Feed Styles */ .camera-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); gap: 1rem; padding: 1rem; } .camera-feed-wrapper { background: #1e293b; border: 1px solid #334155; border-radius: 8px; overflow: hidden; position: relative; } .camera-feed-wrapper.single-view { grid-column: 1 / -1; max-width: 1200px; margin: 0 auto; } /* CRM Styles */ .client-form input, .client-form select { transition: border-color 0.2s; } .client-form input:focus, .client-form select:focus { outline: none; border-color: #06b6d4; box-shadow: 0 0 0 3px rgba(6, 182, 212, 0.1); } /* ONVIF Scanner Animation */ @keyframes scanPulse { 0%, 100% { opacity: 0.4; } 50% { opacity: 1; } } .scanning-active { animation: scanPulse 1.5s ease-in-out infinite; } /* Fullscreen camera override */ camera-feed:fullscreen { width: 100vw; height: 100vh; background: black; } camera-feed:fullscreen .camera-container { height: 100%; } /* Animations */ @keyframes fadeIn { from { opacity: 0; transform: translateY(-5px); } to { opacity: 1; transform: translateY(0); } } @keyframes fadeOut { from { opacity: 1; transform: translateY(0); } to { opacity: 0; transform: translateY(-5px); } } @keyframes pulse-red { 0% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.7); } 70% { box-shadow: 0 0 0 10px rgba(239, 68, 68, 0); } 100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0); } } @keyframes scan-line { 0% { transform: translateX(-100%); } 100% { transform: translateX(200%); } } .animate-fade-in { animation: fadeIn 0.3s ease-out forwards; } .alert-pulse { animation: pulse-red 2s infinite; } /* Map Dots */ .map-dot { width: 24px; height: 24px; border-radius: 50%; background-color: #06b6d4; box-shadow: 0 0 8px #06b6d4; transition: all 0.5s ease-in-out; opacity: 0; transform: scale(0); position: absolute; z-index: 20; display: flex; align-items: center; justify-content: center; font-size: 10px; font-weight: bold; color: white; border: 2px solid rgba(255, 255, 255, 0.3); } .map-dot.active { opacity: 1; transform: scale(1); animation: dotPulse 1.5s ease-in-out infinite; } .map-dot.latent { background-color: #f59e0b; box-shadow: 0 0 10px #f59e0b, 0 0 20px rgba(245, 158, 11, 0.5); animation: dotWarning 1s ease-in-out infinite; border-color: rgba(255, 255, 255, 0.5); } .map-dot.confirmed { background-color: #ef4444; box-shadow: 0 0 15px #ef4444, 0 0 30px rgba(239, 68, 68, 0.5); animation: dotAlert 0.5s ease-in-out infinite; border-color: rgba(255, 255, 255, 0.8); } /* Zone hover effects enhancement */ [id^="zone-"] { transition: all 0.3s ease; position: relative; overflow: visible; } [id^="zone-"]:hover { transform: scale(1.02); z-index: 10; box-shadow: 0 0 20px rgba(6, 182, 212, 0.2); } @keyframes dotPulse { 0%, 100% { box-shadow: 0 0 8px #06b6d4; } 50% { box-shadow: 0 0 16px #06b6d4, 0 0 24px rgba(6, 182, 212, 0.5); } } @keyframes dotWarning { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.2); } } @keyframes dotAlert { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.3); opacity: 0.8; } } /* Scan Beam Effect */ #scan-beam { background: linear-gradient(90deg, transparent, rgba(34, 197, 94, 0.8), #22c55e, rgba(34, 197, 94, 0.8), transparent); width: 150px; height: 100%; position: absolute; animation: scan-line 2s linear infinite; filter: blur(2px); } /* Custom Styles for Web Component Shadow DOM to allow global theme leaking if needed, but usually we encapsulate. Here we just fix base styling. */ sentinel-navbar { display: block; width: 100%; } /* Hover effects for map zones */ [id^="zone-"] { transition: all 0.3s ease; } [id^="zone-"]:hover { transform: scale(1.02); z-index: 5; } /* Simulation button active state */ .sim-btn:active { transform: scale(0.95); } /* Modal animations */ .modal-enter { animation: modalFadeIn 0.3s ease-out; } @keyframes modalFadeIn { from { opacity: 0; transform: scale(0.95); } to { opacity: 1; transform: scale(1); } } /* Camera status indicators */ .status-online { color: #22c55e; } .status-offline { color: #ef4444; } .status-warning { color: #f59e0b; } /* PTZ Controls overlay */ .ptz-overlay { position: absolute; inset: 0; background: rgba(0,0,0,0.3); opacity: 0; transition: opacity 0.3s; display: flex; align-items: center; justify-content: center; } .camera-container:hover .ptz-overlay { opacity: 1; } /* NVR Status Panel Animations */ @keyframes dataPulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } } .animate-data-flow { animation: dataPulse 2s ease-in-out infinite; } /* Uptime counter styling */ #uptime { font-variant-numeric: tabular-nums; letter-spacing: 0.05em; }