/* Stitch — components (design.md 7)
 *
 * Two presentations of one app: an installable iOS-style PWA on the phone,
 * and a dense admin application on the desktop — dark sidebar, search top
 * bar, charts. Mobile-first; the desktop chrome appears at 1024px.
 */

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

html { -webkit-text-size-adjust: 100%; background: var(--bg-system); }

body {
  margin: 0;
  font-family: var(--font);
  font-size: var(--fs-body);
  line-height: 1.4;
  color: var(--label);
  background: var(--bg-system);
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
  overscroll-behavior-y: none;
}

.sidebar, .tabbar, .segmented, .topbar { user-select: none; -webkit-user-select: none; }

a { color: var(--blue); text-decoration: none; }
h1, h2, h3, p, ul, ol, figure { margin: 0; }
ul, ol { list-style: none; padding: 0; }
button { font: inherit; color: inherit; }
code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.9em; }
.icon { width: 22px; height: 22px; display: block; }

/* ---------- Shell ------------------------------------------------------ */

.app { min-height: 100dvh; }
.main { min-width: 0; }
.topbar, .accent, .pagehead, .crumbs { display: none; }

/* ---------- Phone app bar + nav drawer ----------------------------------
 *
 * The five bottom tabs cover the screens used hourly. Everything else —
 * Books, Karigars, Settings, Locations — had no route on a phone at all.
 * The drawer is the SAME nav definition the desktop sidebar renders, so a
 * section added to one appears in the other.
 */

.appbar {
  position: sticky;
  top: 0;
  z-index: 25;
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  min-height: var(--navbar-h);
  padding: 0 var(--sp-1) 0 var(--sp-2);
  padding-top: var(--safe-t);
  background: rgba(255, 255, 255, 0.86);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  border-bottom: 0.5px solid var(--separator);
}

.appbar__title {
  flex: 1;
  min-width: 0;
  font-size: var(--fs-headline);
  font-weight: 600;
  letter-spacing: -0.2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding-inline: var(--sp-1);
}

.appbar__btn {
  position: relative;
  flex: none;
  width: 40px; height: 40px;
  display: grid; place-items: center;
  border: 0;
  border-radius: 10px;
  background: transparent;
  color: var(--label);
  cursor: pointer;
}
.appbar__btn:active { background: var(--fill); }
.appbar__btn .icon { width: 21px; height: 21px; }

/* Phone: the sidebar IS the drawer. Off-canvas until opened. */
.sidebar {
  position: fixed;
  top: 0; left: 0; bottom: 0;
  z-index: 45;
  width: min(84vw, 300px);
  display: flex;
  flex-direction: column;
  padding: calc(var(--safe-t) + var(--sp-4)) var(--sp-3) calc(var(--safe-b) + var(--sp-4));
  background: var(--bg-secondary);
  border-right: 1px solid var(--border);
  overflow-y: auto;
  transform: translateX(-102%);
  visibility: hidden;
  transition: transform 0.24s cubic-bezier(0.32, 0.72, 0, 1), visibility 0.24s;
}
.app.is-nav-open .sidebar { transform: none; visibility: visible; }

.scrim {
  position: fixed;
  inset: 0;
  z-index: 44;
  background: rgba(16, 24, 40, 0.42);
  opacity: 0;
  transition: opacity 0.24s ease;
}
.scrim[hidden] { display: none; }
.app.is-nav-open .scrim { opacity: 1; }

/* The bell carries a number, not a dot — "3 things" is actionable in a way
   that "something" is not. Sits on both the phone app bar and the desktop
   top bar, so it is defined once here. */
.topbar__count {
  position: absolute;
  top: 3px; right: 2px;
  min-width: 17px;
  height: 17px;
  padding: 0 4px;
  border-radius: var(--r-pill);
  background: var(--red);
  color: var(--label-on-color);     /* safe: saturated red pill */
  font-size: 10px;
  font-weight: 700;
  line-height: 17px;
  text-align: center;
  font-variant-numeric: tabular-nums;
  box-shadow: 0 0 0 2px var(--bg-secondary);
}

.sidebar__close {
  flex: none;
  width: 34px; height: 34px;
  display: grid; place-items: center;
  border: 0;
  border-radius: 9px;
  background: var(--fill);
  color: var(--label-secondary);
  cursor: pointer;
}
.sidebar__close .icon { width: 17px; height: 17px; }

/* On the phone the drawer already has a close button, so the collapse
   control would be a second thing meaning almost the same. */
.sidebar__toggle { display: none; }

@media (prefers-reduced-motion: reduce) {
  .sidebar, .scrim { transition: none; }
}

/* ---------- Sidebar contents (shared by drawer and desktop rail) --------- */

.sidebar__head { display: flex; align-items: center; gap: var(--sp-2); padding-bottom: var(--sp-4); }
.sidebar__brand { flex: 1; min-width: 0; display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-2) var(--sp-3); color: var(--label); }

.sidebar__toggle {
  flex: none;
  width: 34px; height: 34px;
  display: grid; place-items: center;
  border: 0;
  border-radius: 9px;
  background: var(--fill);
  color: var(--label-secondary);
  cursor: pointer;
}
.sidebar__toggle:hover { background: var(--fill-strong); color: var(--label); }
.sidebar__toggle .icon { width: 18px; height: 18px; }
.sidebar__mark {
  width: 34px; height: 34px;
  border-radius: 10px;
  background: linear-gradient(150deg, #2f7bff 0%, #0a53d6 100%);
  display: grid; place-items: center;
  color: #fff;                      /* safe: saturated blue tile */
  flex: none;
  box-shadow: 0 2px 6px rgba(10, 83, 214, 0.32);
}
.sidebar__mark .icon { width: 20px; height: 20px; }
.sidebar__brand-text { display: flex; flex-direction: column; }
.sidebar__brand-name { font-size: var(--fs-headline); font-weight: 700; letter-spacing: -0.2px; color: var(--label); }
.sidebar__brand-sub { font-size: 10px; letter-spacing: 0.09em; text-transform: uppercase; color: var(--label-secondary); }

.sidebar__nav { display: flex; flex-direction: column; flex: 1; }

/* A category label with a rule running out from it to the edge. The rule is
   the separation — it closes off the section above without spending a whole
   row of vertical space on a divider. */
.sidebar__group {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--label-secondary);
  font-weight: 600;
  padding: var(--sp-4) var(--sp-3) var(--sp-2);
}
.sidebar__group::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--border);
}

.sidebar__items { display: flex; flex-direction: column; gap: 2px; }

.sidebar__item {
  position: relative;               /* anchors the connector dot below */
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: 40px;
  padding: 0 var(--sp-3);
  border-radius: 9px;
  color: var(--label);
  font-size: var(--fs-subhead);
  font-weight: 500;
  transition: background 0.12s ease, color 0.12s ease;
}

.sidebar__item .sidebar__icon { color: var(--label-secondary); transition: color 0.12s ease; }
.sidebar__item:hover { background: var(--fill); }
.sidebar__item:hover .sidebar__icon { color: var(--label); }

/* The active item is a tinted pill with a rail, so the current section is
   findable at a glance without reading. */
.sidebar__item.is-active {
  background: var(--blue-soft);
  color: var(--blue);
  font-weight: 600;
  box-shadow: inset 2px 0 0 var(--blue);
}
.sidebar__item.is-active .sidebar__icon { color: var(--blue); }

/* Points at a section with more inside it. */
.sidebar__more { width: 14px; height: 14px; flex: none; color: var(--label-tertiary); }
.sidebar__item.is-active .sidebar__more { color: var(--blue); }

.sidebar__icon { width: 19px; height: 19px; flex: none; }
.sidebar__label { flex: 1; }

.sidebar__badge {
  min-width: 20px;
  padding: 1px 6px;
  border-radius: var(--r-pill);
  background: var(--fill-strong);
  color: var(--label-secondary);
  font-size: 11px;
  font-weight: 600;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.sidebar__item.is-active .sidebar__badge { background: var(--blue); color: var(--label-on-color); }

.sidebar__foot { margin-top: var(--sp-4); padding-top: var(--sp-3); border-top: 1px solid var(--border); display: flex; flex-direction: column; gap: var(--sp-2); }

/* What the client is running. On a product sold per install, the edition
   belongs where the operator can read it back to you on a call. */
.sidebar__product {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3);
  border-radius: 10px;
  background: var(--bg-system);
  border: 1px solid var(--border);
}
.sidebar__product-mark {
  width: 30px; height: 30px; flex: none;
  border-radius: 8px;
  display: grid; place-items: center;
  background: var(--blue-soft);
  color: var(--blue);
}
.sidebar__product-mark .icon { width: 17px; height: 17px; }
.sidebar__product-text { display: flex; flex-direction: column; min-width: 0; }
.sidebar__product-name { font-size: var(--fs-footnote); font-weight: 700; color: var(--label); display: flex; align-items: center; gap: 6px; }
.sidebar__product-sub { font-size: 10px; color: var(--label-secondary); }
.sidebar__pro {
  font-size: 9px; font-weight: 700; letter-spacing: 0.04em;
  padding: 1px 5px; border-radius: var(--r-pill);
  background: var(--green-soft); color: var(--green);
}

.sidebar__signout {
  width: 100%;
  min-height: 40px;
  display: flex; align-items: center; justify-content: center; gap: var(--sp-2);
  border: 1px solid var(--border);
  border-radius: 9px;
  background: transparent;
  color: var(--label-secondary);
  font-size: var(--fs-footnote);
  font-weight: 600;
  cursor: pointer;
}
.sidebar__signout .icon { width: 16px; height: 16px; }
.sidebar__signout:hover { background: var(--red-soft); color: var(--red); border-color: transparent; }

.content {
  padding: var(--sp-4) var(--sp-4) calc(var(--tabbar-h) + var(--safe-b) + var(--sp-8));
  max-width: 780px;
  margin: 0 auto;
}

/* A bare CARD page — login, offline. Centred in the viewport. */
.app--bare .content {
  padding-bottom: calc(var(--safe-b) + var(--sp-8));
  min-height: 100dvh;
  display: flex;
  align-items: center;
}

/* A bare DOCUMENT page — label sheet, printable invoice. Starts at the top,
   like paper. Without this the centring above floats a short document in the
   middle of an empty screen, which reads as a broken page. */
.app--bare .content--doc {
  display: block;
  min-height: 0;
  padding-top: var(--sp-5);
}

/* Phone: the large title lives at the top of the content column. */
.pagehead__title { font-size: var(--fs-large-title); font-weight: 700; letter-spacing: -0.5px; }
.pagehead__sub { font-size: var(--fs-subhead); color: var(--label-secondary); margin-top: 2px; }

/* ---------- Bottom tab bar (phone) ------------------------------------- */

.tabbar {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 30;
  display: flex;
  padding-bottom: var(--safe-b);
  background: rgba(249, 249, 249, 0.82);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  border-top: 0.5px solid var(--separator);
}

.tabbar__item {
  flex: 1;
  min-height: var(--tabbar-h);
  padding: 6px 0 4px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  color: var(--label-secondary);
}

.tabbar__item.is-active { color: var(--blue); }
.tabbar__item:active { opacity: 0.55; }
.tabbar__icon { width: 24px; height: 24px; }
.tabbar__label { font-size: 10px; font-weight: 500; }

/* ---------- Cards, groups, lists --------------------------------------- */

.card {
  background: var(--bg-secondary);
  border-radius: var(--r-card);
  padding: var(--sp-4);
  margin-bottom: var(--sp-4);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-card);
}

.card__title { font-size: var(--fs-headline); font-weight: 600; margin-bottom: var(--sp-1); }
.card__sub { font-size: var(--fs-footnote); color: var(--label-secondary); margin-bottom: var(--sp-3); }
.card__head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-4); margin-bottom: var(--sp-3); }
.card--profile { display: flex; align-items: center; gap: var(--sp-3); }
.card__profile-body { display: flex; flex-direction: column; min-width: 0; }
.card__profile-name { font-size: var(--fs-headline); font-weight: 600; }
.card__profile-role { font-size: var(--fs-footnote); color: var(--label-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.group { margin-bottom: var(--sp-5); }

.group__title {
  font-size: var(--fs-footnote);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--label-secondary);
  padding: 0 var(--sp-4) var(--sp-2);
}

.list {
  background: var(--bg-secondary);
  border-radius: var(--r-list);
  overflow: hidden;
  border: 1px solid var(--border);
  box-shadow: var(--shadow-card);
}

.list--plain { box-shadow: none; background: transparent; }

.list__row {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: 8px var(--sp-4);
  min-height: 38px;
  position: relative;
  color: var(--label);
  width: 100%;
  text-align: left;
  background: none;
  border: 0;
  cursor: pointer;
}

.list li + li .list__row::before,
.list__row + .list__row::before {
  content: "";
  position: absolute;
  left: 56px; right: 0; top: 0;
  height: 0.5px;
  background: var(--separator);
}

.list__row--link:active, .list__row--button:active { background: var(--fill); }
.list__row--link:hover { background: rgba(120, 120, 128, 0.06); }
.list__body { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.list__title { font-size: var(--fs-callout); font-weight: 500; }
.list__title--danger { color: var(--red); }
.list__sub { font-size: var(--fs-footnote); color: var(--label-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.list__chevron { color: var(--label-tertiary); font-size: 20px; line-height: 1; flex: none; }

/* ---------- Icon chips -------------------------------------------------- */

.chip { flex: none; width: 30px; height: 30px; border-radius: var(--r-chip); display: grid; place-items: center; }
.chip .icon { width: 18px; height: 18px; }
.chip--sm { width: 29px; height: 29px; }
.chip--lg { width: 44px; height: 44px; border-radius: 12px; }
.chip--lg .icon { width: 24px; height: 24px; }

/* Each chip pairs a ~15% tint with the full-strength colour as the mark, so
   the glyph always has a light surface behind it. */
.chip--blue   { background: var(--blue-soft);   color: var(--blue); }
.chip--green  { background: var(--green-soft);  color: var(--green); }
.chip--orange { background: var(--orange-soft); color: var(--orange); }
.chip--purple { background: var(--purple-soft); color: var(--purple); }
.chip--red    { background: var(--red-soft);    color: var(--red); }

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

.kpis {
  display: flex;
  gap: var(--sp-3);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding-bottom: var(--sp-3);
  margin: 0 calc(var(--sp-4) * -1) var(--sp-2);
  padding-inline: var(--sp-4);
  scrollbar-width: none;
}

.kpis::-webkit-scrollbar { display: none; }

.kpi {
  flex: 0 0 auto;
  min-width: 156px;
  scroll-snap-align: start;
  background: var(--bg-secondary);
  border-radius: var(--r-card);
  padding: var(--sp-3) var(--sp-4) 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  box-shadow: var(--shadow-card);
  overflow: hidden;
  position: relative;
}

.kpi__head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); }
.kpi__label { font-size: var(--fs-footnote); color: var(--label-secondary); font-weight: 500; }
.kpi__value { font-size: var(--fs-title); font-weight: 700; letter-spacing: -0.3px; font-variant-numeric: tabular-nums; }
.kpi__spark { margin: var(--sp-2) calc(var(--sp-4) * -1) 0; height: 44px; }
.kpi__spark .spark { width: 100%; height: 44px; display: block; }
.kpi--zero .kpi__value { color: var(--label-secondary); font-weight: 600; }
.kpi--zero .chip { opacity: 0.55; }

/* ---------- Segmented control ------------------------------------------ */

.segmented { display: flex; background: var(--fill); border-radius: var(--r-input); padding: 2px; margin-bottom: var(--sp-4); }

.segmented__item {
  flex: 1;
  text-align: center;
  padding: 6px 0;
  font-size: var(--fs-footnote);
  font-weight: 500;
  color: var(--label);
  border-radius: 10px;
}

.segmented__item.is-active { background: var(--bg-secondary); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08); font-weight: 600; }

/* ---------- Charts ------------------------------------------------------ */

.chart { width: 100%; height: auto; display: block; }
.donut { width: 168px; height: 168px; display: block; margin: 0 auto; }
.gauge { width: 100%; max-width: 240px; height: auto; display: block; margin: 0 auto; }

.chart-row { display: flex; align-items: center; gap: var(--sp-4); flex-wrap: wrap; }
.chart-row > .donut { flex: none; }
.chart-row > .legend { flex: 1; min-width: 180px; }

/* A legend is always present for >= 2 series — and it is the relief for the
   two palette slots that sit below 3:1 on white. Never colour alone. */
.legend { display: flex; flex-direction: column; gap: 2px; }

.legend__row {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 5px 0;
  font-size: var(--fs-footnote);
}

.legend__dot { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.legend__label { flex: 1; color: var(--label); }
.legend__value { font-variant-numeric: tabular-nums; font-weight: 600; }
.legend__pct { font-variant-numeric: tabular-nums; color: var(--label-secondary); min-width: 40px; text-align: right; }

.legend--inline { flex-direction: row; gap: var(--sp-4); margin-bottom: var(--sp-2); }
.legend--inline .legend__row { padding: 0; }

.barlist { display: flex; flex-direction: column; gap: var(--sp-2); }
.barlist__row { display: flex; align-items: center; gap: var(--sp-3); font-size: var(--fs-footnote); }
.barlist__label { width: 34%; min-width: 90px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.barlist__track { flex: 1; height: 8px; border-radius: var(--r-pill); background: var(--fill); overflow: hidden; }
.barlist__fill { display: block; height: 100%; border-radius: var(--r-pill); }
.barlist__value { font-variant-numeric: tabular-nums; font-weight: 600; min-width: 56px; text-align: right; }

/* ---------- Pipeline ---------------------------------------------------- */

.pipeline { display: flex; flex-direction: column; gap: var(--sp-4); }
.pipeline__head { display: flex; align-items: center; gap: var(--sp-2); }
.pipeline__dot { width: 9px; height: 9px; border-radius: 50%; background: var(--label-tertiary); flex: none; }
.pipeline__dot.is-active { background: var(--orange); }
.pipeline__name { font-size: var(--fs-subhead); font-weight: 500; flex: 1; }
.pipeline__count { font-size: var(--fs-footnote); color: var(--label-secondary); font-variant-numeric: tabular-nums; }
.pipeline__meta { font-size: var(--fs-caption); color: var(--label-secondary); font-variant-numeric: tabular-nums; }

.progress { height: 6px; border-radius: var(--r-pill); background: var(--fill); overflow: hidden; margin: var(--sp-2) 0 var(--sp-1); }
.progress__fill { display: block; height: 100%; border-radius: var(--r-pill); background: var(--orange); transition: width 0.4s ease; }
.progress--lg { height: 8px; margin: var(--sp-3) 0 var(--sp-4); }
.progress__fill--blue { background: var(--blue); }

/* ---------- First-run checklist ---------------------------------------- */

.setup__head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-4); }
.setup__sub { font-size: var(--fs-footnote); color: var(--label-secondary); margin-top: 2px; }
.setup__count { font-size: var(--fs-title); font-weight: 700; color: var(--blue); font-variant-numeric: tabular-nums; line-height: 1; }

.steps { display: flex; flex-direction: column; gap: 2px; }
.step { display: flex; align-items: flex-start; gap: var(--sp-3); padding: var(--sp-3) 0; position: relative; }
.step + .step::before { content: ""; position: absolute; left: 40px; right: 0; top: 0; height: 0.5px; background: var(--separator); }

.step__mark {
  flex: none;
  width: 28px; height: 28px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: var(--fs-footnote);
  font-weight: 600;
  background: var(--fill);
  color: var(--label-secondary);
}

.step__mark .icon { width: 17px; height: 17px; }
.step.is-done .step__mark { background: var(--green-soft); color: var(--green); }
.step__body { display: flex; flex-direction: column; min-width: 0; flex: 1; gap: 2px; }
.step__label { font-size: var(--fs-callout); font-weight: 600; }
.step.is-done .step__label { color: var(--label-secondary); font-weight: 500; }
.step__hint { font-size: var(--fs-footnote); color: var(--label-secondary); line-height: 1.4; }
.step.is-done .step__hint { display: none; }
.step__cta { flex: none; align-self: center; white-space: nowrap; }
.step__cta--muted { font-size: var(--fs-caption); color: var(--label-tertiary); }

.card__more { display: inline-block; margin-top: var(--sp-3); font-size: var(--fs-footnote); font-weight: 500; }

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

.badge { display: inline-block; padding: 3px 8px; border-radius: var(--r-pill); font-size: var(--fs-caption); font-weight: 600; border: 0; }
.badge--ready   { background: var(--green-soft);  color: var(--green); }
.badge--process { background: var(--orange-soft); color: var(--orange); }
.badge--memo    { background: var(--purple-soft); color: var(--purple); }
.badge--sold    { background: var(--fill);        color: var(--label-secondary); }

/* ---------- Forms ------------------------------------------------------- */

.field { margin-bottom: var(--sp-4); }
.field__label { display: block; font-size: var(--fs-footnote); font-weight: 600; color: var(--field-label); margin-bottom: 6px; }

.field__input {
  width: 100%;
  font-size: 16px;              /* stops iOS auto-zoom on focus */
  font-family: inherit;
  color: var(--label);
  background: var(--field-bg);
  border: 1px solid var(--field-border);
  border-radius: var(--r-input);
  box-shadow: var(--field-shadow);
  padding: 7px 10px;
  min-height: 36px;
  appearance: none;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.field__input::placeholder { color: var(--field-placeholder); }
.field__input:hover:not(:disabled):not([readonly]):not(:focus) { border-color: var(--field-border-hov); }

/* The focus ring REPLACES the inset shadow rather than stacking with it, so
   a focused field reads as lifted rather than merely recoloured. */
.field__input:focus { outline: none; border-color: var(--blue); box-shadow: 0 0 0 3px var(--blue-soft); }

.field__input:disabled,
.field__input[readonly] {
  background: var(--fill);
  color: var(--label-secondary);
  box-shadow: none;
  cursor: not-allowed;
}

/* A rejected field must be findable without reading — same weight as focus,
   in red. */
.field__input[aria-invalid="true"] { border-color: var(--red); box-shadow: 0 0 0 3px var(--red-soft); }
.field__hint { font-size: var(--fs-caption); color: var(--label-secondary); margin-top: 5px; }

select.field__input {
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath fill='none' stroke='%233c3c43' stroke-opacity='.6' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round' d='M1 1.5 6 6.5 11 1.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--sp-3) center;
  background-size: 12px 8px;
  padding-right: var(--sp-6);
}

textarea.field__input { min-height: 84px; resize: vertical; line-height: 1.4; }
.field__input--xs { width: 90px; }
.field__input--sm { width: 110px; }
.field--inline { display: flex; gap: var(--sp-3); }
.field--inline > * { flex: 1; }

.toolbar { display: flex; gap: var(--sp-2); margin-bottom: var(--sp-4); }
.toolbar__search { flex: 2; min-height: 40px; padding-block: 8px; }
.toolbar__select { flex: 1; min-height: 40px; padding-block: 8px; }

.switch { display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-2) 0; cursor: pointer; min-height: 44px; }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch__track { flex: none; width: 51px; height: 31px; border-radius: var(--r-pill); background: var(--fill-strong); padding: 2px; transition: background 0.2s ease; }
.switch__thumb { display: block; width: 27px; height: 27px; border-radius: 50%; background: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); transition: transform 0.2s ease; }
.switch input:checked + .switch__track { background: var(--green); }
.switch input:checked + .switch__track .switch__thumb { transform: translateX(20px); }
.switch input:focus-visible + .switch__track { box-shadow: 0 0 0 3px var(--blue-soft); }
.switch__label { font-size: var(--fs-callout); }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-height: 34px;
  padding: 0 var(--sp-4);
  border: 0;
  border-radius: var(--r-input);
  font-size: var(--fs-callout);
  font-weight: 600;
  cursor: pointer;
  transition: opacity 0.12s ease;
}

.btn:active { opacity: 0.6; }
.btn--block { width: 100%; }
.btn--sm { min-height: 34px; padding: 0 var(--sp-3); font-size: var(--fs-footnote); }
.btn--primary { background: var(--blue); color: var(--label-on-color); }
.btn--secondary { background: var(--fill); color: var(--blue); }
.btn--danger { background: var(--red); color: var(--label-on-color); }
.btn-row { display: flex; gap: var(--sp-2); flex-wrap: wrap; }

.savebar {
  position: sticky;
  bottom: calc(var(--tabbar-h) + var(--safe-b));
  display: flex;
  gap: var(--sp-3);
  padding: var(--sp-3) 0;
  background: linear-gradient(to top, var(--bg-system) 65%, transparent);
}

.savebar .btn { flex: 1; }

.fab {
  position: fixed;
  right: calc(var(--sp-4) + var(--safe-r));
  bottom: calc(var(--tabbar-h) + var(--safe-b) + var(--sp-4));
  z-index: 25;
  width: 56px; height: 56px;
  border-radius: 50%;
  background: var(--blue);
  color: var(--label-on-color);
  display: grid;
  place-items: center;
  box-shadow: 0 6px 20px rgba(0, 122, 255, 0.35);
}

.fab:active { opacity: 0.7; }
.fab .icon { width: 26px; height: 26px; }

.alert { padding: var(--sp-3) var(--sp-4); border-radius: var(--r-input); font-size: var(--fs-subhead); margin-bottom: var(--sp-4); }
.alert--error { background: var(--red-soft); color: var(--red); }
.alert--ok { background: var(--green-soft); color: var(--green); }

/* ---------- Key/value + tables ----------------------------------------- */

.kv { display: flex; justify-content: space-between; gap: var(--sp-3); padding: 5px 0; }
.kv + .kv { border-top: 0.5px solid var(--separator); }
.kv__k { color: var(--label-secondary); font-size: var(--fs-subhead); }
.kv__v { font-variant-numeric: tabular-nums; font-size: var(--fs-subhead); font-weight: 500; text-align: right; }
.kv--total .kv__k, .kv--total .kv__v { font-size: var(--fs-headline); font-weight: 700; }

.stat-row { display: flex; gap: var(--sp-4); flex-wrap: wrap; align-items: center; }
.stat { flex: 1; min-width: 90px; display: flex; align-items: center; gap: var(--sp-3); }
.stat__v { display: block; font-size: var(--fs-title); font-weight: 700; font-variant-numeric: tabular-nums; }
.stat__k { display: block; font-size: var(--fs-caption); color: var(--label-secondary); }
.stat__body { min-width: 0; }

/* Optional icon tile. Present on the summary strips, absent where a stat is
   just a number in a table. */
.stat__mark {
  width: 38px; height: 38px; flex: none;
  border-radius: 10px;
  display: grid; place-items: center;
  background: var(--blue-soft);
  color: var(--blue);
}
.stat__mark .icon { width: 19px; height: 19px; }
.stat__mark--green  { background: var(--green-soft);  color: var(--green); }
.stat__mark--orange { background: var(--orange-soft); color: var(--orange); }
.stat__mark--purple { background: var(--purple-soft); color: var(--purple); }

/* Says the figures are computed now, not cached from a nightly job — the
   question every ERP buyer asks about a dashboard. */
.stat__live {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px;
  border-radius: var(--r-pill);
  background: var(--green-soft);
  color: var(--green);
  font-size: var(--fs-caption);
  font-weight: 600;
  flex: none;
}
.stat__live::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }

.scroll-x { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.table { width: 100%; border-collapse: collapse; font-size: var(--fs-footnote); }
.table th, .table td { padding: 6px 10px; text-align: left; white-space: nowrap; }
.table th { color: var(--label-secondary); font-weight: 500; text-transform: uppercase; letter-spacing: 0.04em; font-size: var(--fs-caption); }
.table tbody tr { border-top: 0.5px solid var(--separator); }
.table tbody tr:hover { background: rgba(120, 120, 128, 0.05); }
.table .num { text-align: right; font-variant-numeric: tabular-nums; }

/* ---------- Dense tables (the books) ----------------------------------- */

.table--dense th, .table--dense td { padding: 5px 9px; font-size: var(--fs-caption); }
.table--dense tbody tr { border-top: 1px solid var(--border); }
.table tfoot td { border-top: 2px solid var(--separator); padding-top: 7px; }
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.92em; }
.muted { color: var(--label-secondary); }
.indent { padding-left: 22px !important; }
.row--group { background: rgba(16, 24, 40, 0.025); }
.row--group td { font-weight: 600; }
.pos { color: var(--green); }
.neg { color: var(--red); }

/* ---------- Packet labels ---------------------------------------------- */

.labels__actions { display: flex; gap: var(--sp-3); margin-bottom: var(--sp-4); }
.labels__sheet { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: var(--sp-3); }

.label {
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 8px;
  background: #fff;
  break-inside: avoid;
}

.label__top { display: flex; justify-content: space-between; font-size: var(--fs-caption); margin-bottom: 4px; }
.label__foot { display: flex; justify-content: space-between; font-size: 10px; color: var(--label-secondary); margin-top: 2px; }
.barcode { width: 100%; height: auto; display: block; }

/* An over-norm loss is the one row a floor manager must not scroll past. */
.row--flag { background: var(--red-soft); }

/* ---------- Auth screens ------------------------------------------------ */

.auth { width: 100%; max-width: 380px; margin: 0 auto; padding: var(--sp-6) 0; }
.auth__brand { text-align: center; margin-bottom: var(--sp-6); }
.auth__logo { width: 56px; height: 56px; margin: 0 auto var(--sp-3); color: var(--blue); }
.auth__title { font-size: 28px; font-weight: 700; letter-spacing: -0.4px; }
.auth__tagline { font-size: var(--fs-subhead); color: var(--label-secondary); margin-top: var(--sp-2); }
.auth__form { margin-bottom: var(--sp-4); }
.auth__note { font-size: var(--fs-caption); color: var(--label-secondary); text-align: center; line-height: 1.5; }

/* ---------- Empty states ------------------------------------------------ */

.empty { text-align: center; padding: var(--sp-8) var(--sp-4); }

/* The icon sits in a tinted disc rather than floating grey on grey. An empty
   screen is the first thing a new client sees, and "nothing here" should
   still look like a finished product. */
.empty__icon {
  width: 88px; height: 88px;
  margin: 0 auto var(--sp-5);
  padding: 22px;
  border-radius: 50%;
  background: var(--blue-soft);
  color: var(--blue);
}
.empty__title { font-size: var(--fs-title); font-weight: 700; margin-bottom: var(--sp-2); }
.empty__text { font-size: var(--fs-subhead); color: var(--label-secondary); max-width: 40ch; margin: 0 auto var(--sp-5); line-height: 1.55; }
.empty__meta { font-size: var(--fs-caption); color: var(--label-secondary); margin-bottom: var(--sp-4); }

/* Three things this section does for you — shown while it is empty, because
   that is exactly when the operator does not yet know. */
.empty__points {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: var(--sp-3);
  max-width: 720px;
  margin: var(--sp-6) auto 0;
  text-align: left;
}
.empty__point {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  font-size: var(--fs-footnote);
  font-weight: 500;
}
.empty__point-mark {
  width: 32px; height: 32px; flex: none;
  border-radius: 9px;
  display: grid; place-items: center;
  background: var(--blue-soft);
  color: var(--blue);
}
.empty__point-mark .icon { width: 17px; height: 17px; }
.footnote { text-align: center; font-size: var(--fs-caption); color: var(--label-secondary); padding: var(--sp-4) 0; }

/* ---------- Printable documents ---------------------------------------- */

.doc { background: var(--bg-secondary); border-radius: var(--r-card); padding: var(--sp-5); max-width: 760px; margin: 0 auto; }
.doc__head { display: flex; justify-content: space-between; gap: var(--sp-4); flex-wrap: wrap; }
.doc__right { text-align: right; }
.doc__title { font-size: var(--fs-title); font-weight: 700; }
.doc__kind { font-size: var(--fs-headline); font-weight: 700; letter-spacing: 0.04em; }
.doc__meta { font-size: var(--fs-footnote); color: var(--label-secondary); }
.doc__party { margin: var(--sp-5) 0; }
.doc__totals { margin-top: var(--sp-4); margin-left: auto; max-width: 320px; }
.doc__note { font-size: var(--fs-caption); color: var(--label-secondary); margin-top: var(--sp-4); line-height: 1.5; }
.doc__foot { display: flex; justify-content: space-between; margin-top: var(--sp-8); padding-top: var(--sp-6); font-size: var(--fs-footnote); color: var(--label-secondary); border-top: 0.5px solid var(--separator); }
.doc__actions { display: flex; gap: var(--sp-3); margin-top: var(--sp-5); }

/* ---------- Toasts ------------------------------------------------------
 *
 * For the one-shot flash that crosses a redirect ("Rough lot added."). It is
 * transient and not tied to a place on the page, so it floats.
 *
 * .alert is the OTHER thing and stays: an inline, contextual, persistent
 * message that belongs to a spot in the document ("No open lots — add one
 * first", "the books do not balance"). Those must not float away on a timer.
 *
 * Phone: bottom, clear of the tab bar. Desktop: top right, under the topbar.
 */

.toasts {
  position: fixed;
  z-index: 60;
  left: var(--sp-4);
  right: var(--sp-4);
  bottom: calc(var(--tabbar-h) + var(--safe-b) + var(--sp-3));
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  align-items: center;
  pointer-events: none;          /* the strip never blocks the page... */
}

.toast {
  pointer-events: auto;          /* ...but each toast is still clickable */
  position: relative;
  width: 100%;
  max-width: 400px;
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--sp-3);
  padding: 11px var(--sp-3) 11px var(--sp-4);
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-left: 3px solid var(--label-tertiary);
  border-radius: var(--r-card);
  box-shadow: 0 8px 28px rgba(16, 24, 40, 0.16), 0 2px 6px rgba(16, 24, 40, 0.08);
  overflow: hidden;
  animation: toast-in 0.22s cubic-bezier(0.21, 1.02, 0.73, 1) both;
}

.toast__icon { display: flex; }
.toast__icon .icon { width: 19px; height: 19px; }
.toast__msg { margin: 0; font-size: var(--fs-subhead); line-height: 1.35; color: var(--label); }

.toast__close {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px; height: 28px;
  padding: 0;
  border: 0;
  border-radius: var(--r-chip);
  background: transparent;
  color: var(--label-secondary);
  cursor: pointer;
}
.toast__close:hover { background: var(--fill); color: var(--label); }
.toast__close .icon { width: 15px; height: 15px; }

/* Time remaining, so a toast that is about to vanish says so. */
.toast__bar {
  position: absolute;
  left: 0; bottom: 0;
  height: 2px;
  width: 100%;
  transform-origin: left center;
  background: currentColor;
  opacity: 0.35;
}
.toast.is-running .toast__bar { animation: toast-bar linear forwards; }
.toast.is-paused  .toast__bar { animation-play-state: paused; }

.toast--ok    { border-left-color: var(--green);  }
.toast--ok    .toast__icon { color: var(--green);  }
.toast--ok    .toast__bar  { color: var(--green);  }
.toast--error { border-left-color: var(--red);    }
.toast--error .toast__icon { color: var(--red);    }
.toast--warn  { border-left-color: var(--orange); }
.toast--warn  .toast__icon { color: var(--orange); }
.toast--warn  .toast__bar  { color: var(--orange); }
.toast--info  { border-left-color: var(--blue);   }
.toast--info  .toast__icon { color: var(--blue);   }
.toast--info  .toast__bar  { color: var(--blue);   }

/* An inline action ("Reload"), for a toast that asks for something. */
.toast__action {
  flex: none;
  padding: 5px 11px;
  border: 1px solid var(--blue);
  border-radius: var(--r-chip);
  background: transparent;
  color: var(--blue);
  font-family: inherit;
  font-size: var(--fs-footnote);
  font-weight: 600;
  cursor: pointer;
}
.toast__action:hover { background: var(--blue); color: var(--label-on-color); }

.toast.is-leaving { animation: toast-out 0.18s ease forwards; }

@keyframes toast-in  { from { opacity: 0; transform: translateY(10px) scale(0.98); } }
@keyframes toast-out { to   { opacity: 0; transform: translateY(6px)  scale(0.98); } }
@keyframes toast-bar { from { transform: scaleX(1); } to { transform: scaleX(0); } }

/* Motion is decoration here; the message is the point. */
@media (prefers-reduced-motion: reduce) {
  .toast, .toast.is-leaving { animation: none; }
  .toast.is-running .toast__bar { animation: none; }
}

/* ---------- Accessibility floor -----------------------------------------
 *
 * Three rules that are cheap here and expensive to retrofit.
 */

/* Skip link. Off-screen until focused, then a real, visible target. Not
   display:none — that would take it out of the tab order, which is the one
   thing it exists to be in. */
.skip {
  position: absolute;
  left: var(--sp-3);
  top: -100px;
  z-index: 100;
  padding: 10px var(--sp-4);
  border-radius: 0 0 var(--r-input) var(--r-input);
  background: var(--blue);
  color: var(--label-on-color);      /* safe: saturated blue */
  font-size: var(--fs-footnote);
  font-weight: 600;
  transition: top 0.12s ease;
}
.skip:focus { top: 0; }

/* One visible focus ring for every interactive thing the app styles itself.
   :focus-visible, not :focus, so a mouse click does not light it up. */
.btn:focus-visible,
.sidebar__item:focus-visible,
.tabbar__item:focus-visible,
.topbar__chip:focus-visible,
.topbar__icon-btn:focus-visible,
.topbar__user:focus-visible,
.list__row--link:focus-visible,
.crumbs__item:focus-visible,
.actionbar__quiet:focus-visible,
.toast__close:focus-visible,
.sidebar__signout:focus-visible,
.sidebar__toggle:focus-visible,
.appbar__btn:focus-visible,
.sidebar__close:focus-visible {
  outline: 2px solid var(--blue);
  outline-offset: 2px;
  border-radius: var(--r-chip);
}

/* Windows High Contrast paints no box-shadows, so the ring-only focus styles
   on inputs vanish entirely there. Restore a real outline for those users —
   this is the one place `outline: none` genuinely costs someone the ability
   to use the app. */
@media (forced-colors: active) {
  .field__input:focus,
  .search__input:focus,
  .scan__input:focus {
    outline: 2px solid Highlight;
    outline-offset: 1px;
  }
  .sidebar__item.is-active { border: 1px solid Highlight; }
  .badge, .chip, .pill { border: 1px solid currentColor; }
}

/* ---------- Running total ------------------------------------------------
   What a form is about to commit to, shown while it is being typed. Quiet
   until there is something to say (the element ships hidden), then plain and
   large — this is the number the operator is checking against the bill in
   their other hand. */
.running {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--sp-2) var(--sp-3);
  margin-top: var(--sp-2);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-card);
  background: var(--blue-soft);
}
.running[hidden] { display: none; }
.running__k { font-size: var(--fs-footnote); font-weight: 600; color: var(--blue); }
.running__v {
  font-size: var(--fs-title);
  font-weight: 700;
  color: var(--blue);
  font-variant-numeric: tabular-nums;
  margin-left: auto;
}
.running__note { flex-basis: 100%; font-size: var(--fs-caption); color: var(--label-secondary); font-variant-numeric: tabular-nums; }

/* ---------- Action bar ---------------------------------------------------
   Actions that do the same KIND of thing sit on one row rather than stacking
   as full-width slabs. Three stacked block buttons read as three unrelated
   banners; one row reads as a set of choices, and the eye takes it in at
   once. Wraps rather than scrolls, so a phone stacks them two-up instead of
   pushing anything off-screen. */
.actionbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-4);
}
.actionbar form { display: contents; }
.actionbar .btn { flex: 0 1 auto; }
.actionbar .btn .icon { width: 16px; height: 16px; }

/* A consequential-but-rare action. Present, findable, and not competing with
   the document it acts on. */
.actionbar__quiet {
  margin-left: auto;
  padding: 6px 4px;
  font-size: var(--fs-footnote);
  color: var(--label-secondary);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--separator-opaque);
}
.actionbar__quiet:hover { color: var(--blue); text-decoration-color: currentColor; }
@media (max-width: 559px) { .actionbar__quiet { margin-left: 0; width: 100%; } }

/* The one figure a screen exists to answer. Louder than a total, without
   inventing a new component. */
.kv--flag { background: var(--orange-soft); margin: var(--sp-2) calc(var(--sp-4) * -1) calc(var(--sp-4) * -1); padding: var(--sp-3) var(--sp-4); border-radius: 0 0 var(--r-card) var(--r-card); border-top: 0; }
.kv--flag .kv__k { font-weight: 600; color: var(--orange); }
.kv--flag .kv__v { font-size: var(--fs-headline); font-weight: 700; color: var(--orange); }

/* ---------- Scan ---------------------------------------------------------
   A big target: this is used standing at a bench, often one-handed, and the
   field has to be obviously the thing to point the reader at. */
.scan { position: relative; display: flex; gap: var(--sp-3); align-items: center; }
.scan__icon {
  position: absolute; left: 14px; top: 50%; transform: translateY(-50%);
  width: 20px; height: 20px; color: var(--label-secondary); pointer-events: none;
}
.scan__input {
  flex: 1; min-width: 0;
  min-height: 52px;
  padding: 0 var(--sp-4) 0 44px;
  font-family: var(--font);
  font-size: 18px;
  letter-spacing: .04em;
  color: var(--label);
  background: var(--field-bg);
  border: 2px solid var(--field-border);
  border-radius: var(--r-input);
  appearance: none;
}
.scan__input:focus { outline: none; border-color: var(--blue); box-shadow: 0 0 0 4px var(--blue-soft); }
.scan .btn { min-height: 52px; padding-inline: var(--sp-5); }

/* ---------- Numbered steps ----------------------------------------------- */
/* Numbers here are honest: importing really is a sequence, because stock and
   balances both refer to parties that must exist first. */
.steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--sp-3); }
.steps__item { display: flex; gap: var(--sp-3); align-items: flex-start; }
.steps__n {
  flex: none;
  width: 24px; height: 24px;
  border-radius: 50%;
  display: grid; place-items: center;
  background: var(--blue-soft); color: var(--blue);
  font-size: var(--fs-caption); font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.steps__body { font-size: var(--fs-subhead); color: var(--label-secondary); line-height: 1.5; }
.steps__body b { color: var(--label); font-weight: 650; }

/* ---------- Column reference (collapsed by default) ---------------------- */
.cols { margin: var(--sp-3) 0 var(--sp-4); border: 1px solid var(--border); border-radius: var(--r-card); }
.cols__toggle {
  padding: var(--sp-3) var(--sp-4);
  font-size: var(--fs-footnote); font-weight: 600;
  cursor: pointer; color: var(--label-secondary);
}
.cols__toggle:hover { color: var(--label); }
.cols__list { margin: 0; padding: 0 var(--sp-4) var(--sp-4); }
.cols__list dt { margin-top: var(--sp-3); }
.cols__list dt code { font-size: var(--fs-caption); }
.cols__list dd { margin: 3px 0 0; font-size: var(--fs-footnote); color: var(--label-secondary); line-height: 1.5; }

.plain { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--sp-3); }
.plain li { font-size: var(--fs-subhead); color: var(--label-secondary); line-height: 1.5; }
.plain li b { color: var(--label); font-weight: 650; }

/* ---------- Mail previews ------------------------------------------------ */

.mailkinds {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: var(--sp-3);
  margin-bottom: var(--sp-4);
}

.mailkind {
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  overflow: hidden;
  background: var(--bg-system);
}
.mailkind__head { display: flex; align-items: center; gap: var(--sp-2); padding: var(--sp-3); background: var(--bg-secondary); }
.mailkind__name { font-size: var(--fs-footnote); font-weight: 600; }

/* Scaled down so a 600px email fits a card without a scrollbar. The frame is
   the real message at real width, shrunk — not a re-render at card width,
   which would show a layout the buyer never sees. */
.mailkind__frame {
  display: block;
  width: 600px;
  height: 620px;
  border: 0;
  border-top: 1px solid var(--border);
  transform: scale(0.42);
  transform-origin: top left;
  /* Reserve only the scaled footprint, or the card keeps the full 600px. */
  margin-bottom: calc(620px * -0.58);
  margin-right: calc(600px * -0.58);
  pointer-events: none;
  background: #fff;
}

.mailkind__actions {
  display: flex; gap: var(--sp-2); flex-wrap: wrap;
  padding: var(--sp-3);
  border-top: 1px solid var(--border);
  background: var(--bg-secondary);
}

/* ---------- Offline banner ---------------------------------------------- */

.offline-banner {
  position: fixed;
  left: var(--sp-4); right: var(--sp-4);
  max-width: 420px;
  margin-inline: auto;
  bottom: calc(var(--tabbar-h) + var(--safe-b) + var(--sp-2));
  z-index: 40;
  background: var(--orange);
  color: var(--label-on-color);
  padding: 10px var(--sp-4);
  border-radius: var(--r-input);
  font-size: var(--fs-footnote);
  font-weight: 500;
  text-align: center;
  border: 0;
  cursor: pointer;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
}

.offline-banner[hidden] { display: none; }

/* ---------- Tablet ------------------------------------------------------ */

@media (min-width: 700px) {
  .kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); overflow: visible; }
  .kpi { min-width: 0; }
  .field--inline { gap: var(--sp-4); }
}

/* ======================================================================
 * DESKTOP — the application chrome (design.md 7)
 *
 * The phone keeps its iOS identity; a 1440px screen gets a dark grouped
 * sidebar, a search top bar and dense multi-column content. Same
 * components, re-laid-out — not a phone screen stretched wide.
 * ====================================================================== */

@media (min-width: 1024px) {
  :root { --sidebar-w: 244px; --topbar-h: 64px; }

  .app { display: grid; grid-template-columns: var(--sidebar-w) 1fr; min-height: 100dvh; }
  .app--bare { display: block; }
  .tabbar { display: none; }

  /* ---- Sidebar ----
   * Its CONTENTS are styled once, near the drawer rules, because the phone
   * renders the same markup. Only the placement changes here: a static rail
   * instead of an off-canvas panel. */
  .sidebar {
    position: sticky;
    top: 0;
    left: auto;
    bottom: auto;
    z-index: auto;
    width: auto;
    height: 100dvh;
    padding: var(--sp-4) var(--sp-3);
    transform: none;
    visibility: visible;
    transition: none;
  }

  /* No drawer, so nothing to close or to dim — but the collapse control is
     a desktop affordance and appears here. */
  .sidebar__close, .scrim, .appbar { display: none; }
  .sidebar__toggle { display: grid; }

  /* ---- Collapsed: icons only ----
     A wide table wants the width back. Labels are hidden rather than
     removed, so the markup, the tab order and the title tooltips are
     unchanged — and the choice is remembered per browser. */
  .app.is-nav-collapsed { grid-template-columns: 68px 1fr; }
  .app.is-nav-collapsed .sidebar { padding-inline: 10px; }
  .app.is-nav-collapsed .sidebar__label,
  .app.is-nav-collapsed .sidebar__brand-text,
  .app.is-nav-collapsed .sidebar__badge,
  .app.is-nav-collapsed .sidebar__more,
  .app.is-nav-collapsed .sidebar__product-text,
  .app.is-nav-collapsed .sidebar__signout span { display: none; }
  .app.is-nav-collapsed .sidebar__head { flex-direction: column; gap: var(--sp-2); }
  .app.is-nav-collapsed .sidebar__brand { padding: 0; justify-content: center; }
  .app.is-nav-collapsed .sidebar__item { justify-content: center; padding-inline: 0; }
  .app.is-nav-collapsed .sidebar__product { justify-content: center; padding: var(--sp-2); }
  /* The label is the whole point of a group heading, so a collapsed rail
     keeps only the rule as the separator. */
  .app.is-nav-collapsed .sidebar__group { font-size: 0; padding-inline: 0; gap: 0; }

  /* ---- Top bar ---- */
  .main { display: flex; flex-direction: column; min-height: 100dvh; }

  .topbar {
    display: flex;
    align-items: center;
    gap: var(--sp-4);
    height: var(--topbar-h);
    padding: 0 var(--sp-6);
    background: var(--bg-secondary);
    border-bottom: 0.5px solid var(--separator);
    position: sticky;
    top: 0;
    z-index: 20;
  }

  .search { position: relative; flex: 1; max-width: 460px; }
  .search__icon { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); width: 18px; height: 18px; color: var(--label-secondary); pointer-events: none; }

  .search__input {
    width: 100%;
    min-height: 40px;
    padding: 0 var(--sp-4) 0 38px;
    font-size: var(--fs-subhead);
    font-family: inherit;
    border: 0.5px solid var(--separator);
    border-radius: 10px;
    background: var(--bg-system);
    appearance: none;
  }

  .search__input:focus { outline: none; border-color: var(--blue); box-shadow: 0 0 0 3px var(--blue-soft); background: var(--bg-secondary); }

  .topbar__actions { display: flex; align-items: center; gap: var(--sp-3); margin-left: auto; }

  .topbar__chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: 36px;
    padding: 0 var(--sp-3);
    border-radius: 9px;
    background: var(--blue-soft);
    color: var(--blue);
    font-size: var(--fs-footnote);
    font-weight: 600;
  }

  .topbar__chip .icon { width: 17px; height: 17px; }

  .search__kbd {
    position: absolute;
    right: 10px; top: 50%;
    transform: translateY(-50%);
    padding: 2px 6px;
    border: 1px solid var(--border);
    border-radius: 5px;
    background: var(--bg-secondary);
    color: var(--label-secondary);
    font-family: inherit;
    font-size: 10px;
    font-weight: 600;
    pointer-events: none;
  }
  .search__input:focus ~ .search__kbd { opacity: 0; }

  .topbar__icon-btn {
    position: relative;
    width: 36px; height: 36px;
    display: grid; place-items: center;
    border-radius: 9px;
    color: var(--label-secondary);
  }
  .topbar__icon-btn:hover { background: var(--fill); color: var(--label); }
  .topbar__icon-btn .icon { width: 19px; height: 19px; }

  .topbar__dot {
    position: absolute;
    top: 7px; right: 8px;
    width: 7px; height: 7px;
    border-radius: 50%;
    background: var(--blue);
    box-shadow: 0 0 0 2px var(--bg-secondary);
  }


  .topbar__user { display: flex; align-items: center; gap: var(--sp-2); color: var(--label); padding: 4px 6px 4px 4px; border-radius: 10px; }
  .topbar__user:hover { background: var(--fill); }
  .topbar__caret { width: 14px; height: 14px; color: var(--label-secondary); transform: rotate(90deg); }

  .avatar {
    width: 34px; height: 34px;
    border-radius: 50%;
    background: var(--blue);
    color: var(--label-on-color);   /* safe: saturated blue disc */
    display: grid;
    place-items: center;
    font-size: var(--fs-footnote);
    font-weight: 700;
    flex: none;
  }

  .topbar__who { display: flex; flex-direction: column; line-height: 1.25; }
  .topbar__name { font-size: var(--fs-footnote); font-weight: 600; }
  .topbar__role { font-size: var(--fs-caption); color: var(--label-secondary); }

  /* A thin spectrum strip under the chrome — the one piece of pure
     decoration, and the thing that stops the page reading as a blank sheet. */
  .accent {
    display: block;
    height: 3px;
    background: linear-gradient(90deg,
      var(--blue) 0%, var(--blue) 22%,
      var(--red) 22%, var(--red) 40%,
      var(--orange) 40%, var(--orange) 62%,
      var(--green) 62%, var(--green) 82%,
      var(--purple) 82%, var(--purple) 100%);
  }

  /* ---- Page head + content ---- */
  .crumbs { display: flex; align-items: center; gap: 4px; padding: var(--sp-4) var(--sp-6) 0; }
  .crumbs__item { font-size: var(--fs-footnote); color: var(--label-secondary); }
  a.crumbs__item:hover { color: var(--blue); }
  .crumbs__item.is-current { color: var(--label); font-weight: 600; }
  .crumbs__sep { width: 13px; height: 13px; color: var(--label-tertiary); flex: none; }

  .pagehead { display: flex; align-items: center; gap: var(--sp-4); padding: var(--sp-3) var(--sp-6) 0; }
  .pagehead__body { flex: 1; min-width: 0; }
  .pagehead__title { font-size: 28px; letter-spacing: -0.4px; }
  .pagehead__sub { font-size: var(--fs-footnote); }

  /* An icon tile beside the title. Cheap, and it stops every screen opening
     with an identical wall of text. */
  .pagehead__mark {
    width: 48px; height: 48px;
    flex: none;
    border-radius: 12px;
    display: grid; place-items: center;
    background: var(--blue-soft);
    color: var(--blue);
  }
  .pagehead__mark .icon { width: 23px; height: 23px; }

  .pagehead__actions { display: flex; align-items: center; gap: var(--sp-2); flex: none; }
  .pagehead__actions .btn { min-height: 38px; padding-inline: var(--sp-4); }
  .pagehead__actions .btn .icon { width: 17px; height: 17px; }

  /* The page header carries the primary action on desktop, so the phone's
     floating button would be a duplicate. */
  .pagehead__actions ~ .fab, .pagehead:has(.pagehead__actions) ~ .content .fab { display: none; }

  .content {
    max-width: none;
    margin: 0;
    padding: var(--sp-4) var(--sp-6) var(--sp-8);
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    gap: var(--sp-4);
    align-content: start;
    flex: 1;
  }

  .content > * { grid-column: span 12; margin-bottom: 0; }
  .content > .card, .content > .group { grid-column: span 6; align-self: start; }
  .content > .card--wide, .content > .card--full { grid-column: span 12; }
  .content > .card--third { grid-column: span 4; }
  .content > .card--twothirds { grid-column: span 8; }
  .content > form, .content > .empty, .content > .alert,
  .content > .segmented, .content > .kpis, .content > .doc,
  .content > .toolbar, .content > .footnote, .content > .list { grid-column: span 12; }

  /* An action bar belongs to the card above it, so it takes the same column.
     Spanning all twelve stranded its right-aligned link on the far side of
     the page, detached from the buttons it belongs with. */
  .content > .actionbar { grid-column: span 6; }

  form .card { display: grid; grid-template-columns: 1fr 1fr; gap: 0 var(--sp-4); }
  form .card > .card__title, form .card > .field--inline, form .card > .switch,
  form .card > .field__hint, form .card > .scroll-x, form .card > p,
  form .card > .list, form .card > .card__sub { grid-column: 1 / -1; }

  .savebar { bottom: 0; justify-content: flex-end; padding: var(--sp-4) 0 0; }
  .savebar .btn { flex: 0 0 auto; min-width: 160px; }

  /* The FAB grows a label from its aria-label — a bare circular glyph is a
     phone affordance, and the two can never drift apart this way. */
  .fab { width: auto; height: auto; min-height: 46px; padding: 0 var(--sp-5); border-radius: var(--r-input); gap: var(--sp-2); grid-auto-flow: column; bottom: var(--sp-6); right: var(--sp-6); }
  .fab::after { content: attr(aria-label); font-size: var(--fs-callout); font-weight: 600; }

  .toolbar__search { max-width: 360px; }
  .offline-banner { left: auto; right: var(--sp-6); bottom: var(--sp-6); }
  .list { box-shadow: var(--shadow-card); }

  /* Desktop: toasts drop from the top right, where the eye already is after
     an action in the page header — and there is no tab bar to clear. */
  .toasts {
    left: auto;
    right: var(--sp-6);
    top: calc(var(--navbar-h) + var(--sp-4));
    bottom: auto;
    align-items: flex-end;
    width: min(400px, calc(100vw - var(--sp-8)));
  }
  .toast { animation-name: toast-in-desktop; }
  @keyframes toast-in-desktop { from { opacity: 0; transform: translateX(16px) scale(0.98); } }
}

@media (min-width: 1500px) {
  .content, .pagehead, .topbar, .crumbs { padding-inline: var(--sp-8); }
}

/* ---------- E-invoicing -------------------------------------------------- */

/* A caution that is neither an error nor a confirmation: sandbox mode, or a
   feature switched off. Orange, because "nothing is being filed" needs to be
   noticed without reading as a failure that already happened. */
.alert--warn { background: var(--orange-soft); color: #8A4B00; }
.alert__list { margin: var(--sp-2) 0 0; padding-left: var(--sp-5); }
.alert__list li + li { margin-top: var(--sp-1); }

.badge--flag { background: var(--red-soft); color: var(--red); }
.stat__mark--red { background: var(--red-soft); color: var(--red); }

/* The QR sits on white regardless of theme: a scanner reads contrast, and a
   dark-mode inversion is the classic way to ship a code nothing can read. */
.qr-wrap {
  display: flex;
  justify-content: center;
  padding: var(--sp-4);
  background: #fff;
  border-radius: var(--r-card);
  border: 1px solid var(--border);
}
.qr-wrap .qr { max-width: 100%; height: auto; }

/* Raw portal JSON. Long, and never worth reflowing the page for. */
.pre-scroll {
  overflow-x: auto;
  max-height: 320px;
  overflow-y: auto;
  background: var(--fill);
  border-radius: var(--r-input);
  padding: var(--sp-3);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: var(--fs-caption);
  line-height: 1.5;
  white-space: pre;
  margin: 0 0 var(--sp-3);
}

/* A 64-character IRN has no spaces to break at. */
.breakable { overflow-wrap: anywhere; word-break: break-all; }

details.card > summary {
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-subhead);
}
details.card[open] > summary { margin-bottom: var(--sp-3); }

/* The IRN block on a printed invoice: the QR left, the numbers beside it. */
.doc__irn {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-4);
  margin-top: var(--sp-5);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--separator);
}
.doc__irn .qr { flex: 0 0 auto; }
.doc__irn-meta { min-width: 0; font-size: var(--fs-caption); line-height: 1.6; }
.doc__irn-meta strong { display: block; }
.doc__irn-meta code { overflow-wrap: anywhere; word-break: break-all; }

/* A wide table only scrolls if the reader knows it can. Windows and macOS
   both hide the bar until something moves, so a table cut off at the right
   edge looks broken rather than scrollable — give it a permanent one. */
.scroll-x {
  scrollbar-width: thin;
  scrollbar-color: var(--fill-strong) transparent;
}
.scroll-x::-webkit-scrollbar { height: 10px; }
.scroll-x::-webkit-scrollbar-track {
  background: var(--fill);
  border-radius: var(--r-pill);
}
.scroll-x::-webkit-scrollbar-thumb {
  background: var(--fill-strong);
  border-radius: var(--r-pill);
}
.scroll-x::-webkit-scrollbar-thumb:hover { background: var(--label-tertiary); }

/* ---------- Print ------------------------------------------------------- */

@media print {
  .sidebar, .topbar, .accent, .tabbar, .segmented, .offline-banner,
  .btn, .fab, .savebar, .toolbar, .doc__actions { display: none !important; }
  body { background: #fff; color: #000; }
  .app { display: block; }
  .content { padding: 0; max-width: none; display: block; }
  .app--bare .content { display: block; min-height: 0; }
  .card, .list { box-shadow: none; border: 1px solid #000; break-inside: avoid; margin-bottom: 12px; }
  .doc { box-shadow: none; border: 0; padding: 0; max-width: none; }
  .doc__foot { margin-top: 48px; }
  .table th, .table td { border-bottom: 1px solid #ddd; }
  .scroll-x { overflow: visible; }
  a[href]::after { content: ""; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; }
}

/* ---- Worker-facing documents in Gujarati and Hindi -------------------------
   Devanagari and Gujarati carry marks above and below the base line, so the
   Latin leading that suits an invoice crops them. These documents are read on
   a factory floor, often photographed, and a clipped matra changes a word — so
   the whole document opens up rather than only the headings.

   The font stack lists the faces Windows, Android and iOS actually ship, then
   falls back to the browser's own Indic default. No webfont: these pages are
   printed on a shared-hosting install with no CDN reachable through the CSP,
   and a font that fails to load would silently render as boxes on the one
   document a worker has to be able to read. */
.doc--indic {
  line-height: 1.9;
  font-family: "Nirmala UI", "Noto Sans Gujarati", "Noto Sans Devanagari",
               "Shruti", "Mangal", "Kohinoor Gujarati", "Kohinoor Devanagari",
               system-ui, sans-serif;
}
.doc--indic .doc__kind { line-height: 1.5; }
.doc--indic .table th,
.doc--indic .table td { padding-top: 8px; padding-bottom: 8px; }
/* Codes, weights and money stay Latin and tabular even on an Indic page —
   they are the columns being compared down, and they are the same characters
   the screen showed. */
.doc--indic .mono,
.doc--indic .num { font-family: var(--font-mono, ui-monospace, monospace); font-variant-numeric: tabular-nums; }

/* ---------- Size matrix -------------------------------------------------- */

/* The style x colour x size grid (design.md 7). It appears on the order, on
   cutting, on packing and on the invoice, so it is one component rather than
   four hand-rolled tables that can disagree about their totals.

   The grid scrolls inside ITSELF. A fourteen-size range is wider than a phone
   and the page body must never scroll sideways -- that breaks the tab bar and
   the safe-area padding along with it. */
.matrix__scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  margin: 0 calc(var(--sp-4) * -1);
  padding: 0 var(--sp-4);
}

.matrix { min-width: 100%; white-space: nowrap; }

/* The colour name stays put while the sizes scroll under it. Without this you
   scroll to size XXL and no longer know which colour row you are reading. */
.matrix__colour,
.matrix__corner {
  position: sticky;
  left: 0;
  z-index: 1;
  background: var(--bg-secondary);
  text-align: left;
  font-weight: 600;
}

.matrix__size,
.matrix__cell { text-align: right; font-variant-numeric: tabular-nums; }

.matrix__total { font-weight: 600; }

.matrix tfoot .matrix__cell,
.matrix tfoot .matrix__colour {
  border-top: 1px solid var(--separator-opaque);
  background: var(--bg-grouped);
}

.matrix__grand { font-size: var(--fs-headline); }

/* ---------- Colour split ------------------------------------------------- */

/* Revealed by the style picker on the new-order form. Hidden blocks are
   [hidden]; the noscript rule in the template shows them all again, because
   failing open is better than a form whose fields cannot be reached. */
.colour-split { display: grid; gap: var(--sp-2); }

/* ---------- Invoice document -------------------------------------------- */

.doc__parties {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-5);
  margin: var(--sp-5) 0;
}

.doc__stamp { text-align: right; }

.doc__label {
  font-size: var(--fs-caption);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--label-secondary);
  margin: 0 0 var(--sp-1);
}

.doc__table { width: 100%; margin: var(--sp-4) 0; }
.doc__table td:last-child,
.doc__table th:last-child { text-align: right; font-variant-numeric: tabular-nums; }

.doc__words {
  margin-top: var(--sp-2);
  font-size: var(--fs-footnote);
  color: var(--label-secondary);
}

.doc__sign { margin-top: var(--sp-8); }

/* A draft carries a plain, readable warning rather than a rotated watermark.
   The point is that nobody mistakes it for a tax invoice, and diagonal grey
   text across the page is easier to miss than a line that says so. */
.doc__watermark {
  border: 1px solid var(--red);
  color: var(--red);
  border-radius: var(--r-chip);
  padding: var(--sp-2) var(--sp-3);
  margin-bottom: var(--sp-4);
  font-weight: 600;
  text-align: center;
}

@media print {
  .doc__noprint { display: none !important; }
}

@media (max-width: 560px) {
  .doc__parties { grid-template-columns: 1fr; }
  .doc__stamp { text-align: left; }
}