/* =====================================================================
   SwadSathi Design System — LAYER 3: COMPONENTS
   ---------------------------------------------------------------------
   Every reusable UI part in the product. One class per component, BEM-ish
   modifiers. No component hard-codes a colour, radius, shadow or duration
   — it all comes from tokens.css.

   Contents
     1  Buttons            8  Badges / status      15  Empty states
     2  Button groups      9  Chips / tags         16  Skeletons
     3  Inputs & fields   10  Alerts / banners     17  Toasts
     4  Checkbox/radio    11  Cards                18  Tooltips
     5  Switch            12  Tables               19  Avatars
     6  Select            13  Pagination           20  Progress / meters
     7  Filter bar        14  Modals / drawers     21  Tabs / segmented
   ===================================================================== */

/* =============================================================== 1 ===
   BUTTONS
   Heights: sm 30 / md 36 / lg 42. Every variant shares geometry so a row
   of mixed variants always aligns to the same baseline.
   ==================================================================== */
.rr-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--rr-space-2);
  height: 36px;
  padding: 0 var(--rr-space-4);
  border: 1px solid transparent;
  border-radius: var(--rr-radius-md);
  font-family: var(--rr-font-sans);
  font-size: var(--rr-text-base);
  font-weight: var(--rr-weight-semibold);
  line-height: 1;
  letter-spacing: 0;
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
  text-decoration: none;
  transition: background-color var(--rr-dur-fast) var(--rr-ease),
              border-color var(--rr-dur-fast) var(--rr-ease),
              color var(--rr-dur-fast) var(--rr-ease),
              box-shadow var(--rr-dur-fast) var(--rr-ease),
              transform var(--rr-dur-fast) var(--rr-ease);
}
.rr-btn:hover { text-decoration: none; }
.rr-btn:active:not(:disabled) { transform: translateY(1px); }
.rr-btn:focus-visible { outline: none; box-shadow: var(--rr-ring); }
.rr-btn:disabled, .rr-btn[aria-disabled="true"] {
  opacity: 0.5; cursor: not-allowed; transform: none;
}
.rr-btn .rr-i { width: var(--rr-icon-md); height: var(--rr-icon-md); }

/* -- variants -- */
.rr-btn--primary {
  background: var(--rr-primary-600); color: var(--rr-text-inverse);
  box-shadow: var(--rr-shadow-xs);
}
.rr-btn--primary:hover:not(:disabled) { background: var(--rr-primary-700); }
.rr-btn--primary:active:not(:disabled) { background: var(--rr-primary-800); }

.rr-btn--secondary {
  background: var(--rr-surface); color: var(--rr-text-body);
  border-color: var(--rr-border-strong); box-shadow: var(--rr-shadow-xs);
}
.rr-btn--secondary:hover:not(:disabled) {
  background: var(--rr-surface-2); color: var(--rr-text); border-color: var(--rr-ink-400);
}

.rr-btn--accent  { background: var(--rr-accent-600);  color: var(--rr-text-inverse); }
.rr-btn--accent:hover:not(:disabled)  { background: var(--rr-accent-700); }
.rr-btn--accent:focus-visible { box-shadow: var(--rr-ring-accent); }

.rr-btn--success { background: var(--rr-success-600); color: var(--rr-text-inverse); }
.rr-btn--success:hover:not(:disabled) { background: var(--rr-success-700); }

.rr-btn--warning { background: var(--rr-warning-600); color: var(--rr-text-inverse); }
.rr-btn--warning:hover:not(:disabled) { background: var(--rr-warning-700); }

.rr-btn--danger  { background: var(--rr-error-600);   color: var(--rr-text-inverse); }
.rr-btn--danger:hover:not(:disabled)  { background: var(--rr-error-700); }
.rr-btn--danger:focus-visible { box-shadow: var(--rr-ring-error); }

.rr-btn--outline {
  background: transparent; color: var(--rr-primary-700);
  border-color: var(--rr-primary-300);
}
.rr-btn--outline:hover:not(:disabled) {
  background: var(--rr-primary-50); border-color: var(--rr-primary-400);
}

.rr-btn--outline-danger {
  background: transparent; color: var(--rr-error-600); border-color: var(--rr-error-200);
}
.rr-btn--outline-danger:hover:not(:disabled) { background: var(--rr-error-50); }

.rr-btn--ghost { background: transparent; color: var(--rr-text-muted); }
.rr-btn--ghost:hover:not(:disabled) { background: var(--rr-surface-3); color: var(--rr-text); }

.rr-btn--link {
  background: none; color: var(--rr-text-brand); height: auto; padding: 0;
  font-weight: var(--rr-weight-semibold);
}
.rr-btn--link:hover:not(:disabled) { color: var(--rr-primary-700); text-decoration: underline; }

/* -- sizes -- */
.rr-btn--sm { height: 30px; padding: 0 var(--rr-space-3); font-size: var(--rr-text-sm); gap: var(--rr-space-1-5); }
.rr-btn--sm .rr-i { width: var(--rr-icon-sm); height: var(--rr-icon-sm); }
.rr-btn--lg { height: 42px; padding: 0 var(--rr-space-5); font-size: var(--rr-text-md); }
.rr-btn--lg .rr-i { width: var(--rr-icon-lg); height: var(--rr-icon-lg); }
.rr-btn--block { width: 100%; }

/* -- icon-only: square, never a squashed text button -- */
.rr-btn--icon { width: 36px; padding: 0; }
.rr-btn--icon.rr-btn--sm { width: 30px; }
.rr-btn--icon.rr-btn--lg { width: 42px; }

/* -- loading: spinner replaces the icon slot, label stays put so the
      button never changes width mid-request -- */
.rr-btn--loading { pointer-events: none; }
.rr-btn--loading .rr-btn__label { opacity: 0.75; }
.rr-spinner {
  width: 14px; height: 14px; flex: none;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: rr-spin 620ms linear infinite;
}
.rr-spinner--lg { width: 20px; height: 20px; border-width: 2.5px; }
@keyframes rr-spin { to { transform: rotate(360deg); } }

/* =============================================================== 2 ===
   BUTTON GROUP — segmented row of actions with collapsed inner borders
   ==================================================================== */
.rr-btn-group { display: inline-flex; }
.rr-btn-group .rr-btn { border-radius: 0; margin-left: -1px; }
.rr-btn-group .rr-btn:first-child { border-radius: var(--rr-radius-md) 0 0 var(--rr-radius-md); margin-left: 0; }
.rr-btn-group .rr-btn:last-child  { border-radius: 0 var(--rr-radius-md) var(--rr-radius-md) 0; }
.rr-btn-group .rr-btn:hover, .rr-btn-group .rr-btn:focus-visible { z-index: 1; }

/* =============================================================== 3 ===
   FIELDS — label, control, help, error. One vertical rhythm everywhere.
   ==================================================================== */
.rr-field { display: flex; flex-direction: column; gap: var(--rr-space-1-5); min-width: 0; }

.rr-label {
  font-size: var(--rr-text-sm);
  font-weight: var(--rr-weight-semibold);
  color: var(--rr-text);
  line-height: var(--rr-leading-normal);
}
.rr-label__req { color: var(--rr-error-600); margin-left: 2px; }
.rr-label__opt {
  color: var(--rr-text-subtle); font-weight: var(--rr-weight-normal);
  font-size: var(--rr-text-xs); margin-left: var(--rr-space-1);
}

.rr-input, .rr-select, .rr-textarea {
  width: 100%;
  min-width: 0;
  height: 38px;
  padding: 0 var(--rr-space-3);
  background: var(--rr-surface);
  border: 1px solid var(--rr-border-strong);
  border-radius: var(--rr-radius-md);
  color: var(--rr-text);
  font-family: var(--rr-font-sans);
  font-size: var(--rr-text-base);
  line-height: var(--rr-leading-normal);
  transition: border-color var(--rr-dur-fast) var(--rr-ease),
              box-shadow var(--rr-dur-fast) var(--rr-ease),
              background-color var(--rr-dur-fast) var(--rr-ease);
}
.rr-textarea { height: auto; min-height: 84px; padding: var(--rr-space-2-5) var(--rr-space-3); }

.rr-input::placeholder, .rr-textarea::placeholder { color: var(--rr-text-subtle); }
.rr-input:hover:not(:disabled), .rr-select:hover:not(:disabled), .rr-textarea:hover:not(:disabled) {
  border-color: var(--rr-ink-400);
}
.rr-input:focus, .rr-select:focus, .rr-textarea:focus {
  outline: none;
  border-color: var(--rr-border-focus);
  box-shadow: var(--rr-ring);
}
.rr-input:disabled, .rr-select:disabled, .rr-textarea:disabled {
  background: var(--rr-surface-3); color: var(--rr-text-subtle); cursor: not-allowed;
}
.rr-input[readonly] { background: var(--rr-surface-2); }

.rr-input--sm { height: 32px; font-size: var(--rr-text-sm); }
.rr-input--lg { height: 44px; font-size: var(--rr-text-md); }

/* invalid state — border + ring + message, never colour alone */
.rr-input.is-invalid, .rr-select.is-invalid, .rr-textarea.is-invalid {
  border-color: var(--rr-error-600);
}
.rr-input.is-invalid:focus, .rr-select.is-invalid:focus, .rr-textarea.is-invalid:focus {
  box-shadow: var(--rr-ring-error);
}
.rr-input.is-valid { border-color: var(--rr-success-600); }

.rr-help { font-size: var(--rr-text-xs); color: var(--rr-text-muted); line-height: var(--rr-leading-normal); }
.rr-error-text {
  display: flex; align-items: flex-start; gap: var(--rr-space-1-5);
  font-size: var(--rr-text-xs); font-weight: var(--rr-weight-medium);
  color: var(--rr-error-600); line-height: var(--rr-leading-normal);
}
.rr-error-text .rr-i { width: 13px; height: 13px; margin-top: 1px; }

/* input with a leading/trailing adornment (search icon, ₹, unit, button) */
.rr-input-wrap { position: relative; display: flex; align-items: center; width: 100%; }
.rr-input-wrap .rr-input { padding-left: var(--rr-space-3); }
.rr-input-wrap--lead .rr-input { padding-left: 36px; }
.rr-input-wrap--trail .rr-input { padding-right: 36px; }
.rr-input-icon {
  position: absolute; display: grid; place-items: center;
  width: 36px; height: 100%; color: var(--rr-text-subtle); pointer-events: none;
}
.rr-input-icon--lead  { left: 0; }
.rr-input-icon--trail { right: 0; }
/* clickable trailing control (password eye, clear ×) */
.rr-input-btn {
  position: absolute; right: 2px; display: grid; place-items: center;
  width: 34px; height: 34px; border-radius: var(--rr-radius-sm);
  color: var(--rr-text-muted); cursor: pointer;
  transition: background-color var(--rr-dur-fast) var(--rr-ease), color var(--rr-dur-fast) var(--rr-ease);
}
.rr-input-btn:hover { background: var(--rr-surface-3); color: var(--rr-text); }

/* form grid — collapses to one column on small screens */
.rr-form-grid { display: grid; gap: var(--rr-space-4) var(--rr-space-4); grid-template-columns: repeat(2, minmax(0, 1fr)); }
.rr-form-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.rr-form-grid__full { grid-column: 1 / -1; }
.rr-form-actions {
  display: flex; align-items: center; justify-content: flex-end; gap: var(--rr-space-2);
  padding-top: var(--rr-space-5); margin-top: var(--rr-space-5);
  border-top: 1px solid var(--rr-border);
}
.rr-fieldset { border: 0; padding: 0; margin: 0; }
.rr-fieldset__legend {
  font-family: var(--rr-font-display);
  font-size: var(--rr-text-base); font-weight: var(--rr-weight-semibold);
  color: var(--rr-text); padding: 0 0 var(--rr-space-3);
}
@media (max-width: 720px) {
  .rr-form-grid, .rr-form-grid--3 { grid-template-columns: minmax(0, 1fr); }
  .rr-form-actions { flex-direction: column-reverse; align-items: stretch; }
}

/* =============================================================== 4 ===
   CHECKBOX / RADIO — custom control, native input kept for a11y
   ==================================================================== */
.rr-check {
  display: inline-flex; align-items: flex-start; gap: var(--rr-space-2-5);
  cursor: pointer; font-size: var(--rr-text-base); color: var(--rr-text-body);
  line-height: var(--rr-leading-normal);
}
.rr-check input { position: absolute; opacity: 0; width: 0; height: 0; }
.rr-check__box {
  flex: none; width: 18px; height: 18px; margin-top: 1px;
  background: var(--rr-surface);
  border: 1.5px solid var(--rr-border-strong);
  border-radius: var(--rr-radius-xs);
  display: grid; place-items: center;
  transition: background-color var(--rr-dur-fast) var(--rr-ease),
              border-color var(--rr-dur-fast) var(--rr-ease);
}
.rr-check__box svg { width: 12px; height: 12px; color: #fff; opacity: 0; transform: scale(0.6);
  transition: opacity var(--rr-dur-fast) var(--rr-ease), transform var(--rr-dur-fast) var(--rr-ease-spring); }
.rr-check:hover .rr-check__box { border-color: var(--rr-primary-400); }
.rr-check input:checked + .rr-check__box {
  background: var(--rr-primary-600); border-color: var(--rr-primary-600);
}
.rr-check input:checked + .rr-check__box svg { opacity: 1; transform: scale(1); }
.rr-check input:focus-visible + .rr-check__box { box-shadow: var(--rr-ring); }
.rr-check input:disabled + .rr-check__box { background: var(--rr-surface-3); border-color: var(--rr-border); }
.rr-check input:disabled ~ .rr-check__text { color: var(--rr-text-subtle); }
.rr-check--radio .rr-check__box { border-radius: 50%; }
.rr-check--radio input:checked + .rr-check__box {
  background: var(--rr-surface); border-color: var(--rr-primary-600); border-width: 5px;
}
.rr-check__text { min-width: 0; }
.rr-check__text small { display: block; font-size: var(--rr-text-xs); color: var(--rr-text-muted); }

/* =============================================================== 5 ===
   SWITCH — for instant-effect settings toggles
   ==================================================================== */
.rr-switch { display: inline-flex; align-items: center; gap: var(--rr-space-2-5); cursor: pointer; }
.rr-switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.rr-switch__track {
  position: relative; flex: none; width: 40px; height: 22px;
  background: var(--rr-ink-300); border-radius: var(--rr-radius-pill);
  transition: background-color var(--rr-dur-base) var(--rr-ease);
}
.rr-switch__track::after {
  content: ""; position: absolute; top: 2px; left: 2px;
  width: 18px; height: 18px; background: #fff; border-radius: 50%;
  box-shadow: var(--rr-shadow-sm);
  transition: transform var(--rr-dur-base) var(--rr-ease);
}
.rr-switch input:checked + .rr-switch__track { background: var(--rr-primary-600); }
.rr-switch input:checked + .rr-switch__track::after { transform: translateX(18px); }
.rr-switch input:focus-visible + .rr-switch__track { box-shadow: var(--rr-ring); }
.rr-switch input:disabled + .rr-switch__track { opacity: 0.5; }

/* =============================================================== 6 ===
   SELECT — native element, custom chevron (no JS, no a11y loss)
   ==================================================================== */
.rr-select {
  appearance: none; -webkit-appearance: none;
  padding-right: 34px;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2364748B' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--rr-space-3) center;
  cursor: pointer;
}
.rr-select--sm { height: 32px; font-size: var(--rr-text-sm); }

/* dropdown menu (custom popovers, row action menus) */
.rr-menu {
  position: absolute; z-index: var(--rr-z-dropdown);
  min-width: 190px; padding: var(--rr-space-1-5);
  background: var(--rr-surface);
  border: 1px solid var(--rr-border);
  border-radius: var(--rr-radius-lg);
  box-shadow: var(--rr-shadow-lg);
  animation: rr-pop var(--rr-dur-base) var(--rr-ease-out);
}
@keyframes rr-pop { from { opacity: 0; transform: translateY(-4px) scale(0.98); } }
.rr-menu__item {
  display: flex; align-items: center; gap: var(--rr-space-2-5);
  width: 100%; padding: var(--rr-space-2) var(--rr-space-2-5);
  border-radius: var(--rr-radius-sm);
  font-size: var(--rr-text-base); font-weight: var(--rr-weight-medium);
  color: var(--rr-text-body); text-align: left; cursor: pointer;
  transition: background-color var(--rr-dur-fast) var(--rr-ease);
}
.rr-menu__item:hover { background: var(--rr-surface-3); color: var(--rr-text); text-decoration: none; }
.rr-menu__item .rr-i { color: var(--rr-text-muted); }
.rr-menu__item--danger { color: var(--rr-error-600); }
.rr-menu__item--danger .rr-i { color: var(--rr-error-600); }
.rr-menu__item--danger:hover { background: var(--rr-error-50); color: var(--rr-error-700); }
.rr-menu__sep { height: 1px; background: var(--rr-border); margin: var(--rr-space-1-5) 0; }
.rr-menu__label {
  padding: var(--rr-space-2) var(--rr-space-2-5) var(--rr-space-1);
  font-size: var(--rr-text-2xs); font-weight: var(--rr-weight-semibold);
  letter-spacing: var(--rr-tracking-caps); text-transform: uppercase;
  color: var(--rr-text-subtle);
}

/* =============================================================== 7 ===
   FILTER / TOOLBAR — the search + filters + actions strip above tables
   ==================================================================== */
.rr-toolbar {
  display: flex; align-items: center; gap: var(--rr-space-2);
  flex-wrap: wrap; padding: var(--rr-space-3) var(--rr-space-4);
  border-bottom: 1px solid var(--rr-border);
  background: var(--rr-surface);
}
.rr-toolbar__search { flex: 1 1 240px; max-width: 340px; min-width: 180px; }
.rr-toolbar__group { display: flex; align-items: center; gap: var(--rr-space-2); flex-wrap: wrap; }
.rr-toolbar__divider { width: 1px; align-self: stretch; background: var(--rr-border); margin: 0 var(--rr-space-1); }
@media (max-width: 640px) {
  .rr-toolbar { gap: var(--rr-space-2); }
  .rr-toolbar__search { flex-basis: 100%; max-width: none; }
  .rr-toolbar__group { flex: 1 1 auto; }
}

/* =============================================================== 8 ===
   BADGES / STATUS — a dot carries the meaning, colour reinforces it
   ==================================================================== */
.rr-badge {
  display: inline-flex; align-items: center; gap: var(--rr-space-1-5);
  height: 22px; padding: 0 var(--rr-space-2);
  border: 1px solid; border-radius: var(--rr-radius-pill);
  font-size: var(--rr-text-2xs); font-weight: var(--rr-weight-semibold);
  letter-spacing: 0.01em; white-space: nowrap; line-height: 1;
}
.rr-badge--dot::before {
  content: ""; width: 5px; height: 5px; border-radius: 50%;
  background: currentColor; flex: none;
}
.rr-badge--neutral { color: var(--rr-ink-700);      background: var(--rr-ink-100);      border-color: var(--rr-ink-200); }
.rr-badge--brand   { color: var(--rr-primary-800);  background: var(--rr-primary-50);   border-color: var(--rr-primary-200); }
.rr-badge--success { color: var(--rr-success-700);  background: var(--rr-success-50);   border-color: var(--rr-success-200); }
.rr-badge--warning { color: var(--rr-warning-700);  background: var(--rr-warning-50);   border-color: var(--rr-warning-200); }
.rr-badge--error   { color: var(--rr-error-700);    background: var(--rr-error-50);     border-color: var(--rr-error-200); }
.rr-badge--info    { color: var(--rr-info-700);     background: var(--rr-info-50);      border-color: var(--rr-info-200); }
.rr-badge--accent  { color: var(--rr-accent-700);   background: var(--rr-accent-50);    border-color: var(--rr-accent-200); }
.rr-badge--solid   { color: #fff; background: var(--rr-primary-600); border-color: var(--rr-primary-600); }
.rr-badge--lg { height: 26px; padding: 0 var(--rr-space-2-5); font-size: var(--rr-text-xs); }

/* Offline-mode banner (waiter.php / kitchen.php) — same warning tone as
   every other "needs attention" surface, driven by tokens.css instead of
   a hardcoded hex baked into offline-banner.js. */
.rr-offline-banner {
  position: fixed; left: 0; right: 0; top: 0; z-index: var(--rr-z-toast, 9999);
  background: var(--rr-warning-600); color: #fff;
  font: var(--rr-weight-semibold) var(--rr-text-sm) / 1.4 var(--rr-font-sans);
  text-align: center; padding: var(--rr-space-1-5) var(--rr-space-3);
  display: none;
}

/* live/pulsing indicator for KDS + active order counts */
.rr-badge--live::before { animation: rr-pulse 1.6s var(--rr-ease) infinite; }
@keyframes rr-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.35; } }

/* count pill for nav items and tab labels */
.rr-count {
  display: inline-grid; place-items: center;
  min-width: 20px; height: 20px; padding: 0 6px;
  background: var(--rr-surface-3); color: var(--rr-text-muted);
  border-radius: var(--rr-radius-pill);
  font-size: var(--rr-text-2xs); font-weight: var(--rr-weight-bold);
  font-variant-numeric: tabular-nums;
}
.rr-count--brand { background: var(--rr-primary-600); color: #fff; }

/* =============================================================== 9 ===
   CHIPS — removable filters and quick-range selectors
   ==================================================================== */
.rr-chip {
  display: inline-flex; align-items: center; gap: var(--rr-space-1-5);
  height: 30px; padding: 0 var(--rr-space-3);
  background: var(--rr-surface); color: var(--rr-text-body);
  border: 1px solid var(--rr-border-strong); border-radius: var(--rr-radius-pill);
  font-size: var(--rr-text-sm); font-weight: var(--rr-weight-medium);
  cursor: pointer; white-space: nowrap;
  transition: background-color var(--rr-dur-fast) var(--rr-ease),
              border-color var(--rr-dur-fast) var(--rr-ease), color var(--rr-dur-fast) var(--rr-ease);
}
.rr-chip:hover { background: var(--rr-surface-2); border-color: var(--rr-ink-400); text-decoration: none; }
.rr-chip.is-active, .rr-chip[aria-pressed="true"] {
  background: var(--rr-primary-50); color: var(--rr-primary-800);
  border-color: var(--rr-primary-300); font-weight: var(--rr-weight-semibold);
}
.rr-chip__x {
  display: grid; place-items: center; width: 16px; height: 16px; margin-right: -4px;
  border-radius: 50%; color: var(--rr-text-muted);
}
.rr-chip__x:hover { background: var(--rr-ink-200); color: var(--rr-text); }

/* ============================================================== 10 ===
   ALERTS / BANNERS — icon + title + body, one layout for all severities
   ==================================================================== */
.rr-alert {
  display: flex; gap: var(--rr-space-3);
  padding: var(--rr-space-3) var(--rr-space-4);
  border: 1px solid; border-radius: var(--rr-radius-lg);
  font-size: var(--rr-text-sm); line-height: var(--rr-leading-relaxed);
}
.rr-alert__icon { flex: none; margin-top: 1px; }
.rr-alert__body { min-width: 0; flex: 1; }
.rr-alert__title {
  font-size: var(--rr-text-base); font-weight: var(--rr-weight-semibold);
  margin-bottom: var(--rr-space-0-5); color: var(--rr-text);
}
.rr-alert__text { color: var(--rr-text-body); }
.rr-alert--info    { background: var(--rr-info-50);    border-color: var(--rr-info-200); }
.rr-alert--info    .rr-alert__icon { color: var(--rr-info-600); }
.rr-alert--success { background: var(--rr-success-50); border-color: var(--rr-success-200); }
.rr-alert--success .rr-alert__icon { color: var(--rr-success-600); }
.rr-alert--warning { background: var(--rr-warning-50); border-color: var(--rr-warning-200); }
.rr-alert--warning .rr-alert__icon { color: var(--rr-warning-600); }
.rr-alert--error   { background: var(--rr-error-50);   border-color: var(--rr-error-200); }
.rr-alert--error   .rr-alert__icon { color: var(--rr-error-600); }

/* ============================================================== 11 ===
   CARDS — surface, header, body, footer. Stat card is a card variant.
   ==================================================================== */
.rr-card {
  background: var(--rr-surface);
  border: 1px solid var(--rr-border);
  border-radius: var(--rr-radius-lg);
  box-shadow: var(--rr-shadow-sm);
  overflow: hidden;
}
.rr-card--flat { box-shadow: none; }
.rr-card--raised { box-shadow: var(--rr-shadow-md); }
.rr-card__head {
  display: flex; align-items: center; gap: var(--rr-space-3); flex-wrap: wrap;
  padding: var(--rr-space-3-5, 14px) var(--rr-space-4);
  border-bottom: 1px solid var(--rr-border);
}
.rr-card__title {
  display: block;
  font-family: var(--rr-font-display);
  font-size: var(--rr-text-base); font-weight: var(--rr-weight-semibold);
  color: var(--rr-text); letter-spacing: var(--rr-tracking-tight);
}
/* The subtitle always takes its own line. width:100% covers both markup shapes:
   as a flex child of __head it wraps to the next row, and inside a plain wrapper
   div it simply stacks. Without this, a title and subtitle written as siblings
   run together ("CustomersThe 100 most recent records"). */
.rr-card__sub {
  display: block; width: 100%;
  font-size: var(--rr-text-xs); color: var(--rr-text-muted); margin-top: 1px;
}
.rr-card__body { padding: var(--rr-space-4); }
.rr-card__body--tight { padding: var(--rr-space-3); }
.rr-card__body--flush { padding: 0; }
.rr-card__foot {
  display: flex; align-items: center; gap: var(--rr-space-2);
  padding: var(--rr-space-3) var(--rr-space-4);
  border-top: 1px solid var(--rr-border);
  background: var(--rr-surface-2);
}

/* -- stat card -- */
.rr-stat {
  position: relative;
  background: var(--rr-surface);
  border: 1px solid var(--rr-border);
  border-radius: var(--rr-radius-lg);
  box-shadow: var(--rr-shadow-sm);
  padding: var(--rr-space-4);
  display: flex; flex-direction: column; gap: var(--rr-space-2);
  min-width: 0;
  transition: box-shadow var(--rr-dur-base) var(--rr-ease),
              border-color var(--rr-dur-base) var(--rr-ease);
}
.rr-stat:hover { box-shadow: var(--rr-shadow-md); border-color: var(--rr-border-strong); }
.rr-stat__top { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--rr-space-2); }
.rr-stat__label {
  font-size: var(--rr-text-2xs); font-weight: var(--rr-weight-semibold);
  letter-spacing: var(--rr-tracking-caps); text-transform: uppercase;
  color: var(--rr-text-muted); line-height: var(--rr-leading-normal);
}
.rr-stat__icon {
  display: grid; place-items: center; flex: none;
  width: 32px; height: 32px; border-radius: var(--rr-radius-md);
  background: var(--rr-primary-50); color: var(--rr-primary-600);
  border: 1px solid var(--rr-primary-100);
}
.rr-stat__icon--accent  { background: var(--rr-accent-50);  color: var(--rr-accent-600);  border-color: var(--rr-accent-200); }
.rr-stat__icon--success { background: var(--rr-success-50); color: var(--rr-success-600); border-color: var(--rr-success-200); }
.rr-stat__icon--warning { background: var(--rr-warning-50); color: var(--rr-warning-600); border-color: var(--rr-warning-200); }
.rr-stat__icon--info    { background: var(--rr-info-50);    color: var(--rr-info-600);    border-color: var(--rr-info-200); }
.rr-stat__value {
  font-family: var(--rr-font-display);
  font-size: var(--rr-text-2xl); font-weight: var(--rr-weight-bold);
  line-height: var(--rr-leading-tight); letter-spacing: var(--rr-tracking-tight);
  color: var(--rr-text); font-variant-numeric: tabular-nums;
}
.rr-stat__foot { display: flex; align-items: center; gap: var(--rr-space-2); flex-wrap: wrap; }
.rr-trend {
  display: inline-flex; align-items: center; gap: var(--rr-space-1);
  font-size: var(--rr-text-xs); font-weight: var(--rr-weight-semibold);
}
.rr-trend--up   { color: var(--rr-success-600); }
.rr-trend--down { color: var(--rr-error-600); }
.rr-trend--flat { color: var(--rr-text-muted); }
.rr-stat__hint { font-size: var(--rr-text-xs); color: var(--rr-text-muted); }

/* ============================================================== 12 ===
   TABLES — sticky header, aligned numerics, responsive card fallback
   ==================================================================== */
.rr-table-wrap {
  width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch;
}
.rr-table { width: 100%; border-collapse: separate; border-spacing: 0; }
/* Premium-SaaS header row: a hair taller than before (space-3 vs space-2-5)
   so the row breathes, wider letter-spacing already existed for the caps
   label — this just gives it a touch more weight and a crisper baseline
   rule so the header reads as its own band, not just the first data row
   with different colour. Still --rr-surface-2, the same quiet tint every
   other "raised strip" (card foot, table foot, toolbar) already uses, so a
   table dropped into any screen matches its neighbours automatically. */
.rr-table thead th {
  position: sticky; top: 0; z-index: var(--rr-z-base);
  padding: var(--rr-space-3) var(--rr-space-4);
  background: var(--rr-surface-2);
  border-bottom: 1px solid var(--rr-border-strong);
  font-size: var(--rr-text-2xs); font-weight: var(--rr-weight-bold);
  letter-spacing: var(--rr-tracking-caps); text-transform: uppercase;
  color: var(--rr-text-muted); text-align: left; white-space: nowrap;
}
/* Row height + typography: space-3-5 vertical padding (was space-3) reads as
   "clean SaaS table" rather than "cramped spreadsheet" without pushing a
   50-row Live Orders board off screen. Cell text stays --rr-text-sm — the
   readability ask here was about spacing and hierarchy, not bigger type. */
.rr-table tbody td {
  padding: var(--rr-space-3-5, 14px) var(--rr-space-4);
  border-bottom: 1px solid var(--rr-border);
  font-size: var(--rr-text-sm); color: var(--rr-text-body);
  vertical-align: middle;
}
.rr-table tbody tr:last-child td { border-bottom: 0; }
.rr-table tbody tr {
  transition: background-color var(--rr-dur-fast) var(--rr-ease);
}
/* Faint zebra banding on the even rows — barely-there (--rr-surface-2 is a
   1-step-off-white tint, the same one the header already sits on) so a wide
   table with many numeric columns stays scannable row-to-row without the
   harder striping some admin tools use. Hover still wins over the zebra
   tint so the row you're pointing at is always the most visible one. */
.rr-table tbody tr:nth-child(even) { background: var(--rr-surface-2); }
.rr-table tbody tr:hover { background: var(--rr-surface-3); }
.rr-table tfoot td {
  padding: var(--rr-space-3) var(--rr-space-4);
  background: var(--rr-surface-2);
  border-top: 1px solid var(--rr-border-strong);
  font-size: var(--rr-text-sm); font-weight: var(--rr-weight-bold);
  color: var(--rr-text);
}
/* alignment + emphasis helpers */
.rr-table .rr-td-num    { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.rr-table .rr-td-amount { text-align: right; font-variant-numeric: tabular-nums;
                          font-weight: var(--rr-weight-semibold); color: var(--rr-text); white-space: nowrap; }
.rr-table .rr-td-center { text-align: center; }
.rr-table .rr-td-actions{ text-align: right; white-space: nowrap; width: 1%; }
/* Action buttons used to sit flush against each other on desktop — only the
   responsive (stacked) variant below had a gap. Spacing the siblings rather
   than making the cell a flex container keeps the table cell's own vertical
   alignment and `width:1%` shrink-to-fit behaviour intact. */
.rr-table tbody .rr-td-actions > * + * { margin-left: var(--rr-space-2); }
.rr-table .rr-td-strong { font-weight: var(--rr-weight-semibold); color: var(--rr-text); }
.rr-table .rr-td-id     { font-weight: var(--rr-weight-semibold); color: var(--rr-text-brand);
                          font-variant-numeric: tabular-nums; white-space: nowrap; }
.rr-table__primary { display: block; font-weight: var(--rr-weight-semibold); color: var(--rr-text); }
.rr-table__meta    { display: block; font-size: var(--rr-text-xs); color: var(--rr-text-muted); margin-top: 1px; }
.rr-table--compact tbody td { padding: var(--rr-space-2) var(--rr-space-3); }
.rr-table--compact thead th { padding: var(--rr-space-2) var(--rr-space-3); }

/* sortable header */
.rr-th-sort {
  display: inline-flex; align-items: center; gap: var(--rr-space-1-5);
  color: inherit; font: inherit; letter-spacing: inherit; text-transform: inherit;
  cursor: pointer;
}
.rr-th-sort:hover { color: var(--rr-text); }
.rr-th-sort__i { opacity: 0.4; transition: opacity var(--rr-dur-fast) var(--rr-ease); }
.rr-th-sort[aria-sort]:not([aria-sort="none"]) { color: var(--rr-text-brand); }
.rr-th-sort[aria-sort]:not([aria-sort="none"]) .rr-th-sort__i { opacity: 1; }

/* row selection */
.rr-table tbody tr.is-selected { background: var(--rr-primary-50); }
.rr-table .rr-td-check { width: 1%; padding-right: 0; }

/* responsive: below 768px each row becomes a labelled card.
   Markup requirement: every <td> carries data-label="Column name". */
@media (max-width: 768px) {
  /* The table element itself must leave table layout, otherwise the row
     margins below are added to a 100%-wide table and force a few px of
     horizontal scroll. */
  .rr-table--responsive { display: block; width: auto; }
  .rr-table--responsive thead { display: none; }
  .rr-table--responsive tbody, .rr-table--responsive tfoot { display: block; }
  .rr-table--responsive tbody tr {
    display: block; margin: 0 var(--rr-space-3) var(--rr-space-3);
    background: var(--rr-surface);
    border: 1px solid var(--rr-border);
    border-radius: var(--rr-radius-lg);
    box-shadow: var(--rr-shadow-xs);
    padding: var(--rr-space-1);
  }
  .rr-table--responsive tbody tr:hover { background: var(--rr-surface); }
  .rr-table--responsive tbody td {
    display: flex; align-items: center; justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--rr-space-1) var(--rr-space-4); padding: var(--rr-space-2) var(--rr-space-3);
    border-bottom: 1px dashed var(--rr-border); text-align: right;
  }
  .rr-table--responsive tbody td:last-child { border-bottom: 0; }
  /* A cell holding a primary value AND secondary lines (a bill's split
     breakdown, a dish's Gujarati name, a customer's mobile) turns those spans
     into flex items. Without this they sat in a ROW beside the label and the
     longest one ran past the card edge, where the page's own overflow:hidden
     clipped it — the text was simply gone on a phone. The primary shares line
     one with the label; every meta line gets a full row of its own. */
  .rr-table--responsive tbody td > * { min-width: 0; overflow-wrap: anywhere; }
  .rr-table--responsive tbody td > .rr-table__primary {
    flex: 1 1 auto; text-align: right;
  }
  .rr-table--responsive tbody td > .rr-table__meta {
    flex: 1 1 100%; text-align: right;
  }
  .rr-table--responsive tbody td::before {
    content: attr(data-label);
    flex: none; text-align: left;
    font-size: var(--rr-text-2xs); font-weight: var(--rr-weight-semibold);
    letter-spacing: var(--rr-tracking-caps); text-transform: uppercase;
    color: var(--rr-text-muted);
  }
  /* A cell with no label (row checkbox) shouldn't reserve an empty column. */
  .rr-table--responsive tbody td[data-label=""]::before,
  .rr-table--responsive tbody td:not([data-label])::before { content: none; }
  .rr-table--responsive tbody td[data-label=""] { justify-content: flex-start; }
  /* Reset the desktop shrink-to-fit rules, or the flex cell collapses to
     1% and clips both its label and its buttons. */
  .rr-table--responsive tbody .rr-td-actions,
  .rr-table--responsive tbody .rr-td-check { width: auto; white-space: normal; }
  /* Label pinned left, the action buttons stay grouped on the right. */
  .rr-table--responsive tbody .rr-td-actions { justify-content: flex-end; gap: var(--rr-space-1); }
  .rr-table--responsive tbody .rr-td-actions::before { margin-right: auto; }
  .rr-table--responsive tbody .rr-td-check { padding-right: var(--rr-space-3); }
  /* Totals become a summary band rather than a colspan row that would
     otherwise hold the table at its desktop minimum width. */
  .rr-table--responsive tfoot tr {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--rr-space-4);
    margin: 0 var(--rr-space-3) var(--rr-space-3);
    background: var(--rr-surface-2);
    border: 1px solid var(--rr-border-strong);
    border-radius: var(--rr-radius-lg);
  }
  .rr-table--responsive tfoot td { border: 0; padding: var(--rr-space-3); }
  .rr-table--responsive tfoot td:empty { display: none; }
}

/* ====================================================== 20b ===
   BAR CHART — a server-rendered bar series. No chart library: these are just
   divs, so they print, need no JS, and take their colours from the tokens.
   ==================================================================== */
.rr-bars {
  display: flex; align-items: flex-end; gap: var(--rr-space-2);
  height: 210px; padding-top: var(--rr-space-5);
  overflow-x: auto;
}
.rr-bars__col {
  flex: 1 1 0; min-width: 42px;
  display: flex; flex-direction: column; align-items: center; justify-content: flex-end;
  height: 100%; gap: var(--rr-space-1-5);
}
.rr-bars__bar {
  width: 100%; max-width: 44px; min-height: 4px;
  background: var(--rr-primary-600);
  border-radius: var(--rr-radius-sm) var(--rr-radius-sm) 2px 2px;
  transition: height var(--rr-dur-slow) var(--rr-ease);
}
.rr-bars__bar--accent { background: var(--rr-accent-600); }
.rr-bars__value {
  font-size: var(--rr-text-2xs); font-weight: var(--rr-weight-semibold);
  color: var(--rr-text-muted); font-variant-numeric: tabular-nums; white-space: nowrap;
}
.rr-bars__label {
  font-size: var(--rr-text-2xs); color: var(--rr-text-subtle);
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* -- a module row in Settings: icon, label, switch ----------------------- */
.rr-module {
  display: flex; align-items: center; gap: var(--rr-space-3);
  padding: var(--rr-space-3);
  background: var(--rr-surface); border: 1px solid var(--rr-border);
  border-radius: var(--rr-radius-md); cursor: pointer;
  transition: border-color var(--rr-dur-fast) var(--rr-ease), background-color var(--rr-dur-fast) var(--rr-ease);
}
.rr-module:hover { border-color: var(--rr-border-strong); background: var(--rr-surface-2); }
.rr-module__icon {
  display: grid; place-items: center; flex: none;
  width: 34px; height: 34px; border-radius: var(--rr-radius-md);
  background: var(--rr-surface-3); color: var(--rr-text-muted);
}
.rr-module__text { min-width: 0; flex: 1; }
.rr-module__text strong {
  display: block; font-size: var(--rr-text-sm); font-weight: var(--rr-weight-semibold);
  color: var(--rr-text);
}
.rr-module__text small { display: block; font-size: var(--rr-text-2xs); color: var(--rr-text-muted); margin-top: 1px; }

/* ====================================================== 11b ===
   POS / COUNTER ORDER — a two-pane order screen: dishes on the left, the
   running cart on the right. The cart is sticky and the totals + actions are
   pinned to its bottom, so a busy counter never has to scroll to send an order.
   ==================================================================== */
.rr-pos {
  display: grid; gap: var(--rr-space-4);
  grid-template-columns: minmax(0, 1fr) minmax(340px, 400px);
  align-items: start;
}
.rr-pos__menu { min-width: 0; }
.rr-pos__grid {
  display: grid; gap: var(--rr-space-2-5);
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  /* Rows are as tall as the dish that needs the most room. Without this an
     `auto` row takes the tile's own min-height as its size, so a tile carrying
     Gujarati and Hindi names stayed 76px tall and its price printed on top of
     the tile below. The min-height still gives short tiles a common floor. */
  grid-auto-rows: max-content;
}
/* one dish */
.rr-dish {
  display: flex; flex-direction: row; align-items: center; gap: var(--rr-space-2-5);
  min-height: 76px; padding: var(--rr-space-2-5) var(--rr-space-3);
  background: var(--rr-surface);
  border: 1px solid var(--rr-border-strong);
  border-radius: var(--rr-radius-md);
  text-align: left; cursor: pointer;
  transition: border-color var(--rr-dur-fast) var(--rr-ease),
              background-color var(--rr-dur-fast) var(--rr-ease),
              box-shadow var(--rr-dur-fast) var(--rr-ease);
}
.rr-dish:hover { border-color: var(--rr-primary-300); background: var(--rr-primary-50); }
.rr-dish:focus-visible { outline: none; box-shadow: var(--rr-ring); }
.rr-dish.is-selected { border-color: var(--rr-primary-600); background: var(--rr-primary-50); }
.rr-dish__body {
  display: flex; flex-direction: column; justify-content: space-between; gap: var(--rr-space-1-5);
  flex: 1; min-width: 0;
}
/* A round "thumbnail" — see rrDishArt()'s comment in admin.php for what this
   actually is (an original small illustration keyed off the dish name, not a
   photo). Sized and shaped like a photo thumbnail would be, so the grid reads
   the way a photo-menu grid does, without pretending the picture is a photo. */
.rr-dish__art {
  display: flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; flex: none;
  border-radius: 50%; overflow: hidden;
  background: var(--rr-surface-2);
  border: 1px solid var(--rr-border);
}
.rr-dish__art--round svg { display: block; }
.rr-dish__art .rr-dish__art-fallback { display: flex; color: var(--rr-text-inverse); }
.rr-dish__art .rr-i { width: 18px; height: 18px; }
.rr-dish__art--primary { background: var(--rr-primary-600); }
.rr-dish__art--accent  { background: var(--rr-accent-600); }
.rr-dish__art--success { background: var(--rr-success-600); }
.rr-dish__art--warning { background: var(--rr-warning-600); }
.rr-dish__art--info    { background: var(--rr-info-600); }
.rr-dish__name {
  font-size: var(--rr-text-sm); font-weight: var(--rr-weight-semibold);
  color: var(--rr-text); line-height: var(--rr-leading-snug);
}
/* The Gujarati / Hindi name under the English one. Quieter than the English name
   but still readable body text — this is the name the kitchen reads out, not a
   caption. Indic scripts need more leading than Latin or the matras clip.
   flex:0 0 auto because the card is a column flex box with a min-height, and an
   unflagged child is the one that gets squashed. */
.rr-dish__name-local {
  display: block; flex: 0 0 auto;
  font-size: var(--rr-text-xs); font-weight: var(--rr-weight-medium);
  color: var(--rr-text-muted); line-height: 1.5;
}
/* Favourite star + item code: a thin badge row above the dish name, so a
   waiter scanning the grid sees at a glance which dishes are pinned and what
   code to type for the ones they already know by number. */
.rr-dish__fav { color: var(--rr-warning-600); font-size: var(--rr-text-sm); line-height: 1; margin-right: var(--rr-space-1); }
.rr-dish__code {
  display: inline-block;
  font-size: var(--rr-text-2xs); font-weight: var(--rr-weight-bold);
  color: var(--rr-text-subtle); font-variant-numeric: tabular-nums;
  letter-spacing: var(--rr-tracking-wide);
}
.rr-dish__meta { display: flex; align-items: center; justify-content: space-between; gap: var(--rr-space-2); }
.rr-dish__price {
  font-size: var(--rr-text-sm); font-weight: var(--rr-weight-bold);
  color: var(--rr-text-brand); font-variant-numeric: tabular-nums;
}
.rr-dish__qty {
  display: inline-grid; place-items: center;
  min-width: 20px; height: 20px; padding: 0 5px;
  background: var(--rr-primary-600); color: #fff;
  border-radius: var(--rr-radius-pill);
  font-size: var(--rr-text-2xs); font-weight: var(--rr-weight-bold);
}
.rr-dish--out { opacity: 0.5; cursor: not-allowed; }

/* the cart column */
.rr-pos__cart {
  position: sticky; top: calc(var(--rr-header-h) + var(--rr-space-4));
  display: flex; flex-direction: column;
  max-height: calc(100vh - var(--rr-header-h) - var(--rr-space-8));
}
.rr-pos__cart-list { flex: 1; min-height: 120px; overflow-y: auto; padding: var(--rr-space-2); }
.rr-pos__customer {
  padding: var(--rr-space-2-5) var(--rr-space-3);
  background: var(--rr-accent-50);
  border-bottom: 1px solid var(--rr-border);
  font-size: var(--rr-text-sm); color: var(--rr-text-body);
}
.rr-pos__foot {
  flex: none; padding: var(--rr-space-3) var(--rr-space-4) var(--rr-space-4);
  border-top: 1px solid var(--rr-border);
  background: var(--rr-surface-2);
  display: flex; flex-direction: column; gap: var(--rr-space-3);
}
/* The bill breakdown that sits above the total: quiet by design, because the
   payable figure below it is what the counter reads out. Amounts are tabular
   so the decimal points line up down the column. */
.rr-pos__breakdown {
  display: flex; flex-direction: column; gap: var(--rr-space-1);
  padding: var(--rr-space-3) var(--rr-space-3) var(--rr-space-2);
  margin: 0;
  background: var(--rr-surface); border: 1px solid var(--rr-border);
  border-radius: var(--rr-radius-md);
  font-size: var(--rr-text-sm); color: var(--rr-text-muted);
}
.rr-pos__breakdown-row {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--rr-space-3);
}
.rr-pos__breakdown dt { margin: 0; }
.rr-pos__breakdown dd {
  margin: 0; font-variant-numeric: tabular-nums;
  font-weight: var(--rr-weight-semi); color: var(--rr-text);
}

.rr-pos__total {
  display: flex; align-items: baseline; justify-content: space-between;
  padding: var(--rr-space-3);
  background: var(--rr-surface); border: 1px solid var(--rr-border-strong);
  border-radius: var(--rr-radius-md);
}
/* THE ONE ON-SCREEN GRAND-TOTAL SIZE. 18px/bold, not 24px/extra.
   The owner's note was that the final amount shouts. Every on-screen
   "grand total / amount payable" now reads at --rr-text-lg with
   --rr-weight-bold — this rule, .totals-row.grand strong in pos.css,
   .admin-detail-total strong in admin.css and .rr-settle__row--due strong
   in react-app/src/orders.css. It is still the largest thing in its own
   block and still the display face with tabular numerals; it just no
   longer competes with the page title. The printed 80mm receipt
   (react-app/src/billprint.css) is deliberately NOT part of this — paper
   has its own scale. */
.rr-pos__total strong {
  font-family: var(--rr-font-display);
  font-size: var(--rr-text-lg); font-weight: var(--rr-weight-bold);
  letter-spacing: var(--rr-tracking-tight); color: var(--rr-text);
  font-variant-numeric: tabular-nums;
}
.rr-pos__actions { display: grid; grid-template-columns: 1fr 1fr; gap: var(--rr-space-2); }

/* one cart line */
.rr-cart-row {
  display: grid; grid-template-columns: 1fr auto; gap: var(--rr-space-2);
  align-items: center;
  padding: var(--rr-space-2) var(--rr-space-2-5);
  border-radius: var(--rr-radius-md);
}
.rr-cart-row + .rr-cart-row { border-top: 1px solid var(--rr-border); border-radius: 0; }
/* An item on a loaded order that's since gone out of stock / off the menu.
   Still counts toward the total (that's the fix) — this just flags it so
   staff know why it can't be increased, only removed. */
.rr-cart-row--stale { background: var(--rr-warning-50); }
.rr-cart-row--stale .rr-cart-row__meta { color: var(--rr-warning-700); }
.rr-cart-row__name {
  font-size: var(--rr-text-sm); font-weight: var(--rr-weight-semibold); color: var(--rr-text);
}
.rr-cart-row__meta { font-size: var(--rr-text-2xs); color: var(--rr-text-muted); }
.rr-cart-row__right { display: flex; align-items: center; gap: var(--rr-space-2); }
.rr-cart-row__amount {
  min-width: 66px; text-align: right;
  font-size: var(--rr-text-sm); font-weight: var(--rr-weight-bold);
  color: var(--rr-text); font-variant-numeric: tabular-nums;
}
/* quantity stepper */
.rr-step { display: inline-flex; align-items: center; border: 1px solid var(--rr-border-strong);
  border-radius: var(--rr-radius-md); overflow: hidden; background: var(--rr-surface); }
.rr-step button {
  width: 26px; height: 26px; display: grid; place-items: center;
  color: var(--rr-text-muted); cursor: pointer;
}
.rr-step button:hover { background: var(--rr-surface-3); color: var(--rr-text); }
.rr-step span {
  min-width: 28px; text-align: center;
  font-size: var(--rr-text-sm); font-weight: var(--rr-weight-bold);
  color: var(--rr-text); font-variant-numeric: tabular-nums;
}

@media (max-width: 1100px) {
  .rr-pos { grid-template-columns: minmax(0, 1fr); }
  .rr-pos__cart { position: static; max-height: none; }
  .rr-pos__actions { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 520px) {
  .rr-pos__actions { grid-template-columns: 1fr; }
}

/* ====================================================== 12b ===
   FLOOR PLAN — the table board. A restaurant reads this screen at a glance
   from two metres away, so state is carried by fill AND by a label, and the
   table number is the largest thing on the tile.
   ==================================================================== */
.rr-floor + .rr-floor { margin-top: var(--rr-space-6); }
.rr-floor__head {
  display: flex; align-items: center; gap: var(--rr-space-2-5);
  margin-bottom: var(--rr-space-3);
}
.rr-floor__title {
  font-family: var(--rr-font-display);
  font-size: var(--rr-text-base); font-weight: var(--rr-weight-bold);
  letter-spacing: var(--rr-tracking-caps); text-transform: uppercase;
  color: var(--rr-text-muted);
}
.rr-tile-grid {
  display: grid; gap: var(--rr-space-3);
  grid-template-columns: repeat(auto-fill, minmax(132px, 1fr));
}
.rr-tile { position: relative; }
.rr-tile__face {
  width: 100%; min-height: 108px;
  display: flex; flex-direction: column; align-items: flex-start; justify-content: space-between;
  gap: var(--rr-space-1);
  padding: var(--rr-space-3-5, var(--rr-space-3));
  background: var(--rr-surface);
  border: 1px solid var(--rr-border);
  /* radius-xl, not -lg — the owner's "make the table design more modern,
     premium" request. One step rounder than a plain card is what reads as
     "app", not "spreadsheet", at zero layout cost since every child inside
     already sits clear of the corner. */
  border-radius: var(--rr-radius-xl);
  box-shadow: var(--rr-shadow-sm);
  cursor: pointer; text-align: left;
  transition: border-color var(--rr-dur-fast) var(--rr-ease),
              box-shadow var(--rr-dur-fast) var(--rr-ease),
              transform var(--rr-dur-fast) var(--rr-ease);
}
.rr-tile__face:hover { box-shadow: var(--rr-shadow-lg); transform: translateY(-2px); border-color: var(--rr-primary-200); }
.rr-tile__face:focus-visible { outline: none; box-shadow: var(--rr-ring); }
.rr-tile__no {
  font-family: var(--rr-font-display);
  font-size: var(--rr-text-2xl); font-weight: var(--rr-weight-extra);
  line-height: 1; letter-spacing: var(--rr-tracking-tight);
  color: var(--rr-text);
}
/* A quiet pill instead of bare floating text — the seat count reads as a
   small piece of metadata now rather than a stray label competing with the
   table number for attention. */
.rr-tile__seats {
  position: absolute; top: var(--rr-space-2-5, var(--rr-space-2)); right: var(--rr-space-2-5, var(--rr-space-2));
  display: inline-flex; align-items: center; gap: 3px;
  padding: 2px var(--rr-space-1-5, 6px);
  border-radius: var(--rr-radius-pill);
  background: var(--rr-surface-2);
  font-size: var(--rr-text-2xs); font-weight: var(--rr-weight-semibold);
  color: var(--rr-text-subtle);
}
.rr-tile__amount {
  font-size: var(--rr-text-lg); font-weight: var(--rr-weight-extra);
  color: var(--rr-text); font-variant-numeric: tabular-nums;
  letter-spacing: -0.2px;
}
.rr-tile__state {
  /* align-self:stretch — without it this flex child (inside .rr-tile__face's
     column flex with align-items:flex-start) sizes to its own text's natural
     width and tries to stay on one line. "Needs clearing" at this label's
     font/letter-spacing is wider than the tile, so it silently ran past the
     tile edge (PHP, no visible ellipsis — just invisibly clipped by the
     tile's own overflow) or showed a literal ellipsis (React). Stretching to
     the tile's real width lets it wrap onto a second line instead — every
     status label now fits, in both the PHP tiles and the React ones, since
     this rule is the one place both read their colour AND now their sizing
     from. */
  align-self: stretch;
  font-size: var(--rr-text-2xs); font-weight: var(--rr-weight-semibold);
  letter-spacing: var(--rr-tracking-wide); text-transform: uppercase;
  color: var(--rr-text-muted);
  white-space: normal; line-height: 1.3;
}
/* states */
.rr-tile--free .rr-tile__face { background: var(--rr-surface-2); }
.rr-tile--running .rr-tile__face {
  background: var(--rr-warning-50); border-color: var(--rr-warning-200);
}
.rr-tile--running .rr-tile__state { color: var(--rr-warning-700); }
.rr-tile--ready .rr-tile__face {
  background: var(--rr-info-50); border-color: var(--rr-info-200);
}
.rr-tile--ready .rr-tile__state { color: var(--rr-info-700); }

/* row actions appear on hover on desktop, always on touch */
.rr-tile__actions {
  position: absolute; bottom: var(--rr-space-1-5); right: var(--rr-space-1-5);
  display: flex; gap: 2px;
  opacity: 0; transition: opacity var(--rr-dur-fast) var(--rr-ease);
}
.rr-tile:hover .rr-tile__actions,
.rr-tile:focus-within .rr-tile__actions { opacity: 1; }
@media (hover: none) { .rr-tile__actions { opacity: 1; } }

/* legend */
.rr-legend {
  display: inline-flex; align-items: center; gap: var(--rr-space-1-5);
  font-size: var(--rr-text-xs); font-weight: var(--rr-weight-medium);
  color: var(--rr-text-muted);
}
.rr-legend__dot {
  width: 10px; height: 10px; border-radius: var(--rr-radius-xs);
  border: 1px solid var(--rr-border-strong); background: var(--rr-surface-2);
}
.rr-legend__dot--running { background: var(--rr-warning-50); border-color: var(--rr-warning-600); }
.rr-legend__dot--ready   { background: var(--rr-info-50);    border-color: var(--rr-info-600); }

/* -- stock card: one food item's count, alert level and quick edit -------- */
.rr-stock-card { display: flex; flex-direction: column; }
.rr-stock-card--low { border-left-width: 3px; border-left-color: var(--rr-warning-600); }
.rr-stock-card .rr-card__foot { margin-top: auto; }
.rr-stock-kpi {
  padding: var(--rr-space-2-5) var(--rr-space-3);
  background: var(--rr-surface-2);
  border: 1px solid var(--rr-border);
  border-radius: var(--rr-radius-md);
  display: flex; flex-direction: column; gap: var(--rr-space-1);
}

/* -- order list: a stack of order cards (dashboard + live orders board) -- */
.rr-order-list { display: grid; gap: var(--rr-space-3); padding: var(--rr-space-4); }
.rr-order-list:empty { padding: 0; }
/* A rule in the status tone down the left edge, so a board of orders can be
   triaged by position and colour without reading every badge. A real border
   rather than an inset shadow: it survives print and canvas rasterisation. */
.rr-order { border-left-width: 3px; }
.rr-order--warning { border-left-color: var(--rr-warning-600); }
.rr-order--info    { border-left-color: var(--rr-info-600); }
.rr-order--success { border-left-color: var(--rr-success-600); }
.rr-order--error   { border-left-color: var(--rr-error-600); }
.rr-order--neutral { border-left-color: var(--rr-ink-400); }
.rr-order__items { display: flex; flex-wrap: wrap; gap: var(--rr-space-2); }
.rr-order__item {
  display: inline-flex; flex-direction: column;
  padding: var(--rr-space-1-5) var(--rr-space-2-5);
  background: var(--rr-surface-2);
  border: 1px solid var(--rr-border);
  border-radius: var(--rr-radius-md);
  font-size: var(--rr-text-sm); font-weight: var(--rr-weight-medium); color: var(--rr-text);
}
.rr-order__item small { font-size: var(--rr-text-2xs); color: var(--rr-text-muted); font-weight: var(--rr-weight-normal); }
.rr-order__item em {
  font-style: normal; font-size: var(--rr-text-2xs);
  color: var(--rr-warning-700); font-weight: var(--rr-weight-semibold);
}
.rr-order__note {
  margin-top: var(--rr-space-3);
  padding: var(--rr-space-2-5) var(--rr-space-3);
  background: var(--rr-warning-50);
  border: 1px solid var(--rr-warning-200);
  border-radius: var(--rr-radius-md);
  font-size: var(--rr-text-sm); color: var(--rr-warning-700);
}

/* ============================================================== 13 ===
   PAGINATION
   ==================================================================== */
.rr-pagination {
  display: flex; align-items: center; gap: var(--rr-space-3);
  flex-wrap: wrap; padding: var(--rr-space-3) var(--rr-space-4);
  border-top: 1px solid var(--rr-border);
  background: var(--rr-surface);
}
.rr-pagination__info {
  font-size: var(--rr-text-xs); color: var(--rr-text-muted);
  margin-right: auto; font-variant-numeric: tabular-nums;
}
.rr-pagination__info b { color: var(--rr-text); font-weight: var(--rr-weight-semibold); }
.rr-pagination__pages { display: flex; align-items: center; gap: var(--rr-space-1); }
.rr-page {
  display: grid; place-items: center;
  min-width: 32px; height: 32px; padding: 0 var(--rr-space-2);
  background: var(--rr-surface); color: var(--rr-text-body);
  border: 1px solid var(--rr-border); border-radius: var(--rr-radius-md);
  font-size: var(--rr-text-sm); font-weight: var(--rr-weight-medium);
  font-variant-numeric: tabular-nums; cursor: pointer;
  transition: background-color var(--rr-dur-fast) var(--rr-ease),
              border-color var(--rr-dur-fast) var(--rr-ease), color var(--rr-dur-fast) var(--rr-ease);
}
.rr-page:hover:not(:disabled):not(.is-active) {
  background: var(--rr-surface-2); border-color: var(--rr-border-strong); color: var(--rr-text); text-decoration: none;
}
.rr-page.is-active {
  background: var(--rr-primary-600); border-color: var(--rr-primary-600);
  color: #fff; font-weight: var(--rr-weight-semibold);
}
.rr-page:disabled { opacity: 0.4; cursor: not-allowed; }
.rr-page--gap { border: 0; background: none; cursor: default; color: var(--rr-text-subtle); min-width: 20px; }
.rr-pagination__size { display: flex; align-items: center; gap: var(--rr-space-2); font-size: var(--rr-text-xs); color: var(--rr-text-muted); }
@media (max-width: 640px) {
  .rr-pagination { justify-content: center; }
  .rr-pagination__info { margin-right: 0; flex-basis: 100%; text-align: center; }
  .rr-pagination__size { display: none; }
}

/* ============================================================== 14 ===
   MODALS / DRAWERS
   ==================================================================== */
.rr-overlay {
  position: fixed; inset: 0; z-index: var(--rr-z-overlay);
  background: rgba(28, 25, 23, 0.5);
  backdrop-filter: blur(2px);
  animation: rr-fade var(--rr-dur-base) var(--rr-ease);
}
@keyframes rr-fade { from { opacity: 0; } }

.rr-modal {
  position: fixed; z-index: var(--rr-z-modal);
  left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: min(560px, calc(100vw - var(--rr-space-8)));
  max-height: calc(100vh - var(--rr-space-16));
  display: flex; flex-direction: column;
  background: var(--rr-surface);
  border: 1px solid var(--rr-border);
  border-radius: var(--rr-radius-xl);
  box-shadow: var(--rr-shadow-xl);
  overflow: hidden;
  animation: rr-modal-in var(--rr-dur-slow) var(--rr-ease-out);
}
@keyframes rr-modal-in {
  from { opacity: 0; transform: translate(-50%, calc(-50% + 12px)) scale(0.98); }
}
.rr-modal--sm { width: min(420px, calc(100vw - var(--rr-space-8))); }
.rr-modal--lg { width: min(760px, calc(100vw - var(--rr-space-8))); }
.rr-modal--xl { width: min(1000px, calc(100vw - var(--rr-space-8))); }

.rr-modal__head {
  display: flex; align-items: flex-start; gap: var(--rr-space-3);
  padding: var(--rr-space-4) var(--rr-space-5);
  border-bottom: 1px solid var(--rr-border);
}
.rr-modal__title {
  font-family: var(--rr-font-display);
  font-size: var(--rr-text-lg); font-weight: var(--rr-weight-bold);
  color: var(--rr-text); letter-spacing: var(--rr-tracking-tight);
  line-height: var(--rr-leading-snug);
}
.rr-modal__sub { font-size: var(--rr-text-sm); color: var(--rr-text-muted); margin-top: var(--rr-space-0-5); }
.rr-modal__x {
  flex: none; display: grid; place-items: center;
  width: 32px; height: 32px; margin: -2px -6px 0 auto;
  border-radius: var(--rr-radius-md); color: var(--rr-text-muted); cursor: pointer;
  transition: background-color var(--rr-dur-fast) var(--rr-ease), color var(--rr-dur-fast) var(--rr-ease);
}
.rr-modal__x:hover { background: var(--rr-surface-3); color: var(--rr-text); }
.rr-modal__body { padding: var(--rr-space-5); overflow-y: auto; flex: 1; }
.rr-modal__foot {
  /* flex-wrap: a footer with 3+ buttons (Close/PDF/WhatsApp/Print on
     BillPrintModal.jsx, for one) can be wider than a narrow modal
     (.rr-modal--sm) even ABOVE the 640px phone breakpoint below, which only
     switches to a full-width stacked column -- between those two states,
     nowrap was letting buttons overflow/clip the modal's own edge instead of
     just moving to a second row. Wrapping costs nothing when everything
     already fits on one line. */
  display: flex; align-items: center; justify-content: flex-end; flex-wrap: wrap; gap: var(--rr-space-2);
  padding: var(--rr-space-4) var(--rr-space-5);
  border-top: 1px solid var(--rr-border);
  background: var(--rr-surface-2);
}
/* confirm dialog: icon + copy, destructive by default on danger variant */
.rr-modal__icon {
  display: grid; place-items: center; flex: none;
  width: 40px; height: 40px; border-radius: var(--rr-radius-lg);
  background: var(--rr-warning-50); color: var(--rr-warning-600);
  border: 1px solid var(--rr-warning-200);
}
.rr-modal__icon--danger { background: var(--rr-error-50); color: var(--rr-error-600); border-color: var(--rr-error-200); }

/* drawer (side sheet) — same tokens, edge-anchored */
.rr-drawer {
  position: fixed; z-index: var(--rr-z-modal); top: 0; right: 0; bottom: 0;
  width: min(460px, 100vw);
  display: flex; flex-direction: column;
  background: var(--rr-surface);
  border-left: 1px solid var(--rr-border);
  box-shadow: var(--rr-shadow-xl);
  animation: rr-drawer-in var(--rr-dur-slow) var(--rr-ease-out);
}
@keyframes rr-drawer-in { from { transform: translateX(24px); opacity: 0; } }
.rr-drawer--lg { width: min(680px, 100vw); }

@media (max-width: 640px) {
  /* on phones a modal becomes a bottom sheet — thumb-reachable actions */
  .rr-modal {
    left: 0; right: 0; bottom: 0; top: auto; transform: none;
    width: 100%; max-height: 92vh;
    border-radius: var(--rr-radius-xl) var(--rr-radius-xl) 0 0;
    animation: rr-sheet-in var(--rr-dur-slow) var(--rr-ease-out);
  }
  @keyframes rr-sheet-in { from { transform: translateY(100%); } }
  .rr-modal__foot { flex-direction: column-reverse; align-items: stretch; }
  .rr-modal__foot .rr-btn { width: 100%; }
  .rr-drawer { width: 100vw; border-left: 0; }
}

/* ============================================================== 15 ===
   EMPTY STATES — illustration slot, headline, one clear next action
   ==================================================================== */
.rr-empty {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; padding: var(--rr-space-12) var(--rr-space-6);
  gap: var(--rr-space-1);
}
.rr-empty__art {
  display: grid; place-items: center;
  width: 64px; height: 64px; margin-bottom: var(--rr-space-3);
  border-radius: var(--rr-radius-xl);
  background: var(--rr-primary-50); color: var(--rr-primary-400);
  border: 1px solid var(--rr-primary-100);
}
.rr-empty__art .rr-i { width: 28px; height: 28px; }
.rr-empty__title {
  font-family: var(--rr-font-display);
  font-size: var(--rr-text-md); font-weight: var(--rr-weight-semibold);
  color: var(--rr-text);
}
.rr-empty__text {
  font-size: var(--rr-text-sm); color: var(--rr-text-muted);
  line-height: var(--rr-leading-relaxed); max-width: 42ch;
}
.rr-empty__actions { display: flex; gap: var(--rr-space-2); margin-top: var(--rr-space-4); flex-wrap: wrap; justify-content: center; }
.rr-empty--sm { padding: var(--rr-space-8) var(--rr-space-4); }
.rr-empty--sm .rr-empty__art { width: 48px; height: 48px; }
.rr-empty--sm .rr-empty__art .rr-i { width: 22px; height: 22px; }

/* ============================================================== 16 ===
   SKELETONS — shape-matched placeholders, not spinners
   ==================================================================== */
.rr-skel {
  position: relative; overflow: hidden;
  background: var(--rr-ink-100);
  border-radius: var(--rr-radius-sm);
}
.rr-skel::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.7), transparent);
  transform: translateX(-100%);
  animation: rr-shimmer 1.4s var(--rr-ease) infinite;
}
@keyframes rr-shimmer { to { transform: translateX(100%); } }
@media (prefers-reduced-motion: reduce) { .rr-skel::after { animation: none; } }

.rr-skel--text  { height: 12px; }
.rr-skel--title { height: 18px; width: 40%; }
.rr-skel--line  { height: 12px; width: 100%; }
.rr-skel--line-sm { height: 12px; width: 60%; }
.rr-skel--pill  { height: 22px; width: 72px; border-radius: var(--rr-radius-pill); }
.rr-skel--avatar{ width: 32px; height: 32px; border-radius: 50%; }
.rr-skel--stat  { height: 26px; width: 96px; }
.rr-skel--chart { height: 200px; border-radius: var(--rr-radius-md); }
.rr-skel-rows > * + * { margin-top: var(--rr-space-2-5); }

/* skeleton table row: drop N of these into tbody while loading */
.rr-skel-row td { padding: var(--rr-space-3) var(--rr-space-4); }

/* ============================================================== 17 ===
   TOASTS
   ==================================================================== */
.rr-toasts {
  position: fixed; z-index: var(--rr-z-toast);
  top: var(--rr-space-4); right: var(--rr-space-4);
  display: flex; flex-direction: column; gap: var(--rr-space-2-5);
  width: min(380px, calc(100vw - var(--rr-space-8)));
  pointer-events: none;
}
.rr-toast {
  pointer-events: auto;
  display: flex; align-items: flex-start; gap: var(--rr-space-3);
  padding: var(--rr-space-3) var(--rr-space-3-5, 14px);
  background: var(--rr-surface);
  border: 1px solid var(--rr-border);
  border-left: 3px solid var(--rr-ink-400);
  border-radius: var(--rr-radius-lg);
  box-shadow: var(--rr-shadow-lg);
  animation: rr-toast-in var(--rr-dur-slow) var(--rr-ease-out);
}
@keyframes rr-toast-in { from { opacity: 0; transform: translateX(16px) scale(0.98); } }
.rr-toast.is-leaving { animation: rr-toast-out var(--rr-dur-base) var(--rr-ease) forwards; }
@keyframes rr-toast-out { to { opacity: 0; transform: translateX(16px); } }
.rr-toast__icon { flex: none; margin-top: 1px; }
.rr-toast__body { flex: 1; min-width: 0; }
.rr-toast__title { font-size: var(--rr-text-base); font-weight: var(--rr-weight-semibold); color: var(--rr-text); }
.rr-toast__text  { font-size: var(--rr-text-sm); color: var(--rr-text-muted); line-height: var(--rr-leading-normal); margin-top: 1px; }
.rr-toast__x {
  flex: none; display: grid; place-items: center; width: 24px; height: 24px;
  margin: -2px -4px 0 0; border-radius: var(--rr-radius-sm);
  color: var(--rr-text-subtle); cursor: pointer;
}
.rr-toast__x:hover { background: var(--rr-surface-3); color: var(--rr-text); }
.rr-toast--success { border-left-color: var(--rr-success-600); }
.rr-toast--success .rr-toast__icon { color: var(--rr-success-600); }
.rr-toast--error   { border-left-color: var(--rr-error-600); }
.rr-toast--error   .rr-toast__icon { color: var(--rr-error-600); }
.rr-toast--warning { border-left-color: var(--rr-warning-600); }
.rr-toast--warning .rr-toast__icon { color: var(--rr-warning-600); }
.rr-toast--info    { border-left-color: var(--rr-info-600); }
.rr-toast--info    .rr-toast__icon { color: var(--rr-info-600); }
@media (max-width: 640px) {
  .rr-toasts { top: auto; bottom: var(--rr-space-4); left: var(--rr-space-4); right: var(--rr-space-4); width: auto; }
}

/* ====================================================== 17a ===
   GLOBAL SEARCH — the header field and its results panel
   ==================================================================== */
.rr-search { position: relative; }
.rr-search__panel {
  position: absolute; z-index: var(--rr-z-dropdown);
  top: calc(100% + var(--rr-space-2)); left: 0; right: 0;
  min-width: 320px;
  max-height: min(420px, 70vh); overflow-y: auto;
  background: var(--rr-surface);
  border: 1px solid var(--rr-border);
  border-radius: var(--rr-radius-lg);
  box-shadow: var(--rr-shadow-lg);
  display: none;
}
.rr-search__panel.is-open { display: block; animation: rr-pop var(--rr-dur-base) var(--rr-ease-out); }
.rr-search__group + .rr-search__group { border-top: 1px solid var(--rr-border); }
.rr-search__label {
  display: flex; align-items: center; gap: var(--rr-space-2);
  padding: var(--rr-space-2-5) var(--rr-space-3) var(--rr-space-1-5);
  font-size: var(--rr-text-2xs); font-weight: var(--rr-weight-semibold);
  letter-spacing: var(--rr-tracking-caps); text-transform: uppercase;
  color: var(--rr-text-subtle);
}
.rr-search__item {
  display: block; width: 100%;
  padding: var(--rr-space-2) var(--rr-space-3);
  text-align: left; cursor: pointer;
  transition: background-color var(--rr-dur-fast) var(--rr-ease);
}
.rr-search__item:hover, .rr-search__item.is-active {
  background: var(--rr-surface-3); text-decoration: none;
}
.rr-search__item b {
  display: block; font-size: var(--rr-text-sm);
  font-weight: var(--rr-weight-semibold); color: var(--rr-text);
}
.rr-search__item span {
  display: block; font-size: var(--rr-text-xs); color: var(--rr-text-muted); margin-top: 1px;
}
.rr-search__hint {
  padding: var(--rr-space-6) var(--rr-space-4);
  text-align: center; font-size: var(--rr-text-sm); color: var(--rr-text-muted);
}
.rr-search__foot {
  padding: var(--rr-space-2) var(--rr-space-3);
  border-top: 1px solid var(--rr-border);
  background: var(--rr-surface-2);
  font-size: var(--rr-text-2xs); color: var(--rr-text-subtle);
  display: flex; gap: var(--rr-space-3); flex-wrap: wrap;
}
.rr-search__foot kbd {
  padding: 1px 5px;
  background: var(--rr-surface); border: 1px solid var(--rr-border-strong);
  border-radius: var(--rr-radius-xs);
  font-family: var(--rr-font-mono); font-size: 10px; color: var(--rr-text-body);
}
@media (max-width: 900px) {
  /* the header hides the field below 900px, so the panel goes with it */
  .rr-search__panel { display: none !important; }
}

/* ====================================================== 17a-1 ===
   CUSTOMER POPOVER — WaiterOrderScreen's order-header "customer name/phone"
   control (react-app/src/components/WaiterOrderScreen.jsx). Was built with
   one-off inline styles (a bare .rr-card positioned by hand); the owner's
   complaint was that this reads as a bolted-on extra rather than part of
   the app. Pulling it into its own named component here — same anchored-
   popover shape as .rr-menu / .rr-notif__panel / .rr-search__panel right
   above and below, same radius-lg + shadow-lg + border, same rr-pop
   entrance animation — makes it visually just another one of the app's
   existing dropdown-style panels instead of a bespoke floating box. Nothing
   about WHEN it opens/closes or what it submits changed, only what class
   names carry the visual styling that used to live in the JSX's style={}. */
.rr-customer-anchor { position: relative; display: inline-flex; }
.rr-customer-anchor__dot {
  position: absolute; top: 2px; right: 2px; width: 8px; height: 8px;
  border-radius: 50%; background: var(--rr-success-600);
  border: 1.5px solid var(--rr-surface);
}
/* THE "PC POPUP" BUG — `left: 0; min-width: 220px` with no viewport clamp.
   This anchor button sits at the FAR RIGHT of the order-header row (after a
   `rr-spacer` and the seats/Persons controls — see WaiterOrderScreen.jsx),
   so `left: 0` grows the panel rightward off an anchor that is already
   against the edge of the screen. On a desktop-width header there is enough
   spare room to the right that this never showed; on a real ~360-400px
   phone viewport (the owner's screenshot) the anchor sits within a few
   pixels of the screen edge and a 220px-wide panel growing further right
   is guaranteed to run past the viewport — the exact "popup fits a PC, not
   a phone" shape of bug, and with no ancestor here clipping overflow it also
   widens the whole scrollport, which is how one popover creates a stray
   horizontal scrollbar for the entire order screen.
   Fixed by copying the two OTHER right-anchored popovers in this same file
   (.rr-notif__panel just below, .rr-bellpop further down) rather than
   inventing a third rule: `right: 0` grows the panel LEFTWARD from an anchor
   that is already at the right edge, which is the direction that always has
   room, and `width: min(220px, calc(100vw - var(--rr-space-8)))` is the same
   viewport-relative cap those two already use, so 220px is only ever the
   ceiling and the panel shrinks to fit a phone instead of overflowing it. */
.rr-customer-pop {
  position: absolute; top: 100%; right: 0; left: auto; margin-top: var(--rr-space-2);
  z-index: var(--rr-z-dropdown);
  width: min(220px, calc(100vw - var(--rr-space-8))); padding: var(--rr-space-3);
  display: flex; flex-direction: column; gap: var(--rr-space-2-5);
  background: var(--rr-surface);
  border: 1px solid var(--rr-border);
  border-radius: var(--rr-radius-lg);
  box-shadow: var(--rr-shadow-lg);
  animation: rr-pop var(--rr-dur-base) var(--rr-ease-out);
}
.rr-customer-pop__field {
  display: flex; flex-direction: column; gap: var(--rr-space-1);
  font-size: var(--rr-text-xs); color: var(--rr-text-muted);
}
.rr-customer-pop__foot {
  display: flex; justify-content: flex-end;
  padding-top: var(--rr-space-1);
  border-top: 1px solid var(--rr-border);
}

/* ====================================================== 17b ===
   NOTIFICATION POPOVER — a bell that opens a list anchored to the header.
   `.rr-notif__*` below is the PHP-side desktop-alerts bell (admin.php's
   $notifWidget + renderNotifPanel() in its inline <script>) — left exactly
   as it was; it is rendered and driven entirely from PHP/vanilla JS and
   does not go through this React component at all.
   ==================================================================== */
.rr-notif { position: relative; }
.rr-notif__panel {
  position: absolute; z-index: var(--rr-z-dropdown);
  top: calc(100% + var(--rr-space-2)); right: 0;
  width: min(340px, calc(100vw - var(--rr-space-8)));
  background: var(--rr-surface);
  border: 1px solid var(--rr-border);
  border-radius: var(--rr-radius-lg);
  box-shadow: var(--rr-shadow-lg);
  overflow: hidden;
  display: none;
}
.rr-notif__panel.is-open { display: block; animation: rr-pop var(--rr-dur-base) var(--rr-ease-out); }
.rr-notif__head {
  display: flex; align-items: center; gap: var(--rr-space-2);
  padding: var(--rr-space-3) var(--rr-space-3-5, 14px);
  border-bottom: 1px solid var(--rr-border);
}
.rr-notif__head strong {
  font-family: var(--rr-font-display);
  font-size: var(--rr-text-base); font-weight: var(--rr-weight-semibold);
  color: var(--rr-text); margin-right: auto;
}
.rr-notif__list { max-height: 340px; overflow-y: auto; }
.rr-notif__item {
  display: flex; gap: var(--rr-space-2-5);
  padding: var(--rr-space-3) var(--rr-space-3-5, 14px);
  border-bottom: 1px solid var(--rr-border);
}
.rr-notif__item:last-child { border-bottom: 0; }
.rr-notif__item b {
  display: block; font-size: var(--rr-text-sm);
  font-weight: var(--rr-weight-semibold); color: var(--rr-text);
}
.rr-notif__item span { display: block; font-size: var(--rr-text-xs); color: var(--rr-text-muted); margin-top: 1px; }
.rr-notif__item time { display: block; font-size: var(--rr-text-2xs); color: var(--rr-text-subtle); margin-top: 3px; }
.rr-notif__dot { flex: none; width: 7px; height: 7px; border-radius: 50%; margin-top: 6px; background: var(--rr-ink-300); }
.rr-notif__dot--info    { background: var(--rr-info-600); }
.rr-notif__dot--success { background: var(--rr-success-600); }
.rr-notif__dot--warning { background: var(--rr-warning-600); }
.rr-notif__dot--error   { background: var(--rr-error-600); }
.rr-notif__empty {
  padding: var(--rr-space-8) var(--rr-space-4);
  text-align: center; font-size: var(--rr-text-sm); color: var(--rr-text-muted);
}

/* ---- React topbar bell (Topbar.jsx NotificationBell) --------------------
   Deliberately its own `.rr-bellpop__*` namespace rather than reusing
   `.rr-notif__*` above — that block belongs to the separate PHP/vanilla-JS
   desktop-alerts bell in admin.php and must not be touched by this redesign. */
.rr-bellpop {
  position: absolute; z-index: var(--rr-z-dropdown);
  top: calc(100% + var(--rr-space-2)); right: 0;
  width: min(360px, calc(100vw - var(--rr-space-8)));
  background: var(--rr-surface);
  border: 1px solid var(--rr-border);
  border-radius: var(--rr-radius-xl);
  box-shadow: var(--rr-shadow-lg);
  overflow: hidden;
  animation: rr-pop var(--rr-dur-base) var(--rr-ease-out);
}
.rr-bellpop__head {
  display: flex; align-items: baseline; gap: var(--rr-space-2);
  padding: var(--rr-space-3-5, 14px) var(--rr-space-4);
  border-bottom: 1px solid var(--rr-border);
}
.rr-bellpop__head strong {
  font-family: var(--rr-font-display);
  font-size: var(--rr-text-base); font-weight: var(--rr-weight-semibold);
  color: var(--rr-text); margin-right: auto;
}
.rr-bellpop__head span {
  font-size: var(--rr-text-2xs); font-weight: var(--rr-weight-medium);
  color: var(--rr-text-subtle);
}
/* "Mark all read" — a plain text action beside the title, same weight/size
   as the count it replaces so the head's baseline layout is unchanged. */
.rr-bellpop__markall {
  border: 0; background: none; padding: 0; cursor: pointer;
  font-size: var(--rr-text-2xs); font-weight: var(--rr-weight-semibold);
  color: var(--rr-primary-600);
}
.rr-bellpop__markall:hover { color: var(--rr-primary-700); text-decoration: underline; }
.rr-bellpop__list { max-height: 360px; overflow-y: auto; }
/* Each row gets a 3px status-coloured accent bar down the left edge
   instead of a small dot — reads at a glance without adding an icon set
   for a table (notification_log) that only carries queued/sent/failed. Now
   also a real <button> (admin_notifications rows are clickable to mark
   read), so the box model is reset back to how the div version looked. */
.rr-bellpop__item {
  display: flex; align-items: flex-start; gap: var(--rr-space-3);
  width: 100%; border: 0; border-bottom: 1px solid var(--rr-border);
  padding: var(--rr-space-3) var(--rr-space-4);
  border-left: 3px solid var(--rr-ink-300);
  background: none; text-align: left; cursor: pointer; font: inherit; color: inherit;
  transition: background-color var(--rr-dur-fast) var(--rr-ease);
}
.rr-bellpop__item:hover { background: var(--rr-surface-3); }
.rr-bellpop__item:last-child { border-bottom: 0; }
.rr-bellpop__item--info    { border-left-color: var(--rr-info-600); }
.rr-bellpop__item--success { border-left-color: var(--rr-success-600); }
.rr-bellpop__item--warning { border-left-color: var(--rr-warning-600); }
.rr-bellpop__item--error   { border-left-color: var(--rr-error-600); }
/* Unread admin_notifications row: a faint tint so unread stands out from
   already-read history in the same list, without a second colour system —
   reuses the primary tokens the rest of the shell already uses for "new". */
.rr-bellpop__item--unread { background: var(--rr-primary-50); }
.rr-bellpop__item--unread:hover { background: var(--rr-primary-100, var(--rr-surface-3)); }
.rr-bellpop__item--unread .rr-bellpop__msg { font-weight: var(--rr-weight-semibold); }
.rr-bellpop__body { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1; }
.rr-bellpop__msg {
  font-size: var(--rr-text-sm); font-weight: var(--rr-weight-medium);
  color: var(--rr-text); line-height: var(--rr-leading-snug, 1.35);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.rr-bellpop__meta { display: flex; align-items: center; gap: var(--rr-space-2); }
.rr-bellpop__badge {
  flex: none; padding: 1px var(--rr-space-1-5);
  border-radius: var(--rr-radius-pill);
  background: var(--rr-surface-3); color: var(--rr-text-muted);
  font-size: var(--rr-text-2xs); font-weight: var(--rr-weight-semibold);
  letter-spacing: var(--rr-tracking-caps); text-transform: uppercase;
}
.rr-bellpop__time { font-size: var(--rr-text-2xs); color: var(--rr-text-subtle); }
.rr-bellpop__foot {
  display: block; text-align: center;
  padding: var(--rr-space-2-5) var(--rr-space-4);
  border-top: 1px solid var(--rr-border);
  font-size: var(--rr-text-xs); font-weight: var(--rr-weight-semibold);
  color: var(--rr-primary-600);
  transition: background-color var(--rr-dur-fast) var(--rr-ease);
}
.rr-bellpop__foot:hover { background: var(--rr-surface-3); color: var(--rr-primary-700); text-decoration: none; }
/* Empty/loading/error states mirror the .rr-empty visual language (icon
   badge + title + muted line) at a scale that fits inside a 360px popover
   rather than reusing the full-page component built for space-12 padding. */
.rr-bellpop__empty {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; gap: var(--rr-space-1);
  padding: var(--rr-space-8) var(--rr-space-5);
}
.rr-bellpop__empty-art {
  display: grid; place-items: center;
  width: 44px; height: 44px; margin-bottom: var(--rr-space-2);
  border-radius: var(--rr-radius-lg);
  background: var(--rr-primary-50); color: var(--rr-primary-400);
  border: 1px solid var(--rr-primary-100);
}
.rr-bellpop__empty-art .rr-i { width: 20px; height: 20px; }
.rr-bellpop__empty-title {
  font-size: var(--rr-text-sm); font-weight: var(--rr-weight-semibold); color: var(--rr-text);
}
.rr-bellpop__empty-text { font-size: var(--rr-text-xs); color: var(--rr-text-muted); max-width: 30ch; }

/* ---- Online Menu On/Off "turn item off" schedule panel -------------------
   MenuItemsBoard.jsx's OnlineMenuTab, opened from a Zomato/Swiggy switch
   when it is flipped ON -> OFF (Petpooja reference: "Below are the
   parameters to mark item off only", 2h/4h/8h/24h/Indefinite/Custom radios,
   Cancel/Save Changes). Deliberately reuses the exact positioned-popover
   shell (.rr-bellpop's position/size/border/shadow/animation) under its own
   `.rr-offsched__*` namespace instead of inventing a new overlay mechanism —
   only the anchor point differs (left-aligned under a table-cell switch
   instead of right-aligned under the topbar bell). */
.rr-offsched {
  position: absolute; z-index: var(--rr-z-dropdown);
  top: calc(100% + var(--rr-space-2)); left: 0;
  width: min(280px, calc(100vw - var(--rr-space-8)));
  background: var(--rr-surface);
  border: 1px solid var(--rr-border);
  border-radius: var(--rr-radius-xl);
  box-shadow: var(--rr-shadow-lg);
  overflow: hidden;
  animation: rr-pop var(--rr-dur-base) var(--rr-ease-out);
  text-align: left;
}
.rr-offsched__head {
  padding: var(--rr-space-3) var(--rr-space-4);
  border-bottom: 1px solid var(--rr-border);
  font-size: var(--rr-text-sm); font-weight: var(--rr-weight-semibold); color: var(--rr-text);
}
.rr-offsched__sub {
  display: block; margin-top: 2px;
  font-size: var(--rr-text-2xs); font-weight: var(--rr-weight-medium); color: var(--rr-text-subtle);
}
.rr-offsched__body { padding: var(--rr-space-3) var(--rr-space-4); display: grid; gap: var(--rr-space-2); }
.rr-offsched__opt {
  display: flex; align-items: center; gap: var(--rr-space-2);
  font-size: var(--rr-text-sm); color: var(--rr-text); cursor: pointer;
}
.rr-offsched__opt input { accent-color: var(--rr-primary-600); }
.rr-offsched__custom {
  margin-left: calc(var(--rr-space-2) + 14px);
}
.rr-offsched__foot {
  display: flex; justify-content: flex-end; gap: var(--rr-space-2);
  padding: var(--rr-space-3) var(--rr-space-4);
  border-top: 1px solid var(--rr-border);
}
/* Caption next to an already-OFF switch, e.g. "until 3:45 PM" / "Off
   indefinitely" — read from the list response's *_unavailable_until field,
   no extra request needed. */
.rr-offsched__caption {
  display: block; margin-top: 2px;
  font-size: var(--rr-text-2xs); color: var(--rr-text-subtle);
}

/* ============================================================== 18 ===
   TOOLTIP — CSS only, content from data-rr-tip
   ==================================================================== */
.rr-tip { position: relative; }
.rr-tip::after {
  content: attr(data-rr-tip);
  position: absolute; z-index: var(--rr-z-tooltip);
  bottom: calc(100% + 8px); left: 50%; transform: translateX(-50%);
  padding: var(--rr-space-1-5) var(--rr-space-2-5);
  background: var(--rr-ink-950); color: #fff;
  border-radius: var(--rr-radius-sm);
  font-size: var(--rr-text-xs); font-weight: var(--rr-weight-medium);
  white-space: nowrap; opacity: 0; pointer-events: none;
  transition: opacity var(--rr-dur-fast) var(--rr-ease);
  box-shadow: var(--rr-shadow-md);
}
.rr-tip:hover::after, .rr-tip:focus-visible::after { opacity: 1; }

/* ============================================================== 19 ===
   AVATAR
   ==================================================================== */
.rr-avatar {
  display: grid; place-items: center; flex: none;
  width: 32px; height: 32px; border-radius: 50%;
  background: var(--rr-primary-50); color: var(--rr-primary-700);
  border: 1px solid var(--rr-primary-100);
  font-size: var(--rr-text-xs); font-weight: var(--rr-weight-bold);
  text-transform: uppercase; overflow: hidden;
}
.rr-avatar--sm { width: 26px; height: 26px; font-size: var(--rr-text-2xs); }
.rr-avatar--lg { width: 40px; height: 40px; font-size: var(--rr-text-base); }
.rr-avatar--square { border-radius: var(--rr-radius-md); }

/* ============================================================== 20 ===
   PROGRESS / METER
   ==================================================================== */
.rr-progress {
  height: 6px; background: var(--rr-ink-200);
  border-radius: var(--rr-radius-pill); overflow: hidden;
}
.rr-progress__bar {
  height: 100%; background: var(--rr-primary-600);
  border-radius: var(--rr-radius-pill);
  transition: width var(--rr-dur-slow) var(--rr-ease);
}
.rr-progress__bar--success { background: var(--rr-success-600); }
.rr-progress__bar--warning { background: var(--rr-warning-600); }
.rr-progress__bar--error   { background: var(--rr-error-600); }
.rr-progress--lg { height: 10px; }

/* indeterminate — for exports and long report runs */
.rr-progress--indeterminate .rr-progress__bar {
  width: 35%; animation: rr-indet 1.2s var(--rr-ease) infinite;
}
@keyframes rr-indet {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(320%); }
}

/* ============================================================== 21 ===
   TABS / SEGMENTED CONTROL
   ==================================================================== */
.rr-tabs {
  display: flex; align-items: center; gap: var(--rr-space-1);
  border-bottom: 1px solid var(--rr-border);
  overflow-x: auto;
}
.rr-tab {
  display: inline-flex; align-items: center; gap: var(--rr-space-2);
  padding: var(--rr-space-2-5) var(--rr-space-3);
  border-bottom: 2px solid transparent;
  font-size: var(--rr-text-base); font-weight: var(--rr-weight-medium);
  color: var(--rr-text-muted); white-space: nowrap; cursor: pointer;
  transition: color var(--rr-dur-fast) var(--rr-ease), border-color var(--rr-dur-fast) var(--rr-ease);
}
.rr-tab:hover { color: var(--rr-text); text-decoration: none; }
.rr-tab.is-active {
  color: var(--rr-text-brand); border-bottom-color: var(--rr-primary-600);
  font-weight: var(--rr-weight-semibold);
}

.rr-segment {
  display: inline-flex; padding: 3px; gap: 2px;
  background: var(--rr-surface-3); border-radius: var(--rr-radius-md);
}
.rr-segment__item {
  padding: var(--rr-space-1-5) var(--rr-space-3);
  border-radius: var(--rr-radius-sm);
  font-size: var(--rr-text-sm); font-weight: var(--rr-weight-medium);
  color: var(--rr-text-muted); cursor: pointer; white-space: nowrap;
  transition: background-color var(--rr-dur-fast) var(--rr-ease), color var(--rr-dur-fast) var(--rr-ease);
}
.rr-segment__item:hover { color: var(--rr-text); text-decoration: none; }
.rr-segment__item.is-active {
  background: var(--rr-surface); color: var(--rr-text);
  font-weight: var(--rr-weight-semibold); box-shadow: var(--rr-shadow-xs);
}

/* ==================================================== BILL DETAIL PANEL ====
   The read-only view of one settled bill, shown in a modal from Bill History.
   Deliberately not reusing print.css: those rules are scoped to paper widths
   and thermal type sizes, which are wrong on a screen. */
.rr-doc-meta {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--rr-space-3) var(--rr-space-4);
  margin: 0 0 var(--rr-space-4);
  padding-bottom: var(--rr-space-4);
  border-bottom: 1px solid var(--rr-border);
}
.rr-doc-meta dt {
  font-size: var(--rr-text-2xs); font-weight: var(--rr-weight-semibold);
  letter-spacing: var(--rr-tracking-wide); text-transform: uppercase;
  color: var(--rr-text-subtle); margin-bottom: 2px;
}
.rr-doc-meta dd {
  margin: 0; font-size: var(--rr-text-sm); font-weight: var(--rr-weight-medium);
  color: var(--rr-text); overflow-wrap: anywhere;
}

.rr-doc-sum {
  display: flex; flex-direction: column; gap: var(--rr-space-1);
  margin-top: var(--rr-space-4); padding-top: var(--rr-space-3);
  border-top: 1px solid var(--rr-border);
}
.rr-doc-line {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--rr-space-4);
  font-size: var(--rr-text-sm); color: var(--rr-text-muted);
}
.rr-doc-line .rr-num { font-variant-numeric: tabular-nums; color: var(--rr-text); font-weight: var(--rr-weight-semibold); }
/* The payable figure is the one the eye should land on. */
.rr-doc-line--total {
  margin-top: var(--rr-space-2); padding-top: var(--rr-space-2);
  border-top: 1px solid var(--rr-border-strong);
  font-family: var(--rr-font-display); font-size: var(--rr-text-lg);
  font-weight: var(--rr-weight-extra); color: var(--rr-text);
}
.rr-doc-line--total .rr-num { font-size: var(--rr-text-xl); }

/* BillSettingsBoard.jsx's editor + Live Preview two-column layout
   (react-app/src/components/BillSettingsBoard.jsx, the 4 Bill Settings
   screens under "Bill & Printer Settings"). The inline style there sets a
   fixed 320px preview column with no mobile fallback at all -- sitting
   inside .rr-card__body rather than a table-style scroll wrapper, that
   forced real horizontal overflow below ~900px with nothing to scroll it.
   !important is required here only because it is overriding an inline
   style, not because of any specificity fight with another rule. */
@media (max-width: 900px) {
  .rr-bill-settings-grid { grid-template-columns: minmax(0, 1fr) !important; }
}

/* BillDesignerBoard.jsx's three-pane editor (palette / canvas / style+preview)
   -- same fixed-side-columns issue as .rr-bill-settings-grid above, just with
   two side columns instead of one. This screen is not reachable from the nav
   today (see the comment at its own style prop), so this only prevents
   breakage if it's ever linked directly or re-enabled. */
@media (max-width: 1000px) {
  .rr-bill-designer-grid { grid-template-columns: minmax(0, 1fr) !important; }
}