* { box-sizing: border-box; } :root { font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; color: #eef2f7; background: #0b0f15; color-scheme: dark; font-synthesis: none; } body { margin: 0; min-width: 720px; min-height: 100vh; background: radial-gradient(circle at 12% -10%, rgba(44, 113, 90, .18), transparent 30rem), #0b0f15; } button, input, select { font: inherit; } button { cursor: pointer; } button:disabled { cursor: wait; opacity: .48; } .shell { max-width: 1180px; margin: 0 auto; padding: 28px; } .topbar { display: flex; align-items: center; justify-content: space-between; gap: 18px; margin-bottom: 22px; } .brand { display: flex; align-items: center; gap: 13px; } .mark { width: 42px; height: 42px; border-radius: 12px; display: grid; place-items: center; background: #b9f3d5; color: #092016; font-weight: 900; letter-spacing: -.04em; box-shadow: 0 0 0 1px rgba(185, 243, 213, .18); } h1 { margin: 0; font-size: 21px; letter-spacing: -.025em; } h2 { margin: 2px 0 0; font-size: 15px; letter-spacing: -.01em; } .subtitle { margin: 3px 0 0; color: #8491a3; font-size: 12.5px; } .eyebrow { color: #667386; font-size: 9px; font-weight: 800; letter-spacing: .14em; } .status { display: inline-flex; align-items: center; gap: 8px; border: 1px solid #28313d; background: #111720; border-radius: 999px; padding: 8px 12px; font-size: 11px; font-weight: 700; color: #99a5b5; } .dot, .state-dot { width: 7px; height: 7px; border-radius: 50%; flex: 0 0 auto; background: #647083; } .status.live .dot, #virtual-printer-state.ready + .state-dot { background: #65d69a; } .status.live { border-color: #254b3b; color: #b9f3d5; background: #0f211a; } .status.error-state { color: #ffc7c7; border-color: #5d3131; background: #231414; } .status.error-state .dot { background: #ef7f7f; } .grid { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(330px, .85fr); gap: 16px; } .card { border: 1px solid #202833; border-radius: 16px; background: #10151d; overflow: hidden; box-shadow: 0 14px 38px rgba(0, 0, 0, .2); } .card-head { min-height: 64px; padding: 15px 18px; border-bottom: 1px solid #1e2630; display: flex; align-items: center; justify-content: space-between; gap: 12px; } .card-body { padding: 18px; } .jobs-card { grid-column: 1 / -1; } .field-label, label { display: grid; gap: 7px; color: #a4afbd; font-size: 11px; font-weight: 600; } label.full { grid-column: 1 / -1; } input, select { width: 100%; border: 1px solid #2a3441; border-radius: 9px; background: #0b1016; color: #edf2f7; padding: 10px 11px; outline: none; } select option { background: #0b1016; color: #edf2f7; } input:focus, select:focus { border-color: #4ca77b; box-shadow: 0 0 0 3px rgba(76, 167, 123, .12); } .help { color: #667386; font-size: 10.5px; font-weight: 400; line-height: 1.45; } .route-tiles { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; margin-top: 15px; } .route-tile { min-height: 62px; display: flex; align-items: center; gap: 10px; border: 1px solid #222c38; border-radius: 11px; padding: 10px; background: #0d131a; } .route-tile > div:last-child { display: grid; gap: 2px; } .route-tile strong { font-size: 11.5px; } .route-tile span { color: #667386; font-size: 10px; } .route-icon { width: 28px; height: 28px; border-radius: 8px; display: grid; place-items: center; flex: 0 0 auto; font-size: 10px; font-weight: 900; } .live-route { background: #143326; color: #8be4b4; } .test-route { background: #18273a; color: #9cc7f4; } .printer-state, .account-row, .update-box { margin-top: 12px; border: 1px solid #222c38; border-radius: 11px; background: #0d131a; } .printer-state { display: flex; align-items: flex-start; gap: 9px; padding: 11px; } .printer-state > div { display: grid; gap: 3px; } .printer-state strong, .account-row strong, .update-box strong { font-size: 11px; } #virtual-printer-state { color: #718094; font-size: 10.5px; line-height: 1.4; } #virtual-printer-state.ready { color: #82dca9; } .printer-state:has(#virtual-printer-state.ready) .state-dot { background: #65d69a; } .actions, .inline-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; } .printer-actions { margin-top: 12px; } .btn, .icon-btn { border: 1px solid #2b3643; border-radius: 9px; background: #151d27; color: #dce4ed; font-size: 11px; font-weight: 700; } .btn { padding: 9px 12px; } .icon-btn { width: 32px; height: 32px; padding: 0; } .btn:hover, .icon-btn:hover { background: #1a2430; } .btn.primary { background: #b9f3d5; border-color: #b9f3d5; color: #092016; } .btn.blue { background: #173552; border-color: #24577f; color: #d2e9ff; } .btn.ghost { background: transparent; } .btn.danger { color: #e99b9b; } .fields { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; } .advanced { margin-top: 14px; border-top: 1px solid #1e2630; padding-top: 12px; } .advanced summary { cursor: pointer; color: #7d8999; font-size: 10.5px; font-weight: 700; user-select: none; } .advanced-body { padding-top: 13px; } .compact-actions { margin-top: 12px; } .metrics { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; } .metric { border: 1px solid #222c38; border-radius: 11px; padding: 12px; background: #0d131a; } .metric b { display: block; margin-bottom: 3px; font-size: 21px; letter-spacing: -.04em; } .metric span { color: #667386; font-size: 9px; font-weight: 800; text-transform: uppercase; letter-spacing: .1em; } .account-row { min-height: 60px; padding: 11px; display: flex; align-items: center; justify-content: space-between; gap: 12px; } .account-row > div:first-child { display: grid; gap: 3px; } .login-code { color: #b9f3d5; font: 700 16px ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: .08em; } .muted { color: #667386; font-size: 10.5px; } .small { font-size: 10px; } .update-box { padding: 11px; display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 10px; } .update-box > div:first-child { display: grid; gap: 2px; } .update-box small { line-height: 1.35; } .update-progress { grid-column: 1 / -1; height: 4px; overflow: hidden; border-radius: 999px; background: #1a2430; } .update-progress span { display: block; width: 0; height: 100%; border-radius: inherit; background: #65d69a; transition: width .16s ease; } .jobs { display: grid; gap: 8px; max-height: 420px; overflow: auto; } .job { display: grid; grid-template-columns: minmax(0, 1fr) minmax(140px, 260px); gap: 14px; border: 1px solid #202a36; border-radius: 11px; padding: 12px; background: #0c1117; } .job-main { min-width: 0; } .job-title-row { display: flex; align-items: center; gap: 7px; } .job-title-row time { margin-left: auto; color: #596679; font-size: 10px; } .source-badge, .route-badge { display: inline-flex; align-items: center; min-height: 22px; border-radius: 999px; padding: 0 8px; font-size: 9px; font-weight: 800; } .source-badge { background: #17202b; color: #a9b5c5; } .route-badge.success { background: #123225; color: #8ce1b1; } .route-badge.test { background: #172c43; color: #9fcef5; } .route-badge.neutral { background: #2a2519; color: #e3c47d; } .pallet-badge { display: inline-flex; align-items: center; min-height: 22px; border-radius: 999px; padding: 0 8px; font-size: 9px; font-weight: 800; } .pallet-badge.new-pallet { background: #123225; color: #8ce1b1; } .pallet-badge.reprint-same { background: #2a2519; color: #e3c47d; } .pallet-badge.reprint-changed { background: #411d1d; color: #ffb0b0; } .pallet-badge.reprint-unreadable { background: #242a33; color: #b6c0cc; } .pallet-print-detail { display: flex; gap: 10px; margin: -2px 0 7px; color: #667386; font-size: 9.5px; } .pallet-diff { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 8px; } .pallet-diff span { border: 1px solid #573232; border-radius: 7px; padding: 5px 7px; background: #241313; color: #ffc1c1; font: 10px ui-monospace, SFMono-Regular, Menlo, monospace; } .pallet-diff strong { color: #f5d8d8; font-family: Inter, ui-sans-serif, system-ui, sans-serif; } .job-result { display: block; margin: 9px 0 7px; font-size: 12px; font-weight: 700; } .codes { display: flex; flex-wrap: wrap; gap: 6px; } .code { display: grid; gap: 2px; font: 11px ui-monospace, SFMono-Regular, Menlo, monospace; background: #102b20; border: 1px solid #214b39; color: #bff0d3; border-radius: 7px; padding: 6px 8px; } .code small { color: #68a984; font-size: 8px; font-weight: 800; } .job-meta { min-width: 0; display: flex; align-items: flex-end; justify-content: flex-end; gap: 8px; color: #596679; font-size: 9.5px; text-align: right; } .job-meta span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 180px; } .job-error { margin-top: 7px; color: #f0a0a0; font-size: 10px; } .empty-state { min-height: 150px; display: grid; place-items: center; align-content: center; gap: 5px; color: #667386; text-align: center; } .empty-state strong { color: #a9b5c5; font-size: 12px; } .empty-state span { font-size: 10.5px; } .empty-icon { width: 32px; height: 32px; display: grid; place-items: center; border: 1px solid #26313e; border-radius: 50%; margin-bottom: 3px; } @media (max-width: 860px) { body { min-width: 0; } .shell { padding: 18px; } .topbar { align-items: flex-start; } .grid { grid-template-columns: 1fr; } .jobs-card { grid-column: auto; } .fields, .route-tiles { grid-template-columns: 1fr; } label.full { grid-column: auto; } .job { grid-template-columns: 1fr; } .job-meta { justify-content: flex-start; text-align: left; } } #self-test { color: #9fcef5; border-color: #294865; } .topbar-actions { display: flex; align-items: center; gap: 12px; } .view-tabs { display: inline-flex; gap: 4px; padding: 4px; border: 1px solid #202a36; border-radius: 10px; background: #0d131a; } .view-tab { border: 0; border-radius: 7px; padding: 7px 10px; background: transparent; color: #718094; font-size: 10.5px; font-weight: 800; } .view-tab:hover { color: #dce4ed; background: #151d27; } .view-tab.active { background: #1a2b24; color: #b9f3d5; } .app-view[hidden] { display: none; } .settings-card .settings-account { margin-top: 0; } .running-grid { display: grid; gap: 16px; } .running-summary-card .card-body { display: grid; gap: 14px; } .running-route { display: flex; align-items: center; justify-content: space-between; gap: 18px; border: 1px solid #222c38; border-radius: 11px; padding: 12px; background: #0d131a; } .running-route > div:first-child { min-width: 0; display: grid; gap: 4px; } .running-route strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; } .running-action-state { min-height: 14px; } @media (max-width: 860px) { .topbar-actions { width: 100%; justify-content: space-between; } .topbar { flex-wrap: wrap; } .running-route { align-items: flex-start; flex-direction: column; } } .debug-panel { margin-top: 12px; border: 1px solid #5b4720; border-radius: 11px; background: #151109; overflow: hidden; } .debug-panel[hidden] { display: none; } .debug-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 11px 12px; border-bottom: 1px solid #3a2d16; } .debug-head > div:first-child { display: grid; gap: 3px; } .debug-head .eyebrow { color: #e3ad4f; } .debug-output { margin: 0; padding: 12px; max-height: 340px; overflow: auto; white-space: pre-wrap; overflow-wrap: anywhere; color: #d8dee7; background: #0b0e12; font: 11px/1.55 ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace; } #debug-action-state { display: block; min-height: 14px; padding: 0 12px 10px; } /* OCR refinement workbench */ .ocr-workbench { display: grid; gap: 16px; } .ocr-toolbar-card { overflow: visible; } .ocr-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 14px 16px 10px; } .ocr-profile-title { min-width: 240px; display: grid; gap: 5px; } .ocr-profile-row { display: flex; align-items: center; gap: 8px; } .ocr-profile-row input { min-width: 0; padding: 6px 8px; border: 0; background: transparent; font-size: 16px; font-weight: 800; } .profile-version { flex: 0 0 auto; border: 1px solid #2a3441; border-radius: 999px; padding: 4px 7px; color: #7f8b9c; font-size: 9px; font-weight: 800; } .ocr-document-meta { display: flex; align-items: center; gap: 14px; min-height: 40px; padding: 8px 16px; border-top: 1px solid #1e2630; color: #768497; font-size: 10px; } .ocr-document-meta > span:first-child { min-width: 140px; max-width: 260px; overflow: hidden; color: #c4ccd7; text-overflow: ellipsis; white-space: nowrap; } .ocr-document-meta label { display: flex; grid: none; align-items: center; gap: 6px; color: #758295; font-size: 9px; } .ocr-document-meta input[type="range"] { width: 110px; padding: 0; } .ocr-document-meta select { width: auto; padding: 5px 7px; } #ocr-status { margin-left: auto; text-align: right; } .ocr-layout { display: grid; grid-template-columns: 190px minmax(360px, 1fr) 280px; gap: 12px; min-height: 620px; } .ocr-regions-card, .ocr-preview-card, .ocr-settings-card { min-width: 0; } .ocr-region-sidebar { display: grid; align-content: start; gap: 12px; padding: 12px; } .ocr-add-region { display: grid; gap: 6px; } .ocr-add-region .btn { width: 100%; text-align: left; } .ocr-region-list { display: grid; gap: 5px; } .ocr-region-list-empty, .ocr-region-help, .ocr-no-selection { color: #667386; font-size: 10px; line-height: 1.45; } .ocr-region-help { padding-top: 8px; border-top: 1px solid #202833; } .ocr-region-item { width: 100%; display: grid; grid-template-columns: 9px minmax(0, 1fr) auto; align-items: center; gap: 8px; border: 1px solid #202833; border-radius: 8px; padding: 8px; background: #0c1117; color: #cfd7e1; text-align: left; } .ocr-region-item.active { border-color: #4ca77b; background: #102019; } .ocr-region-item > span:nth-child(2) { min-width: 0; display: grid; gap: 2px; } .ocr-region-item strong, .ocr-region-item small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .ocr-region-item strong { font-size: 10px; } .ocr-region-item small { color: #667386; font-size: 8px; } .region-kind { width: 7px; height: 7px; border-radius: 50%; } .region-kind.type-ocr { background: #65d69a; } .region-kind.type-barcode { background: #77aef2; } .region-kind.type-ignore { background: #b47d7d; } .region-result-ok { color: #79d9a4; font-size: 8px; font-weight: 800; } .ocr-preview-card { display: grid; grid-template-rows: auto 1fr; } .ocr-preview-scroll { position: relative; min-height: 540px; overflow: auto; padding: 22px; background: linear-gradient(45deg, #0c1117 25%, transparent 25%) 0 0/20px 20px, linear-gradient(-45deg, #0c1117 25%, transparent 25%) 0 10px/20px 20px, linear-gradient(45deg, transparent 75%, #0c1117 75%) 10px -10px/20px 20px, linear-gradient(-45deg, transparent 75%, #0c1117 75%) -10px 0/20px 20px, #0f151d; } .ocr-preview-empty[hidden], .ocr-page-frame[hidden] { display: none !important; } .ocr-preview-empty { min-height: 480px; display: grid; place-items: center; align-content: center; gap: 7px; color: #647083; text-align: center; } .ocr-preview-empty strong { color: #aeb8c6; font-size: 13px; } .ocr-preview-empty span { max-width: 360px; font-size: 10.5px; line-height: 1.5; } .ocr-page-frame { position: relative; margin: 0 auto; background: #fff; box-shadow: 0 18px 50px rgba(0,0,0,.45); } #ocr-document-canvas { position: absolute; inset: 0; display: block; background: white; } .ocr-overlay { position: absolute; inset: 0; touch-action: none; cursor: crosshair; } .ocr-overlay.drawing { cursor: crosshair; } .ocr-region-box { position: absolute; border: 2px solid #65d69a; background: rgba(73, 190, 127, .08); cursor: move; user-select: none; } .ocr-region-box.type-barcode { border-color: #77aef2; background: rgba(87, 141, 218, .08); } .ocr-region-box.type-ignore { border-color: #c17c7c; background: rgba(180, 85, 85, .08); } .ocr-region-box.selected { border-width: 3px; box-shadow: 0 0 0 1px rgba(255,255,255,.72); } .ocr-region-box > span { position: absolute; top: -21px; left: -2px; max-width: 180px; overflow: hidden; border-radius: 4px 4px 0 0; padding: 3px 6px; background: #17271f; color: #baf0d1; font-size: 8px; font-weight: 800; text-overflow: ellipsis; white-space: nowrap; } .ocr-region-box.type-barcode > span { background: #17263a; color: #b7d8fa; } .ocr-region-box.type-ignore > span { background: #341c1c; color: #efbbbb; } .ocr-resize-handle { position: absolute; right: -6px; bottom: -6px; width: 12px; height: 12px; border: 2px solid #0d1218; border-radius: 3px; background: currentColor; cursor: nwse-resize; } .ocr-settings-body { padding: 12px; } .ocr-setting-grid { display: grid; grid-template-columns: 1fr 92px; gap: 9px; } .ocr-setting-grid .full { grid-column: 1 / -1; } .ocr-setting-section { display: grid; gap: 10px; margin-top: 12px; padding-top: 12px; border-top: 1px solid #202833; } .ocr-setting-section label { font-size: 9.5px; } .ocr-check { display: flex !important; align-items: center; grid-template-columns: none !important; gap: 7px !important; } .ocr-check input { width: auto; } .ocr-setting-section input[type="range"] { padding: 0; } .ocr-coordinates { margin: 11px 0; color: #667386; font: 9px ui-monospace, SFMono-Regular, Menlo, monospace; } .ocr-crop-panel, .ocr-output-panel { margin-top: 12px; overflow: hidden; border: 1px solid #202833; border-radius: 9px; background: #0a0f15; } .ocr-crop-head { min-height: 32px; display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 7px 9px; border-bottom: 1px solid #202833; font-size: 9px; } #ocr-region-preview { display: block; width: 100%; max-height: 210px; object-fit: contain; background: white; } #ocr-raw-output { margin: 0; min-height: 80px; max-height: 180px; overflow: auto; padding: 9px; color: #cbd4df; white-space: pre-wrap; overflow-wrap: anywhere; font: 9px/1.45 ui-monospace, SFMono-Regular, Menlo, monospace; } @media (max-width: 1040px) { .ocr-layout { grid-template-columns: 160px minmax(340px, 1fr); } .ocr-settings-card { grid-column: 1 / -1; } .ocr-settings-body { max-width: 720px; } } @media (max-width: 760px) { .ocr-toolbar { align-items: stretch; flex-direction: column; } .ocr-document-meta { align-items: flex-start; flex-wrap: wrap; } #ocr-status { width: 100%; margin-left: 0; text-align: left; } .ocr-layout { grid-template-columns: 1fr; } .ocr-settings-card { grid-column: auto; } .ocr-preview-scroll { min-height: 420px; } }