:root {
  color-scheme: light;
  --bg: #f5f7f6;
  --surface: #ffffff;
  --ink: #1f2933;
  --muted: #64707d;
  --line: #d9e0e6;
  --blue: #1769aa;
  --green: #3c7d46;
  --red: #b42318;
  --amber: #8a5a00;
  --shadow: 0 8px 28px rgba(31, 41, 51, 0.08);
  --side-w: 232px;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--ink);
  font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}

button,
input {
  font: inherit;
}

.app-shell {
  width: min(1480px, calc(100% - 48px));
  margin: 0 auto;
  padding: 24px 0 96px;
}

.topbar {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  align-items: flex-start;
  margin-bottom: 18px;
}

h1,
h2,
h3,
p {
  margin: 0;
}

h1 {
  font-size: 28px;
  line-height: 1.15;
}

.topbar p,
.muted {
  color: var(--muted);
  margin-top: 6px;
}

.status-pill,
#summaryBadge,
#providerText,
#resultBadge {
  border: 1px solid var(--line);
  background: #eef4f1;
  color: var(--green);
  padding: 6px 10px;
  border-radius: 999px;
  font-size: 13px;
  white-space: nowrap;
}

.workspace-grid {
  display: grid;
  /* Upload form 30%, picklist panel 70%. The panel carries the picklist chips
     now - one per uploaded file, with its name and counts - so it needs the
     room, while the form is just a file picker and an email box. */
  grid-template-columns: minmax(260px, 30%) minmax(0, 70%);
  gap: 16px;
  align-items: stretch;
}

.panel {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 8px;
  box-shadow: var(--shadow);
}

.controls-panel,
.summary-panel,
.results-panel,
.logs-panel {
  padding: 18px;
}

.controls-panel {
  display: grid;
  gap: 14px;
}

.field {
  display: grid;
  gap: 6px;
}

label,
dt,
th {
  color: #3f4a56;
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0;
}

input[type="text"],
input[type="email"],
input[type="password"],
input[type="number"],
input[type="time"],
input:not([type]) {
  width: 100%;
  min-height: 38px;
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 8px 10px;
  color: var(--ink);
  background: #fff;
}

input[type="text"]:focus,
input[type="email"]:focus,
input[type="password"]:focus,
input[type="number"]:focus,
input[type="time"]:focus,
input:not([type]):focus {
  outline: none;
  border-color: var(--blue);
  box-shadow: 0 0 0 3px rgba(23, 105, 170, 0.15);
}

input::placeholder {
  color: var(--muted);
  opacity: 1;
}

/* Only flag a genuinely wrong address, not an empty box. */
input[type="email"]:not(:placeholder-shown):invalid {
  border-color: var(--red);
}

input[type="email"]:not(:placeholder-shown):invalid:focus {
  box-shadow: 0 0 0 3px rgba(180, 35, 24, 0.15);
}

input[type="file"] {
  width: 100%;
  border: 1px dashed #a8b4bf;
  border-radius: 6px;
  padding: 10px;
  background: #fbfcfd;
}

/* .action-bar sets display on its children, so hidden needs to win. */
[hidden] {
  display: none !important;
}

.two-col {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}

.segmented {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.segmented label,
.check-row {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 8px 10px;
  background: #fbfcfd;
  color: var(--ink);
  text-transform: none;
  font-size: 14px;
  font-weight: 600;
}

button {
  border: 1px solid var(--blue);
  background: #fff;
  color: var(--blue);
  border-radius: 6px;
  min-height: 40px;
  padding: 0 14px;
  font-weight: 700;
  cursor: pointer;
}

a.button-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 40px;
  border: 1px solid var(--blue);
  border-radius: 6px;
  padding: 0 14px;
  color: var(--blue);
  font-weight: 700;
  text-decoration: none;
}

button.primary {
  background: var(--blue);
  color: #fff;
}

button:disabled {
  border-color: #b9c3cc;
  background: #e8edf1;
  color: #7c8792;
  cursor: not-allowed;
}

.section-heading {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  align-items: center;
  margin-bottom: 14px;
}

.section-heading h2 {
  font-size: 17px;
}

.extension-tools {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  color: var(--muted);
  font-size: 13px;
}

/* Inside the fixed bottom bar: auto right margin pushes this to the left edge
   and holds the login / delay / extract controls over on the right. */
.action-bar .extension-tools {
  margin-right: auto;
}

.summary-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
  margin: 0;
}

.summary-list div {
  border-top: 1px solid var(--line);
  padding-top: 10px;
}

dd {
  margin: 4px 0 0;
  font-weight: 800;
  overflow-wrap: anywhere;
}

.warnings {
  display: grid;
  gap: 8px;
  margin-top: 16px;
}

.warning {
  border-left: 3px solid var(--amber);
  background: #fff8e8;
  color: #614100;
  padding: 8px 10px;
  font-size: 13px;
}

.table-panel {
  margin-top: 16px;
  overflow: hidden;
}

.table-panel .section-heading {
  padding: 16px 18px 0;
}

.table-wrap {
  overflow: auto;
  max-height: 48vh;
}

table {
  width: 100%;
  min-width: 1180px;
  border-collapse: collapse;
}

th,
td {
  padding: 10px 12px;
  border-top: 1px solid var(--line);
  text-align: left;
  vertical-align: top;
  font-size: 13px;
}

th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: #eef3f7;
}

td:last-child,
th:last-child {
  text-align: right;
}

.empty {
  color: var(--muted);
  text-align: center;
  height: 80px;
}

.results-panel {
  margin-top: 16px;
}

.result-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
  margin-top: 14px;
}

.automation-log {
  display: grid;
  gap: 6px;
  min-height: 42px;
  max-height: 130px;
  overflow: auto;
  margin-top: 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #fbfcfd;
  padding: 10px;
  color: var(--muted);
  font-size: 13px;
}

.automation-log:empty {
  display: none;
}

.automation-log a {
  color: var(--blue);
  font-weight: 700;
}

.result-list {
  border: 1px solid var(--line);
  border-radius: 8px;
  min-height: 72px;
  max-height: 280px;
  overflow: auto;
}

.result-row {
  padding: 9px 10px;
  border-top: 1px solid var(--line);
  font-size: 13px;
}

.result-row:first-child {
  border-top: 0;
}

.result-row strong {
  display: block;
  margin-bottom: 2px;
}

.result-row small {
  display: block;
  color: var(--muted);
  margin-top: 3px;
}

.success strong {
  color: var(--green);
}

.failed strong {
  color: var(--red);
}

.action-bar {
  position: fixed;
  left: var(--side-w);
  right: 0;
  bottom: 0;
  z-index: 30;
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 10px;
  padding: 12px max(24px, calc((100vw - var(--side-w) - 1480px) / 2 + 16px));
  background: rgba(255, 255, 255, 0.95);
  border-top: 1px solid var(--line);
  box-shadow: 0 -8px 24px rgba(31, 41, 51, 0.08);
  backdrop-filter: blur(12px);
}

.delay-control {
  text-transform: none;
  color: var(--muted);
}

#scanDelay {
  width: 92px;
}

@media (max-width: 900px) {
  .app-shell {
    width: min(100vw - 20px, 720px);
    padding-top: 14px;
  }

  .topbar,
  .workspace-grid,
  .result-grid,
  .two-col {
    grid-template-columns: 1fr;
  }

  .topbar {
    display: grid;
  }

  .action-bar {
    justify-content: stretch;
    flex-wrap: wrap;
  }

  .action-bar button {
    flex: 1 1 130px;
  }

  .action-bar .extension-tools {
    flex: 1 1 100%;
    margin-right: 0;
  }

  .action-bar .extension-tools a.button-link {
    width: 100%;
  }
}

/* ---------------------------------------------------------------- scan dialog */

.scan-overlay {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgba(31, 41, 51, 0.45);
  backdrop-filter: blur(3px);
}

.scan-dialog {
  width: min(620px, 100%);
  max-height: min(88vh, 760px);
  display: flex;
  flex-direction: column;
  gap: 14px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 10px;
  box-shadow: 0 18px 50px rgba(31, 41, 51, 0.25);
  padding: 18px;
}

.scan-dialog-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}

.scan-dialog h2 {
  margin: 0 0 4px;
  font-size: 17px;
}

.scan-dialog-head p {
  margin: 0;
  font-size: 13px;
}

.scan-state {
  border: 1px solid var(--blue);
  border-radius: 999px;
  padding: 4px 12px;
  color: var(--blue);
  font-size: 12px;
  font-weight: 700;
  white-space: nowrap;
}

.scan-state.is-done {
  border-color: var(--green);
  color: var(--green);
}

.scan-state.is-error {
  border-color: var(--red);
  color: var(--red);
}

.scan-progress {
  display: grid;
  gap: 8px;
}

.scan-bar {
  height: 8px;
  border-radius: 999px;
  background: #eef1f4;
  overflow: hidden;
}

.scan-bar-fill {
  height: 100%;
  width: 0;
  border-radius: 999px;
  background: var(--blue);
  transition: width 0.25s ease;
}

.scan-bar-fill.is-done {
  background: var(--green);
}

.scan-counts {
  display: flex;
  gap: 14px;
  font-size: 13px;
  font-weight: 700;
  color: var(--muted);
}

.scan-ok {
  color: var(--green);
}

.scan-bad {
  color: var(--red);
}

.scan-current {
  display: flex;
  align-items: center;
  gap: 10px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #fbfcfd;
  padding: 10px 12px;
}

.scan-current strong {
  display: block;
  font-size: 14px;
}

.scan-current small {
  color: var(--muted);
}

.scan-spinner {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  border: 2px solid #d9e0e6;
  border-top-color: var(--blue);
  border-radius: 50%;
  animation: scan-spin 0.8s linear infinite;
}

@keyframes scan-spin {
  to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
  .scan-spinner { animation-duration: 2.4s; }
  .scan-bar-fill { transition: none; }
}

.scan-feed {
  flex: 1 1 auto;
  min-height: 120px;
  overflow-y: auto;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 6px;
  background: #fff;
}

.scan-row {
  display: grid;
  grid-template-columns: 18px 1fr auto;
  align-items: baseline;
  gap: 8px;
  padding: 6px 8px;
  border-bottom: 1px solid #f0f3f5;
  font-size: 13px;
}

.scan-row:last-child {
  border-bottom: 0;
}

.scan-row .mark {
  font-weight: 700;
}

.scan-row.ok .mark {
  color: var(--green);
}

.scan-row.bad .mark {
  color: var(--red);
}

/* A unit of a cancelled shipment: put back, no label - not a failure. */
.scan-row.putback .mark {
  color: #b7791f;
}

.putback-block {
  grid-column: 1 / -1;
}

.scan-row .why {
  display: block;
  color: var(--muted);
  font-size: 12px;
}

.scan-row .unit {
  color: var(--muted);
  font-size: 12px;
  white-space: nowrap;
}

.scan-summary {
  border: 1px solid var(--line);
  border-left: 3px solid var(--green);
  border-radius: 8px;
  padding: 10px 12px;
  font-size: 13px;
  background: #fbfcfd;
}

.scan-summary.is-error {
  border-left-color: var(--red);
}

.scan-summary p {
  margin: 0 0 6px;
}

.scan-summary p:last-child {
  margin-bottom: 0;
}

.scan-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}

/* ------------------------------------------- automation screenshots */

.scan-shot {
  border: 1px solid var(--line);
  border-radius: 8px;
  overflow: hidden;
  background: #fbfcfd;
}

.scan-shot a {
  display: block;
  line-height: 0;
}

.scan-shot img {
  width: 100%;
  max-height: 220px;
  object-fit: cover;
  object-position: top center;
  display: block;
}

.scan-shot small {
  display: block;
  padding: 6px 10px;
  color: var(--muted);
  font-size: 12px;
  line-height: 1.3;
}

.scan-strip {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  padding-bottom: 4px;
}

.scan-thumb {
  flex: 0 0 auto;
  line-height: 0;
  border: 2px solid var(--line);
  border-radius: 6px;
  overflow: hidden;
}

.scan-thumb.bad {
  border-color: var(--red);
}

.scan-thumb img {
  width: 72px;
  height: 46px;
  object-fit: cover;
  object-position: top center;
  display: block;
}

button.danger {
  border-color: var(--red);
  color: var(--red);
}

button.danger:hover:not(:disabled) {
  background: #fdf2f1;
}

button.danger:disabled {
  opacity: 0.6;
  cursor: default;
}

/* --------------------------------------------- picklist batch queue */

.picklist-queue {
  display: grid;
  gap: 4px;
  margin-bottom: 14px;
  max-height: 280px;
  overflow-y: auto;
}

.picklist-queue-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
  font-size: 12px;
  color: var(--muted);
}

.picklist-queue-head button {
  font-size: 12px;
  padding: 2px 8px;
}

.queue-check {
  flex: 0 0 auto;
  margin: 0 2px 0 0;
}

/* The chip is now a row holding a tick plus a button, so the grid that used to
   lay the button out moves onto .queue-pick. */
.queue-pick {
  display: grid;
  grid-template-columns: 22px auto 1fr auto;
  align-items: center;
  gap: 8px;
  flex: 1 1 auto;
  min-width: 0;
  background: none;
  border: 0;
  padding: 0;
  text-align: left;
  cursor: pointer;
  font: inherit;
  color: inherit;
}

.queue-pick .src {
  color: var(--muted);
  font-size: 12px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.queue-row {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  min-height: 34px;
  padding: 4px 8px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: #fbfcfd;
  color: var(--ink);
  font-weight: 600;
  font-size: 13px;
  text-align: left;
  cursor: pointer;
}

.queue-row.selected {
  border-color: var(--blue);
}

.queue-row .n {
  color: var(--muted);
  font-size: 12px;
}

.queue-row .qty {
  color: var(--muted);
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
}

.queue-row.running {
  border-color: var(--blue);
  background: #f2f8fc;
}

.queue-row.completed {
  border-color: var(--green);
}

.queue-row.completed .no::after {
  content: " ✓";
  color: var(--green);
}

.queue-row.stopped .no::after,
.queue-row.failed .no::after {
  content: " ✕";
  color: var(--red);
}

.scan-picklist {
  margin: 0;
  padding: 6px 10px;
  border-left: 3px solid var(--blue);
  background: #f2f8fc;
  border-radius: 0 6px 6px 0;
  font-size: 13px;
  font-weight: 700;
}


/* Run logs panel */
.logs-panel {
  margin-top: 16px;
}

.logs-panel > .muted {
  margin: 0 0 12px;
}

.logs-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 260px;
  overflow-y: auto;
}

.log-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 10px;
  border: 1px solid rgba(148, 163, 184, 0.25);
  border-radius: 8px;
}

.log-meta {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.log-meta small {
  opacity: 0.7;
}

.log-links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 8px 12px;
  white-space: nowrap;
}

.log-row {
  flex-wrap: wrap;
}

.log-zip-button {
  min-height: 28px;
  padding: 0 10px;
  font-size: 12px;
}

.log-zip-message {
  flex-basis: 100%;
  margin: 0;
  font-size: 12px;
  color: var(--muted);
}

.log-zip-message.is-error {
  color: #b42318;
}

.logs-list .empty {
  height: auto;
  margin: 0;
  padding: 14px 0;
}

.hint {
  color: var(--muted);
  font-size: 12px;
}

.result-group {
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
  padding: 8px 2px 2px;
  border-bottom: 1px solid var(--line);
  margin-bottom: 4px;
}

/* Per-picklist progress inside the scan dialog */
.scan-picklists {
  display: grid;
  gap: 6px;
  margin: 12px 0;
  max-height: 190px;
  overflow-y: auto;
}

.scan-pl {
  display: grid;
  grid-template-columns: 22px 1fr auto;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  border: 1px solid var(--line);
  border-radius: 6px;
  font-size: 13px;
}

.scan-pl .pl-bar {
  grid-column: 1 / -1;
  height: 4px;
  border-radius: 3px;
  background: rgba(148, 163, 184, 0.25);
  overflow: hidden;
}

.scan-pl .pl-bar span {
  display: block;
  height: 100%;
  width: 0;
  background: var(--blue);
}

.scan-pl .pl-counts {
  color: var(--muted);
  font-size: 12px;
  white-space: nowrap;
}

.scan-pl.running { border-color: var(--blue); background: #f2f8fc; }
.scan-pl.completed { border-color: #22c55e; }
.scan-pl.failed, .scan-pl.stopped { border-color: #ef4444; }

#resumeScanButton {
  border-color: var(--blue);
  color: var(--blue);
}

/* ---------------------------------------------------------------- side panel */

/* The panel is fixed to the left edge; the page and the bottom action bar
   start where it ends. */
body {
  padding-left: var(--side-w);
}

.side-panel {
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  z-index: 40;
  width: var(--side-w);
  display: flex;
  flex-direction: column;
  gap: 24px;
  padding: 20px 14px;
  background: var(--surface);
  border-right: 1px solid var(--line);
}

.side-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 8px;
}

.side-brand-mark {
  display: grid;
  place-items: center;
  flex: none;
  width: 36px;
  height: 36px;
  border-radius: 8px;
  background: var(--blue);
  color: #fff;
  font-size: 14px;
  font-weight: 800;
}

.side-brand-name {
  color: var(--ink);
  font-size: 14px;
  font-weight: 800;
  line-height: 1.2;
}

.side-nav {
  display: grid;
  gap: 4px;
}

.side-link {
  display: flex;
  width: 100%;
  border: 0;
  background: none;
  text-align: left;
  cursor: pointer;
  font-family: inherit;
  align-items: center;
  gap: 10px;
  min-height: 40px;
  padding: 0 10px;
  border-radius: 6px;
  color: #3f4a56;
  font-size: 14px;
  font-weight: 700;
  text-decoration: none;
}

.side-link svg {
  flex: none;
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.side-link:hover {
  background: #f1f5f8;
  color: var(--ink);
}

.side-group {
  display: grid;
  gap: 2px;
}

/* The two entries under PickLists, indented under their parent and joined to
   it by a hairline, so they read as belonging to it rather than as two more
   top-level items. */
.side-sub {
  display: grid;
  gap: 2px;
  margin: 0 0 2px 22px;
  padding-left: 10px;
  border-left: 1px solid var(--line);
}

.side-sublink {
  display: flex;
  align-items: center;
  min-height: 32px;
  padding: 0 10px;
  border-radius: 6px;
  color: var(--muted);
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
}

.side-sublink:hover { background: #f1f5f8; color: var(--ink); }

.side-sublink.is-active {
  background: #e7f0f8;
  color: var(--blue);
  font-weight: 700;
}

/* The parent is a heading while one of its children is open - marked, but not
   competing with the child for attention. */
.side-group.is-open > .side-link.is-active {
  background: none;
  box-shadow: none;
  color: var(--blue);
}

.side-link.is-active {
  background: #e7f0f8;
  color: var(--blue);
  box-shadow: inset 3px 0 0 var(--blue);
}

.side-link:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(23, 105, 170, 0.25);
}

/* Delay and Extract SKUs belong to the Home page's scan. */
/* Scan delay and Extract SKUs belong to Home; every other view hides them. */
/* Returns is the one page used on a phone, in a warehouse, by someone holding
   a parcel. The bottom bar is the Unicommerce login tools, which that job never
   needs, and it costs 70px of a 390px screen - so it goes, and the space it
   reserved goes with it. */
body[data-view="returns"] .action-bar {
  display: none;
}

body[data-view="returns"] .app-shell {
  padding-bottom: calc(24px + env(safe-area-inset-bottom));
}

body:not([data-view="home"]) .home-only {
  display: none !important;
}

/* ------------------------------------------------------------ picklist page */

.picklist-grid {
  display: grid;
  grid-template-columns: minmax(280px, 38%) minmax(0, 1fr);
  gap: 16px;
  align-items: start;
}

.picklist-column {
  display: grid;
  gap: 16px;
}

/* Activity fills the right-hand column, so with it hidden the settings panel
   would sit at 38% width with dead space beside it. One column instead - and
   it goes back to two on its own the moment Activity is shown again. */
.picklist-grid:has(> .create-activity-panel[hidden]) {
  grid-template-columns: minmax(0, 1fr);
}

.settings-panel,
.create-panel,
.create-activity-panel {
  padding: 18px;
}

.settings-panel {
  display: grid;
  gap: 14px;
}

.settings-panel .section-heading {
  margin-bottom: 0;
}

.schedule-line {
  margin: -4px 0 0;
  padding: 8px 10px;
  border-radius: 6px;
  background: #eef4f1;
  color: #2c5c47;
  font-size: 13px;
  line-height: 1.5;
}

.schedule-line.is-off {
  background: #f1f3f5;
  color: var(--muted);
}

/* ---------------------------------------------------------- scheduled run */

.schedule-panel {
  padding: 18px;
  margin-bottom: 16px;
}

.run-state {
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 4px 10px;
  background: #f1f3f5;
  color: var(--muted);
  font-size: 13px;
  white-space: nowrap;
}

.run-state.is-running {
  border-color: #b9d4ea;
  background: #e7f0f8;
  color: var(--blue);
}

.run-state.is-done { border-color: #bcd9cb; background: #eef4f1; color: var(--green); }
.run-state.is-error { border-color: #e0b4ae; background: #fbecea; color: var(--red); }

.schedule-next {
  margin: -4px 0 14px;
  padding: 8px 10px;
  border-radius: 6px;
  background: #f7f9fb;
  color: #3f4a56;
  font-size: 13px;
}

.run-steps {
  display: grid;
  gap: 2px;
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: none;
}

.run-step {
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr);
  gap: 12px;
  padding: 10px 0;
  position: relative;
}

/* The line joining the steps, drawn behind the markers. */
.run-step:not(:last-child)::before {
  content: "";
  position: absolute;
  left: 14px;
  top: 34px;
  bottom: -4px;
  width: 2px;
  background: var(--line);
}

.run-step-mark {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border: 2px solid var(--line);
  border-radius: 50%;
  background: var(--surface);
  color: var(--muted);
  font-size: 13px;
  font-weight: 700;
  z-index: 1;
}

.run-step-body {
  display: grid;
  gap: 4px;
  min-width: 0;
}

.run-step-body strong { font-size: 14px; color: #3f4a56; }
.run-step-detail { color: var(--muted); font-size: 13px; }

.run-step-bar {
  height: 4px;
  border-radius: 999px;
  background: #eef1f4;
  overflow: hidden;
}

.run-step-bar span {
  display: block;
  width: 0;
  height: 100%;
  border-radius: 999px;
  background: var(--blue);
  transition: width 0.3s ease;
}

/* Waiting steps stay quiet; the one in flight is the only blue thing. */
.run-step.is-active .run-step-mark {
  border-color: var(--blue);
  background: var(--blue);
  color: #fff;
}

.run-step.is-active .run-step-body strong { color: var(--ink); }

/* A ring around the step in flight, so "what is happening now" is findable
   without reading any of it. */
.run-step.is-active .run-step-mark::after {
  content: "";
  position: absolute;
  width: 40px;
  height: 40px;
  border: 2px solid transparent;
  border-top-color: var(--blue);
  border-radius: 50%;
  animation: scan-spin 1s linear infinite;
}

.run-step.is-active .run-step-mark { position: relative; }

@media (prefers-reduced-motion: reduce) {
  .run-step.is-active .run-step-mark::after { animation-duration: 3s; }
}

.schedule-next.is-running {
  border-left: 3px solid var(--blue);
  background: #f4f9fd;
  color: var(--ink);
  font-weight: 600;
}

.run-step.is-done .run-step-mark {
  border-color: var(--green);
  background: var(--green);
  color: #fff;
}

.run-step.is-done .run-step-bar span { background: var(--green); }

.run-step.is-failed .run-step-mark {
  border-color: var(--red);
  background: var(--red);
  color: #fff;
}

.run-step.is-failed .run-step-detail { color: var(--red); }

.run-step-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}

.run-step-count {
  color: var(--muted);
  font-size: 12px;
  font-weight: 700;
  white-space: nowrap;
}

.run-step.is-active .run-step-count { color: var(--blue); }
.run-step.is-done .run-step-count { color: var(--green); }

/* Which picklists exist so far. */
.run-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 6px;
}

.run-chip {
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 2px 9px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.01em;
}

.run-chip.is-done { border-color: #bcd9cb; background: #eef4f1; color: var(--green); }
.run-chip.is-waiting { border-style: dashed; color: var(--muted); font-weight: 600; }

/* One row per picklist being scanned. */
.run-picklists {
  display: grid;
  gap: 4px;
  margin-top: 8px;
}

.run-pl {
  display: grid;
  grid-template-columns: minmax(72px, auto) minmax(70px, auto) minmax(0, 1fr) auto;
  grid-template-areas: "no units result status" "bar bar bar bar";
  align-items: center;
  gap: 4px 10px;
  padding: 6px 8px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: #fbfcfd;
  font-size: 12px;
}

.run-pl-no { grid-area: no; font-weight: 700; color: #3f4a56; }
.run-pl-units { grid-area: units; color: var(--muted); }
.run-pl-result { grid-area: result; }
.run-pl-status { grid-area: status; color: var(--muted); text-transform: capitalize; }

.run-pl-bar {
  grid-area: bar;
  height: 3px;
  border-radius: 999px;
  background: #eef1f4;
  overflow: hidden;
}

.run-pl-bar > span {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--blue);
  transition: width 0.3s ease;
}

/* The one being scanned is the only row that stands out. */
.run-pl.running {
  border-color: #b9d4ea;
  background: #f4f9fd;
}

.run-pl.running .run-pl-status { color: var(--blue); font-weight: 700; }
.run-pl.done { background: #fbfdfc; }
.run-pl.done .run-pl-bar > span { background: var(--green); }
.run-pl.done .run-pl-status { color: var(--green); }
.run-pl.failed { border-color: #e0b4ae; background: #fdf7f6; }
.run-pl.failed .run-pl-status { color: var(--red); font-weight: 700; }
.run-pl.waiting { opacity: 0.75; }

.run-step-links {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 6px;
}

.run-step-links .button-link { min-height: 30px; padding: 0 10px; font-size: 13px; }

/* ----------------------------------------------------------- settings dialog */

.settings-dialog {
  width: min(560px, 100%);
  gap: 12px;
}

.settings-dialog .scan-dialog-head p {
  margin: 4px 0 0;
  font-size: 13px;
}

.settings-dialog-form {
  display: grid;
  gap: 14px;
}

/* The dialog has its own Close row, so Save sits with the fields rather than
   stretching across the bottom of the panel it used to live in. */
.settings-dialog-form .primary {
  justify-self: start;
  padding: 0 18px;
}

/* ------------------------------------------------------------ day folders */

.folders-panel { padding: 0; overflow: hidden; }

.folders-layout {
  display: grid;
  grid-template-columns: minmax(200px, 250px) minmax(0, 1fr);
  align-items: stretch;
  min-height: 420px;
}

/* The days, down the left. */
.folder-list {
  display: flex;
  flex-direction: column;
  padding: 12px;
  border-right: 1px solid var(--line);
  background: #fbfcfd;
  max-height: 72vh;
  overflow: hidden;
}

/* Only the day buttons scroll, so "Load more" stays put at the bottom. */
#folderGrid {
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}

.folder-item {
  display: grid;
  grid-template-columns: 26px minmax(0, 1fr);
  gap: 10px;
  min-height: 0;
  padding: 9px 10px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: none;
  text-align: left;
  cursor: pointer;
}

.folder-item:hover { background: #eef2f6; }

/* The selected day, marked down its edge rather than shouted. */
.folder-item.is-selected {
  border-color: #b9d4ea;
  background: var(--surface);
  box-shadow: inset 3px 0 0 var(--blue);
}

.folder-icon { align-self: center; color: #c9922b; }

.folder-icon svg {
  width: 22px;
  height: 22px;
  fill: #fdf6e6;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linejoin: round;
}

/* A day with a failure is marked on its folder, so a bad day is findable
   without opening seven of them. */
.folder-item.has-failures .folder-icon { color: var(--red); }
.folder-item.has-failures .folder-icon svg { fill: #fdf1ef; }

.folder-text { display: flex; align-items: center; min-width: 0; }

.folder-name {
  font-size: 14px;
  font-weight: 700;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.folder-item.is-selected .folder-name { color: var(--blue); }

.folder-more-button {
  flex: 0 0 auto;
  margin-top: 8px;
  min-height: 32px;
  font-size: 12px;
}

/* The selected day's runs, on the right. */
.folder-detail {
  padding: 16px 18px;
  max-height: 72vh;
  overflow-y: auto;
}

.folder-detail .processed-day { margin-top: 0; }

@media (max-width: 860px) {
  .folders-layout { grid-template-columns: minmax(0, 1fr); }
  .folder-list {
    border-right: 0;
    border-bottom: 1px solid var(--line);
    max-height: 240px;
  }
}

/* ------------------------------------------------------- processed picklist */

.processed-panel {
  margin-top: 16px;
  overflow: hidden;
  padding-bottom: 6px;
}

.processed-panel > .section-heading {
  padding: 16px 18px 0;
}

.processed-tools {
  display: flex;
  align-items: center;
  gap: 8px;
}

.check-row.is-compact {
  padding: 5px 9px;
  font-size: 13px;
  font-weight: 600;
}

/* Created but not yet scanned. Normally empty, so it only takes room when
   there is something to say. */
.waiting-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 0 18px 12px;
  padding: 10px 12px;
  border: 1px dashed #c8b88a;
  border-radius: 8px;
  background: #fdfaf1;
}

.waiting-label {
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  color: #8a6d1f;
}

.waiting-chip {
  border: 1px solid #d9cfae;
  border-radius: 999px;
  padding: 3px 10px;
  background: #fff;
  color: var(--ink);
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
}

.processed-days {
  display: grid;
  gap: 14px;
  padding: 0 18px 14px;
  max-height: 70vh;
  overflow-y: auto;
}

.processed-days .empty {
  color: var(--muted);
  padding: 10px 0;
}

.processed-day-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--line);
  margin-bottom: 8px;
}

.processed-day-head h3 {
  margin: 0;
  font-size: 14px;
}

.processed-day-counts {
  font-size: 13px;
  color: var(--muted);
}

.processed-batch-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin: 10px 0 6px;
  font-size: 12px;
}

.batch-name {
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: #3f4a56;
}

.batch-counts { color: var(--muted); }

/* On the Processed PickList page a run header is a heading and one button. */
.processed-batch-head { align-items: center; }

.batch-download {
  min-height: 30px;
  padding: 0 14px;
  margin-left: auto;
  font-size: 13px;
}

.batch-links {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-left: auto;
}

.waiting-chip.is-error {
  border-color: #e0b4ae;
  background: #fbecea;
  color: var(--red);
}

.waiting-errors {
  display: grid;
  gap: 3px;
  width: 100%;
  margin: 2px 0 0;
  font-size: 12px;
  color: #8a3227;
}

.processed-run {
  border: 1px solid var(--line);
  border-left: 3px solid var(--green);
  border-radius: 8px;
  background: #fff;
  margin-bottom: 8px;
  overflow: hidden;
}

.processed-run.partial { border-left-color: #c9922b; }
.processed-run.failed  { border-left-color: var(--red); }
.processed-run.stopped { border-left-color: var(--muted); }

.processed-run-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 0;
  border: 0;
  border-radius: 0;
  padding: 10px 12px;
  background: none;
  text-align: left;
  font-weight: 600;
  color: var(--ink);
}

.processed-run-head:hover { background: #f7f9fb; }

.run-caret { color: var(--muted); }
.run-no { font-weight: 700; }
.run-time, .run-duration, .run-units { color: var(--muted); font-weight: 500; font-size: 13px; }

.run-status {
  margin-left: auto;
  border-radius: 999px;
  padding: 2px 10px;
  background: #eef4f1;
  color: var(--green);
  font-size: 12px;
  text-transform: capitalize;
}

.processed-run.partial .run-status { background: #fbf3e3; color: #8a6d1f; }
.processed-run.failed .run-status  { background: #fbecea; color: var(--red); }
.processed-run.stopped .run-status { background: #f1f3f5; color: var(--muted); }

.run-batch {
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 2px 8px;
  font-size: 11px;
  color: var(--muted);
  text-transform: uppercase;
}

.run-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 0 12px 10px;
}

.run-actions .button-link,
.run-actions button {
  min-height: 30px;
  padding: 0 10px;
  font-size: 13px;
}

.run-actions .button-link.is-primary {
  border-color: var(--blue);
  background: var(--blue);
  color: #fff;
}

.run-detail {
  border-top: 1px solid var(--line);
  padding: 12px;
  background: #fbfcfd;
}

.run-detail h4 {
  margin: 12px 0 6px;
  font-size: 13px;
}

.run-detail h4:first-child { margin-top: 0; }

.run-note { margin: 0 0 8px; font-size: 13px; color: var(--muted); }
.run-note.is-error { color: var(--red); }
.run-email { margin: 0 0 8px; font-size: 13px; }

.sku-table {
  width: 100%;
  min-width: 520px;
  border-collapse: collapse;
  font-size: 13px;
}

.sku-table th,
.sku-table td {
  border-bottom: 1px solid var(--line);
  padding: 6px 8px;
  text-align: left;
}

.run-passed, .run-log { margin-top: 10px; font-size: 13px; }
.run-passed summary, .run-log summary { cursor: pointer; font-weight: 600; }

.run-log pre {
  max-height: 260px;
  overflow: auto;
  margin: 8px 0 0;
  padding: 10px;
  border-radius: 6px;
  background: #0f1720;
  color: #d7e2ea;
  font-size: 12px;
  line-height: 1.5;
}

.run-merged { margin: 0; padding-left: 18px; font-size: 13px; }

.shot-strip {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  padding-bottom: 4px;
}

.shot-strip img {
  height: 90px;
  border: 1px solid var(--line);
  border-radius: 6px;
}

/* --------------------------------------------------------- pending picklist */

.pending-panel {
  margin-top: 16px;
  overflow: hidden;
}

.pending-panel > .section-heading,
.pending-note {
  padding: 0 18px;
}

.pending-panel > .section-heading {
  padding-top: 16px;
}

.pending-note {
  margin: -6px 0 12px;
  font-size: 13px;
}

.pending-heading {
  display: flex;
  align-items: center;
  gap: 10px;
}

.pending-badge {
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 4px 10px;
  background: #eef4f1;
  color: var(--green);
  font-size: 13px;
  white-space: nowrap;
}

.pending-table-wrap {
  max-height: 60vh;
}

.pending-table {
  min-width: 560px;
}

.pending-table td:first-child,
.pending-table th:first-child {
  width: 56px;
  color: var(--muted);
}

/* One header row per day, sitting between the days' picklists. */
.pending-table .pending-day th {
  position: static;
  padding: 9px 12px;
  background: #f6f8fa;
  color: var(--ink);
  font-size: 13px;
  text-align: left;
  text-transform: none;
}

.pending-day-count {
  margin-left: 8px;
  color: var(--muted);
  font-weight: 600;
}

.pending-table td {
  vertical-align: middle;
}

.pending-table a.pending-code {
  color: var(--blue);
  font-weight: 800;
  text-decoration: none;
}

.pending-table a.pending-code:hover {
  text-decoration: underline;
}

.pending-table a.pending-open {
  display: inline-flex;
  align-items: center;
  min-height: 30px;
  padding: 0 10px;
  border: 1px solid var(--blue);
  border-radius: 6px;
  color: var(--blue);
  font-size: 13px;
  font-weight: 700;
  text-decoration: none;
}

.pending-table a.pending-open:hover {
  background: #e7f0f8;
}

/* ------------------------------------------------------------- time picker */
/* Hour / Minutes / AM-PM columns; minutes in 10-minute steps. The toggle is
   styled to look like the other inputs, not like a button. */
.time-picker {
  position: relative;
}

.time-picker-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  min-height: 38px;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: #fff;
  color: var(--ink);
  font-weight: 400;
  text-align: left;
}

.time-picker-toggle.is-empty .time-picker-value {
  color: var(--muted);
}

.time-picker-toggle svg {
  flex: none;
  width: 18px;
  height: 18px;
  fill: none;
  stroke: var(--muted);
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.time-picker-toggle:focus-visible,
.time-picker-toggle[aria-expanded="true"] {
  outline: none;
  border-color: var(--blue);
  box-shadow: 0 0 0 3px rgba(23, 105, 170, 0.15);
}

.time-picker-panel {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  z-index: 50;
  display: grid;
  grid-template-columns: repeat(3, minmax(64px, auto));
  gap: 4px;
  min-width: 100%;
  padding: 6px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface);
  box-shadow: 0 12px 32px rgba(31, 41, 51, 0.16);
}

.time-picker-column {
  display: grid;
  align-content: start;
  gap: 2px;
  max-height: 224px;
  overflow-y: auto;
  padding-right: 2px;
  scrollbar-width: thin;
}

.time-picker-column + .time-picker-column {
  border-left: 1px solid var(--line);
  padding-left: 4px;
}

.time-picker-option {
  min-height: 32px;
  padding: 0 12px;
  border: 0;
  border-radius: 4px;
  background: transparent;
  color: var(--ink);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.time-picker-option:hover {
  background: #f1f5f8;
}

.time-picker-option:focus-visible {
  outline: none;
  box-shadow: inset 0 0 0 2px rgba(23, 105, 170, 0.45);
}

.time-picker-option.is-selected {
  background: var(--blue);
  color: #fff;
}

.time-picker-footer {
  grid-column: 1 / -1;
  display: flex;
  justify-content: flex-end;
  padding-top: 6px;
  border-top: 1px solid var(--line);
}

.time-picker-done {
  min-height: 32px;
}

/* --------------------------------------------- Debug: create-flow switches */

.debug-settings-panel { margin-bottom: 16px; }

/* A row that reads as one control: the box, its name, and why you would turn
   it off - all clickable, because the whole row is the label. */
/* `label` is uppercased app-wide for field captions; this row is a sentence. */
.switch-row,
.switch-row * {
  text-transform: none;
  letter-spacing: normal;
}

.switch-row {
  display: grid;
  grid-template-columns: 18px minmax(0, 1fr);
  gap: 10px;
  align-items: start;
  padding: 12px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: #fbfcfd;
  cursor: pointer;
}

.switch-row:hover { border-color: #c6d6e3; }

.switch-row input[type="checkbox"] {
  width: 17px;
  height: 17px;
  margin: 1px 0 0;
  accent-color: var(--blue);
  cursor: pointer;
}

.switch-text { display: grid; gap: 3px; min-width: 0; }
.switch-label { font-size: 14px; font-weight: 700; color: var(--ink); }

.switch-help {
  font-size: 12px;
  line-height: 1.5;
  color: var(--muted);
}

.save-note {
  font-size: 12px;
  font-weight: 700;
  color: var(--muted);
  white-space: nowrap;
}

.save-note.error { color: var(--red); }

.settings-state {
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 6px 10px;
  background: #f4f6f8;
  color: var(--muted);
  font-size: 13px;
  white-space: nowrap;
}

.settings-state.is-saved {
  background: #eef4f1;
  color: var(--green);
}

.settings-state.is-dirty {
  border-color: #ecd9a8;
  background: #fff8e8;
  color: var(--amber);
}

.settings-state.is-error {
  border-color: #f1c4bf;
  background: #fdf1f0;
  color: var(--red);
}

.settings-message {
  font-size: 13px;
  color: var(--muted);
}

.settings-message.is-error {
  color: var(--red);
}

#picklistSettingsSave {
  justify-self: start;
  min-width: 180px;
}

.create-panel {
  display: grid;
  gap: 14px;
}

.create-panel .section-heading {
  margin-bottom: 0;
}

.create-steps {
  display: grid;
  gap: 8px;
  margin: 0;
  padding-left: 20px;
  font-size: 14px;
}

.create-steps li::marker {
  color: var(--blue);
  font-weight: 700;
}

.create-button {
  justify-self: start;
  min-width: 180px;
}

.create-result {
  display: grid;
  gap: 4px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-left-width: 4px;
  border-radius: 6px;
  font-size: 14px;
}

.create-result-line:first-child {
  font-weight: 800;
}

.create-result a {
  color: var(--blue);
  font-weight: 700;
}

.create-result.is-ok {
  border-color: #cfe3d3;
  border-left-color: var(--green);
  background: #f2f8f3;
}

.create-result.is-warn {
  border-color: #ecd9a8;
  border-left-color: var(--amber);
  background: #fff8e8;
}

.create-result.is-bad {
  border-color: #f1c4bf;
  border-left-color: var(--red);
  background: #fdf1f0;
}

.create-activity {
  max-height: 60vh;
  overflow: auto;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #fbfcfd;
}

.create-activity .empty {
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0;
}

.create-activity-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 10px;
  padding: 8px 10px;
  border-top: 1px solid var(--line);
  font-size: 13px;
  overflow-wrap: anywhere;
}

.create-activity-row:first-child {
  border-top: 0;
}

.create-activity-row time {
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.create-activity-row.is-ok span {
  color: var(--green);
}

.create-activity-row.is-bad span {
  color: var(--red);
}

/* The hamburger. Only ever visible once the nav has moved into the drawer. */
.nav-toggle {
  display: none;
  place-items: center;
  flex: none;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface);
  color: #3f4a56;
  cursor: pointer;
}

.nav-toggle svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
  stroke-linecap: round;
}

.nav-scrim {
  position: fixed;
  inset: 0;
  z-index: 50;
  background: rgba(17, 24, 31, 0.45);
}

/* Narrow screens: the side panel becomes a bar across the top and the nav
   slides out from the left. It used to stay in the bar as a flex row, which
   on a phone was wider than the screen - the two PickLists sub-links alone
   pushed it past 414px - and left the whole page scrolling sideways. */
@media (max-width: 900px) {
  :root {
    --side-w: 0px;
  }

  body {
    padding-left: 0;
  }

  .side-panel {
    position: sticky;
    top: 0;
    bottom: auto;
    /* Above the scrim, not below it. The drawer is a CHILD of this element,
       and a positioned parent with a z-index makes its own stacking context -
       so the drawer's z-index is measured inside this one, and at 40 the whole
       panel sat under the scrim. Every tap went to the scrim instead, which
       closed the drawer and looked like the links were dead. Keeping the bar
       above the scrim is right anyway: the hamburger stays usable to close. */
    z-index: 60;
    width: auto;
    flex-direction: row;
    align-items: center;
    gap: 10px;
    /* env() is 0 everywhere that has no notch, so this is safe as the only rule. */
    padding: 8px 12px;
    padding-top: calc(8px + env(safe-area-inset-top));
    border-right: 0;
    border-bottom: 1px solid var(--line);
  }

  .nav-toggle {
    display: grid;
  }

  .side-brand {
    padding: 0;
  }

  .side-brand-name {
    display: none;
  }

  .side-footer {
    margin: 0 0 0 auto;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 0;
    border-top: 0;
  }

  .side-user {
    max-width: 90px;
  }

  /* The drawer itself: off screen until body.nav-open, above the scrim. */
  .side-nav {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    /* Inside .side-panel's stacking context; it only has to clear the brand
       and the footer beside it, not the scrim. */
    z-index: 1;
    width: min(286px, 84vw);
    display: grid;
    align-content: start;
    gap: 4px;
    padding: 16px 12px;
    padding-top: calc(16px + env(safe-area-inset-top));
    padding-bottom: calc(16px + env(safe-area-inset-bottom));
    overflow-y: auto;
    background: var(--surface);
    border-right: 1px solid var(--line);
    box-shadow: 0 0 40px rgba(31, 41, 51, 0.18);
    transform: translateX(-100%);
    transition: transform 0.22s ease;
  }

  body.nav-open .side-nav {
    transform: none;
  }

  /* Comfortable to hit with a thumb. */
  .side-link { min-height: 46px; font-size: 15px; }
  .side-sublink { min-height: 40px; font-size: 14px; }

  .picklist-grid {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 900px) and (prefers-reduced-motion: reduce) {
  .side-nav { transition: none; }
}

/* Phones. Everything here is about thumbs and about not scrolling sideways. */
@media (max-width: 640px) {
  .app-shell {
    /* 100vw counts the scrollbar on some browsers and overflowed by a few
       pixels; a percentage of the body cannot. */
    width: calc(100% - 24px);
    padding: 12px 0 calc(90px + env(safe-area-inset-bottom));
  }

  h1 { font-size: 22px; }
  .topbar { margin-bottom: 12px; gap: 8px; }
  .topbar-pills { flex-wrap: wrap; }

  .controls-panel,
  .summary-panel,
  .results-panel,
  .logs-panel,
  .shipments-panel,
  .returns-panel {
    padding: 14px;
  }

  .section-heading { flex-wrap: wrap; gap: 8px; }

  /* 16px or iOS zooms the page in when the field takes focus, and the layout
     is left scrolled sideways afterwards. */
  input,
  select,
  textarea {
    font-size: 16px;
  }

  button,
  .button-link {
    min-height: 42px;
  }

  /* Wide data tables still scroll inside their wrapper rather than stretching
     the page, but 1180px of minimum is a lot of dragging on a phone. */
  table { min-width: 680px; }
  .table-wrap { max-height: 60vh; }

  .action-bar {
    padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
    flex-wrap: wrap;
    justify-content: stretch;
  }

  .action-bar button,
  .action-bar .button-link {
    flex: 1 1 0;
    min-width: 0;
    font-size: 13px;
  }

  /* The helper is a Chrome extension you install on a computer; offering it on
     a phone spent a whole row of a bar that is already pinned over the page. */
  .action-bar .extension-tools {
    display: none;
  }

  .summary-list { grid-template-columns: minmax(0, 1fr); gap: 10px; }
}

/* ------------------------------------ Settings: scheduler switched off */
.settings-dialog-form .switch-row { margin-bottom: 4px; }

.schedule-disabled-notice {
  margin: 0;
  padding: 8px 10px;
  border: 1px solid #ecd9a8;
  border-radius: 6px;
  background: #fff8e8;
  color: #7a5a12;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.5;
}

.settings-dialog-form :disabled,
.check-row.is-disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

/* ------------------------------------------------ Settings: data cleanup */
.settings-dialog-form { overflow-y: auto; min-height: 0; padding-right: 2px; }

.settings-section {
  display: grid;
  gap: 10px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}

.settings-section h3 {
  margin: 0;
  font-size: 15px;
}

.cleanup-days-field input { max-width: 140px; }

.cleanup-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.cleanup-preview {
  border: 1px solid var(--line);
  border-radius: 6px;
  background: #f8fafb;
  padding: 10px 12px;
  font-size: 13px;
  max-height: 260px;
  overflow-y: auto;
}

.cleanup-preview.is-error { border-color: #f1c4bf; background: #fdf1f0; color: var(--red); }
.cleanup-preview.is-done { border-color: #cfe3d4; background: #eef4f1; color: var(--green); }

.cleanup-preview .cleanup-total { margin: 0 0 8px; font-weight: 700; }

.cleanup-preview details { margin: 6px 0; }

.cleanup-preview summary { cursor: pointer; font-weight: 600; }

.cleanup-preview ul {
  margin: 6px 0 0;
  padding-left: 18px;
  color: var(--muted);
}

.cleanup-preview li { overflow-wrap: anywhere; }

.cleanup-preview .cleanup-day { color: var(--ink); font-variant-numeric: tabular-nums; }

/* Home Run Logs: the Debug run cards (.processed-run), in a taller list. */
.logs-list { gap: 0; max-height: none; overflow: visible; }
.logs-list .processed-run.log-row {
  display: block;
  flex-shrink: 0; /* the list is a flex column: never squash a card */
  padding: 0;
  border-radius: 8px;
  border: 1px solid var(--line);
  border-left: 3px solid var(--green);
}
.logs-list .processed-run.partial { border-left-color: #c9922b; }
.logs-list .processed-run.failed  { border-left-color: var(--red); }
.logs-list .processed-run.stopped,
.logs-list .processed-run.create  { border-left-color: var(--muted); }
.processed-run-head.is-static { cursor: default; }
.processed-run-head.is-static:hover { background: none; }
.run-actions .log-zip-button { min-height: 30px; padding: 0 10px; font-size: 13px; }
.logs-list .log-zip-message { padding: 0 12px 10px; }
.logs-list .run-actions.log-links { justify-content: flex-start; align-items: center; gap: 8px 14px; white-space: normal; }
.logs-list .run-actions.log-links a { font-size: 13px; font-weight: 600; }
/* Links on the left, the two ZIP buttons pushed to the right. */
.logs-list .run-actions.log-links .log-zip-button:first-of-type { margin-left: auto; }

/* ---------------------------------------------------------- shipments page */
.shipments-panel { padding: 18px; margin-bottom: 16px; }
.shipments-search { display: flex; gap: 10px; align-items: stretch; max-width: 560px; }
.shipments-search input { flex: 1 1 auto; min-width: 0; padding: 0 12px; border-radius: 6px; }
.shipments-search button { flex: 0 0 auto; min-width: 110px; }
.shipments-hint { font-size: 13px; }
.shipments-error { margin: 0 0 12px; padding: 8px 10px; border-radius: 6px; background: #fbecea; color: var(--red); font-size: 13px; }
.shipments-now { color: var(--blue); font-size: 12px; font-weight: 600; overflow-wrap: anywhere; }
.shipments-list { margin-top: 6px; }
.shipments-list summary { cursor: pointer; color: var(--blue); font-size: 13px; font-weight: 700; }
.shipments-table-wrap { max-height: 360px; margin-top: 8px; border: 1px solid var(--line); border-radius: 6px; }
.shipments-table { min-width: 0; }
.shipments-table th, .shipments-table td { padding: 8px 10px; vertical-align: middle; }
.shipments-table tr:first-child td { border-top: 0; }
.shipments-table td:last-child, .shipments-table th:last-child { text-align: right; }
.shipments-actions { display: flex; justify-content: flex-end; gap: 8px; flex-wrap: wrap; }
.shipments-actions .button-link, .run-step-links .button-link { min-height: 32px; padding: 0 12px; font-size: 13px; }
a.button-link.is-primary { background: var(--blue); color: #fff; }
.shipment-status { display: inline-block; padding: 2px 8px; border-radius: 999px; font-size: 12px; font-weight: 700; background: #f1f3f5; color: var(--muted); text-transform: capitalize; }
.shipment-status.is-downloading, .shipment-status.is-running { background: #e7f0f8; color: var(--blue); }
.shipment-status.is-done { background: #eef4f1; color: var(--green); }
.shipment-status.is-failed, .shipment-status.is-interrupted { background: #fbecea; color: var(--red); }
@media (max-width: 640px) {
  .shipments-search { flex-direction: column; }
}
.shipments-refresh { min-height: 32px; padding: 0 12px; font-size: 13px; }
/* Cards with failed SKUs open on click. */
.logs-list .processed-run:has([data-log-detail]) { cursor: pointer; }
.logs-list .processed-run:has([data-log-detail]) .processed-run-head.is-static:hover { background: #f7f9fb; }
.logs-list .run-detail[hidden] { display: none; }
.logs-list .run-detail { cursor: auto; }


/* ---------------------------------------------------------------- sign-in */

/* The login page. Standalone - it does not load app.js or the sidebar. */
.login-body {
  display: grid;
  place-items: center;
  padding: 24px;
}

.login-card {
  width: min(360px, 100%);
  display: grid;
  gap: 18px;
  padding: 26px 24px 28px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 10px;
  box-shadow: var(--shadow);
}

.login-brand {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* Its own class rather than .side-brand-name: that one is hidden below 900px,
   where the side panel becomes a top bar - and the login page has no panel. */
.login-brand-name {
  color: var(--ink);
  font-size: 14px;
  font-weight: 800;
  line-height: 1.2;
}

.login-form {
  display: grid;
  gap: 14px;
}

.login-form button.primary {
  margin-top: 4px;
  width: 100%;
}

.login-error {
  padding: 9px 11px;
  border: 1px solid #f0c4bf;
  border-radius: 6px;
  background: #fdf0ee;
  color: var(--red);
  font-size: 13px;
  font-weight: 600;
}

/* Who is signed in, pinned under the nav. */
.side-footer {
  margin-top: auto;
  display: grid;
  gap: 8px;
  padding: 12px 10px 4px;
  border-top: 1px solid var(--line);
}

.side-user {
  color: var(--muted);
  font-size: 12px;
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.side-logout {
  border: 1px solid var(--line);
  border-radius: 6px;
  background: none;
  padding: 7px 10px;
  color: #3f4a56;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
}

.side-logout:hover {
  background: #eef2f5;
}

.topbar-pills {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  justify-content: flex-end;
}

/* AUTH DISABLED: impossible to miss, because it means the app is open. */
.status-pill.pill-danger {
  border-color: #f0c4bf;
  background: #fdf0ee;
  color: var(--red);
  font-weight: 800;
  letter-spacing: 0.04em;
}

/* ----------------------------------------------------------- returns */
.returns-panel { padding: 18px; margin-bottom: 16px; }
.returns-error { margin: 12px 0 0; padding: 8px 10px; border-radius: 6px; background: #fbecea; color: var(--red); font-size: 13px; }
.returns-hint { margin: 10px 0 0; font-size: 13px; }
.run-state.is-open { border-color: #bcd9cb; background: #eef4f1; color: var(--green); }

/* Camera on the left, the read-out and the input on the right; they stack on
   a phone, which is where this page mostly lives. */
.returns-live {
  display: grid;
  grid-template-columns: minmax(240px, 380px) minmax(0, 1fr);
  gap: 16px;
  margin-top: 16px;
}

/* overflow:hidden so the lock-on box is cropped with the video when a barcode
   sits at the very edge of the frame. */
.returns-camera-frame { position: relative; overflow: hidden; border-radius: 8px; }
.returns-camera video {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  /* Keeps the viewfinder off the whole screen on a phone, where the strip and
     the counts have to stay in sight while scanning. */
  max-height: min(48vh, 340px);
  border-radius: 8px;
  border: 1px solid var(--line);
  background: #11181f;
  object-fit: cover;
}
.returns-camera-overlay {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: 12px;
  border-radius: 8px;
  color: #e8eef3;
  background: rgba(17, 24, 31, 0.72);
  font-size: 13px;
  text-align: center;
}
/* ------------------------------------------- seeing a barcode get taken
   Three beats, in order: the lock-on box says "this one, here"; a token flies
   from it down to the strip; the chip it lands on pulses. Nobody watches the
   screen while scanning a good run, but when a count comes out wrong this is
   what shows whether the label was read at all, and which of two codes on it
   the camera took.

   Only a barcode that was ACTUALLY ADDED gets this. A repeat and a price or SKU
   code do nothing at all - no box, no flight, no sound - because a picker
   sweeping a trolley would set them off constantly and the animation would stop
   meaning anything. */
.returns-lock {
  position: absolute;
  border: 2px solid var(--green);
  border-radius: 4px;
  box-shadow: 0 0 0 9999px rgba(17, 24, 31, 0.28);
  pointer-events: none;
}
.returns-lock.is-on { animation: returns-lock-in 220ms ease-out; }
@keyframes returns-lock-in {
  from { opacity: 0; transform: scale(1.35); }
  to { opacity: 1; transform: scale(1); }
}

/* Fixed, and on the body rather than inside the frame, because it has to leave
   the viewfinder and cross whatever sits between it and the strip. */
.returns-fly {
  position: fixed;
  z-index: 70;
  max-width: 220px;
  padding: 4px 9px;
  border-radius: 999px;
  border: 1px solid var(--green);
  background: #eaf4ee;
  color: var(--ink);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  pointer-events: none;
  box-shadow: 0 6px 16px rgba(17, 24, 31, 0.22);
}

.returns-last.is-landing { animation: returns-land 420ms ease-out; }
@keyframes returns-land {
  0% { transform: scale(0.6); box-shadow: 0 0 0 6px rgba(60, 125, 70, 0.35); }
  60% { transform: scale(1.06); }
  100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(60, 125, 70, 0); }
}

@media (prefers-reduced-motion: reduce) {
  /* The flight is skipped in JS; the lock-on and the pulse stay, without
     movement, because they are the part that carries the information. */
  .returns-lock.is-on { animation: none; }
  .returns-last.is-landing { animation: none; box-shadow: 0 0 0 3px rgba(60, 125, 70, 0.45); }
}

.returns-camera-bar { display: flex; gap: 8px; align-items: center; margin-top: 8px; flex-wrap: wrap; }
.returns-camera-bar button { flex: 1 1 auto; }

/* The overlay carries a two-line message, and while there is no live
   viewfinder it is also the tap target that opens the phone's camera. */
.returns-camera-overlay { white-space: pre-line; }
.returns-camera-overlay.is-tappable { cursor: pointer; }
.returns-camera-overlay.is-tappable:hover { background: rgba(17, 24, 31, 0.8); }

.returns-photo-note {
  margin: 8px 0 0;
  padding: 7px 10px;
  border-radius: 6px;
  background: #f1f3f5;
  color: var(--muted);
  font-size: 13px;
}
.returns-photo-note[data-kind="ok"] { background: #eef4f1; color: var(--green); }
.returns-photo-note[data-kind="miss"] { background: #fdf6e9; color: var(--amber); }
.returns-photo-note[data-kind="busy"] { background: #e7f0f8; color: var(--blue); }
.returns-camera-bar select { flex: 1 1 auto; min-width: 0; height: 32px; border: 1px solid var(--line); border-radius: 6px; background: var(--surface); color: var(--ink); }

.returns-entry { display: flex; flex-direction: column; gap: 12px; min-width: 0; }

/* The thing a packer actually looks at: the last barcode, big. */
.returns-last {
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-left: 4px solid var(--line);
  border-radius: 8px;
  background: #f7f9fb;
}
.returns-last[data-state="ok"] { border-left-color: var(--green); background: #f1f7f3; }
.returns-last[data-state="duplicate"] { border-left-color: var(--amber); background: #fdf6e9; }
.returns-last-label { display: block; font-size: 12px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--muted); }
.returns-last-code {
  display: block;
  margin: 4px 0 2px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: clamp(20px, 4vw, 30px);
  line-height: 1.15;
  overflow-wrap: anywhere;
}
.returns-last-meta { font-size: 12px; color: var(--muted); }
/* The courier, read off the label. Quieter than the barcode - it is a
   description of the parcel, not the thing being counted. */
.returns-last-partner {
  display: block;
  margin-top: 4px;
  font-size: 13px;
  font-weight: 600;
  color: var(--blue);
}
.returns-detail-partner {
  padding: 1px 7px;
  border-radius: 999px;
  background: #eaf1f7;
  color: var(--blue);
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
}
/* Good / Bad for the parcel in hand. It sits in the card rather than on a chip
   in a sideways list, because the card is the only place the current parcel is
   shown now. */
.returns-last-controls { margin-top: 10px; }
.returns-last-controls .returns-cond-btn { min-height: 30px; padding: 0 14px; font-size: 12px; }

.returns-manual { display: flex; gap: 10px; }
.returns-manual input { flex: 1 1 auto; min-width: 0; height: 44px; padding: 0 12px; border: 1px solid var(--line); border-radius: 6px; background: var(--surface); color: var(--ink); font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
.returns-manual input:disabled { background: #f1f3f5; color: var(--muted); }
.returns-manual button { flex: 0 0 auto; min-width: 88px; }

.returns-counts { display: flex; gap: 22px; margin: 0; }
.returns-counts div { display: flex; flex-direction: column; gap: 2px; }
.returns-counts dt { font-size: 12px; color: var(--muted); }
.returns-counts dd { margin: 0; font-size: 20px; font-weight: 700; }


/* --------------------------------------- good / bad, and what gets sent
   The same two controls sit on a live chip and on a row of an expanded batch,
   so they are styled once here and the two hosts only size them. */

/* Ticked means "send this one to the putaway". Unticked parcels stay in the
   batch and in the counts, which is why the row dims rather than disappearing:
   it was scanned, it is just not going this time. */
.returns-pick { flex: 0 0 auto; display: grid; place-items: center; cursor: pointer; }
.returns-pick input {
  width: 16px;
  height: 16px;
  margin: 0;
  accent-color: var(--blue);
  cursor: pointer;
}

/* Two buttons, never zero selected - there is no "unset" condition, because a
   default of none would mean every batch needed touching before it could go. */
.returns-cond {
  flex: 0 0 auto;
  display: inline-flex;
  border: 1px solid var(--line);
  border-radius: 6px;
  overflow: hidden;
  background: var(--surface);
}
.returns-cond-btn {
  border: 0;
  padding: 0 8px;
  min-height: 24px;
  background: transparent;
  color: var(--muted);
  font-size: 11px;
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
}
.returns-cond-btn + .returns-cond-btn { border-left: 1px solid var(--line); }
/* Colour carries the meaning at a glance down a long list: green is going back
   on the shelf, red is not. */
.returns-cond-btn.is-on { color: #fff; }
.returns-cond-btn[data-condition="good"].is-on { background: var(--green); }
.returns-cond-btn[data-condition="bad"].is-on { background: var(--red); }
.returns-cond-btn:focus-visible { outline: 2px solid var(--blue); outline-offset: -2px; }

/* The card turns when the parcel in hand is marked bad, the same way a row of
   the batch table does. */
.returns-last.is-bad { border-left-color: var(--red); background: #fdf4f3; }
.returns-detail-list li.is-held { opacity: 0.55; }
.returns-detail-list li.is-held .returns-detail-code { text-decoration: line-through; }

.returns-table tr.is-current { background: #eef4f1; }
.returns-row-actions { display: flex; gap: 6px; justify-content: flex-end; }
.returns-row-actions button { min-height: 30px; padding: 0 10px; font-size: 13px; }
/* Red on sight, not only on hover: it destroys a batch and its scans, and it
   sits next to a button you press every day. */
/* An <a>, so it needs the button's shape spelled out. */
.returns-row-log {
  display: inline-flex;
  align-items: center;
  min-height: 30px;
  padding: 0 10px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--surface);
  color: var(--muted);
  font-size: 13px;
  text-decoration: none;
  white-space: nowrap;
}
.returns-row-log:hover { color: var(--blue); border-color: #b9d3e6; background: #eef4f9; }

.returns-row-delete { color: var(--red); border-color: #e6b3ac; white-space: nowrap; }
.returns-row-delete:hover { background: #fdf3f2; border-color: #d18a80; }
.returns-row-process { white-space: nowrap; }
.returns-row-process:not(:disabled) { color: var(--blue); border-color: #b9d3e6; font-weight: 600; }
.returns-row-process:not(:disabled):hover { background: #eef4f9; }
.returns-row-process:disabled { opacity: 0.5; cursor: not-allowed; }

@media (max-width: 860px) {
  .returns-live { grid-template-columns: minmax(0, 1fr); }

  /* Five columns fit down to about here; Started is the first to go, because
     the putaway code is already ordered newest first. */
  .returns-table th:nth-child(2), .returns-table td:nth-child(2) { display: none; }
}

/* The phone is where this page actually gets used, so it gets thumb-sized
   controls and only the columns that matter on a 390px screen. */
@media (max-width: 640px) {
  .returns-camera video { max-height: 38vh; }
  /* Take photo is the one that works on this deployment, so it gets the width. */
  .returns-camera-bar { gap: 8px; }
  .returns-camera-bar button { flex: 1 1 calc(50% - 4px); min-height: 46px; }
  .returns-last { padding: 12px; }
  .returns-last-code { font-size: clamp(22px, 7.5vw, 30px); }
  .returns-manual input { height: 48px; }
  .returns-manual button { min-width: 76px; }
  .returns-counts { justify-content: space-between; gap: 12px; }
  .returns-counts dd { font-size: 22px; }
  .returns-last-controls .returns-cond-btn { min-height: 36px; padding: 0 16px; font-size: 13px; }

  /* On a phone: the code, the marks and the actions. Status is carried by the
     marks (a batch with neither has not been run), and Started is on the row
     when you open it. */
  .returns-table th:nth-child(4), .returns-table td:nth-child(4) { display: none; }
  .returns-table th, .returns-table td { padding: 8px 6px; }

  .returns-row-actions { flex-direction: column; align-items: stretch; }
  .returns-row-actions button,
  .returns-row-actions .returns-row-log { min-height: 34px; }
}

/* ------------------------------------------------- returns: process + rows
   Process Barcodes hands the batch to the automation browser; the status block
   holds the step list while it walks to putaway and the outcome afterwards.
   The Batch cell is a disclosure button that opens the row into its barcodes. */

/* Sits at the top of the expanded row, above that batch's barcodes. */
.returns-process-status {
  margin: 0 0 10px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-left-width: 3px;
  border-radius: 8px;
  background: #fbfcfc;
  font-size: 13px;
  color: var(--ink);
}
.returns-process-status[data-state="running"] { border-left-color: var(--blue); }
.returns-process-status[data-state="done"] { border-left-color: var(--green); }
.returns-process-status[data-state="error"] { border-left-color: var(--red); }

.returns-process-steps { margin: 0; padding-left: 18px; color: var(--muted); }
.returns-process-steps li { margin: 2px 0; }
.returns-process-code {
  margin: 8px 0 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 18px;
  font-weight: 700;
  color: var(--green);
  letter-spacing: 0.02em;
}
.returns-process-outcome { margin: 4px 0 0; font-weight: 600; }

.returns-process-results {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
  display: grid;
  gap: 3px;
  max-height: 220px;
  overflow-y: auto;
}
.returns-process-results li {
  display: grid;
  grid-template-columns: minmax(90px, auto) 1fr;
  gap: 10px;
  align-items: baseline;
  padding: 4px 8px;
  border-radius: 4px;
  background: var(--surface);
  border: 1px solid var(--line);
}
.returns-process-results li.is-failed { border-color: #e0b4ae; background: #fdf3f2; }
.returns-process-result-code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  overflow-wrap: anywhere;
}
.returns-process-result-why { color: var(--muted); font-size: 12px; overflow-wrap: anywhere; }
.returns-process-results li.is-ok .returns-process-result-why { color: var(--green); }
.returns-process-results li.is-failed .returns-process-result-why { color: var(--red); }

@media (max-width: 640px) {
  .returns-process-results li { grid-template-columns: 1fr; gap: 2px; }
}
.returns-process-status[data-state="error"] .returns-process-outcome { color: var(--red); }
.returns-process-status[data-state="done"] .returns-process-outcome { color: var(--green); }

/* The header cell keeps a hint that the column opens. */
.returns-th-hint::after {
  content: " \00b7 tap to open";
  font-weight: 400;
  color: var(--muted);
  font-size: 11px;
}

.returns-batch-cell { padding: 0 !important; }
.returns-expand {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  min-height: 38px;
  padding: 8px 10px;
  border: 0;
  background: none;
  font: inherit;
  font-size: 13px;
  color: var(--ink);
  text-align: left;
  cursor: pointer;
}
.returns-expand:hover { background: #eef4f1; }
.returns-expand:focus-visible { outline: 2px solid var(--blue); outline-offset: -2px; }
.returns-expand-caret {
  flex: 0 0 auto;
  width: 0; height: 0;
  border-left: 5px solid var(--muted);
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  transition: transform 120ms ease;
}
.returns-expand[aria-expanded="true"] .returns-expand-caret { transform: rotate(90deg); }
.returns-expand-label { overflow-wrap: anywhere; }

.returns-detail-row > td { background: #f7f9f9; border-top: 0; }
/* .shipments-table td:last-child right-aligns the actions column, and the
   detail row's single cell is also a last child - it would inherit that and
   push every barcode to the far edge. Same specificity, declared later. */
.returns-table td.returns-detail-cell {
  padding: 10px 14px 14px !important;
  font-size: 13px !important;
  text-align: left;
}

.returns-detail-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 8px;
}
.returns-detail-loading, .returns-detail-empty { margin: 0; color: var(--muted); }
.returns-detail-error { margin: 0; color: var(--red); }

.returns-detail-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 4px;
  /* Long batches get their own scroll rather than pushing the table off screen. */
  max-height: 320px;
  overflow-y: auto;
}
/* Flex, not grid. The row's children come and go - a dupe badge, the two
   controls, and time/source which are hidden on a phone - and a grid needs its
   column count restated for every one of those combinations, which is how the
   phone layout broke the first time. */
.returns-detail-list li {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 6px;
}
.returns-detail-list li.is-duplicate {
  border-color: #e6d3a8;
  background: #fdf9ef;
}
/* After the duplicate rule: a bad parcel is the more useful thing to see when
   a row is somehow both. */
.returns-detail-list li.is-bad {
  border-color: #e6b3ac;
  background: #fdf4f3;
}
.returns-detail-code {
  /* Takes the slack so the controls stay right-aligned, and wraps rather than
     pushing them off a narrow screen. */
  flex: 1 1 140px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  overflow-wrap: anywhere;
}
.returns-detail-list li .returns-detail-delete { margin-left: auto; }
.returns-detail-badge {
  padding: 1px 6px;
  border-radius: 999px;
  background: #f3e3bf;
  color: var(--amber);
  font-size: 11px;
  font-weight: 600;
}
.returns-detail-when, .returns-detail-source { color: var(--muted); font-size: 12px; white-space: nowrap; }
.returns-detail-source { text-transform: capitalize; }

.returns-detail-delete {
  min-width: 28px;
  min-height: 28px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--surface);
  color: var(--muted);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
}
.returns-detail-delete:hover { color: var(--red); border-color: #e0b4ae; }
.returns-detail-delete:focus-visible { outline: 2px solid var(--blue); outline-offset: 1px; }

@media (max-width: 640px) {
  .returns-th-hint::after { content: none; }
  .returns-detail-cell { padding: 8px 8px 12px !important; }
  /* Time and source drop out - the barcode and its delete are what matter on a
     phone, and four columns in 390px squeezes the code to nothing. */
  .returns-detail-when, .returns-detail-source { display: none; }
  .returns-detail-delete { min-width: 34px; min-height: 34px; }
  /* Thumb-sized: these are tapped while holding a parcel. */
  .returns-cond-btn { min-height: 32px; padding: 0 11px; font-size: 12px; }
  .returns-pick input { width: 20px; height: 20px; }
  .returns-detail-list { max-height: 260px; }
}

/* ------------------------------------------- returns: live putaway run
   The dialog that fills in while the barcodes go into Unicommerce. It is not
   dismissable while the run is going: closing it would read as cancelling,
   which it is not - the job carries on server-side either way. */

.returns-run-scrim {
  position: fixed;
  inset: 0;
  background: rgba(31, 41, 51, 0.45);
  z-index: 80;
}

.returns-run {
  position: fixed;
  z-index: 81;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: min(560px, calc(100vw - 32px));
  max-height: min(78vh, 720px);
  display: flex;
  flex-direction: column;
  padding: 18px;
  border-radius: 12px;
  background: var(--surface);
  box-shadow: var(--shadow);
  border-top: 3px solid var(--blue);
}
.returns-run[data-state="done"] { border-top-color: var(--green); }
.returns-run[data-state="error"] { border-top-color: var(--red); }

.returns-run-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}
.returns-run-head h3 { margin: 0; font-size: 16px; }
.returns-run-putaway {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-weight: 700;
  color: var(--green);
}
.returns-run-phase { margin: 6px 0 10px; color: var(--muted); font-size: 13px; }

.returns-run-bar {
  height: 6px;
  border-radius: 999px;
  background: #e8edf0;
  overflow: hidden;
}
.returns-run-bar-fill {
  height: 100%;
  width: 0;
  background: var(--blue);
  transition: width 220ms ease;
}
.returns-run[data-state="done"] .returns-run-bar-fill { background: var(--green); }
.returns-run[data-state="error"] .returns-run-bar-fill { background: var(--red); }

.returns-run-counts {
  display: flex;
  gap: 22px;
  margin: 12px 0 8px;
}
.returns-run-counts div { display: flex; flex-direction: column; }
.returns-run-counts dt { font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
.returns-run-counts dd { margin: 0; font-size: 18px; font-weight: 700; }

.returns-run-list {
  list-style: none;
  margin: 0;
  padding: 0;
  overflow-y: auto;
  display: grid;
  gap: 4px;
  align-content: start;
  flex: 1;
  min-height: 80px;
}
.returns-run-list li {
  display: grid;
  grid-template-columns: minmax(96px, auto) 1fr;
  gap: 10px;
  align-items: baseline;
  padding: 6px 9px;
  border: 1px solid var(--line);
  border-radius: 6px;
}
.returns-run-list li.is-ok { border-color: #bcd9c3; background: #f3faf5; }
.returns-run-list li.is-failed { border-color: #e0b4ae; background: #fdf3f2; }
.returns-run-list li.is-current { border-color: #b9d3e6; background: #f2f7fb; }
.returns-run-code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 13px;
  overflow-wrap: anywhere;
}
.returns-run-why { font-size: 12px; color: var(--muted); overflow-wrap: anywhere; }
.returns-run-list li.is-ok .returns-run-why { color: var(--green); }
.returns-run-list li.is-failed .returns-run-why { color: var(--red); }
.returns-run-list li.is-current .returns-run-why { color: var(--blue); }

.returns-run-actions { display: flex; justify-content: flex-end; margin-top: 12px; }
.returns-run-actions button { min-height: 38px; padding: 0 18px; }

.returns-row-process.is-retry:not(:disabled) { color: var(--amber); border-color: #e6d3a8; }
.returns-row-process.is-retry:not(:disabled):hover { background: #fdf9ef; }

@media (max-width: 640px) {
  .returns-run {
    width: calc(100vw - 16px);
    max-height: 86vh;
    padding: 14px;
  }
  .returns-run-counts { gap: 16px; }
  .returns-run-list li { grid-template-columns: 1fr; gap: 2px; }
  .returns-run-actions button { width: 100%; min-height: 44px; }
}

@media (prefers-reduced-motion: reduce) {
  .returns-run-bar-fill { transition: none; }
}

/* ===================================== returns: live putaway session =====
   Start camera creates the putaway; every parcel goes in as it is scanned. */

.returns-session {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  margin: 0 0 12px;
  padding: 10px 14px;
  border: 1px solid #bcd9c3;
  border-left: 4px solid var(--green);
  border-radius: 10px;
  background: #f3faf5;
}
.returns-session-label {
  display: block;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--muted);
}
.returns-session-id strong {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 19px;
  color: var(--green);
}
.returns-session-counts { display: flex; gap: 18px; margin: 0; }
.returns-session-counts div { display: flex; flex-direction: column; }
.returns-session-counts dt {
  font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted);
}
.returns-session-counts dd { margin: 0; font-size: 17px; font-weight: 700; }
.returns-session-counts .is-ok dd { color: var(--green); }
.returns-session-counts .is-failed dd { color: var(--red); }
.returns-session-close { margin-left: auto; }

/* ----------------------------------------------------- shared modal shell */
.returns-modal-scrim {
  position: fixed; inset: 0; z-index: 90;
  background: rgba(31, 41, 51, 0.5);
  backdrop-filter: blur(1.5px);
}
.returns-modal {
  position: fixed; z-index: 91;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: min(460px, calc(100vw - 28px));
  max-height: min(84vh, 680px);
  display: flex;
  flex-direction: column;
  padding: 20px;
  border-radius: 14px;
  background: var(--surface);
  box-shadow: 0 18px 50px rgba(31, 41, 51, 0.28);
  border-top: 4px solid var(--blue);
}
.returns-modal[data-state="done"] { border-top-color: var(--green); }
.returns-modal[data-state="error"] { border-top-color: var(--red); }

.returns-modal-head { display: flex; align-items: center; gap: 10px; }
.returns-modal-head h3 { margin: 0; font-size: 17px; }
.returns-modal-phase { margin: 10px 0 0; font-size: 13px; color: var(--muted); }
.returns-modal[data-state="error"] .returns-modal-phase { color: var(--red); font-weight: 600; }
.returns-modal[data-state="done"] .returns-modal-phase { color: var(--green); font-weight: 600; }

.returns-spinner {
  width: 17px; height: 17px; flex: 0 0 auto;
  border: 2px solid #cfe0ec;
  border-top-color: var(--blue);
  border-radius: 50%;
  animation: returns-spin 760ms linear infinite;
}
@keyframes returns-spin { to { transform: rotate(360deg); } }

.returns-modal-steps {
  margin: 12px 0 0;
  padding-left: 20px;
  font-size: 12px;
  color: var(--muted);
  overflow-y: auto;
  max-height: 180px;
}
.returns-modal-steps li { margin: 3px 0; }

.returns-modal-bar {
  height: 6px; border-radius: 999px; background: #e8edf0; overflow: hidden; margin-top: 14px;
}
.returns-modal-bar-fill {
  height: 100%; width: 0; background: var(--blue); transition: width 380ms ease;
}
.returns-modal[data-state="done"] .returns-modal-bar-fill { background: var(--green); }
.returns-modal[data-state="error"] .returns-modal-bar-fill { background: var(--red); }

.returns-modal-actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 18px; }
.returns-modal-actions button { min-height: 44px; padding: 0 22px; font-size: 15px; }

/* ------------------------------------------------------- the scan dialog */
.returns-scan-putaway {
  margin-left: auto;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-weight: 700;
  color: var(--green);
}
.returns-scan-code {
  margin: 14px 0 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: clamp(20px, 6vw, 28px);
  font-weight: 700;
  letter-spacing: .01em;
  overflow-wrap: anywhere;
}
.returns-scan-partner { margin: 4px 0 0; font-size: 13px; color: var(--muted); }

.returns-scan-choice { margin-top: 16px; }
.returns-scan-choice-label {
  display: block; font-size: 11px; text-transform: uppercase;
  letter-spacing: .05em; color: var(--muted); margin-bottom: 6px;
}
/* Buttons, not a select: on a phone a select opens a full-screen picker over
   the viewfinder, and this has to be one tap while holding the parcel. */
.returns-pill { display: flex; gap: 8px; }
.returns-pill button {
  flex: 1;
  min-height: 46px;
  border: 2px solid var(--line);
  border-radius: 9px;
  background: var(--surface);
  font: inherit;
  font-size: 15px;
  font-weight: 600;
  color: var(--muted);
  cursor: pointer;
}
.returns-pill button.is-good.is-on {
  border-color: var(--green); background: #eaf6ee; color: var(--green);
}
.returns-pill button.is-bad.is-on {
  border-color: var(--red); background: #fdeeec; color: var(--red);
}
.returns-pill button:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }

.returns-scan-result { display: flex; gap: 26px; margin: 14px 0 0; }
.returns-scan-result div { display: flex; flex-direction: column; }
.returns-scan-result dt {
  font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted);
}
.returns-scan-result dd { margin: 0; font-size: 20px; font-weight: 700; }

/* The viewfinder keeps running underneath; dim it so the dialog is the focus. */
body.returns-scan-open .returns-camera-frame { filter: saturate(.5) brightness(.8); }

@media (max-width: 640px) {
  .returns-modal {
    width: calc(100vw - 16px);
    max-height: 88vh;
    padding: 16px;
    /* Sit high: the on-screen keyboard and the packer's thumb both live low. */
    top: 12px;
    transform: translateX(-50%);
  }
  .returns-modal-actions { flex-direction: column-reverse; }
  .returns-modal-actions button { width: 100%; }
  .returns-session { gap: 12px; }
  .returns-session-close { margin-left: 0; width: 100%; min-height: 42px; }
  .returns-session-counts { gap: 14px; }
}

@media (prefers-reduced-motion: reduce) {
  .returns-spinner { animation-duration: 2.4s; }
  .returns-modal-bar-fill { transition: none; }
}

/* ======================================== returns: the batch table ======
   Five columns instead of eight. Scans / Unique / Dupes became one subline on
   the putaway code, and the run became a tick and a cross with their counts -
   the point being to see how a batch went without reading a sentence. */

.returns-table th { white-space: nowrap; }
.returns-th-actions { text-align: right; }

.returns-expand { align-items: flex-start; padding: 10px; }
.returns-expand-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.returns-expand-label {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 14px;
  font-weight: 600;
  overflow-wrap: anywhere;
}
.returns-expand-sub { font-size: 11px; color: var(--muted); }
.returns-expand-caret { margin-top: 6px; }

.returns-when-cell { color: var(--muted); font-size: 12px; white-space: nowrap; }

/* A tick and a cross with their counts, in place of the coloured bar that used
   to run across the row. The mark carries the meaning, the colour only backs it
   up - which is also what makes it readable to anyone who cannot tell the two
   colours apart. */
.returns-result-cell { min-width: 110px; }
.returns-result-marks { display: flex; align-items: center; gap: 14px; }
.returns-mark {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  white-space: nowrap;
  cursor: help;
}
.returns-mark-glyph {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  line-height: 1;
  color: #fff;
}
.returns-mark.is-ok .returns-mark-glyph { background: var(--green); }
.returns-mark.is-failed .returns-mark-glyph { background: var(--red); }
.returns-mark-count {
  font-size: 14px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.returns-mark.is-ok .returns-mark-count { color: var(--green); }
.returns-mark.is-failed .returns-mark-count { color: var(--red); }
.returns-result-none { font-size: 12px; color: var(--muted); font-style: italic; }

.returns-status-pill {
  display: inline-block;
  padding: 3px 11px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .03em;
  text-transform: uppercase;
}
.returns-status-pill.is-open { background: #e6f0f8; color: var(--blue); }
.returns-status-pill.is-closed { background: #eef1f3; color: var(--muted); }

/* The row you are scanning into right now. */
.returns-table tr.is-current .returns-expand-label { color: var(--green); }

@media (max-width: 640px) {
  .returns-expand { padding: 8px 6px; }
  .returns-expand-label { font-size: 13px; }
  .returns-result-cell { min-width: 84px; }
  .returns-result-marks { gap: 10px; }
}

/* ============================ returns: the barcodes inside a batch ======
   Read-only. The condition was chosen in the scan dialog before the parcel
   went in; by the time it is on this row it is a record, not a control. */

.returns-detail-cond,
.returns-detail-status {
  flex: 0 0 auto;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .03em;
  text-transform: uppercase;
  white-space: nowrap;
}
.returns-detail-cond.is-good { background: #eaf6ee; color: var(--green); }
.returns-detail-cond.is-bad { background: #fdeeec; color: var(--red); }

/* Two states, pass and fail. There is no third: a parcel that was never sent
   did not go into the putaway, which is what fail means. */
.returns-detail-status { display: inline-flex; align-items: center; gap: 4px; cursor: help; }
.returns-detail-mark { font-size: 12px; line-height: 1; }
.returns-detail-status.is-ok { background: #eaf6ee; color: var(--green); }
.returns-detail-status.is-failed { background: #fdeeec; color: var(--red); }

.returns-detail-qty {
  flex: 0 0 auto;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 13px;
  font-weight: 700;
  color: var(--green);
}

/* The row is flex, not grid: its children come and go - a dupe badge, a
   quantity only on the ones that went in, a partner only when OCR found one -
   and a grid needs its column count restated for every combination. */
.returns-detail-list li { gap: 8px; }
.returns-detail-code { flex: 1 1 auto; min-width: 0; }

@media (max-width: 640px) {
  /* The barcode, what it was and what happened. Everything else is detail. */
  .returns-detail-partner { display: none; }
  .returns-detail-list li { flex-wrap: wrap; row-gap: 4px; }
  .returns-detail-code { flex: 1 0 100%; }
}

/* On a phone the wrapper scrolls sideways, the same as every other table on
   this page. Trying to force five columns into 390px with table-layout:fixed
   squeezed the actions cell to 26px and its buttons spilled over the Result
   column - worse than a scroll the app already uses everywhere else. */
@media (max-width: 640px) {
  .returns-row-actions {
    flex-direction: column;
    align-items: stretch;
    gap: 4px;
  }
  .returns-row-actions button,
  .returns-row-actions a {
    min-height: 32px;
    min-width: 76px;
    padding: 0 10px;
    font-size: 12px;
    white-space: nowrap;
    text-align: center;
    line-height: 32px;
  }
  .returns-result-cell { min-width: 130px; }
}

/* ============================== returns: full-screen camera (phones) ======
   body.returns-fs is set by returnsEnterFs() when the camera starts on a phone.
   The viewfinder covers the screen (z 85: above the top bar, below the returns
   dialogs at 90/91, so the scan dialog opens over the camera). The X at the
   top right hides it; the bottom sheet is the current putaway, row by row. */
.returns-fs-top,
.returns-fs-error,
.returns-sheet { display: none; }

body.returns-fs { overflow: hidden; }

body.returns-fs .returns-camera {
  position: fixed;
  inset: 0;
  z-index: 85;
  background: #000;
}
body.returns-fs .returns-camera-frame {
  position: absolute;
  inset: 0;
  border-radius: 0;
}
body.returns-fs .returns-camera video {
  width: 100%;
  height: 100%;
  max-height: none;
  aspect-ratio: auto;
  border: 0;
  border-radius: 0;
}
body.returns-fs .returns-camera-overlay { border-radius: 0; }
body.returns-fs .returns-camera-bar,
body.returns-fs .returns-photo-note { display: none; }

body.returns-fs .returns-fs-top {
  display: flex;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 2;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: calc(12px + env(safe-area-inset-top)) 14px 28px;
  background: linear-gradient(rgba(0, 0, 0, 0.62), rgba(0, 0, 0, 0));
  color: #fff;
  pointer-events: none;
}
.returns-fs-top > * { pointer-events: auto; }
.returns-fs-title span {
  display: block;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .06em;
  opacity: .8;
}
.returns-fs-title strong {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 19px;
}
.returns-fs-close {
  flex: 0 0 auto;
  width: 46px;
  height: 46px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  cursor: pointer;
}
.returns-fs-close svg {
  width: 22px;
  height: 22px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.4;
  stroke-linecap: round;
}
.returns-fs-close:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

body.returns-fs .returns-fs-error:not([hidden]) {
  display: block;
  position: absolute;
  top: calc(78px + env(safe-area-inset-top));
  left: 12px;
  right: 12px;
  z-index: 2;
  margin: 0;
  padding: 10px 12px;
  border-radius: 10px;
  background: #fdeeec;
  color: var(--red);
  font-size: 13px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.25);
}

/* ------------------------------------------------------ the bottom sheet */
body.returns-fs .returns-sheet {
  display: flex;
  flex-direction: column;
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 3;
  max-height: 66dvh;
  padding-bottom: env(safe-area-inset-bottom);
  border-radius: 16px 16px 0 0;
  background: var(--surface);
  color: var(--ink);
  box-shadow: 0 -10px 30px rgba(0, 0, 0, 0.3);
}
.returns-sheet-head {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  width: 100%;
  padding: 8px 16px 10px;
  border: 0;
  background: none;
  color: inherit;
  text-align: left;
  cursor: pointer;
  touch-action: none;
}
.returns-sheet-grip {
  align-self: center;
  width: 42px;
  height: 5px;
  border-radius: 999px;
  background: #cfd6dc;
}
.returns-sheet-summary {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 10px;
}
.returns-sheet-summary strong { font-size: 15px; }
.returns-sheet-counts { display: flex; gap: 10px; font-size: 13px; font-weight: 600; }
.returns-sheet-counts .is-ok { color: var(--green); }
.returns-sheet-counts .is-failed { color: var(--red); }

.returns-sheet-list {
  list-style: none;
  margin: 0;
  padding: 0 14px 10px;
  /* Closed: the newest parcel peeks out under the handle. */
  max-height: 64px;
  overflow: hidden;
  transition: max-height 240ms ease;
}
.returns-sheet[data-open="true"] .returns-sheet-list {
  max-height: calc(66dvh - 72px);
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}
.returns-sheet-row {
  display: grid;
  grid-template-columns: 20px minmax(0, 1fr) auto;
  gap: 10px;
  align-items: start;
  padding: 10px 2px;
  border-top: 1px solid var(--line);
}
.returns-sheet-row:first-child { border-top: 0; }
.returns-sheet-mark { font-size: 16px; font-weight: 800; line-height: 1.3; }
.returns-sheet-row.is-ok .returns-sheet-mark,
.returns-sheet-row.is-ok .returns-sheet-status { color: var(--green); }
.returns-sheet-row.is-failed .returns-sheet-mark,
.returns-sheet-row.is-failed .returns-sheet-status { color: var(--red); }
.returns-sheet-main { display: flex; flex-direction: column; min-width: 0; gap: 1px; }
.returns-sheet-code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 15px;
  font-weight: 700;
  overflow-wrap: anywhere;
}
.returns-sheet-meta { font-size: 12px; color: var(--muted); }
.returns-sheet-reason { font-size: 12px; color: var(--red); }
.returns-sheet-side { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
.returns-sheet-status { font-size: 12px; font-weight: 600; white-space: nowrap; }
.returns-sheet-empty { padding: 10px 2px; color: var(--muted); font-size: 13px; }

@media (prefers-reduced-motion: reduce) {
  .returns-sheet-list { transition: none; }
}

/* The reason a parcel did not go in, as its own line in the batch row. */
.returns-detail-reason {
  flex: 1 0 100%;
  font-size: 12px;
  line-height: 1.35;
  color: var(--red);
  overflow-wrap: anywhere;
}

/* ================== returns: scan dialog minimise, Stop, timer ========== */
.returns-scan-minimise {
  flex: 0 0 auto;
  width: 36px;
  height: 36px;
  margin-left: 6px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface);
  color: var(--ink);
  cursor: pointer;
}
.returns-scan-minimise svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; }
.returns-scan-putaway + .returns-scan-minimise { margin-left: 10px; }

.returns-scan-timer {
  margin: 6px 0 0;
  font-size: 12px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.returns-scan-timer.is-late { color: var(--red); font-weight: 600; }

.returns-modal-actions button.is-stop {
  border-color: var(--red);
  color: var(--red);
  background: #fdeeec;
  font-weight: 600;
}

/* The minimised dialog: a pill above everything, including the full-screen
   camera (85) but under the dialogs themselves (90/91). */
.returns-scan-chip {
  position: fixed;
  z-index: 89;
  left: 50%;
  bottom: calc(24px + env(safe-area-inset-bottom));
  transform: translateX(-50%);
  max-width: calc(100vw - 32px);
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  border: 1px solid #b9d3e6;
  border-radius: 999px;
  background: #eef4f9;
  color: var(--blue);
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  box-shadow: 0 8px 24px rgba(17, 24, 31, 0.28);
  cursor: pointer;
}
.returns-scan-chip-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.returns-scan-chip-dot {
  width: 9px; height: 9px; flex: 0 0 auto;
  border-radius: 50%;
  background: currentColor;
}
.returns-scan-chip[data-state="running"] .returns-scan-chip-dot { animation: returns-chip-pulse 1s ease-in-out infinite; }
@keyframes returns-chip-pulse { 50% { opacity: .25; } }
.returns-scan-chip[data-state="done"] { border-color: #cfe3d4; background: #eaf6ee; color: var(--green); }
.returns-scan-chip[data-state="error"] { border-color: #f1c4bf; background: #fdeeec; color: var(--red); }
/* Full screen: sit above the bottom sheet's handle. */
body.returns-fs .returns-scan-chip { bottom: calc(96px + env(safe-area-inset-bottom)); }

@media (prefers-reduced-motion: reduce) {
  .returns-scan-chip[data-state="running"] .returns-scan-chip-dot { animation: none; }
}
