/* Shared styles - ported from the invoiceProject ASP pages (highlight #6699CC). */ * { box-sizing: border-box; margin: 0; padding: 0; } body { background: #333; color: #eee; font-family: Arial, sans-serif; font-size: 13px; } h1 { display: flex; align-items: center; background: #444; color: #6699CC; padding: 8px 16px; font-size: 16px; border-bottom: 1px solid #555; } h1 a { color: #aaa; font-size: 12px; font-weight: normal; margin-left: 16px; text-decoration: none; } h1 a:hover { color: #eee; } h1 a.active { color: #eee; box-shadow: inset 0 -2px 0 #6699CC; padding-bottom: 2px; } #pageMode { margin-left: 6px; } #btnTogglePreview, #btnViewParsed, .nav-draft { display: none; background: #555; color: #eee; border: 1px solid #666; border-radius: 3px; padding: 3px 10px; font-size: 11px; cursor: pointer; } #btnPrevDraft { margin-left: auto; } #btnViewParsed { margin-left: 14px; } #btnTogglePreview { margin-left: 6px; } #btnTogglePreview:hover, #btnViewParsed:hover, .nav-draft:hover:not(:disabled) { border-color: #6699CC; color: #6699CC; } .nav-draft:disabled { color: #777; cursor: default; } .draft-pos { color: #999; font-size: 11px; font-weight: normal; margin: 0 6px; } body.review-page #btnTogglePreview, body.review-page #btnViewParsed, body.review-page .nav-draft { display: inline-block; } /* The review screen owns the whole viewport: nothing outside the preview and the line-item table scrolls, so the form never needs a browser zoom-out. */ body.review-page { height: 100vh; overflow: hidden; display: flex; flex-direction: column; } body.review-page h1 { flex-shrink: 0; } /* Two-column layout */ #layout { display: none; gap: 0; padding: 10px; flex: 1; min-height: 0; } #leftPanel { flex: 0 0 38%; min-width: 0; display: flex; flex-direction: column; gap: 8px; } #leftPanel.collapsed, #leftPanel.collapsed + #splitter { display: none; } #rightPanel { flex: 1; min-width: 0; display: flex; flex-direction: column; overflow: hidden; } /* Drag handle between the preview and the form */ #splitter { flex: 0 0 8px; cursor: col-resize; background: transparent; border-radius: 3px; position: relative; } #splitter::after { content: ""; position: absolute; top: 0; bottom: 0; left: 3px; width: 2px; background: #4a4a4a; border-radius: 2px; } #splitter:hover::after, #splitter.dragging::after { background: #6699CC; } #canvasWrapper { flex: 1; overflow: auto; background: #222; border-radius: 4px; padding: 8px; } #previewToolbar { flex: 0 0 auto; display: flex; align-items: center; gap: 6px; } #previewToolbar button { background: #555; color: #eee; border: 1px solid #666; border-radius: 3px; padding: 2px 9px; font-size: 12px; line-height: 1.4; cursor: pointer; } #previewToolbar button:hover { border-color: #6699CC; color: #6699CC; } #zoomLevel { color: #bbb; font-size: 11px; min-width: 40px; text-align: center; } /* One wrapper per rendered page. app.js sets its width for the zoom level; the image fills it, so percentage-positioned line markers stay aligned. */ .page-wrap { position: relative; width: 100%; } .page-wrap + .page-wrap { margin-top: 8px; } .page-wrap img { display: block; width: 100%; height: auto; border-radius: 2px; } .line-marker { position: absolute; left: 0; width: 16px; min-height: 3px; /* Solid edge bar plus a see-through fill: the marker sits over the left margin, where the UPC usually is, so the text must stay readable. */ box-sizing: border-box; border-left: 4px solid rgba(220, 40, 40, 0.9); background: rgba(220, 40, 40, 0.15); border-radius: 0 2px 2px 0; cursor: pointer; z-index: 5; } .line-marker:hover { border-left-color: #ff3030; background: rgba(255, 48, 48, 0.2); width: 26px; } /* The line last jumped to, from either direction. */ .line-marker.active { border-left-color: #ffcc44; background: rgba(255, 204, 68, 0.25); width: 30px; box-shadow: 0 0 0 1px rgba(255, 204, 68, 0.8); } .line-marker:hover::after { content: attr(data-tip); position: absolute; left: 30px; top: -4px; background: #111; color: #eee; border: 1px solid #555; border-radius: 4px; padding: 3px 8px; font-size: 11px; white-space: nowrap; pointer-events: none; z-index: 10; } #lineItemsBody tr.has-source { cursor: pointer; } #lineItemsBody tr.has-source input, #lineItemsBody tr.has-source textarea, #lineItemsBody tr.has-source select, #lineItemsBody tr.has-source button { cursor: auto; } #lineItemsBody tr.has-source button, #lineItemsBody tr.has-source .cand-item { cursor: pointer; } #lineItemsBody tr.row-flash td { animation: rowFlash 1.6s ease-out; } @keyframes rowFlash { 0% { background-color: rgba(220, 40, 40, 0.5); } 100% { background-color: transparent; } } #statusBar { display: none; flex: 0 0 auto; padding: 7px 12px; border-radius: 4px; font-size: 12px; margin-bottom: 8px; } .status-loading { background: #4a4a00; color: #ffee88; } .status-error { background: #4a0000; color: #ff9999; } .status-success { background: #004a00; color: #99ff99; } /* Shown with display:flex by app.js - it is a full-height column so the header and the action bar stay put and only the item table scrolls. */ #reviewSection { display: none; flex-direction: column; flex: 1; min-height: 0; gap: 8px; } .form-section { background: #3a3a3a; border-radius: 6px; padding: 10px 12px; } .form-section h2 { display: flex; align-items: center; font-size: 13px; color: #6699CC; margin-bottom: 8px; padding-bottom: 5px; border-bottom: 1px solid #555; } .header-section, .actions-section { flex: 0 0 auto; } .items-section { flex: 1; min-height: 0; display: flex; flex-direction: column; } .table-scroll { flex: 1; min-height: 0; overflow: auto; } .actions-section { display: flex; align-items: center; gap: 10px; } .actions-right { margin-left: auto; display: flex; gap: 8px; } /* Header fields wrap across the panel width instead of stacking, which keeps the vertical space for the line items. */ .hdr-grid { display: flex; flex-wrap: wrap; gap: 6px 14px; } .hdr-field { display: flex; flex-direction: column; gap: 2px; } .hdr-field > label { color: #bbb; font-size: 10px; text-transform: uppercase; letter-spacing: 0.5px; } .hdr-ctl { display: flex; align-items: center; gap: 6px; } .hdr-field input, .hdr-field select { background: #2a2a2a; border: 1px solid #555; color: #eee; padding: 4px 7px; border-radius: 3px; font-size: 13px; } .hdr-field input:focus, .hdr-field select:focus { outline: none; border-color: #6699CC; } .field-row { display: flex; align-items: center; margin-bottom: 7px; gap: 8px; } .field-row label { width: 110px; text-align: right; color: #bbb; flex-shrink: 0; } .field-row input, .field-row select { background: #2a2a2a; border: 1px solid #555; color: #eee; padding: 4px 7px; border-radius: 3px; font-size: 13px; } .field-row input:focus, .field-row select:focus { outline: none; border-color: #6699CC; } .field-note { color: #888; font-size: 11px; } .parsed-hint { color: #777; font-size: 10px; font-style: italic; } .match-badge { display: inline-block; padding: 2px 7px; border-radius: 10px; font-size: 11px; font-weight: bold; } .badge-exact { background: #1a4a1a; color: #88ff88; } .badge-fuzzy { background: #4a3a00; color: #ffcc44; } .badge-none { background: #4a1a1a; color: #ff8888; } .warn-badge { display: inline-block; margin-left: 5px; padding: 2px 6px; background: #4a0000; color: #ff6666; border-radius: 3px; font-size: 10px; } #lineItemsTable { width: 100%; min-width: 1078px; /* below this the table-scroll wrapper scrolls sideways */ table-layout: fixed; border-collapse: collapse; font-size: 11.5px; } /* Fixed layout: these widths drive the columns, Description takes the rest. */ #lineItemsTable col.c-upc { width: 92px; } #lineItemsTable col.c-cert { width: 72px; } #lineItemsTable col.c-po { width: 38px; } #lineItemsTable col.c-pocost { width: 46px; } #lineItemsTable col.c-qty { width: 44px; } #lineItemsTable col.c-cost { width: 64px; } #lineItemsTable col.c-pack { width: 44px; } #lineItemsTable col.c-unitcost { width: 60px; } #lineItemsTable col.c-retail { width: 52px; } #lineItemsTable col.c-gm { width: 50px; } #lineItemsTable col.c-total { width: 74px; } #lineItemsTable col.c-size { width: 42px; } #lineItemsTable col.c-uom { width: 36px; } #lineItemsTable col.c-match { width: 138px; } #lineItemsTable col.c-del { width: 24px; } #lineItemsTable th { background: #444; color: #6699CC; padding: 4px 5px; text-align: left; border-bottom: 1px solid #555; white-space: nowrap; position: sticky; top: 0; z-index: 3; } #lineItemsTable td { padding: 3px 4px; border-bottom: 1px solid #444; vertical-align: top; } #lineItemsTable tr:hover td { background: #3f3f3f; } #lineItemsTable input { background: #2a2a2a; border: 1px solid #555; color: #eee; padding: 2px 4px; border-radius: 2px; font-size: 11.5px; width: 100%; } #lineItemsTable input:focus { outline: none; border-color: #6699CC; } #lineItemsBody tr.row-added td { background: rgba(102, 153, 204, 0.08); } #lineItemsTable textarea.item-desc { background: #2a2a2a; border: 1px solid #555; color: #eee; padding: 2px 4px; border-radius: 2px; font-size: 11.5px; width: 100%; min-height: 30px; resize: vertical; font-family: Arial, sans-serif; } #lineItemsTable textarea.item-desc:focus { outline: none; border-color: #6699CC; } /* Fixed, not absolute: the table scroller would otherwise clip the dropdown. app.js positions it against the search box it belongs to. */ .search-results { display: none; position: fixed; background: #2a2a2a; border: 1px solid #6699CC; border-radius: 3px; z-index: 400; max-height: 260px; overflow-y: auto; overscroll-behavior: contain; /* do not chain into the table and close itself */ width: 380px; } .search-result-item { padding: 6px 8px; cursor: pointer; font-size: 11px; border-bottom: 1px solid #3a3a3a; } .search-result-item:hover { background: #3a3a3a; } .search-result-item:hover .search-result-desc { color: #6699CC; } .search-result-desc { color: #eee; } .search-result-meta { color: #777; font-size: 10px; } .search-result-empty { padding: 5px 8px; color: #888; font-size: 11px; } #lineItemsTable td:last-child, #lineItemsTable td:nth-last-child(2) { position: relative; } .cand-list { margin-top: 3px; } .cand-item { color: #aaa; font-size: 10px; cursor: pointer; padding: 1px 4px; border: 1px solid #444; border-radius: 3px; margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .cand-item:hover { border-color: #6699CC; color: #6699CC; } .cand-meta { color: #666; } /* Always available, on every row - the suggested match is not always right. */ .search-toggle { display: inline-block; margin-top: 3px; background: transparent; border: 1px solid #666; color: #bbb; border-radius: 3px; padding: 1px 7px; font-size: 10px; cursor: pointer; } .search-toggle:hover { border-color: #6699CC; color: #6699CC; } /* Sits under "Change product": nothing in the file fits, so make one. */ .btn-new-item { display: inline-block; margin-top: 3px; background: transparent; border: 1px solid #4c7a4c; color: #8fce8f; border-radius: 3px; padding: 1px 7px; font-size: 10px; cursor: pointer; } .btn-new-item:hover { border-color: #88ff88; color: #88ff88; } .search-inline-wrap { margin-top: 3px; } .search-inline-wrap .product-search { width: 100%; } .btn-search-cancel { background: transparent; border: none; color: #777; font-size: 10px; cursor: pointer; padding: 2px 0 0; } .btn-search-cancel:hover { color: #6699CC; } #btnSave, #btnScan { background: #6699CC; color: #111; border: none; padding: 7px 18px; border-radius: 4px; font-size: 12px; font-weight: bold; cursor: pointer; } #btnSave:hover, #btnScan:hover { opacity: 0.85; } #btnSave:disabled { opacity: 0.5; cursor: default; } /* Secondary draft actions: kept small and away from Save. */ .btn-quiet { background: transparent; border: 1px solid #555; color: #aaa; padding: 3px 9px; border-radius: 3px; font-size: 11px; cursor: pointer; } .btn-quiet:hover { border-color: #6699CC; color: #6699CC; } .btn-quiet-danger:hover { border-color: #884444; color: #ff8888; } .autosave-error { color: #ff9999; } /* ---------- parsed data viewer ---------- */ #parsedModal { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 550; background: rgba(0,0,0,0.75); } #parsedModal .parsed-box { position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%); background: #3a3a3a; border: 1px solid #555; border-radius: 8px; padding: 16px 18px; width: min(860px, 92vw); height: min(700px, 88vh); display: flex; flex-direction: column; } #parsedModal h2 { display: flex; align-items: center; font-size: 14px; color: #6699CC; margin-bottom: 10px; padding-bottom: 8px; border-bottom: 1px solid #555; } #btnCloseParsed { margin-left: auto; background: #555; color: #eee; border: 1px solid #666; border-radius: 3px; padding: 3px 12px; font-size: 11px; cursor: pointer; } #btnCloseParsed:hover { border-color: #6699CC; color: #6699CC; } .parsed-tabs { display: flex; gap: 6px; margin-bottom: 8px; } .parsed-tab { background: transparent; border: 1px solid #555; color: #aaa; border-radius: 3px; padding: 4px 12px; font-size: 11px; cursor: pointer; } .parsed-tab:hover { color: #eee; } .parsed-tab.active { border-color: #6699CC; color: #6699CC; background: #333; } .parsed-pane { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 6px; } .parsed-pane .field-note { flex: 0 0 auto; } #ocrText { flex: 1; width: 100%; background: #2a2a2a; color: #eee; border: 1px solid #555; padding: 8px; border-radius: 3px; font-size: 11px; font-family: monospace; resize: none; } #ocrText:focus { outline: none; border-color: #6699CC; } #ocrMethod { color: #888; font-size: 11px; font-weight: normal; margin-left: 8px; } .diff-only { margin-left: 14px; color: #aaa; font-size: 11px; font-weight: normal; cursor: pointer; display: flex; align-items: center; gap: 4px; } .diff-only input { cursor: pointer; } #compareScroll { flex: 1; overflow: auto; background: #2a2a2a; border: 1px solid #555; border-radius: 3px; padding: 8px; } #compareHeader, #compareTable { width: 100%; border-collapse: collapse; font-size: 11.5px; } #compareHeader { margin-bottom: 14px; } #compareHeader th, #compareTable th { background: #444; color: #6699CC; padding: 4px 6px; text-align: left; border-bottom: 1px solid #555; position: sticky; top: -8px; z-index: 2; } #compareHeader td, #compareTable td { padding: 4px 6px; border-bottom: 1px solid #3a3a3a; vertical-align: top; color: #ccc; } #compareHeader th:first-child, #compareTable th:first-child { width: 110px; } #compareTable th:first-child { width: 34px; } #compareTable th:last-child { width: 96px; } #compareBody tr { cursor: pointer; } #compareBody tr:hover td { background: #3a3a3a; } .cmp-desc { color: #eee; } .cmp-meta { color: #777; font-size: 10px; margin-top: 2px; } .cmp-diff { color: #ffcc44; font-weight: bold; } .cmp-empty { color: #666; font-style: italic; } #compareBody tr.has-diff td:first-child { border-left: 3px solid #d0a84c; } .cmp-none { color: #888; padding: 14px; text-align: center; } .btn-confirm { margin-top: 4px; background: #4a3a00; color: #ffcc44; border: 1px solid #776600; padding: 2px 8px; border-radius: 3px; font-size: 10px; cursor: pointer; } .btn-confirm:hover { background: #665200; } .btn-remove-row { background: transparent; border: 1px solid #553333; color: #cc5555; width: 22px; height: 22px; border-radius: 3px; cursor: pointer; font-size: 13px; line-height: 1; padding: 0; } .btn-remove-row:hover { background: #4a1a1a; color: #ff8888; border-color: #884444; } .read-only-field { display: inline-block; padding: 4px 7px; color: #ccc; font-size: 13px; } .ro-val { display: inline-block; color: #ccc; font-size: 12px; padding: 2px 0; min-width: 20px; } .desc-toggle-row { margin-top: 3px; display: flex; align-items: center; gap: 4px; } .btn-desc-src { background: transparent; border: 1px solid #555; color: #888; padding: 1px 7px; border-radius: 2px; font-size: 10px; cursor: pointer; } .btn-desc-src:hover:not(:disabled) { color: #eee; } .btn-desc-src.active { border-color: #6699CC; color: #6699CC; background: #333; } .btn-desc-src:disabled { color: #4d4d4d; border-color: #444; cursor: default; } .upc-matched { font-size: 12px; color: #eee; } .upc-parsed-val { font-size: 10px; color: #666; font-style: italic; margin-top: 2px; } #lineItemsTable tr.po-diff td, #lineItemsTable tr.po-inv-only td { background: rgba(255,204,68,0.06); } #lineItemsTable tr.po-match td { background: rgba(80,180,100,0.035); } .po-value { color: #ccc; font-size: 12px; white-space: nowrap; } .po-cell-diff { color: #ffcc44; font-weight: bold; } .cmp-na { color: #555; } .po-note { display: inline-block; margin-left: 5px; padding: 2px 6px; background: #4a3a00; color: #ffcc44; border-radius: 3px; font-size: 10px; font-weight: bold; } .po-summary { color: #888; font-size: 11px; font-weight: normal; margin-left: 8px; } .h2-actions { margin-left: auto; display: flex; gap: 6px; } #btnAcceptAll, #btnAddLine { background: #555; color: #eee; border: 1px solid #666; padding: 4px 10px; border-radius: 3px; font-size: 11px; font-weight: bold; cursor: pointer; } #btnAddLine { background: #2a3a35; border-color: #336655; color: #88ffcc; } #btnAcceptAll:hover, #btnAddLine:hover { border-color: #6699CC; color: #6699CC; } .search-result-new { padding: 5px 8px; cursor: pointer; font-size: 11px; color: #6699CC; border-top: 1px solid #3a3a3a; } .search-result-new:hover { background: #3a3a3a; } /* ---------- Landing dashboard ---------- */ #dashboard { display: none; max-width: 980px; margin: 0 auto; padding: 26px 16px 40px; } .dash-welcome { color: #ddd; font-size: 22px; font-weight: normal; margin: 0 0 16px; } .dash-hero { background: linear-gradient(160deg, #3d3d3d, #353535); border: 1px solid #555; border-radius: 10px; padding: 30px; margin-bottom: 22px; } .dash-hero #uploadZone { border: 2px dashed #6a6a6a; border-radius: 8px; padding: 40px 24px; text-align: center; cursor: pointer; background: #333; transition: border-color 0.2s, background 0.2s; } .dash-hero #uploadZone:hover, .dash-hero #uploadZone.drag-over { border-color: #6699CC; background: #3a3a3a; } .dash-hero #uploadZone .up-icon { font-size: 40px; display: block; margin-bottom: 10px; } .dash-hero #uploadZone label { cursor: pointer; color: #6699CC; font-size: 20px; font-weight: bold; } .dash-hero #uploadPrompt { color: #aaa; margin-top: 10px; font-size: 13px; } .dash-hero #statusBar { margin-top: 14px; } #uploadZone input[type=file] { display: none; } .dash-actions { display: flex; gap: 10px; margin-bottom: 22px; flex-wrap: wrap; } .dash-btn { background: #444; color: #eee; border: 1px solid #666; border-radius: 5px; padding: 9px 18px; font-size: 13px; font-weight: bold; cursor: pointer; text-decoration: none; display: inline-block; } .dash-btn:hover { border-color: #6699CC; color: #6699CC; } .dash-btn.primary { background: #6699CC; color: #111; border-color: #6699CC; } .dash-btn.primary:hover { opacity: 0.85; color: #111; } .stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; } .stat-card { background: #3a3a3a; border: 1px solid #4d4d4d; border-left: 4px solid #666; border-radius: 8px; padding: 16px 18px; text-decoration: none; color: #eee; display: block; transition: transform 0.1s, border-color 0.2s; } .stat-card:hover { transform: translateY(-2px); border-color: #777; } .stat-num { font-size: 30px; font-weight: bold; line-height: 1; } .stat-label { color: #aaa; font-size: 12px; margin-top: 7px; text-transform: uppercase; letter-spacing: 0.5px; } .stat-sub { color: #777; font-size: 11px; margin-top: 3px; } .sc-ready { border-left-color: #4caf50; } .sc-ready .stat-num { color: #88ff88; } .sc-queued { border-left-color: #5a8fd0; } .sc-queued .stat-num { color: #88bbff; } .sc-progress { border-left-color: #d0a84c; } .sc-progress .stat-num { color: #ffcc44; } .sc-error { border-left-color: #c05050; } .sc-error .stat-num { color: #ff8888; } .sc-archived .stat-num { color: #ccc; } .sc-total { border-left-color: #9c7fd0; } .sc-total .stat-num { color: #bba6ff; } .sc-value { border-left-color: #4caf50; } .sc-value .stat-num { color: #88ff88; } .sc-lines { border-left-color: #5a8fd0; } .sc-lines .stat-num { color: #88bbff; } .dash-foot { color: #999; font-size: 11px; margin-top: 16px; text-align: right; } .dash-actions { align-items: center; } .dash-note { color: #aaa; font-size: 12px; } .dash-btn.disabled { background: #444; color: #999; border-color: #555; } /* Ready / Queued / Errors lead; the rest are context. */ .stats-primary { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); margin-bottom: 12px; } .stats-primary .stat-card { padding: 20px 22px; } .stats-primary .stat-num { font-size: 40px; } .stats-secondary { grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 10px; } .stats-secondary .stat-card { padding: 10px 14px; border-left-width: 3px; } .stats-secondary .stat-num { font-size: 20px; } .stats-secondary .stat-label { font-size: 11px; margin-top: 5px; } .stat-card.is-zero .stat-num { color: #888; } .stat-card.sc-error.is-zero { border-left-color: #555; } /* Per-file upload progress, updated live from the worker's stage events. */ .upload-list { list-style: none; margin-top: 12px; max-height: 220px; overflow-y: auto; } .upload-list li { display: flex; align-items: center; gap: 10px; padding: 5px 8px; border-bottom: 1px solid #444; font-size: 12px; } .upload-list .ul-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .upload-list .ul-open { color: #6699CC; text-decoration: none; font-weight: bold; } .upload-list .ul-open:hover { text-decoration: underline; } .stage.stage-uploading { background: #3a3a3a; color: #bbb; } #uploadZone:focus-visible { outline: 2px solid #6699CC; outline-offset: 2px; } /* ---------- pending list page ---------- */ #content { padding: 12px; } #content #statusBar { margin-bottom: 10px; } table.list { width: 100%; border-collapse: collapse; font-size: 12px; background: #3a3a3a; } table.list th { background: #444; color: #6699CC; padding: 6px 8px; text-align: left; border-bottom: 1px solid #555; white-space: nowrap; } table.list td { padding: 6px 8px; border-bottom: 1px solid #444; vertical-align: top; } table.list tr:hover td { background: #3f3f3f; } .muted { color: #888; } .stage { display: inline-block; padding: 2px 7px; border-radius: 10px; background: #4a3a00; color: #ffcc44; font-size: 11px; font-weight: bold; } .stage-queued { background: #2a3a4a; color: #88bbff; } .stage-processing { background: #3a3a00; color: #ffee88; } .stage-parsed { background: #1a4a1a; color: #88ff88; } .stage-review { background: #1a4a1a; color: #88ff88; } .stage-editing { background: #1a4a1a; color: #88ff88; } .stage-error { background: #4a1a1a; color: #ff8888; } .btn { border: 1px solid #666; background: #555; color: #eee; border-radius: 3px; padding: 4px 10px; font-size: 11px; cursor: pointer; text-decoration: none; display: inline-block; margin-right: 5px; } .btn:hover { border-color: #6699CC; color: #6699CC; } .btn-delete { border-color: #663333; color: #ff9999; background: #3a2a2a; } .btn-process { border-color: #336655; color: #88ffcc; background: #2a3a35; } #emptyState { color: #888; padding: 28px; text-align: center; background: #3a3a3a; border-radius: 5px; display: none; } /* ---------- archive page ---------- */ body.archive-page { display: flex; flex-direction: column; height: 100vh; overflow: hidden; } #listPanel { flex-shrink: 0; height: 210px; min-height: 80px; max-height: 70vh; overflow-y: auto; resize: vertical; border-bottom: 2px solid #555; background: #2e2e2e; } #listPanel th.sortable { cursor: pointer; user-select: none; } #listPanel th.sortable:hover { color: #99bbe0; } #listPanel th.sort-asc::after { content: " \25B2"; font-size: 9px; } #listPanel th.sort-desc::after { content: " \25BC"; font-size: 9px; } .result-count { color: #999; font-size: 11px; margin-left: 6px; } #archiveToolbar { position: sticky; top: 0; margin: -10px -10px 8px; padding: 6px 10px; background: #222; border-bottom: 1px solid #3a3a3a; display: flex; align-items: center; gap: 6px; z-index: 2; } #archiveToolbar button { background: #555; color: #eee; border: 1px solid #666; border-radius: 3px; padding: 2px 9px; font-size: 12px; line-height: 1.4; cursor: pointer; } #archiveToolbar button:hover { border-color: #6699CC; color: #6699CC; } #archiveToolbar #btnOpenOriginal { margin-left: auto; margin-right: 0; } #filterPanel { flex-shrink: 0; background: #333; border-bottom: 1px solid #555; padding: 10px 12px; } #filterPanel form { display: flex; flex-wrap: wrap; gap: 8px 10px; align-items: flex-end; } .filter-field { display: flex; flex-direction: column; gap: 3px; } .filter-field label { color: #aaa; font-size: 11px; } .filter-field input, .filter-field select { background: #2a2a2a; border: 1px solid #555; color: #eee; border-radius: 3px; padding: 4px 6px; font-size: 12px; } .filter-field input:focus, .filter-field select:focus { outline: none; border-color: #6699CC; } .filter-actions { display: flex; gap: 6px; align-items: center; padding-bottom: 1px; } .filter-btn { border: 1px solid #666; background: #555; color: #eee; border-radius: 3px; padding: 5px 11px; font-size: 12px; cursor: pointer; text-decoration: none; } .filter-btn.primary { background: #6699CC; color: #111; border-color: #6699CC; font-weight: bold; } .filter-btn:hover { opacity: 0.85; } #listPanel table { width: 100%; border-collapse: collapse; font-size: 12px; } #listPanel th { background: #3a3a3a; color: #6699CC; padding: 5px 8px; text-align: left; border-bottom: 1px solid #555; position: sticky; top: 0; z-index: 1; white-space: nowrap; } #listPanel td { padding: 4px 8px; border-bottom: 1px solid #3a3a3a; white-space: nowrap; } .inv-row { cursor: pointer; } .inv-row:hover td { background: #3a3a3a; } .inv-row.selected td { background: #1a3a5a; } #detailLayout { display: flex; flex: 1; overflow: hidden; } #archiveLeft { flex: 1; overflow-y: auto; background: #222; padding: 10px; } /* Width is set by the archive zoom (applyZoom). */ #archiveLeft img { max-width: none; display: block; border-radius: 2px; } #archiveLeft img + img { margin-top: 8px; } #archiveRight { flex: 1; overflow-y: auto; padding: 12px; background: #333; border-left: 1px solid #444; } #pdfPlaceholder { color: #666; font-size: 12px; padding: 20px; text-align: center; } .info-card { background: #3a3a3a; border-radius: 5px; padding: 12px 14px; margin-bottom: 12px; } .info-card h2 { font-size: 13px; color: #6699CC; margin-bottom: 10px; padding-bottom: 5px; border-bottom: 1px solid #555; } .info-row { display: flex; margin-bottom: 5px; gap: 8px; } .info-label { color: #aaa; width: 100px; flex-shrink: 0; text-align: right; font-size: 12px; } .info-value { color: #eee; font-size: 12px; } /* Header and the batch it produced sit side by side; the batch card takes the space the header card was leaving empty. Each card ends at its own content - stretching the short header card to the batch list's height left dead space. */ .detail-top { display: flex; gap: 12px; align-items: flex-start; flex-wrap: wrap; } .detail-top > .info-card { flex: 1 1 300px; min-width: 0; } .detail-top > .info-card:first-child { flex: 0 1 auto; } #batchCard h2 { display: flex; align-items: center; gap: 8px; } .batch-flag { background: #4a3a00; color: #ffcc44; font-size: 10px; font-weight: bold; padding: 2px 6px; border-radius: 3px; } .batch-none { color: #888; font-size: 12px; } .batch-scroll { max-height: 190px; overflow: auto; margin-top: 8px; border-top: 1px solid #555; } #batchTable { width: 100%; border-collapse: collapse; font-size: 11px; } #batchTable th { background: #444; color: #6699CC; padding: 4px 5px; text-align: left; border-bottom: 1px solid #555; white-space: nowrap; position: sticky; top: 0; } #batchTable td { padding: 3px 5px; border-bottom: 1px solid #3a3a3a; white-space: nowrap; } #batchTable td:nth-child(3), #batchTable td:nth-child(4), #batchTable td:nth-child(5), #batchTable td:nth-child(6) { text-align: right; } #batchTable tr.batch-low td { color: #ffcc44; } #itemsTable { width: 100%; border-collapse: collapse; font-size: 12px; } #itemsTable th { background: #444; color: #6699CC; padding: 5px 6px; text-align: left; border-bottom: 1px solid #555; white-space: nowrap; } #itemsTable td { padding: 4px 5px; border-bottom: 1px solid #3a3a3a; vertical-align: top; } #itemsTable tr:hover td { background: #3f3f3f; } #itemsTable td:nth-child(4), #itemsTable td:nth-child(5), #itemsTable td:nth-child(6) { text-align: right; } /* busy overlay */ #busyOverlay { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 600; background: rgba(0, 0, 0, 0.55); align-items: center; justify-content: center; } #busyOverlay .busy-box { background: #3a3a3a; border: 1px solid #555; border-radius: 8px; padding: 22px 30px; text-align: center; min-width: 260px; } #busyOverlay .busy-spinner { width: 30px; height: 30px; margin: 0 auto 12px; border: 3px solid #555; border-top-color: #6699CC; border-radius: 50%; animation: busySpin 0.8s linear infinite; } #busyOverlay .busy-msg { color: #ccc; font-size: 13px; } @keyframes busySpin { to { transform: rotate(360deg); } } /* new product modal */ #newProductModal { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 500; background: rgba(0,0,0,0.75); } #newProductModal .modal-box { position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%); background: #3a3a3a; border: 1px solid #555; border-radius: 8px; padding: 20px; width: 420px; max-height: 90vh; overflow-y: auto; } #newProductModal h2 { font-size: 14px; color: #6699CC; margin-bottom: 14px; padding-bottom: 8px; border-bottom: 1px solid #555; } /* ---- unit cost / retail / gross margin ---------------------------------- */ /* Computed cells: not inputs, so they read as derived rather than editable. */ .calc-cell { text-align: right; padding: 4px 6px; color: #ccc; font-variant-numeric: tabular-nums; } .calc-cell.cmp-na { color: #666; } .gm-cell { font-weight: bold; } .gm-good { color: #88ff88; } .gm-thin { color: #ffcc66; } .gm-loss { color: #ff8888; } .np-select { background: #2a2a2a; border: 1px solid #555; color: #eee; padding: 4px 7px; border-radius: 3px; font-size: 13px; } /* Database failure banner (showDbError). Stays until the page reloads. */ .db-warning { display: none; margin: 0 12px 8px; padding: 7px 12px; border-radius: 4px; font-size: 12px; background: #4a0000; color: #ff9999; flex-shrink: 0; } /* ---- review sanity checks ---------------------------------------------- */ .attention-count { color: #ffcc44; font-weight: bold; cursor: pointer; text-decoration: underline dotted; } .attention-count:hover { color: #ffe08a; } .attention-none { color: #88ff88; } #lineItemsTable.attention-only tbody tr:not(.needs-attention) { display: none; } .save-blockers { color: #ffcc44; font-size: 11px; margin-left: 12px; } .total-ok { color: #88ff88; } .total-diff { color: #ffcc44; font-weight: bold; } /* Inline validation, set by handleSave and cleared on the next edit. */ .field-error { color: #ff9999; font-size: 10px; } .hdr-field input.field-invalid, .hdr-field select.field-invalid, #lineItemsTable input.field-invalid { border-color: #cc5555; background: #3a2626; } #lineItemsBody tr.row-invalid td:first-child { box-shadow: inset 3px 0 0 #cc5555; } /* Line total that does not equal qty x case cost. */ #lineItemsTable input.item-total.total-mismatch { border-color: #b08a2a; color: #ffcc44; } .match-actions { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 3px; } .match-actions .search-toggle, .match-actions .btn-new-item { margin-top: 0; } .search-result-item.active, .search-result-new.active { background: #3a3a3a; } .search-result-item.active .search-result-desc { color: #6699CC; } .status-actions { margin-left: 10px; } .status-actions a, .status-actions button { margin-left: 6px; background: #2a2a2a; border: 1px solid #5a8a5a; color: #cfe; border-radius: 3px; padding: 2px 9px; font-size: 11px; cursor: pointer; text-decoration: none; } .status-actions a:hover, .status-actions button:hover { border-color: #88ff88; } #reviewSection.saved { opacity: 0.45; pointer-events: none; } /* Undo toast for row removal and Accept All. */ #toast { display: none; position: fixed; left: 50%; bottom: 22px; transform: translateX(-50%); background: #222; color: #eee; border: 1px solid #555; border-radius: 5px; padding: 8px 12px; font-size: 12px; z-index: 700; align-items: center; gap: 12px; box-shadow: 0 4px 14px rgba(0, 0, 0, 0.5); } #toast button { background: transparent; border: 1px solid #6699CC; color: #6699CC; border-radius: 3px; padding: 2px 10px; font-size: 11px; font-weight: bold; cursor: pointer; }