/* ui-audit g1: metric-matched fallbacks. Until the web fonts arrive
   (display=swap) text draws in a local face scaled to the same width, so the
   swap does not reflow lines. Ratios measured in Chromium against the loaded
   fonts: Figtree ~99.7% of Arial's advance width, ascent 0.95 / descent
   0.25; Cormorant Garamond ~87.7% of Georgia's width. */
@font-face {
  font-family: "Figtree Fallback";
  src: local("Arial"), local("ArialMT"), local("Liberation Sans");
  size-adjust: 99.7%;
  ascent-override: 95%;
  descent-override: 25%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Cormorant Fallback";
  src: local("Georgia"), local("Times New Roman");
  size-adjust: 87.7%;
}
:root {
  --brand-charcoal: #282321;
  --brand-copper: #c97945;
  --brand-copper-dark: #92512f;
  --brand-navy: #001b67;
  --brand-cream: #f7f1e8;
  --brand-paper: #fbfaf7;
  --brand-line: #e6ded3;
  --brand-success-bg: #eef4f7;
  --brand-success-text: #31576c;

  /* ui-audit g1: primitive tier. Raw values only -- the exact hex codes the
     older pages already used, now named once so a rule reaches for a token
     instead of a literal. Tiers: primitives (here) -> semantic roles (the
     --ink / --surface / --color-* names below) -> component tokens (the
     last group). Rules should prefer the semantic names; primitives exist so
     the semantic layer has something to point at. */
  --white: #ffffff;
  --stone-50: #fafaf9;
  --stone-100: #f5f5f4;
  --stone-200: #e7e5e4;
  --stone-300: #d6d3d1;
  --stone-400: #a8a29e;
  --stone-500: #78716c;
  --stone-600: #57534e;
  --stone-700: #44403c;
  --stone-800: #292524;
  --stone-900: #1c1917;
  --cream-50: #fffdf9;
  --copper-50: #fff3e8;
  --forest-700: #315f4c;
  --green-700: #15803d;
  --red-50: #fef2f2;
  --red-100: #fee2e2;
  --red-200: #fecaca;
  --red-700: #b91c1c;
  --red-800: #991b1b;
  --rose-50: #fff1f2;
  --amber-50: #fffbeb;
  --amber-100: #fef3c7;
  --amber-200: #fde68a;
  --amber-600: #d97706;
  --amber-700: #b45309;
  --amber-800: #92400e;

  /* Design tokens (2026-09 reporting redesign). Semantic names sit on top of
     the brand palette above so a page never reaches for a hex value: ink for
     text, surface for cards, line for hairlines, accent for the one colour a
     chart is allowed, good/warn/bad only for meaning. analytics.css (Dashboard,
     Reports, Shift close) consumes these; older pages keep their classes until
     they are redesigned. */
  --ink: var(--brand-charcoal);
  --ink-soft: #4a423d;
  --ink-muted: #6f665f; /* ui-audit g1: was #7d746c, 4.39:1 on paper -> 5.38:1 */
  --ink-faint: #a89e95;
  --surface: #ffffff;
  --surface-2: #f6f1ea;
  --surface-3: #efe8de;
  --line: var(--brand-line);
  --line-soft: #f0eae1;
  --accent: var(--brand-copper);
  --accent-ink: var(--brand-copper-dark);
  --accent-soft: #faf0e8;
  --good: #2f7562;
  --good-soft: #e8f2ee;
  --warn: #b0761c;
  --warn-soft: #fbf3e2;
  --warn-ink: #8a5a12; /* ui-audit g1: --warn as text was 3.85:1; this is 5.9:1 (dots and bars keep --warn) */
  --bad: #b23f37;
  --bad-soft: #fbe9e7;

  /* ui-audit g1: semantic colour roles for the older (pre-redesign) pages.
     A rule names the job a colour does -- text-muted, border, surface,
     danger -- never the hue, so the palette can be retuned in one place.
     Each role is the exact value those pages already used. */
  --color-background: var(--brand-paper);
  --color-surface: var(--white);
  --color-surface-muted: var(--stone-50);
  --color-surface-sunken: var(--stone-100);
  --color-surface-warm: var(--cream-50);
  --color-text-primary: var(--stone-800);
  --color-text-secondary: var(--stone-600);
  /* ui-audit g1 contrast (WCAG AA, 4.5:1 for body-size text): muted was
     stone-500 (#78716c), 3.8-4.4:1 on the tinted surfaces it sits on
     (stone-100, copper-50, amber/red/green soft fills); now 4.85:1 or better
     on every surface in this palette. subtle was stone-400 (#a8a29e) at
     2.0-2.5:1 everywhere; it moves up to stone-500 (4.6-4.8:1 on the white,
     paper and cream cards it is used on). stone-400 survives only as the
     disabled tier, which WCAG exempts and which should look unavailable. */
  --color-text-muted: #68615b;
  --color-text-subtle: var(--stone-500);
  --color-text-disabled: var(--stone-400);
  --color-text-inverse: var(--white);
  --color-border: var(--stone-200);
  --color-border-strong: var(--stone-300);
  --color-accent: var(--brand-copper);
  --color-accent-strong: var(--brand-copper-dark);
  --color-accent-soft: var(--copper-50);
  --color-accent-hover: #6f3c26;
  --color-accent-pressed: #5c3120;
  --color-border-warm: #ead9ca;
  --color-success: var(--forest-700);
  --color-warning: var(--amber-800);
  --color-warning-soft: var(--amber-50);
  --color-danger: var(--red-700);
  --color-danger-strong: var(--red-800);
  --series-1: var(--brand-charcoal);
  --series-2: var(--brand-copper);
  --series-3: #7c8b6f;
  --series-4: #4e6b8a;
  --series-5: #b58a5a;
  --series-6: #a09890;
  /* Radius scale. xs for controls (buttons, inputs), sm for cards and
     panels, md/lg for large sheets, full for pills and round badges. A
     control nested in a card takes the next step down so the corners stay
     concentric. Written in rem, identical to the old px at 16px. */
  --radius-none: 0;
  --radius-xs: 0.375rem; /* 6px */
  --radius-sm: 0.5rem; /* 8px */
  --radius-md: 0.75rem; /* 12px */
  --radius-lg: 1rem; /* 16px */
  --radius-full: 999px;
  /* ui-audit g1: elevation. Each tier pairs a tight contact shadow with a
     softer diffuse one, tinted with the charcoal ink rather than pure black
     so it sits naturally on the warm paper background.
       1 resting  -- cards, panels, stat tiles
       2 raised   -- hovered cards, sticky toolbars
       3 overlay  -- dropdown menus, popovers, the skip link
       4 modal    -- dialogs and centred modals
     The -up / -side variants are the same tiers cast upward (bottom bars,
     bottom sheets) or sideways (the right-hand drawer). */
  --elevation-1: 0 1px 2px rgb(40 35 33 / 0.05), 0 1px 3px rgb(40 35 33 / 0.03);
  --elevation-2: 0 1px 2px rgb(40 35 33 / 0.05), 0 4px 12px rgb(40 35 33 / 0.07);
  --elevation-3: 0 2px 6px rgb(40 35 33 / 0.06), 0 10px 30px rgb(40 35 33 / 0.1);
  --elevation-4: 0 4px 12px rgb(40 35 33 / 0.08), 0 24px 60px rgb(40 35 33 / 0.22);
  --elevation-2-up: 0 -1px 2px rgb(40 35 33 / 0.04), 0 -6px 16px rgb(40 35 33 / 0.08);
  --elevation-4-up: 0 -2px 8px rgb(40 35 33 / 0.06), 0 -12px 32px rgb(40 35 33 / 0.18);
  --elevation-4-side: -2px 0 8px rgb(40 35 33 / 0.06), -12px 0 32px rgb(40 35 33 / 0.18);
  --shadow-1: var(--elevation-1);
  --shadow-2: var(--elevation-3);
  /* Spacing scale on a 4px base. Written in rem (identical to the old px
     values at the browser's default 16px) so spacing grows with the text
     when someone raises their default font size. */
  --space-1: 0.25rem; /* 4px */
  --space-2: 0.5rem; /* 8px */
  --space-3: 0.75rem; /* 12px */
  --space-4: 1rem; /* 16px */
  --space-5: 1.25rem; /* 20px */
  --space-6: 1.5rem; /* 24px */
  --space-7: 1.75rem; /* 28px */
  --space-8: 2rem; /* 32px */
  --space-10: 2.5rem; /* 40px */
  --space-12: 3rem; /* 48px */
  /* ui-audit g1: type scale. A dense back-office runs smaller than a
     reading page, so the ladder is anchored on the UI body size (0.9rem,
     what buttons and table cells already used) and steps in ~6% increments
     through the caption tiers, then opens up to a ~1.25 ratio for headings.
     Only the tiers below exist; a rule picks the role, not a number. */
  --text-2xs: 0.65rem; /* micro labels, table-head caps */
  --text-xs: 0.7rem; /* eyebrow / kicker caps */
  --text-caption: 0.75rem; /* badges, hints */
  --text-sm: 0.8rem; /* field labels, secondary lines */
  --text-body-sm: 0.85rem; /* dense table cells, notes */
  --text-body: 0.9rem; /* UI body: buttons, cells, paragraphs */
  --text-body-lg: 1rem; /* emphasised body, card names */
  --text-h4: 1.05rem; /* panel titles */
  --text-h3: 1.25rem;
  --text-h2: 1.5rem;
  --text-h1: 1.9rem; /* page titles */
  --text-display: 2.4rem;
  --font-ui: "Figtree", "Figtree Fallback", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-display: "Cormorant Garamond", "Cormorant Fallback", Georgia, "Times New Roman", serif;

  /* ui-audit g1: component tier -- values one component family owns. */
  --focus-ring: #1d4ed8;
  --icon-sm: 1rem;
  --icon-md: 1.25rem;
  --icon-lg: 1.5rem;
  --tap-min: 2.75rem;
  /* ui-audit g4: motion tokens. fast = hover/press colour shifts, base =
     small movements (drawers' contents, reveals), slow = large surfaces.
     standard eases both ways, out for things arriving, in for leaving. */
  --motion-fast: 150ms;
  --motion-base: 200ms;
  --motion-slow: 350ms;
  --ease-standard: cubic-bezier(0.2, 0, 0, 1);
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in: cubic-bezier(0.4, 0, 1, 1);
}
/* Any author `display` rule outranks the UA stylesheet's [hidden] rule, so an
   element marked hidden kept rendering whenever its class set a display value.
   That was live in several places: the wastage form showed the ingredient
   selects and the menu-item select at once, the menu editor's "New category
   name" field never hid, the roster's custom-time inputs always showed, and
   the wastage Retake button appeared before any photo was captured. Several
   selectors already carried their own [hidden] guard; this makes it universal
   so the next one added cannot regress. !important is deliberate -- it is the
   standard reset for exactly this trap. */
[hidden] {
  display: none !important;
}
body {
  background: var(--color-background);
  /* ui-audit g1: typographic polish -- real kerning and the font's own
     ligatures; tabular figures stay opt-in per number column. */
  font-kerning: normal;
  text-rendering: optimizeLegibility;
}
/* Headings balance their lines so a title never ends on one stranded word;
   explanatory paragraphs avoid a lone last-line orphan. Browsers without
   text-wrap simply ignore it. */
:where(h1, h2, h3, .page-title, .panel-title, .auth-title) {
  text-wrap: balance;
}
:where(.page-subtitle, .empty-state-hint, p.panel-muted, .settings-section-hint, .auth-lede) {
  text-wrap: pretty;
}
/* ui-audit g2: z-index scale. Every stacking value in the back office (app.css
   and analytics.css) comes from these named layers, lowest to highest, instead
   of loose numbers that had drifted into ties (the phone header and the
   Weekly Count filter bar were both 20; the "more" menu and the sticky save
   bars were both 5). Native <dialog> drawers sit in the browser's top layer
   and need no value; the chart tooltip is already appended to <body>.
   The till (pos.css) keeps its own --pos-z-* scale. */
:root {
  --z-raised: 1;      /* sticky rows inside a table (group labels, header cells) */
  --z-raised-top: 2;  /* a table's sticky header, above its sticky group rows */
  --z-sticky: 10;     /* in-page sticky bars: filter bars, save bars, toolbars */
  --z-dropdown: 20;   /* menus opened from the page, above any sticky bar */
  --z-header: 30;     /* app chrome: the phone header and the sidebar */
  --z-tooltip: 40;    /* chart tooltip, above the chrome it may overlap */
  --z-toast: 60;      /* flash toasts (ui-audit g5) */
  --z-loadbar: 70;    /* the thin page-loading bar */
  --z-help-tip: 75;   /* badge help bubbles, above toasts */
  --z-modal: 80;      /* full-screen sheets that are not native <dialog> */
  --z-skip: 100;      /* the skip link, above everything */
}
.skip-link {
  position: fixed;
  top: 0.75rem;
  left: 0.75rem;
  z-index: var(--z-skip);
  transform: translateY(-150%);
  border-radius: var(--radius-xs);
  background: var(--brand-navy);
  color: var(--color-text-inverse);
  padding: var(--space-3) var(--space-4);
  font-weight: 800;
  transition: transform var(--motion-fast) var(--ease-out);
}
/* The shadow only while shown: parked above the viewport its blur still
   reached down and left a grey smudge over the sidebar's top edge. */
.skip-link:focus-visible {
  transform: translateY(0);
  box-shadow: var(--elevation-3);
}
.sr-only {
  position: absolute;
  /* Without an offset an absolutely positioned label sits at its static
     place and escapes any sideways-scrolling ancestor, which slid whole
     pages left at phone width (Purchases, Suppliers, Reports, Staff). */
  left: 0;
  top: auto;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
  margin: -1px;
  padding: 0;
}
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 3px solid var(--focus-ring);
  outline-offset: 3px;
}
:where(button, .btn-primary, .btn-secondary, .chip, .nav-link, .nav-group-trigger, input:not([type="hidden"]):not([type="checkbox"]):not([type="radio"]), select, textarea, summary) {
  min-height: var(--tap-min);
}
input[type="checkbox"],
input[type="radio"] {
  min-width: 1.25rem;
  min-height: 1.25rem;
}
/* ui-audit g2: touch targets. Measured at 360px, these controls sat under
   the 44px floor the rule above sets for plain buttons: tab and filter
   pills (37-42px), the roster week arrows (40px) and per-row "..." buttons
   (26px wide), stock filters (39px), wastage choice pills (40px), the phone
   header's home link (32px) and table checkboxes (20px). On a phone or any
   touch screen they grow to 44px (checkboxes to 24px, the WCAG minimum,
   since a bigger box would crowd table rows); a mouse keeps the compact
   sizes. Prefixed with the body class so these win over each component's
   own later rule without !important. Report/Dashboard controls
   (.an-btn, .dr-*) get the same treatment in analytics.css. */
@media (max-width: 900px), (pointer: coarse) {
  .ui-serenity .inventory-nav a,
  .ui-serenity .segment-bar a,
  .ui-serenity .filter-bar input,
  .ui-serenity .filter-bar select,
  .ui-serenity .report-toolbar select,
  .ui-serenity .scope-picker label,
  .ui-serenity .mobile-brand {
    min-height: 2.75rem;
  }
  .ui-serenity .segment-bar a,
  .ui-serenity .mobile-brand {
    display: inline-flex;
    align-items: center;
  }
  .ui-serenity .roster-step {
    width: 2.75rem;
    height: 2.75rem;
  }
  .ui-serenity .roster-staff .roster-bulk {
    width: 2.75rem;
  }
  .ui-serenity .count-workbook-input .count-number-input {
    min-height: 2.75rem;
  }
  .ui-serenity input[type="checkbox"] {
    min-width: 1.5rem;
    min-height: 1.5rem;
  }
}
:where(button, .btn-primary, .btn-secondary):disabled,
:where(button, .btn-primary, .btn-secondary)[aria-disabled="true"],
:where(button, .btn-primary, .btn-secondary).is-loading,
:where(input, select, textarea):disabled {
  opacity: 0.62;
  cursor: not-allowed;
}
:where(button, .btn-primary, .btn-secondary).is-loading {
  cursor: progress;
}
#main-content:focus-visible {
  outline-offset: -3px;
}
/* ui-audit g3: focus -- the phone header's chip strip scrolls sideways, and a
   scroller clips anything drawn outside it; draw the chip's ring inside. */
.mobile-header .chip:focus-visible {
  outline-offset: -3px;
}
.app-sidebar {
  position: sticky;
  top: 0;
  width: 18rem;
  height: 100vh;
  border-color: var(--brand-line);
  background: var(--color-surface-warm);
  transition: width var(--motion-base) var(--ease-standard), padding var(--motion-base) var(--ease-standard);
  z-index: var(--z-header);
}
.app-sidebar.is-collapsed {
  width: 5.5rem;
}
.app-sidebar.is-collapsed.is-expanded {
  width: 18rem;
}
.sidebar-nav {
  min-height: 0;
  overflow-x: hidden;
  overflow-y: auto;
}
.brand-card {
  position: relative;
  border: 1px solid #e3d7ca;
  border-radius: var(--radius-sm);
  background: linear-gradient(180deg, #fffaf3 0%, var(--brand-cream) 100%);
  padding: var(--space-3);
}
.brand-lockup {
  display: grid;
  gap: 0.45rem;
  min-width: 0;
}
.brand-logo {
  width: 9.5rem;
  max-width: 100%;
  height: auto;
  object-fit: contain;
}
.brand-logo-mark {
  display: none;
}
.app-sidebar.is-collapsed .brand-card {
  padding: 0.45rem;
}
.app-sidebar.is-collapsed .brand-lockup {
  justify-content: center;
}
.app-sidebar.is-collapsed .brand-logo-full {
  display: none;
}
.app-sidebar.is-collapsed .brand-logo-mark {
  display: block;
  width: 3.25rem;
  height: auto;
}
.app-sidebar.is-collapsed.is-expanded .brand-card {
  padding: var(--space-3);
}
.app-sidebar.is-collapsed.is-expanded .brand-lockup {
  justify-content: initial;
}
.app-sidebar.is-collapsed.is-expanded .brand-logo-full {
  display: block;
}
.app-sidebar.is-collapsed.is-expanded .brand-logo-mark {
  display: none;
}
.sidebar-collapse {
  position: absolute;
  top: 0.45rem;
  right: 0.45rem;
  display: none;
  width: 1.75rem;
  height: 1.75rem;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--color-border-warm);
  border-radius: var(--radius-full);
  background: var(--color-surface-warm);
  color: var(--brand-copper-dark);
  font-size: var(--text-h3);
  line-height: 1;
}
.app-sidebar.is-expanded .sidebar-collapse {
  display: inline-flex;
}
.nav-group {
  position: relative;
  display: block;
  margin-bottom: 0.45rem;
}
.nav-group-trigger {
  display: flex;
  width: 100%;
  align-items: center;
  gap: var(--space-3);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  padding: 0.78rem 0.8rem;
  background: transparent;
  color: #5f524a;
  font-weight: 850;
  letter-spacing: 0;
  text-align: left;
}
.nav-group-trigger:hover,
.nav-group.active-group > .nav-group-trigger {
  border-color: var(--color-border-warm);
  background: var(--brand-cream);
  color: var(--brand-charcoal);
}
.nav-icon {
  display: inline-flex;
  width: 2rem;
  height: 2rem;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  background: var(--color-surface-warm);
  color: var(--brand-copper-dark);
  box-shadow: inset 0 0 0 1px var(--color-border-warm);
}
/* ui-audit g1: one icon language. The sidebar's four filled glyphs were
   the only filled icons in the app; everything else (POS rail, branch pill,
   dashboard) is a 24-grid outline icon at stroke 2.5. The sidebar now draws
   the same outline set. Sizes: --icon-sm beside body text, --icon-md in nav
   and buttons, --icon-lg for standalone marks. */
.nav-icon svg {
  width: var(--icon-md);
  height: var(--icon-md);
  fill: none;
  stroke: currentColor;
  stroke-width: 2.25;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.nav-group-title {
  white-space: nowrap;
}
.nav-submenu {
  display: none;
  gap: 0.15rem;
  padding-left: 2.75rem;
  padding-top: 0.35rem;
}
.app-sidebar.is-expanded .nav-group.is-open > .nav-submenu {
  display: grid;
}
.nav-link {
  display: block;
  border-radius: var(--radius-xs);
  padding: var(--space-2) 0.65rem;
  color: #4a403b;
  font-weight: 700;
}
.nav-link:hover {
  background: #fff7ed;
  color: var(--brand-copper-dark);
}
.nav-link.active {
  background: var(--color-accent-soft);
  color: var(--brand-copper-dark);
  box-shadow: inset 3px 0 0 var(--brand-copper);
}
.app-sidebar.is-collapsed .nav-group-trigger {
  justify-content: center;
  padding: 0.72rem 0.55rem;
}
.app-sidebar.is-collapsed .nav-group-title,
.app-sidebar.is-collapsed .sidebar-user,
.app-sidebar.is-collapsed form[action$="logout"] {
  display: none;
}
.app-sidebar.is-collapsed.is-expanded .nav-group-trigger {
  justify-content: flex-start;
  padding: 0.78rem 0.8rem;
}
.app-sidebar.is-collapsed.is-expanded .nav-group-title,
.app-sidebar.is-collapsed.is-expanded .sidebar-user,
.app-sidebar.is-collapsed.is-expanded form[action$="logout"] {
  display: block;
}
.chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  white-space: nowrap;
  border-radius: var(--radius-full);
  border: 1px solid var(--color-border-strong);
  padding: 0.35rem var(--space-3);
  background: var(--color-surface);
  color: var(--color-text-primary);
  font-weight: 750;
}
/* ui-audit g5: the mobile header's sideways chip row fades on whichever
   edge has more destinations behind it (ops-nav.js sets the classes). */
.mobile-nav-chips { scrollbar-width: none; }
.mobile-nav-chips::-webkit-scrollbar { display: none; }
.mobile-nav-chips.has-more-end {
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 2.5rem), transparent);
  mask-image: linear-gradient(to right, #000 calc(100% - 2.5rem), transparent);
}
.mobile-nav-chips.has-more-start {
  -webkit-mask-image: linear-gradient(to left, #000 calc(100% - 2.5rem), transparent);
  mask-image: linear-gradient(to left, #000 calc(100% - 2.5rem), transparent);
}
.mobile-nav-chips.has-more-start.has-more-end {
  -webkit-mask-image: linear-gradient(to right, transparent, #000 2.5rem, #000 calc(100% - 2.5rem), transparent);
  mask-image: linear-gradient(to right, transparent, #000 2.5rem, #000 calc(100% - 2.5rem), transparent);
}
.chip.active,
.chip[aria-current="page"] {
  border-color: var(--brand-copper-dark);
  background: var(--color-accent-soft);
  color: var(--brand-copper-dark);
}
/* ui-audit g4: hover feedback where it was missing. Only real controls
   (a span.chip is a status label and stays still). */
:is(a, button).chip:not(.active):not([aria-current="page"]):hover {
  border-color: #a8a29e;
  background: #fafaf9;
}
:is(a, button, summary).detail-link:hover {
  text-decoration: underline;
  text-underline-offset: 2px;
}
.sidebar-collapse {
  cursor: pointer;
}
.sidebar-collapse:hover {
  border-color: var(--brand-copper);
  background: #fff3e8;
}
.page-kicker {
  color: var(--brand-copper-dark);
  font-size: var(--text-sm);
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.page-title {
  margin-top: 0.1rem;
  /* ui-audit g1: fluid -- 1.6rem on a phone rising to the 1.9rem desktop
     size by ~700px wide, instead of a desktop-sized title on a 375px screen.
     The rem term keeps it growing with the user's own font-size setting. */
  font-size: clamp(1.6rem, 1.15rem + 1.5vw, var(--text-h1));
  font-weight: 800;
  line-height: 1.2;
  letter-spacing: 0;
}
.page-subtitle {
  margin-top: 0.35rem;
  /* ui-audit g1: measure -- a subtitle ran the full 1100px content width
     (~150 characters a line) on a desktop; ~70ch keeps it one easy read. */
  max-width: 70ch;
  color: var(--color-text-secondary);
  font-size: 0.95rem;
  line-height: 1.55;
}
.panel {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  padding: var(--space-4);
  box-shadow: var(--elevation-1);
}
.panel-title {
  font-size: var(--text-h4);
  font-weight: 700;
  line-height: 1.35;
}
/* ui-audit g3: overflow -- real names (items, suppliers, staff, e-mails) run
   longer than the text these were drawn with. An unbroken one wraps inside
   its box instead of pushing the whole page sideways on a phone. */
.page-title,
.page-subtitle,
.panel-title,
.an-title,
.card-title,
.auth-title,
.sidebar-user p,
.flash-message { overflow-wrap: anywhere; }
.row > :first-child,
.metric-line > :first-child { min-width: 0; overflow-wrap: anywhere; }
.panel-muted {
  border-color: var(--color-border-strong);
  background: var(--color-surface-muted);
}
/* The same measure for the explanatory paragraphs panels carry. */
p.panel-muted,
.settings-remove-note {
  max-width: 75ch;
}
.stat {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  padding: var(--space-4);
  box-shadow: var(--elevation-1);
}
.stat span {
  display: block;
  color: var(--color-text-muted);
  font-size: var(--text-body);
}
.stat strong {
  display: block;
  margin-top: 0.35rem;
  font-size: 1.45rem;
}
.stat small {
  display: block;
  margin-top: 0.4rem;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}
/* ui-audit g2: density. Below the md breakpoint the three stat cards
   (roster, stock, wastage) stacked as ~135px boxes -- a whole phone screen
   before the actual list. Each becomes a compact row: label and note on the
   left, the number on the right, about half the height. */
@media (max-width: 767px) {
  .stat {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    column-gap: 1rem;
    padding: 0.75rem 1rem;
  }
  .stat span { grid-column: 1; }
  .stat small { grid-column: 1; margin-top: 0.15rem; }
  .stat strong {
    grid-column: 2;
    grid-row: 1 / span 2;
    margin-top: 0;
    font-size: 1.3rem;
    text-align: right;
  }
}
.row {
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
  border-bottom: 1px solid var(--color-border);
  padding: 0.65rem 0;
}
.row:last-child {
  border-bottom: 0;
}
/* ui-audit g3: numbers -- the value side of a label/value line uses tabular
   digits so OMR amounts stacked in a list line up. */
.row > :last-child,
.metric-line > :last-child,
.stat strong { font-variant-numeric: tabular-nums; }
.empty {
  color: var(--color-text-muted);
  font-size: var(--text-body);
}
/* ui-audit g1: empty states. A list with nothing in it says what would be
   here and offers the next step, instead of one grey line that reads like
   a fault. The .empty sentence becomes the title; .empty-state-hint is the
   one-line explanation; a button or link under it is the way forward. A
   filtered list that came back empty gets "clear the filter", a list that
   has never had anything gets "add the first one". */
.empty-state {
  display: grid;
  justify-items: center;
  gap: var(--space-2);
  padding: var(--space-8) var(--space-4);
  text-align: center;
}
.empty-state::before {
  content: "";
  width: 2.5rem;
  height: 2.5rem;
  margin-bottom: var(--space-1);
  border-radius: var(--radius-full);
  background: var(--color-surface-sunken) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2378716c' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 13h4l1.5 2.5h5L16 13h4'/%3E%3Cpath d='M5.5 6.5 4 13v5h16v-5l-1.5-6.5z'/%3E%3C/svg%3E") center / 1.25rem no-repeat;
}
.empty-state .empty {
  color: var(--color-text-primary);
  font-size: 0.95rem;
  font-weight: 700;
}
.empty-state-hint {
  max-width: 42ch;
  color: var(--color-text-muted);
  font-size: var(--text-body);
  line-height: 1.5;
}
.empty-state :where(.btn-primary, .btn-secondary) {
  margin-top: var(--space-2);
}
.badge {
  display: inline-flex;
  align-items: center;
  border-radius: var(--radius-full);
  padding: 0.22rem 0.55rem;
  background: var(--color-surface-sunken);
  color: var(--color-text-secondary);
  font-size: var(--text-caption);
  font-weight: 800;
}
.badge-good {
  background: var(--brand-success-bg);
  color: var(--brand-success-text);
}
.badge-warn {
  background: var(--amber-100);
  color: var(--color-warning);
}
.badge-danger {
  background: var(--red-100);
  color: var(--color-danger-strong);
}
/* ui-audit g5: status system. One look per state everywhere a status shows:
   neutral .badge / .badge-quiet (no dot), and good / warn / danger, which add
   a leading dot so the state reads by shape and label as well as colour --
   the same dot the report tags (.tag i) and the dashboard shift pill use.
   Count sessions (.count-status-*) map onto the same palette below. */
.badge-good,
.badge-warn,
.badge-danger,
.count-status-approved,
.count-status-submitted {
  gap: 0.3rem;
}
.badge-good::before,
.badge-warn::before,
.badge-danger::before,
.count-status-approved::before,
.count-status-submitted::before {
  flex: none;
  width: 0.4rem;
  height: 0.4rem;
  border-radius: 999px;
  background: currentColor;
  content: "";
}
.badge-warn::before,
.count-status-submitted::before {
  border-radius: 1px;
  transform: rotate(45deg);
}
.badge-danger::before {
  border-radius: 1px;
}
.btn-primary,
.btn-secondary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-xs);
  padding: 0.6rem 0.9rem;
  font-weight: 700;
  font-size: var(--text-body);
}
.btn-primary {
  background: var(--brand-copper-dark);
  color: var(--color-text-inverse);
}
.btn-primary:hover {
  background: var(--color-accent-hover);
}
.btn-secondary {
  border: 1px solid var(--color-border-strong);
  background: var(--color-surface);
  color: var(--color-text-primary);
}
.btn-secondary:hover {
  background: var(--color-surface-sunken);
}
/* ui-audit g1: button states. Hover existed; this adds a quick colour
   transition, a pressed state that dips 1px (tactile without moving the
   layout), a hover that stays put on a disabled button, a danger variant
   with real hover/pressed shades, and a spinner beside the "Working..."
   label ops-ui.js swaps in on submit (it also disables the button, which is
   what stops a double submission). Focus rings come from the global
   :focus-visible rule near the top of this file. */
.btn-primary,
.btn-secondary,
.btn-link {
  transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease, transform 80ms ease;
}
.btn-primary:active:not(:disabled):not([aria-disabled="true"]),
.btn-secondary:active:not(:disabled):not([aria-disabled="true"]) {
  transform: translateY(1px);
}
.btn-primary:active:not(:disabled):not([aria-disabled="true"]) {
  background: var(--color-accent-pressed);
}
.btn-secondary:active:not(:disabled):not([aria-disabled="true"]) {
  background: var(--stone-200);
}
.btn-primary:is(:disabled, [aria-disabled="true"]):hover {
  background: var(--brand-copper-dark);
}
.btn-secondary:is(:disabled, [aria-disabled="true"]):hover {
  background: var(--color-surface);
}
.btn-danger-outline:hover:not(:disabled):not([aria-disabled="true"]) {
  background: var(--red-50);
}
.btn-danger-outline:active:not(:disabled):not([aria-disabled="true"]) {
  background: var(--red-100);
}
:where(button, .btn-primary, .btn-secondary).is-loading::before {
  content: "";
  display: inline-block;
  flex: none;
  width: 0.9em;
  height: 0.9em;
  margin-right: 0.5em;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  vertical-align: -0.125em;
  animation: btn-spin 700ms linear infinite;
}
@keyframes btn-spin {
  to { transform: rotate(360deg); }
}
/* ui-audit g4: micro-interactions. Colour eases on hover, and a pressed
   control dips 1px so a tap on a tablet visibly registers. transform never
   moves layout; the global reduced-motion rule below collapses both. */
.btn-primary,
.btn-secondary,
.chip,
.nav-link {
  transition: background-color var(--motion-fast) var(--ease-standard), border-color var(--motion-fast) var(--ease-standard), color var(--motion-fast) var(--ease-standard), box-shadow var(--motion-fast) var(--ease-standard), transform var(--motion-fast) var(--ease-standard);
}
.btn-primary:active:not(:disabled):not(.is-loading),
.btn-secondary:active:not(:disabled):not(.is-loading),
:is(a, button).chip:active {
  transform: translateY(1px);
}
.flag,
.note {
  border-radius: var(--radius-full);
  padding: var(--space-1) var(--space-2);
  font-weight: 700;
}
.flag {
  background: var(--amber-100);
  color: var(--color-warning);
}
.note {
  background: var(--color-surface-sunken);
  color: var(--color-text-secondary);
}
.form-grid p,
.form-grid label {
  display: grid;
  gap: 0.35rem;
}
form input,
form select,
form textarea {
  width: 100%;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-xs);
  padding: 0.55rem 0.7rem;
  background: var(--color-surface);
}
form input[type="checkbox"] {
  width: auto;
}
/* ui-audit g1: hierarchy. A field wrapped in its label (.compact-field and
   friends) inherited the label's small 750-weight caption type, so what
   the user typed or picked looked like another label. The value reads as
   body text; the label stays the small bold caption above it. Zero-
   specificity :where() so any rule that sizes a specific input still wins. */
label :where(input:not([type="checkbox"]):not([type="radio"]), select, textarea) {
  color: var(--color-text-primary);
  font-size: var(--text-body);
  font-weight: 500;
}
/* ui-audit g4: input states. :where() keeps these at class-level weight so
   any component's own input styling (auth card, count sheet) still wins.
   Focus tints the border as well as the global blue ring; an error (from
   Django, or from form-ux.js's inline check) is red and unmistakable; a
   disabled box looks switched off, not merely faint. */
:where(form) :where(input:not([type="checkbox"]):not([type="radio"]):not([type="file"]), select, textarea) {
  transition: border-color var(--motion-fast) var(--ease-standard), box-shadow var(--motion-fast) var(--ease-standard);
}
:where(form) :where(input:not([type="checkbox"]):not([type="radio"]):not([type="file"]), select, textarea):focus {
  border-color: var(--brand-copper-dark);
}
:where(form) :where(input, select, textarea)[aria-invalid="true"] {
  border-color: #b91c1c;
  background-color: #fff8f7;
}
:where(form) :where(input, select, textarea)[aria-invalid="true"]:focus {
  box-shadow: 0 0 0 3px rgb(185 28 28 / 0.14);
}
:where(form) :where(input:not([type="checkbox"]):not([type="radio"]), select, textarea):disabled {
  background-color: #f5f5f4;
  color: #78716c;
}
/* Phase 5: a plain checkbox + its label on one line (the void drawer's
   "Put the stock back" / "Ring it again" pair) -- .compact-field above is
   for a labelled INPUT, not a checkbox, so this is its own small class. */
.checkbox-field {
  align-items: center;
  color: var(--color-text-secondary);
  display: flex;
  font-size: var(--text-body-sm);
  gap: 0.45rem;
}
.checkbox-field input {
  margin: 0;
}
.is-num {
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: nowrap;
}
.form-grid {
  display: grid;
  gap: 0.8rem;
}
.user-create-grid {
  grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
  align-items: end;
}
.user-create-grid p,
.compact-field {
  display: grid;
  gap: 0.35rem;
  color: var(--color-text-secondary);
  font-size: var(--text-sm);
  font-weight: 750;
}
.permission-check {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  padding: var(--space-4);
}
.flash-message {
  border: 1px solid var(--color-border-warm);
  border-radius: var(--radius-sm);
  background: #fff7ed;
  color: var(--brand-copper-dark);
  padding: var(--space-3) var(--space-4);
  font-size: var(--text-body);
}
.flash-message.success {
  border-color: #b7d7c0;
  background: #edf8f0;
  color: #1f5b32;
}
.flash-message.info,
.flash-message.debug {
  border-color: #bfdbfe;
  background: #eff6ff;
  color: #1e3a8a;
}
.flash-message.warning {
  border-color: #f3d38a;
  background: var(--color-warning-soft);
  color: #7c2d12;
}
.flash-message.error {
  border-color: var(--red-200);
  background: var(--rose-50);
  color: var(--color-danger-strong);
}
/* ui-audit g5: flash + toast (see static/operations/ops-feedback.js).
   Every server message and floating toast carries a type icon so the kind
   of message never rests on colour alone, plus a dismiss button. */
.flash-stack > .flash-message,
.ops-toast {
  position: relative;
  padding-left: 2.6rem;
}
.flash-stack > .flash-message::before,
.ops-toast::before {
  position: absolute;
  left: 0.85rem;
  top: 0.78rem;
  display: grid;
  place-items: center;
  width: 1.15rem;
  height: 1.15rem;
  border-radius: 999px;
  background: currentColor;
  content: "i";
  /* a white glyph on a disc of the message's own text colour */
  -webkit-text-fill-color: #fff;
  font-size: 0.72rem;
  font-weight: 800;
  line-height: 1;
}
.flash-stack > .flash-message.success::before,
.ops-toast.success::before { content: "\2713"; }
.flash-stack > .flash-message.warning::before,
.flash-stack > .flash-message.error::before,
.ops-toast.warning::before,
.ops-toast.error::before { content: "!"; }
.flash-message.is-dismissible,
.ops-toast {
  padding-right: 2.75rem;
}
.flash-dismiss {
  position: absolute;
  top: 0.35rem;
  right: 0.35rem;
  display: grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  border: 0;
  border-radius: 0.4rem;
  background: transparent;
  color: inherit;
  cursor: pointer;
  font-size: 1.25rem;
  line-height: 1;
  opacity: 0.7;
}
.flash-dismiss:hover,
.flash-dismiss:focus-visible {
  background: rgb(0 0 0 / 0.06);
  opacity: 1;
}
.flash-message.is-leaving,
.ops-toast.is-leaving {
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity 0.2s ease, transform 0.2s ease;
}
.ops-toasts {
  position: fixed;
  right: 1rem;
  bottom: max(1rem, env(safe-area-inset-bottom));
  z-index: var(--z-toast);
  display: grid;
  gap: 0.5rem;
  justify-items: end;
  width: min(24rem, calc(100vw - 2rem));
  pointer-events: none;
}
.ops-toast {
  width: 100%;
  border: 1px solid #bfdbfe;
  border-radius: 0.5rem;
  background: #eff6ff;
  box-shadow: 0 10px 30px rgb(28 25 23 / 0.16);
  color: #1e3a8a;
  padding-top: 0.75rem;
  padding-bottom: 0.75rem;
  font-size: 0.9rem;
  pointer-events: auto;
  animation: opsToastIn 0.18s ease-out;
}
.ops-toast.success { border-color: #b7d7c0; background: #edf8f0; color: #1f5b32; }
.ops-toast.warning { border-color: #f3d38a; background: #fffbeb; color: #7c2d12; }
.ops-toast.error { border-color: #fecaca; background: #fff1f2; color: #991b1b; }
@keyframes opsToastIn {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}
@media (max-width: 640px) {
  .ops-toasts { right: 1rem; left: 1rem; width: auto; }
}
/* Page-load bar (ops-feedback.js): a thin copper line along the top edge
   while the next page is on its way. */
.ops-load-bar {
  position: fixed;
  top: 0;
  left: 0;
  z-index: var(--z-loadbar);
  width: 100%;
  height: 3px;
  overflow: hidden;
  background: rgb(201 121 69 / 0.18);
  pointer-events: none;
}
.ops-load-bar[hidden] { display: none; }
.ops-load-bar::after {
  position: absolute;
  inset: 0 auto 0 0;
  width: 35%;
  background: var(--brand-copper);
  content: "";
  animation: opsLoadBar 1.1s ease-in-out infinite;
}
/* Explanation bubble for badges and tags (ops-feedback.js). */
.has-help { cursor: help; }
.has-help:focus-visible { outline: 2px solid var(--brand-copper); outline-offset: 2px; }
.ops-help-tip {
  position: fixed;
  z-index: var(--z-help-tip);
  max-width: min(18rem, calc(100vw - 16px));
  border-radius: 0.4rem;
  background: #1c1917;
  box-shadow: 0 8px 24px rgb(28 25 23 / 0.22);
  color: #fafaf9;
  font-size: 0.8rem;
  font-weight: 500;
  line-height: 1.4;
  padding: 0.5rem 0.65rem;
  pointer-events: none;
}
.ops-help-tip[hidden] { display: none; }
@keyframes opsLoadBar {
  from { transform: translateX(-100%); }
  to { transform: translateX(300%); }
}
@media (prefers-reduced-motion: reduce) {
  .ops-toast { animation: none; }
  .ops-load-bar::after { width: 100%; animation: none; opacity: 0.7; }
  .flash-message.is-leaving,
  .ops-toast.is-leaving { transition: none; transform: none; }
}
.detail-link,
.login-kicker {
  color: var(--brand-copper-dark);
  font-weight: 800;
}
.detail-link {
  font-size: var(--text-body);
}
/* ui-audit g3: colour-only -- a link sitting inside a sentence was told
   apart from the words around it by colour alone (the Tailwind reset strips
   the underline). Underline it; buttons styled as links keep their look. */
p:not(.card-foot) > a:not([class*="btn"]):not([role="button"]):not(.chip) {
  text-decoration: underline;
  text-decoration-thickness: from-font;
  text-underline-offset: 0.18em;
}
.login-kicker {
  font-size: var(--text-sm);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
/* POS checkout styling lives in static/operations/pos.css, which pos.html loads
   after this file. `.pos-filter` remains only as a JS hook in pos-ui.js and is
   styled there as `.pos-chip`. */
.optional-label {
  color: var(--color-text-subtle);
  font-size: var(--text-caption);
  font-weight: 700;
}
.form-errors {
  border: 1px solid var(--red-200);
  border-radius: var(--radius-sm);
  background: var(--rose-50);
  color: var(--color-danger-strong);
  padding: var(--space-3);
  font-size: var(--text-body-sm);
}
/* Django renders field validation errors as a bare <ul class="errorlist">
   with no styling of its own -- a rejected save (e.g. a commission rate out
   of range) looked identical to a successful one because the error was
   easy to miss. */
form ul.errorlist {
  list-style: none;
  margin: 0 0 0.35rem;
  padding: 0.6rem 0.8rem;
  border: 1px solid var(--red-200);
  border-radius: var(--radius-sm);
  background: var(--rose-50);
  color: var(--color-danger-strong);
  font-size: var(--text-sm);
  font-weight: 650;
}
.segment-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  overflow-x: visible;
  padding-bottom: 0.1rem;
}
.segment-bar a {
  flex: 0 0 auto;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-full);
  background: var(--color-surface);
  color: var(--color-text-secondary);
  padding: 0.45rem 0.8rem;
  font-size: var(--text-body-sm);
  font-weight: 800;
}
.segment-bar a.active,
.segment-bar a:hover {
  border-color: var(--brand-copper-dark);
  background: var(--color-accent-soft);
  color: var(--brand-copper-dark);
}
.action-flow {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
}
.action-flow span {
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-full);
  background: var(--color-surface-muted);
  color: var(--color-text-secondary);
  padding: 0.35rem 0.65rem;
  font-size: var(--text-sm);
  font-weight: 800;
}
.toggle-row {
  display: grid;
  grid-template-columns: auto auto 1fr;
  align-items: start;
  gap: 0.7rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  padding: 0.85rem;
}
.toggle-row input {
  position: absolute;
  opacity: 0;
}
.toggle-ui {
  position: relative;
  display: inline-flex;
  width: 2.7rem;
  height: 1.5rem;
  border-radius: var(--radius-full);
  background: var(--stone-300);
  transition: background var(--motion-fast) var(--ease-standard);
}
.toggle-ui::after {
  content: "";
  position: absolute;
  top: 0.18rem;
  left: 0.18rem;
  width: 1.14rem;
  height: 1.14rem;
  border-radius: var(--radius-full);
  background: var(--color-surface);
  box-shadow: 0 1px 3px rgb(0 0 0 / 0.22);
  transition: transform var(--motion-fast) var(--ease-out);
}
.toggle-row input:checked + .toggle-ui {
  background: var(--brand-copper-dark);
}
.toggle-row input:checked + .toggle-ui::after {
  transform: translateX(1.2rem);
}
.toggle-row input:focus-visible + .toggle-ui {
  outline: 3px solid var(--focus-ring);
  outline-offset: 3px;
}
.stock-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  padding: 0.85rem;
}
.stock-card.low {
  border-color: #f3d38a;
  background: var(--color-warning-soft);
}
.stock-card.negative {
  border-color: var(--red-200);
  background: var(--rose-50);
}
.stock-card > div > span,
.inventory-line > div > span,
.inventory-summary small {
  display: block;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}
.inventory-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
}
.inventory-line {
  display: grid;
  grid-template-columns: minmax(12rem, 1fr) auto;
  align-items: center;
  gap: var(--space-4);
  border-top: 1px solid var(--color-border);
  padding: 0.72rem 0;
}
.inventory-line:first-child {
  border-top: 0;
}
.inventory-line-metrics {
  display: grid;
  grid-template-columns: auto minmax(6rem, auto) minmax(6rem, auto);
  align-items: center;
  gap: var(--space-3);
  text-align: right;
}
.component-preview {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}
.component-preview span {
  border-radius: var(--radius-full);
  background: var(--color-surface-sunken);
  color: var(--color-text-secondary);
  padding: 0.28rem 0.55rem;
  font-size: var(--text-sm);
  font-weight: 750;
}
.striped-table tbody tr:nth-child(odd),
.inventory-line:nth-child(odd),
.metric-line:nth-child(odd) {
  background: var(--color-surface-warm);
}
.striped-table tbody tr:nth-child(even),
.inventory-line:nth-child(even),
.metric-line:nth-child(even) {
  background: #f7f3ed;
}
.striped-table td,
.striped-table th {
  border-bottom-color: #eadfd5;
}
.stat-accent {
  border-left: 4px solid var(--brand-copper);
}
.stat-accent.alt {
  border-left-color: var(--brand-navy);
}
.stat-accent.warm {
  border-left-color: #d7a043;
}
.seller-panel {
  border-top: 4px solid var(--brand-copper);
}
.seller-panel.week {
  border-top-color: var(--brand-navy);
}
.seller-panel.month {
  border-top-color: #d7a043;
}
.seller-list {
  display: grid;
  gap: 0.65rem;
}
.seller-card {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-3);
  border: 1px solid #eadfd5;
  border-radius: var(--radius-sm);
  background: var(--color-surface-warm);
  padding: var(--space-3);
}
.seller-card:nth-child(even) {
  background: #f8f4ee;
}
.seller-card small,
.attendance-card p {
  display: block;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}
.seller-rank {
  display: inline-grid;
  width: 1.8rem;
  height: 1.8rem;
  place-items: center;
  border-radius: var(--radius-full);
  background: var(--color-accent-soft);
  color: var(--brand-copper-dark);
  font-weight: 900;
}
.attendance-card {
  overflow: hidden;
  border: 1px solid #eadfd5;
  border-radius: var(--radius-sm);
  background: var(--color-surface);
}
.attendance-card:nth-child(even) {
  background: #fbf7f1;
}
.attendance-card img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}
.attendance-card h2 {
  font-weight: 800;
}
.custom-time-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.35rem;
  margin-top: 0.4rem;
}
.custom-time-row input {
  padding: 0.45rem;
  font-size: var(--text-body-sm);
}
/* Phase 14 roster grid. The chip UI is gated behind .is-enhanced, which only
   roster-grid.js adds: with JavaScript off the chips and the bulk buttons stay
   display:none and the original selects (.roster-cell-fallback) are the page.
   Nothing here uses [hidden] on a wrapper around a form control, because a
   hidden control still submits and the payload must not change either way. */
.roster-stepper {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  border: 1px solid var(--brand-line);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  padding: 0.6rem var(--space-3);
}
.roster-stepper select {
  flex: 1 1 auto;
  min-width: 0;
  font-weight: 700;
}
.roster-step {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  border: 1px solid var(--brand-line);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--brand-copper-dark);
  font-size: 1.3rem;
  font-weight: 800;
  line-height: 1;
  text-decoration: none;
}
.roster-step:hover {
  background: var(--color-accent-soft);
}
.roster-grid {
  display: grid;
  grid-template-columns: minmax(7.5rem, 0.9fr) repeat(7, minmax(0, 1fr));
  gap: 0.35rem;
}
.roster-head-row,
.roster-row {
  display: contents;
}
.roster-head {
  display: flex;
  position: relative;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  background: var(--brand-navy);
  color: var(--color-text-inverse);
  padding: 0.45rem;
  text-align: center;
  font-weight: 800;
}
.roster-head-day {
  background: color-mix(in srgb, var(--day-color, var(--brand-navy)) 55%, var(--brand-navy));
}
.roster-head-daytext {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.roster-head-day small {
  font-size: var(--text-xs);
  font-weight: 600;
  opacity: 0.9;
}
.roster-staff {
  display: flex;
  position: relative;
  align-items: center;
  justify-content: space-between;
  gap: 0.4rem;
  border-radius: var(--radius-sm);
  background: #eaf2fe;
  color: var(--brand-navy);
  padding: var(--space-2) 0.6rem;
  font-weight: 800;
}
.roster-staff-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.roster-bulk {
  display: none;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  width: 1.6rem;
  height: 1.6rem;
  border: 0;
  border-radius: var(--radius-xs);
  background: rgb(255 255 255 / 0.55);
  color: inherit;
  font-size: 0.95rem;
  font-weight: 800;
  line-height: 1;
}
.roster-head .roster-bulk {
  position: absolute;
  top: 0.25rem;
  right: 0.25rem;
  background: rgb(255 255 255 / 0.28);
  color: var(--color-text-inverse);
}
.roster-bulk:hover {
  background: var(--color-surface);
  color: var(--brand-copper-dark);
}
.roster-grid.is-enhanced .roster-bulk {
  display: inline-flex;
}
.roster-cell {
  display: grid;
  border-radius: var(--radius-sm);
  background: var(--day-soft, #f7fbff);
  padding: 0.3rem;
  /* ui-audit g2: the chip (3.1rem) and the staff cell's "..." button that
     roster-grid.js reveals are taller than the select they replace, so every
     row grew after first paint (CLS 0.013 at 1440px). Reserve that height. */
  min-height: 3.75rem;
}
.roster-cell-day {
  display: none;
}
.roster-cell-fallback {
  display: grid;
  align-content: center;
  gap: 0.3rem;
}
.roster-cell-fallback select {
  font-weight: 800;
  text-align: center;
}
.roster-grid.is-enhanced .roster-cell-fallback {
  display: none;
}
.shift-chip {
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.1rem;
  width: 100%;
  min-height: 3.1rem;
  border: 1px solid rgb(0 27 103 / 0.12);
  border-radius: var(--radius-xs);
  background: var(--chip-color, #eef2f7);
  color: #111;
  padding: 0.35rem 0.3rem;
  text-align: center;
}
.roster-grid.is-enhanced .shift-chip {
  display: flex;
}
.shift-chip:hover {
  border-color: var(--brand-copper-dark);
}
.shift-chip-label {
  font-size: var(--text-body-lg);
  font-weight: 900;
  line-height: 1.1;
}
.shift-chip-time {
  max-width: 100%;
  overflow: hidden;
  color: var(--stone-700);
  font-size: var(--text-2xs);
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.shift-chip.is-off .shift-chip-label {
  color: #e00012;
}
.roster-cell.is-dirty {
  outline: 2px solid var(--brand-copper-dark);
  outline-offset: -1px;
}
.roster-actionbar {
  display: flex;
  position: sticky;
  bottom: 0;
  z-index: var(--z-sticky);
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  border: 1px solid var(--brand-line);
  border-radius: var(--radius-sm);
  background: rgb(255 253 249 / 0.96);
  margin-top: var(--space-4);
  padding: var(--space-3) 0.9rem;
  backdrop-filter: blur(8px);
}
.roster-actionbar-text {
  display: grid;
  gap: 0.1rem;
}
.roster-actionbar-text strong {
  font-weight: 800;
}
.roster-dirty {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}
.roster-actionbar.is-dirty .roster-dirty {
  color: var(--brand-copper-dark);
  font-weight: 800;
}
.roster-actionbar-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}
.roster-legend {
  border: 1px solid var(--brand-line);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  padding: 0.9rem;
}
.roster-legend-title {
  font-size: var(--text-sm);
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}
.roster-legend-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: 0.6rem;
}
.roster-legend-chip {
  display: inline-flex;
  flex-direction: column;
  border: 1px solid rgb(0 27 103 / 0.12);
  border-radius: var(--radius-xs);
  background: var(--chip-color, #eef2f7);
  padding: 0.35rem 0.7rem;
  text-align: center;
}
.roster-legend-chip strong {
  font-size: var(--text-body);
  font-weight: 900;
}
.roster-legend-chip small {
  color: var(--stone-700);
  font-size: var(--text-xs);
  font-weight: 600;
}
.shift-preset-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-2);
}
.shift-preset {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.1rem;
  border: 1px solid rgb(0 27 103 / 0.12);
  border-radius: var(--radius-sm);
  background: var(--chip-color, #eef2f7);
  padding: 0.6rem 0.4rem;
  text-align: center;
}
.shift-preset strong {
  font-size: var(--text-body-lg);
  font-weight: 900;
}
.shift-preset small {
  color: var(--stone-700);
  font-size: var(--text-xs);
  font-weight: 600;
}
.shift-preset[aria-pressed="true"] {
  outline: 2px solid var(--brand-copper-dark);
  outline-offset: 1px;
}
.shift-drawer-actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
}
@media (max-width: 900px) {
  /* Stacked cards, never a horizontal scroller -- this page is used on a
     phone and a 8-column grid cannot be read there. */
  .roster-grid {
    display: block;
  }
  .roster-head-row {
    display: none;
  }
  .roster-row {
    display: block;
    border: 1px solid #dbe7f4;
    border-radius: 0.6rem;
    background: var(--color-surface);
    margin-bottom: var(--space-3);
    padding: 0.6rem;
  }
  .roster-staff {
    margin-bottom: var(--space-2);
  }
  .roster-cell {
    grid-template-columns: 6.5rem minmax(0, 1fr);
    align-items: center;
    gap: 0.6rem;
    background: transparent;
    padding: 0.2rem 0;
  }
  .roster-cell + .roster-cell {
    border-top: 1px solid #f1f5f9;
  }
  .roster-cell-day {
    display: block;
    color: var(--color-text-secondary);
    font-size: var(--text-sm);
    font-weight: 700;
  }
  .shift-chip {
    min-height: 2.6rem;
  }
  /* ui-audit g2: density. The sticky save bar stayed on screen at 131px
     (a sixth of a phone) as a column. It now wraps instead: week and status
     share one line, the two buttons sit side by side under it on a phone,
     and everything fits in a single row on a tablet (~70px). */
  .roster-actionbar {
    flex-wrap: wrap;
    gap: 0.5rem 0.75rem;
  }
  .roster-actionbar-text {
    display: flex;
    flex: 1 1 12rem;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0 0.6rem;
  }
  .roster-actionbar-actions {
    flex: 1 1 14rem;
  }
  .roster-actionbar-actions .btn-primary,
  .roster-actionbar-actions .btn-secondary {
    flex: 1 1 7rem;
  }
  /* ui-audit g2: each staff card's seven days flow as a self-wrapping grid
     (day label over its chip) instead of seven full-width rows: three days
     a row on a 360px phone, the whole week in one row on a tablet. Roughly
     halves the page on a phone (eleven staff = 77 rows before). */
  .roster-row {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(5.75rem, 1fr));
    gap: 0.4rem;
  }
  .roster-staff {
    grid-column: 1 / -1;
    margin-bottom: 0.1rem;
  }
  .roster-cell {
    grid-template-columns: minmax(0, 1fr);
    gap: 0.2rem;
    padding: 0;
  }
  .roster-cell + .roster-cell {
    border-top: 0;
  }
  .roster-cell-day {
    font-size: 0.74rem;
    text-align: center;
  }
  .shift-chip {
    min-height: 2.75rem;
  }
}
.btn-secondary.is-selected {
  border-color: var(--brand-copper-dark);
  background: var(--color-accent-soft);
  color: var(--brand-copper-dark);
}
.app-sidebar form[action$="logout"] button {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
}
.filter-bar {
  display: grid;
  gap: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  padding: 0.9rem;
}
.filter-bar label {
  display: grid;
  gap: var(--space-1);
  color: var(--color-text-secondary);
  font-size: var(--text-sm);
  font-weight: 750;
}
.filter-bar input,
.filter-bar select {
  min-height: 2.45rem;
}
.mini-list {
  display: grid;
  gap: 0.7rem;
}
.record-card {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  padding: var(--space-4);
}
.record-card:hover {
  border-color: var(--color-border-strong);
  box-shadow: var(--elevation-2);
}
.metric-line {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  border-bottom: 1px solid var(--color-border);
  padding: 0.65rem 0;
}
.metric-line:last-child {
  border-bottom: 0;
}
.soft-band {
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  background: #f7f5ef;
  padding: var(--space-4);
}
.bar-list {
  display: grid;
  gap: var(--space-3);
}
.bar-row {
  display: grid;
  grid-template-columns: minmax(9rem, 1fr) minmax(12rem, 2fr) minmax(7.5rem, auto);
  align-items: center;
  gap: 0.85rem;
}
.bar-row.compact {
  grid-template-columns: minmax(8rem, 1fr) minmax(8rem, 1.4fr) minmax(6.5rem, auto);
}
.bar-label {
  min-width: 0;
}
.bar-label strong,
.bar-label small {
  display: block;
}
.bar-label strong {
  overflow-wrap: anywhere;
}
.bar-label small {
  color: var(--color-text-muted);
  font-size: var(--text-caption);
}
.bar-track {
  display: block;
  height: 0.72rem;
  overflow: hidden;
  border-radius: var(--radius-full);
  background: var(--stone-200);
}
.bar-track span {
  display: block;
  min-width: 0.35rem;
  height: 100%;
  border-radius: inherit;
  background: var(--brand-copper-dark);
}
.bar-value {
  justify-self: end;
  color: var(--color-text-primary);
  font-size: var(--text-body-sm);
  font-weight: 800;
  text-align: right;
}
.dashboard-chart-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-4);
}
.activity-chart-card {
  min-width: 0;
  overflow: hidden;
  border: 1px solid var(--brand-line);
  border-radius: var(--radius-md);
  background: var(--color-background);
}
.activity-chart-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  border-bottom: 1px solid var(--brand-line);
  padding: 0.9rem var(--space-4);
}
.activity-chart-head h3 {
  color: var(--color-text-primary);
}
.activity-chart-head p {
  margin-top: 0.15rem;
  color: var(--color-text-muted);
  font-size: var(--text-caption);
}
.activity-segments {
  display: flex;
  height: 0.6rem;
  gap: 0.16rem;
  margin: var(--space-12) var(--space-4) var(--space-5);
  overflow: hidden;
  border-radius: var(--radius-full);
  background: var(--brand-cream);
}
.activity-segments > span {
  min-width: 0.25rem;
  border-radius: var(--radius-full);
}
.activity-list {
  display: grid;
  gap: 0.85rem;
  max-height: 26rem;
  overflow-y: auto;
  padding: 0 var(--space-4) var(--space-4);
}
.activity-list-ranked {
  padding-top: 0.9rem;
}
.activity-row {
  display: grid;
  grid-template-columns: minmax(8rem, 1fr) minmax(7rem, 1.6fr) minmax(3.5rem, auto);
  align-items: center;
  gap: var(--space-3);
}
.activity-row-ranked {
  grid-template-columns: 1.8rem minmax(10rem, 1fr) minmax(3.5rem, auto);
}
.activity-name,
.activity-product > span:first-child {
  min-width: 0;
}
.activity-name {
  display: grid;
  grid-template-columns: 0.55rem minmax(0, 1fr);
  align-items: center;
  column-gap: 0.45rem;
}
.activity-name strong,
.activity-product strong {
  min-width: 0;
  overflow: hidden;
  color: var(--stone-700);
  font-size: var(--text-sm);
  text-overflow: ellipsis;
  white-space: nowrap;
}
.activity-name small {
  grid-column: 2;
}
.activity-name small,
.activity-product small,
.activity-value small {
  display: block;
  color: var(--color-text-subtle);
  font-size: var(--text-xs);
}
.activity-dot {
  display: block;
  width: 0.55rem;
  height: 0.55rem;
  border-radius: var(--radius-full);
}
.activity-track {
  display: block;
  height: 0.38rem;
  overflow: hidden;
  border-radius: var(--radius-full);
  background: var(--brand-line);
}
.activity-track > span {
  display: block;
  min-width: 0.3rem;
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--brand-copper), var(--brand-copper-dark));
}
.activity-product {
  display: grid;
  gap: 0.35rem;
}
.activity-product > span:first-child {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
}
.activity-rank {
  display: inline-grid;
  width: 1.55rem;
  height: 1.55rem;
  place-items: center;
  border-radius: var(--radius-full);
  background: var(--brand-cream);
  color: var(--brand-copper-dark);
  font-size: var(--text-xs);
  font-weight: 900;
}
.activity-rank.is-top {
  background: var(--brand-copper-dark);
  color: var(--color-text-inverse);
}
.activity-value {
  color: var(--color-text-primary);
  font-size: var(--text-caption);
  text-align: right;
}
.activity-value strong {
  display: block;
}
.activity-empty {
  margin: var(--space-4);
}
.chart-tone-1 { background: var(--color-success); }
.chart-tone-2 { background: var(--brand-copper); }
.chart-tone-3 { background: #9aa0a6; }
.chart-tone-4 { background: #5f876f; }
.chart-tone-5 { background: var(--brand-copper-dark); }
.chart-tone-6 { background: #c4c7ca; }
.activity-track > .chart-tone-1 { background: var(--color-success); }
.activity-track > .chart-tone-2 { background: var(--brand-copper); }
.activity-track > .chart-tone-3 { background: #9aa0a6; }
.activity-track > .chart-tone-4 { background: #5f876f; }
.activity-track > .chart-tone-5 { background: var(--brand-copper-dark); }
.activity-track > .chart-tone-6 { background: #c4c7ca; }
.low-stock-tone-green { background: var(--color-success) !important; }
.low-stock-tone-orange { background: var(--brand-copper) !important; }
.low-stock-tone-silver { background: #9aa0a6 !important; }
.low-stock-category-chart .bar-row {
  border-radius: var(--radius-sm);
  color: var(--brand-charcoal);
  padding: 0.45rem 0.55rem;
  text-decoration: none;
}
.low-stock-category-chart .bar-row:hover {
  background: var(--brand-cream);
}
details > summary {
  cursor: pointer;
  list-style: none;
}
details > summary::-webkit-details-marker {
  display: none;
}
.table-wrap {
  overflow-x: auto;
}
.suppliers-layout,
.supplier-table-panel {
  min-width: 0;
}
.supplier-table-wrap {
  max-width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.supplier-table-wrap .striped-table {
  min-width: 44rem;
}
table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-body);
  font-variant-numeric: tabular-nums; /* ui-audit g3: digits line up down every column */
}
th,
td {
  border-bottom: 1px solid var(--color-border);
  padding: 0.7rem;
  text-align: left;
}
th {
  color: var(--color-text-muted);
  font-weight: 700;
}
tbody tr:hover {
  background: var(--color-surface-muted);
}
/* ui-audit g5: figures line up down a column in every table, and a column
   marked .num sits on the right like the report tables do. */
td {
  font-variant-numeric: tabular-nums;
}
th.num,
td.num {
  text-align: right;
}
.weekly-roster {
  margin-bottom: var(--space-6);
  overflow-x: auto;
  border: 1px solid #b9d2ea;
  border-radius: var(--radius-md);
  background: #fbfdff;
  padding: 0.6rem;
  box-shadow: var(--elevation-2);
}
.weekly-roster-title {
  border-radius: var(--radius-sm);
  background: var(--brand-navy);
  color: var(--color-text-inverse);
  padding: 0.8rem var(--space-4);
  text-align: center;
  font-size: clamp(1.3rem, 3vw, 2.4rem);
  font-weight: 900;
  letter-spacing: 0;
}
.weekly-roster-grid {
  display: grid;
  grid-template-columns: minmax(130px, 0.9fr) repeat(7, minmax(105px, 1fr));
  margin-top: 0.45rem;
  overflow: hidden;
  border: 1px solid #d8e4f2;
  border-radius: var(--radius-sm);
}
.roster-head,
.staff-cell,
.shift-cell {
  min-height: 4.6rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border-right: 2px solid white;
  border-bottom: 2px solid white;
  padding: 0.45rem;
  text-align: center;
  font-weight: 900;
}
.staff-head {
  background: var(--brand-navy);
  color: var(--color-text-inverse);
  font-size: var(--text-h3);
}
.staff-cell {
  background: #eaf2fe;
  color: var(--brand-navy);
  font-size: var(--text-h4);
}
.shift-cell {
  background: #f8fbff;
  color: #111;
  font-size: var(--text-h4);
}
.shift-cell.off {
  background: #fff0f3;
  color: #e00012;
}
.off-days-panel,
.shift-key-panel {
  display: grid;
  grid-template-columns: repeat(7, minmax(105px, 1fr));
  gap: 0;
  margin-top: 0.8rem;
  overflow: hidden;
  border: 1px solid #b9d2ea;
  border-radius: 0.65rem;
  background: var(--color-surface);
}
.off-title,
.shift-key-title {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--brand-navy);
  color: var(--color-text-inverse);
  padding: 0.7rem;
  font-weight: 900;
}
.off-title {
  grid-column: 1 / -1;
  justify-content: flex-start;
}
.off-day {
  min-height: 4.8rem;
  display: grid;
  align-content: center;
  gap: var(--space-1);
  border-right: 1px solid #b9d2ea;
  padding: 0.55rem;
  text-align: center;
  font-weight: 800;
}
.shift-key-panel {
  grid-template-columns: 180px repeat(5, minmax(120px, 1fr));
}
.shift-key-title {
  grid-row: 1;
}
.shift-key-item {
  display: grid;
  align-content: center;
  min-height: 5rem;
  margin: var(--space-2);
  border-radius: var(--radius-sm);
  background: var(--key-color);
  text-align: center;
}
.shift-key-item strong {
  font-size: 1.1rem;
}
.shift-key-item span {
  font-size: var(--text-sm);
  font-weight: 800;
}
.off-key {
  --key-color: #ffe0e9;
  color: #e00012;
}
.app-shell {
  background: transparent;
}
.app-content {
  width: 100%;
  /* ui-audit g2: a long unbroken string (an invoice number, an e-mail, a
     pasted URL in a note) wraps instead of widening the page on a phone.
     break-word only splits a word that would otherwise overflow. */
  overflow-wrap: break-word;
}
.page-head,
.panel-head,
.page-actions,
.quick-action-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
}
.page-head {
  flex-wrap: wrap;
}
.page-actions,
.quick-action-row {
  flex-wrap: wrap;
  justify-content: flex-end;
}

/* Page-head content pattern (Phase 1 UI foundations). Sits inside the
   existing .page-head flex row above: a title + one-sentence subtitle on
   the left (.page-head-text), actions on the right (.page-head-actions).
   Keep it calm -- at most one .btn-primary among the actions. */
.page-head-text {
  min-width: 0;
}
.page-head-text .page-subtitle {
  max-width: 40rem;
}
.page-head-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
  justify-content: flex-end;
}
@media (max-width: 900px) {
  .page-head-actions {
    width: 100%;
  }
  .page-head-actions .btn-primary,
  .page-head-actions .btn-secondary {
    width: 100%;
  }
}

/* Shared drawer (Phase 1 UI foundations, static/operations/ops-drawer.js).
   Native <dialog>-based sheet: right side on desktop, bottom on mobile.
   The script only opens/closes it and does small DOM conveniences (title
   swap, field prefill, reset) -- forms inside stay plain POST + redirect,
   never AJAX. See the <noscript> reveal rules near the bottom of this file
   for the no-JS fallback (data-drawer-noscript="reveal"). */
dialog.ops-drawer {
  position: fixed;
  inset: 0 0 0 auto;
  height: 100%;
  height: 100dvh;
  width: min(28rem, 92vw);
  max-width: none;
  max-height: none;
  margin: 0;
  border: 0;
  border-left: 1px solid var(--brand-line);
  box-shadow: var(--elevation-4-side);
  background: var(--color-surface);
  color: var(--color-text-primary);
  display: flex;
  flex-direction: column;
  padding: 0;
  transform: translateX(0);
  transition: transform var(--motion-base) var(--ease-out), opacity var(--motion-base) var(--ease-out);
}
dialog.ops-drawer:not([open]) {
  display: none;
}
dialog.ops-drawer::backdrop {
  background: rgb(0 0 0 / 0.42);
}
/* ui-audit g3: dialogs -- the page behind an open drawer stays put (a wheel
   over the backdrop scrolled it); the reserved gutter stops a width jump. */
html:has(dialog.ops-drawer[open]) {
  overflow: hidden;
  scrollbar-gutter: stable;
}
@starting-style {
  dialog.ops-drawer[open] {
    transform: translateX(100%);
    opacity: 0;
  }
}
.ops-drawer-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
  border-bottom: 1px solid var(--brand-line);
  padding: var(--space-4) 1.1rem;
}
.ops-drawer-title {
  font-size: 1.15rem;
  font-weight: 800;
  color: var(--brand-charcoal);
}
.ops-drawer-close {
  border: 0;
  background: transparent;
  color: var(--color-text-muted);
  font-size: 1.2rem;
  line-height: 1;
  padding: var(--space-1) 0.4rem;
}
.ops-drawer-close:hover {
  color: var(--brand-copper-dark);
}
.ops-drawer-body {
  flex: 1;
  overflow-y: auto;
  padding: 1.1rem;
}
@media (max-width: 900px) {
  dialog.ops-drawer {
    inset: auto 0 0 0;
    top: auto;
    width: 100%;
    height: auto;
    max-height: 85vh;
    border-left: 0;
    border-top: 1px solid var(--brand-line);
    border-radius: var(--radius-md) var(--radius-md) var(--radius-none) var(--radius-none);
    box-shadow: var(--elevation-4-up);
    transform: translateY(0);
  }
  @starting-style {
    dialog.ops-drawer[open] {
      transform: translateY(100%);
      opacity: 0;
    }
  }
}

/* ui-audit g2: safe areas. base.html now declares viewport-fit=cover, so on
   a notched phone the page runs edge to edge and env(safe-area-inset-*)
   reports the notch, rounded corners and home bar. Everything that touches
   a screen edge keeps its usual spacing or the inset, whichever is larger:
   the sticky phone header (top + sides), the page gutters in landscape, the
   bottom-sheet drawer, and each sticky bottom save bar (the home bar sat
   over their buttons). Without a notch env() is 0 and nothing moves.
   Prefixed with the body class so it outranks each bar's own padding. */
.ui-serenity .mobile-header {
  padding-top: max(0.75rem, env(safe-area-inset-top));
  padding-left: max(1rem, env(safe-area-inset-left));
  padding-right: max(1rem, env(safe-area-inset-right));
}
/* ui-audit g2: smart sticky header (sidebar.js). Hides on scroll down,
   returns on scroll up; a faint shadow only once the page has moved. The
   transform never changes layout, so nothing below it shifts. The global
   prefers-reduced-motion rule turns the slide into an instant swap. */
.mobile-header {
  transition: transform 220ms cubic-bezier(0.22, 1, 0.36, 1), box-shadow 220ms ease;
}
/* The header's Tailwind z-20 tied with the Weekly Count filter bar, which
   comes later in the page and so painted over it while the two overlapped. */
.ui-serenity .mobile-header {
  z-index: var(--z-header);
}
.mobile-header.is-scrolled {
  box-shadow: 0 6px 18px rgb(40 35 33 / 0.08);
}
.mobile-header.is-hidden {
  transform: translateY(calc(-100% - 1.5rem));
  box-shadow: none;
}
/* The Weekly Count filter bar sticks just under the header while it shows
   and slides up to the top edge when it hides (it is static below 700px). */
.ui-serenity .count-sticky-bar {
  top: var(--ops-header-offset, 0px);
  transition: top 220ms cubic-bezier(0.22, 1, 0.36, 1);
}
@media (max-width: 639px) {
  .ui-serenity .app-content {
    padding-left: max(1rem, env(safe-area-inset-left));
    padding-right: max(1rem, env(safe-area-inset-right));
  }
}
@media (min-width: 640px) and (max-width: 1023px) {
  .ui-serenity .app-content {
    padding-left: max(1.5rem, env(safe-area-inset-left));
    padding-right: max(1.5rem, env(safe-area-inset-right));
  }
}
@media (max-width: 900px) {
  .ui-serenity dialog.ops-drawer .ops-drawer-body {
    padding-bottom: max(1.1rem, env(safe-area-inset-bottom));
  }
}
.ui-serenity .roster-actionbar,
.ui-serenity .editor-savebar {
  padding-bottom: max(0.75rem, env(safe-area-inset-bottom));
}
.ui-serenity .settlement-reconcile {
  padding-bottom: max(0.85rem, env(safe-area-inset-bottom));
}
.ui-serenity .settings-bulk-bar {
  padding-bottom: max(0.8rem, env(safe-area-inset-bottom));
}
.ui-serenity .wastage-submit-bar {
  padding-bottom: max(0.6rem, env(safe-area-inset-bottom));
}

.kpi-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(10.5rem, 1fr));
  gap: var(--space-3);
}
.kpi-tile {
  min-width: 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  padding: var(--space-4);
}
.kpi-tile span,
.kpi-tile small {
  display: block;
  color: var(--color-text-muted);
}
.kpi-tile span {
  font-size: var(--text-sm);
  font-weight: 800;
}
.kpi-tile strong {
  display: block;
  margin-top: 0.35rem;
  color: var(--color-text-primary);
  font-size: 1.45rem;
  line-height: 1.15;
}
.kpi-tile small {
  margin-top: 0.4rem;
  font-size: var(--text-caption);
}
.stat-quiet {
  box-shadow: none;
}
.view-switch {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
}
.view-switch a {
  display: inline-flex;
  min-height: 2.4rem;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-full);
  background: var(--color-surface);
  color: var(--color-text-secondary);
  padding: 0.45rem 0.9rem;
  font-size: var(--text-body);
  font-weight: 800;
}
.view-switch a.active,
.view-switch a:hover {
  border-color: var(--brand-copper-dark);
  background: var(--color-accent-soft);
  color: var(--brand-copper-dark);
}
.filter-bar-inner {
  border: 0;
  background: transparent;
  padding: 0;
  box-shadow: none;
}
.filter-disclosure > summary,
.disclosure-panel > summary,
.form-drawer > summary,
.access-control-block > summary,
.recipe-detail > summary,
.setup-form > summary {
  min-height: 2.4rem;
}
.metric-stack {
  display: grid;
  gap: 0.2rem;
}
.action-queue {
  display: grid;
  gap: var(--space-3);
}
.action-row {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  padding: 0.9rem;
}
.action-row strong,
.action-row small {
  display: block;
}
.action-row small {
  margin-top: 0.2rem;
  color: var(--color-text-muted);
  font-size: var(--text-body-sm);
}
.product-tile-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: 0.8rem;
}
.product-tile {
  min-height: 9rem;
}
.recipe-detail {
  border-top: 1px solid var(--color-border);
  padding-top: 0.7rem;
}
.setup-form {
  background: var(--color-surface);
}
.setup-form[open] {
  border-color: var(--color-border-strong);
}
.user-summary {
  display: flex;
  min-height: 3.25rem;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
}
.user-summary-main strong,
.user-summary-main small {
  display: block;
}
.user-summary-main small {
  color: var(--color-text-muted);
  font-size: var(--text-body-sm);
}
.user-summary-meta {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 0.45rem;
}
.access-control-block {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: 0.85rem;
}
.ui-serenity {
  background: var(--color-background);
  /* Figtree for the interface, the same face the till uses; falls back to
     the system stack when the font request fails. Page titles switch to the
     display serif in analytics.css. */
  font-family: var(--font-ui);
}
.ui-serenity .panel,
.ui-serenity .stat,
.ui-serenity .kpi-tile,
.ui-serenity .record-card,
.ui-serenity .permission-check,
.ui-serenity .toggle-row {
  box-shadow: none;
}
.ui-serenity .panel,
.ui-serenity .stat,
.ui-serenity .kpi-tile {
  border-color: #ebe4dc;
}
.ui-serenity .stat-quiet,
.ui-serenity .kpi-tile {
  background: var(--color-surface-warm);
}
.ui-serenity .metric-line:nth-child(odd),
.ui-serenity .metric-line:nth-child(even),
.ui-serenity .inventory-line:nth-child(odd),
.ui-serenity .inventory-line:nth-child(even),
.ui-serenity .striped-table tbody tr:nth-child(odd),
.ui-serenity .striped-table tbody tr:nth-child(even) {
  background: transparent;
}
.ui-serenity .page-title {
  color: var(--brand-charcoal);
}
.ui-serenity .page-subtitle {
  max-width: 44rem;
}
.ui-serenity .disclosure-panel,
.ui-serenity .filter-disclosure,
.ui-serenity .form-drawer {
  background: var(--color-surface-warm);
}
.ui-serenity .soft-band {
  border-color: #ebe4dc;
  background: var(--color-background);
}

@media (max-width: 900px) {
  .dashboard-chart-grid {
    grid-template-columns: 1fr;
  }
  .page-head,
  .panel-head,
  .page-actions,
  .quick-action-row,
  .user-summary {
    align-items: flex-start;
    flex-direction: column;
  }
  .page-actions,
  .quick-action-row {
    width: 100%;
  }
  .page-actions .btn-primary,
  .page-actions .btn-secondary,
  .quick-action-row .btn-secondary {
    width: 100%;
  }
  .kpi-strip {
    grid-template-columns: 1fr;
  }
  .product-tile-grid {
    grid-template-columns: 1fr;
  }
  .user-summary-meta {
    justify-content: flex-start;
  }
  .inventory-line {
    grid-template-columns: 1fr;
  }
  .inventory-line-metrics {
    grid-template-columns: 1fr;
    text-align: left;
  }
  .bar-row,
  .bar-row.compact {
    grid-template-columns: 1fr;
  }
  .bar-value {
    justify-self: start;
    text-align: left;
  }
}

/* ui-audit g4: page transitions. Back-office pages cross-fade into each
   other (browser-native, Chrome/Edge; others just navigate as before). The
   sidebar and phone header are named so they hold still instead of fading.
   Short enough never to feel like waiting; off for reduced motion. The POS
   does not load this file, so the till never animates between screens. */
@media (prefers-reduced-motion: no-preference) {
  @view-transition {
    navigation: auto;
  }
  ::view-transition-old(root),
  ::view-transition-new(root) {
    animation-duration: var(--motion-fast);
  }
  .app-sidebar {
    view-transition-name: app-sidebar;
  }
  .mobile-header {
    view-transition-name: app-mobile-header;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
    transition-duration: 0.01ms !important;
  }
}

/* Weekly inventory count: touch-first, quiet, and deliberately separate from setup. */
.inventory-nav {
  display: flex;
  gap: 0.4rem;
  overflow-x: auto;
  padding-bottom: 0.2rem;
}
.inventory-nav a {
  flex: 0 0 auto;
  min-height: 2.6rem;
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-full);
  background: var(--color-surface);
  color: var(--color-text-secondary);
  padding: var(--space-2) 0.9rem;
  font-size: var(--text-body);
  font-weight: 800;
}
.inventory-nav a.active,
.inventory-nav a:hover {
  border-color: var(--brand-copper-dark);
  background: var(--color-accent-soft);
  color: var(--brand-copper-dark);
}
.count-start {
  display: flex;
  align-items: end;
  gap: 0.6rem;
}
.count-start label {
  display: grid;
  gap: var(--space-1);
  color: var(--color-text-secondary);
  font-size: var(--text-sm);
  font-weight: 800;
}
.count-start input {
  min-height: 2.7rem;
}
.count-session-list,
.count-row-list,
.count-groups,
.reorder-list {
  display: grid;
  gap: var(--space-3);
}
.count-session-card,
.reorder-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: 0.6rem;
  background: var(--color-surface);
  padding: 0.9rem;
}
.count-session-card strong,
.count-session-card small,
.reorder-row strong,
.reorder-row small,
.metric-label {
  display: block;
}
.count-session-card small,
.reorder-row small,
.metric-label {
  margin-top: 0.18rem;
  color: var(--color-text-muted);
  font-size: var(--text-caption);
}
.count-status-approved {
  background: var(--brand-success-bg);
  color: var(--brand-success-text);
}
.count-status-open {
  background: #edf8f0;
  color: var(--color-success);
}
.count-status-submitted {
  background: var(--color-warning-soft);
  color: var(--color-warning);
}
.count-status-cancelled {
  background: var(--color-surface-sunken);
  color: var(--color-text-muted);
}
.count-callout {
  border-color: #f3d38a;
  background: var(--color-warning-soft);
}
.count-progress {
  display: grid;
  grid-template-columns: auto minmax(8rem, 1fr) auto;
  align-items: center;
  gap: var(--space-4);
}
.count-progress strong,
.count-progress span {
  display: block;
}
.count-progress > div:first-child span {
  color: var(--color-text-muted);
  font-size: var(--text-caption);
}
.count-progress-track {
  height: 0.75rem;
  overflow: hidden;
  border-radius: var(--radius-full);
  background: var(--stone-200);
}
.count-progress-track span {
  height: 100%;
  border-radius: inherit;
  background: var(--brand-copper-dark);
  /* ui-audit g4: the bar glides as each count saves instead of jumping. */
  transition: width var(--motion-slow) var(--ease-out);
}
.count-row {
  border: 1px solid var(--color-border);
  border-radius: 0.65rem;
  background: var(--color-surface);
  padding: 0.8rem;
}
.count-entry-form {
  display: grid;
  gap: var(--space-3);
}
.count-entry-toolbar {
  position: sticky;
  top: 0.75rem;
  z-index: var(--z-sticky);
  display: grid;
  grid-template-columns: minmax(14rem, 20rem) 1fr auto;
  align-items: end;
  gap: var(--space-3);
  padding: 0.8rem;
  border: 1px solid var(--color-border);
  border-radius: 0.65rem;
  background: rgba(255, 255, 255, 0.96);
  box-shadow: var(--elevation-2);
}
.count-filter-label {
  display: grid;
  gap: 0.3rem;
  color: var(--color-text-secondary);
  font-size: var(--text-sm);
  font-weight: 800;
}
.count-filter-label input {
  min-height: 2.7rem;
}
.count-entry-help {
  margin: 0;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}
.count-entry-footer {
  display: flex;
  justify-content: flex-end;
}
.count-entry-form .count-row {
  display: grid;
  grid-template-columns: minmax(12rem, 1fr) minmax(12rem, 16rem);
  align-items: end;
  gap: 0.8rem;
}
.count-row.is-missing {
  border-left: 4px solid #d7a043;
}
.count-row.has-warning {
  border-color: #f3d38a;
  background: var(--color-warning-soft);
}
.count-row form {
  display: grid;
  grid-template-columns: minmax(12rem, 1fr) minmax(12rem, 16rem) auto;
  align-items: end;
  gap: 0.8rem;
}
.count-field-error {
  grid-column: 2;
  margin: 0;
  color: var(--color-danger);
  font-size: var(--text-sm);
  font-weight: 700;
}
.count-item strong,
.count-item small {
  display: block;
}
.count-item small {
  margin-top: 0.22rem;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}
.count-input-label {
  display: grid;
  gap: 0.3rem;
  color: var(--color-text-secondary);
  font-size: var(--text-sm);
  font-weight: 800;
}
.count-input-wrap {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  border: 2px solid var(--stone-400);
  border-radius: 0.6rem;
  background: var(--color-surface);
  padding-right: var(--space-3);
}
.count-number-input {
  min-height: 3.5rem;
  border: 0;
  font-size: var(--text-h2);
  font-weight: 850;
}
.count-number-input:focus {
  outline: 3px solid var(--focus-ring);
  outline-offset: 2px;
}
.count-review-row {
  display: grid;
  grid-template-columns: minmax(12rem, 1fr) repeat(3, minmax(8rem, auto));
  align-items: center;
  gap: var(--space-4);
}
.count-review-row small {
  display: block;
  color: var(--color-text-muted);
}
.count-warning {
  grid-column: 1 / -1;
  color: var(--color-warning);
  font-size: var(--text-sm);
  font-weight: 800;
}
.count-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--space-3);
}
.count-actions form {
  display: flex;
  flex-wrap: wrap;
  gap: 0.55rem;
}
.count-actions button:disabled {
  cursor: not-allowed;
  opacity: 0.5;
}
.reorder-row {
  display: grid;
  grid-template-columns: minmax(12rem, 1fr) minmax(8rem, auto) minmax(8rem, auto);
}
/* Reorder setup grid: reuses the count-workbook sticky bar/table shell; the
   two editable columns just need compact spreadsheet-style inputs. */
.reorder-grid .count-workbook-table table {
  min-width: 52rem;
}
.reorder-input-cell {
  min-width: 8.5rem;
}
.reorder-input-cell .count-number-input {
  min-height: 2.6rem;
  max-width: 7.5rem;
  border: 1px solid var(--stone-400);
  border-radius: var(--radius-xs);
  padding: 0.35rem var(--space-2);
  font-size: var(--text-body-lg);
}
.reorder-input-cell .count-field-error {
  display: block;
  margin-top: 0.3rem;
}

/* O1 (D12): the reorder grid grouped by usual supplier. One block per
   supplier: a head with the name, the owner's ordering notes and the
   Copy / WhatsApp actions, the same workbook table underneath, and a
   collapsed "Order text" box holding the plain message. The Order column
   is a tick box + a packs/units box + the unit words. Reuses the workbook,
   button and badge tokens; no new colour family. */
.reorder-supplier {
  margin-top: var(--space-5);
  padding-top: var(--space-4);
  border-top: 1px solid var(--brand-line);
}
.reorder-supplier:first-of-type {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}
.reorder-supplier-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3) var(--space-4);
  margin-bottom: var(--space-3);
}
.reorder-supplier-who {
  flex: 1 1 16rem;
  min-width: 0;
}
.reorder-supplier-name {
  margin: 0;
  font-size: 1.1rem;
  font-weight: 800;
  color: var(--brand-charcoal);
}
.reorder-supplier-notes {
  margin: var(--space-1) 0 0;
  color: var(--color-text-secondary);
  font-size: var(--text-body);
}
.reorder-supplier-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}
.reorder-supplier-actions .btn-primary[aria-disabled="true"] {
  opacity: 0.55;
  pointer-events: none;
}
.reorder-supplier-nowhatsapp {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}
.reorder-order-cell {
  min-width: 13rem;
  white-space: nowrap;
}
.reorder-order-tick {
  display: inline-flex;
  align-items: center;
  margin-right: 0.35rem;
  vertical-align: middle;
}
.reorder-order-tick input {
  width: 1.25rem;
  height: 1.25rem;
  accent-color: var(--brand-copper-dark);
}
.reorder-order-cell .reorder-order-qty {
  display: inline-block;
  width: 5.5rem;
  min-height: 2.6rem;
  border: 1px solid var(--stone-400);
  border-radius: var(--radius-xs);
  padding: 0.35rem var(--space-2);
  font-size: var(--text-body-lg);
  vertical-align: middle;
}
.reorder-order-unit {
  margin-left: 0.35rem;
  color: var(--color-text-secondary);
  font-size: var(--text-body-sm);
  vertical-align: middle;
}
.reorder-order-text {
  margin-top: 0.6rem;
}
.reorder-order-text summary {
  cursor: pointer;
  color: var(--color-text-secondary);
  font-size: var(--text-body-sm);
  font-weight: 700;
}
.reorder-order-text textarea {
  display: block;
  width: 100%;
  max-width: 34rem;
  margin-top: 0.4rem;
  padding: 0.6rem 0.7rem;
  border: 1px solid var(--brand-line);
  border-radius: var(--radius-sm);
  background: var(--color-background);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--text-body-sm);
  line-height: 1.45;
  resize: vertical;
}
@media (max-width: 640px) {
  .reorder-supplier-actions {
    width: 100%;
  }
  .reorder-supplier-actions .btn-primary,
  .reorder-supplier-actions .btn-secondary {
    flex: 1 1 auto;
  }
}
.count-workbook {
  padding: var(--space-4);
}
.count-workbook-toolbar {
  display: grid;
  grid-template-columns: auto minmax(15rem, 1fr) auto;
  align-items: end;
  gap: 0.6rem var(--space-3);
}
/* The category chips need the toolbar's full width to sit in one neat row
   (the old shared 0.65fr column squeezed all 5 chips into a narrow strip
   next to the search box, forcing an early, cramped wrap). Give the chip
   picker its own full-width row above the search + post-counts row. */
.count-category-control {
  grid-column: 1 / -1;
}
.count-workbook-toolbar label,
.user-picker-row label {
  display: grid;
  gap: 0.3rem;
  color: var(--color-text-secondary);
  font-size: var(--text-sm);
  font-weight: 800;
}
.count-workbook-table {
  max-height: 38rem;
  overflow-y: auto;
  border: 1px solid var(--brand-line);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
}
.count-workbook-table table {
  min-width: 58rem;
}
.count-workbook-table thead th {
  position: sticky;
  top: 0;
  z-index: var(--z-raised-top);
  background: var(--brand-cream);
  color: var(--brand-charcoal);
}
.count-workbook-table td,
.count-workbook-table th {
  padding: 0.7rem var(--space-3);
  vertical-align: middle;
}
.count-workbook-table tbody tr:nth-child(even) {
  background: var(--color-background);
}
.count-workbook-table tbody tr:hover {
  background: var(--color-accent-soft);
}
.count-workbook-input {
  min-width: 9rem;
}
.count-workbook-input .count-number-input {
  min-height: 2.6rem;
  max-width: 8rem;
  border: 1px solid var(--stone-400);
  border-radius: var(--radius-xs);
  padding: 0.35rem var(--space-2);
  font-size: var(--text-body-lg);
}
.count-workbook-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  margin-top: 0.9rem;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

/* Autosaving cells. Each Physical count box carries its own state on the
   wrapper (data-state on .count-cell): "" untouched, dirty (typed, not sent
   yet), saving, saved, conflict (somebody else wrote this line first), error.
   The state is drawn by the box border and a small mark to its right; words
   only appear underneath when the counter needs to do something (conflict,
   blank box, no connection). Nothing about a cell ever becomes a page-level
   banner -- the sheet is 200 rows long and the person is looking at one. */
.count-cell {
  display: grid;
  grid-template-columns: minmax(0, 8rem) 1.25rem;
  align-items: center;
  gap: 0.4rem;
}
.count-cell .count-number-input {
  transition: border-color var(--motion-fast) var(--ease-standard), box-shadow var(--motion-fast) var(--ease-standard);
}
.count-cell-status {
  display: inline-block;
  width: 1.1rem;
  height: 1.1rem;
  border-radius: 50%;
  font-size: var(--text-sm);
  font-weight: 900;
  line-height: 1.1rem;
  text-align: center;
  color: var(--color-text-inverse);
  opacity: 0;
  transition: opacity var(--motion-fast) var(--ease-standard);
}
.count-cell[data-state="dirty"] .count-number-input {
  border-color: var(--stone-400);
  border-style: dashed;
}
.count-cell[data-state="saving"] .count-number-input {
  border-color: var(--brand-copper-dark);
}
.count-cell[data-state="saving"] .count-cell-status {
  opacity: 1;
  background: var(--brand-copper-dark);
  animation: count-cell-pulse 0.9s ease-in-out infinite;
}
.count-cell[data-state="saved"] .count-number-input {
  border-color: var(--green-700);
}
.count-cell[data-state="saved"] .count-cell-status {
  opacity: 1;
  background: var(--green-700);
}
.count-cell[data-state="saved"] .count-cell-status::before {
  content: "\2713";
}
.count-cell[data-state="conflict"] .count-number-input {
  border-color: var(--amber-600);
  background: var(--color-warning-soft);
  box-shadow: 0 0 0 3px var(--amber-200);
}
.count-cell[data-state="conflict"] .count-cell-status {
  opacity: 1;
  background: var(--amber-600);
}
.count-cell[data-state="conflict"] .count-cell-status::before {
  content: "!";
}
.count-cell[data-state="error"] .count-number-input {
  border-color: var(--red-700);
  background: var(--red-50);
}
.count-cell[data-state="error"] .count-cell-status {
  opacity: 1;
  background: var(--red-700);
}
.count-cell[data-state="error"] .count-cell-status::before {
  content: "\00d7";
}
@keyframes count-cell-pulse {
  0%, 100% { transform: scale(0.75); opacity: 0.55; }
  50% { transform: scale(1); opacity: 1; }
}
.count-cell-note {
  max-width: 16rem;
  margin: 0.35rem 0 0;
  color: var(--color-warning);
  font-size: var(--text-sm);
  font-weight: 600;
  line-height: 1.35;
}
.count-cell[data-state="error"] + .count-cell-note {
  color: var(--color-danger);
}
.count-cell-note-action {
  display: inline;
  padding: 0;
  border: 0;
  line-height: inherit;
  vertical-align: baseline;
  background: none;
  color: inherit;
  font: inherit;
  font-weight: 800;
  text-decoration: underline;
  cursor: pointer;
}
.count-entered-by {
  min-width: 8rem;
  white-space: nowrap;
}
.count-entered-by strong,
.count-entered-by small {
  display: block;
}
.count-entered-by strong {
  font-size: var(--text-body);
}
.count-entered-by small {
  margin-top: 0.15rem;
  color: var(--color-text-muted);
  font-size: var(--text-caption);
}
.count-entered-by-empty {
  color: var(--color-text-subtle);
  font-size: var(--text-sm);
}
/* The one sheet-wide line: sits where the Post button used to be. */
.count-save-summary {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  align-self: end;
  justify-self: end;
  margin: 0;
  padding: 0.55rem 0.85rem;
  border-radius: var(--radius-full);
  background: var(--brand-success-bg);
  color: var(--brand-success-text);
  font-size: var(--text-sm);
  font-weight: 800;
  white-space: nowrap;
}
.count-save-summary-dot {
  width: 0.55rem;
  height: 0.55rem;
  border-radius: 50%;
  background: currentColor;
}
.count-save-summary[data-state="saving"] {
  background: var(--color-accent-soft);
  color: var(--brand-copper-dark);
}
.count-save-summary[data-state="saving"] .count-save-summary-dot {
  animation: count-cell-pulse 0.9s ease-in-out infinite;
}
.count-save-summary[data-state="attention"] {
  background: var(--amber-100);
  color: var(--color-warning);
}

/* Phase 15 -- Weekly Count soft redesign. Visual only: the count-workbook
   table's rows/columns and the underlying save/post mechanics are untouched.
   Category chips are a progressive enhancement over the existing <select
   data-count-category>: with JS off the select stays visible and simply
   does nothing extra (same baseline as before this phase), and
   inventory-count.js adds .is-enhanced to swap the two over. */
.count-progress-cell {
  display: grid;
  gap: 0.3rem;
  min-width: 9rem;
}
.count-progress-cell span {
  color: var(--color-text-secondary);
  font-size: var(--text-sm);
  font-weight: 700;
}
.count-progress-track-sm {
  height: 0.5rem;
}
.count-progress-compact {
  margin-bottom: var(--space-3);
}
.count-sticky-bar {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  margin: -1rem -1rem 0.9rem;
  padding: var(--space-4) var(--space-4) 0.85rem;
  background: var(--color-surface);
  border-bottom: 1px solid var(--brand-line);
}
.count-category-control {
  display: grid;
  gap: 0.4rem;
}
.count-chip-bar {
  display: none;
  flex-wrap: wrap;
  gap: 0.4rem;
  align-items: center;
}
.count-workbook.is-enhanced .count-select-fallback {
  display: none;
}
.count-workbook.is-enhanced .count-chip-bar {
  display: flex;
}
.count-chip-bar .chip {
  min-height: 2.5rem;
  padding: 0.4rem 0.9rem;
  cursor: pointer;
}
/* Subtle tonal alternation so the chip set reads as one related group rather
   than a flat row of identical pills -- reuses the existing cream/line
   tokens, no new colour family. The active chip overrides both the odd and
   even tone with the shared brand-copper "active" treatment (already used
   by .chip.active elsewhere) so it never reads as "just the even one". */
.count-chip-bar .chip:nth-child(even) {
  background: var(--brand-cream);
  border-color: var(--brand-line);
}
.count-chip-bar .chip.active,
.count-chip-bar .chip[aria-pressed="true"] {
  background: var(--color-accent-soft);
  border-color: var(--brand-copper-dark);
  color: var(--brand-copper-dark);
}
.count-chip-counter {
  margin-left: 0.4rem;
  font-weight: 800;
  font-size: var(--text-sm);
  opacity: 0.75;
}
.count-group-row td {
  position: sticky;
  top: 2.7rem;
  z-index: var(--z-raised);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-2) var(--space-3);
  background: var(--color-surface-sunken);
  color: var(--brand-charcoal);
  font-size: var(--text-sm);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}
.count-group-count {
  color: var(--color-text-muted);
  font-weight: 700;
  text-transform: none;
  letter-spacing: 0;
}
.count-variance-cell {
  display: grid;
  gap: 0.3rem;
  justify-items: start;
}
.variance-pill {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.1rem;
  border-radius: var(--radius-sm);
  padding: 0.3rem 0.6rem;
  font-size: var(--text-body);
  font-weight: 800;
  line-height: 1.15;
  background: var(--color-surface-sunken);
  color: var(--color-text-secondary);
}
.variance-pill small {
  font-size: var(--text-xs);
  font-weight: 700;
  opacity: 0.85;
}
.variance-pill.is-short {
  background: var(--red-100);
  color: var(--color-danger-strong);
}
.variance-pill.is-over {
  background: var(--amber-100);
  color: var(--color-warning);
}
.variance-pill.is-zero {
  background: var(--brand-success-bg);
  color: var(--brand-success-text);
}
@media (max-width: 900px) {
  .count-sticky-bar {
    margin: -1rem -1rem var(--space-3);
    padding: 0.9rem var(--space-4) var(--space-3);
  }
  .count-chip-bar .chip {
    min-height: 2.75rem;
    font-size: var(--text-body);
  }
  .count-workbook-table {
    max-height: 62vh;
  }
  .count-group-row td {
    top: 3.6rem;
  }
}
/* ui-audit g2: Weekly Count on a phone. The sheet was a 58rem-wide table in
   a 62vh inner scroller under a sticky filter bar 578px tall: at 360px the
   counter saw a sliver of rows and had to scroll sideways to reach the
   count box. Below 700px each line becomes a card -- item and unit on the
   left, the count box on the right under the thumb, the rest in a small
   row beneath -- and the page scrolls as one. CSS only: rows, inputs and
   every data-* hook inventory-count.js uses are untouched, and row.hidden
   still wins through the global [hidden] rule. Scoped to the live
   (autosave) sheet; the read-only closed sheet keeps its table. */
@media (max-width: 700px) {
  [data-count-autosave] .count-sticky-bar {
    position: static;
  }
  [data-count-autosave] .count-chip-bar {
    flex-wrap: nowrap;
    overflow-x: auto;
    margin: 0 -1rem;
    padding: 0 1rem 0.25rem;
    scrollbar-width: none;
  }
  [data-count-autosave] .count-chip-bar .chip {
    flex: none;
  }
  [data-count-autosave] .count-workbook-table {
    max-height: none;
    overflow: visible;
    border: 0;
    background: transparent;
  }
  [data-count-autosave] .count-workbook-table table,
  [data-count-autosave] .count-workbook-table tbody {
    display: block;
    min-width: 0;
    width: 100%;
  }
  [data-count-autosave] .count-workbook-table thead {
    display: none;
  }
  [data-count-autosave] .count-group-row {
    display: block;
  }
  [data-count-autosave] .count-group-row td {
    top: 0;
    border-radius: 0.4rem;
  }
  [data-count-autosave] tr[data-count-row] {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 0.35rem 0.75rem;
    align-items: center;
    padding: 0.75rem 0.25rem;
    border-bottom: 1px solid var(--brand-line);
    background: transparent;
  }
  [data-count-autosave] tr[data-count-row] > td {
    display: block;
    padding: 0;
    border: 0;
  }
  /* The category badge repeats the group header just above it. */
  [data-count-autosave] tr[data-count-row] > td:first-child {
    display: none;
  }
  [data-count-autosave] tr[data-count-row] > td:nth-child(2) {
    grid-column: 1;
    grid-row: 1;
  }
  [data-count-autosave] tr[data-count-row] > td:nth-child(3) {
    grid-column: 1;
    grid-row: 2;
    color: #78716c;
    font-size: 0.82rem;
  }
  [data-count-autosave] tr[data-count-row] > .count-workbook-input {
    grid-column: 2;
    grid-row: 1 / span 2;
    min-width: 0;
  }
  [data-count-autosave] .count-workbook-input .count-number-input {
    width: 7.5rem;
    max-width: 7.5rem;
    min-height: 3rem;
    font-size: 1.25rem;
  }
  /* Entered by + stock before on one line, variance + reorder on the next. */
  [data-count-autosave] tr[data-count-row] > td:nth-child(n + 5) {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.35rem;
    font-size: 0.82rem;
  }
  [data-count-autosave] tr[data-count-row] > td:nth-child(5),
  [data-count-autosave] tr[data-count-row] > td:nth-child(7) {
    grid-column: 1;
  }
  [data-count-autosave] tr[data-count-row] > td:nth-child(6),
  [data-count-autosave] tr[data-count-row] > td:nth-child(8) {
    grid-column: 2;
    justify-content: flex-end;
    text-align: right;
  }
  [data-count-autosave] tr[data-count-row] > td[data-label]::before {
    content: attr(data-label);
    color: #78716c;
    font-size: 0.72rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.04em;
  }
  [data-count-autosave] .count-entered-by strong,
  [data-count-autosave] .count-entered-by small {
    display: inline;
    margin: 0;
  }
}

.user-picker-row {
  display: grid;
  grid-template-columns: minmax(13rem, 0.8fr) minmax(18rem, 1.2fr) auto;
  align-items: end;
  gap: var(--space-3);
}
.dashboard-activity-grid {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: minmax(18rem, 0.82fr) minmax(30rem, 1.35fr);
}
.staff-activity-list {
  display: grid;
  gap: 0.2rem;
}
.staff-activity-row {
  align-items: center;
  border-bottom: 1px solid var(--color-border);
  display: grid;
  gap: 0.7rem;
  grid-template-columns: 2rem minmax(8rem, 1fr) minmax(4.3rem, auto) minmax(4.3rem, auto);
  min-height: 3.35rem;
  padding: 0.45rem 0.1rem;
}
.staff-activity-row:last-child {
  border-bottom: 0;
}
.staff-activity-avatar {
  align-items: center;
  background: var(--color-success);
  border-radius: var(--radius-full);
  color: var(--color-text-inverse);
  display: inline-flex;
  font-size: var(--text-sm);
  font-weight: 900;
  height: 2rem;
  justify-content: center;
  width: 2rem;
}
.staff-activity-person,
.staff-activity-metric {
  display: grid;
  line-height: 1.2;
}
.staff-activity-person small,
.staff-activity-metric small {
  color: var(--color-text-muted);
  font-size: var(--text-xs);
  margin-top: 0.18rem;
}
.staff-activity-metric {
  min-width: 4.3rem;
  text-align: right;
}
.staff-activity-metric strong {
  color: var(--color-text-primary);
  font-size: var(--text-body-lg);
}
.weekly-hour-chart {
  min-height: 15rem;
  overflow-x: auto;
}
.weekly-hour-chart svg {
  display: block;
  min-width: 42rem;
  width: 100%;
}
.weekly-hour-grid line {
  stroke: #dedbd7;
  stroke-dasharray: 4 5;
  stroke-width: 1;
}
.weekly-hour-y-labels text {
  fill: var(--stone-500);
  font-size: 10px;
  text-anchor: end;
}
.weekly-hour-line {
  fill: none;
  stroke: var(--forest-700);
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-width: 4;
}
.weekly-hour-point {
  fill: var(--brand-copper);
  stroke: var(--white);
  stroke-width: 3;
  transition: fill var(--motion-fast) var(--ease-standard), r var(--motion-fast) var(--ease-standard);
}
.weekly-hour-point-link:hover .weekly-hour-point,
.weekly-hour-point-link:focus .weekly-hour-point {
  fill: var(--brand-copper-dark);
  r: 9px;
}
.weekly-hour-point-link:focus {
  outline: none;
}
.weekly-hour-point-label {
  fill: var(--forest-700);
  font-size: 10px;
  font-weight: 800;
  text-anchor: middle;
}
.weekly-hour-x-label {
  fill: var(--stone-600);
  font-size: 11px;
  font-weight: 700;
  text-anchor: middle;
}
.weekly-hour-empty-point {
  fill: #c4c7ca;
}
.daily-sales-summary {
  display: grid;
  gap: var(--space-3);
  grid-template-columns: repeat(2, minmax(9rem, 1fr));
}
.daily-sales-summary > div {
  background: #f7f6f4;
  border: 1px solid var(--color-border);
  border-radius: 0.65rem;
  display: grid;
  gap: 0.15rem;
  padding: 0.8rem var(--space-4);
}
.daily-sales-summary span {
  color: var(--color-text-muted);
  font-size: var(--text-caption);
}
.daily-sales-summary strong {
  color: var(--color-success);
  font-size: 1.15rem;
}

@media (max-width: 700px) {
  .dashboard-activity-grid {
    grid-template-columns: 1fr;
  }
  .activity-segments {
    margin-top: var(--space-6);
  }
  .activity-row {
    grid-template-columns: minmax(0, 1fr) auto;
  }
  .activity-row > .activity-track {
    grid-column: 1 / -1;
    grid-row: 2;
  }
  .activity-row-ranked {
    grid-template-columns: 1.8rem minmax(0, 1fr) auto;
  }
  .activity-row-ranked > .activity-product {
    grid-column: 2;
  }
  .activity-row-ranked > .activity-value {
    grid-column: 3;
  }
  .count-start,
  .count-progress,
  .count-workbook-toolbar,
  .user-picker-row,
  .count-row form,
  .count-entry-form .count-row,
  .count-review-row,
  .reorder-row {
    width: 100%;
    grid-template-columns: 1fr;
  }
  .count-start {
    display: grid;
  }
  .count-workbook-footer {
    align-items: stretch;
    flex-direction: column;
  }
  .count-entry-toolbar {
    position: static;
    grid-template-columns: 1fr;
  }
  .count-start .btn-primary,
  .count-save-button {
    min-height: 3.25rem;
    width: 100%;
  }
  .count-number-input {
    min-height: 4rem;
    font-size: 1.75rem;
  }
  .count-session-card {
    align-items: flex-start;
  }
  .staff-activity-row {
    gap: 0.45rem;
    grid-template-columns: 1.8rem minmax(6.5rem, 1fr) minmax(3.4rem, auto) minmax(3.4rem, auto);
  }
  .staff-activity-avatar {
    height: 1.8rem;
    width: 1.8rem;
  }
  .staff-activity-metric {
    min-width: 3.4rem;
  }
  .daily-sales-summary {
    grid-template-columns: 1fr;
  }
}

/* Reference-style dashboard and reporting visuals ------------------------- */
.ops-dashboard {
  display: grid;
  gap: var(--space-5);
}
.ops-dash-topbar {
  align-items: center;
  border-bottom: 1px solid #e8e3dd;
  display: flex;
  gap: var(--space-4);
  justify-content: space-between;
  padding-bottom: var(--space-4);
}
.ops-dash-actions {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: 0.65rem;
  justify-content: flex-end;
}
.compact-action {
  min-height: 2.25rem;
  padding: 0.45rem 0.85rem;
}
.metric-card-grid {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
}
.metric-icon {
  align-items: center;
  background: #fff0ea;
  border-radius: var(--radius-sm);
  color: var(--brand-copper-dark);
  display: inline-flex;
  flex: 0 0 2rem;
  font-size: var(--text-caption);
  font-weight: 950;
  height: 2rem;
  justify-content: center;
}
.dashboard-reference-grid,
.report-visual-grid {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: minmax(0, 1fr) minmax(18rem, 0.34fr);
}
.dashboard-main-stack,
.dashboard-side-stack {
  display: grid;
  gap: var(--space-4);
  min-width: 0;
}
.visual-select {
  border: 1px solid #dfd9d3;
  border-radius: var(--radius-xs);
  color: #5f5852;
  flex: 0 0 auto;
  font-size: var(--text-xs);
  font-weight: 800;
  padding: 0.35rem 0.55rem;
}
.dot-menu {
  color: #9b948e;
  letter-spacing: 0.12em;
}
.revenue-trend-panel {
  min-height: 23rem;
}
.performance-gauge-panel {
  min-height: 18rem;
}
.gauge-visual {
  height: 10.8rem;
  margin-top: var(--space-2);
  position: relative;
}
.gauge-arc {
  border: 0.74rem solid transparent;
  border-radius: var(--radius-full) var(--radius-full) var(--radius-none) var(--radius-none);
  border-bottom: 0;
  height: 5.4rem;
  left: 50%;
  position: absolute;
  top: 1rem;
  transform: translateX(-50%);
  width: 10.8rem;
}
.gauge-arc-base {
  border-color: #eeecea;
}
.gauge-arc-main {
  border-color: #6c4b43;
  clip-path: polygon(0 0, 76% 0, 76% 100%, 0 100%);
}
.gauge-arc-secondary {
  border-color: #f2bd3d;
  height: 3.95rem;
  top: 2.35rem;
  width: 7.9rem;
}
.gauge-center {
  display: grid;
  left: 0;
  place-items: center;
  position: absolute;
  right: 0;
  text-align: center;
  top: 5.7rem;
}
.gauge-center strong {
  color: #2f2b29;
  font-size: var(--text-body-lg);
  font-weight: 950;
}
.gauge-center span {
  color: #5f5852;
  font-size: var(--text-xs);
  font-weight: 800;
}
.gauge-legend {
  align-items: center;
  border-top: 1px solid #efebe7;
  color: #5f5852;
  display: flex;
  font-size: var(--text-xs);
  justify-content: space-between;
  padding-top: 0.7rem;
}
.gauge-legend span {
  align-items: center;
  display: inline-flex;
  gap: 0.35rem;
}
.gauge-legend i {
  background: #2f7562;
  border-radius: var(--radius-full);
  display: inline-block;
  height: 0.42rem;
  width: 0.42rem;
}
.top-selling-panel .rank-row {
  min-height: 3.2rem;
}
.compact-ops-section {
  border-top-color: #e4dfda;
}
.report-visual-grid {
  align-items: start;
}
.report-visual-grid .revenue-trend-panel {
  min-height: 21rem;
}

@media (max-width: 1100px) {
  .dashboard-reference-grid,
  .report-visual-grid {
    grid-template-columns: 1fr;
  }
  .dashboard-side-stack {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 760px) {
  .ops-dash-topbar {
    align-items: flex-start;
    flex-direction: column;
  }
  .dashboard-side-stack {
    grid-template-columns: 1fr;
  }
  .metric-card-grid {
    grid-template-columns: 1fr;
  }
}

/* Open reporting canvas --------------------------------------------------- */
.report-page-head {
  padding-bottom: var(--space-1);
}
.section-kicker {
  color: var(--brand-copper-dark);
  display: block;
  font-size: var(--text-xs);
  font-weight: 900;
  letter-spacing: 0.12em;
  margin-bottom: var(--space-1);
  text-transform: uppercase;
}
.text-action {
  align-items: center;
  color: var(--brand-copper-dark);
  display: inline-flex;
  font-size: var(--text-body-sm);
  font-weight: 850;
  gap: 0.3rem;
  text-decoration: none;
}
.text-action:hover {
  color: #6f3d24;
  text-decoration: underline;
  text-underline-offset: 0.25rem;
}
.source-chip {
  align-items: center;
  background: transparent;
  border: 1px solid #d9d3cc;
  border-radius: var(--radius-full);
  color: var(--color-text-secondary);
  display: inline-flex;
  font-size: var(--text-xs);
  font-weight: 800;
  gap: 0.4rem;
  min-height: 1.85rem;
  padding: var(--space-1) 0.65rem;
  white-space: nowrap;
}
.source-chip i {
  background: var(--stone-400);
  border-radius: var(--radius-full);
  display: block;
  height: 0.42rem;
  width: 0.42rem;
}
.source-chip-good {
  border-color: #bdd1c7;
  color: var(--color-success);
}
.source-chip-good i {
  background: var(--color-success);
}

.scoreboard {
  border-bottom: 1px solid var(--brand-line);
  border-top: 1px solid var(--brand-line);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr));
}
.scoreboard-metric {
  min-width: 0;
  padding: 1.1rem var(--space-4);
}
.scoreboard-metric:first-child {
  padding-left: 0;
}
.scoreboard-metric + .scoreboard-metric {
  border-left: 1px solid var(--brand-line);
}
.scoreboard-metric span,
.scoreboard-metric small {
  color: var(--color-text-muted);
  display: block;
}
.scoreboard-metric span {
  font-size: var(--text-xs);
  font-weight: 850;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.scoreboard-metric strong {
  color: var(--brand-charcoal);
  display: block;
  font-size: clamp(1.25rem, 2.2vw, 1.85rem);
  line-height: 1.08;
  margin-top: 0.45rem;
  overflow-wrap: anywhere;
}
.scoreboard-metric small {
  font-size: var(--text-xs);
  line-height: 1.35;
  margin-top: 0.42rem;
}
.scoreboard-secondary {
  margin-top: var(--space-5);
}
.scoreboard-report {
  margin-top: 1.1rem;
}
.scoreboard-compact {
  grid-template-columns: repeat(2, minmax(9rem, 14rem));
  margin-top: var(--space-4);
}

.report-section {
  border-top: 2px solid var(--brand-charcoal);
  scroll-margin-top: 1rem;
}
.report-section-title {
  color: var(--brand-charcoal);
  font-size: var(--text-h3);
  font-weight: 850;
  line-height: 1.2;
}
.analysis-pane-head p {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  margin-top: 0.22rem;
}
.source-note {
  align-items: flex-start;
  border-bottom: 1px solid var(--brand-line);
  color: var(--color-text-secondary);
  display: flex;
  font-size: var(--text-caption);
  gap: 0.65rem;
  line-height: 1.55;
  padding: 0.85rem 0;
}
.source-note-icon {
  border: 1px solid var(--stone-400);
  border-radius: var(--radius-full);
  display: inline-grid;
  flex: 0 0 auto;
  font-size: var(--text-xs);
  font-weight: 900;
  height: 1.2rem;
  place-items: center;
  width: 1.2rem;
}
.source-note-bottom {
  margin-top: var(--space-4);
}

.analysis-split {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.analysis-pane {
  min-width: 0;
  padding: 0 var(--space-5) 0 0;
}
.analysis-pane + .analysis-pane {
  border-left: 1px solid var(--brand-line);
  padding-left: var(--space-5);
  padding-right: 0;
}
.analysis-pane-head {
  align-items: flex-start;
  display: flex;
  gap: var(--space-4);
  justify-content: space-between;
  margin-bottom: var(--space-4);
}
.analysis-pane-head h2,
.analysis-pane-head h3 {
  color: var(--brand-charcoal);
  font-size: var(--text-body-lg);
  font-weight: 850;
}
.report-section .activity-segments {
  height: 0.48rem;
  margin: 0 0 var(--space-5);
}

.rank-list {
  display: grid;
}
.rank-row {
  align-items: center;
  border-bottom: 1px solid #eee9e3;
  color: inherit;
  display: grid;
  gap: var(--space-3);
  grid-template-columns: minmax(8rem, 1fr) minmax(6rem, 1.25fr) minmax(5.5rem, auto);
  min-height: 3.5rem;
  padding: 0.55rem 0;
  text-decoration: none;
}
.rank-row:last-child {
  border-bottom: 0;
}
a.rank-row:hover .rank-label strong {
  color: var(--brand-copper-dark);
}
.rank-row-product {
  grid-template-columns: 1.7rem minmax(8rem, 1fr) minmax(5rem, 1fr) minmax(6.2rem, auto);
}
.rank-number {
  color: var(--color-text-subtle);
  font-size: var(--text-xs);
  font-weight: 900;
  text-align: center;
}
.rank-label {
  align-items: center;
  display: flex;
  gap: var(--space-2);
  min-width: 0;
}
.rank-label strong,
.rank-label small,
.rank-value strong,
.rank-value small {
  display: block;
}
.rank-label strong {
  color: #3f3a37;
  font-size: var(--text-sm);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rank-label small,
.rank-value small {
  color: #8c8580;
  font-size: var(--text-2xs);
  margin-top: 0.18rem;
}
.rank-track,
.period-bar-track {
  background: #ebe7e2;
  border-radius: var(--radius-full);
  display: block;
  height: 0.38rem;
  overflow: hidden;
}
.rank-track > span,
.period-bar-track > i {
  background: linear-gradient(90deg, var(--color-success), #5f876f);
  border-radius: inherit;
  display: block;
  height: 100%;
  min-width: 0.2rem;
}
.rank-value {
  color: var(--color-text-primary);
  font-size: var(--text-caption);
  text-align: right;
}
.empty-inline {
  padding: var(--space-4) 0;
}

.dashboard-primary-grid {
  display: grid;
  gap: var(--space-7);
  grid-template-columns: minmax(0, 1.8fr) minmax(15rem, 0.8fr);
}

.attention-rail {
  border-left: 1px solid var(--brand-line);
  padding-left: var(--space-5);
}
.attention-head h3 {
  color: var(--brand-charcoal);
  font-size: var(--text-body-lg);
  font-weight: 850;
}
.attention-list {
  margin-top: 0.6rem;
}
.attention-row {
  align-items: center;
  border-bottom: 1px solid #eee9e3;
  color: inherit;
  display: grid;
  gap: 0.65rem;
  grid-template-columns: 0.55rem minmax(0, 1fr) auto;
  min-height: 3.8rem;
  padding: 0.65rem 0;
  text-decoration: none;
}
.attention-row > i {
  background: #9ca3af;
  border-radius: var(--radius-full);
  height: 0.5rem;
  width: 0.5rem;
}
.attention-row strong,
.attention-row small {
  display: block;
}
.attention-row strong {
  color: var(--stone-700);
  font-size: var(--text-caption);
}
.attention-row small {
  color: var(--color-text-muted);
  font-size: var(--text-xs);
  line-height: 1.4;
  margin-top: 0.15rem;
}
.attention-row b {
  color: var(--color-text-subtle);
}
.attention-warning > i { background: var(--brand-copper); }
.attention-danger > i { background: #b64040; }
.attention-setup > i { background: #3e6f88; }
.attention-good > i { background: var(--color-success); }

.operations-ribbon {
  border-bottom: 1px solid var(--brand-line);
  border-top: 1px solid var(--brand-line);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  margin-top: var(--space-7);
}
.operations-ribbon > div {
  align-items: baseline;
  display: flex;
  gap: 0.65rem;
  justify-content: space-between;
  padding: 0.8rem var(--space-4);
}
.operations-ribbon > div:first-child { padding-left: 0; }
.operations-ribbon > div + div { border-left: 1px solid var(--brand-line); }
.operations-ribbon span { color: var(--color-text-muted); font-size: var(--text-xs); }
.operations-ribbon strong { color: var(--brand-charcoal); font-size: var(--text-body-lg); }

.readiness-line {
  align-items: center;
  border-bottom: 1px solid var(--brand-line);
  border-top: 1px solid var(--brand-line);
  display: grid;
  gap: var(--space-4);
  grid-template-columns: minmax(10rem, 1fr) minmax(8rem, 1.4fr) auto;
  padding: var(--space-4) 0;
}
.readiness-line strong,
.readiness-line small { display: block; }
.readiness-line strong { color: var(--stone-700); font-size: var(--text-sm); }
.readiness-line small { color: var(--color-text-muted); font-size: var(--text-xs); margin-top: 0.2rem; }
.readiness-line b { color: var(--color-text-secondary); font-size: var(--text-caption); }
.readiness-track {
  background: var(--stone-200);
  border-radius: var(--radius-full);
  display: block;
  height: 0.45rem;
  overflow: hidden;
}
.readiness-track i {
  background: var(--color-success);
  border-radius: inherit;
  display: block;
  height: 100%;
}
.setup-explainer,
.statement-note {
  color: var(--color-text-muted);
  font-size: var(--text-xs);
  line-height: 1.5;
  margin-top: var(--space-3);
}

.detail-ledger {
  border-top: 2px solid var(--brand-charcoal);
}
.report-disclosure {
  border-bottom: 1px solid var(--brand-line);
}
.report-disclosure > summary {
  align-items: center;
  display: flex;
  justify-content: space-between;
  min-height: 4.8rem;
  padding: var(--space-3) 0;
}
.report-disclosure > summary strong,
.report-disclosure > summary small { display: block; }
.report-disclosure > summary strong { color: var(--brand-charcoal); font-size: 0.95rem; }
.report-disclosure > summary small { color: var(--color-text-muted); font-size: var(--text-xs); margin-top: 0.2rem; }
.report-disclosure > summary > b { color: var(--brand-copper-dark); font-size: var(--text-caption); }
.report-disclosure > summary > b i { font-size: var(--text-body-lg); margin-left: 0.3rem; }
.report-disclosure[open] > summary > b i { display: inline-block; transform: rotate(45deg); }
.disclosure-body { padding: var(--space-2) 0 var(--space-5); }
.disclosure-body h3 { font-size: var(--text-sm); font-weight: 850; margin-bottom: var(--space-2); }

.report-toolbar {
  align-items: flex-end;
  border-bottom: 1px solid var(--brand-line);
  display: flex;
  gap: var(--space-4);
  justify-content: space-between;
  padding: 0.9rem 0;
}
.report-toolbar form {
  align-items: flex-end;
  display: flex;
  flex-wrap: wrap;
  gap: 0.65rem;
}
.report-toolbar label span {
  color: var(--color-text-muted);
  display: block;
  font-size: var(--text-2xs);
  font-weight: 850;
  margin-bottom: 0.2rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.report-toolbar input {
  min-height: 2.35rem;
}
.inline-notice {
  align-items: flex-start;
  border-bottom: 1px solid #d8c5ac;
  display: flex;
  gap: var(--space-3);
  padding: 0.9rem 0;
}
.inline-notice > span {
  border: 1px solid #bf7b2c;
  border-radius: var(--radius-full);
  color: var(--brand-copper-dark);
  display: inline-grid;
  flex: 0 0 auto;
  font-size: var(--text-xs);
  font-weight: 900;
  height: 1.3rem;
  place-items: center;
  width: 1.3rem;
}
.inline-notice strong { color: #6f3d24; display: block; font-size: var(--text-sm); }
.inline-notice p { color: #785b46; font-size: var(--text-xs); line-height: 1.45; margin-top: 0.15rem; }

.metric-viewbar {
  align-items: center;
  border-bottom: 1px solid var(--brand-line);
  display: flex;
  gap: 0.35rem;
  margin-top: var(--space-5);
  padding-bottom: 0.65rem;
}
.metric-viewbar > span { color: var(--color-text-muted); font-size: var(--text-xs); font-weight: 850; margin-right: 0.35rem; text-transform: uppercase; }
.metric-viewbar a {
  border-radius: var(--radius-full);
  color: var(--color-text-muted);
  font-size: var(--text-xs);
  font-weight: 850;
  padding: 0.35rem 0.65rem;
  text-decoration: none;
}
.metric-viewbar a.active,
.metric-viewbar a:hover { background: var(--brand-cream); color: var(--brand-copper-dark); }
.period-performance { padding-top: 0.45rem; }
.period-bar-row {
  align-items: center;
  border-bottom: 1px solid #eee9e3;
  color: inherit;
  display: grid;
  gap: var(--space-4);
  grid-template-columns: minmax(12rem, 0.8fr) minmax(12rem, 1.8fr) minmax(7rem, auto);
  min-height: 4rem;
  text-decoration: none;
}
.period-bar-label strong,
.period-bar-label small { display: block; }
.period-bar-label strong { color: var(--stone-700); font-size: var(--text-sm); }
.period-bar-label small { color: var(--color-text-muted); font-size: var(--text-xs); margin-top: 0.15rem; }
.period-bar-value { color: var(--color-text-primary); font-size: var(--text-sm); font-weight: 850; text-align: right; }
.costing-readiness { margin-top: var(--space-4); }

.statement-grid {
  display: grid;
  gap: var(--space-8);
  grid-template-columns: minmax(0, 1fr) minmax(19rem, 0.8fr);
}
.financial-statement > div {
  align-items: baseline;
  border-bottom: 1px solid var(--brand-line);
  display: flex;
  font-size: var(--text-sm);
  gap: var(--space-4);
  justify-content: space-between;
  padding: 0.8rem 0;
}
.financial-statement span { color: var(--color-text-secondary); }
.financial-statement strong { color: var(--color-text-primary); }
.financial-statement .statement-total {
  border-bottom: 3px double var(--stone-400);
  font-weight: 900;
}
.vat-visual {
  align-items: center;
  border-bottom: 1px solid var(--brand-line);
  border-top: 1px solid var(--brand-line);
  display: grid;
  gap: 0.8rem;
  grid-template-columns: 1fr auto 1fr;
  padding: var(--space-4) 0;
}
.vat-visual span,
.vat-visual strong,
.vat-visual small { display: block; }
.vat-visual span { color: var(--color-text-muted); font-size: var(--text-xs); }
.vat-visual strong { color: var(--color-text-primary); font-size: var(--text-body-lg); margin-top: 0.3rem; }
.vat-visual small { color: #8c8580; font-size: var(--text-2xs); margin-top: var(--space-1); }
.vat-visual .vat-operator { color: var(--color-text-subtle); font-size: 1.2rem; }
.staff-list-wide { max-width: 48rem; }
.report-table table { border-collapse: collapse; width: 100%; }
.report-table th {
  border-bottom: 1px solid #bdb7b1;
  color: var(--color-text-muted);
  font-size: var(--text-2xs);
  font-weight: 850;
  letter-spacing: 0.04em;
  padding: 0.65rem var(--space-2);
  text-align: left;
  text-transform: uppercase;
}
.report-table th.is-num { text-align: right; } /* ui-audit g3: header sits over its right-aligned figures */
.report-table td {
  border-bottom: 1px solid #eee9e3;
  color: var(--stone-700);
  font-size: var(--text-caption);
  padding: var(--space-3) var(--space-2);
}

@media (max-width: 900px) {
  .dashboard-primary-grid,
  .statement-grid {
    grid-template-columns: 1fr;
  }
  .attention-rail {
    border-left: 0;
    border-top: 1px solid var(--brand-line);
    padding-left: 0;
    padding-top: var(--space-4);
  }
  .scoreboard {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .scoreboard-metric:nth-child(odd) {
    border-left: 0;
    padding-left: 0;
  }
  .scoreboard-metric:nth-child(n+3) {
    border-top: 1px solid var(--brand-line);
  }
  .report-toolbar {
    align-items: flex-start;
    flex-direction: column;
  }
}

@media (max-width: 700px) {
  .analysis-split {
    grid-template-columns: 1fr;
  }
  .analysis-pane {
    padding-right: 0;
  }
  .analysis-pane + .analysis-pane {
    border-left: 0;
    border-top: 1px solid var(--brand-line);
    margin-top: var(--space-6);
    padding-left: 0;
    padding-top: var(--space-6);
  }
  .rank-row,
  .rank-row-product {
    grid-template-columns: 1.5rem minmax(0, 1fr) auto;
  }
  .rank-row:not(.rank-row-product) {
    grid-template-columns: minmax(0, 1fr) auto;
  }
  .rank-row .rank-track {
    grid-column: 1 / -1;
    grid-row: 2;
  }
  .rank-row-product .rank-track {
    grid-column: 2 / -1;
  }
  .scoreboard {
    grid-template-columns: 1fr;
  }
  .scoreboard-metric,
  .scoreboard-metric:first-child,
  .scoreboard-metric:nth-child(odd) {
    border-left: 0;
    border-top: 1px solid var(--brand-line);
    padding-left: 0;
  }
  .scoreboard-metric:first-child {
    border-top: 0;
  }
  .operations-ribbon {
    grid-template-columns: 1fr 1fr;
  }
  .operations-ribbon > div:nth-child(odd) {
    border-left: 0;
    padding-left: 0;
  }
  .operations-ribbon > div:nth-child(n+3) {
    border-top: 1px solid var(--brand-line);
  }
  .period-bar-row,
  .readiness-line {
    grid-template-columns: 1fr auto;
    padding: 0.8rem 0;
  }
  .period-bar-track,
  .readiness-track {
    grid-column: 1 / -1;
    grid-row: 2;
  }
  .report-toolbar form,
  .report-toolbar label,
  .report-toolbar input,
  .report-toolbar .btn-primary {
    width: 100%;
  }
}

/* POS analytics dashboard refresh ---------------------------------------- */
.pos-analytics-dashboard,
.reports-dashboard {
  --analytics-line: #dfe5ec;
  --analytics-muted: #68737d;
  --analytics-ink: #20262c;
  --analytics-panel: var(--white);
  --analytics-soft: #f4f7fa;
  --analytics-blue: #2f80ed;
  --analytics-green: #2f7562;
  display: grid;
  gap: 1.15rem;
}
.dashboard-command-bar,
.reports-command-bar {
  align-items: center;
  border-bottom: 1px solid var(--analytics-line);
  display: flex;
  gap: var(--space-4);
  justify-content: space-between;
  padding-bottom: var(--space-4);
}
.reports-command-bar {
  margin-bottom: var(--space-1);
}
.dashboard-status-panel {
  background: linear-gradient(135deg, var(--color-surface) 0%, #f7fafc 100%);
  border-color: var(--analytics-line);
  box-shadow: none;
}
.source-chip--pos {
  border-color: #bad7cc;
  color: #245d4c;
}
.source-chip--pos i {
  background: #2f7562;
}
.kpi-strip {
  background: var(--analytics-panel);
  border: 1px solid var(--analytics-line);
  border-radius: var(--radius-sm);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(10.5rem, 1fr));
  overflow: hidden;
}
.kpi-tile + .kpi-tile {
  border-left: 1px solid var(--analytics-line);
}
.kpi-label,
.kpi-detail {
  display: block;
}
.kpi-label {
  color: var(--analytics-muted);
  font-size: var(--text-xs);
  font-weight: 850;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.kpi-value {
  color: var(--analytics-ink);
  display: block;
  font-size: clamp(1.25rem, 2vw, 1.75rem);
  font-weight: 950;
  line-height: 1.08;
  margin-top: 0.4rem;
  overflow-wrap: anywhere;
}
.kpi-detail {
  color: #7c8790;
  font-size: var(--text-xs);
  line-height: 1.35;
  margin-top: 0.35rem;
}
.dashboard-analytics-grid,
.report-analytics-grid {
  align-items: start;
  display: grid;
  gap: var(--space-4);
  grid-template-columns: minmax(0, 1.7fr) minmax(18rem, 0.8fr);
}
.dashboard-side-stack.insight-rail {
  display: grid;
  gap: var(--space-4);
}
.today-performance-panel {
  min-height: 15rem;
}
.performance-meter-list {
  display: grid;
  gap: 0.9rem;
  margin-top: 0.4rem;
}
.performance-meter-row {
  display: grid;
  gap: 0.45rem;
  grid-template-columns: minmax(0, 1fr) auto;
}
.performance-meter-row span,
.performance-meter-row strong,
.performance-meter-row small,
.performance-meter-row b {
  display: block;
}
.performance-meter-row strong {
  color: var(--analytics-ink);
  font-size: var(--text-sm);
  font-weight: 900;
}
.performance-meter-row small {
  color: var(--analytics-muted);
  font-size: var(--text-xs);
  margin-top: 0.15rem;
}
.performance-meter-row b {
  color: var(--analytics-green);
  font-size: var(--text-sm);
  font-weight: 950;
  text-align: right;
}
.performance-meter-row > i {
  background: #edf1f4;
  border-radius: var(--radius-full);
  display: block;
  grid-column: 1 / -1;
  height: 0.58rem;
  overflow: hidden;
}
.performance-meter-row em {
  background: linear-gradient(90deg, #2f7562, #5fa58e);
  border-radius: inherit;
  display: block;
  height: 100%;
  max-width: 100%;
}
.performance-meter-row-alt em {
  background: linear-gradient(90deg, #f2a83b, #f6c86a);
}
.performance-baseline {
  align-items: baseline;
  border-top: 1px solid var(--analytics-line);
  color: var(--analytics-muted);
  display: flex;
  font-size: var(--text-xs);
  gap: var(--space-3);
  justify-content: space-between;
  margin-top: var(--space-4);
  padding-top: 0.8rem;
}
.performance-baseline strong {
  color: var(--analytics-ink);
  font-weight: 900;
  text-align: right;
}
.compact-rank-list .rank-row-product {
  grid-template-columns: 1.7rem minmax(9rem, 1fr) minmax(6rem, 1fr) minmax(6.2rem, auto);
}
.dashboard-secondary-section {
  margin-top: var(--space-8);
}
.report-overview-shell .source-note {
  border-bottom: 0;
}

@media (max-width: 1100px) {
  .dashboard-analytics-grid,
  .report-analytics-grid {
    grid-template-columns: 1fr;
  }
  .dashboard-side-stack.insight-rail {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 760px) {
  .dashboard-command-bar,
  .reports-command-bar,
  .dashboard-status-panel {
    align-items: flex-start;
    flex-direction: column;
  }
  .dashboard-status-panel {
    display: flex;
  }
  .dashboard-side-stack.insight-rail {
    grid-template-columns: 1fr;
  }
  .kpi-strip {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .kpi-tile + .kpi-tile {
    border-left: 0;
  }
  .kpi-tile:nth-child(even) {
    border-left: 1px solid var(--analytics-line);
  }
  .kpi-tile:nth-child(n+3) {
    border-top: 1px solid var(--analytics-line);
  }
  .performance-baseline {
    align-items: flex-start;
    flex-direction: column;
    gap: var(--space-1);
  }
  .performance-baseline strong {
    text-align: left;
  }
}

@media (max-width: 430px) {
  .kpi-strip {
    grid-template-columns: 1fr;
  }
  .kpi-tile:nth-child(even),
  .kpi-tile:nth-child(n+3) {
    border-left: 0;
    border-top: 1px solid var(--analytics-line);
  }
  .kpi-tile:first-child {
    border-top: 0;
  }
}

/* POS checkout and settlements -------------------------------------------- */
.receipt-head {
  align-items: center;
  display: flex;
  gap: var(--space-4);
  justify-content: space-between;
}
.modifier-chip {
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-xs);
  background: var(--color-surface);
  font-weight: 850;
}
.receipt-summary > div,
.receipt-payments > div {
  align-items: baseline;
  display: flex;
  gap: var(--space-4);
  justify-content: space-between;
}
.receipt-total {
  border-top: 1px solid var(--brand-line);
  padding-top: 0.8rem;
}
.modifier-sheet {
  background: rgb(0 0 0 / 0.45);
  inset: 0;
  padding: var(--space-4);
  position: fixed;
  z-index: var(--z-modal);
}
.modifier-dialog {
  background: var(--color-surface-warm);
  border: 1px solid #e2d8ce;
  border-radius: var(--radius-sm);
  box-shadow: var(--elevation-4);
  margin: 8vh auto 0;
  max-width: 31rem;
  padding: var(--space-4);
}
.modifier-group h3 {
  color: var(--color-text-secondary);
  font-size: var(--text-caption);
  font-weight: 850;
  margin-bottom: 0.45rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.modifier-chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
}
.modifier-chip {
  padding: 0.45rem 0.7rem;
}
.modifier-chip.selected {
  border-color: var(--brand-copper-dark);
  background: var(--color-accent-soft);
  color: var(--brand-copper-dark);
}
.settings-row,
.settings-subrow {
  align-items: center;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  display: flex;
  gap: var(--space-3);
  justify-content: space-between;
  padding: 0.7rem;
}
.settings-row {
  background: var(--color-surface-warm);
}
.settings-subrow {
  margin-left: var(--space-4);
  padding: 0.45rem 0.65rem;
}
.settings-row span {
  color: var(--color-text-muted);
  display: block;
  font-size: var(--text-caption);
}
.settings-grid,
.settlement-summary-grid {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr));
}

/* ---------- POS settings: platforms, add-ons, discounts ---------- */
/* The page is three URL-driven subtabs now, and every form that used to sit
   inline on it lives in a shared drawer (ops-drawer.js). What is left here is
   the reading layout: a card per platform, add-on options nested inside their
   own group's card, and plain settings rows for discount codes. */
.card-rate-grid {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
}
.card-rate {
  background: var(--color-surface-warm);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-4);
}
.card-rate-head {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
}
.card-rate-head .badge {
  margin-left: auto;
}
.card-rate .commission-rate {
  font-size: 1.7rem;
}
.platform-card-grid {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr));
}
.platform-card {
  border: 1px solid var(--color-border);
  border-radius: 0.6rem;
  background: var(--color-surface-warm);
  padding: var(--space-4);
}
.platform-card.is-off {
  background: var(--color-surface-muted);
  opacity: 0.85;
}
.platform-card-head {
  align-items: center;
  display: flex;
  gap: 0.6rem;
}
.platform-card-head > div {
  flex: 1;
  min-width: 0;
}
.platform-card-name {
  display: block;
  line-height: 1.2;
}
.platform-card-slug {
  color: var(--color-text-subtle);
  display: block;
  font-size: var(--text-xs);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
/* The registry's per-platform colour, the same one the POS pill uses. */
.platform-dot {
  background: var(--platform-color, #6b7280);
  border-radius: var(--radius-full);
  flex: none;
  height: 0.85rem;
  width: 0.85rem;
}
.platform-facts {
  display: grid;
  gap: 0.35rem;
  margin-top: 0.85rem;
}
.platform-facts > div {
  display: flex;
  gap: var(--space-3);
  justify-content: space-between;
}
.platform-facts dt {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}
.platform-facts dd {
  font-size: var(--text-sm);
  font-weight: 650;
  text-align: right;
}
.platform-card-actions {
  margin-top: 0.9rem;
}
.settings-section {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  padding: var(--space-5);
}
.settings-section + .settings-section {
  margin-top: var(--space-5);
}
.settings-section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
}
.settings-section-hint {
  color: var(--color-text-muted);
  font-size: var(--text-body-sm);
  max-width: min(42rem, 75ch);
  line-height: 1.5;
  margin-top: 0.2rem;
}
.commission-rate {
  display: block;
  font-size: 2rem;
  font-weight: 800;
  line-height: 1.15;
  margin-top: 0.15rem;
}
.commission-rate.is-unset {
  color: var(--amber-700);
  font-size: 1.3rem;
}
.commission-card-meta {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  margin-top: 0.1rem;
}
.commission-card-meta.is-warn {
  color: var(--color-danger);
  font-weight: 650;
}
.commission-history {
  margin-top: var(--space-3);
}
.commission-history summary {
  cursor: pointer;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  font-weight: 700;
}

/* Wraps a RadioSelect's rendered markup -- restyled into pills instead of a
   plain list. The installed Django version renders `{{ form.field }}` as
   <div class="scope-picker"><div id="id_field"><div><label><input>...
   </label></div>...</div></div> -- there's an extra id-carrying wrapper div
   between .scope-picker and the per-choice divs (not the flatter <ul><li>
   markup the widget docs describe), so both `.scope-picker` and its direct
   child div need to be flex rows for the actual per-choice divs to wrap as a
   row; the `ul`/`li` rules are kept too in case a widget ever renders list
   markup directly under .scope-picker. */
.scope-picker,
.scope-picker > div {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}
.scope-picker ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  list-style: none;
  margin: 0;
  padding: 0;
}
.scope-picker li {
  list-style: none;
}
.scope-picker label {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  min-height: 2.5rem;
  white-space: nowrap;
  border: 1.5px solid var(--color-border-strong);
  border-radius: var(--radius-full);
  background: var(--color-surface);
  color: var(--color-text-secondary);
  padding: var(--space-2) 0.9rem;
  font-size: var(--text-body-sm);
  font-weight: 700;
  cursor: pointer;
}
.scope-picker label:has(input:checked) {
  border-color: var(--brand-copper-dark);
  background: var(--color-accent-soft);
  color: var(--brand-copper-dark);
}

.addon-group-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin-top: var(--space-4);
}
.addon-group-card {
  border: 1px solid var(--color-border);
  border-radius: 0.6rem;
  background: var(--color-surface-warm);
  padding: 0.85rem var(--space-4);
}
.addon-group-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
}
.addon-group-head .badge {
  margin-left: 0.4rem;
}
.addon-option-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.7rem;
}
.addon-option-chip {
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-full);
  background: var(--color-surface);
  color: var(--stone-700);
  padding: 0.35rem var(--space-3);
  font-size: var(--text-sm);
  font-weight: 650;
  cursor: pointer;
}
.addon-option-chip:hover {
  border-color: var(--brand-copper-dark);
}
.addon-option-chip.is-inactive {
  opacity: 0.5;
  text-decoration: line-through;
}
.addon-option-add {
  border: 1.5px dashed var(--color-border-strong);
  border-radius: var(--radius-full);
  background: transparent;
  color: var(--color-text-muted);
  padding: 0.35rem var(--space-3);
  font-size: var(--text-sm);
  font-weight: 700;
  cursor: pointer;
}
.addon-option-add:hover {
  border-color: var(--brand-copper-dark);
  color: var(--brand-copper-dark);
}
[data-scope-field][hidden] {
  display: none;
}

.receipt-page {
  background: var(--color-surface-sunken);
  color: var(--color-text-primary);
  font-family: system-ui, sans-serif;
}
.receipt {
  background: var(--color-surface);
  margin: var(--space-6) auto;
  max-width: 27rem;
  padding: var(--space-5);
}
.receipt-head {
  justify-content: flex-start;
}
.receipt-head img {
  height: 2.5rem;
}
.receipt-branch {
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-full);
  font-size: var(--text-caption);
  font-weight: 700;
  letter-spacing: 0.02em;
  padding: 0.05rem var(--space-2);
  text-transform: uppercase;
}
.receipt-lines article {
  border-bottom: 1px solid var(--color-border);
  padding: var(--space-3) 0;
}
.receipt-lines article > div {
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
}

/* Category discounts panel (_pos_settings_discounts.html) ----------------- */
.setup-form ul {
  max-height: 12rem;
  overflow-y: auto;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3);
  margin: var(--space-1) 0;
}
.exclusion-chip {
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
  border-radius: var(--radius-full);
  border: 1px solid var(--color-border);
  padding: 0.15rem 0.55rem;
  background: var(--color-surface-sunken);
  color: var(--color-text-secondary);
  font-size: var(--text-caption);
  font-weight: 700;
}
.receipt-lines p {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  margin-top: 0.2rem;
}
.receipt-summary,
.receipt-payments {
  display: grid;
  gap: 0.55rem;
  margin-top: var(--space-4);
}
.receipt-actions {
  display: flex;
  gap: var(--space-2);
  margin-top: var(--space-4);
}
/* Reports > Shift close -- phase 10 report body ---------------------------- */
.shift-close-card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: var(--space-3);
}
.shift-close-card-item {
  border: 1px solid var(--color-border);
  border-radius: 0.6rem;
  padding: var(--space-3);
  background: var(--color-surface);
}
.shift-close-card-item.is-large-variance {
  /* Owner decision (HANDOFF.md #2): a large variance is surfaced, not
     alarmed about -- a quiet left accent and the existing amber .badge-warn,
     never the red .badge-danger the rest of the app reserves for alarms. */
  box-shadow: inset 3px 0 0 var(--amber-600);
  background: #fffaf0;
}
.shift-close-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
}
.shift-close-card-figures {
  display: grid;
  gap: 0.35rem;
  margin: var(--space-2) 0 0;
}
.shift-close-card-figures > div {
  display: flex;
  justify-content: space-between;
  gap: var(--space-2);
  font-size: var(--text-body-sm);
}
.shift-close-card-figures dt {
  color: var(--color-text-muted);
  margin: 0;
}
.shift-close-card-figures dd {
  margin: 0;
  font-weight: 700;
}
.variance-chip.is-large {
  margin-left: 0.35rem;
}
.report-grid-2 {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: var(--space-4);
}
@media print {
  /* The receipt is printed on an 80 mm till roll. Without a declared page the
     browser prints whatever the printer driver calls its default sheet --
     A4, or the roll's maximum length (3.2 m on many drivers), which feeds
     paper until someone switches the printer off. Declaring the roll's own
     size (80 x 297 mm is the size every 80 mm driver lists) gives the browser
     something to match, and a driver on a "Receipt" (variable-length) paper
     setting trims the blank tail. Zero page margin: the roll has none. */
  @page { size: 80mm 297mm; margin: 0; }
  .receipt-page { background: white; margin: 0; padding: 0; width: 80mm; }
  .receipt-actions { display: none; }
  .receipt {
    box-shadow: none;
    font-size: 10.5pt;
    line-height: 1.3;
    margin: 0;
    max-width: none;
    padding: 3mm 4mm 8mm;
    width: 72mm;
  }
  .receipt-head { gap: var(--space-2); }
  .receipt-head img { height: 9mm; }
  .receipt-head h1 { font-size: 13pt; margin: 0; }
  .receipt-head p { font-size: 9pt; margin: 0; }
  .receipt-lines article { break-inside: avoid; padding: 0.3rem 0; }
  .receipt-lines p { font-size: 8.5pt; }
  .receipt-summary, .receipt-payments { gap: 0.2rem; margin-top: var(--space-2); }
  .receipt-total { padding-top: 0.4rem; }
  /* Shift close: print the numbers, not the controls. Every manager action
     (approve/return/close/reopen), the print button itself, and the
     ops-drawer confirm dialogs are useless on paper and would otherwise
     print as dead buttons or -- worse -- an open <dialog>. */
  .shift-close-report .page-head-actions,
  .shift-close-report form,
  .shift-close-report .ops-drawer,
  .shift-close-print-btn {
    display: none !important;
  }
  /* A card or panel splitting across a page break is harder to read than a
     shorter page, so every shift-close card asks to stay whole. */
  .shift-close-report .panel,
  .shift-close-card-item {
    break-inside: avoid;
  }
}
/* pos.css owns every POS/Tables breakpoint now that Tables is a screen
   inside pos.html rather than its own page. */

/* Purchases & Suppliers (Phase 5) ----------------------------------------- */
/* The one KPI tile that is a task rather than a number links into the
   filtered list; it stays a .kpi-tile so the strip reads as one row. */
a.kpi-tile {
  display: block;
  color: inherit;
}
a.kpi-tile:hover {
  border-color: var(--brand-copper-dark);
  box-shadow: var(--elevation-2);
}
/* A primary action in the page head is sometimes a one-button <form> (the
   Post action carries a CSRF token and an idempotency key). */
.page-head-actions form {
  margin: 0;
}
@media (max-width: 900px) {
  .page-head-actions form,
  .page-head-actions form .btn-primary,
  .page-head-actions form .btn-secondary {
    width: 100%;
  }
}
.tab-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}
.table-search {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}
.table-search input {
  width: min(18rem, 62vw);
  min-height: 2.45rem;
}
/* Drafts are the only rows still waiting on a decision, so they carry a
   quiet left accent rather than another column of colour. */
tr.row-draft > td:first-child {
  box-shadow: inset 3px 0 0 var(--brand-copper);
}
.row-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-2);
}
.row-actions form {
  margin: 0;
}
.btn-compact {
  padding: 0.35rem 0.7rem;
  font-size: var(--text-sm);
}
.rank-list {
  display: grid;
}

/* ---------- Settlements ---------- */
/* Reconciling a platform payout is one linear task: pick the platform, tick
   the orders that were in the deposit, type what landed in the bank. The tab
   bar carries each platform's outstanding money so the choice is informed,
   and the reconcile bar stays pinned to the bottom of the viewport so the
   running total and the variance verdict are visible however far down the
   order table the manager has scrolled. */
.settlement-tabs a {
  flex-direction: column;
  align-items: flex-start;
  gap: 0.1rem;
  border-radius: 0.7rem;
  padding: 0.45rem 0.85rem;
  line-height: 1.25;
}
.settlement-tab-name {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}
/* A payout that is past its expected date is the one thing worth interrupting
   for, so it gets a dot rather than another badge competing with the amount. */
.settlement-tab-dot {
  width: 0.45rem;
  height: 0.45rem;
  border-radius: var(--radius-full);
  background: #dc2626;
}
.settlement-tab-amount {
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--color-text-muted);
}
.settlement-tabs a.active .settlement-tab-amount {
  color: var(--brand-copper-dark);
}
.settlement-table .settlement-select-cell {
  width: 2.6rem;
  text-align: center;
}
.settlement-table input[type="checkbox"] {
  width: 1.1rem;
  height: 1.1rem;
}
.settlement-reconcile {
  position: sticky;
  bottom: 0;
  z-index: var(--z-sticky);
  margin-top: var(--space-4);
  border: 1px solid var(--brand-line);
  border-radius: 0.6rem;
  background: var(--color-surface);
  padding: 0.85rem var(--space-4);
  box-shadow: var(--elevation-2-up);
}
.settlement-reconcile-main {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.9rem;
}
.settlement-reconcile-figures {
  display: flex;
  flex-wrap: wrap;
  gap: 1.4rem;
}
.settlement-reconcile-figures p {
  margin: 0;
}
.settlement-reconcile-figures span {
  display: block;
  color: var(--color-text-muted);
  font-size: var(--text-caption);
  font-weight: 800;
}
.settlement-reconcile-figures strong {
  font-size: 1.15rem;
}
.settlement-amount {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  margin-left: auto;
}
.settlement-amount span {
  color: var(--color-text-muted);
  font-size: var(--text-caption);
  font-weight: 800;
}
.settlement-amount input {
  min-height: 2.6rem;
  width: 10rem;
}
.settlement-variance {
  align-self: center;
  min-height: 2.1rem;
  padding: 0.35rem 0.7rem;
  font-size: var(--text-sm);
}
/* Beat any display:* the badge rules set, so the chip really disappears until
   there is a verdict to show. */
.settlement-variance[hidden] {
  display: none;
}
.settlement-reconcile-error {
  margin: 0 0 0.6rem;
  color: var(--color-danger-strong);
  font-size: var(--text-body-sm);
  font-weight: 700;
}
.settlement-extra {
  margin-top: 0.6rem;
}
.settlement-extra > summary {
  cursor: pointer;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  font-weight: 800;
}
@media (max-width: 720px) {
  .settlement-reconcile-main {
    align-items: stretch;
  }
  .settlement-amount {
    margin-left: 0;
  }
  .settlement-amount input,
  .settlement-reconcile-main .btn-primary {
    width: 100%;
  }
}

/* ---- Menu editor (Phase 9) ------------------------------------------- */
/* One calm column: item basics with the photo beside the fields, a stock-mode
   pill pair, the ingredient formset, and a collapsed Advanced block. */
.menu-editor {
  max-width: 52rem;
  margin: 0 auto;
}
.editor-basics {
  display: grid;
  grid-template-columns: 13rem 1fr;
  gap: var(--space-5);
  align-items: start;
}
@media (max-width: 720px) {
  .editor-basics {
    grid-template-columns: 1fr;
  }
}
.menu-photo-tile {
  display: grid;
  gap: 0.6rem;
}
.menu-photo-tile img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border);
  background: var(--color-surface-muted);
}
.menu-photo-tile #menuPhotoEmpty {
  display: grid;
  place-items: center;
  aspect-ratio: 1 / 1;
  border: 1.5px dashed var(--color-border-strong);
  border-radius: var(--radius-sm);
  color: var(--color-text-subtle);
  font-size: var(--text-body-sm);
  font-weight: 700;
  background: var(--color-surface-muted);
}
.menu-photo-tile #menuPhotoEmpty[hidden],
.menu-photo-tile img[hidden] {
  display: none;
}
.field-pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.8rem;
}
@media (max-width: 560px) {
  .field-pair {
    grid-template-columns: 1fr;
  }
}
.field-error {
  color: var(--color-danger-strong);
  font-size: var(--text-sm);
  font-weight: 700;
}
/* ui-audit g3: forms -- an error is more than red text: a warning mark leads
   the message, and the box Django flags aria-invalid gets a heavier red edge. */
.field-error::before {
  content: "\26A0\FE0E  ";
  content: "\26A0\FE0E  " / "";
}
body :is(input, select, textarea)[aria-invalid="true"] {
  border-color: #b91c1c;
  box-shadow: inset 0 0 0 1px #b91c1c;
}
/* Form grids for hand-laid-out field cells (_stacked_field.html). Cells align
   to the TOP: a field carrying an error or a hint is taller than its
   neighbours, and `align-items: end` made the inputs in one row sit at
   different heights. */
.user-form-grid,
.password-form-grid {
  display: grid;
  gap: 0.9rem var(--space-4);
  align-items: start;
}
.user-form-grid {
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
}
.password-form-grid {
  /* Two boxes side by side and no wider than they need to be -- stretched
     across the whole panel they read as unrelated fields. */
  grid-template-columns: repeat(auto-fit, minmax(14rem, 20rem));
  justify-content: start;
}
.field-hint {
  color: var(--color-text-muted);
  font-size: var(--text-xs);
  font-weight: 500;
  line-height: 1.35;
}
.btn-danger-outline {
  border-color: var(--red-700);
  color: var(--color-danger);
}
/* ui-audit g5: a filled button whose action cannot be taken back (Void sale). */
.btn-primary.btn-danger:not(:disabled) {
  border-color: #b91c1c;
  background: #b91c1c;
  color: #fff;
}
.btn-primary.btn-danger:not(:disabled):hover {
  background: #991b1b;
}
/* Sign in / sign up / password pages. These are the only screens a person
   sees before they are anybody here -- and, for a new barista, the first
   thing they ever see of the place -- so they are the lounge's front door
   rather than back-office chrome: the mark at full size, a serif title, and
   one card centred in the window. No standing "staff operations" label and no
   explaining what a sign-in page is (owner, 2026-09-05). */
.auth-shell {
  display: grid;
  place-items: center;
  min-height: calc(100dvh - 2rem);
  padding: var(--space-10) var(--space-4);
}
.auth-shell-inline {
  /* Signed-in pages already have the app chrome around them. */
  min-height: 0;
  padding: var(--space-6) 0;
  justify-items: start;
}
.auth-card {
  width: 100%;
  max-width: 27rem;
  border: 1px solid var(--line);
  border-radius: 20px;
  background: var(--surface);
  padding: var(--space-12) var(--space-10) var(--space-10);
  text-align: center;
  box-shadow:
    0 1px 2px rgb(40 35 33 / 0.04),
    0 24px 60px -36px rgb(74 48 28 / 0.45);
}
.auth-card-wide {
  max-width: 46rem;
}
.auth-logo {
  display: block;
  margin: 0 auto;
  height: 8.5rem;
  width: auto;
  max-width: 100%;
}
/* A hairline under the mark: enough to separate brand from business without
   another line of text doing the job. */
.auth-rule {
  display: block;
  width: 3rem;
  height: 1px;
  margin: var(--space-7) auto 0;
  background: var(--accent);
  opacity: 0.55;
}
.auth-eyebrow {
  color: var(--ink-muted);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.auth-title {
  margin-top: var(--space-6);
  font-family: var(--font-display);
  font-size: clamp(2rem, 1.5rem + 2vw, var(--text-display));
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: 0.005em;
  color: var(--ink);
}
/* The sign-in card's heading names the place rather than the act -- the
   button underneath already says "Sign in" -- so it sits quieter than a
   page title and lets the mark above it lead. */
.auth-title-compact {
  margin-top: var(--space-5);
  font-size: clamp(1.45rem, 1.2rem + 1vw, 1.6rem);
  letter-spacing: 0.03em;
}
.auth-lede {
  margin: 0.85rem auto 0;
  max-width: 34ch;
  color: var(--ink-muted);
  font-size: var(--text-body);
  line-height: 1.6;
}
.auth-card-wide .auth-lede {
  max-width: 48ch;
}
.auth-form {
  display: grid;
  gap: 1.1rem;
  margin-top: var(--space-8);
  text-align: left;
}
.signup-grid {
  display: grid;
  gap: 1.1rem var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  align-items: start;
}
/* The password and its confirmation belong side by side; without this the
   optional phone/branch fields above decide where the pair lands. */
.signup-grid .signup-newrow {
  grid-column: 1;
}
.signup-grid .signup-full {
  grid-column: 1 / -1;
}
/* Django 4+ renders a multi-checkbox field as a plain <div> of <div><label>
   rows (NOT the <ul> older Django produced). Dressed as tick cards so "I work
   at both branches" is one obvious gesture. */
.auth-card .compact-field > div {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: var(--space-2);
}
.auth-card .compact-field > div label {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 0.7rem 0.85rem;
  font-size: var(--text-body);
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink);
  cursor: pointer;
  transition: border-color var(--motion-fast) var(--ease-standard), background var(--motion-fast) var(--ease-standard);
}
.auth-card .compact-field > div label:hover {
  border-color: var(--accent);
  background: var(--accent-soft);
}
.auth-card .compact-field > div input[type="checkbox"] {
  width: 1.05rem;
  height: 1.05rem;
  margin: 0;
  padding: 0;
  border-radius: 4px;
  accent-color: var(--accent-ink);
  flex: 0 0 auto;
}
.auth-card .compact-field > div input[type="checkbox"]:focus {
  box-shadow: none;
  border-color: var(--line);
}
/* Small capitals over the boxes: the label is a quiet caption here, not a
   heading competing with the title. */
.auth-card .compact-field > span:first-child {
  color: var(--ink-muted);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.auth-card input,
.auth-card select {
  border-radius: 10px;
  border-color: var(--line);
  padding: 0.8rem 0.9rem;
  font-size: 0.95rem;
  transition: border-color var(--motion-fast) var(--ease-standard), box-shadow var(--motion-fast) var(--ease-standard);
}
.auth-card input:focus,
.auth-card select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
/* ui-audit g3: focus -- the pale halo above is all but invisible on white;
   a keyboard/typing focus gets a solid copper ring with a white gap. */
.auth-card input:focus-visible,
.auth-card select:focus-visible {
  box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--accent);
}
/* Chrome paints a pale blue over autofilled boxes, which on this card reads
   as a rendering fault. Repaint it in the card's own white. */
.auth-card input:-webkit-autofill,
.auth-card input:-webkit-autofill:hover,
.auth-card input:-webkit-autofill:focus {
  -webkit-box-shadow: 0 0 0 1000px var(--surface) inset;
  -webkit-text-fill-color: var(--ink);
  caret-color: var(--ink);
}
/* ui-audit g4: password show/hide (form-ux.js wraps each password box). The
   button sits inside the box's right edge; the box keeps room for it. */
.password-field {
  position: relative;
  display: block;
}
.password-field > input {
  width: 100%;
  padding-right: 4.25rem;
}
.password-toggle {
  position: absolute;
  top: 50%;
  right: 0.3rem;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  user-select: none;
  min-height: 2.5rem;
  min-width: 3.5rem;
  border: 0;
  border-radius: 0.375rem;
  background: transparent;
  color: var(--brand-copper-dark);
  font-size: 0.8rem;
  font-weight: 700;
  cursor: pointer;
  transition: background-color var(--motion-fast) var(--ease-standard);
}
.password-toggle:hover {
  background: var(--accent-soft);
}
.auth-submit {
  width: 100%;
  border-radius: 10px;
  padding: 0.85rem var(--space-4);
  font-size: 0.95rem;
  letter-spacing: 0.02em;
  box-shadow: 0 10px 20px -14px rgb(74 48 28 / 0.9);
}
.auth-card-wide .auth-submit {
  margin-top: var(--space-7);
}
.auth-links {
  margin-top: var(--space-7);
  font-size: var(--text-body-sm);
  color: var(--ink-muted);
}
.auth-links a {
  color: var(--ink-soft);
  font-weight: 600;
  text-decoration: none;
  border-bottom: 1px solid var(--line);
  padding-bottom: 1px;
  transition: color var(--motion-fast) var(--ease-standard), border-color var(--motion-fast) var(--ease-standard);
}
.auth-links a:hover {
  color: var(--accent-ink);
  border-color: var(--accent);
}
.auth-links-sep {
  color: var(--ink-faint);
  padding: 0 var(--space-2);
}
@media (max-width: 480px) {
  .auth-card {
    padding: 2.25rem var(--space-6) var(--space-8);
  }
  .auth-logo {
    height: 6.5rem;
  }
  .auth-title {
    font-size: 2rem;
  }
  .auth-title-compact {
    font-size: 1.45rem;
  }
}
/* Sign-ups waiting for a decision, at the top of Users & Permissions. */
.panel-pending {
  border-color: #fcd34d;
  background: var(--color-warning-soft);
}
.pending-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  border: 1px solid var(--amber-200);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  padding: var(--space-3) 0.9rem;
}
.pending-actions {
  display: flex;
  gap: var(--space-2);
}
.check-inline {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  font-size: var(--text-body-sm);
  font-weight: 700;
  color: var(--color-text-secondary);
}
.check-inline input[type="checkbox"] {
  margin-top: 0.15rem;
}
.new-category-reveal .detail-link {
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  text-align: left;
}
/* Same pill treatment as .scope-picker, but on hand-rendered radios. */
.stock-mode-picker {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}
.stock-mode-picker label {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  border: 1.5px solid var(--color-border-strong);
  border-radius: var(--radius-full);
  background: var(--color-surface);
  color: var(--color-text-secondary);
  padding: 0.4rem 0.85rem;
  font-size: var(--text-body-sm);
  font-weight: 700;
  cursor: pointer;
}
.stock-mode-picker label:has(input:checked) {
  border-color: var(--brand-copper-dark);
  background: var(--color-accent-soft);
  color: var(--brand-copper-dark);
}
.stock-mode-picker input[type="radio"] {
  width: auto;
}
.ingredient-rows {
  display: grid;
  gap: 0.6rem;
}
.ingredient-row {
  display: grid;
  grid-template-columns: 1fr 11rem auto;
  gap: 0.8rem;
  align-items: start;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  padding: 0.7rem 0.8rem;
}
@media (max-width: 560px) {
  .ingredient-row {
    grid-template-columns: 1fr auto;
  }
  .ingredient-row .ingredient-qty {
    grid-column: 1 / -1;
  }
}
.ingredient-remove {
  margin-top: 1.35rem;
  padding: 0.35rem 0.65rem;
  line-height: 1;
}
.unit-hint {
  color: var(--color-text-subtle);
  font-weight: 700;
}
.unit-hint:empty {
  display: none;
}
.cost-estimate {
  align-self: center;
  border-radius: var(--radius-full);
  background: var(--color-surface-sunken);
  color: var(--color-text-secondary);
  padding: 0.3rem var(--space-3);
  font-size: var(--text-sm);
  font-weight: 750;
  white-space: nowrap;
}
.advanced-recipe > summary {
  cursor: pointer;
}
.editor-savebar {
  position: sticky;
  bottom: 0;
  z-index: var(--z-sticky);
  display: flex;
  align-items: center;
  gap: var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: rgba(255, 255, 255, 0.94);
  backdrop-filter: blur(4px);
  padding: var(--space-3) var(--space-4);
}
.readiness-issue-list {
  margin-top: 0.35rem;
  padding-left: 1.1rem;
  list-style: disc;
}

/* ---- Menu browse (Phase 10) ------------------------------------------ */
/* The owner's catalogue: a quiet card per product with a square photo, one
   status chip, and (for cost-permitted users) an honest cost line. Reuses the
   shared badge/segment-bar/panel tokens; only the grid and card frame are new. */
.menu-alert-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  border: 1px solid #f0d3a8;
  border-left: 4px solid var(--brand-copper-dark);
  border-radius: var(--radius-sm);
  background: #fdf6ec;
  color: #7c4a12;
  padding: 0.7rem 0.95rem;
  font-size: var(--text-body);
  font-weight: 700;
  text-decoration: none;
}
.menu-alert-banner:hover {
  background: #fbeed9;
}
.menu-filters {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-3);
}
.menu-search {
  flex: 1 1 18rem;
}
.menu-status-field {
  flex: 0 1 14rem;
}
.menu-result-count {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  font-weight: 700;
}
.menu-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: var(--space-4);
}
.menu-card {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  overflow: hidden;
}
/* perf p1: menu cards scrolled out of view skip layout and paint until they
   come near the viewport (one card per menu item, 100+). Height = measured
   card height; "auto" then remembers each card's real size. */
.menu-card { content-visibility: auto; contain-intrinsic-block-size: auto 440px; }
.menu-card.is-off-menu {
  opacity: 0.72;
}
.menu-card-photo {
  display: block;
  aspect-ratio: 1 / 1;
  background: var(--color-surface-sunken);
}
.menu-card-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.menu-card-initial {
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  color: var(--color-text-subtle);
  font-size: 2.6rem;
  font-weight: 800;
  letter-spacing: 0.03em;
}
.menu-card-body {
  display: grid;
  gap: 0.55rem;
  padding: 0.8rem 0.9rem 0.9rem;
}
.menu-card-line {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.6rem;
}
.menu-card-name {
  color: inherit;
  font-weight: 750;
  line-height: 1.25;
  text-decoration: none;
}
.menu-card-name:hover {
  text-decoration: underline;
}
.menu-card-price {
  white-space: nowrap;
  font-size: var(--text-body);
}
.menu-card-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}
.chip-quiet {
  display: inline-flex;
  align-items: center;
  border-radius: var(--radius-full);
  background: var(--color-surface-sunken);
  color: var(--color-text-secondary);
  padding: 0.15rem 0.6rem;
  font-size: var(--text-xs);
  font-weight: 700;
}
.menu-card-cost {
  color: var(--color-text-secondary);
  font-size: var(--text-sm);
  font-weight: 700;
}
.cost-percent {
  color: var(--color-text-muted);
  font-weight: 700;
}
.cost-unknown {
  color: var(--color-text-subtle);
  font-style: italic;
  font-weight: 700;
}
/* Plate-cost badge and counter (costing redesign, plan D8) ---------------- */
.menu-card-cost {
  display: grid;
  gap: 0.3rem;
}
.menu-card-cost p {
  margin: 0;
}
.menu-card-cost-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem 0.45rem;
  min-width: 0;
}
.menu-card-cost-note {
  display: flex;
  flex-wrap: wrap;
  gap: 0.2rem 0.6rem;
  color: var(--color-text-muted);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.menu-cost-summary {
  padding: 0.7rem var(--space-4);
}
.menu-cost-counter {
  margin: 0;
  font-size: 0.95rem;
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
}
.menu-cost-details > summary {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.35rem var(--space-3);
  min-height: 2.4rem;
  border-radius: var(--radius-xs);
}
.menu-cost-details > summary:hover .menu-cost-toggle {
  text-decoration: underline;
}
.menu-cost-toggle {
  color: var(--ink-muted);
  font-size: var(--text-body-sm);
  font-weight: 700;
}
.menu-cost-toggle::after {
  content: "Show which ingredients \25BE";
}
.menu-cost-details[open] .menu-cost-toggle::after {
  content: "Hide \25B4";
}
.menu-cost-help {
  margin: var(--space-2) 0 0;
  color: var(--ink-muted);
  font-size: var(--text-body);
}
.menu-uncosted-list {
  list-style: none;
  margin: 0.6rem 0 0;
  padding: 0;
  display: grid;
}
.menu-uncosted-list li {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem var(--space-3);
  padding: var(--space-2) 0;
  border-top: 1px solid var(--stone-100);
}
.menu-uncosted-name {
  font-weight: 700;
  min-width: 0;
  overflow-wrap: anywhere;
}
.menu-uncosted-used {
  flex: 1 1 auto;
  color: var(--ink-muted);
  font-size: var(--text-body-sm);
  font-variant-numeric: tabular-nums;
}
.menu-uncosted-list .btn-secondary {
  font-size: var(--text-sm);
}
/* A number field with a unit glued to its right edge ("25 %"). */
.input-with-suffix {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}
.input-with-suffix input {
  flex: 1 1 auto;
  min-width: 0;
  max-width: 8rem;
}
.input-suffix {
  color: var(--ink-muted);
  font-weight: 700;
}
.menu-card-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-top: 0.15rem;
}
.menu-card-actions .btn-secondary {
  font-size: var(--text-sm);
  padding: 0.3rem 0.6rem;
}

/* Wastage page redesign (Phase 12) -------------------------------------- */
.form-steps {
  display: grid;
  gap: var(--space-3);
  list-style: none;
  padding: 0;
  margin: 0;
}
.form-step {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface-muted);
  padding: var(--space-3) 0.85rem;
}
.form-step-head {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}
.form-step-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 1.6rem;
  height: 1.6rem;
  border-radius: var(--radius-full);
  background: var(--brand-copper-dark);
  color: var(--color-text-inverse);
  font-size: var(--text-sm);
  font-weight: 800;
}
.form-step-title {
  font-weight: 800;
  font-size: 0.95rem;
}
.form-step fieldset {
  border: 0;
  padding: 0;
  margin: 0;
}

/* Camera tile: idle placeholder -> live preview -> captured still, switched
   by camera.js setting data-camera-state on the wrapper. Mirrors the square
   .menu-photo-tile pattern but stays 16:9 to match the original preview. */
.camera-tile {
  position: relative;
  aspect-ratio: 16 / 9;
  width: 100%;
  overflow: hidden;
  border-radius: var(--radius-sm);
  background: #0c0a09;
}
.camera-tile-empty,
.camera-tile video,
.camera-tile img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.camera-tile-empty {
  display: none;
  place-items: center;
  gap: 0.35rem;
  background: var(--stone-900);
  color: var(--color-text-subtle);
  text-align: center;
  padding: var(--space-4);
  font-size: var(--text-body-sm);
}
.camera-tile-empty span {
  font-size: 1.6rem;
}
.camera-tile video,
.camera-tile img {
  display: none;
}
.camera-tile[data-camera-state="idle"] .camera-tile-empty {
  display: grid;
}
.camera-tile[data-camera-state="live"] video {
  display: block;
}
.camera-tile[data-camera-state="captured"] img {
  display: block;
}

.wastage-submit-bar {
  position: sticky;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  margin-top: 0.85rem;
  padding: 0.6rem var(--space-1);
  background: var(--color-surface);
  border-top: 1px solid var(--color-border);
}
.wastage-photo-status {
  font-size: var(--text-body-sm);
  font-weight: 800;
  color: var(--amber-700);
}
.wastage-photo-status[data-captured="true"] {
  color: var(--green-700);
}

/* Inventory item settings redesign ---------------------------------------
   Categorized cards + search/pill toolbar + shared Add/Edit/Remove drawer.
   Reuses .panel, .badge, .row-actions, .segment-bar, and .ops-drawer*. */
.settings-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
}
.settings-search {
  flex: 1 1 16rem;
  min-width: 14rem;
}
.settings-filter-status {
  flex-basis: 100%;
  margin: 0;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  font-weight: 650;
}
/* .segment-bar previously only ever held <a> pills; the settings page uses
   <button> pills because they drive client-side filtering, not navigation. */
.segment-bar button {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  flex: 0 0 auto;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-full);
  background: var(--color-surface);
  color: var(--color-text-secondary);
  padding: 0.45rem 0.8rem;
  font-size: var(--text-body-sm);
  font-weight: 800;
  cursor: pointer;
}
.segment-bar button.active,
.segment-bar button:hover {
  border-color: var(--brand-copper-dark);
  background: var(--color-accent-soft);
  color: var(--brand-copper-dark);
}
.settings-card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 0.9rem;
}
.settings-card {
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  padding: var(--space-4);
  box-shadow: var(--elevation-1);
}
.settings-card.is-inactive {
  opacity: 0.62;
  background: var(--color-surface-muted);
}
.settings-card-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-2);
}
.settings-card-name {
  font-size: 0.95rem;
  font-weight: 750;
  line-height: 1.25;
}
.settings-card-unit {
  color: var(--color-text-secondary);
  font-size: var(--text-sm);
}
.settings-card-levels {
  display: flex;
  gap: 1.1rem;
  margin: 0;
}
.settings-card-levels dt {
  color: var(--color-text-muted);
  font-size: var(--text-xs);
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.settings-card-levels dd {
  margin: 0;
  font-size: var(--text-body-sm);
  font-weight: 700;
}
.settings-card-supplier {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}
.settings-card-actions {
  margin-top: auto;
  align-items: center;
}
.settings-menu-match {
  border: 1px solid #ecd9c6;
  border-radius: 0.65rem;
  background: #fff8f0;
  padding: 0.85rem 0.95rem;
}
.settings-menu-match-title {
  font-size: 0.95rem;
  font-weight: 800;
  color: var(--brand-copper-dark);
}
.settings-menu-match-hint {
  margin-top: 0.15rem;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}
.settings-menu-match-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.55rem;
}
.settings-menu-match-row strong {
  font-size: var(--text-body-sm);
  margin-right: var(--space-1);
}
.settings-menu-chip {
  display: inline-flex;
  align-items: center;
  border: 1px solid #ecd9c6;
  border-radius: var(--radius-full);
  background: var(--color-surface);
  color: var(--brand-copper-dark);
  padding: 0.22rem 0.6rem;
  font-size: var(--text-caption);
  font-weight: 750;
  cursor: pointer;
}
.settings-menu-chip:hover {
  background: var(--color-accent-soft);
}
.settings-remove-form {
  margin-top: 1.1rem;
  padding-top: var(--space-4);
  border-top: 1px dashed var(--color-border);
}
.settings-remove-note {
  margin-top: 0.45rem;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}
/* ui-audit g4: "Also bought from ..." arrives after a fetch; it fades in
   instead of popping into the form. */
@keyframes ops-fade-in {
  from { opacity: 0; }
}
[data-other-prices]:not([hidden]) {
  animation: ops-fade-in var(--motion-base) var(--ease-out);
}

/* --- Item settings: reveal pills, bulk relabel, grouped drawer ------------
   The two "reveal" pills (Inactive / Deleted) sit in the same segment-bar as
   the category pills but are a different control: independent on/off switches
   rather than a single choice, so they mark state with aria-pressed instead of
   the .active class the category pills use. They are styled deliberately
   unlike a category -- a dashed edge when off, filled when on -- so the bar
   does not read as one row of six equivalent choices. */
.segment-bar button[data-settings-show] {
  border-style: dashed;
  color: var(--color-text-muted);
}
.segment-bar button[data-settings-show][aria-pressed="true"] {
  border-style: solid;
  border-color: var(--brand-copper-dark);
  background: var(--color-accent-soft);
  color: var(--brand-copper-dark);
}
/* A deleted card stays legible but visibly set apart from a merely switched-off
   one, which already uses .is-inactive's fade. */
.settings-card[data-settings-archived="1"] {
  border-style: dashed;
  border-color: var(--color-border-strong);
  background: var(--color-surface-muted);
}

/* Bulk select mode. The checkbox is hidden until the owner turns select mode
   on, so it never adds clutter to the normal reading view of a card. */
.settings-card-select {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  cursor: pointer;
}
.settings-card-select input {
  width: 1.05rem;
  height: 1.05rem;
  accent-color: var(--brand-copper-dark);
  cursor: pointer;
}
.settings-bulk-bar {
  position: sticky;
  bottom: 0;
  z-index: var(--z-sticky);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.65rem;
  margin-top: var(--space-5);
  border: 1px solid var(--brand-copper-dark);
  border-radius: 0.65rem;
  background: var(--color-accent-soft);
  padding: 0.8rem 0.95rem;
  box-shadow: var(--elevation-2-up);
}
.settings-bulk-bar p {
  margin: 0;
}
.settings-bulk-bar .settings-remove-note {
  flex-basis: 100%;
  margin-top: 0;
}

/* Drawer sections. The two collapsed ones are <details>, the open one is a
   <fieldset>; both need the same box so the drawer reads as three sections
   rather than one long column of fields. */
.drawer-group {
  margin: 0;
  border: 1px solid var(--color-border);
  border-radius: 0.6rem;
  padding: var(--space-3) 0.9rem;
}
.drawer-group > legend,
.drawer-group > summary {
  padding: 0 0.3rem;
  color: var(--color-text-secondary);
  font-size: var(--text-sm);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.drawer-group > summary {
  cursor: pointer;
  padding: 0;
  list-style: revert;
}
.drawer-group > summary + * {
  margin-top: var(--space-3);
}

/* Menu page: the whole-menu stock-deduction toggle. The main button offers the
   direction most of the menu is not in; when the menu is mixed a quieter
   link-styled button offers the other way, so nobody is ever stuck. */
.menu-bulk-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-5);
}
.btn-link {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  font-size: var(--text-body);
  font-weight: 800;
  color: var(--brand-copper-dark);
  text-decoration: underline;
  text-underline-offset: 0.15em;
  cursor: pointer;
}
.btn-link:hover {
  color: var(--brand-charcoal);
}

/* ---------- Edit the day's orders ---------- */
.day-orders-datepick input {
  min-height: 2.35rem;
}
/* ui-audit g2: phone date stepper. Below 900px the generic page-head rule
   made each of prev / date / next its own full-width row -- four stacked
   buttons before a single order showed. Previous, the date and next now
   share one row (the date takes the slack); the report link keeps its own. */
@media (max-width: 900px) {
  .day-orders .page-head-actions {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
  }
  .day-orders .page-head-actions > .btn-secondary {
    width: auto;
    min-height: 2.75rem;
  }
  .day-orders .page-head-actions > .btn-secondary:last-child {
    grid-column: 1 / -1;
  }
  .day-orders-datepick input {
    width: 100%;
    min-height: 2.75rem;
  }
}
.day-shift-strip {
  display: grid;
  gap: var(--space-3);
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
}
.day-shift-card {
  background: var(--color-surface-warm);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-3) 0.9rem;
}
.day-shift-card.is-active {
  border-color: var(--brand-accent, var(--amber-700));
  box-shadow: 0 0 0 2px rgba(180, 83, 9, 0.12);
}
.day-shift-card a {
  align-items: center;
  color: inherit;
  display: flex;
  gap: var(--space-2);
  justify-content: space-between;
  text-decoration: none;
}
.day-shift-figure {
  font-size: var(--text-sm);
  margin-top: var(--space-1);
}
.report-toolbar select {
  min-height: 2.35rem;
}
.day-orders-filters label {
  min-width: 8rem;
}
.day-orders-table td {
  vertical-align: top;
}
.day-orders-items {
  max-width: 24rem;
}
.day-orders-line {
  display: block;
  font-size: var(--text-sm);
  line-height: 1.35;
}
.day-orders-line small {
  color: var(--color-text-muted);
}
.day-orders-change {
  margin-top: 0.3rem;
}
.tender-chip {
  align-items: center;
  display: inline-flex;
  font-size: var(--text-sm);
  gap: 0.35rem;
  margin: 0.1rem var(--space-2) 0.1rem 0;
  white-space: nowrap;
}
.tender-chip i {
  border-radius: var(--radius-full);
  display: inline-block;
  height: 0.5rem;
  width: 0.5rem;
}
.tender-chip b {
  font-weight: 800;
}
.day-orders-actions {
  white-space: nowrap;
}
.day-orders-actions .btn-compact + .btn-compact {
  margin-left: 0.35rem;
}
.day-orders-close .panel-head {
  align-items: center;
}
.form-grid-2,
.form-grid-3 {
  display: grid;
  gap: var(--space-3);
}
.form-grid-2 {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.form-grid-3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
.fix-methods {
  border: 0;
  display: grid;
  gap: 0.4rem;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  margin: 0;
  padding: 0;
}
.fix-methods legend {
  grid-column: 1 / -1;
  margin-bottom: 0.2rem;
  padding: 0;
}
.fix-method {
  align-items: center;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  display: flex;
  font-size: var(--text-sm);
  font-weight: 700;
  gap: var(--space-2);
  padding: var(--space-2) 0.65rem;
}
.fix-method:has(input:checked) {
  background: #fdf3e7;
  border-color: var(--brand-accent, var(--amber-700));
}
.fix-method:has(input:disabled) {
  color: var(--color-text-disabled);
  cursor: default;
}
.fix-method.is-current::after {
  content: "current";
  color: var(--color-text-subtle);
  font-size: var(--text-2xs);
  font-weight: 800;
  margin-left: auto;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.fix-method input {
  margin: 0;
}
.fix-method span {
  align-items: center;
  display: inline-flex;
  gap: 0.4rem;
}
.tender-dot {
  background: var(--tender-color, var(--stone-400));
  border-radius: var(--radius-full);
  display: inline-block;
  height: 0.55rem;
  width: 0.55rem;
}
.tender-dot[data-tone="cash"] { background: #2f7562; }
.tender-dot[data-tone="card"] { background: #4f8fba; }
.add-sale-lines {
  display: grid;
  gap: var(--space-2);
}
.add-sale-line {
  align-items: center;
  display: grid;
  gap: var(--space-2);
  grid-template-columns: minmax(0, 1fr) 4.5rem 2.25rem;
}
.add-sale-line input,
.add-sale-line select {
  min-height: 2.35rem;
}
#addSaleMoreLine {
  justify-self: start;
}
@media (max-width: 720px) {
  .form-grid-2,
  .form-grid-3,
  .fix-methods {
    grid-template-columns: 1fr;
  }
}

/* Shift close: compact day view */
.shift-close-card-note {
  color: var(--color-text-secondary);
  font-size: var(--text-sm);
  font-style: italic;
  margin-top: 0.4rem;
}
.shift-close-card-review {
  border-top: 1px solid #efebe7;
  margin-top: 0.6rem;
  padding-top: 0.6rem;
}
.shift-close-card-review input[type="text"] {
  flex: 1 1 auto;
  min-width: 0;
}
.shift-close-full > summary {
  cursor: pointer;
  list-style: none;
}
.shift-close-full > summary::-webkit-details-marker {
  display: none;
}
.shift-close-full > summary .panel-title::before {
  content: "▸ ";
  color: var(--color-text-subtle);
}
.shift-close-full[open] > summary .panel-title::before {
  content: "▾ ";
}
.more-menu {
  position: relative;
}
.more-menu > summary {
  cursor: pointer;
  list-style: none;
}
.more-menu > summary::-webkit-details-marker {
  display: none;
}
.more-menu-list {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  box-shadow: var(--elevation-3);
  display: grid;
  min-width: 10rem;
  padding: 0.35rem;
  position: absolute;
  right: 0;
  top: calc(100% + 0.35rem);
  z-index: var(--z-dropdown);
}
.more-menu-list .text-action {
  background: none;
  border: 0;
  cursor: pointer;
  padding: 0.45rem 0.6rem;
  text-align: left;
}

/* ---------- Promotions tab ---------- */
.promo-grid {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
}
.promo-card {
  background: var(--color-surface-warm);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-4);
}
.promo-card.is-quiet {
  background: var(--color-surface-muted);
  opacity: 0.85;
}
.promo-card-head {
  align-items: flex-start;
  display: flex;
  gap: var(--space-3);
  justify-content: space-between;
}
.promo-card-name {
  display: block;
  font-size: var(--text-h4);
}
.promo-card-kind {
  color: var(--amber-700);
  font-size: var(--text-body-sm);
  font-weight: 800;
}
.promo-facts {
  display: grid;
  gap: 0.4rem;
  margin: var(--space-3) 0 0;
}
.promo-facts > div {
  display: grid;
  gap: var(--space-3);
  grid-template-columns: 3.5rem minmax(0, 1fr);
  font-size: var(--text-body-sm);
}
.promo-facts dt {
  color: var(--color-text-muted);
  font-weight: 800;
  text-transform: uppercase;
  font-size: var(--text-2xs);
  padding-top: 0.15rem;
  letter-spacing: 0.04em;
}
.promo-facts dd {
  margin: 0;
}
.promo-facts code {
  background: var(--color-surface-sunken);
  border-radius: 0.3rem;
  padding: 0.05rem 0.35rem;
}
.promo-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
}
.promo-card-actions {
  margin-top: 0.85rem;
}
.ops-drawer-wide {
  width: min(44rem, 100vw);
}
.promo-step {
  border: 1px solid var(--color-border);
  border-radius: 0.6rem;
  display: grid;
  gap: var(--space-3);
  margin: 0;
  padding: 0.9rem var(--space-4) var(--space-4);
}
.promo-step legend {
  align-items: center;
  display: flex;
  font-weight: 800;
  gap: var(--space-2);
  padding: 0 0.35rem;
}
.promo-step-no {
  align-items: center;
  background: #2f2b29;
  border-radius: var(--radius-full);
  color: var(--color-text-inverse);
  display: inline-flex;
  font-size: var(--text-xs);
  height: 1.35rem;
  justify-content: center;
  width: 1.35rem;
}
.promo-checks {
  display: grid;
  gap: var(--space-2);
}
.promo-checks .toggle-row small {
  color: var(--color-text-muted);
  display: block;
  font-size: var(--text-caption);
}
.promo-indent {
  margin-left: var(--space-10);
}
.promo-picker {
  display: grid;
  gap: 0.4rem;
}
/* Django renders CheckboxSelectMultiple as nested <div>s: the outer one
   becomes a wrapping row, each inner one dissolves, and every label is a
   chip that lights up when ticked. */
.promo-picker > div,
.promo-weekdays > div {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}
.promo-picker > div > div,
.promo-weekdays > div > div {
  display: contents;
}
.promo-picker > div {
  max-height: 14rem;
  overflow-y: auto;
}
.promo-picker label,
.promo-weekdays label {
  align-items: center;
  border: 1px solid #d9d3cc;
  border-radius: var(--radius-full);
  cursor: pointer;
  display: inline-flex;
  font-size: var(--text-sm);
  font-weight: 700;
  gap: 0.35rem;
  margin: 0;
  padding: 0.3rem 0.7rem;
}
.promo-picker label:has(input:checked),
.promo-weekdays label:has(input:checked) {
  background: #fdf3e7;
  border-color: var(--amber-700);
}
.promo-picker label input,
.promo-weekdays label input {
  margin: 0;
}
.promo-picker-search {
  max-width: 18rem;
}

/* ---- Add-ons tab (Wave 4A): list on the left, one editor on the right ---- */
.addon-layout {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: minmax(15rem, 18rem) minmax(0, 1fr);
  align-items: start;
}
@media (max-width: 60rem) {
  .addon-layout {
    grid-template-columns: minmax(0, 1fr);
  }
}
.addon-list-items {
  display: grid;
  gap: 0.4rem;
  margin-top: var(--space-3);
}
.addon-list-item {
  border: 1px solid var(--color-border);
  border-radius: 0.6rem;
  background: var(--color-surface-warm);
  color: inherit;
  display: grid;
  gap: 0.1rem;
  padding: 0.6rem 0.8rem;
  text-decoration: none;
}
.addon-list-item span {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}
.addon-list-item:hover {
  border-color: var(--brand-copper-dark);
}
.addon-list-item.is-selected {
  border-color: var(--amber-700);
  background: #fdf3e7;
}
.addon-list-item.is-inactive strong {
  color: var(--color-text-disabled);
}
.addon-list-new {
  margin-top: var(--space-3);
}
.addon-editor .form-grid {
  margin-top: var(--space-3);
}
.addon-empty {
  display: grid;
  gap: var(--space-3);
  justify-items: start;
  padding: var(--space-4) 0;
}
.addon-options {
  display: grid;
  gap: 0.6rem;
}
.addon-option {
  border: 1px solid var(--color-border);
  border-radius: 0.6rem;
  background: var(--color-surface);
  display: grid;
  gap: var(--space-2);
  padding: 0.7rem 0.8rem;
}
.addon-option.is-removed {
  opacity: 0.45;
}
.addon-option.is-removed .addon-option-stock {
  display: none;
}
.addon-option-main {
  align-items: end;
  display: grid;
  gap: 0.6rem;
  grid-template-columns: minmax(8rem, 2fr) minmax(6rem, 1fr) auto auto auto;
}
.addon-option-stock {
  align-items: end;
  display: grid;
  gap: 0.6rem;
  grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
  border-top: 1px dashed var(--color-border);
  padding-top: var(--space-2);
}
@media (max-width: 48rem) {
  .addon-option-main {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }
}
.addon-option .toggle-row {
  padding-bottom: 0.35rem;
}
.addon-option-remove {
  cursor: pointer;
  padding-bottom: 0.2rem;
}
.addon-option-remove input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
}
.addon-option-remove input:checked + span {
  background: var(--red-100);
  border-color: var(--red-700);
  color: var(--color-danger);
}
.addon-option-remove input:focus-visible + span {
  outline: 2px solid var(--brand-copper-dark);
  outline-offset: 2px;
}
.addon-option-errors {
  color: var(--color-danger);
  display: grid;
  font-size: var(--text-sm);
  gap: 0.2rem;
}
.addon-option-errors ul {
  margin: 0;
  padding-left: var(--space-4);
}
.addon-form-foot {
  align-items: end;
}
.addon-form-foot .toggle-row small {
  color: var(--color-text-muted);
  display: block;
  font-size: var(--text-caption);
}
[data-stock-only][hidden] {
  display: none;
}

/* --- Ingredient set-up pop-up (Item settings, D7) --------------------------
   The Grams / Millilitres / Pieces radios read as one control; the "We buy it
   as a [Bag] of [2] [kg] and pay [1.250] OMR per bag" sentence keeps its
   blanks inline and wraps on a phone; .drawer-echo is the live
   "≈ 0.000625 OMR per gram" line. Everything else reuses .checkbox-field,
   .field-pair and .settings-remove-note.

   2026-09-19: this one screen is a centred pop-up rather than a side sheet
   (owner's ask), and its three groups are flat -- no boxes, no lettering, no
   uppercase legends. The .ops-modal / .ing-* classes below are used ONLY by
   templates/operations/inventory_settings.html; .ops-drawer, .drawer-group
   and .drawer-subgroup are shared with the supplier drawer and are untouched,
   so ops-drawer.js still supplies focus, Escape, focus-return and the locked
   background here exactly as it does everywhere else. */
dialog.ops-drawer.ops-modal {
  inset: 0;
  margin: auto;
  /* Wide, not tall (owner, 2026-09-19): the form is laid out in columns, so
     the whole of Add and Edit fits on a laptop screen with nothing to scroll.
     94vw keeps a margin at every window width, so the pop-up can never be
     wider than the window. */
  width: min(76rem, 94vw);
  /* fit-content, not auto: a fixed box with inset:0 and height:auto is
     stretched to fill the screen, which left the form floating in an empty
     box on a big monitor. With a real height the auto margins centre it and
     the pop-up is exactly as tall as what is in it, up to the cap below. */
  height: fit-content;
  max-height: min(96dvh, 52rem);
  border: 1px solid var(--brand-line);
  border-radius: 0.9rem;
  box-shadow: var(--elevation-4);
  transform: none;
}
@starting-style {
  dialog.ops-drawer.ops-modal[open] {
    transform: translateY(0.75rem);
    opacity: 0;
  }
}
/* On a phone the same pop-up fills the screen: a long form behind a 85vh
   sheet meant scrolling a sheet inside a page. */
@media (max-width: 900px) {
  dialog.ops-drawer.ops-modal {
    inset: 0;
    width: 100%;
    height: 100dvh;
    max-height: none;
    border: 0;
    border-radius: var(--radius-none);
  }
  @starting-style {
    dialog.ops-drawer.ops-modal[open] {
      transform: translateY(1.5rem);
      opacity: 0;
    }
  }
}
/* Set by inventory-settings.js while the ingredient pop-up is open, so the
   page cannot slide about behind it. This screen only. */
html.ing-modal-open,
html.ing-modal-open body {
  overflow: hidden;
}
/* The form is a grid: three columns on a laptop, two in a small window, one
   on a phone (auto-fit does the choosing), with the full-width rows -- form
   errors, the big-change confirm -- spanning all of them. DOM order is fill
   order; the grid only decides where each group sits, so tab order is
   untouched. */
.ing-form.form-grid {
  grid-template-columns: 1fr;
  gap: 0.9rem var(--space-6);
  align-items: start;
}
/* Two columns in a small window, four on any normal laptop. Explicit rather
   than auto-fit: with four groups, a track count of three would drop one of
   them onto a second row and make the pop-up taller than the screen, which
   is the whole thing we are fixing. */
@media (min-width: 901px) {
  .ing-form.form-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
/* auto-fit rather than repeat(4): when "Costs nothing and never runs out"
   hides the buying and stock-sheet groups, the empty tracks collapse and the
   two that are left spread out, instead of leaving half a pop-up of nothing.
   16rem tracks mean four of them fit in every window this rule applies to. */
@media (min-width: 1250px) {
  .ing-form.form-grid {
    grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  }
}
/* Every row the pop-up spends on its frame is a row the form does not get:
   on this one screen the head, the body padding and the Save bar are a
   little tighter than the shared drawer's. */
.ops-modal .ops-drawer-head {
  padding: 0.7rem 1.1rem;
}
.ops-modal .ops-drawer-body {
  padding: 0.85rem 1.1rem;
}
.ing-span {
  grid-column: 1 / -1;
}
/* .form-grid makes every label a grid, which puts a <span> inside a label --
   "What we pay for one [bag] (before VAT)" -- on a row of its own, three
   deep. A label is a sentence. (.checkbox-field, .measure-option and
   .radio-row carry more specificity and keep their flex row.) */
.ing-form label {
  display: block;
}
/* The three measure pills share one line inside a column. */
.ing-form .measure-option {
  padding: 0.38rem 0.55rem;
  font-size: var(--text-sm);
  gap: 0.3rem;
}
.ing-form .measure-picker {
  gap: 0.3rem;
}
/* A field whose contents include a <details> cannot be a <p> (the parser
   closes the <p> at the <details>), so it is a div with the same layout. */
.ing-field {
  display: grid;
  gap: 0.35rem;
}
/* A group is a hairline and a quiet one-line label, not a titled box. */
.ing-section {
  margin: 0;
  min-width: 0;
  border: 0;
  border-top: 1px solid #f0efed;
  padding: 0.85rem 0 0;
}
/* A fieldset is not a grid container here on purpose: a rendered <legend> is
   laid out by the fieldset itself, not as a child, so a grid would leave it
   out of the gaps. Plain flow plus this owl rule keeps every row spaced. */
.ing-section > * + * {
  margin-top: 0.7rem;
}
.ing-section > legend {
  padding: 0;
  margin-bottom: 0.55rem;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  font-weight: 750;
}
.ing-hint {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  line-height: 1.45;
}
/* A quiet label above a control that is not a single input (the measure
   radios), so the column's own heading can name the whole group. */
.ing-sublabel {
  display: block;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  font-weight: 700;
}
/* Buying sits under measuring in the same column; a dashed hairline keeps
   the two apart without a second heading. */
.ing-subsection {
  border-top: 1px dashed var(--color-border);
  padding-top: 0.7rem;
}
.ing-rows {
  display: grid;
  gap: 0.6rem;
}
/* "[Bag] of [2] [kg]": one row where there is room for it (a phone's single
   column is 358 px wide), two lines in a laptop column (285 px), with the
   empty .ing-pack-break as the line break. The controls share the width
   instead of each claiming 9rem and wrapping where they like. */
.ing-pack-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
}
.ing-pack-row select,
.ing-pack-row input {
  width: auto;
  min-width: 0;
  flex: 1 1 4rem;
  padding: var(--space-2) 0.45rem;
}
.ing-pack-row > span {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}
.ing-levels {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.6rem 0.8rem;
}
@media (min-width: 901px) {
  .ing-levels {
    grid-template-columns: 1fr;
  }
}
.ing-pack-break {
  display: none;
}
@media (min-width: 901px) {
  .ing-pack-break {
    display: block;
    flex-basis: 100%;
    height: 0;
    margin: 0;
  }
}
/* .form-grid makes every <p> a grid, which breaks a sentence that has a
   <strong> in the middle of it into stacked rows. A plain sentence says so. */
p.ing-line {
  display: block;
}
.ing-sub {
  color: var(--color-text-secondary);
  font-size: var(--text-body-sm);
  font-weight: 800;
  margin-bottom: var(--space-2);
}
/* The naming rule, folded: one small line under the Name box that costs
   nothing until it is asked for. */
.ing-why > summary {
  cursor: pointer;
  color: var(--color-text-muted);
  font-size: var(--text-caption);
  font-weight: 700;
  list-style: revert;
}
.ing-why > summary::-webkit-details-marker {
  display: revert;
}
.ing-why > summary + * {
  margin-top: 0.3rem;
  display: block;
}
/* app.css hides the marker on every <details> by default; a disclosure the
   owner is meant to notice and open needs its triangle back. */
.ing-disclosure > summary,
.ing-more > summary {
  cursor: pointer;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  font-weight: 750;
  list-style: revert;
}
.ing-disclosure > summary::-webkit-details-marker,
.ing-more > summary::-webkit-details-marker {
  display: revert;
}
.ing-disclosure > summary + * {
  margin-top: 0.55rem;
}
.ing-more {
  margin-top: 0.2rem;
  border-top: 1px solid #f0efed;
  padding-top: 0.55rem;
}
.ing-more-body {
  margin-top: 0.8rem;
  /* Opened, this is the one part that may be taller than the pop-up; it is
     also the one nobody opens while adding an ingredient. Give it its own
     column so the danger zone does not run off the bottom. */
  display: grid;
  gap: 0.6rem var(--space-6);
}
@media (min-width: 901px) {
  .ing-more-body {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    align-items: start;
  }
}
/* The fields a first pass never fills (piece weights, cup weight, usable
   share) sit behind a one-line disclosure; this is the space they get once
   opened. .form-grid gives each <p> inside its own rows. */
.ing-disclosure-body {
  display: grid;
  gap: 0.7rem;
  margin-top: 0.55rem;
}
/* Save is a bar on the pop-up under the scrolling part, not a button at the
   end of the form: always in reach, and (unlike a floating bar) never over a
   field. The dialog is already a flex column with a scrolling body, so this
   just takes the last row. */
.ing-save-bar {
  border-top: 1px solid var(--brand-line);
  background: var(--color-surface);
  padding: 0.7rem 1.1rem;
  padding-bottom: calc(0.7rem + env(safe-area-inset-bottom, 0px));
}
.ing-save-bar .btn-primary {
  width: 100%;
}
/* Full width is right under one thumb on a phone; across a 1200 px pop-up it
   is just a brown band, so on a laptop Save is a button at the end of the
   row where a form's action belongs. */
@media (min-width: 901px) {
  .ing-save-bar {
    display: flex;
    justify-content: flex-end;
  }
  .ing-save-bar .btn-primary {
    width: auto;
    min-width: 11rem;
  }
}
@media (max-width: 900px) {
  /* A phone screen is the scarce one: take a little air out of the rows so
     more of the form is in front of the owner at once. */
  .ing-form.form-grid {
    gap: 0.6rem;
  }
  .ing-section {
    padding-top: 0.7rem;
  }
  .ing-section > * + * {
    margin-top: 0.6rem;
  }
}
.measure-picker {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}
/* .form-grid label is display:grid (box above text); a checkbox or radio row
   in the drawer keeps its box beside its words. */
.form-grid label.checkbox-field,
.form-grid label.measure-option,
.form-grid label.radio-row {
  display: flex;
}
.measure-option {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-full);
  background: var(--color-surface);
  color: var(--color-text-secondary);
  padding: 0.45rem 0.85rem;
  font-size: var(--text-body-sm);
  font-weight: 800;
  cursor: pointer;
}
.measure-option:hover,
.measure-option:has(input:checked) {
  border-color: var(--brand-copper-dark);
  background: var(--color-accent-soft);
  color: var(--brand-copper-dark);
}
.measure-option:has(input:disabled) {
  cursor: default;
  opacity: 0.75;
}
.measure-option:has(input:focus-visible) {
  outline: 2px solid var(--brand-copper-dark);
  outline-offset: 2px;
}
.measure-option input {
  margin: 0;
  accent-color: var(--brand-copper-dark);
}
.buy-sentence,
.unit-change-sentence {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.45rem var(--space-2);
  line-height: 1.5;
}
.buy-sentence input,
.buy-sentence select,
.unit-change-sentence input,
.unit-change-sentence select {
  width: auto;
  min-width: 5rem;
  max-width: 9rem;
  padding: 0.45rem 0.55rem;
}
.field-with-unit {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.field-with-unit > span {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  font-weight: 700;
  white-space: nowrap;
}
.drawer-echo {
  margin: 0;
  color: var(--brand-copper-dark);
  font-size: var(--text-body);
  font-weight: 750;
  font-variant-numeric: tabular-nums;
}
.drawer-indent {
  margin-left: var(--space-5);
}
.drawer-subgroup {
  border-top: 1px dashed var(--color-border);
  padding-top: 0.6rem;
}
.drawer-subgroup > summary {
  cursor: pointer;
  color: var(--color-text-secondary);
  font-size: var(--text-sm);
  font-weight: 800;
}
.drawer-subgroup > summary + * {
  margin-top: 0.6rem;
}
.radio-row {
  display: flex;
  align-items: flex-start;
  gap: 0.55rem;
  cursor: pointer;
}
.radio-row input[type="radio"] {
  width: auto;
  margin-top: 0.3rem;
  accent-color: var(--brand-copper-dark);
}

/* Recipe editors (menu item + prepared good): per-line usable-share list,
   the "This recipe makes" row and the plate-cost breakdown table. Folded in
   from the former _recipe_editor_styles.html partial. */
.line-hint[data-state="needs"] { color: var(--color-warning); }
.yield-override-list { display: grid; gap: var(--space-2); }
.yield-override-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-3);
  color: var(--color-text-secondary);
  font-size: var(--text-body-sm);
  font-weight: 600;
}
.yield-override-name { min-width: 0; overflow-wrap: anywhere; }
.yield-override-input { display: inline-flex; align-items: center; gap: 0.35rem; }
.yield-override-input input { width: 13rem; }
.yield-override-empty:not(:only-child) { display: none; }
.recipe-makes-inputs { display: grid; grid-template-columns: minmax(0, 1fr) minmax(6rem, auto); gap: var(--space-2); }
.recipe-makes-inputs select { min-width: 0; }
.plate-cost-table td.num,
.plate-cost-table th.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.plate-cost-table tbody td:first-child { font-weight: 700; color: var(--color-text-primary); }
.plate-cost-table .plate-cost-group th {
  background: var(--color-surface-muted);
  color: var(--color-text-secondary);
  font-size: var(--text-caption);
  letter-spacing: 0;
  text-transform: none;
}
.plate-cost-table .plate-cost-unknown td { color: var(--color-warning); }
.plate-cost-table .plate-cost-quiet { color: var(--color-text-subtle); }
.plate-cost-table tfoot th {
  border-bottom: 1px solid #eee9e3;
  color: var(--stone-700);
  font-size: var(--text-caption);
  letter-spacing: 0;
  text-align: right;
  text-transform: none;
}
.plate-cost-table tfoot td { color: var(--color-text-primary); }
.plate-cost-table tfoot .plate-cost-total th,
.plate-cost-table tfoot .plate-cost-total td { border-top: 2px solid #bdb7b1; font-weight: 800; }
@media (max-width: 560px) {
  .yield-override-row { grid-template-columns: 1fr; gap: 0.3rem; }
  .yield-override-input input { width: 100%; }
}

/* ---------- Suppliers (D11, S3): list rows, the supplier page, the catalogue ---------- */
/* A list row is one tap into the supplier's page; the buttons at its end
   keep their own click. The three secondary columns fold away on a phone so
   what is left is who, WhatsApp, terms, spend and owed. */
tr.supplier-row {
  cursor: pointer;
}
.supplier-list .supplier-note {
  display: block;
  color: var(--color-text-muted);
  font-size: var(--text-caption);
  font-weight: 600;
}
.supplier-owed {
  color: var(--color-warning);
}
.supplier-facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: 0.85rem var(--space-6);
  margin: 0;
}
.supplier-facts dt {
  color: var(--color-text-muted);
  font-size: var(--text-xs);
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.supplier-facts dd {
  margin: 0.15rem 0 0;
  font-size: var(--text-body);
  font-weight: 700;
  overflow-wrap: anywhere;
}
.supplier-facts-wide {
  grid-column: 1 / -1;
}
.supplier-two-up {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
  gap: var(--space-5);
}
.catalogue-table tr.row-usual > td:first-child {
  box-shadow: inset 3px 0 0 var(--brand-copper);
}
.catalogue-price-form {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0;
}
.catalogue-price-form input {
  width: 6.5rem;
}
.catalogue-history {
  margin-top: var(--space-1);
}
.catalogue-history > summary {
  cursor: pointer;
  color: var(--brand-copper-dark);
  font-size: var(--text-caption);
  font-weight: 800;
}
.catalogue-history ul {
  list-style: none;
  margin: 0.35rem 0 0;
  padding: 0;
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
}
.catalogue-history li + li {
  margin-top: 0.2rem;
}
.catalogue-add-row td {
  vertical-align: middle;
}
.catalogue-add-row select {
  min-width: 11rem;
}
.catalogue-add-row input[type="number"] {
  width: 6.5rem;
}
/* "[Bag] of [2] [kg]" reads as one phrase; the boxes wrap on a narrow cell. */
.catalogue-add-pack,
.catalogue-add-pack > span {
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.35rem;
}
.catalogue-add-pack select {
  min-width: 0;
}
.catalogue-add-pack input[type="number"] {
  width: 4.5rem;
}
.catalogue-add-pack input[type="text"] {
  width: 9rem;
}
@media (max-width: 700px) {
  .supplier-col-secondary {
    display: none;
  }
}
/* ---- Menu > Prices and Targets (plan D16 / M2) --------------------------- */
/* The suggestions table has eleven columns; on a phone each row becomes a
   small card (label/value pairs) instead of a sideways scroll. */
.price-head { align-items: flex-start; flex-wrap: wrap; }
.price-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); justify-content: flex-end; }
.price-actions form { margin: 0; }
.price-updated { color: var(--color-text-muted); font-size: var(--text-body-sm); }
.price-table th.num, .price-table td.num, .targets-table th.num, .targets-table td.num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
/* Eleven columns need room: the wrap scrolls sideways rather than the
   browser crushing Item and Why into one-word-per-line ribbons. */
.price-table { min-width: 60rem; }
.price-table td { vertical-align: top; }
.price-item { min-width: 11rem; }
.price-item-name { font-weight: 800; color: var(--color-text-primary); }
.price-item-meta { display: flex; flex-wrap: wrap; gap: 0.3rem; margin-top: 0.3rem; }
.price-suggested strong { color: var(--brand-copper-dark); }
.price-sub { display: block; color: var(--color-text-muted); font-size: var(--text-caption); font-weight: 500; white-space: nowrap; }
.price-why { color: var(--color-text-secondary); font-size: var(--text-body-sm); min-width: 12rem; max-width: 17rem; }
.price-row-actions { text-align: right; white-space: nowrap; }
.price-row-actions form { display: inline-flex; gap: var(--space-2); align-items: center; margin: 0; }
.price-table tr.is-flagged td:first-child { box-shadow: inset 3px 0 0 var(--amber-600); }
.price-legend { margin-top: 0.9rem; color: var(--color-text-muted); font-size: var(--text-sm); line-height: 1.5; }
.price-legend span { display: block; }
.price-details > summary { cursor: pointer; font-weight: 800; color: var(--color-text-primary); list-style: none; }
.price-details > summary::-webkit-details-marker { display: none; }
.price-details > summary::before { content: "\25B8"; display: inline-block; width: 1.1rem; color: var(--color-text-subtle); }
.price-details[open] > summary::before { content: "\25BE"; }
.price-plain-list { margin-top: var(--space-3); display: grid; gap: 0.35rem; }
.price-plain-list li { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--space-1) var(--space-4); padding: 0.35rem 0; border-top: 1px solid var(--stone-100); }
.price-plain-list li form { margin: 0; }
.price-plain-meta { color: var(--color-text-muted); font-size: var(--text-sm); }
.targets-table input[type="number"] { width: 9rem; max-width: 100%; }
.targets-table tr.has-error td { background: #fff7ed; }
.form-error { display: block; color: var(--color-danger-strong); font-size: var(--text-sm); font-weight: 600; margin-top: var(--space-1); }
@media (max-width: 720px) {
  .price-table thead { display: none; }
  .price-table { min-width: 0; }
  .price-table, .price-table tbody, .price-table tr, .price-table td { display: block; width: 100%; }
  .price-item, .price-why { min-width: 0; }
  .price-table tr { border: 1px solid var(--color-border); border-radius: 0.6rem; background: var(--color-surface); padding: var(--space-3) 0.85rem; margin-bottom: 0.7rem; }
  .price-table tr.is-flagged td:first-child { box-shadow: none; }
  .price-table tr.is-flagged { border-left: 3px solid var(--amber-600); }
  .price-table td { border: 0; padding: 0.2rem 0; text-align: left; }
  .price-table td.num { display: flex; justify-content: space-between; gap: var(--space-4); text-align: right; }
  .price-table td[data-label]::before { content: attr(data-label); color: var(--color-text-muted); font-size: var(--text-sm); font-weight: 700; flex: 1 1 auto; text-align: left; }
  .price-table td.price-why[data-label]::before, .price-table td[data-label="Type"]::before { display: block; margin-bottom: 0.1rem; }
  .price-table .price-sub { display: inline; margin-left: 0.3rem; white-space: normal; }
  .price-why { max-width: none; }
  .price-row-actions { text-align: left; padding-top: 0.6rem; }
  .price-row-actions form { display: flex; justify-content: space-between; width: 100%; }
  .targets-table thead { display: none; }
  .targets-table, .targets-table tbody, .targets-table tr, .targets-table td { display: block; width: 100%; }
  .targets-table tr { border: 1px solid var(--color-border); border-radius: 0.6rem; background: var(--color-surface); padding: var(--space-3) 0.85rem; margin-bottom: 0.7rem; }
  .targets-table td { border: 0; padding: var(--space-1) 0; text-align: left; }
  .targets-table td[data-label]::before { content: attr(data-label); display: block; color: var(--color-text-muted); font-size: var(--text-sm); font-weight: 700; }
  .targets-table td:first-child[data-label]::before { display: none; }
  .targets-table input[type="number"] { width: 100%; }
}

/* Purchases (D13, P2): the one-screen purchase form, the invoice page's
   badges and payment drawer, and the Purchases list. The lines table is an
   entry sheet, not a report -- on a phone each line stacks into a card with
   the column name printed above each box. */
.purchase-header-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: 0.8rem var(--space-4);
  align-items: start;
}
/* The invoice list is wider than a phone, so it scrolls sideways inside its
   own box. The hidden "Actions" label in the last column is positioned, and
   with nothing to anchor to it was measured against the whole page and slid
   the entire screen sideways on a phone; anchoring it here keeps it inside
   the box. (The same hidden-label rule does this on other screens too --
   reported, not fixed here, because that rule is shared.) */
.purchase-table-wrap {
  position: relative;
  max-width: 100%;
  -webkit-overflow-scrolling: touch;
}
.purchase-lines {
  width: 100%;
  border-collapse: collapse;
}
.purchase-lines th {
  text-align: left;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  font-weight: 800;
  padding: 0.35rem 0.4rem;
  white-space: nowrap;
}
.purchase-lines td {
  vertical-align: top;
  padding: 0.45rem 0.4rem;
  border-top: 1px solid #f0efed;
}
.purchase-lines select,
.purchase-lines input {
  min-width: 6rem;
}
.purchase-lines td:first-child {
  min-width: 14rem;
}
.purchase-lines .field-with-unit input {
  width: 7rem;
}
.purchase-line-expense {
  display: grid;
  gap: 0.45rem;
  margin-top: 0.45rem;
}
.purchase-line-invalid td {
  background: #fff7f7;
}
.purchase-line-total {
  padding-top: 0.95rem;
  font-weight: 750;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.purchase-line-remove {
  width: 3rem;
  text-align: right;
}
.purchase-line-x {
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-full);
  background: var(--color-surface);
  color: var(--color-text-muted);
  width: 2.2rem;
  height: 2.2rem;
  font-size: 1.2rem;
  line-height: 1;
  cursor: pointer;
}
.purchase-line-x:hover,
.purchase-line-x:focus-visible {
  border-color: var(--red-700);
  color: var(--color-danger);
}
.purchase-lines-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem var(--space-4);
}
.purchase-lines-foot .field-hint {
  flex: 1 1 18rem;
}
.purchase-totals-wrap {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(16rem, 22rem);
  gap: var(--space-4) var(--space-8);
  align-items: start;
  border-top: 1px solid var(--color-border);
  padding-top: var(--space-4);
}
.purchase-totals {
  margin: 0;
  display: grid;
  gap: 0.35rem;
  max-width: 22rem;
}
.purchase-totals div {
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
  color: var(--color-text-secondary);
  font-size: var(--text-body);
}
.purchase-totals dd {
  margin: 0;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
}
.purchase-totals-grand {
  border-top: 1px solid var(--color-border);
  padding-top: 0.35rem;
  color: var(--color-text-primary) !important;
  font-size: var(--text-h4) !important;
}
.purchase-totals-grand dd {
  font-weight: 850;
}
.purchase-receipt-check {
  display: grid;
  gap: 0.4rem;
}
.purchase-diff {
  margin: 0;
  border-radius: var(--radius-sm);
  padding: 0.55rem 0.7rem;
  font-size: var(--text-body-sm);
  font-weight: 650;
}
.purchase-diff[data-tone="warn"] {
  background: var(--amber-100);
  color: var(--color-warning);
}
.purchase-diff[data-tone="good"] {
  background: #ecfdf5;
  color: #065f46;
}
.purchase-photo {
  display: grid;
  gap: var(--space-3);
  max-width: 28rem;
}
.purchase-photo-thumb {
  display: block;
  width: 9rem;
  height: 9rem;
  object-fit: cover;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface-muted);
}
.purchase-pay-grid {
  display: grid;
  gap: 0.6rem;
  max-width: 34rem;
}
.purchase-pay-grid .radio-row {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  padding: 0.7rem 0.85rem;
  font-weight: 650;
  color: var(--color-text-primary);
}
.purchase-pay-grid .radio-row:has(input:checked) {
  border-color: var(--brand-copper-dark);
  background: var(--color-accent-soft);
}
.purchase-pay-grid .radio-row.is-disabled {
  color: var(--color-text-disabled);
  cursor: not-allowed;
}
.purchase-pay-by {
  margin-left: 1.9rem;
  max-width: 16rem;
}
.purchase-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 0.6rem;
}
.purchase-badges {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  vertical-align: middle;
}
.badge-quiet {
  background: var(--color-surface-sunken);
  color: var(--color-text-muted);
}
.purchase-links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem var(--space-4);
  font-size: var(--text-body-sm);
  font-weight: 700;
}
.purchase-line-typed {
  display: block;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  font-weight: 600;
}
/* The app showing its working under the money box: what one gram, one
   millilitre or one piece of this line cost. */
.purchase-line-each {
  display: block;
  margin-top: var(--space-1);
  color: var(--color-text-muted);
  font-size: var(--text-caption);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
@media (max-width: 720px) {
  .purchase-lines thead {
    display: none;
  }
  .purchase-lines,
  .purchase-lines tbody,
  .purchase-lines tr,
  .purchase-lines td {
    display: block;
    width: 100%;
  }
  .purchase-lines tr {
    position: relative;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-surface);
    padding: 0.7rem 0.8rem 0.8rem;
    margin-top: 0.7rem;
  }
  .purchase-lines td {
    border: 0;
    padding: 0.3rem 0;
    min-width: 0;
  }
  .purchase-lines td[data-label]::before {
    content: attr(data-label);
    display: block;
    color: var(--color-text-muted);
    font-size: var(--text-caption);
    font-weight: 800;
    margin-bottom: 0.2rem;
  }
  .purchase-lines td:first-child {
    padding-right: 2.6rem;
  }
  .purchase-lines select,
  .purchase-lines input,
  .purchase-lines .field-with-unit input {
    width: 100%;
    min-width: 0;
  }
  .purchase-line-total {
    padding-top: 0.3rem;
    text-align: left;
  }
  .purchase-line-remove {
    position: absolute;
    top: 0.55rem;
    right: 0.6rem;
    width: auto;
    padding: 0;
  }
  .purchase-totals-wrap {
    grid-template-columns: 1fr;
  }
  .purchase-actions {
    flex-direction: column-reverse;
  }
  .purchase-actions .btn-primary,
  .purchase-actions .btn-secondary {
    width: 100%;
    text-align: center;
  }
}
.purchase-detail-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: var(--space-4);
}

/* ==========================================================================
   Purchases & suppliers on a phone (390 px, one hand)
   --------------------------------------------------------------------------
   Every wide table here becomes one card per row under 700 px, the way the
   Prices and Targets tables already do: the <thead> is taken out of the
   flow and each cell prints its own column name from data-label. Nothing is
   hidden -- a phone shows the same nine or eight facts, stacked instead of
   sideways. The purchase form goes further: a line reads as one compact
   card (item and how many on one row, money and VAT on the next) and the
   running total rides with the save buttons on a bar stuck to the bottom of
   the screen, so adding lines never pushes Save out of reach.
   ========================================================================== */

/* ---- the shared card shape ---------------------------------------------- */
@media (max-width: 700px) {
  .supplier-list,
  .purchase-list,
  .catalogue-table,
  .invoice-lines {
    min-width: 0;
  }
  .supplier-list thead,
  .purchase-list thead,
  .catalogue-table thead,
  .invoice-lines thead {
    /* Out of the flow, still read by a screen reader that wants it. */
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .supplier-list, .supplier-list tbody, .supplier-list tr, .supplier-list td,
  .purchase-list, .purchase-list tbody, .purchase-list tr, .purchase-list td,
  .catalogue-table, .catalogue-table tbody, .catalogue-table tr, .catalogue-table td,
  .invoice-lines, .invoice-lines tbody, .invoice-lines tr, .invoice-lines td {
    display: block;
    width: 100%;
  }
  .supplier-list tr,
  .purchase-list tr,
  .catalogue-table tr,
  .invoice-lines tr {
    border: 1px solid var(--color-border);
    border-radius: 0.6rem;
    background: var(--color-surface);
    padding: var(--space-3) 0.85rem;
    margin-bottom: 0.7rem;
  }
  .supplier-list td,
  .purchase-list td,
  .catalogue-table td,
  .invoice-lines td {
    border: 0;
    padding: 0.2rem 0;
    text-align: left;
  }
  /* A labelled cell reads "Terms .......... Credit 30 days" on one line. */
  .supplier-list td[data-label],
  .purchase-list td[data-label],
  .catalogue-table td[data-label],
  .invoice-lines td[data-label] {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-4);
  }
  .supplier-list td[data-label]::before,
  .purchase-list td[data-label]::before,
  .catalogue-table td[data-label]::before,
  .invoice-lines td[data-label]::before {
    content: attr(data-label);
    flex: 0 0 auto;
    color: var(--color-text-muted);
    font-size: var(--text-sm);
    font-weight: 700;
  }
  /* The one-per-card headline: the name, big, with nothing in front of it. */
  .supplier-cell-name,
  .purchase-cell-number,
  .catalogue-cell-item,
  .invoice-cell-item {
    font-size: var(--text-body-lg);
    font-weight: 800;
    padding-bottom: 0.45rem !important;
  }
}

/* ---- Suppliers list ------------------------------------------------------ */
@media (max-width: 700px) {
  .supplier-table-wrap .striped-table { min-width: 0; }
  /* The three quieter columns used to disappear on a phone; in a card there
     is room for them, so the phone now shows everything the desk does. */
  .supplier-col-secondary { display: flex; }
  /* Who, what we owe them and what we spend are what the owner came for,
     so they read as full-width lines. The five quieter facts run on as one
     small wrapped line under them -- present, labelled, out of the way. */
  .supplier-list tr {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    row-gap: 0.1rem;
    column-gap: 0.8rem;
  }
  .supplier-list td.supplier-cell-name { flex: 1 1 100%; order: -3; }
  .supplier-list td.supplier-cell-owed { flex: 1 1 100%; order: -2; font-size: var(--text-body-lg); }
  .supplier-list td.supplier-cell-owed strong { font-size: var(--text-body-lg); }
  .supplier-list td.supplier-cell-spend { flex: 1 1 100%; order: -1; }
  .supplier-list td.supplier-cell-meta {
    flex: 0 1 auto;
    width: auto;
    justify-content: flex-start;
    gap: 0.3rem;
    color: var(--color-text-secondary);
    font-size: var(--text-sm);
  }
  .supplier-list td.supplier-cell-meta::before { font-size: var(--text-xs); }
  .supplier-list td.supplier-cell-chat .btn-compact { padding-top: 0.1rem; padding-bottom: 0.1rem; }
  .supplier-list td.supplier-cell-actions { flex: 1 1 100%; padding-top: 0.6rem; }
  .supplier-cell-actions .row-actions { display: flex; gap: var(--space-2); }
  .supplier-cell-actions .row-actions form { margin: 0; }
  .supplier-cell-actions .btn-secondary { flex: 1 1 auto; text-align: center; }
  .supplier-help-more { display: none; }
}

/* ---- Purchases list ------------------------------------------------------ */
@media (max-width: 700px) {
  .purchase-table-wrap .striped-table { min-width: 0; }
  /* The number, who it is from and what it came to read as full lines; the
     date, the line count and the two state badges run on underneath. */
  .purchase-list tr {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    row-gap: 0.1rem;
    column-gap: 0.8rem;
  }
  .purchase-list td.purchase-cell-number { flex: 1 1 100%; order: -3; }
  .purchase-list td.purchase-cell-number::before { display: none; }
  .purchase-list td.purchase-cell-supplier {
    flex: 1 1 100%;
    order: -2;
    display: block;
    color: var(--color-text-secondary);
    font-weight: 650;
  }
  .purchase-list td.purchase-cell-supplier::before { display: none; }
  .purchase-list td.purchase-cell-money { flex: 1 1 100%; order: -1; font-size: var(--text-body-lg); font-weight: 800; }
  .purchase-list td.purchase-cell-meta {
    flex: 0 1 auto;
    width: auto;
    justify-content: flex-start;
    gap: 0.3rem;
    color: var(--color-text-secondary);
    font-size: var(--text-sm);
  }
  .purchase-list td.purchase-cell-meta::before { font-size: var(--text-xs); }
  .purchase-list td.purchase-cell-actions { flex: 1 1 100%; padding-top: 0.6rem; }
  .purchase-cell-actions .row-actions { display: flex; gap: var(--space-4); }
}

/* ---- Supplier page: what we buy from them -------------------------------- */
@media (max-width: 700px) {
  .catalogue-table tr.row-usual > td:first-child { box-shadow: none; }
  .catalogue-table tr.row-usual { border-left: 3px solid var(--brand-copper); }
  .catalogue-price-form { justify-content: flex-end; }
  .catalogue-price-form input { width: 6rem; }
  .catalogue-cell-actions { padding-top: var(--space-2) !important; }
  /* The "Add an item" row is a form, so its boxes go full width and its
     button sits under them where a thumb expects it. */
  .catalogue-add-row td[data-label] { display: block; }
  .catalogue-add-row td[data-label]::before {
    content: attr(data-label);
    display: block;
    color: var(--color-text-muted);
    font-size: var(--text-sm);
    font-weight: 700;
    margin-bottom: 0.2rem;
  }
  .catalogue-add-row select,
  .catalogue-add-row input[type="number"],
  .catalogue-add-row .field-with-unit { width: 100%; min-width: 0; }
  .catalogue-add-pack { display: grid; gap: 0.35rem; }
  .catalogue-add-pack > span { display: flex; }
  .catalogue-add-pack input[type="number"],
  .catalogue-add-pack input[type="text"] { width: 100%; }
  .catalogue-add-submit { padding-top: 0.7rem !important; }
  .catalogue-add-submit .btn-primary { width: 100%; }
}

/* The "Add an item" boxes sit in the table and reach their form through
   form=, so they are outside any <form> element and the shared "form input"
   box never reached them: they drew with no border at any width. */
.catalogue-add-row input,
.catalogue-add-row select {
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-xs);
  padding: 0.55rem 0.7rem;
  background: var(--color-surface);
}

/* A text link is a 22 px tap target; in a card, where it is the only way
   out of the row, give the thumb a full-height one. */
@media (max-width: 700px) {
  .purchase-cell-actions .detail-link,
  .supplier-cell-actions .btn-secondary,
  .catalogue-cell-actions .btn-link {
    display: inline-flex;
    align-items: center;
    min-height: 2.5rem;
  }
}

/* ---- Invoice page -------------------------------------------------------- */
@media (max-width: 700px) {
  .invoice-lines tr { margin-bottom: 0.6rem; }
  .invoice-lines .purchase-line-typed { display: inline; margin-left: 0.3rem; }
}

/* ---- Reports > Purchases: the two five-column tables --------------------- */
@media (max-width: 560px) {
  #purchasesUnpaidTable thead,
  #purchasesPriceTable thead { display: none; }
  #purchasesUnpaidTable, #purchasesUnpaidTable tbody, #purchasesUnpaidTable tr, #purchasesUnpaidTable td,
  #purchasesPriceTable, #purchasesPriceTable tbody, #purchasesPriceTable tr, #purchasesPriceTable td {
    display: block;
    width: 100%;
  }
  #purchasesUnpaidTable tfoot, #purchasesUnpaidTable tfoot tr, #purchasesUnpaidTable tfoot td { display: block; width: 100%; }
  #purchasesUnpaidTable tr,
  #purchasesPriceTable tr {
    border-bottom: 1px solid var(--line);
    padding: var(--space-3) 0;
  }
  #purchasesUnpaidTable td,
  #purchasesPriceTable td { border: 0; padding: 2px 0; text-align: left; }
  #purchasesUnpaidTable td[data-label],
  #purchasesPriceTable td[data-label] {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-4);
  }
  #purchasesUnpaidTable td[data-label]::before,
  #purchasesPriceTable td[data-label]::before {
    content: attr(data-label);
    color: var(--ink-muted);
    font-size: var(--text-sm);
    font-weight: 650;
  }
  #purchasesUnpaidTable td small,
  #purchasesPriceTable td small { display: inline; margin-left: 0.35rem; }
  .rp-cell-lead { font-weight: 700; padding-bottom: 0.3rem !important; }
  .rp-cell-action { padding-top: 0.45rem !important; }
  .rp-cell-action .an-btn { display: block; text-align: center; }
}

/* ---- The purchase form: fewest taps, least scrolling --------------------- */
/* A quiet fold. Everything inside still posts and is still reachable with a
   keyboard; it is closed only because most receipts never need it. */
.purchase-optional > summary,
.purchase-optional-panel > summary {
  cursor: pointer;
  list-style: none;
  color: var(--brand-copper-dark);
  font-size: var(--text-body-sm);
  font-weight: 750;
  padding: 0.2rem 0;
}
.purchase-optional > summary::-webkit-details-marker,
.purchase-optional-panel > summary::-webkit-details-marker { display: none; }
.purchase-optional > summary::before,
.purchase-optional-panel > summary::before {
  content: "\25B8";
  display: inline-block;
  width: 1.1rem;
  color: var(--color-text-subtle);
}
.purchase-optional[open] > summary::before,
.purchase-optional-panel[open] > summary::before { content: "\25BE"; }
.purchase-optional-panel > summary { color: inherit; }
.purchase-optional-panel > summary .panel-title { display: inline; }
.purchase-optional-body { margin-top: 0.6rem; display: grid; gap: var(--space-2); }
/* The copy of the running total that rides in the save bar. Hidden on a
   desk, where the totals list is already on screen next to the buttons. */
.purchase-actions-total { display: none; margin: 0; }

@media (max-width: 720px) {
  /* A line is one card: item and how many on the first row, what it cost
     and VAT on the second, the line total under them. Tab order still runs
     down the line in the order a person reads it, because the cells are in
     that order in the page. */
  .purchase-lines tr {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 7.25rem;
    gap: 0.3rem 0.6rem;
    align-items: start;
    padding: 0.7rem 2.9rem var(--space-3) 0.8rem;
    scroll-margin-bottom: 8rem;
  }
  .purchase-lines td { display: block; padding: 0.15rem 0; }
  .purchase-lines td:first-child { padding-right: 0; }
  .purchase-cell-item { grid-column: 1; }
  .purchase-cell-qty { grid-column: 2; }
  .purchase-cell-cost { grid-column: 1; }
  .purchase-cell-vat { grid-column: 2; }
  .purchase-lines td[data-label]::before { margin-bottom: 0.1rem; }
  .purchase-lines .purchase-line-total {
    grid-column: 1 / -1;
    display: flex;
    justify-content: space-between;
    gap: var(--space-4);
    border-top: 1px solid #f0efed;
    margin-top: 0.2rem;
    padding-top: 0.4rem;
  }
  .purchase-lines .purchase-line-total::before {
    content: "Line total";
    color: var(--color-text-muted);
    font-size: var(--text-caption);
    font-weight: 800;
  }

  /* The save bar sticks to the bottom of the screen: however many lines are
     on the sheet, the total and "Save and receive stock" are one tap away. */
  .purchase-actions {
    position: sticky;
    bottom: 0;
    z-index: var(--z-sticky);
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: var(--space-2) var(--space-3);
    align-items: center;
    margin-left: -1rem;
    margin-right: -1rem;
    border-top: 1px solid var(--color-border);
    background: var(--color-surface);
    box-shadow: var(--elevation-2-up);
    padding: 0.65rem var(--space-4) calc(0.65rem + env(safe-area-inset-bottom, 0px));
  }
  .purchase-actions-total {
    display: flex;
    align-items: baseline;
    gap: 0.4rem;
    grid-column: 1;
    font-variant-numeric: tabular-nums;
  }
  .purchase-actions-total span { color: var(--color-text-muted); font-size: var(--text-sm); font-weight: 700; }
  .purchase-actions-total strong { font-size: var(--text-h4); font-weight: 850; }
  .purchase-actions .btn-secondary { grid-column: 2; width: auto; }
  .purchase-actions .btn-primary { grid-column: 1 / -1; width: 100%; text-align: center; }
}
