/*
 * This is a manifest file that'll be compiled into application.css.
 *
 * With Propshaft, assets are served efficiently without preprocessing steps. You can still include
 * application-wide styles in this file, but keep in mind that CSS precedence will follow the standard
 * cascading order, meaning styles declared later in the document or manifest will override earlier ones,
 * depending on specificity.
 *
 * Consider organizing styles into separate files for maintainability.
 */

/* ── Design tokens ─────────────────────────────────────────────────────────────────────────
   Inlined from what used to be design_tokens.css, imported here as `@import "design_tokens"`.
   That import never worked in production. Propshaft does not resolve CSS @import at build time —
   the browser resolves it, against an undigested path that production does not serve — so the
   file 404'd and every global --color-* / --space-* token below was undefined for real users.
   75 rules in this file referenced them; flash messages, borders and muted text were falling
   back to browser defaults. It went unnoticed because the newer surfaces (customer, dashboard,
   bartender, onboarding, admin) each define their own scoped --*-color-* tokens further down
   THIS file, so they were unaffected.

   Kept in one file deliberately: with Propshaft the alternative is a stylesheet_link_tag in
   every layout, which is nine places to keep in sync and a tenth to forget.
   ───────────────────────────────────────────────────────────────────────────────────────── */
/* =============================================================
   Scanord — Design Tokens
   These are the global Ascent tokens. The newer per-surface scopes (--order-color-*,
   --dash-color-*, --bar-color-*, --onboard-color-*) are defined further down this same file,
   each on its own body class.
   ============================================================= */

/* Google Fonts */

/* -------------------------------------------------------------
   Color Tokens
   ------------------------------------------------------------- */
:root {
  /* Neutrals */
  --color-text:        #0a0a0d;   /* near-black, primary text */
  --color-text-muted:  #3d3d4d;   /* secondary / helper text */
  --color-bg:          #fafafd;   /* near-white page background */
  --color-surface:     #f0f0fa;   /* cards, panels */
  --color-border:      #d8d8f0;   /* dividers, input borders */

  /* Blue system — indigo family */
  --color-primary:     #4645c7;   /* main CTAs, active states */
  --color-primary-hover: #3534a8; /* hover / pressed */
  --color-primary-light: #ebebfb; /* tinted backgrounds, badges */
  --color-secondary:   #8a89ee;   /* secondary buttons, tags */
  --color-accent-blue: #3e3dfb;   /* links, highlights */

  /* Warm accent — amber/terracotta family */
  --color-warm:        #c97941;   /* primary warm accent */
  --color-warm-hover:  #b0672f;   /* hover state */
  --color-warm-light:  #fdf0e6;   /* tinted warm backgrounds */
  --color-warm-muted:  #e8a97a;   /* soft warm, e.g. tags, icons */

  /* Semantic / status colors */
  --color-success:     #3d8c5e;
  --color-success-light: #e6f4ed;
  --color-warning:     #c97941;   /* reuses warm accent */
  --color-warning-light: #fdf0e6;
  --color-danger:      #c0392b;
  --color-danger-light: #fdecea;

  /* Order status colors — bartender board */
  --color-status-pending:    #8a89ee;   /* indigo-muted */
  --color-status-confirmed:  #3e3dfb;   /* accent indigo */
  --color-status-preparing:  #c97941;   /* warm amber — in progress */
  --color-status-ready:      #3d8c5e;   /* green — ready to deliver */
  --color-status-delivered:  #4a4d56;   /* muted — done */
  --color-status-cancelled:  #c0392b;   /* red */

  /* Modal / overlay backgrounds */
  --color-modal-background: #eaeaf5;   /* soft lavender — modals, overlays, form sections */
}

/* -------------------------------------------------------------
   Typography Tokens
   ------------------------------------------------------------- */
:root {
  /* Families */
  --font-body:    'Hind', 'Segoe UI', system-ui, sans-serif;
  --font-display: 'DM Serif Display', Georgia, serif;
    /* DM Serif Display is used sparingly for hero headings and
       the customer-facing menu — adds warmth without sacrificing
       readability. All UI chrome uses Hind only. */

  /* Weights */
  --font-weight-regular:  400;
  --font-weight-medium:   500;
  --font-weight-semibold: 600;
  --font-weight-bold:     700;

  /* Scale (Major Third — 1.25 ratio) */
  --text-xs:   0.640rem;   /*  ~10px */
  --text-sm:   0.800rem;   /*  ~13px */
  --text-base: 1.000rem;   /*   16px */
  --text-md:   1.250rem;   /*   20px */
  --text-lg:   1.563rem;   /*   25px */
  --text-xl:   1.953rem;   /*  ~31px */
  --text-2xl:  2.441rem;   /*  ~39px */
  --text-3xl:  3.052rem;   /*  ~49px */

  /* Line heights */
  --leading-tight:  1.2;
  --leading-snug:   1.4;
  --leading-normal: 1.6;
  --leading-loose:  1.8;
}

/* -------------------------------------------------------------
   Spacing Tokens (8px base grid)
   ------------------------------------------------------------- */
:root {
  --space-1:   0.25rem;   /*  4px */
  --space-2:   0.50rem;   /*  8px */
  --space-3:   0.75rem;   /* 12px */
  --space-4:   1.00rem;   /* 16px */
  --space-5:   1.25rem;   /* 20px */
  --space-6:   1.50rem;   /* 24px */
  --space-8:   2.00rem;   /* 32px */
  --space-10:  2.50rem;   /* 40px */
  --space-12:  3.00rem;   /* 48px */
  --space-16:  4.00rem;   /* 64px */
  --space-20:  5.00rem;   /* 80px */
}

/* -------------------------------------------------------------
   Border Radius Tokens
   ------------------------------------------------------------- */
:root {
  --radius-sm:   0.25rem;   /*  4px — inputs, badges */
  --radius-md:   0.50rem;   /*  8px — cards, buttons */
  --radius-lg:   0.75rem;   /* 12px — modals, panels */
  --radius-xl:   1.00rem;   /* 16px — large cards */
  --radius-full: 9999px;    /* pills */
}

/* -------------------------------------------------------------
   Shadow Tokens
   ------------------------------------------------------------- */
:root {
  --shadow-xs: 0 1px 2px rgba(13, 14, 16, 0.06);
  --shadow-sm: 0 1px 4px rgba(13, 14, 16, 0.08);
  --shadow-md: 0 4px 12px rgba(13, 14, 16, 0.10);
  --shadow-lg: 0 8px 24px rgba(13, 14, 16, 0.12);
  --shadow-xl: 0 16px 40px rgba(13, 14, 16, 0.14);
}

/* -------------------------------------------------------------
   Transition Tokens
   ------------------------------------------------------------- */
:root {
  --transition-fast:   100ms ease;
  --transition-base:   200ms ease;
  --transition-slow:   350ms ease;
}

/* -------------------------------------------------------------
   Z-index Scale
   ------------------------------------------------------------- */
:root {
  --z-base:    0;
  --z-raised:  10;
  --z-dropdown: 100;
  --z-sticky:  200;
  --z-modal:   300;
  --z-toast:   400;
}

/* -------------------------------------------------------------
   Base Reset & Defaults
   ------------------------------------------------------------- */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  font-size: 100%;
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  font-family: var(--font-body);
  font-weight: var(--font-weight-regular);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  color: var(--color-text);
  background-color: var(--color-bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-body);
  font-weight: var(--font-weight-bold);
  line-height: var(--leading-tight);
  color: var(--color-text);
}

/* Display headings — use on customer-facing pages only */
.display-heading {
  font-family: var(--font-display);
  font-weight: var(--font-weight-regular); /* DM Serif is elegant at regular weight */
}

h1 { font-size: var(--text-3xl); }
h2 { font-size: var(--text-2xl); }
h3 { font-size: var(--text-xl);  }
h4 { font-size: var(--text-lg);  }
h5 { font-size: var(--text-md);  }
h6 { font-size: var(--text-base); }

a {
  color: var(--color-accent-blue);
  text-decoration: none;
  transition: color var(--transition-fast);
}
a:hover { color: var(--color-primary-hover); }

/* -------------------------------------------------------------
   Tailwind CSS Variable Bridge
   Add to tailwind.config.js to expose tokens as Tailwind utilities.

   theme: {
     extend: {
       colors: {
         'primary':      'var(--color-primary)',
         'primary-hover':'var(--color-primary-hover)',
         'warm':         'var(--color-warm)',
         'warm-light':   'var(--color-warm-light)',
         'surface':      'var(--color-surface)',
         'border-base':  'var(--color-border)',
         ... etc
       }
     }
   }
   ------------------------------------------------------------- */

.flash {
  padding: var(--space-3) var(--space-4);
  margin: var(--space-4);
  border-radius: var(--radius-md);
  font-weight: var(--font-weight-medium);
}
.flash-notice { background: var(--color-success-light); color: var(--color-success); }
.flash-alert  { background: var(--color-danger-light);  color: var(--color-danger);  }

.signup-card {
  max-width: 28rem;
  margin: var(--space-12) auto;
  padding: var(--space-8);
  background: #eaeaf5 !important;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}
.signup-card h1 { margin-bottom: var(--space-2); }
.signup-card .meta {
  color: var(--color-text-muted);
  margin-bottom: var(--space-6);
}
.signup-card .meta.center,
.signup-card.center { text-align: center; }

.signup-form .field { margin-bottom: var(--space-4); }
.signup-form label {
  display: block;
  margin-bottom: var(--space-1);
  font-weight: var(--font-weight-medium);
}
.signup-form input[type="text"],
.signup-form input[type="email"],
.signup-form input[type="password"] {
  width: 100%;
  padding: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font: inherit;
  background: var(--color-bg);
}
.signup-form .hint {
  margin-top: var(--space-1);
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}
.signup-form .actions input[type="submit"] {
  background: var(--color-primary);
  color: var(--color-bg);
  border: 0;
  padding: var(--space-3) var(--space-6);
  border-radius: var(--radius-md);
  font: inherit;
  font-weight: var(--font-weight-semibold);
  cursor: pointer;
}
.signup-form .actions input[type="submit"]:hover { background: var(--color-primary-hover); }

.form-errors {
  background: var(--color-danger-light);
  color: var(--color-danger);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  margin-bottom: var(--space-4);
}
.form-errors ul { margin: var(--space-2) 0 0 var(--space-5); }

/* ============================================================
   Auth card — login / signup pages
   Blueprint design language — scoped locally to these two pages
   only (via .auth-page), intentionally distinct from the app-wide
   Ascent tokens in design_tokens.css. See CLAUDE.md Design System.
   ============================================================ */

.auth-page {
  --color-bg: #f2f2f3;
  --color-surface: #e9e9ea;
  --color-text: #1d1f20;
  --color-accent: #5980a6;
  --color-divider: color-mix(in srgb, #1d1f20 16%, transparent);
  --color-accent-600: #597ea3;
  --color-accent-700: #416180;
  --color-accent-800: #2c455d;
  --color-accent-900: #1d2d3d;
  --font-heading: "Barlow Condensed", system-ui, sans-serif;
  --font-heading-weight: 600;
  --font-body: "Barlow", system-ui, sans-serif;
  --auth-space-2: 6.8px;
  --auth-space-3: 10.2px;
  --auth-space-4: 13.6px;
  --auth-radius-md: 4px;
  --auth-leading: 24px;
  --auth-half: 12px;
  --auth-edge: clamp(20px, 5vw, 72px);

  font-family: var(--font-body);
  color: var(--color-text);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

.auth-page .nav {
  display: flex;
  align-items: center;
  padding: var(--auth-half) var(--auth-edge);
}
/* The logo's link back to the landing page. This rule used to style a TEXT brand and was
   orphaned when the logo image replaced it — the typographic properties it carried (font-size,
   letter-spacing) styled a string no element holds any more. Repurposed rather than deleted,
   since the class name is still the right one for the slot.

   inline-flex so the anchor wraps the image tightly: an inline <a> around a block image leaves
   a few pixels of line-box descender under it, which shows up as the nav sitting very slightly
   off-centre. text-decoration:none because a UA underline would return the moment anyone puts
   a text fallback back inside. */
.auth-page .nav-brand {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  color: var(--color-text);
}
.auth-page .nav-brand-logo {
  display: block;
  height: 68px;
  width: auto;
}

.auth-wrap {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: calc(2 * var(--auth-leading)) var(--auth-edge);
}

.auth-card {
  position: relative;
  width: 100%;
  max-width: 26rem;
  padding: calc(2 * var(--auth-leading));
  background: color-mix(in srgb, var(--color-bg) 88%, transparent);
  backdrop-filter: blur(6px);
  border: 1px solid var(--color-divider);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.12);
}
.auth-card > .corner {
  position: absolute;
  width: 15px;
  height: 15px;
  color: color-mix(in srgb, var(--color-text) 55%, transparent);
  pointer-events: none;
}
.auth-card > .corner::before {
  content: ""; position: absolute; left: 7px; top: 0; width: 1px; height: 100%; background: currentColor;
}
.auth-card > .corner::after {
  content: ""; position: absolute; top: 7px; left: 0; width: 100%; height: 1px; background: currentColor;
}
.auth-card > .corner.tl { top: -8px; left: -8px; }
.auth-card > .corner.tr { top: -8px; right: -8px; }
.auth-card > .corner.bl { bottom: -8px; left: -8px; }
.auth-card > .corner.br { bottom: -8px; right: -8px; }

.auth-card .kicker {
  display: block;
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--color-accent-700);
  margin: 0 0 var(--auth-half);
}
.auth-card h1 {
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  font-size: 28px;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  margin: 0 0 var(--auth-half);
  color: var(--color-text);
}
.auth-card .meta {
  color: color-mix(in srgb, var(--color-text) 78%, transparent);
  margin-bottom: var(--auth-leading);
  font-size: 16px;
  line-height: 1.5;
}

.auth-form .field { margin-bottom: var(--auth-leading); }
.auth-form label {
  display: block;
  margin-bottom: 5px;
  font-size: 14px;
  color: color-mix(in srgb, var(--color-text) 85%, transparent);
}
.auth-form input[type="text"],
.auth-form input[type="email"],
.auth-form input[type="password"],
.auth-form input[type="tel"],
.auth-form textarea,
.auth-form select {
  width: 100%;
  min-height: 36px;
  padding: 6px 10px;
  font: inherit;
  font-size: 15px;
  color: var(--color-text);
  /* Lighter than the card, not darker. --color-surface (#e9e9ea) is a shade BELOW the card's
     own --color-bg (#f2f2f3), so fields used to sink into the panel instead of reading as
     places you type. Solid white rather than a translucent mix: the card is frosted over a
     photo, so anything semi-transparent here shifts tone with whatever is behind it. */
  background: #fff;
  border: 1px solid var(--color-divider);
  border-radius: var(--auth-radius-md);
}
.auth-form textarea { resize: vertical; line-height: 1.5; padding: 8px 10px; }

/* Selects need appearance:none plus our own arrow, otherwise the browser paints its native
   control and the field is the one thing on the form that ignores the design system. The arrow
   is an inline SVG data URI so it needs no asset and inherits nothing from the OS theme. */
.auth-form select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 32px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%231d1f20' stroke-width='1.6' stroke-linecap='square'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 11px center;
  cursor: pointer;
}

.auth-form input[type="text"]:hover,
.auth-form input[type="email"]:hover,
.auth-form input[type="password"]:hover,
.auth-form input[type="tel"]:hover,
.auth-form textarea:hover,
.auth-form select:hover {
  border-color: color-mix(in srgb, var(--color-text) 45%, transparent);
}
.auth-form input[type="text"]:focus,
.auth-form input[type="email"]:focus,
.auth-form input[type="password"]:focus,
.auth-form input[type="tel"]:focus,
.auth-form textarea:focus,
.auth-form select:focus {
  outline: none;
  border-color: var(--color-accent);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--color-accent) 25%, transparent);
}

.auth-form .row-between {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--auth-space-3);
  margin-bottom: var(--auth-leading);
  font-size: 15px;
  flex-wrap: wrap;
}
.auth-form .field-checkbox {
  display: flex;
  align-items: center;
  gap: var(--auth-space-2);
  margin: 0;
}
.auth-form .field-checkbox input[type="checkbox"] {
  width: 1rem;
  height: 1rem;
  accent-color: var(--color-accent);
  flex-shrink: 0;
  cursor: pointer;
}
.auth-form .field-checkbox label {
  margin: 0;
  font-size: 15px;
  color: var(--color-text);
  cursor: pointer;
}
.auth-form .row-between a {
  color: var(--color-accent-700);
  font-size: 15px;
}
.auth-form .row-between a:hover { color: var(--color-accent-900); }

.auth-form .grid-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--auth-leading);
}
@media (max-width: 480px) {
  .auth-form .grid-2 { grid-template-columns: 1fr; }
}

.auth-form .actions {
  margin-top: var(--auth-space-2);
}
.auth-form .actions input[type="submit"] {
  width: 100%;
  background: var(--color-accent-900);
  color: var(--color-bg);
  border: 1px solid var(--color-accent-900);
  padding: 10px var(--auth-space-4);
  border-radius: var(--auth-radius-md);
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  font-size: 16px;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  cursor: pointer;
  min-height: 44px;
}
.auth-form .actions input[type="submit"]:hover { background: var(--color-accent-800); border-color: var(--color-accent-800); }
.auth-form .actions input[type="submit"]:active { background: var(--color-accent-700); border-color: var(--color-accent-700); }

.auth-card .foot-note {
  margin-top: var(--auth-leading);
  font-size: 15px;
  text-align: center;
  color: color-mix(in srgb, var(--color-text) 78%, transparent);
}
.auth-card .foot-note a { color: var(--color-accent-700); }
.auth-card .foot-note a:hover { color: var(--color-accent-900); }

/* ============================================================
   Onboarding Wizard — "Industry" system, sixth token scope
   (after .auth-page, .customer-body/.order-*, .dashboard-body,
   .bartender-body). Same hex family as the other five, own
   --onboard-* names so a palette change to one scope can't leak
   into another. See CLAUDE.md Design System.
   ============================================================ */

.onboarding-body {
  --onboard-color-bg: #f2f2f3;
  --onboard-color-surface: #e9e9ea;
  --onboard-color-text: #1d1f20;
  --onboard-color-divider: color-mix(in srgb, #1d1f20 16%, transparent);
  --onboard-color-accent-100: #eef6ff;
  --onboard-color-accent-500: #749dc4;
  --onboard-color-accent-600: #597ea3;
  --onboard-color-accent-700: #416180;
  --onboard-color-accent-800: #2c455d;
  --onboard-color-accent-900: #1d2d3d;
  --onboard-font-heading: "Barlow Condensed", system-ui, sans-serif;
  --onboard-font-heading-weight: 600;
  --onboard-font-body: "Barlow", system-ui, sans-serif;

  margin: 0;
  min-height: 100vh;
  background: var(--onboard-color-bg);
  color: var(--onboard-color-text);
  font-family: var(--onboard-font-body);
}

.onboarding-header {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 24px;
  border-bottom: 1px solid var(--onboard-color-divider);
}
.onboarding-header-logo { display: block; height: 68px; width: auto; }
.onboarding-header-shop {
  font-family: var(--onboard-font-heading);
  font-weight: var(--onboard-font-heading-weight);
  font-size: 15px;
  color: color-mix(in srgb, var(--onboard-color-text) 70%, transparent);
  padding-left: 14px;
  border-left: 1px solid var(--onboard-color-divider);
}

.onboarding-main {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 48px 24px 64px;
}

.onboarding-shell { width: 100%; max-width: 40rem; }

/* The flash is a direct child of .onboarding-main alongside .onboarding-shell. Without an
   explicit column direction above it sat *beside* the card as a second flex item, which on a
   phone squeezed the card off-screen (horizontal scroll). It now stacks above the card and
   shares the shell's width. Square corners + no outer margin to match the Industry scope —
   the global .flash is an Ascent component (rounded, var(--space-4) margin). */
.onboarding-body .flash {
  width: 100%;
  max-width: 40rem;
  margin: 0 0 20px;
  border-radius: 0;
}

@media (max-width: 540px) {
  .onboarding-main { padding: 24px 16px 48px; }
}

.onboarding-card {
  position: relative;
  background: var(--onboard-color-surface);
  border: 1px solid var(--onboard-color-divider);
}
.onboarding-card > .corner {
  position: absolute;
  width: 12px;
  height: 12px;
  color: color-mix(in srgb, var(--onboard-color-text) 55%, transparent);
  pointer-events: none;
}
.onboarding-card > .corner::before { content: ""; position: absolute; left: 5px; top: 0; width: 1px; height: 100%; background: currentColor; }
.onboarding-card > .corner::after { content: ""; position: absolute; top: 5px; left: 0; width: 100%; height: 1px; background: currentColor; }
.onboarding-card > .corner.tl { top: -6px; left: -6px; }
.onboarding-card > .corner.tr { top: -6px; right: -6px; }
.onboarding-card > .corner.bl { bottom: -6px; left: -6px; }
.onboarding-card > .corner.br { bottom: -6px; right: -6px; }

.onboarding-stepper {
  padding: 20px 32px;
  border-bottom: 1px solid var(--onboard-color-divider);
}
.onboarding-stepper ol {
  list-style: none;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 8px;
  margin: 0;
  padding: 0;
}
.onboarding-stepper li {
  flex: 1;
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.onboarding-stepper li .bullet {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border: 1px solid var(--onboard-color-divider);
  background: var(--onboard-color-bg);
  color: color-mix(in srgb, var(--onboard-color-text) 55%, transparent);
  font-family: var(--onboard-font-heading);
  font-weight: var(--onboard-font-heading-weight);
  font-size: 13px;
  margin-bottom: 6px;
  z-index: 1;
}
.onboarding-stepper li .label {
  font-family: var(--onboard-font-heading);
  font-weight: var(--onboard-font-heading-weight);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: color-mix(in srgb, var(--onboard-color-text) 55%, transparent);
}

/* connector line between bullets */
.onboarding-stepper li::before {
  content: "";
  position: absolute;
  top: 14px;
  left: -50%;
  right: 50%;
  height: 1px;
  background: var(--onboard-color-divider);
  z-index: 0;
}
.onboarding-stepper li:first-child::before { display: none; }

.onboarding-stepper li.done .bullet {
  background: var(--onboard-color-accent-800);
  border-color: var(--onboard-color-accent-800);
  color: var(--onboard-color-bg);
}
.onboarding-stepper li.current .bullet {
  background: var(--onboard-color-accent-500);
  border-color: var(--onboard-color-accent-500);
  color: var(--onboard-color-bg);
}
.onboarding-stepper li.done .label,
.onboarding-stepper li.current .label {
  color: var(--onboard-color-text);
}
.onboarding-stepper li.done::before { background: var(--onboard-color-accent-800); }

@media (max-width: 540px) {
  .onboarding-stepper li .label { display: none; }
}

.onboarding-card-body { padding: 32px; }
@media (max-width: 540px) {
  .onboarding-card-body { padding: 20px; }
}
.onboarding-card-body h1 {
  font-family: var(--onboard-font-heading);
  font-weight: var(--onboard-font-heading-weight);
  font-size: 26px;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  margin: 0 0 8px;
}
.onboarding-card-body .meta {
  color: color-mix(in srgb, var(--onboard-color-text) 78%, transparent);
  margin-bottom: 24px;
  line-height: 1.5;
  font-size: 15px;
}

.onboarding-body .field { margin-bottom: 20px; }
.onboarding-body label {
  display: block;
  margin-bottom: 5px;
  font-size: 14px;
  color: color-mix(in srgb, var(--onboard-color-text) 85%, transparent);
}
.onboarding-body input[type="text"],
.onboarding-body input[type="email"],
.onboarding-body input[type="number"] {
  width: 100%;
  min-height: 36px;
  padding: 6px 10px;
  font: inherit;
  font-size: 15px;
  color: var(--onboard-color-text);
  background: var(--onboard-color-bg);
  border: 1px solid var(--onboard-color-divider);
}
.onboarding-body input[type="text"]:hover,
.onboarding-body input[type="email"]:hover,
.onboarding-body input[type="number"]:hover {
  border-color: color-mix(in srgb, var(--onboard-color-text) 45%, transparent);
}
.onboarding-body input[type="text"]:focus,
.onboarding-body input[type="email"]:focus,
.onboarding-body input[type="number"]:focus {
  outline: none;
  border-color: var(--onboard-color-accent-500);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--onboard-color-accent-500) 25%, transparent);
}
.onboarding-body .hint {
  margin-top: 5px;
  font-size: 13px;
  color: color-mix(in srgb, var(--onboard-color-text) 65%, transparent);
}

.onboarding-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}
@media (max-width: 540px) {
  .onboarding-row { grid-template-columns: 1fr; }
}

.onboarding-actions {
  display: flex;
  justify-content: flex-end;
  margin-top: 28px;
  padding-top: 20px;
  border-top: 1px solid var(--onboard-color-divider);
}
.onboarding-actions form { margin: 0; }
.onboarding-body .btn-primary,
.onboarding-actions button,
.onboarding-actions input[type="submit"] {
  background: var(--onboard-color-accent-900);
  color: var(--onboard-color-bg);
  border: 1px solid var(--onboard-color-accent-900);
  padding: 10px 24px;
  font-family: var(--onboard-font-heading);
  font-weight: var(--onboard-font-heading-weight);
  font-size: 15px;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  cursor: pointer;
  min-height: 42px;
}
.onboarding-actions button:hover,
.onboarding-actions input[type="submit"]:hover {
  background: var(--onboard-color-accent-800);
  border-color: var(--onboard-color-accent-800);
}

.onboarding-info-panel {
  background: var(--onboard-color-accent-100);
  padding: 16px 20px;
  border: 1px solid var(--onboard-color-divider);
  margin-bottom: 20px;
}
.onboarding-info-panel p { margin: 0; font-size: 15px; line-height: 1.5; }
.onboarding-info-panel p + p { margin-top: 8px; }

.onboarding-section-title {
  font-family: var(--onboard-font-heading);
  font-weight: var(--onboard-font-heading-weight);
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--onboard-color-accent-700);
  margin: 24px 0 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--onboard-color-divider);
}
.onboarding-section-title:first-child { margin-top: 0; }

.onboarding-recap {
  list-style: none;
  padding: 0;
  margin: 0 0 16px;
}
.onboarding-recap li {
  display: flex;
  justify-content: space-between;
  padding: 10px 0;
  border-bottom: 1px solid var(--onboard-color-divider);
  font-size: 15px;
}
.onboarding-recap li:last-child { border-bottom: 0; }
.onboarding-recap .label {
  color: color-mix(in srgb, var(--onboard-color-text) 65%, transparent);
}
.onboarding-recap .value { font-weight: 600; }

/* Buttons — Ascent */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-md);
  font-weight: 700;
  font-size: var(--text-sm);
  cursor: pointer;
  border: 0;
  font-family: inherit;
  text-decoration: none;
  transition: all 200ms ease;
  line-height: 1.4;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
}
.btn:active {
  transform: translateY(0);
}
.btn-sm { padding: var(--space-1) var(--space-3); font-size: var(--text-sm); }
.btn-primary {
  background: linear-gradient(135deg, var(--color-primary) 0%, #5a59c8 100%);
  color: white;
  box-shadow: 0 4px 12px rgba(70, 69, 199, 0.3);
}
.btn-primary:hover {
  background: linear-gradient(135deg, var(--color-primary-hover) 0%, #4848b8 100%);
  box-shadow: 0 8px 24px rgba(70, 69, 199, 0.4);
}
.btn-ghost {
  background: white;
  color: var(--color-primary);
  border: 2px solid #d8d8e8;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
}
.btn-ghost:hover {
  background: var(--color-primary-light);
  border-color: var(--color-primary);
  box-shadow: 0 4px 12px rgba(70, 69, 199, 0.15);
}
.btn-outline {
  background: white;
  border: 2px solid currentColor;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
}
.btn-outline:hover {
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.btn-danger.btn-outline {
  background: white !important;
  color: #d32f2f;
  border-color: #d32f2f;
  box-shadow: 0 2px 8px rgba(211, 47, 47, 0.1);
}
.btn-danger.btn-outline:hover {
  background: #ffe6e6 !important;
  border-color: #d32f2f;
  box-shadow: 0 4px 12px rgba(211, 47, 47, 0.15);
}
.btn-danger {
  background: linear-gradient(135deg, #d32f2f 0%, #b71c1c 100%);
  color: white;
  box-shadow: 0 4px 12px rgba(211, 47, 47, 0.3);
}
.btn-danger:hover {
  background: linear-gradient(135deg, #b71c1c 0%, #a01414 100%);
  box-shadow: 0 8px 24px rgba(211, 47, 47, 0.4);
}
.btn-icon-danger {
  background: transparent;
  color: #d32f2f;
  border: 0;
  padding: var(--space-2) var(--space-2);
  border-radius: var(--radius-md);
  font-weight: 700;
  font-size: var(--text-lg);
  cursor: pointer;
  font-family: inherit;
  transition: all 200ms ease;
  display: inline-block;
  line-height: 1.4;
  box-shadow: none;
}
.btn-icon-danger:hover {
  background: #ffe6e6;
  box-shadow: 0 2px 8px rgba(211, 47, 47, 0.15);
  transform: none;
}
.btn-icon-danger:active {
  transform: none;
}
.btn-danger-ghost {
  background: white;
  color: #d32f2f;
  border: 2px solid #f5d9d9;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
}
.btn-danger-ghost:hover {
  background: #ffe6e6;
  border-color: #d32f2f;
  box-shadow: 0 4px 12px rgba(211, 47, 47, 0.15);
}

/* button_to wraps in a <form>, neutralize default styles */
form.button_to { display: inline; margin: 0; }
/* `all: unset` also resets box-sizing to content-box, so any button with an explicit
   height/min-height/width (e.g. the mobile touch-target rules, .btn-block) sized
   inconsistently against its non-button_to siblings. Put border-box back. */
form.button_to button { all: unset; cursor: pointer; box-sizing: border-box; }
form.button_to button.btn,
form.button_to button.btn-primary,
form.button_to button.btn-danger,
form.button_to button.btn-ghost,
form.button_to button.btn-danger-ghost,
form.button_to button.btn-icon-danger,
form.button_to button.btn-sm,
form.button_to button.user-menu-logout {
  /* re-apply where needed via the class above (.btn etc) */
}

.empty-state {
  background: white;
  border: 2px dashed #d8d8e8;
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  text-align: center;
  color: #8a8a94;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.02);
}


.muted { color: var(--color-text-muted); }
.small { font-size: var(--text-sm); }

/* ============================================================
   Customer-facing menu — Ascent Design System
   ============================================================ */

.customer-body {
  background: linear-gradient(135deg, #f8f9fc 0%, #f3f4f9 100%);
  min-height: 100vh;
  padding-bottom: 6rem; /* leave room for sticky cart bar */
}

/* Order-composing screens (home/search/browse/review) render under the
   separate layouts/customer_order.html.erb layout, which adds this class
   alongside .customer-body — single source of truth for the flat Industry
   background, replacing the Ascent gradient above for just these screens.
   Receipt/flagged/payment keep rendering under layouts/customer.html.erb
   (.customer-body only), so they're unaffected. */
.customer-order-body {
  background: #f2f2f3;
  padding-bottom: 0;

  /* "Industry" design tokens — defined here (body level) rather than only on the
     5 screen containers below, since the persistent order-chrome header/footer
     (layouts/customer_order.html.erb) sit outside all of them as body-level
     siblings and still need these to inherit down to them. */
  --order-color-bg: #f2f2f3;
  --order-color-text: #111213; /* was #1d1f20 until 2026-09-23 — deepened a step, owner asked for "a tiny bit more black" */
  --order-color-divider: color-mix(in srgb, #1d1f20 16%, transparent);
  --order-color-accent: #5980a6;
  --order-color-accent-100: #eef6ff;
  --order-color-accent-500: #749dc4;
  --order-color-accent-600: #597ea3;
  --order-color-accent-700: #416180;
  --order-color-accent-800: #2c455d;
  --order-color-neutral-100: #f5f5f8;
  --order-color-neutral-800: #424244;
  /* The one warm in the customer scope, and the only fill that means "tap this".
     One accent ramp used to do four jobs on the chat screen — chrome, the assistant's speech,
     the customer's speech and the primary button — so two pairs came out as the same hex: the
     assistant's reply matched the header and footer (accent-100), and the primary button
     matched the customer's own bubble (accent-500). Hue separates them now: blue is speech,
     warm is action.
     NOT the global palette's --color-warm (#c97941): white text on that measures 3.34:1, which
     would trade a colour problem for a legibility one. #9c5a28 measures 5.38:1. */
  --order-color-warm: #9c5a28;
  --order-color-warm-hover: #834b20;
  --order-color-warm-active: #6b3d1a;
  /* The same "warm means tap this" idea, lighter, for controls sitting ON the dark chrome.
     --order-color-warm is tuned to separate from the light page ground and all but vanishes
     against accent-800 (1.85:1, under the 3:1 floor for a control's own edge). This one
     measures 3.54:1 against the chrome and takes DARK text (5.9:1), where the body's warm
     takes light. */
  --order-color-warm-on-dark: #d4894f;
  --order-color-warm-on-dark-hover: #e0a06a;
  --order-color-success: #3d6b4f;
  --order-color-success-bg: #e6f0ea;
  /* Danger was a TEXT and border colour only until CUST-15 (.tag-danger, the flagged banner);
     the restart confirmation is the first control filled with it, so it gained the hover/active
     pair warm already had. Measured against --order-color-bg, which is the text on it: 6.73:1
     resting, 8.29:1 hover, 10.14:1 active — all clear of normal-text AA, and all deeper than
     warm's own 4.80:1, which is the point. Warm means "go forward" everywhere in this scope, so
     the one control that destroys the customer's order must not look like it. */
  --order-color-danger: #8c3b34;
  --order-color-danger-hover: #76322c;
  --order-color-danger-active: #612924;
  --order-color-danger-bg: #f6e8e6;
  --order-font-heading: "Barlow Condensed", system-ui, sans-serif;
  --order-font-heading-weight: 600;
  --order-font-body: "Barlow", system-ui, sans-serif;
  /* The fixed footer's height, in ONE place. Four things are positioned off it: the body's
     bottom padding, the chat composer, the order-home "add more" panel, and order home's own
     padding. It used to be the literal 76px repeated at each of those, which is why the footer
     could not grow — a taller footer silently sat on top of the composer. Keep this in step
     with .order-chrome-footer's own min-height (there is no CSS way to read a fixed element's
     height); spec/system/customer/order_flow_spec.rb asserts the composer clears the footer,
     so a drift between the two fails rather than merely looking wrong. The value is MEASURED,
     not estimated — identical at 390px and 1280px. It was 108px while the footer ran to two
     rows; icon-only controls brought it back to one. */
  --order-chrome-footer-h: 70px;
  --order-space-1: 3.4px;
  --order-space-2: 6.8px;
  --order-space-3: 10.2px;
  --order-space-4: 13.6px;
  font-family: var(--order-font-body);
  /* One point above the browser's 16px default, for the text that sets no size of its own and
     inherits this. Every explicit px size in the customer scope moved up by the same 1px on
     2026-09-23, so the ratios between them are unchanged. */
  font-size: 17px;
  color: var(--order-color-text);
}

/* ============================================================
   Customer order-composing flow — "Industry" design system
   Scoped to home/search/browse/review + the product-card partial
   only. Receipt/flagged/payment screens intentionally keep the
   Ascent styling below (.customer-receipt, .customer-mini-hero,
   .flagged-*) — no design reference exists for them yet. See
   CLAUDE.md Design System section.

   This is the exact same "Industry" system as landing/signup/login
   (blueprint) — verified against the reference's own styles.css.
   Component classes below (.btn, .tag, .field/.input, .seg, .corner,
   .blueprint) are scoped under .customer-body since the equivalent
   bare classes (.btn, .btn-primary, .btn-ghost) already exist
   globally for the Ascent system (dashboard/bartender/settings) —
   scoping avoids colliding with those. Custom-property tokens stay
   scoped to the 5 screen containers, same pattern as .auth-page.
   ============================================================ */

/* Tokens for these 5 containers now live on .customer-order-body above (the
   common body-level ancestor) — see comment there for why. */

/* — persistent order-chrome header/footer (layouts/customer_order.html.erb) —
   present on every order-composing screen: shop + table + "Porosia juaj" up
   top, running cart total pinned to the bottom regardless of scroll. */
/* Dark chrome, deliberately. The header and footer used to fill with accent-100 — the same hex
   as the assistant's own bubble — so the instruction a customer is meant to read carried the
   same tint as the furniture around it. The chrome now frames the conversation instead of
   competing with it: accent-800 top and bottom, speech light in between, and exactly one warm
   control that means "tap this". Everything that sits ON this chrome inverts with it (see the
   footer below) — it was all accent-800, which is now the ground it stands on. */
/* A row since CUST-15: identity on the left, the restart icon pinned right. It has to keep
   working with no button at all, which is the case for as long as an order is with the counter —
   space-between on a single child leaves that child exactly where it was. */
.order-chrome-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 28px 20px 16px;
  background: var(--order-color-accent-800);
  border-bottom: 1px solid var(--order-color-accent-800);
}
.order-chrome-header h1 {
  margin: 0;
  font-family: var(--order-font-heading);
  font-weight: var(--order-font-heading-weight);
  font-size: 19px;
  line-height: 22px;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--order-color-accent-100);
}
.order-chrome-body { padding-bottom: var(--order-chrome-footer-h); } /* clears the fixed footer below */
.order-chrome-footer {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  /* Two rows, not one: "Totali i porosisë: 12.50 EUR" plus two buttons does not fit on a 390px
     phone in a single line. min-height must stay in step with --order-chrome-footer-h. */
  min-height: var(--order-chrome-footer-h);
  box-sizing: border-box;
  padding: 14px 20px calc(14px + env(safe-area-inset-bottom));
  background: var(--order-color-accent-800);
  border-top: 1px solid var(--order-color-accent-800);
  font-family: var(--order-font-heading);
  font-weight: var(--order-font-heading-weight);
  font-size: 16px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--order-color-accent-100);
}
/* One row: the total on the left, the two icon controls on the right. Worded labels forced
   this to two rows at 390px; icons are what buy the space back. */
.order-chrome-footer-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.order-chrome-footer-total { margin: 0; }
.order-chrome-footer-amount {
  font-variant-numeric: tabular-nums;
  color: var(--order-color-accent-100);
  font-size: 19px; /* ~20% bigger than the footer's 16px base */
}
.order-chrome-footer-actions { display: flex; gap: 8px; flex: 0 0 auto; }
.order-chrome-footer-btn {
  display: inline-flex;
  gap: 6px;
  align-items: center;
  justify-content: center;
  background: transparent;
  color: var(--order-color-accent-100);
  font-family: var(--order-font-heading);
  font-weight: var(--order-font-heading-weight);
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  /* min-height/min-width, not padding alone: these are the flow's primary controls on a touch
     screen and they carry no text to widen them, so the 40px floor the dashboard pass
     established for a real fingertip has to be stated on both axes. */
  min-height: 40px;
  min-width: 44px;
  padding: 8px 10px;
  border: 1px solid color-mix(in srgb, var(--order-color-accent-100) 55%, transparent);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
}
.order-chrome-footer-cta {
  background: var(--order-color-warm-on-dark);
  border-color: var(--order-color-warm-on-dark);
  color: var(--order-color-text);
}
.order-chrome-footer-btn:hover:not(:disabled) {
  background: var(--order-color-accent-100);
  border-color: var(--order-color-accent-100);
  color: var(--order-color-accent-800);
}
.order-chrome-footer-cta:hover:not(:disabled) {
  background: var(--order-color-warm-on-dark-hover);
  border-color: var(--order-color-warm-on-dark-hover);
  color: var(--order-color-text);
}
/* Disabled rather than absent, so the footer's height never changes as the cart fills or
   empties — see the comment in layouts/_order_badge.html.erb. */
.order-chrome-footer-btn:disabled {
  opacity: 0.4;
  cursor: default;
}
.order-chrome-footer-icon { width: 17px; height: 17px; flex: 0 0 auto; }
/* 13px against the buttons' 12px: this number is the only thing telling a customer what is
   behind an otherwise wordless control, so it does not shrink with the label it replaced. */
.customer-body .order-chrome-footer-count { font-variant-numeric: tabular-nums; font-size: 14px; }

/* — CUST-15: the restart control in the header, and its confirmation — */
.order-chrome-header h1 { flex: 1 1 auto; min-width: 0; }
/* Inverted on the dark chrome, exactly like the footer's two icon controls — everything sitting
   on accent-800 takes accent-100, and the ghost border is a 55% mix of it. Same 40px touch floor
   the footer pair states on both axes: this one carries no text to widen it either.
   Deliberately NOT warm — warm means "tap this to go forward" everywhere in this flow, and this
   control goes backward. */
.order-chrome-restart {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  min-height: 40px;
  min-width: 40px;
  padding: 8px;
  background: transparent;
  border: 1px solid color-mix(in srgb, var(--order-color-accent-100) 55%, transparent);
  color: var(--order-color-accent-100);
  cursor: pointer;
}
.order-chrome-restart:hover {
  background: var(--order-color-accent-100);
  border-color: var(--order-color-accent-100);
  color: var(--order-color-accent-800);
}
.order-chrome-restart-icon { width: 18px; height: 18px; display: block; }

/* The confirmation dialog. Same box treatment as the order-items dialog above — including the
   8px padding, which is there to CONTAIN the corner marks (.corner sits at -6px outside its
   .blueprint parent, and a flush inner box pushes them outside the dialog, which then scrolls). */
.customer-body .chat-restart-modal {
  width: min(92vw, 24rem);
  margin: auto;
  padding: 8px;
  border: 1px solid var(--order-color-text);
  border-radius: 0;
  background: var(--order-color-bg);
  color: var(--order-color-text);
  font-family: var(--order-font-body);
}
.customer-body .chat-restart-modal::backdrop {
  background: color-mix(in srgb, #1d1f20 55%, transparent);
}
.customer-body .chat-restart-modal-inner { position: relative; padding: 16px 12px 12px; }
.customer-body .chat-restart-modal-inner h2 {
  margin: 0 0 8px;
  font-family: var(--order-font-heading);
  font-weight: var(--order-font-heading-weight);
  font-size: 18px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}
.customer-body .chat-restart-modal-body {
  margin: 0 0 16px;
  font-size: 15px;
  color: color-mix(in srgb, var(--order-color-text) 75%, transparent);
}
/* Side by side and equal width, the same treatment the "add another product" panel gives its
   pair. Cancel is FIRST: the two are one tap apart on a phone, and the safe one should be the
   one a thumb reaches without aiming. button_to wraps its button in a <form>, so the form is
   what has to flex, not the button inside it. */
.customer-body .chat-restart-modal-actions {
  display: flex;
  gap: 12px;
}
.customer-body .chat-restart-modal-actions > form,
.customer-body .chat-restart-modal-actions > .btn { flex: 1 1 0; }
.customer-body .chat-restart-modal-actions .btn { width: 100%; }

/* The worded twin inside a flagged/cancelled bubble. Block-level with a little air above it, so
   it reads as the answer to the sentence over it rather than part of the sentence. */
.customer-body .chat-status-restart {
  display: block;
  width: 100%;
  margin-top: 12px;
}

/* — the order-items dialog, opened from the footer's "Shiko artikujt" —
   A native <dialog>, so the backdrop, focus trapping and Esc-to-close are the element's own
   behaviour rather than CSS and JS of ours (see layouts/_order_items_modal.html.erb). What is
   left to style is the box itself, which follows the same Industry vocabulary as every other
   surface in this flow: square corners, hairline border, corner registration marks. */
.customer-body .order-items-modal {
  width: min(92vw, 30rem);
  max-height: 80vh;
  /* Explicit rather than relying on the UA stylesheet's own margin:auto, which this sheet's
     reset was overriding — the dialog opened pinned to the top-left corner. */
  margin: auto;
  /* 8px of padding exists to CONTAIN the corner marks: .corner sits at -6px outside its
     .blueprint parent, which with a flush inner box put them outside the dialog itself and gave
     it a horizontal scrollbar. Same -6px overflow CLAUDE.md records for the dashboard cards,
     except a dialog scrolls instead of quietly overflowing the page. */
  padding: 8px;
  border: 1px solid var(--order-color-text);
  border-radius: 0;
  background: var(--order-color-bg);
  color: var(--order-color-text);
  font-family: var(--order-font-body);
}
.customer-body .order-items-modal::backdrop {
  background: color-mix(in srgb, #1d1f20 55%, transparent);
}
.customer-body .order-items-modal-inner { position: relative; padding: 12px; }
.customer-body .order-items-modal-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 14px;
}
.customer-body .order-items-modal-head h2 {
  margin: 0;
  font-family: var(--order-font-heading);
  font-weight: var(--order-font-heading-weight);
  font-size: 18px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}
.customer-body .order-items-modal-close {
  background: none;
  border: 0;
  padding: 4px;
  /* 32px, not the footer's 40px: it sits in a corner away from the destructive controls, and
     the dialog can also be dismissed by Esc or a backdrop tap. */
  min-width: 32px;
  min-height: 32px;
  font-size: 23px;
  line-height: 1;
  color: var(--order-color-text);
  cursor: pointer;
}
.customer-body .order-items-modal-body {
  max-height: 56vh;
  overflow-y: auto;
}
.customer-body .order-items-lines { list-style: none; margin: 0; padding: 0; }
.customer-body .order-items-line {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 9px 0;
  font-size: 15px;
}
.customer-body .order-items-line + .order-items-line {
  border-top: 1px solid var(--order-color-divider);
}
/* CUST-14. The customer's own instruction for this line — their words, read back to them. */
.customer-body .cart-line-details {
  display: block;
  font-size: 13px;
  color: color-mix(in srgb, var(--order-color-text) 65%, transparent);
}
.customer-body .order-items-line-end {
  display: flex;
  align-items: center;
  gap: 10px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.customer-body .order-items-total {
  display: flex;
  justify-content: space-between;
  padding-top: 10px;
  font-family: var(--order-font-heading);
  font-weight: var(--order-font-heading-weight);
  font-size: 16px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
}
.customer-body .order-items-empty {
  margin: 0;
  padding: 18px 0;
  text-align: center;
  font-size: 15px;
  color: color-mix(in srgb, var(--order-color-text) 65%, transparent);
}

/* — reusable "Industry" components, scoped under .customer-body — */
.customer-body .btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  cursor: pointer; text-decoration: none;
  font-family: var(--order-font-heading); font-weight: var(--order-font-heading-weight);
  font-size: 15px; line-height: 1.2; color: var(--order-color-text);
  background: transparent; border: 1px solid var(--order-color-divider);
  padding: var(--order-space-2) calc(var(--order-space-3) * 1.2);
  border-radius: 0;
}
.customer-body .btn:disabled { opacity: 0.45; cursor: not-allowed; }
/* Warm, and the only warm on the screen: it is what makes a control distinguishable from
   speech at a glance rather than by depth of blue. Applies to every primary in the customer
   flow — the chat's mode buttons, the recap's "Përfundo porosinë", review and cash-amount —
   so "the warm one is the one that acts" holds on every screen, not just the chat. */
.customer-body .btn-primary { background: var(--order-color-warm); color: var(--order-color-bg); border-color: var(--order-color-warm); }
.customer-body .btn-primary:hover { background: var(--order-color-warm-hover); border-color: var(--order-color-warm-hover); }
.customer-body .btn-primary:active { background: var(--order-color-warm-active); border-color: var(--order-color-warm-active); }
/* The one destructive fill in this scope, and deliberately NOT warm — warm means "tap this to
   go forward" on every other screen in the flow, so a confirm that drops the customer's whole
   order must read differently from the "Përfundo porosinë" they tapped a moment earlier.
   Only the restart confirmation uses it today; anything else that destroys customer data
   belongs here rather than in a one-off rule. */
.customer-body .btn-danger { background: var(--order-color-danger); color: var(--order-color-bg); border-color: var(--order-color-danger); }
.customer-body .btn-danger:hover { background: var(--order-color-danger-hover); border-color: var(--order-color-danger-hover); }
.customer-body .btn-danger:active { background: var(--order-color-danger-active); border-color: var(--order-color-danger-active); }
.customer-body .btn-secondary { border-color: var(--order-color-divider); }
.customer-body .btn-secondary:hover { background: color-mix(in srgb, var(--order-color-text) 7%, transparent); }
.customer-body .btn-ghost { color: var(--order-color-accent); border-color: transparent; padding-inline: var(--order-space-1); }
.customer-body .btn-ghost:hover { background: color-mix(in srgb, var(--order-color-accent) 10%, transparent); }
.customer-body .btn-block { width: 100%; }

.customer-body .blueprint { position: relative; }
.customer-body .blueprint > .corner, .customer-body .frame > .corner, .customer-body .pcard > .corner {
  position: absolute; width: 12px; height: 12px;
  color: color-mix(in srgb, var(--order-color-text) 55%, transparent);
  pointer-events: none;
}
.customer-body .blueprint > .corner::before, .customer-body .frame > .corner::before, .customer-body .pcard > .corner::before,
.customer-body .blueprint > .corner::after, .customer-body .frame > .corner::after, .customer-body .pcard > .corner::after {
  content: ""; position: absolute; background: currentColor;
}
.customer-body .blueprint > .corner::before, .customer-body .frame > .corner::before, .customer-body .pcard > .corner::before { left: 5px; top: 0; width: 1px; height: 100%; }
.customer-body .blueprint > .corner::after, .customer-body .frame > .corner::after, .customer-body .pcard > .corner::after { top: 5px; left: 0; width: 100%; height: 1px; }
.customer-body .corner.tl { top: -6px; left: -6px; }
.customer-body .corner.tr { top: -6px; right: -6px; }
.customer-body .corner.bl { bottom: -6px; left: -6px; }
.customer-body .corner.br { bottom: -6px; right: -6px; }

.customer-body .tag {
  display: inline-flex; align-items: center; font-size: 12px; letter-spacing: 0.02em;
  padding: 3px 10px; border-radius: 3px; border: none; cursor: pointer; font-family: inherit;
}
.customer-body .tag-accent { background: var(--order-color-accent-100); color: var(--order-color-accent-800); }
.customer-body .tag-neutral { background: var(--order-color-neutral-100); color: var(--order-color-neutral-800); }
.customer-body .tag-outline { background: transparent; border: 1px solid var(--order-color-accent); color: var(--order-color-accent); }
.customer-body .tag-success { background: var(--order-color-success-bg); color: var(--order-color-success); }
.customer-body .tag-danger { background: var(--order-color-danger-bg); color: var(--order-color-danger); }

/* The counter-pickup notice on the order status screen. `danger` because it is the one line on
   that screen the customer loses something by ignoring: a shop that calls people over cannot
   deliver to someone who wandered off or closed the page. Square corners and a hairline rule
   like every other surface here; the leading rail is what makes it read as a warning rather
   than another paragraph. */
.customer-body .order-status-note {
  margin: 16px 0 0;
  padding: 12px 14px;
  border: 1px solid var(--order-color-divider);
  font-size: 15px;
  line-height: 1.45;
}
.customer-body .order-status-note.danger {
  background: var(--order-color-danger-bg);
  border-color: color-mix(in srgb, var(--order-color-danger) 35%, transparent);
  border-left: 3px solid var(--order-color-danger);
  color: var(--order-color-danger);
}

.customer-body .field > label { display: block; font-size: 13px; margin-bottom: 5px; color: color-mix(in srgb, var(--order-color-text) 70%, transparent); }
.customer-body .input {
  width: 100%; min-height: 36px; padding: 6px 10px; font: inherit;
  font-size: 15px; color: var(--order-color-text); caret-color: var(--order-color-accent);
  background: var(--order-color-bg); border: 1px solid var(--order-color-divider); border-radius: 0;
}
.customer-body .input:hover { border-color: color-mix(in srgb, var(--order-color-text) 45%, transparent); }
.customer-body .input:focus-visible { border-color: var(--order-color-accent); outline-offset: 0; }

.customer-body .seg { display: inline-flex; overflow: hidden; border: 1px solid var(--order-color-divider); }
.customer-body .seg-opt { display: inline-flex; align-items: center; gap: 6px; padding: 7px 12px; font-size: 14px; cursor: pointer; }
.customer-body .seg-opt + .seg-opt { border-left: 1px solid var(--order-color-divider); }
.customer-body .seg-opt:has(input:checked) { background: var(--order-color-accent); color: var(--order-color-bg); }
.customer-body .seg-opt:not(:has(input:checked)):hover { background: color-mix(in srgb, var(--order-color-text) 7%, transparent); }

/* — screen shell: .frame/.pcard cards, stepper, etc. The old per-screen .hd
   heading is gone — replaced by the persistent .order-chrome-header in
   layouts/customer_order.html.erb. Only a light "← Prapa" back-link row
   remains local to search/browse/review. */
.order-back-row { padding: 16px 20px 0; }
.order-back-row .btn { margin-bottom: 0; }
.customer-body .sub { font-size: 14px; color: color-mix(in srgb, var(--order-color-text) 70%, transparent); margin-top: 4px; }

.customer-body .frame {
  position: relative; border: 1px solid var(--order-color-divider);
  width: 52px; height: 52px; display: flex; align-items: center; justify-content: center;
  font-size: 23px; color: var(--order-color-accent-700);
}
.customer-body .pcard { position: relative; border: 1px solid var(--order-color-divider); background: var(--order-color-bg); padding: 14px; }
.customer-body .pname { font-family: var(--order-font-heading); font-weight: var(--order-font-heading-weight); font-size: 17px; letter-spacing: 0.01em; color: var(--order-color-text); }
.customer-body .pprice { font-size: 14px; font-weight: 600; color: var(--order-color-accent-700); font-variant-numeric: tabular-nums; margin-top: 2px; }

/* Higher specificity than the app-wide `form.button_to button { all: unset }` reset (0,1,2). */

.customer-body .tag-row { display: flex; gap: 6px; margin-top: 12px; flex-wrap: wrap; }
/* CUST-14. The browse/search lane's own note field — same .input look as the search bar, just
   given room above whatever it follows (the row itself, or the variant pills). */
.customer-body .product-card-details { margin-top: 10px; }
.customer-body .addbtn {
  background: var(--order-color-accent-500); color: var(--order-color-bg);
  border: 1px solid var(--order-color-accent-500); padding: 8px 14px;
  font-size: 13px; font-weight: 600; letter-spacing: 0.02em; white-space: nowrap; cursor: pointer;
}
.customer-body .quickadd { width: 26px; height: 26px; border: 1px solid var(--order-color-divider); display: flex; align-items: center; justify-content: center; font-size: 16px; color: var(--order-color-accent-700); flex: 0 0 auto; background: none; cursor: pointer; }
.customer-body .categories { display: flex; gap: 8px; padding: 16px 20px 0; overflow-x: auto; }

.customer-body .divider { height: 1px; background: var(--order-color-divider); margin: 10px 0; }
.customer-body .review-row { display: flex; justify-content: space-between; font-size: 15px; color: var(--order-color-text); }
.customer-body .review-row .meta { color: color-mix(in srgb, var(--order-color-text) 70%, transparent); font-size: 14px; }
.customer-body .total-row { display: flex; justify-content: space-between; font-size: 16px; font-weight: 700; font-family: var(--order-font-heading); text-transform: uppercase; letter-spacing: 0.02em; }

/* — order home — */
.customer-order-home {
  max-width: 36rem;
  margin: 0 auto;
  /* Accounts for .order-chrome-header above it (~44px padding + up to 2 lines
     of heading text) so the empty-state centering below has the actual
     remaining viewport height to work with, not a full extra 100vh. */
  min-height: calc(100vh - 90px);
  display: flex;
  flex-direction: column;
  /* .order-home-add-more is position: fixed (see below) and no longer occupies flex space —
     this keeps content (the empty-state's centered block, or the last line item) clear of
     where it now floats: the fixed footer's own height (--order-chrome-footer-h) + the
     add-more panel's own height + a gap. */
  padding-bottom: calc(var(--order-chrome-footer-h) + 104px);
}
.customer-order-home-empty {
  flex: 1 1 0%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 0 40px;
  gap: 8px;
}
.customer-order-home-empty .frame { margin: 0 auto; }
.customer-order-home-empty h2 { font-family: var(--order-font-heading); font-weight: var(--order-font-heading-weight); font-size: 17px; text-transform: uppercase; color: var(--order-color-text); margin: 8px 0 0; }
.customer-order-home-empty p { color: color-mix(in srgb, var(--order-color-text) 70%, transparent); font-size: 14px; margin: 0; }

.customer-body .order-home-heading {
  font-family: var(--order-font-heading);
  font-weight: var(--order-font-heading-weight);
  font-size: 21px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--order-color-text);
  padding: 20px 20px 0;
  margin: 0;
}

.customer-order-home-body { flex: 0 1 auto; padding: 20px; }
.customer-line-items { list-style: none; padding: 0; margin: 0 0 12px; display: flex; flex-direction: column; gap: 16px; }
/* 10% bigger than the shared 13px .pprice used elsewhere (product cards in search/browse
   keep the base size — this scopes the bump to order-home's own row totals only). */
.customer-body .customer-line-items .pprice { font-size: 15.3px; }

/* Pinned just above the fixed footer (position: fixed; bottom: --order-chrome-footer-h —
   the same token .order-chrome-body reserves as clearance for the footer's own height, so
   this sits flush above it with no gap or overlap) rather than sitting in normal document
   flow. It used to be reachable only by scrolling past the empty-state's centered content
   or the full line-item list — moved here so "add a product" is always visible without
   scrolling, on both the empty and filled states (same shared partial, see below).
   Needs an opaque background now that content scrolls underneath it — the earlier
   transparent/no-fill treatment (chosen to avoid a third colored block matching the
   header/footer's accent-100) assumed normal in-flow placement against the plain page
   background; fixed-positioned, transparent would let scrolled content show through it.
   --order-color-bg keeps it neutral (the page's own base tone, not a new accent color)
   while still being opaque. */
.customer-body .order-home-add-more {
  position: fixed;
  left: 0;
  right: 0;
  bottom: var(--order-chrome-footer-h);
  z-index: 5;
  margin: 0 20px;
  background: var(--order-color-bg);
  border: 1px solid var(--order-color-accent-500);
  padding: 9px;
}
.customer-body .order-home-add-more-heading {
  font-family: var(--order-font-heading);
  font-weight: var(--order-font-heading-weight);
  font-size: 14px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--order-color-accent-700);
  margin: 0 0 10px;
}
.customer-body .order-home-add-more-actions { display: flex; flex-direction: row; gap: 16px; }
.customer-body .order-home-add-more-actions .btn {
  flex: 1 1 0;
  background: var(--order-color-accent-500);
  border-color: var(--order-color-accent-500);
  color: var(--order-color-bg);
}
.customer-body .order-home-add-more-actions .btn:hover {
  background: var(--order-color-accent-600);
  border-color: var(--order-color-accent-600);
}

/* The generic "+" corner registration marks (shared with .frame/.pcard sectioning
   elements elsewhere) read as too heavy on these two small buttons, making them look
   like another bordered panel rather than a tappable action — shrink and lighten them
   here specifically. */
.customer-body .order-home-add-more-actions .blueprint > .corner {
  width: 8px; height: 8px;
  color: color-mix(in srgb, var(--order-color-text) 30%, transparent);
}
.customer-body .order-home-add-more-actions .blueprint > .corner::before { left: 3px; }
.customer-body .order-home-add-more-actions .blueprint > .corner::after { top: 3px; }
.customer-body .order-home-add-more-actions .corner.tl { top: -4px; left: -4px; }
.customer-body .order-home-add-more-actions .corner.tr { top: -4px; right: -4px; }
.customer-body .order-home-add-more-actions .corner.bl { bottom: -4px; left: -4px; }
.customer-body .order-home-add-more-actions .corner.br { bottom: -4px; right: -4px; }
.pcard-row { display: flex; justify-content: space-between; align-items: center; gap: 12px; }
.pcard-row-end { display: flex; align-items: center; gap: 12px; }
.pcard-info { flex: 1; min-width: 0; }
/* The add control is the row's last flex item, so .pcard-row's space-between pins it to the
   right edge with no rule of its own. It must not shrink, though: the label is `white-space:
   nowrap`, and a shrinking flex item would let the text spill past its own background on a
   narrow phone rather than squeezing the name column, which has min-width: 0 for exactly this.
   (.pcard-footer, the line it used to sit on below the card, went with it.) */
.pcard-add { flex: 0 0 auto; }
.pcard-thumb { flex: 0 0 auto; }
.pcard-thumb-img { width: 100%; height: 100%; object-fit: cover; }
/* Shown when an item has no picture, so the row does not read as a broken image. Sized to the
   52px frame and kept quiet — it is a statement of absence, not a thing to look at. */
.pcard-thumb-placeholder {
  width: 22px;
  height: 22px;
  color: color-mix(in srgb, var(--order-color-text) 38%, transparent);
}
.pcard-video { width: 100%; max-width: 320px; margin-top: 10px; display: block; }

/* Order-home line items are read-only (name, unit price, quantity, row total) —
   quantity is only ever changed via the search/browse product-card stepper, so
   these rows get a small remove (×) button instead of the +/- stepper. */
.customer-body .line-stats { display: flex; flex-direction: row; align-items: baseline; gap: 4px; }
.customer-body .line-price, .customer-body .line-qty {
  font-size: 13px; color: color-mix(in srgb, var(--order-color-text) 65%, transparent); font-variant-numeric: tabular-nums;
}
/* Higher specificity than the app-wide `form.button_to button { all: unset }` reset (0,1,2). */
/* Every container this control appears in has to be listed: the global `form.button_to button
   { all: unset }` rule strips its box, so an unlisted container renders it at zero size —
   invisible, and not clickable even by a test. */
.customer-body .pcard .line-remove-btn,
.customer-body .order-items-line .line-remove-btn,
.customer-body .review-row .line-remove-btn {
  flex: 0 0 auto;
  width: 26px; height: 26px;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--order-color-divider);
  background: none; color: var(--order-color-accent-700);
  cursor: pointer;
}
.customer-body .pcard .line-remove-btn svg,
.customer-body .order-items-line .line-remove-btn svg,
.customer-body .review-row .line-remove-btn svg { width: 14px; height: 14px; }

/* — search — */
.customer-search { max-width: 36rem; margin: 0 auto; padding-bottom: 20px; }
.customer-search-bar { position: relative; padding: 16px 20px 0; }
.customer-search-bar .customer-search-icon { position: absolute; left: 32px; top: 50%; transform: translateY(-50%); color: color-mix(in srgb, var(--order-color-text) 55%, transparent); pointer-events: none; }
.customer-search-bar .input { padding-left: 30px; }
.customer-search-empty { color: color-mix(in srgb, var(--order-color-text) 70%, transparent); text-align: center; padding: var(--space-8) 20px; }
.customer-product-list { display: flex; flex-direction: column; gap: 12px; padding: 16px 20px 0; }

/* — browse — */
.customer-browse { max-width: 36rem; margin: 0 auto; padding-bottom: 20px; }

/* — review — */
.customer-review { max-width: 36rem; margin: 0 auto; padding: 0 20px 20px; }
.customer-review-list { list-style: none; padding: 0; margin: 16px 0 0; display: flex; flex-direction: column; gap: 8px; }
.customer-review-form { display: flex; flex-direction: column; gap: 16px; margin-top: 20px; }
.customer-review-caption { text-align: center; color: color-mix(in srgb, var(--order-color-text) 70%, transparent); font-size: 14px; }

/* Payment method picker — .seg segmented control, extrapolated from the
   system's own form-control vocabulary (no explicit mockup for this partial). */
.customer-payment-picker { display: flex; flex-direction: column; gap: 16px; }
.payment-method-fieldset { border: none; padding: 0; margin: 0; }
.payment-method-fieldset legend { font-size: 13px; margin-bottom: 5px; color: color-mix(in srgb, var(--order-color-text) 70%, transparent); padding: 0; }

/* — receipt (Order Placed) — rendered via the dedicated customer_receipt layout, not the
   persistent order-chrome header/footer (there's no cart left to total once an order exists —
   see Customer::OrdersController::RECEIPT_ACTIONS). Reuses .order-chrome-header directly as a
   plain view-local element for the same shop/table identity strip as every other screen. */
.customer-receipt-main { max-width: 36rem; margin: 0 auto; padding: 20px; }
.receipt-heading { font-family: var(--order-font-heading); font-weight: var(--order-font-heading-weight); font-size: 25px; text-transform: uppercase; letter-spacing: 0.02em; margin: 0 0 8px; }
.receipt-meta-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 14px; color: color-mix(in srgb, var(--order-color-text) 65%, transparent); margin-bottom: 16px; }
.receipt-payment { font-size: 15px; margin-bottom: 16px; }

/* ============================================================
   Owner/manager dashboard + settings — "Industry" design system
   ============================================================
   Fourth scope for this design system (after .auth-page, .customer-body/
   .customer-order-body, and landing.html.erb's own inline copy) — same shared
   palette/fonts, copied into a new scope rather than centralized, matching how
   this system has been extended each previous time. Tokens prefixed --dash-*
   (not bare --color-*) to match the more recent .customer-body precedent
   (--order-color-*) and avoid any ambiguity with design_tokens.css's global
   Ascent --color-* tokens. Every component below is scoped under
   .dashboard-body — never a bare class name — since bare .btn/.btn-primary/
   .card already exist for Ascent elsewhere in the app (e.g. the onboarding
   wizard). The bartender board (a separate, later redesign pass) has since
   moved off bare Ascent classes too, onto its own --bar-color-*-scoped
   .bartender-body components — see that block further down this file — and
   the old unscoped bartender.css was deleted as dead code. */
.dashboard-body {
  background: #f2f2f3;
  --dash-color-bg: #f2f2f3;
  --dash-color-surface: #e9e9ea;
  --dash-color-text: #1d1f20;
  --dash-color-divider: color-mix(in srgb, #1d1f20 16%, transparent);
  --dash-color-accent: #5980a6;
  --dash-color-accent-100: #eef6ff;
  --dash-color-accent-500: #749dc4;
  --dash-color-accent-600: #597ea3;
  --dash-color-accent-700: #416180;
  --dash-color-accent-800: #2c455d;
  --dash-color-accent-900: #1d2d3d;
  --dash-color-neutral-100: #f5f5f8;
  --dash-color-neutral-800: #424244;
  --dash-color-success: #3d6b4f;
  --dash-color-success-bg: #e6f0ea;
  --dash-color-danger: #8c3b34;
  --dash-color-danger-bg: #f6e8e6;
  --dash-font-heading: "Barlow Condensed", system-ui, sans-serif;
  --dash-font-heading-weight: 600;
  --dash-font-body: "Barlow", system-ui, sans-serif;
  font-family: var(--dash-font-body);
  color: var(--dash-color-text);
}
/* Base heading treatment: condensed font + weight only. text-transform: uppercase is applied
   separately, only to genuinely static UI chrome (page titles, section labels, modal/tab
   headers) — deliberately NOT here, since these bare h1-h3 selectors also wrap dynamic,
   user-entered content (zone/menu names in .pcard-head h3). Uppercasing e.g. "Outdoor Seating"
   unconditionally both looks aggressive on real names and breaks exact-case Capybara text
   matching in specs that assert on that user-entered text — same reasoning that kept
   .customer-body .pname (product names) out of the uppercase treatment already. */
.dashboard-body h1, .dashboard-body h2, .dashboard-body h3, .dashboard-body .heading {
  font-family: var(--dash-font-heading);
  font-weight: var(--dash-font-heading-weight);
  letter-spacing: 0.02em;
  margin: 0;
  color: var(--dash-color-text);
}
.dashboard-body .kicker { font-size: 12px; letter-spacing: 0.08em; text-transform: uppercase; font-weight: 600; color: var(--dash-color-accent-700); margin: 0 0 6px; }

/* — corner-bracket motif, 12px canonical variant (matches .customer-body/landing) — */
.dashboard-body .blueprint, .dashboard-body .pcard, .dashboard-body .form-card, .dashboard-body .dash-modal-content { position: relative; }
.dashboard-body .corner { position: absolute; width: 12px; height: 12px; color: color-mix(in srgb, var(--dash-color-text) 55%, transparent); pointer-events: none; }
.dashboard-body .corner::before { content: ""; position: absolute; left: 5px; top: 0; width: 1px; height: 100%; background: currentColor; }
.dashboard-body .corner::after { content: ""; position: absolute; top: 5px; left: 0; width: 100%; height: 1px; background: currentColor; }
.dashboard-body .corner.tl { top: -6px; left: -6px; }
.dashboard-body .corner.tr { top: -6px; right: -6px; }
.dashboard-body .corner.bl { bottom: -6px; left: -6px; }
.dashboard-body .corner.br { bottom: -6px; right: -6px; }

/* — buttons — */
.dashboard-body .btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  cursor: pointer; text-decoration: none;
  font-family: var(--dash-font-heading); font-weight: var(--dash-font-heading-weight);
  font-size: 13.5px; line-height: 1.2; color: var(--dash-color-text);
  background: transparent; border: 1px solid var(--dash-color-divider);
  padding: 9px 16px; border-radius: 0;
}
.dashboard-body .btn:disabled { opacity: 0.45; cursor: not-allowed; }
.dashboard-body .btn-primary { background: var(--dash-color-accent-800); color: var(--dash-color-bg); border-color: var(--dash-color-accent-800); }
.dashboard-body .btn-primary:hover { background: var(--dash-color-accent-900); border-color: var(--dash-color-accent-900); }
.dashboard-body .btn-secondary { border-color: var(--dash-color-accent-500); color: var(--dash-color-accent-700); }
.dashboard-body .btn-secondary:hover { background: color-mix(in srgb, var(--dash-color-accent-500) 10%, transparent); }
.dashboard-body .btn-ghost { border-color: transparent; color: var(--dash-color-accent-700); }
.dashboard-body .btn-ghost:hover { background: color-mix(in srgb, var(--dash-color-accent) 10%, transparent); }
.dashboard-body .btn-danger-ghost { border-color: transparent; color: var(--dash-color-danger); }
.dashboard-body .btn-danger-ghost:hover { background: color-mix(in srgb, var(--dash-color-danger) 10%, transparent); }
.dashboard-body .btn-sm { padding: 5px 10px; font-size: 12px; }
/* Primary create/edit actions on the dashboard home cards — deliberately larger than the
   base .btn so they read as the main action on their section, and comfortably clear the
   ~44px touch target without needing the mobile min-height override. */
.dashboard-body .btn-lg { padding: 12px 22px; font-size: 15px; }
.dashboard-body .btn-block { width: 100%; }

/* — form fields — */
.dashboard-body .field { margin-bottom: 18px; max-width: 30rem; }
.dashboard-body .field.wide { max-width: 100%; }
.dashboard-body .field > label { display: block; font-size: 12.5px; margin-bottom: 5px; color: color-mix(in srgb, var(--dash-color-text) 70%, transparent); }
.dashboard-body .input,
.dashboard-body textarea.input,
.dashboard-body select.input {
  width: 100%; min-height: 38px; padding: 7px 10px; font: inherit; font-size: 14px;
  color: var(--dash-color-text); background: var(--dash-color-bg);
  border: 1px solid var(--dash-color-divider); border-radius: 0;
}
.dashboard-body textarea.input { min-height: 84px; resize: vertical; }
.dashboard-body .input:hover { border-color: color-mix(in srgb, var(--dash-color-text) 45%, transparent); }
.dashboard-body .input:focus-visible { outline: none; border-color: var(--dash-color-accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--dash-color-accent) 20%, transparent); }
.dashboard-body .field-hint { font-size: 12px; color: color-mix(in srgb, var(--dash-color-text) 60%, transparent); margin-top: 5px; }
.dashboard-body .field-media-preview { margin-bottom: 10px; }
.dashboard-body .field-media-preview img { max-width: 160px; display: block; margin-bottom: 6px; }
.dashboard-body .field-media-preview video { max-width: 220px; display: block; margin-bottom: 6px; }
.dashboard-body .form-errors { border: 1px solid var(--dash-color-danger); background: var(--dash-color-danger-bg); color: var(--dash-color-danger); padding: 12px 14px; margin-bottom: 18px; font-size: 13px; }
.dashboard-body .form-errors ul { margin: 4px 0 0; padding-left: 18px; }

/* — subscription status banner (OWN-18) — expired/suspended owners can now reach
   Dashboard::SubscriptionsController, which deliberately skips check_subscription_access, so
   this can render there too. Same visual language as .form-errors (danger tokens, left accent
   border) rather than the Tailwind utility classes it shipped with — Tailwind isn't installed
   in this app. */
.dashboard-body .subscription-status-banner {
  border: 1px solid var(--dash-color-danger);
  border-left: 4px solid var(--dash-color-danger);
  background: var(--dash-color-danger-bg);
  color: var(--dash-color-danger);
  padding: 12px 14px;
  margin-bottom: 18px;
  font-size: 13px;
  font-weight: 600;
}
.dashboard-body .subscription-status-banner p { margin: 0; }

.dashboard-body .seg { display: inline-flex; overflow: hidden; border: 1px solid var(--dash-color-divider); }
.dashboard-body .seg-opt { display: inline-flex; align-items: center; gap: 6px; padding: 8px 16px; font-size: 13px; cursor: pointer; font-weight: 600; }
.dashboard-body .seg-opt + .seg-opt { border-left: 1px solid var(--dash-color-divider); }
.dashboard-body .seg-opt:has(input:checked) { background: var(--dash-color-accent); color: var(--dash-color-bg); }
.dashboard-body .seg-opt:not(:has(input:checked)):hover { background: color-mix(in srgb, var(--dash-color-text) 7%, transparent); }

/* — tags / status chips — */
.dashboard-body .tag { display: inline-flex; align-items: center; font-size: 11px; letter-spacing: 0.02em; padding: 3px 9px; border-radius: 3px; border: none; font-family: var(--dash-font-body); font-weight: 600; }
.dashboard-body .tag-accent  { background: var(--dash-color-accent-100); color: var(--dash-color-accent-800); }
.dashboard-body .tag-neutral { background: var(--dash-color-neutral-100); color: var(--dash-color-neutral-800); }
.dashboard-body .tag-outline { background: transparent; border: 1px solid var(--dash-color-accent); color: var(--dash-color-accent-700); }
.dashboard-body .tag-success { background: var(--dash-color-success-bg); color: var(--dash-color-success); }
.dashboard-body .tag-danger  { background: var(--dash-color-danger-bg); color: var(--dash-color-danger); }

/* — cards — */
.dashboard-body .pcard { border: 1px solid var(--dash-color-divider); background: var(--dash-color-bg); padding: 16px; }
.dashboard-body .form-card { border: 1px solid var(--dash-color-divider); background: var(--dash-color-bg); padding: 28px; max-width: 34rem; }
.dashboard-body .form-actions { display: flex; gap: 10px; margin-top: 22px; padding-top: 18px; border-top: 1px solid var(--dash-color-divider); }
.dashboard-body .empty-state { border: 1px dashed var(--dash-color-divider); padding: 32px 20px; text-align: center; color: color-mix(in srgb, var(--dash-color-text) 65%, transparent); font-size: 13px; }

/* — QR code page — */
.dashboard-body .qr-card {
  border: 1px solid var(--dash-color-divider); background: var(--dash-color-bg); padding: 32px; max-width: 26rem;
  display: flex; flex-direction: column; align-items: center; gap: 20px; position: relative;
}
.dashboard-body .qr-image { background: var(--dash-color-bg); padding: 16px; border: 1px solid var(--dash-color-divider); max-width: 20rem; width: 100%; }
.dashboard-body .qr-image svg { display: block; width: 100%; height: auto; }
.dashboard-body .qr-meta { text-align: center; }
.dashboard-body .qr-label { font-size: 15px; font-weight: 700; margin-bottom: 8px; }
.dashboard-body .qr-url code { font-size: 12px; word-break: break-all; color: color-mix(in srgb, var(--dash-color-text) 65%, transparent); background: var(--dash-color-surface); padding: 3px 7px; }
.dashboard-body .qr-actions { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; }
.dashboard-body .qr-warning { text-align: center; max-width: 22rem; }

@media print {
  .dashboard-body .app-shell > .sidebar, .dashboard-body .dash-topbar, .dashboard-body .qr-actions, .dashboard-body .qr-warning, .dashboard-body .flash { display: none !important; }
  .dashboard-body .qr-card { border: 0; padding: 0; }
  .dashboard-body .qr-image { max-width: 70vw; padding: 0; border: 0; }
}

/* — page shell (replaces .dashboard-container/.dashboard-header) — */
.dashboard-body .dash-content { padding: 28px 32px 60px; max-width: 78rem; }
.dashboard-body .dash-content.narrow { max-width: 34rem; }
.dashboard-body .dash-topbar {
  border-bottom: 1px solid var(--dash-color-divider);
  padding: 20px 32px;
  display: flex; align-items: baseline; justify-content: space-between; flex-wrap: wrap; gap: 8px;
}
.dashboard-body .dash-topbar h1 { font-size: 22px; text-transform: uppercase; }
.dashboard-body .dash-topbar .sub { font-size: 13px; font-family: var(--dash-font-body); text-transform: none; letter-spacing: normal; font-weight: 400; color: color-mix(in srgb, var(--dash-color-text) 65%, transparent); margin-top: 4px; }
.dashboard-body .dash-topbar .back-link { display: block; font-size: 12.5px; color: var(--dash-color-accent-700); text-decoration: none; margin-bottom: 6px; }
.dashboard-body .dash-topbar .back-link:hover { text-decoration: underline; }

.dashboard-body .section { margin-bottom: 40px; }
/* Hairline between consecutive sections (Zonat/Tavolinat -> Menyja). Uses the adjacent-sibling
   selector rather than a border on every .section, so the first section gets no stray rule above
   it and any section added later is separated automatically. */
.dashboard-body .dash-content .section + .section {
  border-top: 1px solid var(--dash-color-divider);
  padding-top: 40px;
}
.dashboard-body .section-head { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 16px; gap: 12px; flex-wrap: wrap; }
.dashboard-body .section-head h2 { font-size: 17px; text-transform: uppercase; }
.dashboard-body .grid-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr)); gap: 16px; }
.dashboard-body .pcard-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.dashboard-body .pcard-head h3 { font-size: 15.5px; }
.dashboard-body .pcard-head .count { font-size: 11px; font-weight: 600; color: color-mix(in srgb, var(--dash-color-text) 60%, transparent); border: 1px solid var(--dash-color-divider); padding: 1px 7px; font-family: var(--dash-font-body); text-transform: none; letter-spacing: normal; }
.dashboard-body .pcard-list { list-style: none; margin: 0 0 14px; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.dashboard-body .pcard-list li { display: flex; align-items: center; justify-content: space-between; font-size: 13px; padding: 7px 0; border-bottom: 1px solid var(--dash-color-divider); }
.dashboard-body .pcard-list li:last-child { border-bottom: none; }
.dashboard-body .pcard-list .row-actions { display: flex; gap: 4px; }
.dashboard-body .pcard-actions { display: flex; gap: 8px; }
.dashboard-body .pcard-actions .btn { flex: 1 1 0; }
.dashboard-body .pcard-meta { font-size: 13px; color: color-mix(in srgb, var(--dash-color-text) 65%, transparent); margin: 0 0 14px; }
.dashboard-body .pcard-list-row { display: flex; justify-content: space-between; font-size: 13px; padding-bottom: 10px; margin-bottom: 10px; border-bottom: 1px solid var(--dash-color-divider); }
.dashboard-body .pcard-list-row.large { border-bottom: none; margin-bottom: 0; padding-bottom: 0; font-family: var(--dash-font-heading); font-weight: var(--dash-font-heading-weight); font-size: 18px; }

/* — sidebar nav — */
.dashboard-body .app-shell { display: flex; align-items: stretch; min-height: 100vh; }
.dashboard-body .sidebar {
  width: 240px; flex: 0 0 auto;
  background: var(--dash-color-surface);
  border-right: 1px solid var(--dash-color-divider);
  display: flex; flex-direction: column;
  position: sticky; top: 0; height: 100vh;
}
.dashboard-body .sidebar-brand { padding: 22px 20px 18px; border-bottom: 1px solid var(--dash-color-divider); }
.dashboard-body .sidebar-brand a { color: inherit; text-decoration: none; }
.dashboard-body .sidebar-brand .word { font-family: var(--dash-font-heading); font-weight: var(--dash-font-heading-weight); font-size: 19px; text-transform: uppercase; letter-spacing: 0.04em; }
.dashboard-body .sidebar-brand-logo { display: block; max-height: 68px; max-width: 100%; height: auto; width: auto; }
.dashboard-body .sidebar-brand .shop { margin-top: 4px; font-size: 12.5px; color: color-mix(in srgb, var(--dash-color-text) 70%, transparent); }
.dashboard-body .sidebar-nav { flex: 1 1 auto; padding: 14px 0; overflow-y: auto; }
.dashboard-body .sidebar-link {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 20px; margin: 0 10px;
  font-family: var(--dash-font-heading); font-weight: var(--dash-font-heading-weight); font-size: 14.5px; letter-spacing: 0.01em;
  color: var(--dash-color-text); text-decoration: none; cursor: pointer;
  border-left: 2px solid transparent;
}
.dashboard-body .sidebar-link:hover { background: color-mix(in srgb, var(--dash-color-text) 6%, transparent); }
.dashboard-body .sidebar-link.active { background: var(--dash-color-accent-100); border-left-color: var(--dash-color-accent-700); color: var(--dash-color-accent-800); }
.dashboard-body .sidebar-footer { border-top: 1px solid var(--dash-color-divider); padding: 14px 20px; display: flex; align-items: center; gap: 10px; }
.dashboard-body .sidebar-avatar { width: 30px; height: 30px; flex: 0 0 auto; border: 1px solid var(--dash-color-accent-700); display: flex; align-items: center; justify-content: center; font-family: var(--dash-font-heading); font-weight: var(--dash-font-heading-weight); font-size: 13px; color: var(--dash-color-accent-700); }
.dashboard-body .sidebar-footer .who { min-width: 0; }
.dashboard-body .sidebar-footer .name { font-size: 13px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dashboard-body .sidebar-footer .role { font-size: 11.5px; text-transform: uppercase; letter-spacing: 0.04em; color: color-mix(in srgb, var(--dash-color-text) 60%, transparent); }
.dashboard-body .sidebar-footer form { margin-left: auto; }
.dashboard-body .sidebar-footer .logout-btn { background: none; border: none; padding: 4px; cursor: pointer; color: color-mix(in srgb, var(--dash-color-text) 55%, transparent); font-size: 12px; font-family: var(--dash-font-body); }
.dashboard-body .sidebar-footer .logout-btn:hover { color: var(--dash-color-danger); }

/* — sidebar subscription callout (OWN-18) — */
.dashboard-body .sidebar-callout {
  flex: 0 0 auto; margin: 0 14px 14px; padding: 12px;
  border: 1px solid var(--dash-color-accent-500);
  background: var(--dash-color-accent-100); color: var(--dash-color-accent-800);
}
.dashboard-body .sidebar-callout-kicker {
  display: block; font-family: var(--dash-font-heading); font-size: 11px;
  letter-spacing: 0.06em; text-transform: uppercase; margin-bottom: 6px;
}
.dashboard-body .sidebar-callout-body { font-size: 12px; line-height: 1.45; margin: 0 0 10px; }
.dashboard-body .sidebar-callout-body strong { font-variant-numeric: tabular-nums; }
.dashboard-body .sidebar-callout-cta {
  display: block; text-align: center; text-decoration: none;
  background: var(--dash-color-accent-800); color: var(--dash-color-bg);
  font-family: var(--dash-font-heading); font-size: 12.5px; padding: 8px 10px;
}
.dashboard-body .sidebar-callout-cta:hover { background: var(--dash-color-accent-900); }
.dashboard-body .main { flex: 1 1 auto; min-width: 0; }

/* — data table — */
.dashboard-body .filter-row { display: flex; align-items: flex-end; gap: 14px; flex-wrap: wrap; margin-bottom: 18px; }
.dashboard-body .filter-row .field { margin-bottom: 0; }
.dashboard-body .table-wrap { border: 1px solid var(--dash-color-divider); overflow-x: auto; }
.dashboard-body .data-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.dashboard-body .data-table th {
  text-align: left; font-family: var(--dash-font-heading); font-weight: var(--dash-font-heading-weight); font-size: 11.5px;
  text-transform: uppercase; letter-spacing: 0.04em; color: color-mix(in srgb, var(--dash-color-text) 65%, transparent);
  padding: 11px 16px; border-bottom: 1px solid var(--dash-color-divider); background: var(--dash-color-surface);
  white-space: nowrap;
}
.dashboard-body .data-table td { padding: 12px 16px; border-bottom: 1px solid var(--dash-color-divider); vertical-align: middle; }
.dashboard-body .data-table tbody tr:last-child td { border-bottom: none; }
.dashboard-body .data-table tbody tr:hover { background: color-mix(in srgb, var(--dash-color-accent) 4%, transparent); }
.dashboard-body .data-table .num { font-variant-numeric: tabular-nums; text-align: right; }
.dashboard-body .data-table .id { color: color-mix(in srgb, var(--dash-color-text) 55%, transparent); font-variant-numeric: tabular-nums; }

/* CUST-14. The customer's instruction for this line, staff-facing (#staff_details). */
.dashboard-body .order-item-details {
  font-size: 12px;
  color: color-mix(in srgb, var(--dash-color-text) 65%, transparent);
}
/* Totals footer. `tbody tr:last-child td` drops its bottom border, so the 2px top border here
   is what separates the sum from the rows it sums. Uppercase on the label only — it is static
   chrome like a <th>, never user-entered text (see the uppercase heading rule). */
.dashboard-body .data-table tfoot td {
  padding: 12px 16px; background: var(--dash-color-surface);
  border-top: 2px solid var(--dash-color-divider);
  font-family: var(--dash-font-heading); font-weight: var(--dash-font-heading-weight); font-size: 14px;
}
.dashboard-body .data-table .table-totals-label {
  text-transform: uppercase; letter-spacing: 0.04em; font-size: 11.5px;
  color: color-mix(in srgb, var(--dash-color-text) 65%, transparent);
}

/* Reports (REPORT-01) */
.dashboard-body .report-kpis { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin-bottom: 28px; }
.dashboard-body .report-kpi { position: relative; border: 1px solid var(--dash-color-divider); padding: 16px 18px; background: var(--dash-color-bg); }
.dashboard-body .report-kpi-label { font-size: 11.5px; letter-spacing: 0.08em; text-transform: uppercase; font-weight: 600; color: var(--dash-color-accent-700); margin-bottom: 8px; }
.dashboard-body .report-kpi-value { font-family: var(--dash-font-heading); font-size: 28px; line-height: 1; font-variant-numeric: tabular-nums; color: var(--dash-color-text); }
.dashboard-body .report-kpi-delta { margin-top: 8px; font-size: 12px; display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; }
.dashboard-body .report-delta { font-weight: 600; font-variant-numeric: tabular-nums; }
.dashboard-body .report-delta-up { color: var(--dash-color-success); }
.dashboard-body .report-delta-down { color: var(--dash-color-danger); }
.dashboard-body .report-delta-none { color: color-mix(in srgb, var(--dash-color-text) 45%, transparent); }
.dashboard-body .report-kpi-delta-note { color: color-mix(in srgb, var(--dash-color-text) 55%, transparent); }

.dashboard-body .report-bars { border: 1px solid var(--dash-color-divider); padding: 14px 18px; margin-bottom: 28px; }
.dashboard-body .report-bar { display: flex; align-items: center; gap: 12px; padding: 4px 0; }
.dashboard-body .report-bar-label { flex: 0 0 72px; font-size: 12px; color: color-mix(in srgb, var(--dash-color-text) 65%, transparent); }
.dashboard-body .report-bar-track { flex: 1 1 auto; height: 12px; background: var(--dash-color-neutral-100); border: 1px solid var(--dash-color-divider); }
.dashboard-body .report-bar-fill { display: block; height: 100%; background: var(--dash-color-accent-500); }
.dashboard-body .report-bar-value { flex: 0 0 88px; text-align: right; font-size: 12.5px; font-variant-numeric: tabular-nums; }

.dashboard-body .report-subrow td { color: color-mix(in srgb, var(--dash-color-text) 65%, transparent); }
.dashboard-body .report-subrow-label { padding-left: 18px; font-size: 12px; }

@media (max-width: 860px) {
  .dashboard-body .report-kpis { grid-template-columns: repeat(2, 1fr); }
}
.dashboard-body .table-actions { display: flex; gap: 6px; }
.dashboard-body .table-foot { display: flex; align-items: center; justify-content: space-between; padding: 12px 16px; border-top: 1px solid var(--dash-color-divider); background: var(--dash-color-surface); font-size: 12.5px; color: color-mix(in srgb, var(--dash-color-text) 65%, transparent); flex-wrap: wrap; gap: 10px; }
/* Targets Kaminari's actual default markup verbatim (checked against the gem's own partials,
   not assumed): <nav class="pagination"><span class="page[ current]">, <span class="next/prev">,
   <span class="page gap">. No custom Kaminari theme/views exist in this app. */
.dashboard-body .pagination { display: flex; gap: 4px; list-style: none; margin: 0; padding: 0; }
.dashboard-body .pagination .page,
.dashboard-body .pagination .next,
.dashboard-body .pagination .prev {
  display: inline-flex; align-items: center; justify-content: center; min-width: 26px; height: 26px;
  padding: 0 8px; border: 1px solid var(--dash-color-divider); font-size: 12px; color: var(--dash-color-text);
}
.dashboard-body .pagination a { text-decoration: none; color: inherit; }
.dashboard-body .pagination .page.current { background: var(--dash-color-accent-800); border-color: var(--dash-color-accent-800); color: var(--dash-color-bg); }
.dashboard-body .pagination .page.gap { opacity: 0.5; border-color: transparent; }
.dashboard-body .pagination .page:has(a):hover, .dashboard-body .pagination .next:has(a):hover, .dashboard-body .pagination .prev:has(a):hover { border-color: var(--dash-color-accent); }
.dashboard-body .pagination .next:not(:has(a)), .dashboard-body .pagination .prev:not(:has(a)) { opacity: 0.4; }

/* — modals (menu category/item add/edit) — */
.dashboard-body .dash-modal {
  position: fixed; inset: 0; display: none; align-items: flex-start; justify-content: center;
  background: color-mix(in srgb, var(--dash-color-accent-900) 45%, transparent);
  padding: 60px 20px; overflow-y: auto; z-index: 300;
}
.dashboard-body .dash-modal.open { display: flex; }
.dashboard-body .dash-modal-content { background: var(--dash-color-bg); border: 1px solid var(--dash-color-divider); width: 100%; max-width: 30rem; }
.dashboard-body .dash-modal-header { display: flex; align-items: center; justify-content: space-between; padding: 18px 20px; border-bottom: 1px solid var(--dash-color-divider); }
.dashboard-body .dash-modal-header h2 { font-size: 15px; text-transform: uppercase; }
.dashboard-body .dash-modal-close { background: none; border: none; cursor: pointer; font-size: 18px; line-height: 1; color: var(--dash-color-text); padding: 2px; }
.dashboard-body .dash-modal-body { padding: 20px; }
.dashboard-body .dash-modal-footer { display: flex; align-items: center; gap: 10px; padding: 16px 20px; border-top: 1px solid var(--dash-color-divider); }
.dashboard-body .dash-modal-danger { margin-top: 4px; padding: 18px 20px 20px; border-top: 1px solid var(--dash-color-divider); }
.dashboard-body .dash-modal-danger .label { display: block; font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--dash-color-danger); font-weight: 600; margin-bottom: 8px; font-family: var(--dash-font-heading); }

/* — tabs (menu editor categories) — */
.dashboard-body .dash-tabs { display: flex; gap: 4px; overflow-x: auto; border-bottom: 1px solid var(--dash-color-divider); }
.dashboard-body .dash-tab {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 10px 16px; font-family: var(--dash-font-heading); font-weight: var(--dash-font-heading-weight);
  font-size: 13.5px; letter-spacing: 0.01em;
  color: color-mix(in srgb, var(--dash-color-text) 65%, transparent);
  background: none; border: none; border-bottom: 2px solid transparent; cursor: pointer; white-space: nowrap;
}
.dashboard-body .dash-tab:hover { color: var(--dash-color-text); }
.dashboard-body .dash-tab.active { color: var(--dash-color-accent-800); border-bottom-color: var(--dash-color-accent-700); }
.dashboard-body .dash-tab .edit-cat { margin-left: 2px; opacity: 0.6; text-decoration: none; color: inherit; }
.dashboard-body .dash-tab .edit-cat:hover { opacity: 1; }
.dashboard-body .dash-tab-wrap { display: inline-flex; align-items: center; gap: 2px; }
.dashboard-body .dash-tab-wrap .edit-cat { padding: 4px 6px 4px 0; opacity: 0.5; text-decoration: none; color: inherit; font-size: 12px; }
.dashboard-body .dash-tab-wrap .edit-cat:hover { opacity: 1; }
.dashboard-body .dash-tab-content { padding: 20px 0; }
.dashboard-body .dash-tab-content-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.dashboard-body .dash-item-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.dashboard-body .dash-item-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  border: 1px solid var(--dash-color-divider); padding: 10px 14px; cursor: pointer; background: var(--dash-color-bg);
}
.dashboard-body .dash-item-row:hover { background: var(--dash-color-surface); }
.dashboard-body .dash-item-row:nth-child(even) { background: var(--dash-color-surface); }
.dashboard-body .dash-item-row .name { font-weight: 600; font-size: 13.5px; }
.dashboard-body .dash-item-row .price { font-variant-numeric: tabular-nums; color: var(--dash-color-accent-700); font-weight: 600; font-size: 13px; }
.dashboard-body .dash-item-row .item-link {
  display: flex; align-items: center; justify-content: space-between; width: 100%; gap: 10px;
  text-decoration: none; color: inherit;
}

/* — menu editor: variant manager — */
.dashboard-body .field-check { display: flex; align-items: center; gap: 8px; margin-bottom: 16px; font-size: 13px; }
.dashboard-body .field-check input[type="checkbox"] { width: 16px; height: 16px; }
.dashboard-body .variant-add-form { border: 1px solid var(--dash-color-divider); background: var(--dash-color-surface); padding: 14px; margin-bottom: 16px; }
.dashboard-body .variant-form-grid { display: grid; grid-template-columns: 1fr 1fr auto; gap: 8px; align-items: end; }
.dashboard-body .variant-form-grid.invoice-line-grid { grid-template-columns: 1fr 1fr 1fr auto; }
.dashboard-body .variant-form-grid .field { margin-bottom: 0; max-width: none; }
.dashboard-body .variant-form-grid .field > label { font-size: 11px; }

/* — settings — */
.dashboard-body .settings-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 24px; border: 1px solid var(--dash-color-divider); padding: 20px; max-width: 40rem; }
.dashboard-body .settings-row h3 { font-size: 15px; margin-bottom: 6px; text-transform: uppercase; }
.dashboard-body .settings-row p { margin: 0; font-size: 13px; font-family: var(--dash-font-body); text-transform: none; letter-spacing: normal; font-weight: 400; color: color-mix(in srgb, var(--dash-color-text) 65%, transparent); max-width: 34ch; }
.dashboard-body .settings-note { display: flex; gap: 10px; border: 1px solid var(--dash-color-accent-100); background: var(--dash-color-accent-100); padding: 14px 16px; max-width: 40rem; margin-top: 18px; font-size: 12.5px; color: var(--dash-color-accent-800); }

/* — subscription plan cards (OWN-18) — */
.dashboard-body .plan-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 20px;
}
.dashboard-body .plan-card {
  position: relative; border: 1px solid var(--dash-color-divider);
  background: var(--dash-color-bg); padding: 24px 22px; display: flex; flex-direction: column;
}
.dashboard-body .plan-card-featured { border-color: var(--dash-color-accent-500); }
.dashboard-body .plan-card-badge {
  position: absolute; top: -1px; right: -1px;
  background: var(--dash-color-accent-800); color: var(--dash-color-bg);
  font-family: var(--dash-font-heading); font-size: 11px; letter-spacing: 0.04em;
  padding: 4px 10px;
}
.dashboard-body .plan-card-name {
  font-family: var(--dash-font-heading); font-weight: var(--dash-font-heading-weight);
  font-size: 17px; margin: 0 0 6px;
}
.dashboard-body .plan-card-price { margin: 0 0 10px; }
.dashboard-body .plan-card-price .amount {
  font-family: var(--dash-font-heading); font-size: 30px; color: var(--dash-color-accent-800);
  font-variant-numeric: tabular-nums;
}
.dashboard-body .plan-card-price .period {
  font-size: 12.5px; color: color-mix(in srgb, var(--dash-color-text) 60%, transparent);
}
.dashboard-body .plan-card-desc {
  font-size: 13px; color: color-mix(in srgb, var(--dash-color-text) 75%, transparent); margin: 0 0 14px;
}
.dashboard-body .plan-card-features { list-style: none; padding: 0; margin: 0 0 20px; flex: 1 1 auto; }
.dashboard-body .plan-card-features li {
  font-size: 13px; line-height: 1.5; padding-left: 16px; position: relative; margin-bottom: 6px;
}
.dashboard-body .plan-card-features li::before {
  content: "+"; position: absolute; left: 0; color: var(--dash-color-accent-500);
}

/* The dashboard inside the mobile app (OWN-22).

   Mirrors the <=860px collapsed-sidebar rules at ANY width, because a 240px vertical rail sitting
   under an app header looks wrong on a tablet in landscape — and in the app the header, not the
   sidebar, is the chrome. CSS cannot OR a media query with a class, so these are duplicated
   rather than shared; if the collapsed rules below change, change these too. */
.dashboard-body.is-native .app-shell {
  flex-direction: column;
  /* The header sits above the shell now, so the shell filling the viewport on its own would push
     the page just past it and produce a scrollbar on every short screen. */
  min-height: 0;
}
.dashboard-body.is-native .sidebar {
  width: 100%; height: auto; position: static; flex-direction: row; align-items: center; overflow-x: auto;
}
.dashboard-body.is-native .sidebar-brand {
  border-bottom: none; border-right: 1px solid var(--dash-color-divider); flex: 0 0 auto;
}
.dashboard-body.is-native .sidebar-nav { display: flex; padding: 0; overflow-y: visible; }
.dashboard-body.is-native .sidebar-link { border-left: none; border-bottom: 2px solid transparent; white-space: nowrap; }
.dashboard-body.is-native .sidebar-link.active {
  border-left-color: transparent; border-bottom-color: var(--dash-color-accent-700);
}

@media (max-width: 860px) {
  .dashboard-body .app-shell { flex-direction: column; }
  .dashboard-body .sidebar { width: 100%; height: auto; position: static; flex-direction: row; align-items: center; overflow-x: auto; }
  .dashboard-body .sidebar-brand { border-bottom: none; border-right: 1px solid var(--dash-color-divider); flex: 0 0 auto; }
  .dashboard-body .sidebar-nav { display: flex; padding: 0; overflow-y: visible; }
  .dashboard-body .sidebar-link { border-left: none; border-bottom: 2px solid transparent; white-space: nowrap; }
  .dashboard-body .sidebar-link.active { border-left-color: transparent; border-bottom-color: var(--dash-color-accent-700); }
  .dashboard-body .sidebar-footer { border-top: none; border-left: 1px solid var(--dash-color-divider); flex: 0 0 auto; margin-left: auto; }
  .dashboard-body .sidebar-footer .who { display: none; }

  .dashboard-body .sidebar-callout {
    margin: 0 10px; padding: 0; border: none; background: none; flex: 0 0 auto;
  }
  .dashboard-body .sidebar-callout-kicker,
  .dashboard-body .sidebar-callout-body { display: none; }
  .dashboard-body .sidebar-callout-cta { min-height: 44px; display: flex; align-items: center; white-space: nowrap; }

  /* Touch targets. At desktop density .btn is 26–34px tall and .btn-sm only 26px — about half
     the ~44px a fingertip needs, and the dashboard's row actions (QR / Open / Remove / Edit /
     Delete) are all .btn-sm. Bump them on the same breakpoint where the layout already goes
     single-column, and let the action rows wrap instead of squeezing the wider buttons. */
  .dashboard-body .btn { min-height: 44px; padding: 10px 16px; font-size: 14px; }
  .dashboard-body .btn-sm { min-height: 40px; min-width: 44px; padding: 8px 12px; font-size: 13px; }
  .dashboard-body .sidebar-footer .logout-btn { min-height: 44px; padding: 4px 10px; font-size: 13px; }
  .dashboard-body .pcard-list li { flex-wrap: wrap; gap: 8px; }
  .dashboard-body .pcard-head { flex-wrap: wrap; gap: 8px; }
  .dashboard-body .row-actions,
  .dashboard-body .pcard-list .row-actions,
  .dashboard-body .table-actions { flex-wrap: wrap; align-items: center; gap: 8px; }

  /* The 68px logo is ~255px wide — on a 390px screen it left the collapsed nav strip with
     almost no room, pushing every link behind a horizontal scroll. Same shrink-to-fit reasoning
     as the desktop sidebar rule, one step further for the horizontal bar. */
  .dashboard-body .sidebar-brand { padding: 10px 14px; }
  .dashboard-body .sidebar-brand-logo { max-height: 36px; }
}

/* Receipt — Ascent Design */
.customer-receipt {
  max-width: 32rem;
  margin: var(--space-10) auto;
  padding: 0 var(--space-4);
}
.customer-receipt-inner {
  background: white;
  border-radius: var(--radius-xl);
  padding: var(--space-8);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.12);
  border: 1px solid #e8e8eb;
  text-align: center;
}
.customer-receipt h1.display-heading {
  font-size: var(--text-2xl);
  font-weight: 700;
  background: linear-gradient(135deg, var(--color-primary), #5a59c8);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  margin: var(--space-2) 0;
  letter-spacing: -0.01em;
}
.customer-receipt-meta {
  color: #7a7a8e;
  margin-bottom: var(--space-6);
  font-weight: 500;
}
.customer-receipt-meta code {
  background: linear-gradient(135deg, rgba(70, 69, 199, 0.08), rgba(70, 69, 199, 0.04));
  padding: 4px var(--space-2);
  border-radius: var(--radius-md);
  border: 1px solid rgba(70, 69, 199, 0.12);
  font-size: var(--text-sm);
  color: var(--color-primary);
  font-weight: 600;
}
.customer-receipt-items {
  list-style: none;
  padding: 0;
  margin: 0 0 var(--space-4);
  text-align: left;
}
.customer-receipt-items li {
  display: grid;
  grid-template-columns: 3rem 1fr auto;
  gap: var(--space-3);
  padding: var(--space-2) 0;
  border-bottom: 1px dashed var(--color-border);
}
.customer-receipt-items .qty { color: var(--color-text-muted); }
.customer-receipt-items .price { font-variant-numeric: tabular-nums; }
.customer-receipt-total {
  display: flex;
  justify-content: space-between;
  padding: var(--space-4) 0;
  border-top: 2px solid var(--color-text);
  font-size: var(--text-md);
  margin-bottom: var(--space-4);
}
/* The live order status region on /r/:token. */
.customer-body .order-status {
  margin: var(--space-3) 0;
}

.customer-body .order-status-headline {
  margin: 8px 0 4px;
  font-size: 21px;
}

/* The only status that asks the customer to move. */
.customer-body .order-status-ready {
  color: var(--color-status-ready);
}

.customer-body .order-status-sub {
  margin: 0;
  color: color-mix(in srgb, var(--order-color-text) 65%, transparent);
}

.customer-receipt-note { color: var(--color-text-muted); font-size: var(--text-sm); }

/* Receipt — compact header shown above receipt & flagged cards — Ascent */
.customer-mini-hero {
  background: linear-gradient(135deg, var(--color-primary), #5a59c8);
  color: white;
  padding: var(--space-6) var(--space-5) var(--space-5);
  text-align: center;
  box-shadow: 0 8px 24px rgba(70, 69, 199, 0.15);
}
.customer-mini-hero--flagged {
  background: linear-gradient(135deg, #ff6b6b, #ee5a52);
  box-shadow: 0 8px 24px rgba(255, 107, 107, 0.15);
}
.customer-mini-hero-inner { max-width: 32rem; margin: 0 auto; }
.customer-mini-shop {
  font-size: var(--text-md);
  font-weight: 600;
  color: rgba(255,255,255,0.95);
  margin-top: var(--space-2);
  letter-spacing: -0.01em;
}

/* Inline status pill used on receipt page — Ascent */
.order-status-pill {
  display: inline-block;
  padding: 6px var(--space-2);
  border-radius: var(--radius-md);
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.order-status-pill--pending_verification { background: rgba(70, 69, 199, 0.1); color: var(--color-primary); }
.order-status-pill--verified             { background: rgba(70, 69, 199, 0.1); color: var(--color-primary); }
.order-status-pill--flagged              { background: rgba(255, 107, 107, 0.1); color: #ff6b6b; }
.order-status-pill--confirmed            { background: rgba(70, 69, 199, 0.1); color: var(--color-primary); }
.order-status-pill--preparing            { background: rgba(201, 121, 65, 0.1); color: #c97941; }
.order-status-pill--ready                { background: rgba(61, 140, 94, 0.1); color: #3d8c5e; }
.order-status-pill--delivered            { background: rgba(74, 77, 86, 0.1); color: #4a4d56; }
.order-status-pill--cancelled            { background: rgba(255, 107, 107, 0.1); color: #ff6b6b; }

/* Flagged order screen — Ascent */
.flagged-icon {
  font-size: var(--text-3xl);
  margin-bottom: var(--space-3);
  color: #ff6b6b;
  filter: drop-shadow(0 4px 12px rgba(255, 107, 107, 0.15));
}

.flagged-section {
  margin-bottom: var(--space-6);
  text-align: left;
  background: white;
  padding: var(--space-5);
  border-radius: var(--radius-lg);
  border: 1px solid #f0f0f3;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.04);
}

.flagged-section-title {
  font-size: var(--text-sm);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: #7a7a8e;
  margin-bottom: var(--space-3);
  padding-bottom: var(--space-3);
  border-bottom: 2px solid #e8e8eb;
}
.flagged-section--unavailable .flagged-section-title {
  color: #ff6b6b;
  border-bottom-color: rgba(255, 107, 107, 0.2);
}

.receipt-item--unavailable {
  opacity: 0.55;
  text-decoration: line-through;
}

.unavailable-badge {
  display: inline-block;
  background: rgba(255, 107, 107, 0.15);
  color: #ff6b6b;
  font-size: var(--text-xs);
  font-weight: 700;
  padding: 4px var(--space-2);
  border-radius: var(--radius-md);
  white-space: nowrap;
  text-decoration: none;
  border: 1px solid rgba(255, 107, 107, 0.2);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.flagged-actions { margin: var(--space-6) 0 var(--space-5); }

.customer-cta--full {
  width: 100%;
  display: block;
  text-align: center;
  border-radius: var(--radius-lg);
}

/* ============================================================
   Bartender Board — Industry design system
   ============================================================ */

.bartender-body {
  --bar-color-bg: #f2f2f3;
  --bar-color-surface: #ffffff;
  --bar-color-text: #1d1f20;
  --bar-color-divider: color-mix(in srgb, #1d1f20 16%, transparent);
  --bar-color-accent-100: #eef6ff;
  --bar-color-accent-500: #749dc4;
  --bar-color-accent-600: #597ea3;
  --bar-color-accent-700: #416180;
  --bar-color-accent-800: #2c455d;
  --bar-font-heading: "Barlow Condensed", system-ui, sans-serif;
  --bar-font-body: "Barlow", system-ui, sans-serif;

  background: var(--bar-color-bg);
  color: var(--bar-color-text);
  font-family: var(--bar-font-body);
  min-height: 100vh;
}

.bartender-body .bartender-topbar {
  background: var(--bar-color-surface);
  border-bottom: 1px solid var(--bar-color-divider);
  color: var(--bar-color-text);
  padding: var(--space-3) var(--space-6);
  display: flex;
  align-items: center;
  justify-content: space-between;
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
}

.bartender-body .bartender-brand {
  font-family: var(--bar-font-heading);
  font-weight: 600;
  font-size: var(--text-md);
  color: var(--bar-color-accent-700);
}
.bartender-body .bartender-shop {
  color: var(--bar-color-text);
  opacity: 0.6;
  text-transform: none;
  font-family: var(--bar-font-body);
  font-weight: 400;
}

.bartender-body .bartender-topbar-actions {
  display: flex;
  align-items: center;
  gap: var(--space-4);
}
.bartender-body .bartender-user-name { font-size: var(--text-sm); color: var(--bar-color-text); opacity: 0.65; }

.bartender-body .btn-logout-bartender {
  font-family: var(--bar-font-heading);
  font-weight: 600;
  font-size: var(--text-sm);
  background: transparent;
  color: var(--bar-color-accent-700);
  border: 1px solid var(--bar-color-accent-500);
  padding: var(--space-2) var(--space-4);
  border-radius: 0;
  cursor: pointer;
  transition: background 150ms ease;
}
.bartender-body .btn-logout-bartender:hover { background: color-mix(in srgb, var(--bar-color-accent-500) 10%, transparent); }

.bartender-body .bartender-main { padding: var(--space-6) var(--space-8); }

/* Corner-bracket registration marks — same technique as .dashboard-body .corner */
.bartender-body .bar-card,
.bartender-body .bar-modal-content { position: relative; }
.bartender-body .corner { position: absolute; width: 12px; height: 12px; color: color-mix(in srgb, var(--bar-color-text) 55%, transparent); pointer-events: none; }
.bartender-body .corner::before { content: ""; position: absolute; left: 5px; top: 0; width: 1px; height: 100%; background: currentColor; }
.bartender-body .corner::after { content: ""; position: absolute; top: 5px; left: 0; width: 100%; height: 1px; background: currentColor; }
.bartender-body .corner.tl { top: -6px; left: -6px; }
.bartender-body .corner.tr { top: -6px; right: -6px; }
.bartender-body .corner.bl { bottom: -6px; left: -6px; }
.bartender-body .corner.br { bottom: -6px; right: -6px; }

.bartender-body .bar-section { margin-bottom: var(--space-6); }

.bartender-body .bar-section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin: 0 0 var(--space-3);
  padding-bottom: var(--space-2);
  border-bottom: 1px solid var(--bar-color-divider);
}
.bartender-body .bar-section-head h2 {
  font-family: var(--bar-font-heading);
  font-weight: 600;
  font-size: var(--text-md);
  color: var(--bar-color-accent-700);
  margin: 0;
}
.bartender-body .bar-section-head .muted { opacity: 0.6; font-size: var(--text-sm); }

.bartender-body .board-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 10rem;
  text-align: center;
  color: var(--bar-color-text);
  opacity: 0.55;
}
.bartender-body .board-empty-inner h2 { font-size: var(--text-lg); font-weight: 600; margin-bottom: var(--space-2); }

.bartender-body .board-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr));
  gap: var(--space-4);
}

.bartender-body .order-card-link { display: block; cursor: pointer; text-decoration: none; color: inherit; }
.bartender-body .order-card-link:focus-visible { outline: 2px solid var(--bar-color-accent-500); outline-offset: 2px; }

.bartender-body .bar-card {
  background: var(--bar-color-surface);
  border: 1px solid var(--bar-color-divider);
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.bartender-body .bar-card[data-status="delivered"],
.bartender-body .bar-card[data-status="cancelled"] { opacity: 0.6; }

.bartender-body .order-card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-2);
}
.bartender-body .order-table-name { font-size: var(--text-md); font-weight: 700; }
.bartender-body .order-time { font-size: var(--text-sm); opacity: 0.55; margin-top: 2px; }

.bartender-body .order-status-badge {
  display: inline-block;
  padding: 3px 8px;
  font-family: var(--bar-font-heading);
  font-weight: 600;
  font-size: 11px;
  white-space: nowrap;
}
.bartender-body .order-status-badge[data-status="pending_verification"] { background: var(--color-warm-light); color: var(--color-warm-hover); }
.bartender-body .order-status-badge[data-status="verified"] { background: var(--color-primary-light); color: var(--color-primary); }
.bartender-body .order-status-badge[data-status="flagged"] { background: var(--color-danger-light); color: var(--color-danger); }
.bartender-body .order-status-badge[data-status="confirmed"] { background: var(--color-primary-light); color: var(--color-status-confirmed); }
.bartender-body .order-status-badge[data-status="preparing"] { background: var(--color-warm-light); color: var(--color-status-preparing); }
.bartender-body .order-status-badge[data-status="ready"] { background: #e5f2ec; color: var(--color-status-ready); }
.bartender-body .order-status-badge[data-status="delivered"] { background: #eceded; color: var(--color-status-delivered); }
.bartender-body .order-status-badge[data-status="cancelled"] { background: var(--color-danger-light); color: var(--color-status-cancelled); }

.bartender-body .order-items { list-style: none; margin: 0; padding: 0; font-size: var(--text-sm); }
.bartender-body .order-items li { display: flex; gap: 6px; padding: 2px 0; }
.bartender-body .order-items li.unavailable { opacity: 0.5; text-decoration: line-through; }
.bartender-body .order-items .qty { font-weight: 600; opacity: 0.7; min-width: 22px; }
.bartender-body .order-item-variant { opacity: 0.6; font-size: 11px; margin-left: 2px; }

/* CUST-14. The customer's instruction for this line, staff-facing (#staff_details — prefers the
   translation once one exists, falls back to the customer's own words otherwise). */
.bartender-body .order-item-details {
  display: block;
  font-size: 12.5px;
  font-style: italic;
  color: color-mix(in srgb, var(--bar-color-text) 70%, transparent);
}

.bartender-body .order-notes {
  font-size: var(--text-sm);
  opacity: 0.75;
  padding: var(--space-2);
  background: var(--bar-color-bg);
  border-left: 2px solid var(--bar-color-accent-500);
}

.bartender-body .order-payment-tag {
  font-family: var(--bar-font-heading);
  font-size: 11px;
  font-weight: 600;
  opacity: 0.6;
}

.bartender-body .order-card-footer { display: flex; flex-direction: column; gap: var(--space-2); margin-top: auto; }

.bartender-body .bar-btn {
  display: block;
  width: 100%;
  text-align: center;
  font-family: var(--bar-font-heading);
  font-weight: 600;
  font-size: 13px;
  padding: var(--space-2) var(--space-3);
  border-radius: 0;
  border: 1px solid var(--bar-color-accent-500);
  background: var(--bar-color-accent-500);
  color: var(--bar-color-bg);
  cursor: pointer;
  min-height: 40px;
  transition: background 150ms ease;
}
.bartender-body .bar-btn:hover { background: var(--bar-color-accent-600); border-color: var(--bar-color-accent-600); }
.bartender-body .bar-btn-ghost { background: transparent; color: var(--bar-color-accent-700); }
.bartender-body .bar-btn-ghost:hover { background: color-mix(in srgb, var(--bar-color-accent-500) 10%, transparent); }

.bartender-body .flag-details { width: 100%; }
.bartender-body .flag-details summary { list-style: none; cursor: pointer; }
.bartender-body .flag-details summary::-webkit-details-marker { display: none; }
.bartender-body .flag-details[open] > summary.bar-btn-ghost { background: var(--bar-color-accent-100); border-color: var(--bar-color-accent-500); }

.bartender-body .flag-items-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin: var(--space-2) 0;
  padding: var(--space-2);
  border: 1px solid var(--bar-color-divider);
  max-height: 160px;
  overflow-y: auto;
}
.bartender-body .flag-item-label { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-sm); cursor: pointer; }
.bartender-body .flag-item-label input[type="checkbox"] { accent-color: var(--bar-color-accent-500); cursor: pointer; margin: 0; }

.bartender-body .verify-form, .bartender-body .flag-form { width: 100%; margin: 0; }
.bartender-body .verify-form input[type="submit"] { width: 100%; }

/* Detail / verification modal */
.bartender-body .modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(29, 31, 32, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  padding: var(--space-4);
}

.bartender-body .bar-modal-content {
  background: var(--bar-color-bg);
  border: 1px solid var(--bar-color-divider);
  max-width: 30rem;
  width: 100%;
  max-height: 90vh;
  display: flex;
  flex-direction: column;
}

.bartender-body .bar-modal-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  padding: var(--space-5) 40px var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--bar-color-divider);
  gap: var(--space-3);
}
.bartender-body .bar-modal-header h2 { margin: 0; font-family: var(--bar-font-heading); font-weight: 600; font-size: 17px; }
.bartender-body .bar-modal-header .modal-time { margin: 3px 0 0; font-size: 11px; opacity: 0.55; }

.bartender-body .bar-modal-location {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--bar-color-divider);
}
.bartender-body .bar-modal-location .location-item { display: flex; flex-direction: column; }
.bartender-body .bar-modal-location .location-item label {
  display: block;
  font-family: var(--bar-font-heading);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: 10.5px;
  font-weight: 600;
  opacity: 0.55;
  margin-bottom: 3px;
}
.bartender-body .bar-modal-location .location-item span { font-size: 14px; font-weight: 600; }

.bartender-body .bar-modal-items { padding: var(--space-4) var(--space-5); border-bottom: 1px solid var(--bar-color-divider); flex: 1; overflow-y: auto; }
.bartender-body .bar-modal-items h3 { margin: 0 0 var(--space-2); font-family: var(--bar-font-heading); font-weight: 600; font-size: 13px; color: var(--bar-color-accent-700); }
.bartender-body .items-list { list-style: none; margin: 0; padding: 0; }
.bartender-body .items-list li { display: flex; gap: var(--space-2); padding: 5px 0; font-size: 13.5px; }
.bartender-body .items-list li.unavailable { opacity: 0.6; text-decoration: line-through; }
.bartender-body .items-list .qty { font-weight: 600; min-width: 30px; opacity: 0.7; }
.bartender-body .items-list .variant { opacity: 0.6; font-size: 11px; margin-left: 4px; }
.bartender-body .empty-state { opacity: 0.6; font-size: 14px; margin: 0; }

.bartender-body .bar-modal-notes { padding: var(--space-4) var(--space-5); border-bottom: 1px solid var(--bar-color-divider); background: var(--bar-color-surface); }
.bartender-body .bar-modal-notes h3 { margin: 0 0 var(--space-2); font-family: var(--bar-font-heading); font-weight: 600; font-size: 12px; opacity: 0.6; }
.bartender-body .bar-modal-notes p { margin: 0; font-size: 14px; line-height: 1.5; }

.bartender-body .modal-error {
  padding: var(--space-3) var(--space-5);
  background: var(--color-danger-light);
  color: var(--color-danger);
  border-bottom: 1px solid var(--bar-color-divider);
  font-size: 13px;
  line-height: 1.4;
}

.bartender-body .bar-modal-footer { padding: var(--space-4) var(--space-5); display: flex; flex-direction: column; gap: var(--space-3); }
.bartender-body .flag-items-container { padding: var(--space-2) 0; }

.bartender-body .modal-close {
  position: absolute;
  top: 8px;
  right: 8px;
  background: none;
  border: none;
  font-size: 24px;
  line-height: 1;
  cursor: pointer;
  color: var(--bar-color-text);
  opacity: 0.5;
  padding: 4px 8px;
}
.bartender-body .modal-close:hover { opacity: 0.9; }

.bartender-body .bar-alert-controls {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
  padding: 0 0 var(--space-3);
}

.bartender-body .bar-sound-toggle {
  background: var(--bar-color-surface);
  color: var(--bar-color-text);
  border: 1px solid var(--bar-color-divider);
  border-radius: 6px;
  padding: 6px 14px;
  font: inherit;
  cursor: pointer;
}

.bartender-body.has-unseen-orders {
  box-shadow: inset 0 0 0 4px var(--bar-color-accent-500);
}

/* The owner's "require order alerts" policy. Sound-on becomes plain text rather than a button,
   because with the policy on there is no action left to offer. */
.bartender-body .bar-alert-state {
  color: var(--bar-color-text);
  border: 1px solid var(--bar-color-divider);
  border-radius: 6px;
  padding: 6px 14px;
  font: inherit;
}

.bartender-body .bar-alert-banner {
  flex-basis: 100%;
  background: color-mix(in srgb, var(--bar-color-accent-500) 18%, var(--bar-color-surface));
  border: 1px solid var(--bar-color-accent-500);
  border-radius: 6px;
  color: var(--bar-color-text);
  padding: var(--space-2) var(--space-3);
  margin-bottom: var(--space-2);
  text-align: left;
}

/* ============================================================
   The mobile app's header (.native-topbar)
   Rendered by shared/_native_topbar, shared by both staff layouts.

   Its tokens are declared on the header ITSELF rather than under .bartender-body or
   .dashboard-body, because one partial serves both scopes and must not borrow either's
   palette — and per docs/rules/design-system.md they must never reach :root.
   ============================================================ */

.native-topbar {
  --native-bg: #1d1f20;
  --native-fg: #ffffff;
  --native-divider: rgb(255 255 255 / 16%);
  --native-menu-bg: #ffffff;
  --native-menu-fg: #1d1f20;
  --native-danger: #c0392b;

  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  /* env(safe-area-inset-top) so the header clears a notch when the app runs full-bleed. It
     resolves to 0 in a browser, so this costs the web nothing. */
  padding: calc(var(--space-2) + env(safe-area-inset-top, 0px)) var(--space-3) var(--space-2);
  background: var(--native-bg);
  color: var(--native-fg);
}

.native-topbar-brand {
  font-weight: 700;
  font-size: 16px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.native-topbar-actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.native-icon-button {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  /* 44px is the minimum comfortable touch target on a phone; anything smaller gets mis-tapped
     next to a neighbouring control. */
  min-width: 44px;
  min-height: 44px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: inherit;
  cursor: pointer;
}

.native-avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 36px;
  min-height: 36px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  color: #ffffff;
  font: inherit;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.02em;
  cursor: pointer;
}

.native-profile-wrap,
.native-topbar .bar-bell-wrap {
  position: relative;
  display: inline-flex;
}

.native-profile-menu {
  position: absolute;
  top: calc(100% + var(--space-1));
  right: 0;
  z-index: 40;
  min-width: 220px;
  overflow: hidden;
  border-radius: 8px;
  background: var(--native-menu-bg);
  color: var(--native-menu-fg);
  box-shadow: 0 10px 30px rgb(0 0 0 / 28%);
  text-align: left;
}

.native-profile-identity {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid rgb(0 0 0 / 10%);
}

.native-profile-identity span {
  font-size: 12px;
  opacity: 0.7;
}

.native-profile-item {
  display: block;
  width: 100%;
  padding: var(--space-2) var(--space-3);
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.native-profile-item.is-danger {
  color: var(--native-danger);
}

.native-profile-form {
  margin: 0;
}

/* The bell badge is styled for the light board; on the dark app header it needs its own
   treatment or it disappears into the bar. */
.native-topbar .bar-bell-badge {
  position: absolute;
  top: 4px;
  right: 4px;
  min-width: 18px;
  margin: 0;
  background: var(--native-danger);
  color: #ffffff;
  font-size: 11px;
  line-height: 18px;
}

.native-topbar .bar-notification-panel {
  top: calc(100% + var(--space-1));
  color: var(--native-menu-fg);
}

/* The bell and its panel. Anchored to the alert-controls row rather than the topbar — see
   .claude/specs/BAR-13-notification-panel.md for why. */
.bartender-body .bar-bell-wrap {
  position: relative;
  display: inline-block;
}

.bartender-body .bar-bell-badge {
  display: inline-block;
  min-width: 20px;
  margin-left: var(--space-1);
  padding: 0 6px;
  border-radius: 10px;
  background: var(--bar-color-accent-700);
  color: var(--bar-color-surface);
  font-size: 12px;
  text-align: center;
}

/* The cause is cascade ORIGIN, not specificity: the UA stylesheet's own
   `[hidden] { display: none }` loses to ANY author `display` declaration, however weak its
   selector, because origin is resolved before specificity. So the rule above would otherwise
   leave a badge carrying the `hidden` attribute visible with its `display: inline-block`
   intact. Re-declare it explicitly so toggling the attribute (server-rendered on load, or
   notification-bell#markRead/#increment in JS) actually hides/shows the element.
   See docs/rules/notifications.md — any element both given a `display` here and toggled with
   `hidden` needs its own `[hidden]` rule. */
.bartender-body .bar-bell-badge[hidden] {
  display: none;
}

.bartender-body .bar-notification-panel {
  position: absolute;
  right: 0;
  z-index: 20;
  width: min(360px, calc(100vw - 2 * var(--space-3)));
  max-height: 70vh;
  overflow-y: auto;
  background: var(--bar-color-surface);
  border: 1px solid var(--bar-color-divider);
  border-radius: 6px;
  box-shadow: 0 8px 24px rgb(0 0 0 / 18%);
  text-align: left;
}

.bartender-body .bar-notification-panel-head {
  margin: 0;
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--bar-color-divider);
  font-size: 14px;
}

.bartender-body .bar-notification-list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.bartender-body .bar-notification-entry {
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--bar-color-divider);
  cursor: pointer;
}

.bartender-body .bar-notification-entry.is-unread {
  background: color-mix(in srgb, var(--bar-color-accent-500) 12%, var(--bar-color-surface));
}

.bartender-body .bar-notification-title {
  margin: 0;
  font-weight: 700;
}

.bartender-body .bar-notification-body,
.bartender-body .bar-notification-meta {
  margin: 2px 0 0;
  font-size: 13px;
}

.bartender-body .bar-notification-meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-2);
}

.bartender-body .bar-notification-empty,
.bartender-body .bar-notification-truncated {
  margin: 0;
  padding: var(--space-3);
  font-size: 13px;
}

/* ============================================================
   Auth pages background — coffee shop aesthetic
   ============================================================ */

html, body {
  min-height: 100vh;
  position: relative;
}

/* ============================================================
   Confirmation Page — Email Verification
   Blueprint/Industry design language — scoped to .auth-page,
   built on top of the shared .auth-card corner-bracket component
   (see the "Landing / Signup / Login — Blueprint Exception" section
   of CLAUDE.md's Design System).
   ============================================================ */

.auth-page .confirmation-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: calc(2 * var(--auth-leading));
  width: 100%;
  max-width: 64rem;
}

@media (max-width: 768px) {
  .auth-page .confirmation-grid {
    grid-template-columns: 1fr;
  }
}

.auth-page .confirmation-card {
  max-width: none;
}

.auth-page .confirmation-card h2 {
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  font-size: 22px;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  margin: 0 0 var(--auth-half);
  color: var(--color-text);
}

.auth-page .confirmation-steps ol {
  list-style: none;
  padding: 0;
  margin: 0 0 var(--auth-leading);
}

.auth-page .confirmation-steps li {
  padding: var(--auth-space-3) 0;
  border-bottom: 1px solid var(--color-divider);
  line-height: 1.5;
  font-size: 15px;
}

.auth-page .confirmation-steps li:last-child {
  border-bottom: none;
}

.auth-page .video-card {
  display: flex;
  flex-direction: column;
}

.auth-page .youtube-embed {
  position: relative;
  width: 100%;
  padding-bottom: 56.25%;
  height: 0;
  overflow: hidden;
  margin: var(--auth-half) 0 var(--auth-leading);
  background: var(--color-surface);
  border: 1px solid var(--color-divider);
}

.auth-page .youtube-embed iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border: none;
}

.auth-page .resend-section {
  margin-top: var(--auth-leading);
  padding-top: var(--auth-leading);
  border-top: 1px solid var(--color-divider);
}

.auth-page .resend-section p {
  margin-bottom: var(--auth-space-3);
  color: color-mix(in srgb, var(--color-text) 78%, transparent);
  font-size: 15px;
}

.auth-page #resend-btn {
  background: var(--color-accent-900);
  color: var(--color-bg);
  border: 1px solid var(--color-accent-900);
  padding: 10px var(--auth-space-4);
  border-radius: var(--auth-radius-md);
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  font-size: 15px;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  cursor: pointer;
  min-height: 40px;
  transition: background 0.15s ease, border-color 0.15s ease;
}

.auth-page #resend-btn:hover:not(:disabled) {
  background: var(--color-accent-800);
  border-color: var(--color-accent-800);
}

.auth-page #resend-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.auth-page #resend-message {
  display: none;
  margin-top: var(--auth-space-3);
  padding: var(--auth-space-3);
  border-radius: var(--auth-radius-md);
  font-size: 14px;
}

.auth-page #resend-message.success {
  background: color-mix(in srgb, #3d8c5e 15%, transparent);
  color: #3d8c5e;
}

.auth-page #resend-message.error {
  background: color-mix(in srgb, #c0392b 15%, transparent);
  color: #c0392b;
}

.auth-page .confirmation-card .foot-note {
  border-top: 1px solid var(--color-divider);
  padding-top: var(--auth-leading);
}

/* Contact page honeypot — hidden from people, present for bots. Not display:none, which some
   bots skip; off-canvas with zero size is filled in far more often. */
.auth-page .contact-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* Plan cards — contact-only price slot and the yearly upsell line. */
.dashboard-body .plan-card-price-text { font-size: 20px; line-height: 1.25; }
.dashboard-body .plan-card-yearly-note {
  font-size: 12px;
  color: color-mix(in srgb, var(--dash-color-text) 70%, transparent);
  margin: 8px 0;
  text-align: center;
}
.dashboard-body .plan-card-save {
  display: inline-block;
  background: var(--dash-color-accent-500);
  color: var(--dash-color-bg);
  font-size: 10px;
  font-weight: 700;
  padding: 2px 6px;
  text-transform: uppercase;
  letter-spacing: .05em;
}

/* QR action button — the one row action worth spotting at a glance, so it gets an icon and a
   larger target than its btn-sm siblings. min-height overrides btn-sm's 26px; the icon is sized
   in px rather than em so it does not shrink with the button's small font-size. */
.dashboard-body .btn-qr {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 32px;
  padding-inline: 10px;
}
.dashboard-body .btn-qr .qr-icon {
  width: 18px;
  height: 18px;
  flex: none;
  display: block;
}

/* — Platform admin (/admin) —
   The admin panel reuses the .dashboard-body component scope wholesale: same Industry design
   system, same English copy, same components. Duplicating those rules under an --admin-color-*
   token family would be pure waste. .admin-body adds only the identity badge, so a superadmin
   can never mistake this screen for a shop's own dashboard. */
.admin-body .admin-badge {
  display: inline-block;
  font-family: var(--dash-font-heading);
  font-weight: var(--dash-font-heading-weight);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 12px;
  padding: 3px 8px;
  background: var(--dash-color-accent-900);
  color: var(--dash-color-bg);
}

/* — Blueprint import picker (shared/_blueprint_picker) —
   Rendered inside two different token scopes: the English dashboard screen and the Albanian
   onboarding step. Both scopes' tokens resolve, so the rules are grouped rather than duplicated. */
.dashboard-body .bp-category,
.onboarding-body .bp-category {
  border: 1px solid var(--dash-color-divider, rgba(29, 31, 32, 0.16));
  padding: 10px 12px;
  margin: 0 0 12px;
}
.dashboard-body .bp-category legend,
.onboarding-body .bp-category legend {
  font-family: var(--dash-font-heading, "Barlow Condensed", system-ui, sans-serif);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 0 6px;
}
.dashboard-body .bp-item,
.onboarding-body .bp-item {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 4px 0;
}
.dashboard-body .bp-item-name,
.onboarding-body .bp-item-name { flex: 1 1 auto; }
.dashboard-body .bp-item-price,
.onboarding-body .bp-item-price {
  font-variant-numeric: tabular-nums;
  opacity: 0.65;
}

/* — Add Category modal's tab strip (dashboard/menus/_add_category_modal) —
   Reuses .dash-tabs/.dash-tab, the menu editor's own component, so the two tab strips on this
   screen read as one thing; only the modal's own padding is new. The picker's item list is
   capped and scrolls, so a twenty-item blueprint category cannot push the modal footer — and
   the Import button with it — off the bottom of the viewport. */
.dashboard-body .menu-modal-tabs {
  padding: 0 20px;
  margin-bottom: 0;
}
.dashboard-body .menu-modal-tabs .dash-tab {
  padding-left: 0;
  padding-right: 0;
  margin-right: 18px;
}
.dashboard-body .dash-modal-body .bp-picker .bp-category {
  max-height: 40vh;
  overflow-y: auto;
}

/* — Chat ordering assistant (phase 1 skeleton) —
   Scoped under .customer-body like every other order-flow component: bare .chat-* names
   would be fine today, but this file's convention is that customer-flow components never
   claim a global class name. Uses the same --order-color-* tokens as the rest of the
   order-composing screens, so the chat reads as part of that system rather than a new one. */
.customer-body .customer-chat {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 12px 0 0;
  /* Room for the fixed composer (which sits above the fixed footer) so the last message is
     never hidden behind it. Mirrors how .order-home-add-more reserved its own clearance. */
  padding-bottom: 84px;
}
/* CUST-13 — the language picker: the app's only screen with no conversation and no footer.
   Same Industry surfaces as everything else in the customer flow (square corners, hairline
   borders, dark chrome above), just centred, because seven rows and a question is the whole
   screen. Seven fit a phone without scrolling; an eighth would need a grid or a scroll, and the
   last language in a scrolling list is the one nobody picks. */
.customer-body.no-order-footer .order-chrome-body { padding-bottom: 0; }
.customer-body .language-picker {
  min-height: calc(100dvh - 96px);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 18px;
  padding: 24px 20px 40px;
}
.customer-body .language-picker-ask {
  margin: 0;
  text-align: center;
  font-size: 15px;
  color: color-mix(in srgb, var(--order-color-text) 70%, transparent);
}
.customer-body .language-picker-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
/* button_to renders a form, so the row's width comes from the form and the button inside it. */
.customer-body .language-picker-list form { display: block; }
.customer-body .language-picker-option {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 12px;
  /* Left, not centred: seven names of different lengths read as a list this way and as a ragged
     cloud the other. */
  justify-content: flex-start;
  text-align: left;
  min-height: 48px;
}
.customer-body .language-picker-flag { font-size: 20px; line-height: 1; flex: 0 0 auto; }
.customer-body .language-picker-name { font-weight: 500; }

/* CUST-16 — the welcome screen, right after the picker and built the same way: no footer, centred
   in the viewport, one way forward. Four short paragraphs, no heading, sized to fit a phone
   without scrolling in the longest of the seven languages. */
.customer-body .welcome-screen {
  min-height: calc(100dvh - 96px);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 24px;
  padding: 24px 20px 40px;
}
.customer-body .welcome-copy p {
  margin: 0 0 12px;
  font-size: 16px;
  line-height: 1.5;
  color: var(--order-color-text);
  overflow-wrap: anywhere;
}
.customer-body .welcome-copy p:last-child { margin-bottom: 0; }
.customer-body .welcome-copy .welcome-lead {
  font-size: 19px;
  font-weight: 600;
  color: var(--order-color-accent-700);
}
/* button_to renders a form; the form is what has to be full width. */
.customer-body .welcome-screen form { display: block; }
.customer-body .welcome-continue { width: 100%; min-height: 48px; }

.customer-body .chat-messages {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  /* Turns need separating from each other, not just stacking. At 10px a question and its answer
     read as one block of text. */
  gap: 16px;
  flex: 1 1 auto;
}
.customer-body .chat-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 32px 0;
  text-align: center;
  color: color-mix(in srgb, var(--order-color-text) 65%, transparent);
}
.customer-body .chat-message { display: flex; }
.customer-body .chat-message-customer { justify-content: flex-end; }
.customer-body .chat-message-assistant { justify-content: flex-start; }
.customer-body .chat-bubble {
  max-width: 78%;
  padding: 12px 14px;
  border: 1px solid var(--order-color-divider);
  font-size: 15px;
  line-height: 1.45;
  /* Square corners and a hairline border, not the rounded speech bubbles a chat UI usually
     reaches for — this screen belongs to the same Industry wireframe system as the rest of
     the customer flow. */
  border-radius: 0;
}
/* The customer's own words. accent-600, not the accent-500 this used to be: 500 was ALSO the
   primary button's fill, so a thing you tap and a thing you said were the same colour — and its
   text measured 2.55:1, under the 4.5:1 AA floor. */
.customer-body .chat-message-customer .chat-bubble {
  background: var(--order-color-accent-600);
  border-color: var(--order-color-accent-600);
  color: var(--order-color-bg);
}
/* The assistant's rows carry the instructions, so they have to be findable.
   They used to fill with --order-color-neutral-100 (#f5f5f8) on an --order-color-bg (#f2f2f3)
   page — three units apart, so there was no visible bubble at all, only text on the page. The
   accent tint separates from the ground, and the rail down the leading edge lets the eye find
   every instruction by scanning one line rather than reading. */
.customer-body .chat-message-assistant .chat-bubble {
  background: var(--order-color-accent-100);
  border-color: color-mix(in srgb, var(--order-color-accent-500) 45%, transparent);
  border-left: 3px solid var(--order-color-accent-700);
  /* Keeps the text's left edge where it was, despite the thicker border. */
  padding-left: 13px;
}
/* A reply flashes on arrival so the customer sees that the assistant answered. Pure CSS: the
   animation runs because the element is new to the document, so nothing has to notice it land.
   It starts on a deeper wash of the accent and settles to the assistant bubble's own resting
   tint, with `forwards` so it ends there rather than snapping back.

   **It animates background only.** It used to animate `border-color` too, which is shorthand for
   all four sides — that would repaint the spotlight rail mid-flash and then leave it the divider
   colour, quietly undoing it. The `to` value must also stay in step with the assistant bubble's
   resting background above, or a flashed message settles on a colour no other message has.

   Only ever applied to markup a Turbo Stream appended — see _chat_message.html.erb for why the
   full-transcript replay must never carry it. */
@keyframes chat-message-arrive {
  /* HELD, not faded from frame one. The old curve was `from`/`to` over 1.5s, which is at full
     strength for a single frame and then only decaying — and the reveal scroll is still
     travelling through the first few hundred milliseconds of it, so by the time the reply is
     actually on screen the highlight is most of the way gone. Measured at 79% spent 0.9s in.
     Reported as "I'm still having a hard time working out where the answer is"; no existing
     spec could have caught it, because they all assert the marker, and the marker was there. */
  0%, 62% { background: color-mix(in srgb, var(--order-color-accent-500) 45%, var(--order-color-bg)); }
  100%    { background: var(--order-color-accent-100); }
}
.customer-body .chat-message-fresh .chat-bubble {
  /* `both`, not `forwards`: backwards fill means the bubble is already lit on the frame it is
     inserted, rather than painting its resting colour for a beat first. */
  animation: chat-message-arrive 1.6s ease-out both;
}
@media (prefers-reduced-motion: reduce) {
  /* Settled colours, no transition — the same opt-out the typing dots and send arrow use. */
  .customer-body .chat-message-fresh .chat-bubble { animation: none; }
}

/* The optimistic turn the composer paints while the model is thinking: the customer's own
   bubble and, under it, dots where the reply will land. Built in JS, never by the server, and
   removed by create_chat_message.turbo_stream.erb when the real pair arrives — so this holds
   two .chat-message rows and has to reproduce the list's own column gap itself. */
.customer-body .chat-pending {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.customer-body .chat-typing {
  /* Matches the assistant bubble it stands in for — same fill, same square corners, same
     line-height — so the real reply does not visibly jump when it replaces this. */
  min-height: 21px;
  display: flex;
  align-items: center;
}
.customer-body .chat-typing-dots { display: inline-flex; gap: 4px; }
.customer-body .chat-typing-dots i {
  display: block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  /* The same pulse, stagger and reduced-motion opt-out the send arrow's dots already use —
     one motion vocabulary on this screen, not two. */
  animation: chat-send-pulse 1s infinite ease-in-out;
}
.customer-body .chat-typing-dots i:nth-child(2) { animation-delay: 0.15s; }
.customer-body .chat-typing-dots i:nth-child(3) { animation-delay: 0.3s; }
@media (prefers-reduced-motion: reduce) {
  .customer-body .chat-typing-dots i { animation: none; opacity: 0.6; }
}
/* Pinned just above the fixed footer, the same position and z-index the order-home
   "add another product" panel used — a chat input that scrolls away with the transcript is
   useless, and this screen already had a solved precedent for bottom-anchoring. */
/* The scripted options slot (Customer::GuidedFlow). Not a bubble — these are controls, so
   they sit full-width under the conversation rather than inside an assistant-coloured box. */
.customer-body .chat-options {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 4px;
}

.customer-body .chat-options-label {
  margin: 0;
  font-family: var(--order-font-heading);
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--order-color-accent-700);
}

.customer-body .chat-options-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.customer-body .chat-options-stack .btn {
  flex: 1 1 auto;
  min-height: 44px;
}

.customer-body .chat-option-num {
  flex: 0 0 auto;
  min-width: 44px;
  min-height: 44px;
}

.customer-body .chat-options-items {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* button_to renders a form, and the global `form.button_to button { all: unset }` reset means
   these need their box back — the same fix the dashboard's touch-target rules already carry.
   The form is the flex item here, not the button, so growth has to be set on the FORM: setting
   it on .btn alone lets a wide viewport stretch six number buttons across the whole row. */
.customer-body .chat-options form.button_to {
  display: flex;
  flex: 0 0 auto;
}

.customer-body .chat-options-stack form.button_to {
  flex: 1 1 auto;
}

.customer-body .chat-options-stack form.button_to > .btn {
  width: 100%;
}

.customer-body .chat-composer {
  position: fixed;
  left: 0;
  right: 0;
  bottom: var(--order-chrome-footer-h);
  z-index: 5;
  margin: 0 20px;
}
/* The field and its send arrow share one rounded box, so the pair reads as a single control
   the way a chat composer normally does. The 24px radius is a DELIBERATE exception to this
   flow's square-corner rule — see the comment in _chat_composer.html.erb. The box carries the
   border and the white fill (it has to separate from the page's own #f2f2f3 ground); the
   textarea inside it carries neither. */
.customer-body .chat-composer-field {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  background: #fff;
  border: 1px solid var(--order-color-divider);
  border-radius: 24px;
  padding: 6px 6px 6px 16px;
  transition: border-color 140ms ease, box-shadow 140ms ease;
}
.customer-body .chat-input {
  flex: 1 1 auto;
  min-width: 0;
  border: 0;
  background: transparent;
  resize: none;
  padding: 8px 0;
  font-family: var(--order-font-body, inherit);
  /* 16px, not 15px: iOS Safari zooms the whole page in on focus for anything smaller, which
     on this screen shoves the fixed footer and composer off-viewport mid-order. */
  font-size: 17px;
  line-height: 1.4;
  color: var(--order-color-text);
  /* Matches the controller's own MAX_HEIGHT ceiling; the field scrolls past about four lines. */
  max-height: 108px;
  overflow-y: auto;
}
.customer-body .chat-input::placeholder {
  color: color-mix(in srgb, var(--order-color-text) 45%, transparent);
}
.customer-body .chat-input:focus { outline: none; }
/* Keyboard focus has to remain visible once the textarea's own outline is suppressed — the ring
   moves to the container instead of disappearing. A soft ring rather than the square 2px outline
   used elsewhere, since a hard outline reads badly against a 24px radius. */
.customer-body .chat-composer-field:focus-within {
  border-color: var(--order-color-accent-500);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--order-color-accent-500) 22%, transparent);
}
/* Circular, filled with accent-800 — the same tone as the footer's "Vazhdo" button, so the two
   strong actions on this screen read as a pair. 34px keeps it inside the field's height while
   staying a comfortable thumb target next to the 44px minimum used elsewhere. */
.customer-body .chat-send {
  flex: none;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--order-color-accent-800);
  color: var(--order-color-bg);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background 140ms ease, transform 120ms ease;
}
.customer-body .chat-send:hover:not(:disabled) { background: var(--order-color-accent-700); }
.customer-body .chat-send:active:not(:disabled) { transform: scale(0.94); }
/* The arrow is the only affordance left, so an empty field has to visibly disarm it. */
.customer-body .chat-send:disabled {
  background: color-mix(in srgb, var(--order-color-text) 16%, transparent);
  color: color-mix(in srgb, var(--order-color-text) 45%, transparent);
  cursor: default;
}
.customer-body .chat-send:focus-visible {
  outline: 2px solid var(--order-color-accent-700);
  outline-offset: 2px;
}
.customer-body .chat-send-arrow { width: 18px; height: 18px; display: block; }
/* While a turn is in flight the arrow becomes three dots, so a slow model reply never looks
   like a dropped tap. Driven by data-sending on the form, set by the Stimulus controller from
   Turbo's own submit-start/submit-end events. */
.customer-body .chat-send-dots { display: none; gap: 3px; }
.customer-body .chat-send-dots i {
  display: block;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: currentColor;
  animation: chat-send-pulse 1s infinite ease-in-out;
}
.customer-body .chat-send-dots i:nth-child(2) { animation-delay: 0.15s; }
.customer-body .chat-send-dots i:nth-child(3) { animation-delay: 0.3s; }
@keyframes chat-send-pulse { 0%, 60%, 100% { opacity: 0.3; } 30% { opacity: 1; } }
.customer-body .chat-composer[data-sending] .chat-send-arrow { display: none; }
.customer-body .chat-composer[data-sending] .chat-send-dots { display: inline-flex; }
@media (prefers-reduced-motion: reduce) {
  .customer-body .chat-send-dots i { animation: none; opacity: 0.6; }
  .customer-body .chat-send,
  .customer-body .chat-composer-field { transition: none; }
}
/* Visually-hidden label for the chat composer. The input carries a placeholder, but a
   placeholder is not an accessible name — this keeps the field labelled for a screen reader
   without putting a redundant "Mesazhi juaj" above it. First use in this codebase; scoped
   like every other customer-flow rule rather than claiming the global .sr-only name. */
.customer-body .sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
/* Review rows carry the remove control since chat took over order home (phase 1 of the
   chat assistant) — the price and the button share the row's trailing edge. */
.customer-body .review-row-end {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* — Chat recap (phase 4) — the scripted order summary the assistant asks to have shown.
   Rendered inside an assistant bubble so it reads as part of the conversation rather than a
   modal interrupting it, but wider, because it carries a line list and two actions. */
.customer-body .chat-recap { max-width: 100%; width: 100%; }
.customer-body .chat-recap-lines {
  list-style: none;
  margin: 0 0 8px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.customer-body .chat-recap-lines li { display: flex; justify-content: space-between; gap: 12px; }
.customer-body .chat-recap-total {
  display: flex;
  justify-content: space-between;
  border-top: 1px solid var(--order-color-divider);
  padding-top: 6px;
  font-weight: 700;
}
.customer-body .chat-recap-actions {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 10px;
}
/* button_to renders a form per button; `all: unset` on those buttons means the .btn rules
   need the width set here or the two actions come out different sizes. */
.customer-body .chat-recap-actions form { display: block; width: 100%; }
.customer-body .chat-recap-actions .btn { width: 100%; }

/* — Chat cart summary — the live "order so far" under the conversation, so a customer can see
   what they have added without opening the footer's items dialog. Shares .chat-recap-lines and
   .chat-recap-total above: it shows the same lines in the same shape as the recap, and a
   private copy of those rules would be one more place for the two to fall out of step.

   Full width for the same reason .chat-recap is — it carries a line list, not a sentence. */
.customer-body .chat-cart-summary { max-width: 100%; width: 100%; }
/* Same treatment as .chat-options-label, not the same class: this one sits inside an assistant
   bubble rather than above the controls, so it is a heading for the list under it. Uppercased
   in CSS, which means a spec asserting on this string needs a case-insensitive match. */
.customer-body .chat-cart-summary-label {
  margin: 0 0 8px;
  font-family: var(--order-font-heading);
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--order-color-accent-700);
}

/* — Chat status (phase 5): the post-order half, rendered from the order and pushed over
   turbo-rails' cable when the bartender acts. */
.customer-body .chat-status-waiting { display: flex; align-items: center; gap: 8px; }
.customer-body .chat-status-spinner {
  flex: none;
  width: 12px;
  height: 12px;
  border: 2px solid var(--order-color-accent-500);
  border-top-color: transparent;
  border-radius: 50%;
  animation: chat-status-spin 0.9s linear infinite;
}
@keyframes chat-status-spin { to { transform: rotate(360deg); } }
/* Respect a reduced-motion preference: the spinner is decoration, the sentence carries the
   meaning. */
@media (prefers-reduced-motion: reduce) {
  .customer-body .chat-status-spinner { animation: none; opacity: 0.5; }
}

/* — Chat payment question (phase 6). Two full-width choices, or one when the shop's plan
   does not include card payments. */
.customer-body .chat-payment-question { margin: 0 0 8px; }
.customer-body .chat-payment-actions { display: flex; flex-direction: column; gap: 6px; }
.customer-body .chat-payment-actions form { display: block; width: 100%; }
.customer-body .chat-payment-actions .btn { width: 100%; }
