/* ========================================= LaserPerception Design System ========================================= */ :root { /* --- Colors --- */ --bg: #060914; --panel: #0b1026; --panel2: #0a0f22; --stroke: rgba(255, 255, 255, .08); --stroke2: rgba(255, 255, 255, .12); --text: rgba(255, 255, 255, .92); --muted: rgba(255, 255, 255, .62); --faint: rgba(255, 255, 255, .42); --good: #22c55e; --warn: #f59e0b; --bad: #ef4444; --accent: #7c3aed; --cyan: #22d3ee; --mag: #fb7185; /* --- Effects --- */ --shadow: 0 18px 60px rgba(0, 0, 0, .55); /* --- Typography --- */ --mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; --sans: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif; } * { box-sizing: border-box; } html, body { height: 100%; margin: 0; } body { background: radial-gradient(1200px 700px at 20% 8%, rgba(124, 58, 237, .22), transparent 60%), radial-gradient(900px 500px at 82% 18%, rgba(34, 211, 238, .18), transparent 60%), radial-gradient(800px 520px at 52% 82%, rgba(251, 113, 133, .10), transparent 65%), linear-gradient(180deg, #040614, #060914); color: var(--text); font-family: var(--sans); overflow: hidden; } /* ========================================= Layout & Structure ========================================= */ #app { height: 100%; display: flex; flex-direction: column; } header { display: flex; align-items: center; justify-content: space-between; padding: 14px 16px 12px; border-bottom: 1px solid var(--stroke); background: linear-gradient(180deg, rgba(255, 255, 255, .035), transparent); } .workspace { flex: 1; display: grid; grid-template-columns: 540px 1fr; /* Fixed sidebar width */ gap: 12px; padding: 12px; min-height: 0; } aside, main { background: rgba(255, 255, 255, .02); border: 1px solid var(--stroke); border-radius: 16px; box-shadow: var(--shadow); overflow: hidden; display: flex; flex-direction: column; min-height: 0; } footer { padding: 10px 14px; border-top: 1px solid var(--stroke); color: var(--muted); font-size: 11px; display: flex; justify-content: space-between; align-items: center; gap: 10px; background: linear-gradient(0deg, rgba(255, 255, 255, .03), transparent); } footer .mono { font-family: var(--mono); color: rgba(255, 255, 255, .76); } /* ========================================= Brand & Status ========================================= */ .brand { display: flex; gap: 12px; align-items: center; min-width: 420px; } .logo { width: 40px; height: 40px; border-radius: 14px; background: radial-gradient(circle at 30% 30%, rgba(34, 211, 238, .9), rgba(124, 58, 237, .9) 55%, rgba(0, 0, 0, .1) 70%), linear-gradient(135deg, rgba(255, 255, 255, .10), transparent 60%); box-shadow: 0 16px 46px rgba(124, 58, 237, .25); border: 1px solid rgba(255, 255, 255, .16); position: relative; overflow: hidden; } .logo:after { content: ""; position: absolute; inset: -40px; background: conic-gradient(from 180deg, transparent, rgba(255, 255, 255, .10), transparent); animation: spin 10s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } .brand h1 { font-size: 14px; margin: 0; letter-spacing: .16em; text-transform: uppercase; } .brand .sub { font-size: 12px; color: var(--muted); margin-top: 2px; line-height: 1.2; } .status-row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; justify-content: flex-end; } /* ========================================= Components: Cards & Panels ========================================= */ .card { padding: 12px 12px 10px; border-bottom: 1px solid var(--stroke); position: relative; } .card:last-child { border-bottom: none; } .card h2 { margin: 0; font-size: 12px; letter-spacing: .14em; text-transform: uppercase; color: rgba(255, 255, 255, .78); } .card small { color: var(--muted); } .card .hint { color: var(--faint); font-size: 11px; line-height: 1.35; margin-top: 6px; } .panel { background: linear-gradient(180deg, rgba(255, 255, 255, .03), rgba(255, 255, 255, .015)); border: 1px solid var(--stroke); border-radius: 16px; padding: 10px; box-shadow: 0 10px 30px rgba(0, 0, 0, .35); overflow: hidden; position: relative; } .panel h3 { margin: 0 0 8px; font-size: 12px; letter-spacing: .14em; text-transform: uppercase; color: rgba(255, 255, 255, .78); display: flex; align-items: center; justify-content: space-between; gap: 8px; } .panel h3 .rightnote { font-size: 11px; color: var(--muted); font-family: var(--mono); letter-spacing: 0; text-transform: none; } .collapse-btn { background: rgba(255, 255, 255, .05); border: 1px solid rgba(255, 255, 255, .12); border-radius: 8px; padding: 4px 8px; color: var(--muted); cursor: pointer; font-size: 11px; font-family: var(--mono); transition: all 0.2s ease; text-transform: none; letter-spacing: 0; } .collapse-btn:hover { background: rgba(255, 255, 255, .08); color: var(--text); border-color: rgba(255, 255, 255, .18); } /* ========================================= Components: Inputs & Controls ========================================= */ .grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 10px; } .row { display: flex; gap: 8px; align-items: center; justify-content: space-between; margin-top: 8px; } label { font-size: 11px; color: var(--muted); } input[type="range"] { width: 100%; } select, textarea, input[type="text"], input[type="number"] { width: 100%; background: rgba(255, 255, 255, .04); border: 1px solid var(--stroke2); border-radius: 10px; padding: 8px 10px; color: var(--text); outline: none; font-size: 12px; } select:focus, textarea:focus, input[type="text"]:focus, input[type="number"]:focus { border-color: rgba(124, 58, 237, .55); box-shadow: 0 0 0 3px rgba(124, 58, 237, .16); } .btn { user-select: none; cursor: pointer; border: none; border-radius: 12px; padding: 10px 12px; font-weight: 700; font-size: 12px; letter-spacing: .04em; color: rgba(255, 255, 255, .92); background: linear-gradient(135deg, rgba(124, 58, 237, .95), rgba(34, 211, 238, .45)); box-shadow: 0 18px 40px rgba(124, 58, 237, .24); } .btn:hover { filter: brightness(1.06); } .btn:active { transform: translateY(1px); } .btn.secondary { background: rgba(255, 255, 255, .06); border: 1px solid var(--stroke2); box-shadow: none; font-weight: 600; } .btn.secondary:hover { background: rgba(255, 255, 255, .08); } .btn.danger { background: linear-gradient(135deg, rgba(239, 68, 68, .95), rgba(251, 113, 133, .55)); box-shadow: 0 18px 40px rgba(239, 68, 68, .18); } .btnrow { display: flex; gap: 8px; margin-top: 10px; } .btnrow .btn { flex: 1; } .pill { display: flex; align-items: center; gap: 10px; padding: 8px 12px; border-radius: 999px; border: 1px solid var(--stroke2); background: rgba(255, 255, 255, .04); box-shadow: 0 10px 26px rgba(0, 0, 0, .35); font-size: 12px; color: var(--muted); white-space: nowrap; } .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--good); box-shadow: 0 0 16px rgba(34, 197, 94, .6); } .dot.warn { background: var(--warn); box-shadow: 0 0 16px rgba(245, 158, 11, .55); } .dot.bad { background: var(--bad); box-shadow: 0 0 16px rgba(239, 68, 68, .55); } .kbd { font-family: var(--mono); font-size: 11px; padding: 2px 6px; border: 1px solid var(--stroke2); border-bottom-color: rgba(255, 255, 255, .24); background: rgba(0, 0, 0, .35); border-radius: 7px; color: rgba(255, 255, 255, .78); } .badge { display: inline-flex; align-items: center; gap: 6px; padding: 4px 8px; border-radius: 999px; border: 1px solid var(--stroke2); background: rgba(0, 0, 0, .25); font-family: var(--mono); } /* ========================================= Navigation: Tabs ========================================= */ .tabs { display: flex; gap: 8px; padding: 10px 12px; border-bottom: 1px solid var(--stroke); background: linear-gradient(180deg, rgba(255, 255, 255, .035), transparent); flex-wrap: wrap; } .tabbtn { cursor: pointer; border: none; border-radius: 999px; padding: 8px 12px; font-size: 12px; color: rgba(255, 255, 255, .75); background: rgba(255, 255, 255, .04); border: 1px solid var(--stroke2); } .tabbtn.active { color: rgba(255, 255, 255, .92); background: linear-gradient(135deg, rgba(124, 58, 237, .35), rgba(34, 211, 238, .10)); border-color: rgba(124, 58, 237, .45); box-shadow: 0 0 0 3px rgba(124, 58, 237, .14); } .tab { display: none; flex: 1; min-height: 0; overflow: auto; padding: 12px; } .tab.active { display: block; } /* ========================================= Visualization: Views & Canvas ========================================= */ .viewbox { position: relative; border-radius: 14px; overflow: hidden; background: radial-gradient(700px 380px at 30% 30%, rgba(124, 58, 237, .12), rgba(0, 0, 0, .0) 60%), linear-gradient(180deg, rgba(0, 0, 0, .25), rgba(0, 0, 0, .15)); border: 1px solid rgba(255, 255, 255, .08); min-height: 360px; } .viewbox canvas, .viewbox video { width: 100%; height: 100%; display: block; object-fit: contain; /* Maintain aspect ratio, letterbox if needed */ } /* Always show the engage video feed */ #videoEngage { display: block; opacity: 1; } /* Overlay must use same object-fit as the main canvas to align properly */ .viewbox .overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; object-fit: contain; /* CRITICAL: match frameCanvas object-fit */ } /* Make engage overlay visible as main display (not just overlay) */ #engageOverlay { display: none; pointer-events: none; } .viewbox .watermark { position: absolute; left: 10px; bottom: 10px; font-family: var(--mono); font-size: 11px; color: rgba(255, 255, 255, .55); background: rgba(0, 0, 0, .35); border: 1px solid rgba(255, 255, 255, .14); padding: 6px 8px; border-radius: 10px; } .viewbox .empty { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; color: rgba(255, 255, 255, .72); text-align: center; padding: 22px; } .viewbox .empty .big { font-size: 14px; letter-spacing: .12em; text-transform: uppercase; } .viewbox .empty .small { color: var(--muted); font-size: 12px; max-width: 520px; line-height: 1.4; } /* ========================================= Lists & Tables ========================================= */ .list { display: flex; flex-direction: column; gap: 8px; min-height: 160px; max-height: 320px; overflow: auto; padding-right: 4px; } .obj { padding: 10px; border-radius: 14px; border: 1px solid var(--stroke2); background: rgba(255, 255, 255, .03); cursor: pointer; } .obj:hover { background: rgba(255, 255, 255, .05); } .obj.active { border-color: rgba(34, 211, 238, .45); box-shadow: 0 0 0 3px rgba(34, 211, 238, .14); background: linear-gradient(135deg, rgba(34, 211, 238, .10), rgba(124, 58, 237, .08)); } .obj .top { display: flex; align-items: center; justify-content: space-between; gap: 10px; } .obj .id { font-family: var(--mono); font-size: 12px; color: rgba(255, 255, 255, .90); } .obj .cls { font-size: 12px; color: rgba(255, 255, 255, .80); } .obj .meta { margin-top: 6px; display: flex; gap: 10px; flex-wrap: wrap; font-size: 11px; color: var(--muted); } .table { width: 100%; border-collapse: separate; border-spacing: 0; overflow: hidden; border-radius: 14px; border: 1px solid rgba(255, 255, 255, .10); } .table th, .table td { padding: 8px 10px; font-size: 12px; border-bottom: 1px solid rgba(255, 255, 255, .08); vertical-align: top; } .table th { background: rgba(255, 255, 255, .04); color: rgba(255, 255, 255, .78); letter-spacing: .12em; text-transform: uppercase; font-size: 11px; } .table tr:last-child td { border-bottom: none; } .k { font-family: var(--mono); color: rgba(255, 255, 255, .84); } .mini { font-size: 11px; color: var(--muted); line-height: 1.35; } /* ========================================= Metrics & Logs ========================================= */ .metricgrid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; } .metric { border: 1px solid rgba(255, 255, 255, .10); background: rgba(255, 255, 255, .03); border-radius: 14px; padding: 10px; } .metric .label { font-size: 11px; color: var(--muted); letter-spacing: .12em; text-transform: uppercase; } .metric .value { margin-top: 6px; font-family: var(--mono); font-size: 16px; color: rgba(255, 255, 255, .92); } .metric .sub { margin-top: 4px; font-size: 11px; color: var(--faint); line-height: 1.35; } .log { font-family: var(--mono); font-size: 11px; color: rgba(255, 255, 255, .78); line-height: 1.45; background: rgba(0, 0, 0, .35); border: 1px solid rgba(255, 255, 255, .12); border-radius: 14px; padding: 10px; height: 210px; overflow: auto; white-space: pre-wrap; } .log .t { color: rgba(34, 211, 238, .95); } .log .w { color: rgba(245, 158, 11, .95); } .log .e { color: rgba(239, 68, 68, .95); } .log .g { color: rgba(34, 197, 94, .95); } /* ========================================= Tab Specific: Intel + Frame ========================================= */ .frame-grid { display: grid; grid-template-columns: 1.6fr .9fr; grid-template-rows: auto auto 1fr; gap: 12px; min-height: 0; } .intel { margin-top: 10px; display: flex; flex-direction: column; gap: 8px; } .intel-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .thumbrow { display: flex; gap: 8px; } .thumbrow img { flex: 1; height: 86px; object-fit: cover; border-radius: 12px; border: 1px solid rgba(255, 255, 255, .12); background: rgba(0, 0, 0, .25); } .intelbox { font-size: 12px; line-height: 1.45; color: rgba(255, 255, 255, .84); background: rgba(0, 0, 0, .35); border: 1px solid rgba(255, 255, 255, .12); border-radius: 14px; padding: 10px; min-height: 72px; } /* ========================================= Tab Specific: Engage ========================================= */ .engage-grid { display: grid; grid-template-columns: 1.6fr .9fr; gap: 12px; min-height: 0; transition: grid-template-columns 0.3s ease; } .engage-grid.sidebar-collapsed { grid-template-columns: 1fr 0fr; } .engage-grid.sidebar-collapsed .engage-right { display: none; } .engage-right { display: flex; flex-direction: column; gap: 12px; min-height: 0; } .radar { height: 540px; display: flex; flex-direction: column; } .radar canvas { flex: 1; width: 100%; height: 100%; display: block; } .strip { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; font-size: 12px; color: var(--muted); } .strip .chip { padding: 6px 10px; border-radius: 999px; border: 1px solid rgba(255, 255, 255, .12); background: rgba(255, 255, 255, .03); font-family: var(--mono); color: rgba(255, 255, 255, .78); } /* Sidebar Checkbox Row */ .checkbox-row { grid-column: span 2; margin-top: 8px; border-top: 1px solid var(--stroke2); padding-top: 8px; display: flex; align-items: center; gap: 8px; cursor: pointer; } .checkbox-row input[type="checkbox"] { width: auto; margin: 0; } .bar { height: 10px; border-radius: 999px; background: rgba(255, 255, 255, .08); border: 1px solid rgba(255, 255, 255, .12); overflow: hidden; } .bar>div { height: 100%; width: 0%; background: linear-gradient(90deg, rgba(34, 211, 238, .95), rgba(124, 58, 237, .95)); transition: width .18s ease; } /* ========================================= Tab Specific: Trade Space ========================================= */ .trade-grid { display: grid; grid-template-columns: 1.35fr .65fr; gap: 12px; min-height: 0; } .plot { height: 420px; } /* ========================================= Utilities ========================================= */ ::-webkit-scrollbar { width: 10px; height: 10px; } ::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, .10); border-radius: 999px; border: 2px solid rgba(0, 0, 0, .25); } ::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, .16); } /* Track Cards */ .track-card { background: rgba(255, 255, 255, 0.03); border: 1px solid var(--border-color); border-radius: 4px; padding: 8px; margin-bottom: 8px; cursor: pointer; transition: all 0.2s; } .track-card:hover { background: rgba(255, 255, 255, 0.08); } .track-card.active { border-color: var(--accent); background: rgba(34, 211, 238, 0.1); } .track-card-header { display: flex; justify-content: space-between; align-items: center; font-weight: 600; margin-bottom: 4px; font-size: 13px; color: var(--text-color); } .track-card-meta { font-size: 11px; color: var(--text-dim); margin-bottom: 4px; } .track-card-body { font-size: 11px; line-height: 1.4; color: #ccc; background: rgba(0, 0, 0, 0.2); padding: 6px; border-radius: 4px; } .gpt-badge { color: gold; font-size: 10px; border: 1px solid gold; border-radius: 3px; padding: 1px 4px; margin-left: 6px; } .gpt-text { color: #e0e0e0; }