| |
| |
| |
|
|
| :root { |
| --blue: #2563eb; |
| --blue-light: #eff6ff; |
| --blue-mid: #dbeafe; |
| --green: #16a34a; |
| --green-light: #f0fdf4; |
| --amber: #d97706; |
| --amber-light: #fffbeb; |
| --red: #dc2626; |
| --red-light: #fef2f2; |
|
|
| --text: #111827; |
| --text-2: #6b7280; |
| --text-3: #9ca3af; |
| --border: #e5e7eb; |
| --bg: #f9fafb; |
| --surface: #ffffff; |
| --shadow: 0 1px 3px rgba(0, 0, 0, 0.08), 0 1px 2px rgba(0, 0, 0, 0.05); |
| --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.08), 0 2px 4px -2px rgba(0, 0, 0, 0.05); |
|
|
| --radius: 8px; |
| --font: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; |
| } |
|
|
| * { |
| box-sizing: border-box; |
| margin: 0; |
| padding: 0; |
| } |
|
|
| body { |
| font-family: var(--font); |
| font-size: 14px; |
| color: var(--text); |
| background: var(--bg); |
| line-height: 1.5; |
| -webkit-font-smoothing: antialiased; |
| } |
|
|
| |
| .header { |
| background: var(--surface); |
| border-bottom: 1px solid var(--border); |
| position: sticky; |
| top: 0; |
| z-index: 100; |
| } |
|
|
| .header-inner { |
| max-width: 1100px; |
| margin: 0 auto; |
| padding: 0 20px; |
| height: 52px; |
| display: flex; |
| align-items: center; |
| justify-content: space-between; |
| } |
|
|
| .header-brand { |
| display: flex; |
| align-items: center; |
| gap: 10px; |
| font-weight: 600; |
| font-size: 15px; |
| color: var(--text); |
| } |
|
|
| .header-brand svg { |
| color: var(--blue); |
| } |
|
|
| .header-right { |
| display: flex; |
| align-items: center; |
| gap: 12px; |
| } |
|
|
| .status-dot { |
| width: 8px; |
| height: 8px; |
| border-radius: 50%; |
| display: inline-block; |
| } |
|
|
| .status-dot.online { |
| background: var(--green); |
| } |
|
|
| .status-dot.offline { |
| background: var(--red); |
| } |
|
|
| .btn-install { |
| font-family: var(--font); |
| font-size: 13px; |
| font-weight: 500; |
| color: var(--blue); |
| background: var(--blue-light); |
| border: 1px solid var(--blue-mid); |
| padding: 5px 12px; |
| border-radius: var(--radius); |
| cursor: pointer; |
| } |
|
|
| |
| .tab-nav { |
| background: var(--surface); |
| border-bottom: 1px solid var(--border); |
| display: flex; |
| gap: 0; |
| padding: 0 20px; |
| max-width: 100%; |
| overflow-x: auto; |
| } |
|
|
| .tab-btn { |
| font-family: var(--font); |
| font-size: 14px; |
| font-weight: 500; |
| color: var(--text-2); |
| background: none; |
| border: none; |
| border-bottom: 2px solid transparent; |
| padding: 12px 16px; |
| cursor: pointer; |
| white-space: nowrap; |
| transition: color 0.15s, border-color 0.15s; |
| } |
|
|
| .tab-btn:hover { |
| color: var(--text); |
| } |
|
|
| .tab-btn.active { |
| color: var(--blue); |
| border-bottom-color: var(--blue); |
| } |
|
|
| |
| .main { |
| max-width: 1100px; |
| margin: 0 auto; |
| padding: 24px 20px; |
| } |
|
|
| .tab-panel { |
| display: none; |
| } |
|
|
| .tab-panel.active { |
| display: block; |
| } |
|
|
| .two-col { |
| display: grid; |
| grid-template-columns: 1fr 1fr; |
| gap: 20px; |
| align-items: start; |
| } |
|
|
| @media (max-width: 768px) { |
| .two-col { |
| grid-template-columns: 1fr; |
| } |
| } |
|
|
| |
| .panel { |
| background: var(--surface); |
| border: 1px solid var(--border); |
| border-radius: var(--radius); |
| box-shadow: var(--shadow); |
| } |
|
|
| .panel-header { |
| padding: 16px 20px; |
| border-bottom: 1px solid var(--border); |
| } |
|
|
| .panel-header h2 { |
| font-size: 15px; |
| font-weight: 600; |
| } |
|
|
| .panel-desc { |
| color: var(--text-2); |
| font-size: 13px; |
| margin-top: 2px; |
| } |
|
|
| .panel-body { |
| padding: 20px; |
| display: flex; |
| flex-direction: column; |
| gap: 16px; |
| } |
|
|
| |
| .field { |
| display: flex; |
| flex-direction: column; |
| gap: 6px; |
| } |
|
|
| label { |
| font-size: 13px; |
| font-weight: 500; |
| color: var(--text-2); |
| } |
|
|
| .input, |
| .select { |
| font-family: var(--font); |
| font-size: 14px; |
| color: var(--text); |
| background: var(--surface); |
| border: 1px solid var(--border); |
| border-radius: var(--radius); |
| padding: 8px 12px; |
| outline: none; |
| transition: border-color 0.15s; |
| width: 100%; |
| } |
|
|
| .input:focus, |
| .select:focus { |
| border-color: var(--blue); |
| } |
|
|
| |
| .seg-control { |
| display: flex; |
| background: var(--bg); |
| border: 1px solid var(--border); |
| border-radius: var(--radius); |
| padding: 3px; |
| gap: 2px; |
| } |
|
|
| .seg-btn { |
| flex: 1; |
| font-family: var(--font); |
| font-size: 13px; |
| font-weight: 500; |
| color: var(--text-2); |
| background: transparent; |
| border: none; |
| padding: 6px 10px; |
| border-radius: 6px; |
| cursor: pointer; |
| transition: all 0.15s; |
| } |
|
|
| .seg-btn.active { |
| background: var(--surface); |
| color: var(--text); |
| box-shadow: var(--shadow); |
| } |
|
|
| |
| .dropzone { |
| border: 1px dashed var(--border); |
| border-radius: var(--radius); |
| padding: 20px; |
| display: flex; |
| flex-direction: column; |
| align-items: center; |
| gap: 8px; |
| cursor: pointer; |
| transition: border-color 0.15s, background 0.15s; |
| background: var(--bg); |
| text-align: center; |
| } |
|
|
| .dropzone:hover { |
| border-color: var(--blue); |
| background: var(--blue-light); |
| } |
|
|
| .dropzone svg { |
| color: var(--text-3); |
| } |
|
|
| .dropzone span { |
| font-size: 13px; |
| color: var(--text-2); |
| } |
|
|
| |
| .camera-step { |
| border: 1px solid var(--border); |
| border-radius: var(--radius); |
| padding: 14px; |
| display: flex; |
| flex-direction: column; |
| gap: 10px; |
| } |
|
|
| .camera-step.disabled { |
| opacity: 0.4; |
| pointer-events: none; |
| } |
|
|
| .step-label { |
| font-size: 12px; |
| font-weight: 600; |
| color: var(--text-2); |
| text-transform: uppercase; |
| letter-spacing: 0.5px; |
| } |
|
|
| .cam-view { |
| width: 100%; |
| min-height: 160px; |
| background: #000; |
| border-radius: 6px; |
| overflow: hidden; |
| } |
|
|
| .snap-preview { |
| width: 100%; |
| border-radius: 6px; |
| display: block; |
| } |
|
|
| .cam-actions { |
| display: flex; |
| gap: 8px; |
| } |
|
|
| |
| .btn { |
| display: inline-flex; |
| align-items: center; |
| justify-content: center; |
| gap: 6px; |
| font-family: var(--font); |
| font-size: 14px; |
| font-weight: 500; |
| border-radius: var(--radius); |
| padding: 8px 16px; |
| cursor: pointer; |
| border: none; |
| transition: all 0.15s; |
| } |
|
|
| .btn-primary { |
| background: var(--blue); |
| color: #fff; |
| } |
|
|
| .btn-primary:hover:not(:disabled) { |
| background: #1d4ed8; |
| } |
|
|
| .btn-primary:disabled { |
| opacity: 0.4; |
| cursor: not-allowed; |
| } |
|
|
| .btn-secondary { |
| background: var(--surface); |
| color: var(--text); |
| border: 1px solid var(--border); |
| } |
|
|
| .btn-secondary:hover:not(:disabled) { |
| background: var(--bg); |
| } |
|
|
| .btn-secondary:disabled { |
| opacity: 0.4; |
| cursor: not-allowed; |
| } |
|
|
| .btn-ghost { |
| background: transparent; |
| color: var(--text-2); |
| border: 1px solid var(--border); |
| } |
|
|
| .btn-ghost:hover { |
| background: var(--bg); |
| } |
|
|
| .btn-full { |
| width: 100%; |
| } |
|
|
| |
| .spinner { |
| width: 14px; |
| height: 14px; |
| border: 2px solid rgba(255, 255, 255, 0.3); |
| border-top-color: currentColor; |
| border-radius: 50%; |
| animation: spin 0.7s linear infinite; |
| display: inline-block; |
| } |
|
|
| @keyframes spin { |
| to { |
| transform: rotate(360deg); |
| } |
| } |
|
|
| |
| .empty-state { |
| display: flex; |
| flex-direction: column; |
| align-items: center; |
| gap: 12px; |
| padding: 48px 20px; |
| text-align: center; |
| color: var(--text-3); |
| } |
|
|
| .empty-state p { |
| font-size: 13px; |
| max-width: 260px; |
| } |
|
|
| |
| .result-banner { |
| display: flex; |
| align-items: center; |
| gap: 12px; |
| padding: 12px 16px; |
| border-radius: var(--radius); |
| margin-bottom: 16px; |
| border: 1px solid; |
| } |
|
|
| .result-banner.EXACT { |
| background: var(--green-light); |
| border-color: #bbf7d0; |
| } |
|
|
| .result-banner.CORRECTED { |
| background: var(--amber-light); |
| border-color: #fde68a; |
| } |
|
|
| .result-banner.FAILED { |
| background: var(--red-light); |
| border-color: #fecaca; |
| } |
|
|
| .banner-title { |
| font-size: 14px; |
| font-weight: 600; |
| } |
|
|
| .EXACT .banner-title { |
| color: var(--green); |
| } |
|
|
| .CORRECTED .banner-title { |
| color: var(--amber); |
| } |
|
|
| .FAILED .banner-title { |
| color: var(--red); |
| } |
|
|
| .banner-sub { |
| font-size: 12px; |
| color: var(--text-2); |
| margin-top: 1px; |
| } |
|
|
| |
| .result-table { |
| width: 100%; |
| border-collapse: collapse; |
| margin-bottom: 16px; |
| } |
|
|
| .result-table td { |
| padding: 8px 0; |
| border-bottom: 1px solid var(--border); |
| vertical-align: top; |
| } |
|
|
| .result-table tr:last-child td { |
| border-bottom: none; |
| } |
|
|
| .rt-label { |
| font-size: 12px; |
| font-weight: 500; |
| color: var(--text-2); |
| width: 40%; |
| padding-right: 12px; |
| } |
|
|
| .rt-value { |
| font-size: 14px; |
| } |
|
|
| .mono { |
| font-family: 'Courier New', monospace; |
| letter-spacing: 0.5px; |
| } |
|
|
| |
| .section-title { |
| font-size: 12px; |
| font-weight: 600; |
| color: var(--text-2); |
| text-transform: uppercase; |
| letter-spacing: 0.5px; |
| margin-bottom: 8px; |
| } |
|
|
| .pre-tabs { |
| display: flex; |
| gap: 4px; |
| overflow-x: auto; |
| margin-bottom: 10px; |
| } |
|
|
| .pre-tab { |
| font-family: var(--font); |
| font-size: 12px; |
| font-weight: 500; |
| color: var(--text-2); |
| background: var(--bg); |
| border: 1px solid var(--border); |
| padding: 4px 10px; |
| border-radius: 20px; |
| cursor: pointer; |
| white-space: nowrap; |
| transition: all 0.15s; |
| } |
|
|
| .pre-tab:hover { |
| color: var(--text); |
| } |
|
|
| .pre-tab.active { |
| background: var(--blue); |
| color: #fff; |
| border-color: var(--blue); |
| } |
|
|
| .pre-img-wrap { |
| border: 1px solid var(--border); |
| border-radius: var(--radius); |
| overflow: hidden; |
| background: #f3f4f6; |
| position: relative; |
| } |
|
|
| .pre-img-wrap img { |
| width: 100%; |
| display: block; |
| max-height: 240px; |
| object-fit: contain; |
| background: #000; |
| } |
|
|
| .pre-ocr-label { |
| padding: 8px 12px; |
| font-size: 12px; |
| color: var(--text-2); |
| border-top: 1px solid var(--border); |
| background: var(--surface); |
| } |
|
|
| |
| .progress-row { |
| display: flex; |
| justify-content: space-between; |
| font-size: 13px; |
| color: var(--text-2); |
| margin-bottom: 6px; |
| } |
|
|
| .progress-track { |
| height: 6px; |
| background: var(--bg); |
| border-radius: 3px; |
| border: 1px solid var(--border); |
| overflow: hidden; |
| } |
|
|
| .progress-fill { |
| height: 100%; |
| background: var(--blue); |
| border-radius: 3px; |
| transition: width 0.3s; |
| } |
|
|
| .stats-grid { |
| display: grid; |
| grid-template-columns: repeat(4, 1fr); |
| gap: 12px; |
| } |
|
|
| @media (max-width: 600px) { |
| .stats-grid { |
| grid-template-columns: 1fr 1fr; |
| } |
| } |
|
|
| .stat-card { |
| border: 1px solid var(--border); |
| border-radius: var(--radius); |
| padding: 16px; |
| text-align: center; |
| background: var(--bg); |
| } |
|
|
| .stat-value { |
| font-size: 22px; |
| font-weight: 700; |
| color: var(--text); |
| line-height: 1.2; |
| } |
|
|
| .stat-label { |
| font-size: 12px; |
| color: var(--text-2); |
| margin-top: 4px; |
| } |
|
|
| .table-toolbar { |
| margin-bottom: 12px; |
| } |
|
|
| .search-input { |
| max-width: 300px; |
| } |
|
|
| .table-scroll { |
| overflow-x: auto; |
| } |
|
|
| .data-table { |
| width: 100%; |
| border-collapse: collapse; |
| font-size: 13px; |
| } |
|
|
| .data-table th { |
| text-align: left; |
| padding: 8px 12px; |
| font-size: 12px; |
| font-weight: 600; |
| color: var(--text-2); |
| background: var(--bg); |
| border-bottom: 1px solid var(--border); |
| white-space: nowrap; |
| } |
|
|
| .data-table td { |
| padding: 10px 12px; |
| border-bottom: 1px solid var(--border); |
| vertical-align: middle; |
| } |
|
|
| .data-table tbody tr:hover { |
| background: var(--bg); |
| } |
|
|
| .data-table tbody tr:last-child td { |
| border-bottom: none; |
| } |
|
|
| .badge { |
| display: inline-block; |
| font-size: 11px; |
| font-weight: 600; |
| padding: 2px 8px; |
| border-radius: 20px; |
| letter-spacing: 0.2px; |
| } |
|
|
| .badge-exact { |
| background: var(--green-light); |
| color: var(--green); |
| } |
|
|
| .badge-corrected { |
| background: var(--amber-light); |
| color: var(--amber); |
| } |
|
|
| .badge-failed { |
| background: var(--red-light); |
| color: var(--red); |
| } |
|
|
| |
| .modal { |
| position: fixed; |
| inset: 0; |
| background: rgba(0, 0, 0, 0.5); |
| z-index: 500; |
| display: flex; |
| align-items: center; |
| justify-content: center; |
| padding: 20px; |
| } |
|
|
| .modal-box { |
| background: var(--surface); |
| border-radius: var(--radius); |
| box-shadow: var(--shadow-md); |
| width: 100%; |
| max-width: 860px; |
| overflow: hidden; |
| } |
|
|
| .modal-head { |
| display: flex; |
| justify-content: space-between; |
| align-items: center; |
| padding: 14px 20px; |
| border-bottom: 1px solid var(--border); |
| font-weight: 600; |
| font-size: 14px; |
| } |
|
|
| .modal-close-btn { |
| background: none; |
| border: none; |
| font-size: 20px; |
| color: var(--text-2); |
| cursor: pointer; |
| line-height: 1; |
| padding: 0 4px; |
| } |
|
|
| .modal-body { |
| padding: 20px; |
| max-height: 75vh; |
| overflow-y: auto; |
| } |
|
|
| |
| .toast-stack { |
| position: fixed; |
| bottom: 20px; |
| right: 20px; |
| display: flex; |
| flex-direction: column; |
| gap: 8px; |
| z-index: 1000; |
| } |
|
|
| .toast { |
| background: var(--surface); |
| border: 1px solid var(--border); |
| border-radius: var(--radius); |
| box-shadow: var(--shadow-md); |
| padding: 10px 16px; |
| font-size: 13px; |
| font-weight: 500; |
| max-width: 320px; |
| animation: slide-up 0.2s ease; |
| display: flex; |
| align-items: center; |
| gap: 8px; |
| } |
|
|
| .toast.success { |
| border-left: 3px solid var(--green); |
| } |
|
|
| .toast.error { |
| border-left: 3px solid var(--red); |
| } |
|
|
| .toast.info { |
| border-left: 3px solid var(--blue); |
| } |
|
|
| @keyframes slide-up { |
| from { |
| opacity: 0; |
| transform: translateY(8px); |
| } |
|
|
| to { |
| opacity: 1; |
| transform: translateY(0); |
| } |
| } |
|
|
| |
|
|
| .chassis-video-wrap { |
| position: relative; |
| display: inline-block; |
| width: 100%; |
| } |
|
|
| .guide-box { |
| position: absolute; |
| top: 50%; |
| left: 50%; |
| transform: translate(-50%, -50%); |
| width: 70%; |
| height: 22%; |
| border: 3px solid #2563eb; |
| border-radius: 8px; |
| box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.45); |
| pointer-events: none; |
| z-index: 2; |
| } |
|
|
| |
| .hidden { |
| display: none !important; |
| } |
|
|
| .hidden-input { |
| display: none; |
| } |