:root { --bg: #06090c; --surface: #0b1015; --surface-2: #10161c; --surface-3: #151c23; --border: rgba(255, 255, 255, 0.08); --border-strong: rgba(255, 255, 255, 0.13); --text: #f5f7f8; --muted: #87929d; --muted-2: #5f6a74; --accent: #8bf0b9; --accent-soft: rgba(139, 240, 185, 0.10); --accent-border: rgba(139, 240, 185, 0.25); --danger: #ff7777; --radius-lg: 24px; --radius-md: 16px; --radius-sm: 12px; --shadow: 0 24px 70px rgba(0, 0, 0, 0.35); --ease: cubic-bezier(0.22, 1, 0.36, 1); } * { box-sizing: border-box; } html { width: 100%; min-height: 100%; background: var(--bg); } body { margin: 0; width: 100%; min-height: 100%; background: radial-gradient( circle at 70% -10%, rgba(139, 240, 185, 0.055), transparent 32% ), var(--bg); color: var(--text); font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; } button, input { font: inherit; } button { -webkit-tap-highlight-color: transparent; } button:focus-visible, input:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; } /* ========================================= APP ========================================= */ #app { width: 100%; min-height: 100vh; padding: 18px max(18px, 3vw) 28px; } /* ========================================= TOPBAR ========================================= */ .topbar { width: 100%; max-width: 1600px; margin: 0 auto 18px; display: flex; align-items: center; justify-content: space-between; min-height: 52px; } .brand { display: flex; align-items: center; gap: 11px; } .brand-mark { width: 34px; height: 34px; border: 1px solid var(--accent-border); border-radius: 11px; display: flex; align-items: center; justify-content: center; gap: 3px; background: linear-gradient( 145deg, rgba(139, 240, 185, 0.12), rgba(139, 240, 185, 0.025) ); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06); } .brand-mark span { width: 3px; border-radius: 4px; background: var(--accent); } .brand-mark span:nth-child(1) { height: 9px; opacity: 0.55; } .brand-mark span:nth-child(2) { height: 15px; opacity: 0.8; } .brand-mark span:nth-child(3) { height: 21px; } .brand-name { font-size: 17px; font-weight: 800; letter-spacing: -0.035em; } .brand-name span { color: var(--accent); } .brand-version { margin-top: 1px; color: var(--muted-2); font-size: 9px; font-weight: 700; letter-spacing: 0.16em; } .connection { display: flex; align-items: center; gap: 8px; padding: 8px 12px; border: 1px solid var(--border); border-radius: 999px; background: rgba(255, 255, 255, 0.018); color: var(--muted); font-size: 12px; } .connection-dot { width: 7px; height: 7px; border-radius: 50%; transition: background 0.3s ease, box-shadow 0.3s ease; } .connection-dot.online { background: var(--accent); box-shadow: 0 0 0 4px rgba(139, 240, 185, 0.09), 0 0 14px rgba(139, 240, 185, 0.45); } .connection-dot.offline { background: #5e6871; } .connection-dot.error { background: var(--danger); box-shadow: 0 0 0 4px rgba(255, 119, 119, 0.08); } /* ========================================= MAIN ========================================= */ .main { width: 100%; max-width: 1600px; margin: 0 auto; display: grid; grid-template-columns: minmax(0, 1fr) minmax(320px, 390px); gap: 18px; align-items: start; } /* ========================================= VIEWER ========================================= */ .viewer { min-width: 0; } .camera-card { position: relative; width: 100%; min-height: 520px; overflow: hidden; border: 1px solid var(--border-strong); border-radius: var(--radius-lg); background: #030506; box-shadow: var(--shadow); isolation: isolate; } .camera-card::after { content: ""; position: absolute; inset: 0; pointer-events: none; z-index: 5; background: linear-gradient( 180deg, rgba(0, 0, 0, 0.20), transparent 20%, transparent 78%, rgba(0, 0, 0, 0.28) ); } #camera { display: block; width: 100%; height: 100%; min-height: 520px; object-fit: cover; background: #030506; } #overlay { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 4; } /* ========================================= PLACEHOLDER ========================================= */ .camera-placeholder { position: absolute; inset: 0; z-index: 7; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 30px; text-align: center; background: radial-gradient( circle at center, rgba(139, 240, 185, 0.055), transparent 40% ); } .camera-placeholder h2 { margin: 16px 0 6px; font-size: clamp(20px, 3vw, 28px); letter-spacing: -0.04em; } .camera-placeholder p { max-width: 390px; margin: 0 0 22px; color: var(--muted); line-height: 1.6; font-size: 14px; } .camera-icon { width: 70px; height: 70px; border: 1px solid var(--accent-border); border-radius: 22px; display: grid; place-items: center; background: rgba(139, 240, 185, 0.055); animation: floatIcon 4s ease-in-out infinite; } .camera-icon svg { width: 29px; height: 29px; fill: none; stroke: var(--accent); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; } @keyframes floatIcon { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-5px); } } /* ========================================= LIVE BADGE ========================================= */ .live-badge { position: absolute; top: 16px; left: 16px; z-index: 8; display: flex; align-items: center; gap: 7px; padding: 8px 11px; border: 1px solid rgba(139, 240, 185, 0.18); border-radius: 999px; background: rgba(5, 12, 9, 0.72); backdrop-filter: blur(14px); color: var(--accent); font-size: 10px; font-weight: 800; letter-spacing: 0.13em; } .live-pulse { width: 7px; height: 7px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 0 rgba(139, 240, 185, 0.5); animation: pulseLive 1.7s infinite; } @keyframes pulseLive { 0% { box-shadow: 0 0 0 0 rgba(139, 240, 185, 0.5); } 70% { box-shadow: 0 0 0 8px rgba(139, 240, 185, 0); } 100% { box-shadow: 0 0 0 0 rgba(139, 240, 185, 0); } } /* ========================================= FPS ========================================= */ .fps-badge { position: absolute; top: 16px; right: 16px; z-index: 8; padding: 8px 10px; border: 1px solid var(--border); border-radius: 999px; background: rgba(5, 7, 9, 0.70); backdrop-filter: blur(14px); color: #fff; font-size: 10px; font-weight: 700; letter-spacing: 0.06em; } /* ========================================= RETICLE ========================================= */ .reticle { position: absolute; top: 50%; left: 50%; width: 34px; height: 34px; transform: translate(-50%, -50%); z-index: 3; opacity: 0.65; pointer-events: none; } .reticle::before, .reticle::after { content: ""; position: absolute; inset: 0; border: 1px solid rgba(139, 240, 185, 0.7); border-radius: 50%; } .reticle::after { inset: 11px; border: 1px solid var(--accent); background: rgba(139, 240, 185, 0.08); } /* ========================================= CAMERA CONTROLS ========================================= */ .camera-controls { display: flex; align-items: center; gap: 9px; margin-top: 12px; } .control-button { min-height: 44px; display: inline-flex; align-items: center; justify-content: center; gap: 8px; padding: 0 15px; border: 1px solid var(--border); border-radius: 13px; background: rgba(255, 255, 255, 0.025); color: var(--text); cursor: pointer; transition: transform 0.2s var(--ease), background 0.2s ease, border-color 0.2s ease, opacity 0.2s ease; } .control-button:hover:not(:disabled) { transform: translateY(-1px); background: rgba(255, 255, 255, 0.055); border-color: var(--border-strong); } .control-button:active:not(:disabled) { transform: scale(0.97); } .control-button:disabled { opacity: 0.35; cursor: not-allowed; } .control-button.danger { color: #ff9a9a; } .button-icon { opacity: 0.75; } .upload-button { cursor: pointer; } /* ========================================= SIDEBAR ========================================= */ .sidebar { min-width: 0; display: flex; flex-direction: column; gap: 12px; } .panel { padding: 19px; border: 1px solid var(--border); border-radius: var(--radius-lg); background: linear-gradient( 145deg, rgba(17, 23, 29, 0.96), rgba(9, 13, 17, 0.96) ); box-shadow: 0 18px 50px rgba(0, 0, 0, 0.20); } /* ========================================= PANEL HEADER ========================================= */ .panel-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 18px; } .eyebrow { margin-bottom: 5px; color: var(--accent); font-size: 9px; font-weight: 800; letter-spacing: 0.16em; } .panel-header h1 { margin: 0; font-size: 24px; letter-spacing: -0.045em; } .model-chip { flex-shrink: 0; display: flex; align-items: center; gap: 6px; padding: 6px 8px; border: 1px solid var(--border); border-radius: 999px; color: var(--muted); font-size: 9px; font-weight: 800; letter-spacing: 0.08em; } .model-chip span { width: 5px; height: 5px; border-radius: 50%; background: var(--accent); } /* ========================================= SEARCH ========================================= */ .search-wrapper { position: relative; width: 100%; } .search-wrapper input { width: 100%; min-height: 52px; padding: 0 42px 0 43px; border: 1px solid var(--border-strong); border-radius: 15px; background: rgba(0, 0, 0, 0.22); color: var(--text); font-size: 14px; outline: none; transition: border-color 0.2s ease, background 0.2s ease, box-shadow 0.2s ease; } .search-wrapper input::placeholder { color: var(--muted-2); } .search-wrapper input:focus { border-color: var(--accent-border); background: rgba(139, 240, 185, 0.025); box-shadow: 0 0 0 4px rgba(139, 240, 185, 0.045); } .search-icon { position: absolute; left: 15px; top: 50%; width: 19px; height: 19px; transform: translateY(-50%); fill: none; stroke: var(--muted); stroke-width: 1.7; stroke-linecap: round; pointer-events: none; } .clear-query { position: absolute; right: 9px; top: 50%; width: 34px; height: 34px; transform: translateY(-50%); border: 0; border-radius: 10px; background: transparent; color: var(--muted); cursor: pointer; font-size: 20px; line-height: 1; transition: background 0.2s ease, color 0.2s ease; } .clear-query:hover { background: rgba(255, 255, 255, 0.05); color: var(--text); } /* ========================================= SECTIONS ========================================= */ .quick-section, .mode-section { margin-top: 18px; } .section-label { margin-bottom: 9px; color: var(--muted-2); font-size: 9px; font-weight: 800; letter-spacing: 0.14em; } /* ========================================= CHIPS ========================================= */ .chips { display: flex; flex-wrap: wrap; gap: 7px; } .chip { min-height: 34px; padding: 0 11px; border: 1px solid var(--border); border-radius: 999px; background: rgba(255, 255, 255, 0.025); color: var(--muted); font-size: 11px; cursor: pointer; transition: all 0.2s var(--ease); } .chip:hover { color: var(--text); background: rgba(255, 255, 255, 0.05); } .chip.active { border-color: var(--accent-border); background: var(--accent-soft); color: var(--accent); } /* ========================================= MODE SWITCH ========================================= */ .mode-switch { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; padding: 5px; border: 1px solid var(--border); border-radius: 15px; background: rgba(0, 0, 0, 0.18); } .mode-button { min-height: 58px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; border: 0; border-radius: 11px; background: transparent; color: var(--muted); cursor: pointer; transition: all 0.25s var(--ease); } .mode-button strong { color: inherit; font-size: 11px; } .mode-button span { font-size: 9px; opacity: 0.65; white-space: nowrap; } .mode-button.active { background: var(--surface-3); color: var(--accent); box-shadow: 0 5px 18px rgba(0, 0, 0, 0.22); } /* ========================================= STATS ========================================= */ .stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 7px; margin-top: 18px; } .stat { min-width: 0; padding: 11px; border: 1px solid var(--border); border-radius: 13px; background: rgba(255, 255, 255, 0.018); text-align: center; } .stat-value { min-height: 22px; overflow: hidden; text-overflow: ellipsis; font-size: 15px; font-weight: 800; } .stat-label { margin-top: 3px; color: var(--muted-2); font-size: 9px; } /* ========================================= STATUS ========================================= */ .status-box { display: flex; align-items: flex-start; gap: 10px; margin-top: 12px; padding: 13px; border: 1px solid rgba(139, 240, 185, 0.10); border-radius: 14px; background: rgba(139, 240, 185, 0.035); } .status-icon { width: 24px; height: 24px; flex: 0 0 auto; display: grid; place-items: center; border-radius: 8px; background: rgba(139, 240, 185, 0.08); } .status-icon span { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); } .status-box strong { display: block; margin-bottom: 3px; font-size: 11px; } .status-box p { margin: 0; color: var(--muted); font-size: 10px; line-height: 1.45; } /* ========================================= RESULTS ========================================= */ .results-panel { padding: 15px; border: 1px solid var(--border); border-radius: 18px; background: rgba(11, 16, 21, 0.85); } .results-header { display: flex; justify-content: space-between; color: var(--muted); font-size: 9px; font-weight: 800; letter-spacing: 0.13em; } .results-header span:last-child { color: var(--accent); } .results-list { display: flex; flex-direction: column; gap: 6px; margin-top: 10px; } .result-item { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 9px 10px; border: 1px solid var(--border); border-radius: 11px; background: rgba(255, 255, 255, 0.02); animation: resultIn 0.35s var(--ease) both; } @keyframes resultIn { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: translateY(0); } } .result-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); font-size: 11px; } .result-index { flex-shrink: 0; color: var(--accent); font-size: 9px; } /* ========================================= MODEL INFO ========================================= */ .model-info { display: flex; align-items: center; gap: 10px; padding: 11px 13px; border: 1px solid var(--border); border-radius: 15px; background: rgba(255, 255, 255, 0.015); } .model-info-icon { width: 27px; height: 27px; display: grid; place-items: center; border-radius: 9px; background: var(--accent-soft); color: var(--accent); font-size: 13px; } .model-info strong { display: block; font-size: 10px; } .model-info span { display: block; margin-top: 2px; color: var(--muted-2); font-size: 9px; } /* ========================================= PRIMARY BUTTON ========================================= */ .primary-button { min-height: 45px; padding: 0 18px; border: 1px solid rgba(139, 240, 185, 0.28); border-radius: 13px; background: var(--accent); color: #06100a; font-size: 12px; font-weight: 800; cursor: pointer; box-shadow: 0 10px 28px rgba(139, 240, 185, 0.10); transition: transform 0.2s var(--ease), box-shadow 0.2s ease; } .primary-button:hover { transform: translateY(-2px); box-shadow: 0 14px 32px rgba(139, 240, 185, 0.17); } .primary-button:active { transform: scale(0.97); } /* ========================================= MOBILE BAR ========================================= */ .mobile-bar { display: none; } /* ========================================= MODAL ========================================= */ .modal { position: fixed; inset: 0; z-index: 100; display: grid; place-items: center; padding: 20px; background: rgba(0, 0, 0, 0.68); backdrop-filter: blur(12px); } .modal-card { width: min( 100%, 380px ); padding: 27px; border: 1px solid var(--border-strong); border-radius: 22px; background: var(--surface-2); text-align: center; box-shadow: 0 30px 90px rgba(0, 0, 0, 0.45); animation: modalIn 0.35s var(--ease); } @keyframes modalIn { from { opacity: 0; transform: translateY(14px) scale(0.97); } to { opacity: 1; transform: translateY(0) scale(1); } } .modal-icon { font-size: 30px; } .modal-card h2 { margin: 13px 0 7px; font-size: 20px; letter-spacing: -0.035em; } .modal-card p { margin: 0 0 20px; color: var(--muted); font-size: 13px; line-height: 1.55; } /* ========================================= UTILITIES ========================================= */ .hidden { display: none !important; } /* ========================================= TABLET ========================================= */ @media (max-width: 1050px) { #app { padding: 15px 15px 90px; } .main { grid-template-columns: minmax(0, 1fr) 330px; } .camera-card, #camera { min-height: 480px; } } /* ========================================= MOBILE ========================================= */ @media (max-width: 780px) { #app { padding: 12px 12px 85px; } .topbar { margin-bottom: 11px; } .connection { padding: 7px 9px; } .connection span:last-child { display: none; } .main { display: flex; flex-direction: column; gap: 12px; } .viewer { width: 100%; } .camera-card { min-height: 62vw; max-height: 72vh; border-radius: 19px; } #camera { min-height: 62vw; max-height: 72vh; } .camera-controls { display: none; } .sidebar { width: 100%; } .panel { padding: 15px; border-radius: 19px; } .panel-header h1 { font-size: 21px; } .model-chip { display: none; } .mode-button { min-height: 54px; } .mode-button span { display: none; } .mobile-bar { position: fixed; left: 10px; right: 10px; bottom: 10px; z-index: 50; display: grid; grid-template-columns: 1fr 1fr; gap: 8px; padding: 7px; border: 1px solid var(--border-strong); border-radius: 17px; background: rgba(11, 16, 21, 0.88); backdrop-filter: blur(20px); box-shadow: 0 15px 45px rgba(0, 0, 0, 0.38); } .mobile-action { min-height: 45px; border: 0; border-radius: 12px; background: rgba(255, 255, 255, 0.05); color: var(--text); font-size: 12px; font-weight: 750; } .mobile-action.primary { background: var(--accent); color: #06100a; } .mobile-action:disabled { opacity: 0.35; } } /* ========================================= SMALL PHONES ========================================= */ @media (max-width: 400px) { .brand-name { font-size: 15px; } .brand-mark { width: 31px; height: 31px; } .camera-placeholder { padding: 20px; } .camera-placeholder h2 { font-size: 20px; } .camera-placeholder p { font-size: 12px; } .camera-icon { width: 60px; height: 60px; } .stats { gap: 5px; } .stat { padding: 9px 5px; } .stat-value { font-size: 13px; } .stat-label { font-size: 8px; } } /* ========================================= REDUCED MOTION ========================================= */ @media (prefers-reduced-motion: reduce) { *, *::before, *::after { scroll-behavior: auto !important; animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; } }