/* --- Sysfreight web design tokens ------------------------------------------
   Sampled from a screenshot of the real Import Job screen (c:\tmp\img), as the
   dominant fill of each region rather than by eye, so this app reads as part of
   the product rather than as a separate tool.

   The brand here is BLUE. The login shell's stylesheet
   (sysfreightweb.com/SysfreightWeb/Main/css/style.css) overrides .btn-success
   to red, which is why a first pass at this used red -- but that stylesheet
   does not govern the application screens: on the real form the primary chrome
   is #7AB8EA and Refresh is still Bootstrap's own green. The screenshot wins.

   Status colours (ok / warn / error on chips, validators, field tints) stay as
   they are: they carry meaning, and the product agrees -- its Delete is red and
   its Refresh green against the same blue chrome.

   Previous look: --sf-primary #1976d2, --sf-link #1565c0, --sf-font "Segoe UI".
   Or restore style.css.pre-sysfreight-20260926-1840. */
:root {
  --sf-font: Tahoma, Geneva, Verdana, "Segoe UI", sans-serif;
  --sf-mono: Consolas, "Courier New", monospace;

  --sf-primary: #7AB8EA;        /* header, section bars, active tab, buttons */
  --sf-primary-dark: #4A90C8;   /* hover / pressed */
  --sf-primary-tint: #DCEAF8;   /* faint wash for selected rows */
  --sf-sidebar: #80BCEC;
  --sf-on-primary: #14385c;     /* text on the blue -- it is light, so dark ink */

  --sf-panel: #CCCCCC;          /* form panel / page background */
  --sf-toolbar: #ECECEC;
  --sf-tab-idle: #F6F6F6;
  --sf-readonly: #C6DAE0;       /* read-only and computed inputs */
  --sf-disabled: #A2C0DA;       /* disabled buttons */
  --sf-field: #FEFEFE;

  --sf-danger: #D8524E;         /* Delete */
  --sf-success: #5CB85C;        /* Refresh */
  --sf-link: #1565c0;
  --sf-link-hover: #0d47a1;
  --sf-ink: #333;
  --sf-label: #546382;
}

* { box-sizing: border-box; }
html, body {
  margin: 0; padding: 0;
  font-family: var(--sf-font);
  font-size: 13px;
  color: var(--sf-ink);
  background: #eaf0f7;
}
a { color: var(--sf-link); text-decoration: none; }
a:hover { color: var(--sf-link-hover); }
a:hover { text-decoration: underline; }

/* top bar */
header.topbar {
  background: var(--sf-primary);
  color: white;
  padding: 10px 18px;
  display: flex;
  align-items: center;
  gap: 16px;
}
header.topbar h1 { margin: 0; font-size: 15px; font-weight: 600; }
header.topbar a { color: #ffe9e9; }
header.topbar .spacer { flex: 1; }
header.topbar .right { font-size: 12px; opacity: 0.9; }

/* main layout */
main { padding: 16px; max-width: 1400px; margin: 0 auto; }
main.wide { max-width: none; }

/* split view: PDF on the left, form on the right */
.split-view {
  display: flex;
  gap: 12px;
  height: calc(100vh - 80px);
}
.split-left {
  flex: 1 1 48%;
  min-width: 380px;
  display: flex;
  flex-direction: column;
}
.split-left .pdf-header {
  background: #37474f;
  color: #eceff1;
  padding: 6px 10px;
  font-size: 12px;
  display: flex;
  align-items: center;
  gap: 10px;
}
.split-left .pdf-header a { color: #81d4fa; }
.pdf-frame {
  flex: 1;
  width: 100%;
  border: 1px solid #90a4ae;
  border-top: 0;
  background: #263238;
}
.split-right {
  flex: 1 1 52%;
  min-width: 460px;
  overflow-y: auto;
  padding-right: 6px;
}

/* When no PDF is available, hide the split and let the form use full width. */
.split-view.no-pdf .split-left { display: none; }
.split-view.no-pdf .split-right { flex: 1 1 100%; }

/* toast */
.toast {
  background: #c8e6c9; color: #1b5e20;
  padding: 8px 14px; border-radius: 4px;
  margin-bottom: 12px; font-weight: 500;
}

/* status chips */
.chip[hidden] { display: none !important; }   /* .chip sets display, which beats the UA [hidden] rule */

.chip {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 10px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.3px;
}
.chip.conf-high   { background: #c8e6c9; color: #1b5e20; }
.chip.conf-medium { background: #fff9c4; color: #795548; }
.chip.conf-low    { background: #ffcdd2; color: #b71c1c; }
.chip.conf-\?     { background: #e0e0e0; color: #555; }
.chip.review      { background: #ffcdd2; color: #b71c1c; }
.chip.tag         { background: var(--sf-primary-tint); color: var(--sf-primary-dark); }
.chip.flag        { background: #ffe0b2; color: #e65100; }
.chip.time        { background: #e1f5fe; color: #01579b; }
.chip.ocr         { background: #ede7f6; color: #4527a0; }
.chip.mode        { background: #e8eaf6; color: #283593; }
/* A mode a reviewer asked for, so it reads differently from the default. */
.chip.mode.forced { background: #d1c4e9; color: #311b92; }

/* "Run Vision Mode" — a chip-shaped submit button in the status strip. Its
   own little form (an edit form is already open further down the page and
   forms cannot nest), kept inline so the strip lays out as one row. */
.mode-rerun { display: inline; margin: 0; }
.chip-btn {
  display: inline-block;
  padding: 2px 9px;
  border: 1px solid #7986cb;
  border-radius: 10px;
  background: #fff;
  color: #283593;
  font-size: 11px;
  font-weight: 600;
  font-family: inherit;
  text-transform: uppercase;
  letter-spacing: 0.3px;
  cursor: pointer;
}
.chip-btn:hover { background: #e8eaf6; }
.chip-btn:active { background: #c5cae9; }
/* Nothing to do until the reviewer picks a different type -- re-reading a
   document as the type it already is costs a full extraction and changes
   nothing. app.js enables it on the first real change. */
.chip-btn:disabled {
  border-color: #c5cad2;
  color: #9aa0a8;
  background: #f5f6f8;
  cursor: default;
}
.chip-btn:disabled:hover { background: #f5f6f8; }

/* The document-type control: the classifier's answer, and the way to overrule
   it. Shaped like the chips it sits among so the strip stays one row. */
.chip-form { display: inline-flex; align-items: center; gap: 4px; margin: 0; }
.chip-label {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.3px;
  color: var(--sf-primary-dark);
}
.chip-select {
  padding: 2px 6px;
  border: 1px solid #7986cb;
  border-radius: 10px;
  background: #fff;
  color: #283593;
  font-size: 11px;
  font-weight: 600;
  font-family: inherit;
  max-width: 230px;
}
/* A type with no target is a statement about where the record IS, not a
   destination -- it reads as a warning rather than a choice. */
.chip-select option[data-no-target] { color: #e65100; }
.chip.ocr.weak    { background: #ffe0b2; color: #e65100; }

/* file list */
table.files {
  width: 100%;
  border-collapse: collapse;
  background: white;
  border: 1px solid #b0bec5;
}
table.files th, table.files td {
  padding: 7px 10px;
  border-bottom: 1px solid #e0e0e0;
  text-align: left;
  vertical-align: middle;
}
table.files th {
  background: #cfd8dc;
  font-weight: 600;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.3px;
}
table.files tr:hover { background: #f5f5f5; }

/* form card (matches the screenshot blue-box look) */
.card {
  background: #d6e4f5;
  border: 1px solid #90a4ae;
  padding: 12px;
  margin-bottom: 14px;
  border-radius: 3px;
}
/* The product heads each section with a filled blue bar ("B/L Info"), not an
   underlined caption. Same idiom here so the two read alike. */
.card h2 {
  margin: -10px -10px 10px;
  font-size: 13px;
  font-weight: 600;
  color: var(--sf-on-primary);
  background: var(--sf-primary);
  padding: 5px 10px;
  border-bottom: none;
  border-radius: 3px 3px 0 0;
}

/* field rows: label + input */
.grid {
  display: grid;
  grid-template-columns: 160px 1fr 160px 1fr;
  gap: 6px 10px;
  align-items: center;
}
.grid.two { grid-template-columns: 160px 1fr; }
.grid label {
  font-weight: 500;
  color: #263238;
  padding-left: 2px;
}
.grid input, .grid select, .grid textarea {
  background: white;
  border: 1px solid #90a4ae;
  padding: 4px 7px;
  font-size: 13px;
  font-family: inherit;
  min-height: 26px;
  width: 100%;
}
.grid input:read-only { background: #f5f5f5; color: #555; }
/* Two boxes sharing one grid cell -- a code and the account code that belongs
   to it. Both end up shorter than a full cell, which is the point: the pair
   fits where one field was, and the row's other half stays free for the next
   one. The lookup keeps the larger share because it carries the picker button
   inside its own width. */
.grid .field-pair {
  display: flex;
  gap: 6px;
  align-items: center;
  min-width: 0;
}
.grid .field-pair > .lookup-wrap { flex: 3 1 0; min-width: 0; }
.grid .field-pair > input        { flex: 2 1 0; min-width: 0; }

.grid .span2 { grid-column: span 2; }
.grid .span3 { grid-column: span 3; }
.grid .span4 { grid-column: span 4; }
.grid .null-input { color: #999; font-style: italic; }

/* The "..." opener shares the label's gutter rather than the input column,
   so Name and Address 1-4 boxes all start at the same x. It right-aligns in
   the gutter, landing at the same spot on every party block. */
.addr-label {
  display: flex;
  align-items: center;
  gap: 6px;
  padding-left: 2px;
}
.addr-label label { flex: 1 1 auto; padding-left: 0; }

/* ---------- PDF panel: canvas pages + source highlight ---------- */
.pdf-canvas-host {
  flex: 1 1 auto;
  overflow: auto;
  background: #546e7a;
  padding: 8px;
  min-height: 0;
}
.pdf-page {
  position: relative;
  margin: 0 auto 10px;
  width: fit-content;
  box-shadow: 0 1px 6px rgba(0, 0, 0, .4);
  background: white;
}
.pdf-page canvas { display: block; }
/* Invisible, selectable text over the rendered page: PDF.js places one span
   per text run, so the reader can select and copy from the PDF exactly as in
   the browser's own viewer. Transparent text, real glyph boxes. */
.pdf-textlayer {
  position: absolute;
  inset: 0;
  overflow: hidden;
  line-height: 1;
  text-align: initial;
  transform-origin: 0 0;
  forced-color-adjust: none;
}
.pdf-textlayer span,
.pdf-textlayer br {
  position: absolute;
  white-space: pre;
  cursor: text;
  color: transparent;
  transform-origin: 0 0;
}
.pdf-textlayer ::selection { background: rgba(0, 120, 255, .35); }
/* PDF.js appends this to make a drag past the last line behave. */
.pdf-textlayer .endOfContent {
  display: block;
  position: absolute;
  inset: 100% 0 0;
  z-index: -1;
  cursor: default;
  user-select: none;
}

/* Sits exactly over its page; never eats clicks meant for the page. */
.pdf-overlay {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.pdf-hit {
  position: absolute;
  border: 2px solid #ff6d00;
  background: rgba(255, 193, 7, .28);
  border-radius: 2px;
  box-shadow: 0 0 0 2px rgba(255, 109, 0, .18);
  animation: pdf-hit-in .18s ease-out;
}
@keyframes pdf-hit-in {
  from { opacity: 0; transform: scale(1.25); }
  to   { opacity: 1; transform: scale(1); }
}
.pdf-hit-status {
  flex: 0 0 auto;
  padding: 4px 10px;
  font-size: 11px;
  color: #455a64;
  background: #eceff1;
  border-top: 1px solid #b0bec5;
  min-height: 20px;
}
.pdf-hit.approx {
  border-style: dashed;
  border-color: #6a1b9a;
  background: rgba(156, 39, 176, .16);
  box-shadow: 0 0 0 2px rgba(106, 27, 154, .15);
}
.pdf-hit-status.ok     { color: #1b5e20; }
.pdf-hit-status.approx { color: #6a1b9a; }
.pdf-hit-status.miss { color: #8d6e63; }

/* "ports don't say which" note, inline in the Import / Export card. */
.dir-hint {
  padding: 4px 8px;
  background: #fff8e1;
  border-left: 3px solid #ffa000;
  font-size: 11px;
  color: #6d4c41;
}
.addr-dots {
  flex: 0 0 26px;
  background: #eceff1;
  border: 1px solid #90a4ae;
  color: #37474f;
  font-family: inherit;
  font-size: 12px;
  line-height: 1;
  letter-spacing: 1px;
  min-height: 26px;
  padding: 0;
  cursor: pointer;
}
.addr-dots:hover { background: #cfd8dc; }
.addr-dots:active { background: #b0bec5; }

/* Count beside a party heading when the document prints more address lines
   than the four boxes can show. Red because it marks text the form is NOT
   displaying, not merely a long value. */
/* Row count beside the Marks / Description labels. Green while the block fits
   the target's slots as a clerk expects it to, red and bold once it runs past
   the nominal 15 lines -- the count is the only thing on the form that can say
   the block is longer than the shape it is going into. */
.row-count {
  margin-left: 8px;
  color: #2e7d32;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: normal;
  white-space: nowrap;
}

.row-count.over {
  color: #c62828;
  font-weight: 800;
}

.addr-count {
  margin-left: 8px;
  color: #c62828;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: normal;
  white-space: nowrap;
}

/* ---------- address editor modal (opened by the "..." button) ---------- */
.addr-modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(38, 50, 56, .35);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}
.addr-modal {
  background: #d6e4f5;
  border: 1px solid #607d8b;
  box-shadow: 0 8px 28px rgba(0, 0, 0, .35);
  width: min(620px, 92vw);
  font-size: 13px;
}
.addr-modal-head {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--sf-primary);
  color: white;
  font-weight: 600;
  padding: 5px 8px;
}
.addr-modal-head .who { font-weight: 400; color: #bbdefb; font-size: 12px; }
.addr-modal-x {
  margin-left: auto;
  background: #eceff1;
  border: 1px solid #90a4ae;
  color: #263238;
  cursor: pointer;
  font-size: 12px;
  line-height: 1;
  padding: 2px 6px;
}
.addr-modal-x:hover { background: #cfd8dc; }
.addr-modal-body { padding: 10px 10px 0; }
.addr-modal-body textarea {
  width: 100%;
  box-sizing: border-box;
  min-height: 110px;
  resize: vertical;
  background: white;
  border: 1px solid var(--sf-primary);
  padding: 5px 7px;
  font-family: inherit;
  font-size: 13px;
  line-height: 1.4;
}
.addr-modal-hint {
  margin-top: 6px;
  min-height: 15px;
  font-size: 11px;
  color: #546e7a;
}
.addr-modal-hint.warn { color: #bf360c; font-weight: 500; }
.addr-modal-foot {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 8px 10px 10px;
}
.addr-modal-foot .spacer { margin-left: auto; }
.addr-modal-foot .btn[disabled] { opacity: .5; cursor: not-allowed; }

/* tabs */
.tabs {
  display: flex;
  gap: 2px;
  margin-bottom: -1px;
  position: relative;
  z-index: 1;
}
.tab {
  background: #90caf9;
  color: var(--sf-primary-dark);
  padding: 8px 18px;
  border: 1px solid #90a4ae;
  border-bottom: 1px solid #d6e4f5;
  cursor: pointer;
  font-size: 13px;
  font-weight: 500;
}
.tab.active {
  background: #d6e4f5;
  border-bottom: 1px solid #d6e4f5;
}
.tab-content { display: none; }
.tab-content.active { display: block; }

/* line items / grid table */
table.lines {
  width: 100%;
  border-collapse: collapse;
  background: white;
  border: 1px solid #90a4ae;
  font-size: 12px;
}
table.lines th, table.lines td {
  padding: 4px 6px;
  border-bottom: 1px solid #e0e0e0;
  border-right: 1px solid #e0e0e0;
  vertical-align: middle;
}
table.lines th {
  background: #b0bec5;
  font-weight: 600;
  text-align: left;
  text-transform: uppercase;
  font-size: 11px;
  letter-spacing: 0.3px;
  position: relative;   /* anchors the .col-grip resize handle */
}
table.lines td { padding: 0; }
table.lines td input {
  border: 0;
  padding: 4px 6px;
  font-size: 12px;
  width: 100%;
  min-height: 24px;
  background: transparent;
}
table.lines td input:focus {
  background: #fff9c4;
  outline: 1px solid var(--sf-primary);
}

/* add/delete row controls */
.row-x {
  background: #ef5350;
  color: white;
  border: 0;
  width: 22px; height: 22px;
  font-size: 15px; font-weight: bold;
  cursor: pointer;
  border-radius: 3px;
  line-height: 1;
  padding: 0;
}
.row-x:hover { background: #c62828; }
.add-row {
  background: #43a047;
  color: white;
  border: 0;
  padding: 6px 12px;
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  border-radius: 3px;
  margin-top: 8px;
}
.add-row:hover { background: #2e7d32; }

/* sibling-doc nav: shown when a PDF yielded multiple sub-documents */
.sibling-strip {
  display: flex;
  gap: 6px;
  align-items: center;
  flex-wrap: wrap;
  background: #e8f5e9;
  border: 1px solid #81c784;
  padding: 8px 10px;
  border-radius: 3px;
  margin-bottom: 10px;
  font-size: 12px;
}
.sibling-label { color: #2e7d32; font-weight: 600; }
.sibling-chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 4px 10px;
  background: white;
  border: 1px solid #81c784;
  color: #2e7d32;
  border-radius: 14px;
  text-decoration: none;
}
.sibling-chip:hover { background: #c8e6c9; text-decoration: none; }
.sibling-chip.current {
  background: #2e7d32;
  color: white;
  border-color: #1b5e20;
}
.sibling-chip .pages { color: inherit; opacity: 0.85; font-size: 11px; }
/* The number a chip is named after -- the one thing a reviewer scanning a
   consol's strip is actually reading, so it is not dimmed like the pages and
   does not wrap away from its label. */
.sibling-chip .sibling-ref {
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.2px;
  white-space: nowrap;
}

/* "Blank page" pad for the Marks & Description block — single freeform
   textarea with no grid lines, styled to look like a sheet of paper. */
.marks-pad-card .marks-pad-hint {
  font-size: 11px; color: #78909c; margin: 0 0 8px;
}
.marks-pad-card .marks-pad-hint.busy {
  color: var(--sf-primary-dark); font-weight: 600;
}
textarea.marks-pad {
  width: 100%;
  min-height: 320px;
  padding: 14px 16px;
  background: #fffef7;
  background-image: linear-gradient(to bottom, transparent 23px, #eceff1 24px);
  background-size: 100% 24px;
  border: 1px solid #cfd8dc;
  border-radius: 3px;
  font: 13px/24px ui-monospace, "Cascadia Mono", var(--sf-mono);
  color: #263238;
  resize: vertical;
  outline: none;
}
textarea.marks-pad:focus {
  border-color: #2e7d32;
  box-shadow: 0 0 0 2px #c8e6c9;
}

/* Subtle "running OCR…" cue on the focused field during a paste. */
input.ocr-busy, textarea.ocr-busy {
  background: linear-gradient(90deg, #fff8e1 0%, #fffde7 50%, #fff8e1 100%);
  background-size: 200% 100%;
  animation: ocr-shimmer 1.2s linear infinite;
}
@keyframes ocr-shimmer { 0% { background-position: 100% 0 } 100% { background-position: -100% 0 } }
.sibling-nav {
  display: inline-flex; align-items: center;
  padding: 4px 12px;
  background: #2e7d32;
  border: 1px solid #1b5e20;
  color: white;
  border-radius: 14px;
  font-weight: 600;
  text-decoration: none;
  user-select: none;
}
.sibling-nav:hover { background: #1b5e20; text-decoration: none; }
.sibling-nav.disabled {
  background: #e0e0e0;
  border-color: #bdbdbd;
  color: #9e9e9e;
  cursor: not-allowed;
  pointer-events: none;
}
.sibling-counter {
  margin-left: auto;
  color: #2e7d32;
  font-weight: 600;
  font-size: 11px;
}

/* validator-flagged fields: more alarming than a format error */
input.field-flagged, select.field-flagged, textarea.field-flagged {
  background: #ffcdd2 !important;
  border: 1.5px solid #c62828 !important;
  box-shadow: 0 0 0 1px rgba(198, 40, 40, 0.2);
}
table.lines td input.field-flagged {
  background: #ffcdd2 !important;
  border: 1.5px solid #c62828 !important;
}

/* flash when a validator chip / detail line is clicked */
input.flash-highlight, select.flash-highlight, textarea.flash-highlight {
  background: #fff59d !important;
  box-shadow: 0 0 0 3px #fbc02d, 0 0 0 6px rgba(251, 192, 45, 0.3) !important;
  transition: background 200ms, box-shadow 200ms;
}

/* clickable flag chips / validator list items */
.chip[data-flag-code].flag-has-anchor {
  cursor: pointer;
}
.chip[data-flag-code].flag-has-anchor::after {
  content: " ↓";
  font-size: 10px;
}
.chip[data-flag-code].flag-has-anchor:hover {
  filter: brightness(0.92);
  text-decoration: none;
}
.chip[data-flag-code].flag-no-anchor {
  cursor: default;
  opacity: 0.85;
}

.validator-panel li[data-flag-code] {
  cursor: pointer;
  padding: 3px 6px;
  margin-left: -6px;
  border-radius: 3px;
  transition: background 120ms;
}
.validator-panel li.flag-has-anchor:hover {
  background: #fff3c4;
}
.validator-panel li.flag-has-anchor::after {
  content: " ↓";
  color: #8d6e63;
  font-size: 11px;
}
.validator-panel li.flag-no-anchor { cursor: default; }

/* field-level highlights: empty vs format-error */
input.field-empty, select.field-empty, textarea.field-empty {
  background: #fff8e1;
  border-left: 3px solid #ffb300;
}
input.field-error, select.field-error, textarea.field-error {
  background: #ffebee;
  border-left: 3px solid #e53935;
}
/* inside the compact line-item tables the left-border feels heavy — use
   a flat background tint instead */
table.lines td input.field-empty { background: #fff8e1; border-left: 0; }
table.lines td input.field-error { background: #ffebee; border-left: 0; }
input.field-error:hover, input.field-error:focus {
  outline: 2px solid #e53935;
  outline-offset: -1px;
}

/* a line-item cell whose own arithmetic does not add up: Amount that is not
   Qty x Unit Rate, or a Local Amt that is not Amount x Curr Rate. Louder than
   field-error (a format hint) because the figure is readable and still wrong,
   and !important so it shows through the empty/format tints underneath. The
   cell's tooltip says what the row came to. */
table.lines td input.cell-math-off,
input.cell-math-off {
  background: #ffcdd2 !important;
  border: 1.5px solid #c62828 !important;
  color: #b71c1c;
}
input.cell-math-off:hover, input.cell-math-off:focus {
  outline: 2px solid #c62828;
  outline-offset: -1px;
}

/* a code the tenant's master does not hold -- the invoice's Job No against
   vw_Jmjm1. Same red as cell-math-off, and for the same reason: the value is
   perfectly readable and still wrong, so it has to outrank the empty/format
   tints underneath rather than sit beside them. The box's tooltip says what
   is wrong with it. */
input.code-not-in-master,
table.lines td input.code-not-in-master {
  background: #ffcdd2 !important;
  border: 1.5px solid #c62828 !important;
  color: #b71c1c;
}
input.code-not-in-master:hover, input.code-not-in-master:focus {
  outline: 2px solid #c62828;
  outline-offset: -1px;
}

/* small pair of chips shown in the status strip */
.chip.field-empty-chip { background: #fff8e1; color: #c77700; border: 1px solid #ffb300; }
.chip.field-error-chip { background: #ffebee; color: #b71c1c; border: 1px solid #e53935; }

/* animate-fill effect on freshly extracted docs */
input.pending-fill, select.pending-fill, textarea.pending-fill {
  background: #fff8e1 !important;
  transition: background 200ms;
}
input.just-filled, select.just-filled, textarea.just-filled {
  background: #c8e6c9 !important;
  box-shadow: 0 0 0 2px #66bb6a;
  transition: background 450ms, box-shadow 450ms;
}

/* upload zone on home page */
#upload-form { margin-bottom: 12px; }
#upload-zone {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  border: 2px dashed #78909c;
  background: white;
  padding: 24px;
  text-align: center;
  cursor: pointer;
  border-radius: 4px;
  transition: background 120ms, border-color 120ms;
}
#upload-zone strong { color: var(--sf-primary-dark); font-size: 15px; }
#upload-zone span { color: #546e7a; font-size: 12px; }
#upload-zone.drag-over {
  background: var(--sf-primary-tint);
  border-color: var(--sf-primary);
}
#upload-zone.uploading {
  background: #fff3e0;
  border-color: #ff9800;
  cursor: progress;
}
#upload-filename { color: var(--sf-primary); font-weight: 500; font-size: 13px; }

/* progress bar on /processing page */
.progress-wrap {
  position: relative;
  height: 14px;
  background: #eceff1;
  border-radius: 7px;
  overflow: hidden;
}
.progress-bar {
  position: absolute;
  top: 0; left: 0; bottom: 0;
  background: var(--sf-primary);
  transition: width 500ms ease-out;
  background-image: linear-gradient(45deg,
    rgba(255,255,255,.15) 25%, transparent 25%,
    transparent 50%, rgba(255,255,255,.15) 50%,
    rgba(255,255,255,.15) 75%, transparent 75%, transparent);
  background-size: 28px 28px;
  animation: progress-stripes 1s linear infinite;
}
@keyframes progress-stripes {
  from { background-position: 0 0; }
  to   { background-position: 28px 0; }
}
.stage {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 0;
  font-size: 13px;
  color: #78909c;
}
.stage .dot {
  width: 10px; height: 10px;
  border-radius: 50%;
  background: #cfd8dc;
  flex-shrink: 0;
}
.stage.stage-done .dot { background: #43a047; }
.stage.stage-done .stage-label { color: #43a047; }
.stage.stage-active .dot {
  background: var(--sf-primary);
  box-shadow: 0 0 0 0 rgba(25, 118, 210, 0.5);
  animation: pulse 1.2s infinite;
}
.stage.stage-active .stage-label { color: var(--sf-primary-dark); font-weight: 500; }
.stage.stage-error .dot { background: #e53935; }
.stage.stage-error .stage-label { color: #b71c1c; }

/* How long each pipeline stage took, filled by the processing page from the
   job record. Tabular figures so a ticking number does not jitter, and pushed
   to the right of the row so the times line up in a column. */
.stage-time {
  margin-left: auto;
  font-family: Consolas, "SF Mono", monospace;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: #b0bec5;
}
.stage.stage-done .stage-time   { color: #43a047; }
.stage.stage-active .stage-time { color: var(--sf-primary-dark); font-weight: 500; }
.stage.stage-error .stage-time  { color: #b71c1c; }
@keyframes pulse {
  0% { box-shadow: 0 0 0 0 rgba(25, 118, 210, 0.5); }
  70% { box-shadow: 0 0 0 8px rgba(25, 118, 210, 0); }
  100% { box-shadow: 0 0 0 0 rgba(25, 118, 210, 0); }
}

/* filter bar on home page */
.filter-bar {
  display: flex;
  gap: 12px;
  align-items: center;
  margin-bottom: 12px;
  background: white;
  border: 1px solid #b0bec5;
  padding: 8px 12px;
  border-radius: 3px;
}
.filter-bar input[type="text"] {
  flex: 1;
  padding: 5px 8px;
  border: 1px solid #90a4ae;
  font-size: 13px;
  min-height: 28px;
}
.filter-bar label {
  font-size: 12px;
  display: flex;
  align-items: center;
  gap: 5px;
  cursor: pointer;
}
.filter-bar .count { font-size: 12px; color: #78909c; }

/* action bar — sticks to the bottom of the scrolling form pane */
.actions {
  display: flex;
  gap: 10px;
  padding: 10px 6px;
  margin-top: 10px;
  border-top: 1px solid #90a4ae;
  align-items: center;
  position: sticky;
  bottom: 0;
  background: #eaf0f7;
  z-index: 10;
  box-shadow: 0 -2px 4px rgba(0,0,0,0.05);
}
.actions .spacer { flex: 1; }
.actions .hint {
  color: #e65100;
  font-size: 12px;
  font-style: italic;
  min-width: 120px;
  text-align: right;
}
.actions .kbd {
  font-size: 11px;
  color: #78909c;
  font-family: var(--sf-mono);
  border: 1px solid #b0bec5;
  padding: 1px 5px;
  border-radius: 3px;
  background: white;
}
.btn {
  background: var(--sf-primary);
  color: white;
  border: 0;
  padding: 8px 16px;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  border-radius: 3px;
}
.btn:hover { background: var(--sf-primary-dark); }
.btn.secondary { background: #78909c; }
.btn.secondary:hover { background: #546e7a; }

/* validator panel */
.validator-panel {
  background: #fff8e1;
  border: 1px solid #ffb300;
  padding: 8px 12px;
  margin-bottom: 14px;
  border-radius: 3px;
  font-size: 12px;
}
.validator-panel h3 {
  margin: 0 0 6px 0;
  font-size: 12px;
  color: #e65100;
  text-transform: uppercase;
  letter-spacing: 0.3px;
}
.validator-panel ul { margin: 0; padding-left: 18px; }

/* raw JSON view */
pre.raw {
  background: #263238;
  color: #eceff1;
  padding: 14px;
  border-radius: 3px;
  overflow: auto;
  font-family: var(--sf-mono);
  font-size: 12px;
  line-height: 1.4;
}

/* -------- /help page: TOC sidebar + readable markdown content -------- */
.help-layout {
  display: grid;
  grid-template-columns: 260px 1fr;
  gap: 24px;
  align-items: start;
  max-width: 1400px;
  margin: 0 auto;
}
.help-toc {
  position: sticky;
  top: 70px;
  max-height: calc(100vh - 90px);
  overflow-y: auto;
  background: white;
  border: 1px solid #b0bec5;
  border-radius: 4px;
}
.help-toc-inner {
  padding: 12px 14px;
  font-size: 12.5px;
}
.help-toc-inner strong {
  display: block;
  color: var(--sf-primary-dark);
  margin-bottom: 6px;
  text-transform: uppercase;
  font-size: 11px;
  letter-spacing: 0.4px;
}
.help-toc-inner .toc ul {
  list-style: none;
  padding: 0;
  margin: 0;
}
.help-toc-inner .toc li { margin: 2px 0; }
.help-toc-inner .toc ul ul { padding-left: 12px; font-size: 12px; }
.help-toc-inner .toc a {
  color: #455a64;
  text-decoration: none;
  display: block;
  padding: 2px 4px;
  border-radius: 2px;
}
.help-toc-inner .toc a:hover { background: var(--sf-primary-tint); color: var(--sf-primary-dark); }

.markdown-body {
  background: white;
  border: 1px solid #b0bec5;
  padding: 28px 36px;
  border-radius: 4px;
  font-size: 14px;
  line-height: 1.6;
  color: #263238;
  max-width: 960px;
}
.markdown-body h1, .markdown-body h2, .markdown-body h3,
.markdown-body h4, .markdown-body h5 {
  color: var(--sf-primary-dark);
  margin-top: 1.5em;
  margin-bottom: 0.5em;
}
.markdown-body h1 { font-size: 26px; border-bottom: 2px solid var(--sf-primary); padding-bottom: 6px; }
.markdown-body h2 { font-size: 20px; border-bottom: 1px solid #b0bec5; padding-bottom: 4px; }
.markdown-body h3 { font-size: 16px; }
.markdown-body p { margin: 0.8em 0; }
.markdown-body ul, .markdown-body ol { padding-left: 24px; }
.markdown-body li { margin: 3px 0; }
.markdown-body code {
  background: #eceff1;
  padding: 2px 5px;
  border-radius: 3px;
  font-family: var(--sf-mono);
  font-size: 13px;
  color: #37474f;
}
.markdown-body pre {
  background: #263238;
  color: #eceff1;
  padding: 12px 14px;
  border-radius: 4px;
  overflow-x: auto;
  font-size: 12.5px;
  line-height: 1.45;
}
.markdown-body pre code {
  background: transparent;
  color: inherit;
  padding: 0;
  font-size: inherit;
}
.markdown-body table {
  border-collapse: collapse;
  width: 100%;
  margin: 1em 0;
  font-size: 13px;
}
.markdown-body th, .markdown-body td {
  border: 1px solid #cfd8dc;
  padding: 6px 10px;
  text-align: left;
  vertical-align: top;
}
.markdown-body th { background: #cfd8dc; font-weight: 600; }
.markdown-body tr:nth-child(even) td { background: #f7f9fa; }
.markdown-body blockquote {
  border-left: 4px solid #90a4ae;
  margin: 1em 0;
  padding: 4px 14px;
  color: #455a64;
  background: #eceff1;
}
.markdown-body hr {
  border: 0;
  border-top: 1px solid #b0bec5;
  margin: 2em 0;
}
.markdown-body a { color: var(--sf-primary-dark); text-decoration: none; }
.markdown-body a:hover { text-decoration: underline; }
/* anchor targets from TOC get a subtle highlight */
.markdown-body :target {
  background: #fff8e1;
  padding: 2px 6px;
  margin: -2px -6px;
  border-radius: 3px;
}

/* Session badge in topbar — shows who the clerk is and which DB they're writing to */
.session-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: rgba(255,255,255,0.12);
  color: var(--sf-primary-tint);
  font-size: 12px;
  padding: 4px 10px;
  border-radius: 14px;
  margin-right: 10px;
  font-family: var(--sf-font);
}
.session-badge strong { color: #fff; font-weight: 600; }
.session-badge .op-name { color: #b3e5fc; font-size: 11px; }
.session-badge .db-name { color: #ffcc80; font-weight: 500; }
.session-badge .logout-link {
  color: var(--sf-primary-tint);
  text-decoration: none;
  margin-left: 4px;
  padding: 0 4px;
  border-radius: 3px;
  opacity: 0.7;
}
.session-badge .logout-link:hover { opacity: 1; background: rgba(255,255,255,0.1); }

/* Save toast: inline DB-write status */
.toast-db {
  display: inline-block;
  margin-left: 10px;
  padding: 2px 10px;
  border-radius: 10px;
  font-size: 12px;
  font-family: var(--sf-mono);
}
.toast-db.ok  { background: #c8e6c9; color: #1b5e20; }
.toast-db.err { background: #ffcdd2; color: #b71c1c; }

/* ---------- resizable line-item columns ---------- */
/* Header grips let the user widen a column whose values are clipped. The
   table is only pinned to pixel widths once a column has been resized, so
   untouched tables keep their percentage layout. */
.lines-scroll {
  overflow-x: auto;
  max-width: 100%;
}
table.lines.cols-sized td input,
table.lines.cols-sized td textarea {
  min-width: 0;
}
.col-grip {
  position: absolute;
  top: 0;
  right: -3px;
  width: 7px;
  height: 100%;
  cursor: col-resize;
  user-select: none;
  z-index: 2;
}
.col-grip:hover,
body.col-resizing .col-grip {
  background: var(--sf-primary);
  opacity: 0.55;
}
body.col-resizing {
  cursor: col-resize;
  user-select: none;
}

/* Master-data picker. Shares the address modal's backdrop and chrome; only the
   list inside it is its own. Wider than the address editor because a job row
   carries four columns of reference numbers. */
.lookup-modal { width: min(860px, 94vw); }

.lookup-search {
  display: flex;
  gap: 8px;
  align-items: center;
  padding: 10px 10px 6px;
}

.lookup-search input {
  flex: 1;
  min-width: 0;
  box-sizing: border-box;
  font-size: 13px;
  padding: 5px 8px;
  border: 1px solid #b0bec5;
  border-radius: 3px;
}

.lookup-search label {
  flex: none;
  font-size: 11px;
  color: #78909c;
  white-space: nowrap;
}

.lookup-search select {
  font-size: 12px;
  padding: 4px 5px;
  margin-left: 4px;
  max-width: 190px;
}

.lookup-body {
  max-height: 52vh;
  overflow: auto;
  padding: 0 10px;
}

.lookup-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
}

.lookup-table th {
  position: sticky;
  top: 0;
  background: #eceff1;
  text-align: left;
  font-weight: 600;
  color: #37474f;
  padding: 5px 7px;
  border-bottom: 1px solid #b0bec5;
  white-space: nowrap;
}

.lookup-table td {
  padding: 4px 7px;
  border-bottom: 1px solid #eceff1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 260px;
}

.lookup-table tbody tr { cursor: pointer; }
.lookup-table tbody tr:hover { background: var(--sf-primary-tint); }
.lookup-table tbody tr.sel { background: #bbdefb; }
.lookup-table td:first-child { font-family: var(--sf-mono); }

.lookup-err {
  padding: 14px 4px;
  color: #78909c;
  font-size: 12px;
}

/* The "..." button beside a code field, and its wrapper so the button sits
   next to the input rather than under it. */
/* --- the glyphs the product draws INSIDE a field -------------------------
   On the Sysfreight screens a lookup is a magnifying glass at the right edge
   of the box it fills, and a date is a small calendar in the same place --
   part of the field, not a button beside it. So both sit on top of the input,
   which reserves room for them with padding rather than giving up width.

   The colours are sampled from the screenshots: the magnifier is a muted
   blue-grey, the calendar a plain grey. */
.sf-icon { display: block; }

.lookup-wrap { position: relative; display: flex; gap: 0; align-items: center; }
.lookup-wrap input { flex: 1; min-width: 0; padding-right: 22px; }

.lookup-dots, .date-cal {
  position: absolute;
  right: 2px;
  top: 50%;
  transform: translateY(-50%);
  flex: none;
  border: none;
  background: transparent;
  border-radius: 2px;
  cursor: pointer;
  line-height: 0;
  padding: 2px 3px;
}
.lookup-dots { color: #8FA8C8; }
.date-cal    { color: #8A8A8A; }

.lookup-dots:hover, .date-cal:hover {
  color: var(--sf-primary-dark, #4A90C8);
  background: var(--sf-primary-tint, #DCEAF8);
}
.lookup-dots:focus-visible, .date-cal:focus-visible {
  outline: 2px solid var(--sf-primary, #7AB8EA);
  outline-offset: -1px;
}

/* A date field is the same arrangement: input plus one glyph over its edge. */
.date-wrap { position: relative; display: flex; align-items: center; }
.date-wrap > input { flex: 1; min-width: 0; padding-right: 22px; }
/* The native picker's own input is only a means of opening it -- it must never
   be visible or take the field's place. It is NOT given a 1px box: the browser
   anchors the calendar popup to this element, so it is sized to sit exactly
   over the calendar icon, which is where the popup should appear. Transparent
   and click-through, so the button underneath still takes the click. */
.date-wrap > input[type="date"].date-native {
  position: absolute; right: 0; top: 0; bottom: 0;
  width: 24px; padding: 0; border: 0; margin: 0;
  min-height: 0; min-width: 0;
  opacity: 0; pointer-events: none;
}
/* The grid span classes are written for the input; a date field puts them on
   its wrapper instead, so they have to reach it too. */
.grid .date-wrap.span2 { grid-column: span 2; }
.grid .date-wrap.span3 { grid-column: span 3; }
.grid .date-wrap.span4 { grid-column: span 4; }

/* --- idioms taken from the Import Job screen ------------------------------ */

/* Read-only and computed boxes are filled blue-grey there, not white, so a
   clerk can see at a glance which fields they cannot type into. */
input[readonly], textarea[readonly], select:disabled,
input:disabled, textarea:disabled {
  background: var(--sf-readonly);
  color: #35506a;
}

/* Labels sit left-aligned in their own narrow column -- the product overrides
   Bootstrap's right-aligned .control-label to do exactly this. */
.grid > label, .grid.two > label {
  text-align: left;
  color: var(--sf-label);
}

/* Its form rows are tighter than ours were. */
.grid { row-gap: 5px; }
.card { background: #fff; }

/* Primary action: the product's blue with dark ink, because the blue is light.
   Delete stays red and anything confirming stays green -- as it does there. */
.btn {
  background: var(--sf-primary);
  color: var(--sf-on-primary);
  border: 1px solid var(--sf-primary-dark);
  font-weight: 600;
}

.btn:hover { background: var(--sf-primary-dark); color: #fff; }
.btn.secondary { background: var(--sf-tab-idle); color: #37474f; }
.btn.secondary:hover { background: #e0e0e0; color: #263238; }
.btn.danger { background: var(--sf-danger); color: #fff; border-color: #b73f3c; }
.btn:disabled, .btn.disabled {
  background: var(--sf-disabled);
  border-color: var(--sf-disabled);
  color: #5b7893;
  cursor: default;
}


/* ---- "Get container no from the PDF" ---------------------------------- *
 * An .add-row button that can be armed: while it waits for the reviewer to
 * highlight something on the page it says so, and looks like it is waiting. */
.pick-btn { margin-left: 8px; }
.pick-btn.armed {
  background: var(--sf-primary);
  border-color: var(--sf-primary);
  color: #fff;
  animation: pick-pulse 1.4s ease-in-out infinite;
}
@keyframes pick-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(25, 118, 210, 0.45); }
  60%      { box-shadow: 0 0 0 6px rgba(25, 118, 210, 0); }
}
.pick-hint {
  margin-left: 10px;
  font-size: 11px;
  color: #78909c;
}
.pick-hint.ok   { color: #2e7d32; font-weight: 600; }
.pick-hint.warn { color: #e65100; }

/* ---------- column totals on a line-items heading ---------- */
/* Floated rather than flexed: the shared `.card h2` rule paints every heading
   bar on the review screens, and nothing about it needs to change for this. */
.line-totals {
  font-weight: 600;
  letter-spacing: normal;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
/* Still floated wherever the bar rides on a card heading. The line-item
   tables moved theirs into their own <tfoot> (see .lines-total-row), where a
   float would collapse the cell it sits in. */
h2 > .line-totals { float: right; }

/* The totals row at the foot of a line-items table: right-aligned, so the
   figures land under the Amount / Local Amt columns they add up, and ruled off
   from the last line so it does not read as one more row of data. The row
   carries `hidden` until there is something to show -- an all-blank table gets
   no empty strip under it. */
table.lines tfoot .lines-total-row > td {
  padding: 7px 10px;
  text-align: right;
  background: #eceff1;
  border-top: 2px solid #90a4ae;
  border-right: 0;
  border-bottom: 0;
}
/* The figures carry no column names, so a divider is what tells them apart.
   Drawn in CSS rather than built into the markup, so it can sit lighter than
   the numbers it separates. */
.line-totals .lt-group + .lt-group::before {
  content: "|";
  margin: 0 9px;
  font-weight: 400;
  opacity: .45;
}
/* A total that could not take every line in: said quietly, but said. */
.line-totals .lt-partial {
  font-weight: 400;
  opacity: .8;
}
