/* ---------------------------------------------------------------------------
   Boxes marketplace clone — design tokens lifted from app.boxes.market
   (Hyvä "Satoshi" theme).
--------------------------------------------------------------------------- */

@font-face {
  font-family: Satoshi;
  src: url("../fonts/Satoshi-Medium.woff2") format("woff2");
  font-weight: 500;
  font-display: swap;
  font-style: normal;
}
@font-face {
  font-family: Satoshi;
  src: url("../fonts/Satoshi-Bold.woff2") format("woff2");
  font-weight: 700;
  font-display: swap;
  font-style: normal;
}

:root {
  --color-primary-50: #7e7e7e;
  --color-primary-100: #4b4b4b;
  --color-primary-400: #252525;
  --color-primary-500: #181818;
  --color-primary-600: #0b0b0b;
  --color-primary-700: #3f3f3f;

  --color-background-50: #ffffff;
  --color-background-400: #ffffff;
  --color-background-500: #f9f9f9;
  --color-background-600: #efefef;
  --color-background-700: #e6e6e6;

  --color-secondary-500: #f5f5f5;
  --color-secondary-600: #e8e8e8;
  --color-secondary-700: #dcdcdc;

  --color-text-50: #000000;
  --color-text-100: #0f0f0f;
  --color-text-400: #353535;
  --color-text-500: #424242;
  --color-text-600: #4f4f4f;
  --color-text-700: #5c5c5c;

  --color-overlay: #18181833;
  --color-overlay-dark: #18181866;
  --fade-in-bg: #f3f3f3;

  --header-shadow: 0 10px 8px rgb(0 0 0 / 0.04);
  --minicart-width: 400px;
  --account-width: 200px;
  --search-width: 450px;
  --menu-width: 250px;

  --font-body-family: "Satoshi", sans-serif;
  --font-body-weight: 500;
  --font-heading-weight: 700;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

/* The UA rule for [hidden] is only `display: none`, so any component that sets
   its own `display` silently outranks it and the JS `el.hidden = true` stops
   working. That bit the intake queue filter and the matched-listing card. */
[hidden] {
  display: none !important;
}

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--color-background-500);
  color: var(--color-text-700);
  font-family: var(--font-body-family);
  font-weight: var(--font-body-weight);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3,
h4 {
  font-weight: var(--font-heading-weight);
  color: var(--color-text-500);
  margin: 0;
}

a {
  color: inherit;
  text-decoration: none;
}

img {
  display: block;
  max-width: 100%;
}

button {
  font: inherit;
  color: inherit;
  border: 0;
  background: none;
  cursor: pointer;
}

input {
  font: inherit;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* A required field says so before the submit, not after it. The asterisk
   is decorative; the sr-only word inside carries it to a screen reader. */
.req {
  color: #b3261e;
  font-weight: 700;
  margin-left: 2px;
}

.content-wrapper {
  width: 100%;
  max-width: 1280px;
  margin-inline: auto;
  padding-inline: 16px;
}

/* --------------------------------------------------------------- buttons -- */

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 48px;
  padding-inline: 20px;
  border-radius: 8px;
  font-weight: 500;
  white-space: nowrap;
  transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}

.button--filled-primary {
  background: var(--color-primary-500);
  color: #fff;
}
.button--filled-primary:hover {
  background: var(--color-primary-600);
}

.button--filled-secondary {
  background: var(--color-background-50);
  color: var(--color-text-500);
}
.button--filled-secondary:hover {
  background: var(--color-secondary-600);
}

.button--outline-secondary {
  border: 1px solid var(--color-text-700);
  color: var(--color-text-500);
}
.button--outline-secondary:hover:not(.button--disabled) {
  background: var(--color-secondary-600);
}

.button--disabled {
  color: var(--color-secondary-700);
  border-color: var(--color-secondary-700);
  cursor: not-allowed;
}

.icon-button {
  width: 48px;
  height: 48px;
  padding: 0 12px;
  border-radius: 8px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

/* Theme hook: only paints an edge in forced-contrast mode, like the original. */
.contrast-border {
  border: 0;
}

@media (prefers-contrast: more) {
  .contrast-border {
    border: 1px solid var(--color-secondary-700);
  }
}

/* ---------------------------------------------------------------- header -- */

.page-header {
  position: sticky;
  top: 0;
  z-index: 60;
  padding: 20px;
  pointer-events: none;
}

.page-header__inner {
  max-width: 1280px;
  margin-inline: auto;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: start;
  gap: 12px;
}

.page-header__inner > * {
  pointer-events: auto;
}

/* Once content scrolls under it, the floating header needs its own surface —
   otherwise the logo sits unreadable on top of a product image. */
.page-header::before {
  content: "";
  position: absolute;
  inset: 0;
  background: color-mix(in srgb, var(--color-background-500) 82%, transparent);
  box-shadow: var(--header-shadow);
  opacity: 0;
  transition: opacity 0.2s ease;
  pointer-events: none;
}

@supports (backdrop-filter: blur(1px)) {
  .page-header::before {
    backdrop-filter: blur(12px) saturate(1.4);
  }
}

.page-header.is-stuck::before {
  opacity: 1;
}

.header-left {
  justify-self: start;
}

.header-logo {
  justify-self: center;
  display: flex;
  align-items: center;
  height: 48px;
}

.header-logo img {
  height: 39px;
  width: auto;
}

.header-right {
  justify-self: end;
  display: flex;
  align-items: start;
  gap: 8px;
}

/* These need a surface of their OWN, not just a fill that happens to differ
   from the page.

   Once the page scrolls, ::before turns the header into a frosted panel —
   82% opaque with blurred content moving underneath. A white pill on a
   near-white frosted panel stops reading as a button, and on phones the
   fill was dropped entirely, so the icons had nothing separating them from
   the churn behind. They were still there and still clickable; they just
   stopped looking like anything. The hairline is what survives both states,
   and being border-box it costs no layout width. */
.header-right .icon-button,
.menu-button {
  /* Not decoration — this is what keeps them on screen.

     The header paints a backdrop-filter once it sticks, and a statically
     positioned child gets flattened into that backdrop and disappears. The
     three icons that never went missing (cart, intake, ask) were the three
     that happened to carry `position: relative` for their badge dots; the
     two that vanished on every logged-in page, search and account, were the
     two without it. Promoting all of them to their own layer is the fix —
     `isolation` states the intent so nobody removes the `relative` later
     thinking it is leftover from a badge. */
  position: relative;
  isolation: isolate;
}

.header-right .icon-button {
  background: var(--color-background-50);
  color: var(--color-text-500);
  /* A surface of their own: a white pill on the near-white frosted panel
     stops reading as a button without an edge. */
  border: 1px solid var(--color-border, #ddd);
}
.header-right .icon-button:hover {
  background: var(--color-secondary-600);
}

.menu-button {
  gap: 12px;
  padding-inline: 16px;
  width: auto;
}

.menu-button__label {
  font-weight: 700;
  color: var(--color-text-500);
}

.cart-badge {
  position: absolute;
  top: 6px;
  right: 6px;
  min-width: 18px;
  height: 18px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--color-primary-500);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  line-height: 18px;
  text-align: center;
}

.icon-button--cart {
  position: relative;
}

/* --------------------------------------------------------------- panels --- */

.overlay {
  position: fixed;
  inset: 0;
  background: var(--color-overlay);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.25s ease, visibility 0.25s ease;
  z-index: 70;
}

.overlay.is-open {
  opacity: 1;
  visibility: visible;
}

.panel {
  position: fixed;
  top: 0;
  bottom: 0;
  z-index: 80;
  width: min(100vw, var(--panel-width, 400px));
  background: var(--color-background-50);
  display: flex;
  flex-direction: column;
  transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  overflow-y: auto;
}

.panel--left {
  left: 0;
  transform: translateX(-100%);
}
.panel--right {
  right: 0;
  transform: translateX(100%);
}
.panel.is-open {
  transform: translateX(0);
}

.panel--menu {
  --panel-width: 320px;
}
.panel--search {
  --panel-width: var(--search-width);
}
.panel--account {
  --panel-width: 320px;
}
.panel--cart {
  --panel-width: var(--minicart-width);
}

.panel__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 20px 20px 12px;
}

.panel__title {
  font-size: 20px;
  font-weight: 700;
  color: var(--color-text-500);
}

.panel__body {
  padding: 8px 20px 24px;
  flex: 1;
}

.panel__foot {
  padding: 16px 20px 24px;
  border-top: 1px solid var(--color-background-700);
}

.panel-close {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--color-text-500);
  font-weight: 700;
}

/* menu */

.menu-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.menu-list li + li {
  border-top: 1px solid var(--color-background-600);
}

.menu-list a,
.menu-list button {
  display: flex;
  width: 100%;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 14px 4px;
  color: var(--color-text-500);
  font-weight: 500;
  text-align: start;
}

.menu-list a:hover,
.menu-list button:hover {
  color: var(--color-text-50);
}

/* Sort & filter, in the drawer below the categories (2026-08-23). */
.menu-refine {
  margin-top: 18px;
  padding-top: 18px;
  border-top: 1px solid var(--color-background-700);
}

.menu-refine__label {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-text-700);
  margin-bottom: 8px;
}

.menu-refine__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.menu-refine__toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 14px 4px 0;
  margin-top: 10px;
  font-size: 15px;
  color: var(--color-text-400);
  text-decoration: none;
}

.switch {
  position: relative;
  display: inline-block;
  flex: 0 0 auto;
  width: 36px;
  height: 20px;
  border-radius: 999px;
  background: var(--color-background-700);
  transition: background 0.15s ease;
}

.switch__knob {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  border-radius: 999px;
  background: #fff;
  transition: left 0.15s ease;
}

.switch.is-on {
  background: var(--color-primary-500);
}

.switch.is-on .switch__knob {
  left: 18px;
}

.menu-sublist {
  list-style: none;
  margin: 0;
  padding: 0 0 8px 16px;
  display: none;
}

.menu-sublist.is-open {
  display: block;
}

.menu-sublist a {
  padding: 10px 4px;
  font-size: 15px;
  color: var(--color-text-700);
}

.menu-chevron {
  transition: transform 0.2s ease;
}
.menu-chevron.is-open {
  transform: rotate(180deg);
}

/* search */

.search-field {
  position: relative;
  display: flex;
  align-items: center;
  border: 1px solid var(--color-text-700);
  border-radius: 8px;
  padding: 0 12px;
  height: 48px;
  gap: 8px;
}

.search-field input {
  flex: 1;
  border: 0;
  outline: none;
  background: transparent;
  color: var(--color-text-500);
  min-width: 0;
}

.search-section-title {
  margin-top: 24px;
  margin-bottom: 8px;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-text-500);
}

.search-hint,
.search-empty {
  font-size: 14px;
  color: var(--color-text-700);
}

.search-empty strong {
  display: block;
  color: var(--color-text-500);
}

.search-result {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 0;
  border-top: 1px solid var(--color-background-600);
}

.search-result img {
  width: 48px;
  height: 60px;
  object-fit: cover;
  border-radius: 6px;
  background: var(--fade-in-bg);
  mix-blend-mode: darken;
}

.search-result__name {
  font-weight: 700;
  font-size: 15px;
  color: var(--color-text-500);
}

.search-result__seller {
  font-size: 13px;
  color: var(--color-text-700);
}

/* account */

.account-links {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.account-links a {
  padding: 12px 4px;
  color: var(--color-text-500);
  font-weight: 500;
  border-bottom: 1px solid var(--color-background-600);
}

/* Collapsible menu sections.
   An admin has 21 destinations; flat, that is a wall people hunt through
   rather than read. A closed section has to look like a HEADING and not like
   one more link, or the menu just gains six entries. */

.nav-group {
  border-bottom: 1px solid var(--color-background-600);
}

.nav-group__head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 4px;
  cursor: pointer;
  color: var(--color-text-700);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  list-style: none;                 /* Firefox marker */
  user-select: none;
}

/* Safari/Chrome draw their own triangle; ours is the chevron below. */
.nav-group__head::-webkit-details-marker { display: none; }

.nav-group__head:hover { color: var(--color-text-500); }

/* Focus has to be visible: <summary> is the only keyboard control in this
   menu, and removing list-style is exactly the change that usually takes the
   focus ring with it. */
.nav-group__head:focus-visible {
  outline: 2px solid var(--color-text-500);
  outline-offset: 2px;
  border-radius: 4px;
}

.nav-group__chev {
  margin-left: auto;
  flex: none;
  transition: transform 0.15s ease;
}

.nav-group[open] > .nav-group__head > .nav-group__chev {
  transform: rotate(180deg);
}

@media (prefers-reduced-motion: reduce) {
  .nav-group__chev { transition: none; }
}

.nav-group__head .pill { margin-left: 0; }

/* Indented so a link clearly belongs to the section above it, and without the
   divider each link carries at top level — inside a group the group's own
   border is the separator. */
.nav-group__body {
  display: flex;
  flex-direction: column;
  padding-bottom: 4px;
}

.nav-group__body a {
  padding: 10px 4px 10px 14px;
  border-bottom: 0;
  font-weight: 500;
}

.nav-group__body a[aria-current="page"] {
  color: var(--color-text-500);
  font-weight: 700;
  box-shadow: inset 2px 0 0 var(--color-text-500);
}

/* mini cart */

.cart-empty {
  color: var(--color-text-700);
  padding: 24px 0;
}

.cart-line {
  display: flex;
  gap: 12px;
  padding: 16px 0;
  border-bottom: 1px solid var(--color-background-600);
}

.cart-line img {
  width: 64px;
  height: 80px;
  object-fit: cover;
  border-radius: 8px;
  background: var(--fade-in-bg);
  mix-blend-mode: darken;
}

.cart-line__name {
  font-weight: 700;
  font-size: 15px;
  color: var(--color-text-500);
}

.cart-line__meta {
  font-size: 13px;
  color: var(--color-text-700);
}

.cart-line__remove {
  margin-left: auto;
  align-self: start;
  color: var(--color-text-700);
}

/* A line that can't be ordered is dimmed and says why — never removed.
   Nothing is destroyed; it comes back intact when the condition clears. */
.cart-line--blocked img,
.cart-line--blocked .cart-line__name {
  opacity: 0.55;
}

.cart-line__blocked,
.line-blocked__why {
  font-size: 13px;
  color: #8a5a00;
  margin: 4px 0 0;
}

.line--blocked th,
.line--blocked td { opacity: 0.7; }
.line--blocked .line-blocked__why { opacity: 1; }

.order-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 0 16px;
}

.order-summary__label {
  font-weight: 700;
  color: var(--color-text-500);
}

.checkout-link {
  width: 100%;
}

/* ------------------------------------------------------------ home grid --- */

.main {
  padding-top: 12px;
  padding-bottom: 64px;
}

/* Two up on a phone, matching app.boxes.market — measured at 375px, its cards
   are 162px in a two-column grid. Beyond looking like the real thing, a card
   half as wide needs a quarter of the pixels, so the same page of products is a
   fraction of the bytes. */
.product-grid {
  display: grid;
  gap: 12px;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  margin-inline: auto;
}

@media (min-width: 1024px) {
  .product-grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.card-link {
  position: relative;
  display: flex;
  height: 100%;
  min-width: 0;
  border-radius: 6px;
  cursor: pointer;
}

/* Soft panel that fades in behind the whole card on hover. It bleeds 8px past
   the card on every side, which is wider than the 12px grid gap — so adjacent
   panels overlap by 4px. That is what the storefront does, and it is invisible
   because the fill is flat with no border. */
.card-link::before {
  content: "";
  position: absolute;
  inset: -8px;
  border-radius: 16px;
  background: var(--color-secondary-500);
  opacity: 0;
  transition: opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.card-link:hover::before {
  opacity: 1;
}

.card-product {
  position: relative;
  z-index: 10;  /* above the hover panel */
  display: flex;
  flex-direction: column;
  align-items: stretch;
  width: 100%;
  height: 100%;
  /* The clip stays for the media, but the text below must not sit under it.
     `overflow: hidden` on a 12px radius shaves whatever touches a corner,
     and the price is the last line in the card — bottom-left, exactly where
     the curve bites. On a phone that took the leading "$" clean off. The
     media already clips itself, so the card does not have to. */
  border-radius: 12px;
  text-align: start;
}

.card-product__media {
  position: relative;
  overflow: hidden;
  border-radius: 6px;
  background: var(--fade-in-bg);
  transform: translateZ(0);
}

.card-product__media-inner {
  aspect-ratio: 0.75 / 1;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  /* The same fill as the parent, on the element that scales. Not redundant:
     transform makes this a stacking context, which becomes the isolation
     boundary for the image's mix-blend-mode. Without a fill here the image
     would blend against transparency the moment hover applies the scale, and
     the product's white backdrop would stop being darkened — the picture
     visibly washes out. The storefront puts the background on both for the
     same reason. */
  background: var(--fade-in-bg);
}

.card-product__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  mix-blend-mode: darken;
  transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

/* Both the frame and the image scale by 1.05, so the picture grows 1.1025x
   overall — the storefront puts the class on both elements and the transforms
   compound. Pointer devices only: a tap on a phone would leave the card stuck
   in its hover state. */
@media (min-width: 768px) and (hover: hover) {
  .card-link:hover .card-product__media-inner,
  .card-link:hover .card-product__media img {
    transform: scale(1.05);
  }
}

.card-product__body {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: 12px;
  /* Fill the card so the price row's `margin-top: auto` has somewhere to
     push against — that is what puts every price on the same baseline
     across a row, however long the name or whether there is a badge. */
  flex: 1;
  /* One character of breathing room at the edges. The card clips on a 12px
     radius, and text set flush to the corner loses its first glyph — which
     is how the leading "$" was disappearing on a phone. */
  padding-inline: 2px;
}

.card-product__body p {
  margin: 0;
}

.card-product__name {
  font-size: 16px;
  font-weight: 700;
  color: var(--color-text-500);
}

.card-product__seller {
  font-size: 16px;
  color: var(--color-text-700);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.card-product__seller strong {
  color: var(--color-text-500);
}

/* The last row of every card: price, and the hemp badge when there is one.
   Pinned to the bottom so a two-up grid lines its prices up regardless of
   how many lines the name above took. */
.card-product__priceline {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: auto;
  padding-top: 4px;
}

.card-product__price {
  color: var(--color-text-700);
  margin: 0;
}

/* A correlation row whose packages did not all land on the same listing. Rare
   and always the result of a deliberate correction, so it reads as an
   explanation rather than an alarm — the operator did this on purpose and
   needs confirmation, not a scolding. */
.line__split {
  margin: 10px 0 0;
  padding: 10px 12px;
  background: #fffbeb;
  border: 1px solid #fde68a;
  border-radius: 8px;
}

.line__split-head {
  margin: 0 0 6px;
  font-size: 13px;
  line-height: 1.5;
}

.line__split-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 6px;
}

.line__split-list li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px;
  font-size: 13.5px;
}

/* The tags wrap onto their own line and stay selectable — an operator
   checking a correction reads them one at a time against a shelf. */
.line__split-tags {
  flex-basis: 100%;
  font-size: 11.5px;
  color: var(--color-text-700, #6b7280);
  word-break: break-all;
}

/* ------------------------------------------------------------ packing slip
   A document, not a screen. It has to survive three contexts: a phone in a
   picker's hand, a desktop reprint, and a sheet of paper in a box. The print
   rules at the bottom are the point — everything else is chrome that must
   disappear when it hits the printer. */
.slip-page {
  padding-bottom: 60px;
}

.slip-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  align-items: flex-end;
  justify-content: space-between;
  margin: 24px 0 20px;
}

/* ------------------------------------------------- a buyer's own orders -- */

.order-card {
  background: #fff;
  border: 1px solid var(--color-line, #e5e7eb);
  border-radius: 14px;
  padding: 18px 20px;
  margin-bottom: 14px;
}

.order-card__head {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: space-between;
  align-items: baseline;
}

.order-card__number {
  font-size: 18px;
  font-weight: 700;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

.order-card__meta {
  display: block;
  font-size: 13px;
  color: var(--color-text-700, #6b7280);
}

.order-card__money {
  display: flex;
  align-items: baseline;
  gap: 10px;
}

.order-card__total { font-size: 18px; font-weight: 700; }

/* Four dots and three joins. Deliberately not a percentage bar: an order is
   at a named stage, and a bar invites reading a half-finished pick as
   "60% delivered". */
.order-steps {
  display: flex;
  list-style: none;
  margin: 16px 0 8px;
  padding: 0;
}

.order-steps__step {
  flex: 1;
  position: relative;
  text-align: center;
  font-size: 12px;
  color: var(--color-text-700, #6b7280);
}

.order-steps__step::before {
  content: "";
  position: absolute;
  top: 6px;
  left: -50%;
  width: 100%;
  height: 2px;
  background: var(--color-line, #e5e7eb);
}

.order-steps__step:first-child::before { display: none; }

.order-steps__dot {
  display: block;
  position: relative;
  width: 14px;
  height: 14px;
  margin: 0 auto 6px;
  border-radius: 50%;
  background: var(--color-line, #e5e7eb);
}

.order-steps__step.is-done::before,
.order-steps__step.is-now::before { background: #1f6b3a; }

.order-steps__step.is-done .order-steps__dot,
.order-steps__step.is-now .order-steps__dot { background: #1f6b3a; }

.order-steps__step.is-now .order-steps__dot {
  box-shadow: 0 0 0 4px rgba(31, 107, 58, .18);
}

.order-steps__step.is-now .order-steps__label {
  color: #1f6b3a;
  font-weight: 700;
}

.order-card__state {
  margin: 0 0 14px;
  font-size: 14px;
  color: var(--color-text-700, #6b7280);
}

.order-card__facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px;
  padding: 12px 0;
  border-top: 1px solid var(--color-line, #e5e7eb);
}

.order-card__facts > div { display: flex; flex-direction: column; gap: 2px; }

.order-card__short {
  margin: 0 0 12px;
  padding: 10px 12px;
  font-size: 13px;
  line-height: 1.55;
  background: #fffbeb;
  border: 1px solid #fde68a;
  border-radius: 8px;
  color: #8a5a00;
}

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

/* A packing slip is a company document, not a web card. It prints on the
   real letterhead — assets/letterhead.jpg, the same sheet invoice_pdf.py
   draws its PDFs on — so the page carries the artwork and the content sits
   in the letterhead's own safe area.

   The proportions are US Letter (8.5 x 11) and the insets are the ones the
   PDF writer uses, expressed as percentages so they hold at any width:
   the letterhead owns the top ~19% (logo, tagline, green rule) and the
   bottom ~11% (footer band), with a 9% side margin. */
.slip {
  position: relative;
  background: #fff url("../img/letterhead.jpg") no-repeat center / 100% 100%;
  aspect-ratio: 8.5 / 11;
  width: 100%;
  max-width: 850px;
  margin: 0 auto 26px;
  padding: 19.2% 9.15% 11.4%;
  box-sizing: border-box;
  color: #111827;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
  overflow: hidden;
  /* The letterhead is the point — a browser dropping backgrounds to save
     toner would print a blank sheet with a table on it. */
  -webkit-print-color-adjust: exact;
  print-color-adjust: exact;
}

/* A slip with a lot of tags can outgrow one sheet. Better to let it run than
   to clip a package tag off the bottom of a compliance document. */
.slip--long {
  aspect-ratio: auto;
  min-height: 0;
}

.slip__head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
  padding-bottom: 10px;
  margin-bottom: 14px;
  border-bottom: 1px solid #d1d5db;
}

.slip__doctype {
  display: block;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: #4b7c46;
}

.slip__ref {
  text-align: right;
}

.slip__order {
  display: block;
  font-size: 21px;
  font-weight: 700;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

.slip__sub {
  display: block;
  font-size: 12.5px;
  color: #6b7280;
}

.slip__meta {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 14px 20px;
  margin: 18px 0;
}

.slip__label {
  display: block;
  font-size: 11px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: #6b7280;
  margin-bottom: 2px;
}

.slip__strong {
  font-size: 17px;
  font-weight: 700;
}

.slip__notes {
  background: #f9fafb;
  border-left: 3px solid #111827;
  padding: 8px 12px;
  margin: 0 0 18px;
  font-size: 14px;
}

.slip__section {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 15px;
  margin: 22px 0 8px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--color-line, #e5e7eb);
}

.slip__icon {
  font-size: 17px;
}

.slip__hint {
  font-size: 13px;
  color: #6b7280;
  margin: 0 0 10px;
}

.slip__table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}

.slip__table th,
.slip__table td {
  padding: 9px 10px;
  border-bottom: 1px solid #eef0f3;
  text-align: left;
  vertical-align: top;
}

.slip__table thead th {
  font-size: 10.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #6b7280;
  border-bottom: 1px solid #d1d5db;
}

.slip__table .num {
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.slip__sku {
  display: block;
  font-size: 11.5px;
  color: #6b7280;
}

/* Tags wrap as chips rather than one unreadable run-on string: a receiver
   checking a delivery reads them one at a time, off paper, against a case. */
.slip__tags {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  max-width: 340px;
}

.slip__tag {
  font-size: 11px;
  padding: 2px 6px;
  border: 1px solid #d1d5db;
  border-radius: 4px;
  white-space: nowrap;
}

.slip__short {
  display: block;
  font-size: 11.5px;
  font-weight: 700;
  color: #b3261e;
}

.slip__short-note {
  background: #fdf2f2;
  border: 1px solid #f0c8c4;
  border-radius: 8px;
  padding: 10px 12px;
  font-size: 13.5px;
  margin: 18px 0 0;
}

.slip__foot {
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
  justify-content: space-between;
  align-items: flex-end;
  margin-top: 22px;
  padding-top: 14px;
  /* Lighter than it was: the letterhead already ends the page with its own
     dark band, and a heavy black rule just above it reads as a mistake. */
  border-top: 1px solid #d1d5db;
}

.slip__sign {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  flex: 1;
  min-width: 240px;
  justify-content: flex-end;
}

.slip__rule {
  display: inline-block;
  border-bottom: 1px solid #9ca3af;
  width: 150px;
  height: 18px;
}

.slip__rule--short {
  width: 90px;
}

/* On a phone the four-column table runs off the edge and the value column is
   simply gone — and the warehouse is a phone-only surface, so that is not a
   corner case, it is the primary one. Stack to label/value below 640px, the
   same shape every other table in the app uses. SCREEN only: on paper the
   columns fit and a stacked slip would waste half a sheet. */
@media screen and (max-width: 640px) {
  .slip {
    padding: 18px 16px;
    /* The three that made this unreadable on a phone. A Letter sheet is
       8.5/11 with overflow hidden, so at 375px the sheet is locked to ~485px
       tall while the STACKED table below is far taller — the bottom of the
       slip, package tags included, was simply cut off. On screen, at this
       width, let the document grow with its content.

       The letterhead image goes too: at 375px the artwork is unreadable and
       it is the thing forcing the fixed ratio. Print and the downloaded PDF
       are untouched — this block is `@media screen` and the PDF is generated
       by invoice_pdf.py, which never sees this stylesheet. */
    aspect-ratio: auto;
    overflow: visible;
    background-image: none;
    border: 1px solid var(--color-line, #e5e7eb);
    border-radius: 10px;
  }

  /* Says where the letterhead went, so nobody thinks the document is broken. */
  .slip__screen-note {
    display: block;
  }

  .slip__table thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }

  .slip__table tr {
    display: block;
    padding: 12px 0;
    border-bottom: 1px solid #eef0f3;
  }

  .slip__table th[scope="row"] {
    display: block;
    padding: 0 0 6px;
    border: 0;
    font-size: 15px;
  }

  .slip__table td {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    padding: 3px 0;
    border: 0;
    text-align: right;
  }

  .slip__table td::before {
    content: attr(data-label);
    flex-shrink: 0;
    margin-right: auto;
    text-align: left;
    font-size: 11px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: #6b7280;
  }

  .slip__tags {
    max-width: none;
    justify-content: flex-end;
  }
}

/* The slip is a paper document first. Chrome goes, one slip per sheet, and
   nothing is allowed to break a line across a page boundary — a package tag
   split over two sheets is a tag nobody can check. */
@media print {
  .no-print,
  .page-header,
  .page-footer,
  .panel,
  .overlay,
  .toast,
  .flash-stack {
    display: none !important;
  }

  body {
    background: #fff;
  }

  .slip-page {
    padding: 0;
  }

  /* One sheet of letterhead per slip. The aspect-ratio box is dropped here:
     on paper the PAGE sets the height, and keeping a fixed ratio would leave
     a slip either short of the footer band or spilling onto a second sheet
     with nothing on it.

     The @page rule that makes the artwork bleed lives in packing_slip.html,
     NOT here — @page cannot be scoped to a selector, so putting it in the
     shared stylesheet would silently change the margins of every other page
     on the site somebody ever prints. */
  .slip {
    aspect-ratio: auto;
    width: 100%;
    max-width: none;
    min-height: 100vh;
    margin: 0;
    box-shadow: none;
    page-break-after: always;
    break-after: page;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  .slip:last-child {
    page-break-after: auto;
    break-after: auto;
  }

  .slip__table tr,
  .slip__section,
  .slip__short-note {
    page-break-inside: avoid;
    break-inside: avoid;
  }
}

/* A field that stands on its own outside a form, so it needs the separation a
   form's own rhythm would otherwise give it. Without this the marketplace
   switch on the seller page reads as the tail of the paragraph above it. */
.field--standalone {
  margin-top: 26px;
}

/* Hemp marker on a grid card. Only hemp is badged — tracked is the norm, and
   a badge on every card is a badge on none — so this sits between the seller
   line and the price without pushing the card taller than an unbadged one. */
/* Inline with the price now, not a row of its own. */
.card-product__regime {
  flex: none;
  line-height: 1;
}

.card-product__quickbuy {
  position: absolute;
  right: 0;
  top: 0;
  color: var(--color-primary-500);
}

/* The quick-buy icon floats over the top-right of the body, so the two lines
   it sits beside have to keep out of its way. A long product name was
   running right up to the bag on a phone. */
.card-product__name,
.card-product__seller {
  padding-right: 34px;
}

@media (min-width: 768px) {
  .card-product__quickbuy {
    display: none;
  }

  /* No button up here, so no reason to reserve the space. */
  .card-product__name,
  .card-product__seller {
    padding-right: 0;
  }
}

/* -------------------------------------------------------- product detail -- */

.product-view {
  position: relative;
  z-index: 30;
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-inline: auto;
  width: 100%;
}

@media (min-width: 768px) {
  .product-view {
    display: grid;
    grid-template-columns: 1fr 250px;
    align-items: start;
    gap: 24px;
  }
}

@media (min-width: 1024px) {
  .product-view {
    grid-template-columns: 1fr 330px;
  }
}

@media (min-width: 1280px) {
  .product-view {
    grid-template-columns: 1fr 400px;
    gap: 64px;
  }
}

.gallery {
  display: grid;
  gap: 20px;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  padding-bottom: 28px;
}

.gallery__figure {
  position: relative;
  /* <figure> carries a UA default of `margin: 1em 40px`. With width:100% below
     that made the box 80px wider than its track and shoved it 40px right —
     off-centre on every screen and overflowing on a phone. */
  margin: 0;
  /* Width must be definite or the ratio resolves against the row height. */
  width: 100%;
  aspect-ratio: 0.75 / 1;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background: var(--fade-in-bg);
  border-radius: 16px;
  cursor: zoom-in;
}

.gallery__figure img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  mix-blend-mode: darken;
}

/* The strip of other angles under the hero. Scrolls sideways when there are
   more than fit — snap keeps a whole square in view on a phone — and the
   whole row simply isn't rendered for a one-picture listing. */
.gallery__strip {
  /* .gallery is a grid; without this the strip lands as a SECOND COLUMN
     beside the hero instead of a row under it. Column 1 keeps it exactly
     the hero's width. */
  grid-column: 1;
  display: flex;
  gap: 8px;
  margin-top: 10px;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
  padding-bottom: 4px;
}

.gallery__thumb {
  flex: 0 0 auto;
  width: 72px;
  height: 72px;
  padding: 0;
  border: 2px solid transparent;
  border-radius: 12px;
  overflow: hidden;
  background: var(--fade-in-bg);
  cursor: pointer;
  scroll-snap-align: start;
}

.gallery__thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  mix-blend-mode: darken;
}

.gallery__thumb.is-active {
  border-color: var(--color-primary-500);
}

.product-info {
  padding-top: 8px;
}

/* The vendor's picture manager on the listing form. */
.photo-grid {
  list-style: none;
  margin: 0 0 12px;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 12px;
}

.photo-card {
  position: relative;
  border: 1px solid var(--color-background-700);
  border-radius: 12px;
  overflow: hidden;
  background: var(--color-background-500);
}

.photo-card.is-dragging {
  opacity: 0.5;
}

.photo-card > img {
  width: 100%;
  aspect-ratio: 0.75 / 1;
  object-fit: cover;
  display: block;
}

.photo-card__badge {
  position: absolute;
  top: 8px;
  left: 8px;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--color-primary-500);
  color: var(--color-background-50);
  font-size: 12px;
  font-weight: 600;
}

.photo-card__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  padding: 6px;
  justify-content: space-between;
}

.photo-card__actions form {
  display: flex;
  gap: 4px;
}

.photo-card__btn {
  padding: 4px 8px;
  border: 1px solid var(--color-background-700);
  border-radius: 8px;
  background: var(--color-background-50);
  font-size: 13px;
  cursor: pointer;
  /* Finger-sized on a phone even though it draws small. */
  min-height: 30px;
}

.photo-card__btn:disabled {
  opacity: 0.35;
  cursor: default;
}

.photo-card__btn--danger {
  color: #b3261e;
  border-color: #e5c1be;
}

.photo-add {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
}

@media (min-width: 768px) {
  .product-info {
    position: sticky;
    top: 88px;
  }
}

.product-title {
  margin-bottom: 12px;
  font-size: 22px;
  line-height: 1.15;
  color: var(--color-text-500);
}

@media (min-width: 768px) {
  .product-title {
    font-size: 36px;
  }
}

.rating {
  display: flex;
  gap: 2px;
  color: var(--color-secondary-700);
  margin-bottom: 24px;
}

.product-price {
  color: var(--color-text-700);
  margin-bottom: 32px;
}

.add-to-cart-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 24px;
}

.qty-input {
  width: 44px;
  height: 48px;
  flex-shrink: 0;
  padding: 0 4px;
  text-align: center;
  background: transparent;
  border: 1px solid var(--color-text-700);
  border-radius: 8px;
  color: var(--color-text-500);
  -moz-appearance: textfield;
}

.qty-input::-webkit-outer-spin-button,
.qty-input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.add-to-cart {
  flex: 1 1 180px;
}

.product-meta {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-bottom: 8px;
}

.product-meta__row strong,
.product-meta__row a {
  color: var(--color-text-500);
  font-weight: 700;
}

.product-meta__row a {
  text-decoration: underline;
  text-underline-offset: 2px;
}

.accordion {
  border-top: 1px solid var(--color-background-700);
  margin-top: 16px;
}

.accordion__trigger {
  display: flex;
  width: 100%;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  padding: 16px 0;
  text-align: start;
  font-weight: 700;
  color: var(--color-text-500);
}

.accordion__icon {
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  border: 1px solid var(--color-background-700);
  border-radius: 8px;
  transition: transform 0.2s ease;
}

.accordion__trigger[aria-expanded="true"] .accordion__icon {
  transform: rotate(180deg);
}

.accordion__panel {
  display: none;
  padding-bottom: 20px;
  color: var(--color-text-700);
}

.accordion__panel.is-open {
  display: block;
}

.accordion__panel p {
  margin: 0 0 16px;
}

.accordion__panel h4 {
  margin: 0 0 4px;
  font-size: 16px;
}

.share-row {
  display: flex;
  justify-content: center;
  padding: 32px 0;
}

.share-button {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-weight: 700;
  color: var(--color-text-500);
}

/* ------------------------------------------------------ similar products -- */

.similar {
  margin-top: 48px;
}

.similar__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 16px;
}

.similar__title {
  font-size: 22px;
}

@media (min-width: 768px) {
  .similar__title {
    font-size: 28px;
  }
}

.similar__nav {
  display: flex;
  gap: 8px;
}

.similar__nav .icon-button {
  width: 44px;
  height: 44px;
}

.similar__rail {
  display: flex;
  gap: 12px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: thin;
  scrollbar-color: var(--color-secondary-700) transparent;
  /* overflow-x:auto clips vertically too, so leave room for the 8px hover
     panel bleed and pull it back with a matching negative margin — otherwise
     the top edge of the panel is sliced off. */
  padding-top: 8px;
  margin-top: -8px;
  padding-bottom: 12px;
  /* bleed to the viewport edges so cards scroll past the wrapper padding */
  margin-inline: -16px;
  padding-inline: 16px;
}

.similar__rail::-webkit-scrollbar {
  height: 6px;
}

.similar__rail::-webkit-scrollbar-track {
  background: var(--color-background-700);
  border-radius: 999px;
}

.similar__rail::-webkit-scrollbar-thumb {
  background: var(--color-secondary-700);
  border-radius: 999px;
}

.similar__rail::-webkit-scrollbar-thumb:hover {
  background: var(--color-primary-50);
}

.similar__item {
  flex: 0 0 auto;
  width: 240px;
  scroll-snap-align: start;
}

@media (min-width: 768px) {
  .similar__item {
    width: 303px;
  }
}

/* ----------------------------------------------------------------- reviews */

.reviews {
  border-top: 1px solid var(--color-background-700);
  padding-top: 40px;
  margin-top: 40px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.reviews__title {
  font-size: 22px;
  margin-bottom: 8px;
}

@media (min-width: 768px) {
  .reviews__title {
    font-size: 28px;
  }
}

.reviews__subtitle {
  color: var(--color-text-700);
  margin: 0 0 24px;
}

.review-form {
  display: grid;
  gap: 16px;
  width: 100%;
  max-width: 560px;
  text-align: start;
}

.review-form .rating-input {
  justify-content: center;
  width: 100%;
}

.review-form .field:first-child {
  text-align: center;
}

.field label {
  display: block;
  margin-bottom: 6px;
  font-size: 14px;
  font-weight: 700;
  color: var(--color-text-500);
}

.field input,
.field textarea,
.field select {
  width: 100%;
  padding: 12px;
  border: 1px solid var(--color-text-700);
  border-radius: 8px;
  background: transparent;
  color: var(--color-text-500);
  outline: none;
}

/* Selects don't inherit the page font the way the input reset does, and a
   system-font control beside a Satoshi input is what "inconsistent" looks
   like. Every label-above select gets the input treatment. */
.field select {
  font: inherit;
}

.field input:focus,
.field textarea:focus,
.field select:focus,
.search-field:focus-within {
  border-color: var(--color-primary-500);
}

.rating-input {
  display: inline-flex;
  gap: 4px;
}

.rating-input button {
  color: var(--color-secondary-700);
  line-height: 0;
}

.rating-input button.is-active {
  color: var(--color-primary-500);
}

.review-form .button {
  justify-self: center;
  min-width: 200px;
}

/* ---------------------------------------------------------------- footer -- */

.page-footer {
  border-top: 1px solid var(--color-background-700);
  margin-top: 48px;
  padding: 24px 0 40px;
}

.footer-accordion {
  max-width: 1280px;
  margin-inline: auto;
  padding-inline: 16px;
}

.footer-accordion__trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 16px 0;
  font-weight: 700;
  color: var(--color-text-500);
}

.footer-links {
  display: none;
  padding-bottom: 16px;
}

.footer-links.is-open {
  display: block;
}

.footer-links a {
  color: var(--color-text-700);
}
.footer-links a:hover {
  color: var(--color-text-500);
}

.copyright {
  padding-top: 24px;
  font-size: 14px;
  color: var(--color-text-700);
}

/* ------------------------------------------------------------------ misc -- */

.stub {
  min-height: 40vh;
  display: grid;
  place-items: center;
  text-align: center;
  gap: 8px;
  padding: 80px 16px;
}

.stub h1 {
  font-size: 32px;
}

.toast {
  position: fixed;
  left: 50%;
  bottom: 24px;
  transform: translate(-50%, 16px);
  background: var(--color-primary-500);
  color: #fff;
  padding: 12px 20px;
  border-radius: 8px;
  font-size: 15px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease, transform 0.2s ease;
  z-index: 90;
}

.toast.is-open {
  opacity: 1;
  transform: translate(-50%, 0);
}

/* The magnified layer sits inside the gallery frame, not over the page. Its
   background is the same file at 2x, panned by background-position as the
   cursor moves — see the zoom block in app.js. */
.zoomed-img-container {
  position: absolute;
  inset: 0;
  z-index: 10;
  margin: 0;
  display: block;
  height: 100%;
  width: 100%;
  max-width: 100%;
  cursor: zoom-out;
  border-radius: 16px;
  background-color: var(--fade-in-bg);
}

.zoomed-img-container .zoomed-img {
  height: 100%;
  background-repeat: no-repeat;
  /* Same blend as the resting image, so the product's white backdrop drops out
     on the tinted frame instead of showing as a bright rectangle. */
  mix-blend-mode: darken;
}

/* =========================================================================
   Marketplace: accounts, vendor listings, admin review
   ========================================================================= */

/* ----------------------------------------------------------------- flashes */

.flash-stack {
  display: grid;
  gap: 8px;
  margin-bottom: 20px;
}

.flash {
  padding: 12px 16px;
  border-radius: 8px;
  font-size: 15px;
  border: 1px solid transparent;
}

.flash--success {
  background: var(--color-background-50);
  border-color: var(--color-background-700);
  color: var(--color-text-500);
}

.flash--error {
  background: #fdf1f1;
  border-color: #f0cccc;
  color: #8c2f2f;
}

/* ------------------------------------------------------------ form pages -- */

.form-page {
  max-width: 520px;
  margin-inline: auto;
  padding: 8px 0 24px;
}

.form-page__head {
  margin-bottom: 24px;
  text-align: center;
}

.form-page__title {
  font-size: 28px;
  line-height: 1.15;
}

@media (min-width: 768px) {
  .form-page__title {
    font-size: 36px;
  }
}

.form-page__subtitle {
  margin: 8px 0 0;
  color: var(--color-text-700);
}

.stacked-form {
  display: grid;
  gap: 18px;
  background: var(--color-background-50);
  padding: 24px;
  border-radius: 12px;
}

.stacked-form .button[type="submit"] {
  width: 100%;
}

/* Cloudflare Turnstile renders a fixed-width iframe inside this div —
   centered so it sits on the form's axis like every other control. */
.cf-turnstile {
  display: flex;
  justify-content: center;
}

.field__hint {
  margin: 6px 0 0;
  font-size: 13px;
  color: var(--color-text-700);
}

.field textarea {
  resize: vertical;
  font-family: inherit;
}

.field input[type="file"] {
  padding: 10px;
  border: 1px dashed var(--color-text-700);
  background: var(--color-background-500);
}

.form-foot {
  margin: 0;
  text-align: center;
  font-size: 15px;
  color: var(--color-text-700);
}

.form-foot a,
.form-page a {
  color: var(--color-text-500);
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.form-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

.form-actions .button {
  flex: 1 1 160px;
}

.demo-accounts {
  border-top: 1px solid var(--color-background-700);
  padding-top: 16px;
  font-size: 14px;
  color: var(--color-text-700);
}

.demo-accounts h2 {
  font-size: 14px;
  margin-bottom: 6px;
}

.demo-accounts ul {
  margin: 0;
  padding-left: 18px;
}

/* choice cards (buyer / vendor) */

.choice-grid {
  display: grid;
  gap: 12px;
  grid-template-columns: 1fr 1fr;
}

/* `label.choice` beats the `.field label { display: block }` base rule. */
label.choice {
  display: grid;
  gap: 2px;
  margin-bottom: 0;
  padding: 14px;
  border: 1px solid var(--color-background-700);
  border-radius: 8px;
  cursor: pointer;
  transition: border-color 0.15s ease, background-color 0.15s ease;
}

.choice:hover {
  border-color: var(--color-primary-50);
}

.choice.is-selected {
  border-color: var(--color-primary-500);
  background: var(--color-secondary-500);
}

.choice input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.choice__title {
  font-weight: 700;
  color: var(--color-text-500);
}

.choice__desc {
  font-size: 13px;
  color: var(--color-text-700);
}

.image-preview {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 10px;
  font-size: 13px;
  color: var(--color-text-700);
}

.image-preview img {
  width: 60px;
  height: 75px;
  object-fit: cover;
  border-radius: 8px;
  background: var(--fade-in-bg);
  flex: 0 0 auto;
}

/* The removal control sits with the picture it removes, not down in the
   form actions where it would read as part of saving the listing. */
.image-preview span {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  flex-wrap: wrap;
  min-width: 0;
}

.image-preview--empty img {
  object-fit: contain;
  border: 1px dashed var(--color-background-700, #e6e6e6);
}

/* -------------------------------------------------------------- dashboard */

.dash {
  padding: 8px 0 24px;
}

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

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

/* Folded admin sections (Users: the add-forms). The summary wears the
   ordinary section title plus a disclosure arrow; open, it reads exactly
   as the unfolded page always did. */
.disclose > summary {
  cursor: pointer;
  list-style: none;
}
.disclose > summary::-webkit-details-marker {
  display: none;
}
.disclose > summary .section-title::before {
  content: "\25B8\00a0";
  color: var(--color-text-300, #8a8a8a);
}
.disclose[open] > summary .section-title::before {
  content: "\25BE\00a0";
}
.disclose > summary .section-title {
  display: inline-block;
}

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

@media (min-width: 768px) {
  .dash__title {
    font-size: 36px;
  }
}

.dash__subtitle {
  margin: 8px 0 0;
  color: var(--color-text-700);
}

.stat-row {
  display: grid;
  gap: 12px;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin-bottom: 24px;
}

.stat {
  background: var(--color-background-50);
  border-radius: 12px;
  padding: 20px;
  display: grid;
  gap: 2px;
}

.stat__value {
  font-size: 32px;
  font-weight: 700;
  color: var(--color-text-500);
  line-height: 1.1;
}

.stat__label {
  font-size: 14px;
  color: var(--color-text-700);
}

/* ---------------------------------------------------------- listing rows -- */

.listing-rows {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 12px;
}

.listing-row {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  padding: 16px;
  background: var(--color-background-50);
  border-radius: 12px;
}

.listing-row__img {
  width: 80px;
  height: 100px;
  object-fit: cover;
  border-radius: 8px;
  background: var(--fade-in-bg);
  mix-blend-mode: darken;
  flex-shrink: 0;
}

.listing-row__main {
  flex: 1 1 260px;
  min-width: 0;
}

.listing-row__name {
  font-size: 17px;
  margin-bottom: 4px;
}

.listing-row__meta,
.listing-row__desc {
  margin: 0 0 6px;
  font-size: 14px;
  color: var(--color-text-700);
}

.listing-row__desc {
  max-width: 60ch;
}

.listing-row__note {
  margin: 8px 0 0;
  font-size: 14px;
  color: #8c2f2f;
}

.listing-row__preview {
  display: inline-block;
  margin-top: 8px;
  font-size: 14px;
  font-weight: 700;
  color: var(--color-text-500);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.listing-row__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 8px;
  margin-left: auto;
}

.listing-row__actions .button {
  height: 40px;
  padding-inline: 14px;
  font-size: 15px;
}

.listing-row__actions--review {
  flex-direction: column;
  align-items: stretch;
  min-width: 220px;
}

.reject-form {
  display: flex;
  gap: 8px;
}

.reject-note {
  flex: 1;
  min-width: 0;
  height: 40px;
  padding: 0 10px;
  border: 1px solid var(--color-background-700);
  border-radius: 8px;
  background: transparent;
  color: var(--color-text-500);
  outline: none;
}

.reject-note:focus {
  border-color: var(--color-primary-500);
}

.button--danger {
  border-color: #d9a7a7;
  color: #8c2f2f;
}

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

/* ------------------------------------------------------------- badges ----- */

.status {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.02em;
}

.status--approved {
  background: #e6f4ea;
  color: #1e6b38;
}

.status--pending {
  background: #fdf3e0;
  color: #8a5a12;
}

.status--rejected {
  background: #fdf1f1;
  color: #8c2f2f;
}

.role-badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  text-transform: capitalize;
  background: var(--color-secondary-600);
  color: var(--color-text-500);
}

.role-badge--admin {
  background: var(--color-primary-500);
  color: #fff;
}

.role-badge--vendor {
  background: var(--color-text-500);
  color: #fff;
}

.role-badge--rep {
  background: #22662c;
  color: #fff;
}

.pill {
  display: inline-block;
  min-width: 20px;
  padding: 0 6px;
  border-radius: 999px;
  background: var(--color-primary-500);
  color: #fff;
  font-size: 12px;
  font-weight: 700;
  line-height: 20px;
  text-align: center;
}

/* ---------------------------------------------------------------- tabs ---- */

.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 20px;
}

.tab {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 40px;
  padding-inline: 16px;
  border-radius: 8px;
  background: var(--color-background-50);
  color: var(--color-text-700);
  font-weight: 700;
}

.tab:hover {
  background: var(--color-secondary-600);
}

.tab.is-active {
  background: var(--color-primary-500);
  color: #fff;
}

.tab.is-active .pill {
  background: #fff;
  color: var(--color-primary-500);
}

/* -------------------------------------------------------- empty + banner -- */

.empty-state {
  background: var(--color-background-50);
  border-radius: 12px;
  padding: 48px 24px;
  text-align: center;
  display: grid;
  gap: 8px;
  justify-items: center;
}

.empty-state h2 {
  font-size: 20px;
}

.empty-state p {
  margin: 0 0 8px;
  color: var(--color-text-700);
}

.preview-banner {
  margin-bottom: 20px;
  padding: 14px 16px;
  border-radius: 8px;
  background: #fdf3e0;
  color: #8a5a12;
  font-size: 15px;
}

/* -------------------------------------------------------- account panel --- */

.account-greeting {
  margin: 0 0 16px;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  color: var(--color-text-700);
}

.account-greeting strong {
  color: var(--color-text-500);
}

.account-signout {
  margin-top: 20px;
}

.account-signout .button {
  width: 100%;
}

.account-hint {
  margin-top: 16px;
  font-size: 14px;
  color: var(--color-text-700);
}

.account-links a {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* =========================================================================
   Inventory + Metrc intake
   ========================================================================= */

.section-title {
  font-size: 20px;
  margin: 40px 0 12px;
}

.section-subtitle {
  font-size: 15px;
  margin: 22px 0 8px;
  color: var(--color-text-700, #666);
}

.breadcrumb {
  margin: 0 0 8px;
  font-size: 14px;
}

.breadcrumb a,
.linked {
  color: var(--color-text-500);
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.form-actions--tight .button {
  flex: 0 0 auto;
}

.field-pair {
  display: grid;
  gap: 18px;
  grid-template-columns: 1fr 1fr;
}

.stat-row--4 {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}

/* Two stats, each half the row. The default 3-column grid left a seller with
   transport switched off looking at a third of a row of empty space. */
.stat-row--2 {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

/* A rate can be a five-figure sum in a narrow column. Let it shrink rather
   than push out of its box; the exact figure is on the title attribute. */
.stat__value {
  overflow-wrap: anywhere;
}

@media (max-width: 640px) {
  .stat-row,
  .stat-row--4,
  .stat-row--2,
  .field-pair,
  .choice-grid {
    grid-template-columns: 1fr 1fr;
  }
}

.stat--warn .stat__value {
  color: #8a5a12;
}

.stat--danger .stat__value {
  color: #8c2f2f;
}

/* ---------------------------------------------------------------- tables -- */

.table-scroll {
  overflow-x: auto;
  background: var(--color-background-50);
  border-radius: 12px;
}

.inv-table {
  width: 100%;
  border-collapse: collapse;
  min-width: 720px;
}

.inv-table th,
.inv-table td {
  padding: 12px 16px;
  text-align: left;
  vertical-align: middle;
  border-bottom: 1px solid var(--color-background-600);
}

.inv-table thead th {
  font-size: 13px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--color-text-700);
  white-space: nowrap;
}

.inv-table tbody tr:last-child th,
.inv-table tbody tr:last-child td {
  border-bottom: 0;
}

.inv-table .num {
  text-align: right;
}

.inv-table .mono,
.mono {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px;
}

.inv-product {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 260px;
}

.inv-product img {
  width: 40px;
  height: 50px;
  object-fit: cover;
  border-radius: 6px;
  background: var(--fade-in-bg);
  mix-blend-mode: darken;
  flex-shrink: 0;
}

.inv-name {
  display: block;
  font-weight: 700;
  color: var(--color-text-500);
}

.inv-sku {
  display: block;
  font-size: 13px;
  font-weight: 500;
  color: var(--color-text-700);
}

.table-note {
  margin: 10px 2px 0;
  font-size: 14px;
  color: var(--color-text-700);
}

/* --------------------------------------------------------------- stepper -- */

.stepper {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.stepper__btn {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  border: 1px solid var(--color-background-700);
  color: var(--color-text-500);
  font-weight: 700;
  line-height: 1;
}

.stepper__btn:hover {
  background: var(--color-secondary-600);
}

.stepper__input,
.inline-input {
  width: 72px;
  height: 32px;
  padding: 0 8px;
  text-align: right;
  border: 1px solid var(--color-background-700);
  border-radius: 8px;
  background: transparent;
  color: var(--color-text-500);
  outline: none;
  -moz-appearance: textfield;
}

.stepper__input::-webkit-outer-spin-button,
.stepper__input::-webkit-inner-spin-button,
.inline-input::-webkit-outer-spin-button,
.inline-input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.stepper__input:focus,
.inline-input:focus,
.inline-select:focus {
  border-color: var(--color-primary-500);
}

.inline-input.is-saved,
.stepper__input.is-saved {
  border-color: #7fb894;
}

.inline-select {
  height: 40px;
  min-width: 240px;
  max-width: 100%;
  padding: 0 10px;
  border: 1px solid var(--color-background-700);
  border-radius: 8px;
  background: var(--color-background-50);
  color: var(--color-text-500);
  font: inherit;
  outline: none;
}

/* ------------------------------------------------------------ stock chips -- */

.stock-chip {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  white-space: nowrap;
}

.stock-chip--ok {
  background: #e6f4ea;
  color: #1e6b38;
}

.stock-chip--low {
  background: #fdf3e0;
  color: #8a5a12;
}

.stock-chip--out {
  background: #fdf1f1;
  color: #8c2f2f;
}

/* Takes over the pull-up under the price, since it now sits above .stock-line. */
.case-line {
  margin: -20px 0 6px;
  font-size: 14px;
  color: var(--color-text-700);
}

.case-line strong {
  color: var(--color-text-500);
}

.stock-line {
  margin: -20px 0 24px;
  font-size: 15px;
  font-weight: 700;
}

/* Only the first of the pair pulls up; otherwise they overlap. */
.case-line + .stock-line {
  margin-top: 0;
}

/* Which regime the listing is under, on the detail page. Wraps as a block so
   the badge and its sentence stay together at narrow widths instead of the
   explanation orphaning onto its own line. */
.case-line--regime {
  margin: 0 0 14px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  line-height: 1.4;
}

.case-line + .case-line--regime {
  margin-top: 8px;
}

.stock-line--ok {
  color: #1e6b38;
}
.stock-line--low {
  color: #8a5a12;
}
.stock-line--out {
  color: #8c2f2f;
}

.sold-out {
  position: absolute;
  top: 10px;
  left: 10px;
  padding: 4px 10px;
  border-radius: 999px;
  background: rgb(255 255 255 / 0.92);
  color: #8c2f2f;
  font-size: 12px;
  font-weight: 700;
}

/* Same pill as Out of stock, different message — Private is a state of
   access, not a defect, so it drops the alarm red. */
.sold-out--private {
  color: #3f3f74;
}

.card-product__quickbuy[disabled],
.add-to-cart[disabled] {
  opacity: 0.45;
  cursor: not-allowed;
}

.add-to-cart[disabled]:hover {
  background: var(--color-primary-500);
}

/* -------------------------------------------------------------- notices --- */

.notice {
  padding: 14px 16px;
  border-radius: 8px;
  margin-bottom: 20px;
  font-size: 15px;
  background: var(--color-background-50);
  border: 1px solid var(--color-background-700);
  color: var(--color-text-700);
}

.notice--ok {
  background: #e6f4ea;
  border-color: #c3e2ce;
  color: #1e6b38;
}

.notice--warn {
  background: #fdf3e0;
  border-color: #edd6ab;
  color: #8a5a12;
}

.notice code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px;
  background: rgb(0 0 0 / 0.05);
  padding: 1px 5px;
  border-radius: 4px;
}

/* --------------------------------------------------------- transfer lines - */

.line-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 12px;
}

.line {
  display: grid;
  gap: 20px;
  padding: 20px;
  background: var(--color-background-50);
  border-radius: 12px;
}

@media (min-width: 900px) {
  .line {
    grid-template-columns: 1fr 420px;
  }
}

.line--done {
  opacity: 0.75;
}

.line__label {
  margin: 0 0 6px;
  color: var(--color-text-700);
}

/* The case count leads the row: it is the quantity being bought and sold, and
   it replaced the package tag that used to sit here. */
.line__cases {
  display: flex;
  align-items: baseline;
  gap: 5px;
  margin: 0 0 4px;
  font-size: 14px;
  color: var(--color-text-700);
}

.case-count {
  font-size: 22px;
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--color-text-500);
}

.case-size {
  color: var(--color-text-700);
}

.warn {
  color: #a2521a;
  font-weight: 700;
}

/* Collapsed rows must never hide which physical packages they stand for, so the
   tags stay one click away rather than being dropped. */
.line__tags {
  margin: 8px 0 0;
  font-size: 13px;
}

.line__tags > summary {
  cursor: pointer;
  color: var(--color-text-700);
  width: fit-content;
}

.line__tags > summary:hover {
  color: var(--color-text-500);
}

/* Where the cases in one row came from, when they span more than one batch. */
.batch-list {
  margin: 6px 0 0;
  padding: 8px 10px;
  list-style: none;
  border-radius: 8px;
  background: var(--color-background-500);
}

.batch-list li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  font-size: 12px;
  line-height: 1.9;
  color: var(--color-text-700);
}

.batch-list__count {
  flex-shrink: 0;
  font-weight: 700;
  color: var(--color-text-500);
}

.tag-list {
  margin: 6px 0 0;
  padding: 8px 10px;
  list-style: none;
  border-radius: 8px;
  background: var(--color-background-500);
}

.tag-list li {
  font-size: 12px;
  line-height: 1.7;
  color: var(--color-text-700);
}

.line__name {
  font-size: 17px;
  margin-bottom: 4px;
}

.line__meta {
  margin: 0 0 4px;
  font-size: 14px;
  color: var(--color-text-700);
}

.line__hint {
  margin: 8px 0 0;
  font-size: 13px;
  color: var(--color-text-700);
}

.line__map {
  display: grid;
  gap: 10px;
  align-content: start;
}

.map-form,
.receive-form {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.map-form .button,
.receive-form .button {
  height: 40px;
  padding-inline: 14px;
  font-size: 15px;
}

.receive-form .inline-input {
  height: 40px;
  width: 90px;
}

.empty-state--tight {
  padding: 24px;
}

/* =========================================================================
   Mobile — matches the live theme's small-screen header, plus responsive
   treatments for the marketplace screens the original doesn't have.
   ========================================================================= */

@media (max-width: 767px) {

  /* ------------------------------------------------------------- header -- */

  .page-header {
    padding: 16px 24px;
  }

  .page-header__inner {
    gap: 8px;
  }

  /* Icon-only, no pill — same as the theme's max-md treatment. */
  .menu-button {
    width: 40px;
    height: 40px;
    padding: 0;
    gap: 0;
    background: transparent;
  }

  .menu-button:hover {
    background: var(--color-secondary-600);
  }

  .menu-button__label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
  }

  .header-logo {
    height: 40px;
  }

  .header-logo img {
    height: 18px;
  }

  .header-right {
    gap: 0;
  }

  .header-right .icon-button,
  .menu-button {
    width: 40px;
    height: 40px;
    padding: 0;
  }

  /* Phones keep the surface too. Stripping the fill here saved nothing —
     the button is the same 40px either way — and it was the width where
     the icons vanished hardest against the frosted header, because they had
     neither a fill nor a border to stand on. */
  .header-right .icon-button {
    background: var(--color-background-50);
  }

  .cart-badge {
    top: 2px;
    right: 2px;
  }

  .main {
    padding-top: 8px;
  }

  /* ------------------------------------------------------------- cards --- */

  /* Leave room for the quick-buy button pinned to the right of the card body. */
  .card-product__name,
  .card-product__seller {
    width: calc(100% - 40px);
  }

  /* Type was sized for a full-width card. In the two-column grid the card is
     ~162px, where 16px runs a product name to three lines and pushes the next
     row of products off the screen. */
  .card-product__name {
    font-size: 13px;
    line-height: 1.3;
  }

  .card-product__seller,
  .card-product__price {
    font-size: 12px;
    line-height: 1.4;
  }

  .card-product__body {
    gap: 2px;
  }

  /* The button is 24px of icon in a 40px gutter; at this card width that gutter
     is a quarter of the row, so tighten it to match the smaller type. */
  .card-product__quickbuy svg {
    width: 20px;
    height: 20px;
  }

  /* ------------------------------------------------------ product page --- */

  /* Full-bleed gallery, like the theme's mobile carousel. */
  .gallery {
    margin-inline: -16px;
    padding-bottom: 20px;
    gap: 8px;
  }

  .gallery__figure {
    border-radius: 0;
    cursor: default;
  }

  .product-title {
    font-size: 22px;
  }

  .stock-line {
    margin-top: -16px;
    margin-bottom: 20px;
  }

  /* Stepper on one line, Add to cart full width beneath it. */
  .add-to-cart {
    flex: 1 0 100%;
  }

  .reviews {
    padding-top: 32px;
    margin-top: 32px;
  }

  /* --------------------------------------------------- similar products -- */

  /* Cards peek past the edge so the rail reads as scrollable without arrows. */
  .similar__nav {
    display: none;
  }

  .similar__rail {
    scroll-padding-inline: 16px;
    gap: 10px;
    -webkit-overflow-scrolling: touch;
  }

  .similar__item {
    width: 68vw;
    max-width: 280px;
  }

  .similar__title {
    font-size: 20px;
  }

  /* ------------------------------------------------------------- forms --- */

  .choice-grid,
  .field-pair,
  .form-actions {
    grid-template-columns: 1fr;
  }

  .form-actions {
    display: grid;
  }

  /* Was grid-auto-flow: column with auto-columns — which forced EVERY child
     into its own equal column on a phone, no wrapping. Three buttons at 375px
     got ~115px each and "Add a product" / "Incoming transfers" were clipped
     mid-word. Two columns that wrap, and the primary action takes a full row
     of its own below them (Nick's call). */
  .form-actions--tight {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .form-actions__primary {
    grid-column: 1 / -1;
  }

  .stacked-form {
    padding: 20px 16px;
  }

  .form-page__title,
  .dash__title {
    font-size: 26px;
  }

  .dash__head {
    gap: 12px;
  }

  /* Keep tap targets comfortable. */
  .field input,
  .field textarea,
  .inline-select {
    font-size: 16px; /* stops iOS zooming on focus */
  }

  .inline-select {
    min-width: 0;
    width: 100%;
  }

  /* ------------------------------------------------------------ tables --- */

  /* Restack rows as cards instead of forcing a horizontal scroll. */
  .table-scroll {
    background: transparent;
    overflow-x: visible;
  }

  .inv-table,
  .inv-table tbody,
  .inv-table tr,
  .inv-table td {
    display: block;
    width: auto;
    min-width: 0;
  }

  .inv-table thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
  }

  .inv-table tr {
    background: var(--color-background-50);
    border-radius: 12px;
    padding: 14px 16px;
    margin-bottom: 10px;
  }

  .inv-table th[scope="row"] {
    display: flex;
    /* Flex drops whitespace-only text nodes, so the markup's space between
       a row label and a trailing marker vanishes and they render touching
       ("Transporter licenseoptional"). The sibling td rule already carries a
       gap; this one did not. Wrap, because a long license name plus its
       marker does not fit on one line at 375px. */
    gap: 8px;
    align-items: baseline;
    flex-wrap: wrap;
    width: auto;
    padding: 0 0 10px;
    border: 0;
    font-size: 16px;
  }

  .inv-table td {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 6px 0;
    border: 0;
    text-align: left;
  }

  .inv-table td:empty {
    display: none;
  }

  .inv-table td {
    text-align: right;
  }

  .inv-table td::before {
    content: attr(data-label);
    flex-shrink: 0;
    margin-right: auto;
    text-align: left;
    font-size: 13px;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--color-text-700);
  }

  .cell-stack {
    display: block;
    min-width: 0;
  }

  .inv-table td[data-label=""]::before {
    content: none;
  }

  .inv-table td[data-label=""] {
    padding-top: 12px;
  }

  .inv-table td[data-label=""] .button {
    width: 100%;
  }

  .inv-table .mono {
    word-break: break-all;
    text-align: right;
  }

  .inv-product {
    min-width: 0;
  }

  .stepper__btn {
    width: 36px;
    height: 36px;
  }

  .stepper__input,
  .inline-input {
    height: 36px;
  }

  /* ------------------------------------------------------ listing rows --- */

  .listing-row__actions,
  .listing-row__actions--review {
    margin-left: 0;
    width: 100%;
    min-width: 0;
  }

  .listing-row__actions .button,
  .listing-row__actions form {
    flex: 1 1 100px;
  }

  .listing-row__actions form .button {
    width: 100%;
  }

  .listing-row__img {
    width: 64px;
    height: 80px;
  }

  /* ------------------------------------------------- metrc transfer UI --- */

  .map-form,
  .receive-form {
    flex-direction: column;
    align-items: stretch;
    /* Inherited flex-wrap:wrap would make a column container wrap into a second
       *column*, putting the button beside the field and reserving dead height. */
    flex-wrap: nowrap;
  }

  .receive-form .inline-input {
    width: 100%;
    height: 44px;
    text-align: center;
  }

  /* In a column flex container these are main-axis sized, so they shrink unless
     told not to — which drops them under the 44px touch minimum. */
  .map-form .button,
  .receive-form .button {
    height: 44px;
    min-height: 44px;
    flex-shrink: 0;
  }

  .line {
    padding: 16px;
  }

  .line__label {
    word-break: break-all;
  }

  .tabs {
    overflow-x: auto;
    flex-wrap: nowrap;
    padding-bottom: 4px;
    margin-inline: -16px;
    padding-inline: 16px;
  }

  .tab {
    flex-shrink: 0;
    height: 44px;
  }

  /* Drawer controls were inheriting text-sized hit areas. */
  .panel-close {
    min-height: 44px;
    padding-inline: 4px;
  }

  .cart-line__remove {
    min-width: 44px;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: flex-end;
  }

  /* ------------------------------------------------------------ panels --- */

  .panel--menu,
  .panel--account {
    --panel-width: min(86vw, 340px);
  }

  .panel--search,
  .panel--cart {
    --panel-width: 100vw;
  }

  .notice,
  .preview-banner,
  .flash {
    font-size: 14px;
  }
}

/* Very narrow phones */
@media (max-width: 380px) {
  .stat-row,
  .stat-row--4 {
    grid-template-columns: 1fr 1fr;
  }

  .similar__item {
    width: 74vw;
  }
}

/* ------------------------------------------------- poller + credit routing -- */

.poll-bar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  margin-bottom: 20px;
  border-radius: 12px;
  background: var(--color-background-50);
  font-size: 14px;
  color: var(--color-text-700);
}

.poll-bar--off {
  background: #fdf3e0;
  color: #8a5a12;
}

.poll-bar__text {
  flex: 1;
  min-width: 0;
}

.poll-bar__text strong {
  color: var(--color-text-500);
}

.poll-bar__err {
  display: block;
  margin-top: 4px;
  color: #8c2f2f;
  word-break: break-word;
}

.poll-dot {
  width: 9px;
  height: 9px;
  border-radius: 999px;
  background: var(--color-secondary-700);
  flex-shrink: 0;
}

.poll-dot--on {
  background: #2f9e5a;
  box-shadow: 0 0 0 0 rgb(47 158 90 / 0.5);
  animation: poll-pulse 2.4s ease-out infinite;
}

@keyframes poll-pulse {
  70% { box-shadow: 0 0 0 7px rgb(47 158 90 / 0); }
  100% { box-shadow: 0 0 0 0 rgb(47 158 90 / 0); }
}

@media (prefers-reduced-motion: reduce) {
  .poll-dot--on { animation: none; }
}

.credit {
  margin: 10px 0 0;
  padding: 8px 12px;
  border-radius: 8px;
  font-size: 14px;
}

.credit--note {
  background: #eef2fd;
  color: #2f4a8c;
}

.credit--license {
  background: #e6f4ea;
  color: #1e6b38;
}

.credit--none {
  background: #fdf3e0;
  color: #8a5a12;
}

.line__note {
  margin: 8px 0 0;
  padding: 8px 12px;
  border-radius: 8px;
  background: var(--color-background-500);
  font-size: 13px;
  color: var(--color-text-700);
  word-break: break-word;
}

.notice__runs {
  display: block;
  margin-top: 10px;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}

.run-chip {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--color-secondary-500);
  color: var(--color-text-700);
  font-size: 12px;
  white-space: nowrap;
}

.run-chip--bad {
  background: #fdf1f1;
  color: #8c2f2f;
}

.table-note--lead {
  margin: -4px 2px 12px;
}

/* ------------------------------------------------- intake search + combobox -- */

.queue-tools {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 14px;
}

.queue-search {
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
  min-width: 0;
  height: 44px;
  padding: 0 14px;
  border: 1px solid var(--color-background-700);
  border-radius: 10px;
  background: var(--color-background-50);
  color: var(--color-text-700);
}

.queue-search:focus-within {
  border-color: var(--color-primary-500);
}

.queue-search input {
  flex: 1;
  min-width: 0;
  border: 0;
  outline: none;
  background: transparent;
  color: var(--color-text-500);
}

.queue-count {
  flex-shrink: 0;
  font-size: 14px;
  color: var(--color-text-700);
  white-space: nowrap;
}

.queue-empty {
  padding: 32px;
  text-align: center;
  color: var(--color-text-700);
  background: var(--color-background-50);
  border-radius: 12px;
}

/* suggestion chips */

.suggests {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin-bottom: 4px;
}

/* Its own row: as a plain flex item the label sat inline with the first chip
   and only the overflow wrapped beneath it. 100% basis forces the break. */
.suggests__label {
  flex: 0 0 100%;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-text-700);
}

.suggest-chip {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  max-width: 100%;
  padding: 5px 10px;
  border: 1px solid var(--color-background-700);
  border-radius: 999px;
  background: var(--color-background-50);
  font-size: 13px;
  color: var(--color-text-500);
  text-align: left;
  transition: border-color 0.15s ease, background-color 0.15s ease;
}

.suggest-chip:hover {
  border-color: var(--color-primary-500);
  background: var(--color-secondary-500);
}

.suggest-chip--top {
  border-color: #7fb894;
  background: #e6f4ea;
  color: #1e6b38;
  font-weight: 700;
}

/* A different listing was chosen, so the recommendation is no longer the
   answer — drop it to neutral rather than showing two "correct" states. */
.suggest-chip--muted {
  border-color: var(--color-background-700);
  background: var(--color-background-50);
  color: var(--color-text-700);
  font-weight: 500;
}

.suggest-chip--muted:hover {
  border-color: var(--color-primary-500);
  background: var(--color-secondary-500);
}

.suggest-chip.is-chosen {
  border-color: #2f9e5a;
  background: #e6f4ea;
  color: #1e6b38;
  font-weight: 700;
}

.suggest-chip.is-chosen::before {
  content: "✓";
  font-size: 11px;
}

.suggest-chip__sku {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  opacity: 0.7;
}

/* combobox */

.combo {
  position: relative;
  flex: 1 1 260px;
  min-width: 0;
}

.combo__input {
  width: 100%;
  height: 40px;
  padding: 0 34px 0 12px;
  font-size: 14px;
  border: 1px solid var(--color-background-700);
  border-radius: 8px;
  background: var(--color-background-50);
  color: var(--color-text-500);
  outline: none;
}

.combo__input:focus {
  border-color: var(--color-primary-500);
}

/* Smaller than the value text so the hint fits a narrow field. */
.combo__input::placeholder {
  font-size: 13px;
  color: var(--color-text-700);
  opacity: 0.85;
}

.combo--set .combo__input {
  border-color: #7fb894;
  font-weight: 700;
}

.combo__clear {
  position: absolute;
  top: 0;
  right: 0;
  width: 34px;
  height: 40px;
  font-size: 20px;
  line-height: 1;
  color: var(--color-text-700);
}

.combo__clear:hover {
  color: var(--color-text-50);
}

.combo__list {
  position: absolute;
  z-index: 40;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  max-height: 300px;
  overflow-y: auto;
  margin: 0;
  padding: 4px;
  list-style: none;
  background: var(--color-background-50);
  border: 1px solid var(--color-background-700);
  border-radius: 10px;
  box-shadow: 0 12px 28px rgb(0 0 0 / 0.12);
}

.combo__opt {
  display: grid;
  gap: 1px;
  padding: 8px 10px;
  border-radius: 6px;
  cursor: pointer;
}

.combo__opt:hover,
.combo__opt.is-active {
  background: var(--color-secondary-500);
}

.combo__name {
  font-size: 14px;
  font-weight: 700;
  color: var(--color-text-500);
}

.combo__meta {
  font-size: 12px;
  color: var(--color-text-700);
}

.combo__list mark {
  background: #fdf3c0;
  color: inherit;
  border-radius: 2px;
}

.combo__empty {
  padding: 10px;
  font-size: 13px;
  color: var(--color-text-700);
}

@media (max-width: 767px) {
  .queue-tools {
    flex-wrap: wrap;
  }
  .queue-search {
    flex: 1 1 100%;
    height: 48px;
  }
  .queue-search input {
    font-size: 16px;
  }
  .combo__input {
    height: 44px;
    font-size: 16px;
  }
  .combo__clear {
    height: 44px;
  }
  .suggest-chip {
    max-width: 100%;
  }
}

/* ------------------------------------------------- combobox selected card -- */

.combo__field {
  position: relative;
}

/* The card is a sibling of the form inside .line__map, so it spans the whole
   column rather than sharing a flex row with the Save button. */
.combo__detail--above {
  margin-bottom: 2px;
}

.combo__detail--below {
  margin-top: 2px;
}

.combo__detail {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid #7fb894;
  border-left-width: 3px;
  border-radius: 10px;
  background: #f2f9f4;
}

.combo__check {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 999px;
  background: #2f9e5a;
  color: #fff;
}

.combo__thumb {
  flex-shrink: 0;
  width: 34px;
  height: 42px;
  object-fit: cover;
  border-radius: 6px;
  background: var(--fade-in-bg);
  mix-blend-mode: darken;
}

.combo__detail-text {
  display: grid;
  gap: 2px;
  min-width: 0;
  flex: 1;
}

.combo__detail-eyebrow {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: #1e6b38;
}

/* Wraps rather than truncating — seeing the whole title is the point. */
.combo__detail-name {
  font-size: 14px;
  font-weight: 700;
  line-height: 1.3;
  color: var(--color-text-500);
  overflow-wrap: anywhere;
}

.combo__detail-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--color-text-700);
}

.combo__change {
  flex-shrink: 0;
  align-self: flex-start;
  padding: 4px 10px;
  border: 1px solid #7fb894;
  border-radius: 999px;
  background: transparent;
  font-size: 12px;
  font-weight: 700;
  color: #1e6b38;
}

.combo__change:hover {
  background: #e6f4ea;
}

/* With the card carrying the detail, a committed field just invites a new search. */
.combo--set .combo__input {
  border-color: var(--color-background-700);
  font-weight: 500;
}

/* ---------------------------------------------------------- variant demo -- */

.variant {
  background: var(--color-background-50);
  border-radius: 12px;
  padding: 20px;
  margin-bottom: 20px;
}

.variant__head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 4px;
}

.variant__tag {
  display: inline-block;
  padding: 2px 10px;
  border-radius: 999px;
  background: var(--color-primary-500);
  color: #fff;
  font-size: 12px;
  font-weight: 700;
}

.variant__note {
  margin: 0 0 16px;
  font-size: 14px;
  color: var(--color-text-700);
}

.variant .line-list {
  margin: 0;
}

@media (max-width: 767px) {
  .combo__detail {
    flex-wrap: wrap;
  }
  .combo__change {
    margin-left: auto;
  }
}

/* --------------------------------------------- intake queue on small screens -- */

@media (max-width: 767px) {
  /* Chips hold long product titles; let them wrap instead of overflowing. */
  .suggest-chip {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    width: 100%;
    border-radius: 10px;
    padding: 8px 10px;
    font-size: 14px;
  }

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

  .suggests__label {
    margin-bottom: 2px;
  }

  /* Full-width controls: the map form already stacks, keep the parts matched. */
  .combo {
    flex: 1 1 100%;
  }

  .combo__input {
    height: 44px;
    font-size: 16px; /* keeps iOS from zooming on focus */
  }

  .combo__input::placeholder {
    font-size: 14px;
  }

  .combo__clear {
    height: 44px;
  }

  .combo__list {
    max-height: 50vh;
  }

  .combo__opt {
    padding: 10px;
  }

  .combo__detail {
    align-items: flex-start;
    padding: 12px;
  }

  .combo__detail-name {
    font-size: 15px;
  }

  .combo__change {
    order: 3;
    width: 100%;
    min-height: 44px;
    margin-top: 8px;
    padding: 8px;
    text-align: center;
  }

  /* Stretch the field to its label so a tap anywhere in the box lands on it. */
  .queue-search input {
    align-self: stretch;
  }

  .line__map {
    gap: 8px;
  }

  .line__metrc {
    padding-bottom: 4px;
    border-bottom: 1px solid var(--color-background-600);
  }

  /* Manifest/package identifiers are long strings of digits. */
  .line__meta .mono,
  .credit .mono {
    overflow-wrap: anywhere;
  }

  .queue-tools {
    position: sticky;
    top: 76px;
    z-index: 20;
    padding: 8px 0;
    margin-inline: -16px;
    padding-inline: 16px;
    background: var(--color-background-500);
  }

  .queue-count {
    flex: 1 1 100%;
    text-align: right;
  }

  .variant {
    padding: 16px 12px;
  }
}

/* ------------------------------------------------------- read-only stock -- */

.stock-count {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  font-size: 15px;
  color: var(--color-text-500);
}

.readonly-value {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: 0;
  padding: 10px 12px;
  border: 1px dashed var(--color-background-700);
  border-radius: 8px;
  background: var(--color-background-500);
}

.readonly-value strong {
  font-size: 18px;
  color: var(--color-text-500);
}

.readonly-value span {
  font-size: 13px;
  color: var(--color-text-700);
}

/* ------------------------------------------------------------ intake nav -- */

.icon-button--intake {
  position: relative;
}

/* Same badge treatment as the cart, so the two read as one row of tools. */
.intake-badge {
  position: absolute;
  top: 6px;
  right: 6px;
  min-width: 18px;
  height: 18px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--color-primary-500);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  line-height: 18px;
  text-align: center;
}

/* ---------------------------------------------------- product copy blocks -- */

.product-short {
  margin: 0 0 12px;
  font-size: 15px;
  line-height: 1.55;
  color: var(--color-text-600);
}

.product-meta__muted {
  color: var(--color-text-700);
}

/* --------------------------------------------------------- coa directory -- */

.coa-flag {
  display: inline-block;
  padding: 1px 7px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.02em;
  vertical-align: middle;
}

.coa-flag--pass {
  background: #e7f4ea;
  color: #17692e;
}

.coa-flag--fail {
  background: #fdeceb;
  color: #a11c15;
}

.field__optional {
  margin-left: 6px;
  font-size: 12px;
  font-weight: 400;
  color: var(--color-text-700);
  text-transform: none;
}

.coa-index {
  max-width: 860px;
  margin-inline: auto;
  padding-block: 24px 48px;
}

.coa-index__back {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-bottom: 16px;
  font-size: 14px;
  font-weight: 700;
  color: var(--color-text-600);
}

.coa-index__back:hover {
  color: var(--color-text-400);
}

.coa-index__title {
  margin: 0;
  font-size: 30px;
  line-height: 1.2;
  color: var(--color-text-400);
}

.coa-index__subtitle {
  margin: 6px 0 0;
  color: var(--color-text-600);
}

.coa-index__note {
  margin: 12px 0 0;
  max-width: 62ch;
  font-size: 13px;
  line-height: 1.55;
  color: var(--color-text-700);
}

.coa-index__list {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin: 28px 0 0;
  padding: 0;
  list-style: none;
}

.coa-entry {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  padding: 18px;
  border: 1px solid var(--color-background-700);
  border-radius: 12px;
  background: var(--color-background-50);
}

.coa-entry__main {
  flex: 1 1 auto;
  min-width: 0;
}

/* The date the certificate joined this listing — the label the list is read by. */
.coa-entry__added {
  margin: 0 0 4px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-text-700);
}

.coa-entry__title {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin: 0;
  font-size: 18px;
  color: var(--color-text-400);
}

.coa-entry__facts {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 24px;
  margin: 12px 0 0;
}

.coa-entry__facts div {
  display: flex;
  gap: 6px;
  font-size: 13px;
}

.coa-entry__facts dt {
  color: var(--color-text-700);
}

.coa-entry__facts dd {
  margin: 0;
  color: var(--color-text-500);
  overflow-wrap: anywhere;
}

.coa-entry__analytes {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 14px;
}

.coa-analyte {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--color-background-500);
  font-size: 12px;
  color: var(--color-text-700);
}

.coa-analyte strong {
  color: var(--color-text-500);
  font-variant-numeric: tabular-nums;
}

.coa-analyte--fail {
  background: #fdeceb;
  color: #a11c15;
}

.coa-analyte--fail strong {
  color: #a11c15;
}

.coa-entry__actions {
  flex: 0 0 auto;
}

@media (max-width: 767px) {
  .coa-index__title {
    font-size: 24px;
  }

  .coa-entry {
    flex-wrap: wrap;
    padding: 14px;
  }

  .coa-entry__facts {
    flex-direction: column;
    flex-wrap: nowrap;
    gap: 4px;
  }

  .coa-entry__actions {
    flex: 1 1 100%;
  }

  .coa-entry__actions .button {
    width: 100%;
    min-height: 44px;
  }
}

/* ------------------------------------------------------- browse + paging -- */

.browse-head {
  padding: 24px 0 8px;
}

.browse-head__title {
  margin: 0;
  font-size: 28px;
  line-height: 1.2;
  color: var(--color-text-400);
}

.browse-head__count {
  margin: 4px 0 0;
  font-size: 14px;
  color: var(--color-text-700);
}

.facets {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px 0 20px;
}

.facets__group {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
}

.facets__label {
  flex: 0 0 auto;
  min-width: 56px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-text-700);
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border: 1px solid var(--color-background-700);
  border-radius: 999px;
  background: var(--color-background-50);
  font-size: 13px;
  color: var(--color-text-600);
}

.chip:hover {
  background: var(--color-secondary-600);
}

.chip.is-active {
  background: var(--color-primary-500);
  border-color: var(--color-primary-500);
  color: #fff;
}

.chip__count {
  font-size: 11px;
  opacity: 0.7;
  font-variant-numeric: tabular-nums;
}

.pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  padding: 32px 0 48px;
}

.pager__status {
  font-size: 14px;
  color: var(--color-text-600);
  text-align: center;
}

.pager__total {
  color: var(--color-text-700);
}

/* Compact numbered pager. Buttons are 34px so they clear the 44px touch
   target once the 10px gap is counted, and the whole strip wraps rather
   than scrolling sideways on a narrow phone. */
.pager--compact {
  gap: 10px;
  padding: 20px 0 32px;
  flex-wrap: wrap;
}

.pager__pages {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-wrap: wrap;
  justify-content: center;
}

.pager__page,
.pager__step {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 34px;
  height: 34px;
  padding: 0 8px;
  border-radius: 8px;
  border: 1px solid transparent;
  font-size: 14px;
  line-height: 1;
  text-decoration: none;
  color: var(--color-text-700);
}

.pager__page:hover,
.pager__step:hover {
  background: var(--color-surface-alt, rgba(0, 0, 0, 0.04));
}

.pager__page--current {
  border-color: var(--color-border, #ddd);
  background: var(--color-surface-alt, rgba(0, 0, 0, 0.04));
  font-weight: 600;
  color: var(--color-text-900, inherit);
}

.pager__step {
  font-size: 20px;
}

/* Kept in the flow rather than hidden so the arrows do not shuffle
   sideways when you land on the first or last page. */
.pager__step--off {
  opacity: 0.3;
  cursor: default;
}

.pager__gap {
  padding: 0 2px;
  color: var(--color-text-600);
}

@media (max-width: 767px) {
  .browse-head__title {
    font-size: 22px;
  }

  .facets__group {
    /* Chips scroll sideways rather than stacking into a wall of rows. */
    flex-wrap: nowrap;
    overflow-x: auto;
    padding-bottom: 4px;
    -webkit-overflow-scrolling: touch;
  }

  .chip {
    flex: 0 0 auto;
    min-height: 36px;
  }

  .pager {
    gap: 10px;
  }

  .pager .button {
    padding-inline: 14px;
  }

  .pager__total {
    display: none;
  }
}

/* ------------------------------------------------------- fixed unit count -- */

/* The booked quantity is the manifest's, so it reads as a fact rather than a
   field. Same dashed treatment as the read-only stock box on the product form. */
.units-fixed {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: 0;
  padding: 8px 12px;
  border: 1px dashed var(--color-background-700);
  border-radius: 8px;
  background: var(--color-background-500);
  white-space: nowrap;
}

.units-fixed strong {
  font-size: 18px;
  font-variant-numeric: tabular-nums;
  color: var(--color-text-500);
}

.units-fixed span {
  font-size: 12px;
  color: var(--color-text-700);
}

@media (max-width: 767px) {
  .units-fixed {
    flex: 1 1 100%;
    white-space: normal;
  }
}

/* ------------------------------------------------------------ seller pages */

/* Built around the empty case. A seller who fills in nothing still gets a
   header with weight to it: the badge slot is always occupied — by a lettered
   tile when there is no picture — and the description is dropped entirely
   rather than left as a gap. Nothing here should read as "unfinished". */

.seller-head {
  display: flex;
  align-items: flex-start;
  gap: 28px;
  padding: 32px 0 28px;
  border-bottom: 1px solid var(--color-background-700);
  margin-bottom: 28px;
}

/* With no picture and no description there is far less to balance, so the
   whole block tightens rather than floating in space. */
.seller-head--bare {
  align-items: center;
  padding: 24px 0 20px;
  gap: 20px;
}

.seller-head__badge {
  flex-shrink: 0;
  width: 160px;
  height: 160px;
  border-radius: 16px;
  overflow: hidden;
  /* Not --color-background-500: that is the page background, and the tile
     vanished into it. 600 reads as a placed object against the page. */
  background: var(--color-background-600);
  display: grid;
  place-items: center;
}

.seller-head--bare .seller-head__badge {
  width: 104px;
  height: 104px;
  border-radius: 12px;
}

.seller-head__banner {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* The placeholder. Deliberately typographic rather than an icon — initials on a
   tinted tile look like a chosen mark, a grey image glyph looks like a 404. */
.seller-head__monogram {
  font-family: var(--font-heading-family, inherit);
  font-size: 54px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--color-text-500);
  opacity: 0.55;
  user-select: none;
}

.seller-head--bare .seller-head__monogram {
  font-size: 36px;
}

.seller-head__text {
  min-width: 0;
  flex: 1;
}

.seller-head__title {
  margin: 0;
  font-size: 32px;
  line-height: 1.15;
  color: var(--color-text-400);
  overflow-wrap: anywhere;
}

.seller-head__meta {
  margin: 8px 0 0;
  font-size: 14px;
  color: var(--color-text-700);
}

.seller-head__store {
  font-weight: 700;
  color: var(--color-text-500);
}

.seller-head__bio {
  margin-top: 14px;
  max-width: 62ch;
}

.seller-head__bio p {
  margin: 0 0 10px;
  font-size: 15px;
  line-height: 1.6;
  color: var(--color-text-500);
}

.seller-head__bio p:last-child {
  margin-bottom: 0;
}

.seller-head__actions {
  margin: 16px 0 0;
}

@media (max-width: 767px) {
  /* With something to read, the picture gets its own row and the text runs the
     full width beneath it. */
  .seller-head {
    flex-direction: column;
    align-items: flex-start;
    gap: 16px;
    padding: 20px 0 18px;
  }

  .seller-head__badge {
    width: 96px;
    height: 96px;
  }

  .seller-head__monogram {
    font-size: 34px;
  }

  .seller-head__title {
    font-size: 26px;
  }

  /* Nothing to read, so stacking only pushes the products further down the
     phone. Badge and title share a row and the whole header stays shallow. */
  .seller-head--bare {
    flex-direction: row;
    align-items: center;
    gap: 14px;
    padding: 16px 0 14px;
  }

  .seller-head--bare .seller-head__badge {
    width: 64px;
    height: 64px;
    border-radius: 10px;
  }

  .seller-head--bare .seller-head__monogram {
    font-size: 24px;
  }

  .seller-head--bare .seller-head__title {
    font-size: 22px;
  }

  .seller-head--bare .seller-head__meta {
    margin-top: 4px;
  }

  /* The owner's edit button would otherwise force the row taller than the
     badge; below the header it costs nothing. */
  .seller-head--bare .seller-head__actions {
    margin-top: 10px;
  }

  .seller-search {
    margin-bottom: 16px;
  }
}

/* -- the edit form -- */

.banner-field {
  display: flex;
  align-items: flex-start;
  gap: 16px;
}

.banner-field__preview {
  flex-shrink: 0;
  width: 120px;
  height: 120px;
  border-radius: 12px;
  overflow: hidden;
  background: var(--color-background-600);
  border: 1px solid var(--color-background-700);
  display: grid;
  place-items: center;
}

.banner-field__preview img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.banner-field__monogram {
  font-size: 40px;
  font-weight: 700;
  color: var(--color-text-500);
  opacity: 0.5;
}

.banner-field__controls {
  min-width: 0;
  flex: 1;
}

.banner-field__controls .field__hint {
  margin-top: 6px;
}

/* Scoped, because `.field label { display: block }` would otherwise stack the
   checkbox above its text — the same specificity trap as the COA picker. */
.field .choice--inline {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
  font-size: 14px;
  cursor: pointer;
}

.field__optional {
  margin-left: 6px;
  font-size: 12px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-700);
  opacity: 0.75;
}

@media (max-width: 600px) {
  .banner-field {
    flex-direction: column;
  }
}

/* -- admin index -- */

.seller-row {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}

.seller-row__badge {
  flex-shrink: 0;
  width: 36px;
  height: 36px;
  border-radius: 8px;
  overflow: hidden;
  background: var(--color-background-600);
  display: grid;
  place-items: center;
  font-size: 14px;
  font-weight: 700;
  color: var(--color-text-700);
}

.seller-row__badge img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.button--small {
  padding: 6px 12px;
  font-size: 13px;
}

.muted {
  color: var(--color-text-700);
  opacity: 0.7;
}

/* -- seller page search -- */

.seller-search {
  display: flex;
  align-items: center;
  gap: 8px;
  position: relative;
  margin: 0 0 20px;
  padding: 0 12px;
  border: 1px solid var(--color-background-700);
  border-radius: 999px;
  background: var(--color-background-50);
  transition: border-color 0.15s ease;
}

.seller-search:focus-within {
  border-color: var(--color-primary-500);
}

.seller-search__icon {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  color: var(--color-text-700);
}

.seller-search__input {
  flex: 1;
  min-width: 0;
  border: 0;
  outline: none;
  background: transparent;
  padding: 12px 0;
  font-family: inherit;
  font-size: 15px;
  color: var(--color-text-500);
}

/* Safari draws its own clear affordance on type=search, next to ours. */
.seller-search__input::-webkit-search-decoration,
.seller-search__input::-webkit-search-cancel-button {
  -webkit-appearance: none;
  appearance: none;
}

.seller-search__clear {
  flex-shrink: 0;
  width: 26px;
  height: 26px;
  border: 0;
  border-radius: 999px;
  background: var(--color-background-600);
  color: var(--color-text-500);
  font-size: 17px;
  line-height: 1;
  cursor: pointer;
}

.seller-search__clear:hover {
  background: var(--color-secondary-700);
}

.seller-search__go {
  flex-shrink: 0;
  padding: 8px 16px;
  font-size: 14px;
}

/* Dims the outgoing results while a request is in flight, rather than blanking
   them — a flash of empty grid between keystrokes reads as broken. */
.is-searching .product-grid {
  opacity: 0.55;
  transition: opacity 0.12s ease;
}

.seller-results__note {
  margin: 0 0 14px;
  font-size: 14px;
  color: var(--color-text-700);
}

.seller-results__note .linked {
  margin-left: 6px;
}

/* A submit button that has to read as a link inside a sentence. */
.linked--button {
  border: 0;
  padding: 0;
  background: none;
  font: inherit;
  color: inherit;
  cursor: pointer;
  text-decoration: underline;
}

@media (max-width: 600px) {
  /* The Search button is redundant on a phone: the keyboard has a Go key and
     results land as you type, so drop it and give the field the width. */
  .seller-search__go {
    display: none;
  }

  .seller-search__input {
    font-size: 16px; /* keeps iOS from zooming the page on focus */
  }
}

/* The escape hatch out of the ten-row dropdown and onto the results page. */
.search-all {
  margin: 16px 0 0;
}

.search-all .button {
  width: 100%;
  justify-content: center;
}

/* ------------------------------------------------------- sales & payouts */

/* Money direction reuses the status-pill palette: earned green, out red. */
.amount-in {
  color: #1e6b38;
  font-weight: 600;
}

.amount-out {
  color: #8c2f2f;
  font-weight: 600;
}

.ledger-filter {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  margin: 20px 0 16px;
}

.ledger-filter label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--color-text-600);
}

.ledger-filter .inline-input {
  width: auto;
}

.ledger-filter__note {
  margin-left: auto;
  font-size: 13px;
  color: var(--color-text-600);
}

.receipt-label {
  color: var(--color-text-600);
  font-size: 13px;
}

.receipt-net td {
  border-top: 2px solid var(--color-text-50);
  font-size: 15px;
  font-weight: 700;
}

.payout-form {
  display: flex;
  gap: 8px;
  align-items: center;
}

.payout-form .inline-input {
  width: 90px;
}

.payout-form .inline-input[name="note"] {
  width: 140px;
}

.cart-line__price {
  font-weight: 600;
  color: var(--color-text-100);
}

/* Two fields side by side, stacking on phones. */
.field-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}

.field-row .field {
  min-width: 0;
}

@media (max-width: 640px) {
  .field-row {
    grid-template-columns: 1fr;
  }
}

.pay-options {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  margin-top: 12px;
}

.pay-option {
  background: var(--color-background-500);
  border: 1px solid var(--color-secondary-700);
  border-radius: 12px;
  padding: 18px;
}

.pay-option h3 {
  margin: 0 0 8px;
  font-size: 15px;
}

.pay-option__id {
  font-size: 20px;
  font-weight: 700;
  letter-spacing: 0.04em;
  background: var(--color-background-600);
  border-radius: 8px;
  padding: 8px 12px;
  display: inline-block;
}

/* Two columns so the label sits beside its number: account and routing
   digits are transcribed by hand into a banking form, and a stacked list
   makes it far too easy to carry the wrong one across. */
.bank-details {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 4px 16px;
  margin: 0 0 12px;
  font-size: 15px;
}

.bank-details dt {
  color: var(--color-foreground-600);
}

.bank-details dd {
  margin: 0;
  font-weight: 600;
}

@media (max-width: 640px) {
  .pay-options {
    grid-template-columns: 1fr;
  }
}

.qb-panel {
  background: var(--color-background-500);
  border: 1px solid var(--color-secondary-700);
  border-radius: 12px;
  padding: 18px;
}

.qb-panel code {
  background: var(--color-background-600);
  border-radius: 4px;
  padding: 1px 6px;
  font-size: 12px;
  word-break: break-all;
}

/* ------------------------------------------------- shipment batch builder */

.combo__opt--thumbed {
  display: flex;
  align-items: center;
  gap: 10px;
}

.combo__opt--thumbed .combo__thumb {
  width: 28px;
  height: 28px;
  object-fit: cover;
  border-radius: 6px;
  flex: 0 0 auto;
}

.combo__opt--thumbed .combo__meta {
  margin-left: auto;
  white-space: nowrap;
}

.ship-lines {
  margin-top: 12px;
}

.ship-lines__thumb {
  width: 40px;
}

.ship-lines__thumb .combo__thumb {
  width: 32px;
  height: 32px;
  object-fit: cover;
  border-radius: 6px;
  display: block;
}

.ship-lines .inline-input {
  width: 72px;
}

.draft-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  background: var(--color-background-500);
  border: 1px solid var(--color-secondary-700);
  border-radius: 12px;
  padding: 14px 18px;
  margin-bottom: 10px;
}

.draft-card__dest {
  margin: 0 0 4px;
  font-weight: 600;
}

.draft-card__lines {
  margin: 0;
  font-size: 13px;
  color: var(--color-text-600);
}

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

.dest-chip {
  border: 1px solid var(--color-secondary-700);
  background: var(--color-background-500);
  border-radius: 999px;
  padding: 6px 14px;
  font-size: 13px;
  cursor: pointer;
}

.dest-chip:hover {
  background: var(--color-background-600);
}

/* ------------------------------------------------- inventory sort + hide */

.inv-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 18px 0 6px;
}

.inv-controls--seller {
  margin-top: 12px;
}

.inv-controls__label {
  font-size: 13px;
  color: var(--color-text-600);
  margin-right: 2px;
}

.sort-chip {
  border: 1px solid var(--color-secondary-700);
  background: var(--color-background-500);
  border-radius: 999px;
  padding: 5px 13px;
  font-size: 13px;
  text-decoration: none;
  color: var(--color-text-500);
  white-space: nowrap;
}

.sort-chip:hover {
  background: var(--color-background-600);
}

.sort-chip.is-active {
  background: var(--color-primary-500);
  border-color: var(--color-primary-500);
  color: #fff;
}

.sort-chip--toggle {
  margin-left: auto;
}

/* A hidden listing is still inventory, so it stays legible — just visibly
   set apart from what buyers can see. */
.is-hidden-listing {
  opacity: 0.62;
}

.is-hidden-listing .inv-name {
  text-decoration: line-through;
  text-decoration-color: var(--color-text-600);
}

.button--small {
  padding: 5px 12px;
  font-size: 13px;
}

/* ------------------------------------------------- package tag drill-down */

.inv-product__open {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  background: none;
  border: 0;
  padding: 0;
  text-align: left;
  cursor: pointer;
  font: inherit;
  color: inherit;
  position: relative;
  padding-right: 20px;
}

.inv-product__open:hover .inv-name {
  text-decoration: underline;
}

.inv-product__chev {
  position: absolute;
  right: 0;
  top: 2px;
  display: inline-flex;
  color: var(--color-text-600);
  transition: transform 0.15s ease;
}

.inv-product__open[aria-expanded="true"] .inv-product__chev {
  transform: rotate(180deg);
}

.pkg-row > td {
  background: var(--color-background-600);
  padding: 0;
}

.pkg-panel {
  padding: 16px 18px;
}

.pkg-panel--loading,
.pkg-panel--empty {
  color: var(--color-text-600);
  font-size: 13px;
}

.pkg-panel--empty p {
  margin: 0;
}

.pkg-panel__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 12px;
}

.pkg-panel__meta {
  font-size: 13px;
  color: var(--color-text-600);
}

.pkg-panel__note {
  flex-basis: 100%;
  font-size: 12px;
  color: var(--color-text-600);
  font-style: italic;
}

/* --------------------------------------------------- bulk match saving */

.bulk-bar {
  position: sticky;
  bottom: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 16px;
  padding: 14px 18px;
  background: var(--color-primary-500);
  color: #fff;
  border-radius: 12px;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.18);
}

.bulk-bar__text {
  margin-right: auto;
  font-size: 14px;
}

.bulk-bar .button--outline-secondary {
  border-color: rgba(255, 255, 255, 0.5);
  color: #fff;
  background: transparent;
}

.bulk-bar .button--outline-secondary:hover {
  background: rgba(255, 255, 255, 0.12);
}

.bulk-bar .button--filled-primary {
  background: #fff;
  color: var(--color-primary-500);
  border-color: #fff;
}

/* An edited line stays visually tied to the bar until it is saved. */
.line--pending-save {
  box-shadow: inset 3px 0 0 var(--color-primary-500);
}

@media (max-width: 640px) {
  .bulk-bar {
    flex-wrap: wrap;
  }

  .bulk-bar__text {
    flex-basis: 100%;
    margin-right: 0;
  }
}

.pkg-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 8px;
}

.pkg-item {
  display: grid;
  grid-template-columns: minmax(200px, auto) 1fr auto;
  align-items: center;
  gap: 6px 16px;
  background: var(--color-background-50);
  border: 1px solid var(--color-secondary-700);
  border-radius: 10px;
  padding: 10px 14px;
}

.pkg-item--pending {
  border-style: dashed;
  opacity: 0.8;
}

.pkg-item__tag {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.01em;
  word-break: break-all;
}

.pkg-item__added,
.pkg-item__from {
  font-size: 12px;
  color: var(--color-text-600);
}

.pkg-item__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  justify-content: flex-end;
}

.pkg-chip {
  background: var(--color-background-600);
  border-radius: 999px;
  padding: 2px 9px;
  font-size: 11px;
  color: var(--color-text-500);
  white-space: nowrap;
}

.pkg-chip--warn {
  background: #fdf3e0;
  color: #8a5a12;
}

/* A tag that has left the building: named order, dimmed row. */
.pkg-chip--sold {
  background: #e8f1ea;
  color: #1f6b3a;
}

.pkg-item--sold .pkg-item__tag,
.pkg-item--sold .pkg-item__added,
.pkg-item--sold .pkg-item__from {
  opacity: 0.55;
}

@media (max-width: 760px) {
  .pkg-item {
    grid-template-columns: 1fr;
    gap: 4px;
  }

  .pkg-item__chips {
    justify-content: flex-start;
  }
}

@media (max-width: 640px) {
  .sort-chip--toggle {
    margin-left: 0;
  }
}

@media (max-width: 640px) {
  .draft-card {
    flex-direction: column;
    align-items: flex-start;
  }
}

@media (max-width: 640px) {
  .ledger-filter__note {
    margin-left: 0;
    flex-basis: 100%;
  }

  .payout-form {
    flex-wrap: wrap;
  }
}

/* Batch payout selection (admin payouts) */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

.batch-payout-bar {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 16px;
  margin-top: 12px;
  padding: 12px 16px;
  border: 1px solid var(--color-border, #ddd);
  border-radius: 8px;
  background: var(--color-background-100, #fafafa);
  font-weight: 600;
}

.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}

.modal-backdrop[hidden] {
  display: none;
}

.modal {
  background: var(--color-background, #fff);
  border-radius: 10px;
  padding: 24px;
  max-width: 460px;
  width: calc(100% - 32px);
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.25);
}

.modal .form-actions {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
  margin-top: 16px;
}

.batch-payout-bar--toolbar {
  justify-content: flex-start;
  flex-wrap: wrap;
  margin: 0 0 12px;
}

.batch-payout-bar__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  flex: 1;
}

.batch-payout-bar--toolbar [data-vendor-select][aria-pressed="true"] {
  border-color: var(--color-foreground-600, #333);
  background: var(--color-background-600, #eee);
  font-weight: 600;
}

.field__hint-error {
  color: #a03123;
  font-weight: 600;
}

/* Warehouse pick flow */
.pick-scan input {
  font-size: 18px;
  padding: 12px;
}

.pick-scan__result {
  font-weight: 600;
  margin-top: 6px;
}

.pick-scan__result--ok { color: #1f6b3a; }
.pick-scan__result--err { color: #a03123; }

.pick-line {
  border: 1px solid var(--color-border, #ddd);
  border-radius: 10px;
  padding: 14px 16px;
  margin-bottom: 14px;
}

.pick-line__head {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 8px;
}

.pick-line__count {
  margin-left: auto;
  font-weight: 700;
}

/* Same visual language as the correlation view's listing thumbs
   (.combo__thumb), sized up a step: the picker identifies the product at
   a glance from across a rack.

   The tile is the span, not the image. A listing with no picture renders
   the empty carton mark, and one whose file 404s lays a broken image over
   the same mark — with alt="" the browser draws nothing for it, so the
   placeholder shows through instead of a torn-page glyph. */
.pick-thumb {
  position: relative;
  flex-shrink: 0;
  width: 48px;
  height: 60px;
  border-radius: 6px;
  background: var(--fade-in-bg);
  overflow: hidden;
}

.pick-thumb::before {
  content: "";
  position: absolute;
  inset: 0;
  margin: auto;
  width: 22px;
  height: 18px;
  border: 2px solid #c9c9c9;
  border-radius: 3px;
  box-shadow: inset 0 5px 0 -3px #c9c9c9;
}

.pick-thumb img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  mix-blend-mode: darken;
}

.pick-line__alts summary { cursor: pointer; }

.pkg-list--plain {
  list-style: none;
  padding: 8px 0 0;
  display: grid;
  gap: 4px;
}

.pick-done {
  text-align: center;
  padding: 28px;
  border: 2px solid #1f6b3a;
  border-radius: 12px;
  margin-top: 18px;
  background: #e8f1ea;
}

.pick-done__mark {
  width: 72px;
  height: 72px;
  margin: 0 auto 10px;
  border-radius: 50%;
  background: #1f6b3a;
  color: #fff;
  font-size: 44px;
  line-height: 72px;
  animation: pick-pop 0.45s cubic-bezier(0.2, 1.6, 0.4, 1);
}

@keyframes pick-pop {
  0% { transform: scale(0); }
  100% { transform: scale(1); }
}

.warehouse-cta-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.warehouse-cta {
  font-size: 17px;
  padding: 12px 22px;
}

.warehouse-cta .pill { margin-left: 6px; }

/* Shelf alternates as chips — sleeker than the old bullet list, and the
   scan JS moves chips in and out of it live. */
.shelf-tags {
  list-style: none;
  padding: 10px 0 4px;
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.shelf-tag {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px 12px;
  border: 1px solid var(--color-border, #ddd);
  border-radius: 10px;
  background: var(--color-bg-050, #fafafa);
  min-width: 0;
}

.shelf-tag__label { font-size: 13px; font-weight: 600; }

.shelf-tag__loc { font-size: 12px; color: var(--color-text-700, #666); }

.shelf-count {
  display: inline-block;
  min-width: 22px;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--color-bg-100, #eee);
  font-size: 13px;
  text-align: center;
  font-weight: 600;
}

.putback {
  border: 1px solid var(--color-border, #ccc);
  background: transparent;
  border-radius: 8px;
  padding: 4px 10px;
  margin-left: 8px;
  font-size: 13px;
  cursor: pointer;
}

.putback:hover { background: var(--color-bg-100, #eee); }

/* Queue: claim and unclaim actions. */
/* Dock-time badges: when the box must be packed and ready to load.
   Overdue shouts, due-today nudges, later whispers. */
.dock-badge {
  display: inline-block;
  padding: 2px 10px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
}

/* Two speeds only: red is this shift's problem (overdue, today, or
   tomorrow), yellow is the day after tomorrow onward. */
.dock-badge--urgent { background: #7c1d12; color: #fff; }

.dock-badge--later { background: #f4e8cc; color: #6b4e00; }

.section-title--urgent { color: #7c1d12; }

/* Integrity screen: the ledgers agree (quiet green) or they don't (loud). */
.delta-badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  white-space: nowrap;
}
.delta-badge--ok { background: #e3efe3; color: #22662c; }
.delta-badge--bad { background: #7c1d12; color: #fff; }

.pkg-panel__note--warn { color: #7c1d12; font-weight: 600; }

/* Physical quantity under a case count — "10" over "350 g". */
.inv-qty {
  display: block;
  font-size: 12px;
  color: var(--color-text-700, #555);
  white-space: nowrap;
}

/* Check-in: who did what, small and grey under the status chip. */
.checkin-by {
  display: block;
  font-size: 11px;
  color: var(--color-text-700, #555);
}

/* Exclusivity screen: two knobs, then the people. */
.access-form { margin: 12px 0 4px; }
.access-knob { margin-bottom: 14px; }
.access-check { display: flex; gap: 10px; align-items: flex-start; cursor: pointer; }
.access-check input { margin-top: 3px; }
.access-check .field__hint { display: block; margin-top: 2px; }
.access-inline { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.stock-line--private { color: #6b4e00; font-weight: 600; }

/* Notifications list. */
.notice-list { list-style: none; margin: 0; padding: 0; }
.notice-item {
  border: 1px solid var(--color-border, #e3e3e3);
  border-radius: 10px;
  padding: 12px 14px;
  margin-bottom: 10px;
}
.notice-item--unread { border-left: 4px solid #7c1d12; background: #fbf7f6; }
.notice-item__head { display: flex; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.notice-item__when { color: var(--color-text-700, #555); font-size: 13px; }
.notice-item__body { margin: 6px 0; }

/* Cash-in forms on the admin order page. */
.payments-forms { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }
.payment-form { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.payment-form .inline-input { max-width: 180px; }

/* Employee identity editor on the admin roster. */
.employee-form {
  display: flex;
  gap: 6px;
  align-items: center;
  flex-wrap: wrap;
}
.employee-form .inline-input { max-width: 150px; }
.employee-form .inline-input--short { max-width: 90px; }

/* The admin roster, remade 2026-08-10 (Nick: "make it possible to see
   what's in the text boxes"). Identity lives in one cell, so the edit
   forms stack and their inputs take the whole column — a license number
   or a full name is READ in its box, not scrolled inside 150px. */
.inv-table--users td,
.inv-table--users th[scope="row"] { vertical-align: top; }
.inv-table--users td { min-width: 170px; }
.user-cell { max-width: 260px; }
.user-cell__name {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 15px;
}
.user-cell__store {
  display: block;
  font-weight: 600;
  color: var(--color-text-700, #555);
}
.user-cell__meta {
  display: block;
  font-weight: 400;
  font-size: 12.5px;
  color: var(--color-text-700, #777);
  overflow-wrap: anywhere;
}
.user-edit {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 6px;
  max-width: 240px;
}
.user-edit .inline-input {
  width: 100%;
  max-width: none;
  font-size: 14px;
}
.user-edit .button { align-self: flex-start; }

/* Tap-down pick preview: the lines inside an order, one tap away. */
.pick-preview summary {
  cursor: pointer;
  color: var(--color-text-700, #555);
  font-size: 14px;
}

.pick-preview__lines {
  list-style: none;
  margin: 6px 0 2px;
  padding: 8px 10px;
  display: grid;
  gap: 4px;
  border-left: 3px solid var(--color-border, #ddd);
  font-size: 14px;
}

.pick-preview__qty {
  display: inline-block;
  min-width: 2.2em;
  font-weight: 700;
}

.dock-form {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 8px;
}

.dock-form input[type="datetime-local"] {
  padding: 7px 10px;
  border: 1px solid var(--color-border, #ccc);
  border-radius: 8px;
  font: inherit;
}

.stat--alert .stat__value { color: #7c1d12; }

/* The warehouse how-to guide: numbered cards, phone-first. */
.guide__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 14px;
  margin-bottom: 16px;
}

.guide__card {
  border: 1px solid var(--color-border, #ddd);
  border-radius: 12px;
  padding: 16px 18px;
}

.guide__card p { margin: 0; line-height: 1.55; }

/* The "what this place is / a normal day" narrative that opens each guide.
   Wider measure and larger type than the cards below it: it is meant to be
   read start to finish once, where the cards are looked up one at a time. */
.guide__day {
  max-width: 62ch;
  margin-bottom: 22px;
}

.guide__day p {
  margin: 0 0 12px;
  line-height: 1.65;
  font-size: 16px;
}

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

.guide__clock {
  display: inline-block;
  min-width: 6.5em;
  font-weight: 700;
  color: #123f68;
}

@media (prefers-color-scheme: dark) {
  .guide__clock { color: #8fc7f0; }
}

.guide__h {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 8px;
  font-size: 17px;
}

.guide__num {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: #123f68;
  color: #fff;
  font-size: 15px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Batch picks: builder bar on the queue, per-order cards, the big
   pack-out sort target. */
.batch-check-col { width: 40px; }

.batch-check-col input { width: 22px; height: 22px; }

.batch-bar {
  position: sticky;
  bottom: 12px;
  z-index: 30;
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  margin-top: 14px;
  padding: 12px 16px;
  border: 1px solid var(--color-border, #ddd);
  border-radius: 12px;
  background: var(--color-bg, #fff);
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.12);
}

.batch-bar__summary { flex: 1 1 auto; }

.batch-chip {
  display: inline-block;
  padding: 2px 10px;
  border-radius: 999px;
  background: #123f68;
  color: #fff;
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
}

.batch-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 14px;
  margin-bottom: 16px;
}

.batch-card {
  border: 1px solid var(--color-border, #ddd);
  border-radius: 12px;
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.batch-card--target {
  border-color: #1f6b3a;
  box-shadow: 0 0 0 2px #1f6b3a inset;
}

.batch-card__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  flex-wrap: wrap;
}

.batch-card__meta { font-size: 13px; color: var(--color-text-700, #666); margin: 0; }

.batch-card__tags {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 4px;
  max-height: 200px;
  overflow-y: auto;
}

.batch-card__tags li {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-size: 14px;
}

.batch-card__tick {
  margin-left: auto;
  color: #c9c9c9;
  font-weight: 700;
}

.batch-card__tick.is-on { color: #1f6b3a; }

/* A returned case and everything that has happened to it. The disposal
   variant is deliberately loud — it is the one state on the screen where
   the next action cannot be taken back. */
.return-case {
  border: 1px solid var(--color-border, #ddd);
  border-radius: 12px;
  padding: 14px 16px;
  margin-bottom: 14px;
}

.return-case--danger {
  border-color: #b3261e;
  box-shadow: 0 0 0 1px #b3261e inset;
}

.return-case__head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 6px;
}

/* Quiet, and last: dropping a box is an escape hatch, not a step. */
.batch-card__drop {
  margin-top: auto;
  padding-top: 4px;
}

.batch-disband { margin-top: 18px; }

.sort-target {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 14px;
  flex-wrap: wrap;
  margin-top: 12px;
  padding: 18px;
  border: 2px solid #123f68;
  border-radius: 12px;
  background: #eef4fa;
}

.sort-target__product { font-size: 16px; font-weight: 600; }

.sort-target__arrow { font-size: 24px; }

.sort-target__order {
  font-size: 34px;
  font-weight: 800;
  letter-spacing: 0.02em;
  color: #123f68;
}

.sort-target--flash { animation: pick-pop 0.35s cubic-bezier(0.2, 1.6, 0.4, 1); }

/* Facility home: the two scrollable pick panels. */
.pick-panels {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
  margin-bottom: 8px;
}

.pick-panel { min-width: 0; }

.pick-list {
  list-style: none;
  margin: 0;
  padding: 0;
  max-height: 340px;
  overflow-y: auto;
  border: 1px solid var(--color-border, #ddd);
  border-radius: 12px;
}

.pick-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  padding: 10px 14px;
  border-bottom: 1px solid var(--color-border, #eee);
}

.pick-item:last-child { border-bottom: 0; }

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

.pick-item__side {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

/* Facility inventory: a search box, not a bubble per vendor. The tabs and
   the click-to-sort headers that used to live here are gone — both only
   ever reordered the rows this page had already shipped, which stops being
   the truth the moment the building outgrows one page. */
.inv-controls {
  display: flex;
  align-items: flex-end;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}

.inv-search {
  flex: 1 1 260px;
  min-width: 0;
  margin: 0;
}

.inv-search input {
  width: 100%;
}

.inv-sort { margin-left: auto; }

.inv-sort select {
  padding: 8px 10px;
  border-radius: 8px;
  border: 1px solid var(--color-border, #ccc);
  font-size: 14px;
}

.inv-pager {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 12px;
}

.inv-pager__jump {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--color-text-700, #666);
  font-size: 14px;
}

.inv-pager__input {
  width: 5.5ch;
  padding: 6px 8px;
  border: 1px solid var(--color-border, #ccc);
  border-radius: 8px;
  font: inherit;
  text-align: center;
}

[data-inv-panel][aria-busy="true"] { opacity: 0.55; }

/* A total with no pager behind it. A single unpaged screen used to say
   nothing at all about how much it was showing, which reads as "this is
   everything" whether or not it is. */
.inv-pager__label--alone {
  margin: 12px 0 0;
  color: var(--color-text-700, #666);
  font-size: 14px;
}

/* ---------------------------------------------------------- rep console
   Two jobs on one page — opening somebody's session, and rationing a
   vendor's shelf. They were two identical tables under one heading and
   one search box; these give each half a visible edge of its own. */
.rep-section {
  margin-top: 28px;
  padding: 18px 20px 20px;
  background: var(--color-background-50, #fff);
  border: 1px solid var(--color-background-700, #e6e6e6);
  border-radius: 14px;
}

.rep-section--catalogue {
  background: var(--color-background-500, #f9f9f9);
}

.rep-section__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}

.rep-section__title {
  margin: 0;
  font-size: 19px;
  font-weight: var(--font-heading-weight, 700);
  color: var(--color-text-100, #0f0f0f);
}

.rep-section__note {
  margin: 4px 0 0;
  max-width: 62ch;
  color: var(--color-text-700, #5c5c5c);
  font-size: 14px;
  line-height: 1.5;
}

.rep-section__search {
  flex: 0 1 300px;
}

.rep-section__search input {
  width: 100%;
  padding: 9px 12px;
  border: 1px solid var(--color-background-700, #e6e6e6);
  border-radius: 10px;
  background: var(--color-background-50, #fff);
  font: inherit;
  font-size: 16px; /* iOS zooms a focused field below 16px */
}

@media (max-width: 640px) {
  .rep-section {
    padding: 16px 14px 18px;
  }
  .rep-section__search {
    flex: 1 1 100%;
  }
}

/* Storefront seller filter: only the pill for an active `seller=` link.
   There is no picker — the header search covers finding a vendor. */
.chip--clearable .chip__x {
  margin-left: 6px;
  font-weight: 700;
  opacity: 0.75;
}

.chip--clearable:hover .chip__x { opacity: 1; }

/* Admin browse-as: the always-visible way back to your own session. */
.impersonation-bar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 90;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  flex-wrap: wrap;
  padding: 10px 16px;
  background: #5c3d00;
  color: #fff;
  font-size: 15px;
  box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.25);
}

.impersonation-bar .role-badge { background: rgba(255, 255, 255, 0.2); color: #fff; }

.impersonation-bar__stop {
  border: 1px solid rgba(255, 255, 255, 0.7);
  background: transparent;
  color: #fff;
  border-radius: 999px;
  padding: 7px 16px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}

.impersonation-bar__stop:hover { background: rgba(255, 255, 255, 0.15); }

/* The fixed bar must never cover the page's last content. */
body:has(.impersonation-bar) .main { padding-bottom: 64px; }

/* Phones are the warehouse's real hardware: keep the scan box in reach,
   fatten every touch target, stack the pick panels. */
@media (max-width: 767px) {
  .pick-scan {
    position: sticky;
    top: 0;
    z-index: 20;
    background: var(--color-bg, #fff);
    padding: 10px 0 8px;
  }

  .pick-scan input { font-size: 16px; }

  .pick-panels { grid-template-columns: 1fr; }

  /* Flex-wrapping put the thumbnail on a row of its own and pushed the
     name down — a wasted row on the screen a picker scrolls all day. Pin
     the tile beside the text instead, spanning both of its lines. */
  .pick-line__head {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas:
      "thumb name  count"
      "thumb sku   count";
    column-gap: 12px;
    row-gap: 2px;
    align-items: center;
  }

  .pick-line__head .pick-thumb { grid-area: thumb; }
  .pick-line__head strong { grid-area: name; }
  .pick-line__head .inv-sku { grid-area: sku; }
  .pick-line__head .pick-line__count { grid-area: count; margin-left: 0; }

  .pick-item__side .button,
  .queue-actions .button,
  .batch-card .button {
    padding-top: 10px;
    padding-bottom: 10px;
  }

  .batch-bar {
    bottom: 8px;
    padding: 10px 12px;
    gap: 10px;
  }

  .batch-bar .button { width: 100%; }

  .sort-target__order { font-size: 42px; }

  .inv-sort { margin-left: 0; width: 100%; }

  .inv-sort select { width: 100%; }

  .putback { padding: 8px 14px; }
}

/* ------------------------------------------------------------------- ask
   The support panel. Layout only — the panel shell, scrim and slide come
   from .panel above. Width matches the cart, so the right edge of the site
   has one behaviour rather than two. */
.panel--ask { width: var(--minicart-width); display: flex; flex-direction: column; }
.panel--ask .panel__body.ask { flex: 1; overflow-y: auto; padding: 16px 18px 8px; }

.ask__intro { font-size: 13.5px; color: var(--color-text-500); line-height: 1.55; }
.ask__intro p { margin: 0 0 8px; }
.ask__intro strong { color: var(--color-text-50); }
.ask__humans { font-size: 12.5px; color: var(--color-text-600); }
.ask__humans a { color: var(--color-text-100); }

.ask__thread { display: flex; flex-direction: column; gap: 10px; margin-top: 14px; }
.ask__b {
  max-width: 88%; padding: 10px 13px; font-size: 14px; line-height: 1.5;
  border-radius: 13px; white-space: pre-wrap; word-wrap: break-word;
}
.ask__b--me {
  align-self: flex-end; background: var(--color-primary-500); color: #fff;
  border-bottom-right-radius: 4px;
}
.ask__b--bot {
  align-self: flex-start; background: var(--color-secondary-500);
  border-bottom-left-radius: 4px;
}
.ask__b--bot a { color: #1d5f42; }
.ask__b.is-waiting { color: var(--color-text-700); font-style: italic; }

.ask__starters { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 14px; }
.ask__starters button {
  border: 1px solid var(--color-background-700); background: var(--color-background-400);
  border-radius: 999px; padding: 7px 13px; font: inherit; font-size: 12.5px;
  color: var(--color-text-500); cursor: pointer;
}
.ask__starters button:hover { border-color: var(--color-text-700); }

.ask__ask {
  display: flex; gap: 9px; align-items: center; padding: 12px 18px 6px;
  border-top: 1px solid var(--color-background-700);
}
.ask__ask input {
  flex: 1; border: 1px solid var(--color-background-700); border-radius: 999px;
  padding: 11px 16px; font: inherit; font-size: 14px;
}
.ask__ask input:focus { outline: none; border-color: var(--color-text-700); }
.ask__ask button { flex: none; width: 42px; height: 42px; border-radius: 50%; padding: 0; }
.ask__foot {
  font-size: 11px; color: var(--color-text-700); text-align: center;
  padding: 0 18px 14px; margin: 0;
}

/* A thread is still open. Not a notification — nothing is waiting on them. */
.icon-button--ask { position: relative; }
.ask-dot {
  position: absolute; top: 6px; right: 6px; width: 7px; height: 7px;
  background: #2f6f4e; border-radius: 50%; box-shadow: 0 0 0 1.5px var(--color-background-400);
}

/* Phones: a full sheet. A 400px drawer on a 390px screen is just a bad drawer,
   and the warehouse works one-handed. */
@media (max-width: 640px) {
  .panel--ask { width: 100%; }
  .ask__b { max-width: 92%; font-size: 15px; }
}
.ask__b--bot strong { font-weight: 700; }
.ask__b--bot code {
  background: var(--color-background-600); border-radius: 4px;
  padding: 1px 5px; font-size: 12.5px;
}

/* Rendered assistant replies. white-space:pre-wrap is right for a plain-text
   bubble and wrong once there are real blocks in it — it doubles every gap. */
.ask__b--bot.is-rich { white-space: normal; }
.ask__b--bot.is-rich > :first-child { margin-top: 0; }
.ask__b--bot.is-rich > :last-child { margin-bottom: 0; }
.ask__b--bot p { margin: 0 0 9px; }
.ask__b--bot ul { margin: 0 0 9px; padding-left: 0; list-style: none; }
.ask__b--bot li { position: relative; padding-left: 15px; margin-bottom: 5px; }
.ask__b--bot li:last-child { margin-bottom: 0; }
.ask__b--bot li::before {
  content: ""; position: absolute; left: 3px; top: 9px;
  width: 4px; height: 4px; border-radius: 50%;
  background: var(--color-text-700);
}

/* Queue: last-scan vs claim time, and the order nobody can finish. */
.queue-lastscan { display: block; font-size: 11.5px; color: var(--color-text-700); margin-top: 2px; }
.queue-lastscan--idle { color: #9a6b1f; }
.queue-unpackable { margin-left: 6px; vertical-align: middle; }

/* Quantity stepper, on the checkout table AND in the cart drawer. The number
   a buyer sees is now the number they can actually have — bounded server-side
   by every limit that applies to them — so it has to be editable wherever it
   is shown, rather than only on the product page they may have left twenty
   minutes ago. */
.qty-stepper {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  justify-content: flex-end;
}

.qty-stepper__n {
  min-width: 2ch;
  text-align: center;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
}

/* The reason the "+" stopped moving. A stepper that goes dead with no
   explanation is the same dead end as a button that refuses with none. */
.qty-stepper__why {
  margin: 4px 0 0;
  text-align: right;
  max-width: 22ch;
  margin-left: auto;
}

.plain-list {
  margin: 6px 0 0;
  padding-left: 18px;
}

/* Package tags on a sale receipt. A Metrc label is 24 fixed-width
   characters, so the column is sized by content rather than by a fraction:
   auto-fill at a 250px minimum gives four columns on a desktop receipt, two
   on a tablet and one on a phone, without a media query per breakpoint. */
.receipt-tag-head {
  margin: 18px 0 6px;
  font-size: 0.95rem;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px;
}

.tag-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 2px 18px;
}

.tag-grid li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  padding: 3px 0;
  border-bottom: 1px solid var(--color-border, #ddd);
}

/* In the drawer the stepper sits inline with the line's meta text rather than
   right-aligned in a table cell. */
.qty-stepper--cart {
  justify-content: flex-start;
  margin: 4px 0;
  gap: 8px;
}

.qty-stepper--cart .cart-line__meta {
  margin: 0;
}

/* Scheduling, deliberately behind a disclosure. ASAP is the default and the
   only thing on screen; a fixed window is two taps away with the cost stated.
   The friction is the point — a promised window means the order waits for a
   slot instead of going on the next run, which is slower for the buyer AND
   for everyone else on that route. */
.sched {
  border: 1px solid var(--color-text-700);
  border-radius: 8px;
  padding: 12px;
  margin-bottom: 16px;
}

.sched__summary {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px;
  cursor: pointer;
  list-style: none;
}

.sched__summary::-webkit-details-marker {
  display: none;
}

.sched__asap {
  flex: 1 1 260px;
  min-width: 0;
}

.sched__toggle {
  font-size: 14px;
  white-space: nowrap;
}

.sched[open] .sched__toggle {
  visibility: hidden;
}

.sched__body {
  margin-top: 12px;
}

/* datetime-local carries its own intrinsic width and padding on iOS, so it
   rendered taller and wider than the text inputs beside it even with
   width:100% — the two window fields looked like a different control from
   everything else on the form. Normalise the box and pin one control height so
   a row of mixed input types lines up. */
.field input[type="datetime-local"],
.field input[type="date"],
.field input[type="time"] {
  -webkit-appearance: none;
  appearance: none;
  min-width: 0;
  max-width: 100%;
  min-height: 46px;
  line-height: 1.2;
  font: inherit;
  font-size: 16px; /* under 16px iOS zooms the whole page on focus */
}

/* Only shown on a narrow screen, where the letterhead background is dropped
   so the slip can grow with its content. Hidden on desktop and on paper,
   where the real letterhead is there to see. */
.slip__screen-note {
  display: none;
  font-size: 12px;
  color: #6b7280;
  margin: 0 0 12px;
}

@media print {
  .slip__screen-note {
    display: none !important;
  }
}

/* A pick line whose cases are all pulled, and the one the scanner just moved
   you to. The picker's hands are on a scanner rather than a mouse, so finishing
   a line has to move the page for them — otherwise they click out of the scan
   field to scroll, and the next barcode lands nowhere. */
.pick-line--done .pick-line__count {
  color: var(--color-primary-500);
  font-weight: 700;
}

.pick-line--next {
  outline: 2px solid var(--color-primary-500);
  outline-offset: 4px;
  border-radius: 10px;
  transition: outline-color 0.4s ease;
}

/* ------------------------------------------------------- remote picker
   The generic searchable picker (app.js, [data-remote-picker]). Deliberately
   plainer than the intake combobox: that one is a listing matcher with a
   thumbnail and a stock chip, this one is a name and an email. */
.picker {
  position: relative;
  min-width: 0;
}

.picker__field {
  position: relative;
}

.picker__input {
  width: 100%;
  height: 40px;
  padding: 0 12px;
  border: 1px solid var(--color-background-700, #e6e6e6);
  border-radius: 10px;
  background: var(--color-background-50, #fff);
  font: inherit;
  font-size: 16px;
}

.picker__input:focus {
  outline: none;
  border-color: var(--color-primary-500, #181818);
  box-shadow: 0 0 0 3px var(--color-secondary-600, #e8e8e8);
}

.picker__list {
  position: absolute;
  z-index: 40;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  max-height: 260px;
  overflow-y: auto;
  margin: 0;
  padding: 4px;
  list-style: none;
  background: var(--color-background-50, #fff);
  border: 1px solid var(--color-background-700, #e6e6e6);
  border-radius: 10px;
  box-shadow: 0 12px 28px rgb(0 0 0 / 0.12);
}

.picker__option {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 8px 10px;
  border-radius: 7px;
  cursor: pointer;
}

.picker__option.is-active,
.picker__option:hover {
  background: var(--color-secondary-500, #f5f5f5);
}

.picker__option-name {
  font-size: 14px;
  color: var(--color-text-100, #0f0f0f);
}

.picker__option-hint {
  font-size: 12px;
  color: var(--color-text-700, #5c5c5c);
}

.picker__empty {
  padding: 10px;
  color: var(--color-text-700, #5c5c5c);
  font-size: 14px;
}

.picker__chosen {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 8px;
  padding: 5px 6px 5px 11px;
  background: var(--color-secondary-500, #f5f5f5);
  border-radius: 999px;
  font-size: 14px;
  max-width: 100%;
}

.picker__chosen-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.picker__clear {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--color-background-50, #fff);
  color: var(--color-text-500, #424242);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
}

/* ---------------------------------------------------- allowances console
   Exclusivity used to be one listing per page. This is the same settings
   applied to a vendor's shelf at once, so the selection state has to be
   visible at all times — hence a bar that is part of the page rather than
   a floating overlay that a phone would put over the rows it describes. */
.alw-bar {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px 14px;
  margin-bottom: 14px;
  background: var(--color-background-50, #fff);
  border: 1px solid var(--color-background-700, #e6e6e6);
  border-radius: 12px;
}

.alw-bar[hidden] { display: none !important; }

.alw-bar__count {
  font-weight: var(--font-heading-weight, 700);
  font-size: 15px;
  color: var(--color-text-50, #000);
}

.alw-bar__row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.alw-bar__sep {
  width: 1px;
  height: 22px;
  background: var(--color-background-700, #e6e6e6);
}

.alw-bar__label {
  font-size: 14px;
  color: var(--color-text-700, #5c5c5c);
}

.alw-bar__num {
  width: 6.5ch;
  height: 34px;
  padding: 0 8px;
  border: 1px solid var(--color-background-700, #e6e6e6);
  border-radius: 8px;
  font: inherit;
  font-size: 16px;
  text-align: center;
}

.alw-bar__buyer {
  flex: 1 1 240px;
  min-width: 0;
}

.alw-list {
  list-style: none;
  margin: 0;
  padding: 0;
  border: 1px solid var(--color-background-700, #e6e6e6);
  border-radius: 12px;
  overflow: hidden;
  background: var(--color-background-50, #fff);
}

.alw-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 14px;
  border-top: 1px solid var(--color-background-600, #efefef);
}

.alw-row:first-child { border-top: 0; }
.alw-row:has(input:checked) { background: var(--color-secondary-500, #f5f5f5); }

.alw-row__check {
  width: 17px;
  height: 17px;
  flex: 0 0 auto;
  margin: 0;
}

.alw-row__main {
  flex: 1 1 auto;
  min-width: 0;
}

.alw-row__name {
  margin: 0;
  font-size: 15px;
  color: var(--color-text-50, #000);
}

.alw-row__meta {
  margin: 1px 0 0;
  font-size: 12px;
  color: var(--color-text-700, #5c5c5c);
}

.alw-row__state {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.alw-tabs {
  display: flex;
  gap: 20px;
  margin: 18px 0 16px;
  border-bottom: 1px solid var(--color-background-700, #e6e6e6);
}

.alw-tab {
  padding: 8px 0 10px;
  border-bottom: 2px solid transparent;
  color: var(--color-text-700, #5c5c5c);
  text-decoration: none;
  font-size: 15px;
}

.alw-tab[aria-current="page"] {
  color: var(--color-text-50, #000);
  border-bottom-color: var(--color-primary-500, #181818);
}

.alw-head {
  display: flex;
  align-items: flex-end;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 4px;
}

.alw-head__field {
  flex: 1 1 240px;
  min-width: 0;
}

.alw-head__field label {
  display: block;
  margin-bottom: 5px;
  font-size: 13px;
  color: var(--color-text-700, #5c5c5c);
}

.alw-head__field select,
.alw-head__field input {
  width: 100%;
  height: 40px;
  padding: 0 12px;
  border: 1px solid var(--color-background-700, #e6e6e6);
  border-radius: 10px;
  background: var(--color-background-50, #fff);
  font: inherit;
  font-size: 16px;
}

@media (max-width: 640px) {
  .alw-row {
    flex-wrap: wrap;
  }
  .alw-row__state {
    width: 100%;
    justify-content: flex-start;
    padding-left: 29px;
  }
}

/* -------------------------------------------------------- tag recovery */
.rec-find {
  padding: 16px 18px;
  margin-bottom: 18px;
  background: var(--color-background-50, #fff);
  border: 1px solid var(--color-background-700, #e6e6e6);
  border-radius: 12px;
}

.rec-find__label {
  display: block;
  font-size: 17px;
  font-weight: var(--font-heading-weight, 700);
  color: var(--color-text-50, #000);
}

.rec-find__row {
  display: flex;
  gap: 8px;
  margin-top: 10px;
  flex-wrap: wrap;
}

.rec-find__input {
  flex: 1 1 260px;
  min-width: 0;
  height: 44px;
  padding: 0 12px;
  border: 1px solid var(--color-primary-100, #4b4b4b);
  border-radius: 10px;
  font-size: 16px;
  letter-spacing: 0.02em;
}

.rec-hits {
  list-style: none;
  margin: 0 0 18px;
  padding: 0;
  border: 1px solid var(--color-background-700, #e6e6e6);
  border-radius: 12px;
  overflow: hidden;
  background: var(--color-background-50, #fff);
}

.rec-hits__item {
  padding: 11px 14px;
  border-top: 1px solid var(--color-background-600, #efefef);
}

.rec-hits__item:first-child { border-top: 0; }

.rec-hits__link {
  display: block;
  font-size: 15px;
}

.rec-hits__meta {
  display: block;
  margin-top: 2px;
  color: var(--color-text-700, #5c5c5c);
  font-size: 13px;
}

.rec-card {
  padding: 16px 18px;
  background: var(--color-background-50, #fff);
  border: 1px solid var(--color-background-700, #e6e6e6);
  border-radius: 12px;
}

.rec-card__head { margin: 0 0 12px; }

.rec-card__facts {
  display: grid;
  grid-template-columns: 104px minmax(0, 1fr);
  gap: 7px 14px;
  margin: 0 0 4px;
  font-size: 14px;
}

.rec-card__facts dt {
  color: var(--color-text-700, #5c5c5c);
}

.rec-card__facts dd {
  margin: 0;
  min-width: 0;
  color: var(--color-text-100, #0f0f0f);
}

.rec-move {
  margin-top: 16px;
  padding: 14px 16px;
  background: var(--color-background-500, #f9f9f9);
  border: 1px solid var(--color-background-700, #e6e6e6);
  border-radius: 12px;
}

.rec-move[hidden] { display: none !important; }

.rec-move__title {
  margin: 0 0 4px;
  font-size: 15px;
  font-weight: var(--font-heading-weight, 700);
  color: var(--color-text-50, #000);
}

.rec-move__effect {
  margin: 0 0 10px;
  font-size: 13px;
  color: var(--color-text-600, #4f4f4f);
}

.rec-move__effect:empty { display: none; }

.rec-move__picker { max-width: 460px; }

.rec-groups {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.rec-group {
  padding: 12px 14px;
  background: var(--color-background-50, #fff);
  border: 1px solid var(--color-background-700, #e6e6e6);
  border-radius: 12px;
}

.rec-group:has([data-rec-case]:checked) {
  border-color: var(--color-primary-100, #4b4b4b);
}

.rec-group__head {
  display: flex;
  align-items: center;
  gap: 12px;
}

.rec-group__check {
  width: 17px;
  height: 17px;
  flex: 0 0 auto;
  margin: 0;
}

.rec-group__main { flex: 1 1 auto; min-width: 0; }

.rec-group__name {
  margin: 0;
  font-size: 15px;
  color: var(--color-text-50, #000);
}

.rec-group__meta {
  margin: 1px 0 0;
  font-size: 12px;
  color: var(--color-text-700, #5c5c5c);
}

.rec-group__count {
  flex: 0 0 auto;
  font-size: 13px;
  color: var(--color-text-600, #4f4f4f);
  white-space: nowrap;
}

.rec-group__cases {
  margin-top: 10px;
  padding-left: 29px;
}

.rec-group__cases summary {
  cursor: pointer;
  font-size: 13px;
  color: var(--color-text-700, #5c5c5c);
}

.rec-cases {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.rec-cases__item label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
}

.rec-locked {
  margin-top: 10px;
  margin-left: 29px;
  padding: 9px 11px;
  background: var(--color-background-500, #f9f9f9);
  border-radius: 9px;
}

.rec-locked__head {
  margin: 0 0 4px;
  font-size: 13px;
  color: var(--color-text-400, #353535);
}

.rec-locked__list {
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: 12px;
  color: var(--color-text-700, #5c5c5c);
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.rec-locked__fix { color: var(--color-text-400, #353535); }

@media (max-width: 640px) {
  .rec-card__facts { grid-template-columns: 1fr; gap: 2px; }
  .rec-card__facts dt { margin-top: 8px; }
  .rec-group__head { flex-wrap: wrap; }
  .rec-group__count { width: 100%; padding-left: 29px; }
  .rec-group__cases, .rec-locked { margin-left: 0; padding-left: 0; }
}

/* ------------------------------------------------------- payouts ledger
   Boxes moves no money; this screen records what a human moved. The banner
   says so once at the top rather than repeating it in every button. */
.payout-truth {
  margin-bottom: 18px;
}

/* The summary nudges instead of the primary button going dead. A disabled
   black button is how this page read as broken: you click the one obvious
   control and nothing happens because a checkbox came first. */
.batch-payout-bar [data-batch-summary].is-nudged {
  color: var(--color-text-50, #000);
  font-weight: var(--font-heading-weight, 700);
}

.payment-line {
  display: block;
  font-size: 13px;
  line-height: 1.5;
}

.payment-line--reversed {
  color: var(--color-text-700, #5c5c5c);
  text-decoration: line-through;
}

.payment-line .warn {
  color: #b45309;
}

/* ---------------------------------------------------------- dock check-in
   Two people unload one truck. The count has to be the SAME number on both
   their screens, which is why it is large, shared and polled rather than
   each browser quietly tracking its own scans. */
.dock-remaining {
  display: flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
  padding: 14px 16px;
  margin-bottom: 14px;
  background: var(--color-background-50, #fff);
  border: 1px solid var(--color-background-700, #e6e6e6);
  border-radius: 12px;
}

.dock-remaining__count {
  font-size: 30px;
  font-weight: var(--font-heading-weight, 700);
  line-height: 1;
  color: var(--color-text-50, #000);
}

.dock-remaining__label {
  display: block;
  font-size: 13px;
  color: var(--color-text-700, #5c5c5c);
}

.dock-remaining__bar-wrap {
  flex: 1 1 180px;
  min-width: 0;
}

.dock-remaining__bar {
  height: 7px;
  border-radius: 4px;
  background: var(--color-background-700, #e6e6e6);
  overflow: hidden;
}

.dock-remaining__bar span {
  display: block;
  height: 100%;
  background: var(--color-primary-500, #181818);
  transition: width 200ms ease;
}

.dock-remaining__meta {
  margin: 7px 0 0;
  font-size: 13px;
  color: var(--color-text-700, #5c5c5c);
}

.dock-remaining__live {
  font-size: 12px;
  color: var(--color-text-700, #5c5c5c);
}

/* The count might be old. Say so rather than showing a confident stale one. */
.dock-remaining__live.is-stale::after {
  content: " — reconnecting";
}

.dock-putaway {
  padding: 14px 16px;
  margin-bottom: 14px;
  background: var(--color-background-500, #f9f9f9);
  border: 1px solid var(--color-background-700, #e6e6e6);
  border-radius: 12px;
}

.dock-putaway__title {
  margin: 0 0 8px;
  font-size: 15px;
  color: var(--color-text-50, #000);
}

.dock-putaway__fields {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 8px;
}

.dock-putaway__fields select,
.dock-putaway__fields input {
  width: 100%;
  height: 42px;
  padding: 0 11px;
  border: 1px solid var(--color-background-700, #e6e6e6);
  border-radius: 10px;
  background: var(--color-background-50, #fff);
  font: inherit;
  font-size: 16px;
}

/* A row somebody ELSE just scanned. Without this the line simply changes
   under a worker who is halfway down the aisle looking for it. */
[data-checkin-row].is-theirs {
  animation: theirs-flash 2.4s ease-out;
}

@keyframes theirs-flash {
  0%   { background: #fff4d6; }
  100% { background: transparent; }
}

@media (max-width: 640px) {
  .dock-putaway__fields { grid-template-columns: 1fr; }
}

/* Fault is fixed by the reason, not chosen per case, so it cannot be argued
   after the fact. Showing it change as the reason changes is what makes
   that visible rather than buried in a lookup table. */
.disposal-fault {
  font-size: 14px;
  color: var(--color-text-700, #5c5c5c);
}

.disposal-fault--boxes {
  color: #b3261e;
  font-weight: var(--font-heading-weight, 700);
}

.disposal-fault--vendor {
  color: var(--color-text-400, #353535);
}

/* ------------------------------------------------------- warehouse today
   One front door for a shift. The ranked "do this first" is the whole
   point: four equal tiles is still four decisions, and a warehouse almost
   always has one obvious next action. */
.wh-today { padding-bottom: 84px; }   /* clear of the tab bar */

.wh-next {
  padding: 16px 18px;
  margin-bottom: 16px;
  border-radius: 12px;
  background: #fdf6e6;
  border: 1px solid #f0dfb8;
}

.wh-next--clear { background: var(--color-background-500, #f9f9f9); border-color: var(--color-background-700, #e6e6e6); }

.wh-next__kicker {
  margin: 0 0 3px;
  font-size: 11px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: #8a6516;
}

.wh-next__title {
  margin: 0 0 3px;
  font-size: 19px;
  font-weight: var(--font-heading-weight, 700);
  color: var(--color-text-50, #000);
}

.wh-next__detail {
  margin: 0 0 12px;
  font-size: 14px;
  line-height: 1.5;
  color: var(--color-text-600, #4f4f4f);
}

.wh-counts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 8px;
  margin-bottom: 8px;
}

.wh-count {
  display: block;
  padding: 12px 14px;
  border-radius: 10px;
  background: var(--color-background-500, #f9f9f9);
  text-decoration: none;
}

.wh-count--bad { background: #fdeceb; }

.wh-count__n {
  display: block;
  font-size: 24px;
  font-weight: var(--font-heading-weight, 700);
  line-height: 1.1;
  color: var(--color-text-50, #000);
}

.wh-count--bad .wh-count__n { color: #b3261e; }

.wh-count__label {
  display: block;
  margin-top: 1px;
  font-size: 12px;
  color: var(--color-text-700, #5c5c5c);
}

.wh-mine {
  list-style: none;
  margin: 0;
  padding: 0;
  border: 1px solid var(--color-background-700, #e6e6e6);
  border-radius: 12px;
  overflow: hidden;
  background: var(--color-background-50, #fff);
}

.wh-mine__row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 14px;
  border-top: 1px solid var(--color-background-600, #efefef);
}

.wh-mine__row:first-child { border-top: 0; }
.wh-mine__main { flex: 1 1 auto; min-width: 0; }

.wh-mine__label {
  margin: 0;
  font-size: 15px;
  color: var(--color-text-50, #000);
}

.wh-mine__detail {
  margin: 1px 0 0;
  font-size: 12px;
  color: var(--color-text-700, #5c5c5c);
}

/* Thumb-reachable, because this is carried around a building. */
.wh-tabs {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 60;
  display: flex;
  background: var(--color-background-50, #fff);
  border-top: 1px solid var(--color-background-700, #e6e6e6);
  padding-bottom: env(safe-area-inset-bottom, 0);
}

.wh-tabs__tab {
  position: relative;
  flex: 1;
  padding: 9px 2px 8px;
  text-align: center;
  font-size: 11px;
  color: var(--color-text-700, #5c5c5c);
  text-decoration: none;
  border-bottom: 2px solid transparent;
}

.wh-tabs__tab.is-current {
  color: var(--color-text-50, #000);
  border-bottom-color: var(--color-primary-500, #181818);
}

.wh-tabs__icon {
  display: block;
  font-size: 18px;
  line-height: 1.2;
}

.wh-tabs__pill {
  position: absolute;
  top: 4px;
  left: 56%;
  min-width: 17px;
  padding: 1px 4px;
  border-radius: 9px;
  background: #b3261e;
  color: #fff;
  font-size: 10px;
  line-height: 1.5;
}

/* ------------------------------------------------------- pick screen
   Three permanent buttons above the work, on a handheld, for controls used
   at most once per order. They live behind this now. */
.pick-more {
  position: relative;
  flex: 0 0 auto;
}

.pick-more > summary {
  list-style: none;
  cursor: pointer;
  width: 42px;
  height: 42px;
  line-height: 40px;
  text-align: center;
  font-size: 20px;
  border: 1px solid var(--color-background-700, #e6e6e6);
  border-radius: 10px;
  background: var(--color-background-50, #fff);
}

.pick-more > summary::-webkit-details-marker { display: none; }

.pick-more__menu {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  z-index: 40;
  min-width: 200px;
  padding: 6px;
  background: var(--color-background-50, #fff);
  border: 1px solid var(--color-background-700, #e6e6e6);
  border-radius: 10px;
  box-shadow: 0 12px 28px rgb(0 0 0 / 0.12);
}

/* The menu hangs off the RIGHT of its trigger, which is correct while the
   trigger sits at the right of the header. On a handheld it does not:
   .dash__head is flex-wrap:wrap, so the overflow button drops onto its own
   line and lands at the LEFT edge — and a 200px menu anchored right:0 to a
   42px trigger at x=16 renders from x=-142. Measured at 375px: 142px off the
   screen, a 58px sliver showing, all four links past the edge and untappable.

   Nothing is broken at desktop width, and nothing about the menu looks wrong
   in isolation — it is only wrong relative to where the header happened to
   wrap, which is why it survived every non-phone pass. Pickers work on a
   phone one-handed, so this width is the only one that matters here. */
@media (max-width: 640px) {
  .pick-more__menu {
    right: auto;
    left: 0;
    min-width: 0;
    width: max-content;
    /* Bounded so a long label cannot push it off the other edge instead. */
    max-width: calc(100vw - 32px);
  }
}

.pick-more__menu a {
  display: block;
  padding: 9px 11px;
  border-radius: 7px;
  font-size: 15px;
  color: var(--color-text-100, #0f0f0f);
  text-decoration: none;
}

.pick-more__menu a:hover { background: var(--color-secondary-500, #f5f5f5); }

/* Where first, tag second. The tag is a confirmation once you are standing
   at the shelf; the location is the instruction that gets you there. */
.pick-where {
  font-size: 15px;
  font-weight: var(--font-heading-weight, 700);
  color: var(--color-text-50, #000);
  white-space: nowrap;
}

.pick-tag {
  font-size: 12px;
  color: var(--color-text-700, #5c5c5c);
}

@media (max-width: 640px) {
  .pick-tag { font-size: 11px; }
}

/* ---------------------------------------------------------- employees
   The one-time handover. Loud on purpose: it is shown once, nothing stores
   a readable password, and an admin who scrolls past it has to reset. */
.handover {
  padding: 18px 20px;
  margin-bottom: 20px;
  border: 2px solid #b45309;
  border-radius: 12px;
  background: #fdf6e6;
}

.handover__kicker {
  margin: 0 0 2px;
  font-size: 11px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: #8a6516;
}

.handover__name {
  margin: 0 0 12px;
  font-size: 19px;
  font-weight: var(--font-heading-weight, 700);
  color: var(--color-text-50, #000);
}

.handover__creds {
  display: grid;
  grid-template-columns: 96px minmax(0, 1fr);
  gap: 6px 14px;
  margin: 0 0 14px;
  font-size: 15px;
}

.handover__creds dt {
  color: var(--color-text-700, #5c5c5c);
  font-size: 13px;
  align-self: center;
}

.handover__creds dd {
  margin: 0;
  user-select: all;   /* one tap selects the whole credential */
}

.handover__pw {
  font-size: 19px;
  letter-spacing: 0.04em;
  color: var(--color-text-50, #000);
}

.handover__warn {
  margin: 12px 0 0;
  font-size: 13px;
  line-height: 1.55;
  color: #8a6516;
}

.emp-new {
  margin-bottom: 8px;
  padding: 14px 16px;
  border: 1px solid var(--color-background-700, #e6e6e6);
  border-radius: 12px;
  background: var(--color-background-50, #fff);
}

.emp-new > summary {
  cursor: pointer;
  font-size: 16px;
  font-weight: var(--font-heading-weight, 700);
  color: var(--color-text-50, #000);
}

.emp-new[open] > summary { margin-bottom: 14px; }

.emp-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 10px;
  margin-bottom: 12px;
}

.emp-grid .field { margin: 0; }

.emp-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.emp-row {
  padding: 16px 18px;
  border: 1px solid var(--color-background-700, #e6e6e6);
  border-radius: 12px;
  background: var(--color-background-50, #fff);
}

/* Closed accounts stay on the roster. They are the people whose names are
   on last quarter's boxes. */
.emp-row--gone {
  background: var(--color-background-500, #f9f9f9);
  opacity: 0.82;
}

.emp-row__head { margin-bottom: 12px; }

.emp-row__name {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  font-size: 17px;
  font-weight: var(--font-heading-weight, 700);
  color: var(--color-text-50, #000);
}

.emp-row__meta,
.emp-row__work {
  margin: 3px 0 0;
  font-size: 13px;
  color: var(--color-text-700, #5c5c5c);
}

.emp-row__work { color: var(--color-text-600, #4f4f4f); }

.emp-row__actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--color-background-600, #efefef);
}

@media (max-width: 640px) {
  .handover__creds { grid-template-columns: 1fr; gap: 2px; }
  .handover__creds dt { margin-top: 8px; }
}

/* One wire settles several payouts, because a payout is one per order. The
   list is what you match a bank line against, so it has to be reachable —
   but it is reconciliation detail, so it stays closed until asked for. */
.payment-batch {
  margin-top: 4px;
  font-size: 0.8rem;
}

.payment-batch > summary {
  cursor: pointer;
  color: var(--color-muted);
}

.payment-batch > span {
  display: block;
  margin-top: 3px;
  word-break: break-word;
}

/* ------------------------------------------------------ sales chart --- */

/* Range presets. They set the same start/end the ledger reads, so the chip
   that is on is the window the whole page is showing — not a second filter
   competing with the date fields beside it. */
.range-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 4px 0 16px;
}

.range-chip {
  padding: 6px 14px;
  border: 1px solid var(--color-border, #ddd);
  border-radius: 999px;
  font-size: 14px;
  line-height: 1;
  text-decoration: none;
  color: var(--color-text-700);
  background: var(--color-background-50);
}

.range-chip:hover { background: var(--color-secondary-600); }

.range-chip--on {
  background: var(--color-text-500);
  border-color: var(--color-text-500);
  color: var(--color-background-50);
  font-weight: 600;
}

.chart {
  margin: 0 0 24px;
}

.chart__title {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  font-size: 14px;
  font-weight: 600;
  margin-bottom: 8px;
}

.chart__total {
  font-weight: 400;
  color: var(--color-text-600);
}

/* preserveAspectRatio="none" stretches the drawing to whatever width it
   gets, so the height here is the real one and the viewBox is only a
   coordinate space. */
.chart__svg {
  width: 100%;
  height: 200px;
  display: block;
  overflow: visible;
}

/* Recessive: the grid is a reference, not content. */
.chart__grid { stroke: var(--color-border, #ddd); stroke-width: 1; opacity: 0.5; }
.chart__axis { stroke: var(--color-border, #ddd); stroke-width: 1; }

/* One series, one hue — no categorical palette to validate. The fill is the
   same green the letterhead rule uses, at low alpha so the line stays the
   thing you read. */
.chart__area { fill: rgba(115, 166, 77, 0.18); stroke: none; }
.chart__line {
  fill: none;
  stroke: #73a64d;
  stroke-width: 2;
  vector-effect: non-scaling-stroke;
  stroke-linejoin: round;
  stroke-linecap: round;
}

/* Invisible, full-height, one per bucket: a hit target far bigger than the
   mark, carrying a native tooltip. No script involved. */
.chart__hit { fill: transparent; }
.chart__hit:hover { fill: rgba(115, 166, 77, 0.10); }

.chart__scale {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  font-size: 12px;
  color: var(--color-text-600);
  margin-top: 6px;
}

/* Names the unit next to the title, so "Sold per day" cannot be read as a
   count of sales. Recessive — it is a clarification, not a heading. */
.chart__unit {
  font-weight: 400;
  font-size: 12px;
  color: var(--color-text-600);
}

/* Plot + its y-axis. The labels are HTML because the SVG is drawn with
   preserveAspectRatio="none" — anything inside it stretches with the
   width, text included. */
.chart__plot {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 8px;
  align-items: stretch;
}

.chart__yaxis {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  height: 200px;
  font-size: 11px;
  color: var(--color-text-600);
  text-align: right;
  /* Each label names the grid line it sits on; nudging up by half a line
     centres it on the rule rather than hanging below it. */
  transform: translateY(-0.4em);
  white-space: nowrap;
}

.chart__svg { height: 200px; }

/* ---- hover layer -------------------------------------------------------
   Laid over the plot, not inside the SVG: the SVG is drawn with
   preserveAspectRatio="none" so text within it stretches with the width.
   Columns are equal-width hit targets — far bigger than the 2px line they
   explain, which is the whole point of a hover layer on a sparse series. */
.chart__plot { position: relative; }

.chart__hover {
  position: absolute;
  inset: 0 0 0 0;
  display: flex;
  /* Sits in the second grid column, over the SVG only — never over the
     y-axis labels. */
  left: auto;
  width: 100%;
  pointer-events: auto;
}

/* The overlay spans the SVG cell; the axis column is auto-width beside it,
   so the grid places this correctly without magic numbers. */
.chart__plot > .chart__hover { grid-column: 2; }

.chart__col {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
}

/* Crosshair. Drawn on hover only, and recessive — it locates the reading, it
   is not a mark of its own. */
.chart__col::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 50%;
  width: 1px;
  background: var(--color-text-600);
  opacity: 0;
  transition: opacity 0.08s ease;
}
.chart__col:hover::before { opacity: 0.35; }

.chart__dot,
.chart__tip { opacity: 0; transition: opacity 0.08s ease; }
.chart__col:hover .chart__dot,
.chart__col:hover .chart__tip { opacity: 1; }

/* ≥8px marker, ringed in the surface colour so it reads on the fill. */
.chart__dot {
  position: absolute;
  left: 50%;
  width: 9px;
  height: 9px;
  margin: 0 0 -4.5px -4.5px;
  border-radius: 50%;
  background: #73a64d;
  box-shadow: 0 0 0 2px var(--color-background-500);
}

.chart__tip {
  position: absolute;
  left: 50%;
  transform: translate(-50%, 14px);
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 6px 9px;
  border-radius: 8px;
  border: 1px solid var(--color-border, #ddd);
  background: var(--color-background-50);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.10);
  font-size: 11px;
  font-weight: 400;
  line-height: 1.3;
  color: var(--color-text-600);
  white-space: nowrap;
  z-index: 2;
}

/* The value is the reading; the date is its label. */
.chart__tip em {
  font-style: normal;
  font-weight: 700;
  font-size: 13px;
  color: var(--color-text-900, inherit);
}

/* Anchor inward at the ends so a label cannot be clipped off the plot. */
.chart__col:first-child .chart__tip { left: 0; transform: translate(0, 14px); }
.chart__col:last-child .chart__tip { left: auto; right: 0; transform: translate(0, 14px); }

@media (max-width: 767px) {
  /* Shorter plot, smaller axis: the chart is a glance on a phone, and a
     220px block pushed the ledger below the fold on every load. */
  .chart__svg,
  .chart__yaxis { height: 150px; }

  .chart__yaxis { font-size: 10px; }

  .chart__plot { gap: 6px; }

  /* Touch has no hover state to rest in, so the tooltip must also answer to
     a press. iOS fires :hover on tap and keeps it until you tap elsewhere;
     :active covers the browsers that do not. */
  .chart__col:active::before { opacity: 0.35; }
  .chart__col:active .chart__dot,
  .chart__col:active .chart__tip { opacity: 1; }

  /* A 30-bucket month is a 10px column on a 375px screen. The label is what
     needs the room, so it grows rather than the target. */
  .chart__tip {
    font-size: 12px;
    padding: 7px 10px;
  }
  .chart__tip em { font-size: 15px; }

  .range-chip { padding: 8px 14px; }

  /* Title, unit and total stack rather than crushing into one line. */
  .chart__title { display: block; }
  .chart__unit { display: block; }
  .chart__total { display: block; margin-top: 2px; }
}

/* --------------------------------------------------- buyer contacts
   Who we ring when a delivery cannot get in. The contact list is the
   buyer's address book; the license-contacts row hangs a subset of it
   under each premises. */
.license-contacts > td {
  padding-top: 0;
  border-top: 0;
}

.license-contacts__label {
  display: inline-block;
  margin-right: 10px;
  font-size: 12px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-text-500, #6b7280);
}

/* The picker needs room to open, so the add form sits on its own line
   under the chips rather than fighting them for width. */
.license-contacts__add {
  display: flex;
  gap: 8px;
  align-items: center;
  margin-top: 8px;
  flex-wrap: wrap;
}

.license-contacts__add .picker { flex: 1 1 240px; min-width: 0; }

/* The × is a submit button for a form elsewhere on the page, so it has to
   shed the button chrome to read as part of the chip. */
.chip__x {
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  cursor: pointer;
  color: inherit;
  line-height: 1;
}

.contact-list {
  list-style: none;
  margin: 0 0 18px;
  padding: 0;
  display: grid;
  gap: 8px;
}

.contact-card {
  display: flex;
  gap: 12px;
  align-items: center;
  justify-content: space-between;
  padding: 10px 14px;
  border: 1px solid var(--color-background-700, #ddd);
  border-radius: 10px;
  background: var(--color-background-50, #fff);
}

.contact-card .muted { font-size: 13px; }

@media (max-width: 640px) {
  .contact-card { flex-direction: column; align-items: flex-start; }
}

/* --------------------------------------------------------- TOTP enrolment
   The QR is an inline SVG generated server-side, so the secret never travels
   to a third-party chart service the way an <img src="…/qr?data="> would.
   Boxed on white regardless of theme: a dark-mode QR with inverted modules
   does not scan on many phones. */
.totp-qr {
  display: inline-block;
  padding: 12px;
  margin: 4px 0 14px;
  background: #fff;
  border: 1px solid var(--color-background-700, #ddd);
  border-radius: 10px;
  line-height: 0;
}

.totp-qr svg { width: 200px; height: 200px; }

/* ---- Message wording (admin) ---------------------------------------- */
/* Editor and preview side by side: the whole value of this screen is
   seeing your change and its result at the same time. Below 1000px they
   stack, editor first — on a phone you are almost certainly fixing a typo
   somebody just reported, not composing. */
.tpl-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 28px;
  align-items: start;
}

@media (max-width: 1000px) {
  .tpl-grid { grid-template-columns: minmax(0, 1fr); gap: 20px; }
}

.tpl-grid__edit textarea { width: 100%; resize: vertical; }

.mail-preview {
  border: 1px solid var(--color-background-700, #ddd);
  border-radius: 10px;
  overflow: hidden;
  margin-bottom: 18px;
}

.mail-preview__subject {
  padding: 10px 14px;
  font-weight: 600;
  background: var(--color-background-200, #f4f4f4);
  border-bottom: 1px solid var(--color-background-700, #ddd);
}

/* pre, not a <p> stack: these bodies are plain text and their alignment is
   load-bearing — the ACH block is columns held together by spaces. */
.mail-preview__body {
  margin: 0;
  padding: 14px;
  white-space: pre-wrap;
  word-break: break-word;
  font: 13px/1.55 var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
}

/* ---- Pay several invoices with one transfer -------------------------- */
.pay-pick { list-style: none; margin: 12px 0; padding: 0; }

.pay-pick li + li { margin-top: 2px; }

.pay-pick label {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  padding: 8px 10px;
  border-radius: 8px;
  cursor: pointer;
}

.pay-pick label:hover { background: var(--color-background-200, #f4f4f4); }

/* The amount sits hard right on a wide row so the column is scannable, and
   falls back into the flow on a phone rather than stranding itself. */
.pay-pick label > span:nth-of-type(2) { margin-left: auto; font-variant-numeric: tabular-nums; }

@media (max-width: 560px) {
  .pay-pick label > span:nth-of-type(2) { margin-left: 0; }
}

/* ---- Disabled buttons, everywhere ------------------------------------ */
/* Only .add-to-cart and the quick-buy had this. Everywhere else a disabled
   button rendered at full contrast with a pointer cursor — it looks live, so
   somebody clicks it and nothing happens, with no clue why. Found on the
   "Receipt in QuickBooks" button, which is disabled precisely when money
   would otherwise move against a disconnected ledger. */
.button[disabled],
.button:disabled {
  opacity: 0.45;
  cursor: not-allowed;
  box-shadow: none;
}

.button[disabled]:hover,
.button:disabled:hover {
  opacity: 0.45;
  transform: none;
}

/* ---- Terms of Service: a long legal document, kept readable ----------- */
.terms {
  max-width: 760px;
  margin: 0 auto;
  line-height: 1.6;
}

.terms p,
.terms li { margin: 0 0 12px; }

.terms ol,
.terms ul { padding-left: 26px; }

/* ---- Register: the clickwrap line ------------------------------------- */
.checkline {
  display: flex;
  gap: 10px;
  align-items: flex-start;
}

.checkline input[type="checkbox"] {
  margin-top: 4px;
  flex: none;
}

/* ---- GreenCard pay page: their checkout embedded, ours around it ------ */
/* Narrow on purpose: their checkout is a phone-shaped sheet, and payment
   forms stretched across a desktop read as fake. */
.pay-sheet { max-width: 680px; margin: 0 auto; }

.pay-sheet__bar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 12px;
}

.pay-sheet__ref {
  color: var(--color-text-700);
  overflow-wrap: anywhere;
}

.pay-sheet__actions {
  margin-left: auto;
  display: flex;
  gap: 8px;
}

/* White plate behind the frame so their sheet has no dark seam while it
   loads, in our dark theme included — the framed page is light-only. */
.pay-sheet__frame {
  background: #fff;
  border: 1px solid var(--color-background-700, #ddd);
  border-radius: 12px;
  overflow: hidden;
}

.pay-sheet__frame iframe {
  display: block;
  width: 100%;
  border: 0;
  height: 74vh;
  height: clamp(520px, 78dvh, 820px);
}

@media (max-width: 820px) {
  .pay-sheet__actions { margin-left: 0; width: 100%; }
  .pay-sheet__actions .button { flex: 1 1 0; }
}
