:root {
  color-scheme: light;
  /* The same palette the mini app ships (restoran/src/styles/tokens.css). An operator moves
     between the storefront and this panel all day; they should read as one product. Navy carries
     the dark surfaces and the type, green carries the actions, terracotta is the accent the brand
     book gives it, and cream warms the panels that need emphasis. */
  --bg: #f4f5f6;
  --bg-muted: #e9ebee;
  --surface: #ffffff;
  --surface-raised: #ffffff;
  --surface-soft: #f8e8d5;
  --ink: #152238;
  --muted: #5a6577;
  --line: #e3e6ea;
  --line-strong: #ccd2da;
  --control-line: #a7b0bd;
  /* Green text and green button fills both use the darker tone: the bright #0f8a4f fails
     contrast against white, which is why the storefront reserves it for decoration. */
  --brand: #0b6d3e;
  --brand-strong: #152238;
  --brand-accent: #a9573b;
  --brand-mint: #8fd6ae;
  --brand-soft: #e4f5eb;
  --focus: #0f8a4f;
  --danger: #b42318;
  --danger-strong: #8f1d15;
  --danger-soft: #fdf0ee;
  --danger-line: #efc0bb;
  --warning: #7a4a08;
  --warning-soft: #fff6e5;
  --warning-line: #e8cb91;
  /* Navy, not the brand green: this is the tone every unrecognised status falls back to, and an
     unpaid order rendered in the success colour tells the kitchen the opposite of the truth.
     Green is reserved for the states that really are settled. */
  --info: #2b4a72;
  --info-soft: #eef2f8;
  --shadow: 0 12px 32px rgba(21, 34, 56, 0.10);
  --shadow-strong: 0 24px 64px rgba(21, 34, 56, 0.22);
  --radius: 12px;
  --sidebar-width: 288px;
  --sidebar-bg: #152238;
  --sidebar-surface: #223351;
  --sidebar-line: rgba(255, 255, 255, 0.12);
  --sidebar-muted: #9fb0c7;
  --sidebar-accent: #a9573b;
  --ornament-image: url("/backoffice/assets/asia-ornament.svg");
  font-family: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  /* The mini app's display face, character for character. Headings and figures are where
     a brand is recognised, and a panel set entirely in the UI sans reads as a different
     product from the app the same operator just looked at. */
  --font-display: Georgia, "Times New Roman", serif;
}
* {
  box-sizing: border-box;
}
html {
  min-width: 320px;
  min-height: 100%;
  background: var(--bg);
}
body {
  min-height: 100%;
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
button,
input,
select,
textarea {
  font: inherit;
}
button {
  color: inherit;
}
a {
  color: var(--brand);
  text-underline-offset: 3px;
}
button:focus-visible,
a:focus-visible,
input:focus-visible,
select:focus-visible,
summary:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
}
#page-title:focus {
  outline: none;
}
[hidden] {
  display: none !important;
}
::selection {
  background: var(--brand-mint);
  color: var(--brand-strong);
}
.muted {
  color: var(--muted);
}
.eyebrow {
  margin: 0 0 4px;
  color: var(--brand);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.13em;
  line-height: 1.4;
  text-transform: uppercase;
}
.brand-logo {
  display: block;
  flex: 0 0 auto;
  object-fit: contain;
}
/* Authentication */
/* Light, like every other surface in this panel. This screen used to be a navy field, which
   made the first thing an operator sees the only dark page in the product — and it read as a
   different application from the cream storefront they had just closed. The ornament is the
   mini app's, at watermark strength; it is held fully inside the box so it can never widen
   the page. */
.login-layout {
  position: relative;
  display: grid;
  min-height: 100svh;
  place-items: center;
  overflow-y: auto;
  padding: clamp(20px, 5vw, 64px);
  /* The colour is named as well as the gradient: a gradient alone leaves background-color
     transparent, and a field that fails to paint should still be cream rather than whatever
     sits behind the page. */
  background: linear-gradient(180deg, #fffdf9 0%, var(--surface-soft) 100%) var(--surface-soft);
}
.login-layout::before {
  content: '';
  position: absolute;
  right: 0;
  bottom: 0;
  width: min(48vw, 400px);
  aspect-ratio: 1;
  background: var(--ornament-image) center / contain no-repeat;
  opacity: 0.15;
  pointer-events: none;
}
.login-card {
  position: relative;
  width: min(100%, 448px);
  /* A white card on cream needs a real edge; the old translucent-white border was drawn to
     separate the card from navy and is invisible here. */
  border: 1px solid var(--line-strong);
  border-top: 5px solid var(--brand-accent);
  border-radius: 14px;
  background: var(--surface);
  box-shadow: var(--shadow);
  padding: clamp(28px, 5vw, 44px);
}
/* The mark is a disc everywhere it appears — the mini app splash, the sidebar, the app icon. A
   rounded square here read as a different logo. The light field takes the light mark, the same
   pairing the storefront makes, and it is the vector rather than the 512px raster: at 76px on a
   3× screen the bitmap was visibly soft. */
.brand-logo--login {
  width: 76px;
  height: 76px;
  margin-bottom: 28px;
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  background: var(--surface);
}
.login-card h1 {
  max-width: 340px;
  margin: 0;
  color: var(--brand-strong);
  font-size: clamp(27px, 5vw, 34px);
  font-weight: 760;
  letter-spacing: -0.035em;
  line-height: 1.13;
}
.login-card > .muted {
  margin: 10px 0 30px;
}
/* Forms */
.form-stack,
.field-grid {
  display: grid;
  gap: 18px;
}
.field-grid {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.field-grid .field--wide {
  grid-column: 1 / -1;
}
.form-stack label,
.field,
.field-grid label {
  display: grid;
  min-width: 0;
  gap: 7px;
  color: var(--ink);
  font-size: 12px;
  font-weight: 720;
  letter-spacing: 0.01em;
}
input,
select,
textarea {
  width: 100%;
  min-width: 0;
  min-height: 46px;
  border: 1px solid var(--control-line);
  border-radius: 8px;
  background: var(--surface);
  color: var(--ink);
  padding: 10px 12px;
  transition: border-color 150ms ease, box-shadow 150ms ease, background 150ms ease;
}
/* A shade lighter than --muted so a placeholder never reads as a filled value, but still on the
   navy grey ramp rather than the green one the panel used to sit on. */
input::placeholder,
textarea::placeholder {
  color: #7d879a;
  opacity: 1;
}
input:hover,
select:hover,
textarea:hover {
  border-color: var(--brand);
}
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  border-color: var(--brand-accent);
  outline: none;
  box-shadow: 0 0 0 3px rgba(22, 130, 85, 0.18);
}
input:disabled,
select:disabled,
textarea:disabled {
  cursor: not-allowed;
  background: var(--bg-muted);
  color: var(--muted);
  opacity: 0.8;
}
textarea {
  min-height: 112px;
  line-height: 1.55;
  resize: vertical;
}
select[multiple] {
  min-height: 132px;
  padding: 6px;
}
select[multiple] option {
  border-radius: 5px;
  padding: 8px;
}
.form-error {
  margin: 0;
  border: 1px solid var(--danger-line);
  border-left: 4px solid var(--danger);
  border-radius: 7px;
  background: var(--danger-soft);
  color: var(--danger-strong);
  padding: 10px 12px;
  font-size: 12px;
  font-weight: 700;
}
.field-help,
.field-error {
  display: block;
  margin-top: -2px;
  font-size: 11px;
  font-weight: 600;
  line-height: 1.45;
}
.field-help {
  color: var(--muted);
}
.field-error {
  color: var(--danger);
}
input[aria-invalid="true"],
select[aria-invalid="true"],
textarea[aria-invalid="true"] {
  border-color: var(--danger);
  box-shadow: 0 0 0 3px rgba(180, 35, 24, 0.12);
}
.field-checkbox {
  display: flex !important;
  grid-column: 1 / -1;
  align-items: flex-start;
  gap: 10px !important;
  line-height: 1.45;
}
.field-checkbox input[type="checkbox"] {
  width: 19px;
  height: 19px;
  min-height: 19px;
  flex: 0 0 19px;
  margin: 1px 0 0;
  accent-color: var(--brand);
}
.field-checkbox > span {
  display: grid;
  min-width: 0;
  gap: 4px;
}
.field-checkbox .field-help,
.field-checkbox .field-error {
  margin-top: 0;
}
/* Actions */
.button,
.icon-button,
.refresh-button,
.profile-button,
.nav-item,
.table-action,
.segmented button {
  cursor: pointer;
}
.button {
  display: inline-flex;
  min-height: 42px;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border: 1px solid transparent;
  border-radius: 8px;
  padding: 0 15px;
  font-size: 12px;
  font-weight: 760;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  transition: background 140ms ease, border-color 140ms ease, color 140ms ease, transform 140ms ease;
}
.button:hover:not(:disabled) {
  transform: translateY(-1px);
}
.button:active:not(:disabled) {
  transform: translateY(0);
}
.button:disabled {
  cursor: not-allowed;
  opacity: 0.5;
}
.button--primary {
  border-color: var(--brand);
  background: var(--brand);
  color: #ffffff;
}
.button--primary:hover:not(:disabled) {
  border-color: var(--brand-strong);
  background: var(--brand-strong);
}
.button--ghost {
  border-color: var(--line-strong);
  background: var(--surface);
  color: var(--brand-strong);
}
.button--ghost:hover:not(:disabled) {
  border-color: var(--brand);
  background: var(--brand-soft);
}
.button--danger {
  border-color: var(--danger-line);
  background: var(--danger-soft);
  color: var(--danger-strong);
}
.button--danger:hover:not(:disabled) {
  border-color: var(--danger);
  background: var(--danger);
  color: #ffffff;
}
.button--wide {
  width: 100%;
  margin-top: 4px;
}
.spinner {
  display: none;
  width: 16px;
  height: 16px;
  border: 2px solid rgba(255, 255, 255, 0.42);
  border-top-color: #ffffff;
  border-radius: 50%;
  animation: spin 650ms linear infinite;
}
.is-loading .spinner {
  display: inline-block;
}
@keyframes spin {
  to { transform: rotate(360deg); }
}
/* Page composition */
.page-container {
  position: relative;
  z-index: 1;
  width: min(100%, 1540px);
  margin: 0 auto;
  padding: 30px clamp(20px, 3.2vw, 48px) 64px;
}
.route-content {
  animation: page-in 180ms ease-out both;
}
@keyframes page-in {
  from { opacity: 0; transform: translateY(4px); }
}
.toolbar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 18px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  padding: 12px;
}
.toolbar input,
.toolbar select {
  width: auto;
  min-width: min(210px, 100%);
}
.toolbar > .button:first-of-type {
  margin-left: auto;
}
.toolbar--actions {
  justify-content: flex-end;
  border: 0;
  background: transparent;
  padding: 0;
}
.toolbar--actions > .button:first-of-type {
  margin-left: 0;
}
.stats-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 14px;
  margin-bottom: 20px;
}
.stat-card,
.panel,
.empty-state {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
}
.stat-card {
  position: relative;
  min-height: 138px;
  overflow: hidden;
  border-top: 3px solid var(--brand);
  padding: 18px 19px;
  box-shadow: 0 5px 18px rgba(11, 47, 34, 0.05);
}
.stat-card small {
  display: block;
  min-height: 20px;
  color: var(--muted);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.02em;
}
.stat-card strong {
  display: block;
  margin-top: 12px;
  color: var(--brand-strong);
  font-size: clamp(25px, 2.6vw, 32px);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.04em;
  line-height: 1.08;
}
.stat-card .stat-money-list {
  display: grid;
  gap: 3px;
  margin-top: 0;
  color: inherit;
  font-size: clamp(16px, 1.6vw, 22px);
  font-weight: inherit;
}
.stat-card .stat-money-list > span {
  display: flex;
  align-items: baseline;
  gap: 7px;
  margin-top: 0;
  color: inherit;
  font-size: inherit;
  font-weight: inherit;
}
.stat-card .stat-money-currency {
  min-width: 3ch;
  margin-top: 0;
  color: var(--muted);
  font-size: 0.52em;
  letter-spacing: 0.05em;
}
.stat-card > span:last-child {
  display: inline-block;
  margin-top: 8px;
  color: var(--brand);
  font-size: 10px;
  font-weight: 750;
}
.dashboard-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.7fr) minmax(280px, 0.8fr);
  align-items: start;
  gap: 18px;
}
.panel {
  min-width: 0;
  overflow: hidden;
  box-shadow: 0 5px 18px rgba(11, 47, 34, 0.04);
}
.panel__header {
  display: flex;
  min-height: 62px;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  border-bottom: 1px solid var(--line);
  background: var(--surface-raised);
  padding: 15px 18px;
}
.panel__header h2 {
  min-width: 0;
  flex: 1 1 220px;
  margin: 0;
  color: var(--brand-strong);
  font-size: 16px;
  font-weight: 760;
  letter-spacing: -0.015em;
  overflow-wrap: anywhere;
}
.panel__header .button,
.panel__header a,
.panel__header .icon-button {
  margin-left: auto;
  white-space: nowrap;
}
.panel__body {
  padding: 19px;
}
/* Tables */
.table-wrap {
  max-width: 100%;
  overflow-x: auto;
  overscroll-behavior-inline: contain;
  scrollbar-color: var(--line-strong) var(--surface-raised);
  scrollbar-width: thin;
  -webkit-overflow-scrolling: touch;
}
.data-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-variant-numeric: tabular-nums;
}
.data-table th,
.data-table td {
  border-bottom: 1px solid var(--line);
  padding: 13px 16px;
  text-align: left;
  vertical-align: middle;
  white-space: nowrap;
}
.data-table th {
  position: sticky;
  z-index: 1;
  top: 0;
  background: var(--surface-soft);
  color: var(--muted);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}
.data-table tbody tr {
  transition: background 120ms ease;
}
.data-table tbody tr:hover {
  background: var(--surface-raised);
}
.data-table tbody tr:last-child td {
  border-bottom: 0;
}
.table-primary {
  display: grid;
  max-width: 320px;
  gap: 2px;
}
.table-primary strong,
.table-primary small {
  overflow: hidden;
  text-overflow: ellipsis;
}
.table-primary small {
  color: var(--muted);
  font-size: 11px;
}
/* What is inside a set box on an order line. Indented under the dish name so the kitchen
   reads "box, then its contents" rather than four unrelated rows. */
.order-item-contents {
  display: grid;
  gap: 1px;
  border-inline-start: 2px solid var(--line-strong);
  margin-top: 3px;
  padding-inline-start: 7px;
}
.order-item-contents small {
  overflow: hidden;
  color: var(--muted);
  font-size: 11px;
  text-overflow: ellipsis;
}
.table-action {
  min-height: 34px;
  border: 1px solid var(--line-strong);
  border-radius: 7px;
  background: var(--surface);
  color: var(--brand-strong);
  padding: 6px 10px;
  font-size: 11px;
  font-weight: 720;
  transition: border-color 120ms ease, background 120ms ease, color 120ms ease;
}
.table-action:hover {
  border-color: var(--brand);
  background: var(--brand-soft);
  color: var(--brand-strong);
}
/* Status language */
.status-pill {
  display: inline-flex;
  min-height: 26px;
  align-items: center;
  border: 1px solid var(--line-strong);
  border-left: 3px solid var(--info);
  border-radius: 6px;
  background: var(--info-soft);
  color: var(--info);
  padding: 3px 8px;
  font-size: 9px;
  font-weight: 850;
  letter-spacing: 0.055em;
  line-height: 1.2;
  text-transform: uppercase;
}
/* Green means settled or on track: an accepted order, a payment that landed, food ready to hand
   over. Everything the vocabulary does not name here falls through to the neutral base. */
.status-pill--success,
.status-pill--active,
.status-pill--completed,
.status-pill--confirmed,
.status-pill--paid,
.status-pill--ready {
  border-color: var(--brand-mint);
  border-left-color: var(--brand);
  background: var(--brand-soft);
  color: var(--brand-strong);
}
.status-pill--warning,
.status-pill--pending,
.status-pill--preparing {
  border-color: var(--warning-line);
  border-left-color: var(--warning);
  border-style: dashed;
  background: var(--warning-soft);
  color: var(--warning);
}
.status-pill--danger,
.status-pill--cancelled,
.status-pill--failed {
  border-color: var(--danger-line);
  border-left-color: var(--danger);
  background: var(--danger-soft);
  color: var(--danger-strong);
}
.status-pill--inactive {
  border-color: var(--line-strong);
  border-left-color: var(--muted);
  background: var(--bg-muted);
  color: var(--muted);
}
.activity-icon {
  display: grid;
  width: 36px;
  height: 36px;
  flex: 0 0 auto;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--brand-soft);
  color: var(--brand);
}
.entity-grid {
  /* Without this the columns below and the two breakpoints that step them down never
     applied: the cards laid out as blocks and the `gap` did nothing. */
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
}
.entity-card {
  display: grid;
  min-width: 0;
  grid-template-columns: 82px minmax(0, 1fr);
  gap: 13px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface);
  padding: 12px;
  transition: border-color 140ms ease, box-shadow 140ms ease, transform 140ms ease;
}
.entity-card:hover {
  border-color: var(--line-strong);
  box-shadow: 0 8px 24px rgba(11, 47, 34, 0.08);
  transform: translateY(-1px);
}
.entity-card img,
.entity-image {
  width: 82px;
  height: 82px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface-soft);
  object-fit: cover;
}
.entity-card__copy {
  display: grid;
  min-width: 0;
  align-content: center;
  gap: 4px;
}
.entity-card__copy strong,
.entity-card__copy small,
.entity-card__copy b {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.entity-card__copy strong {
  color: var(--brand-strong);
  font-size: 13px;
}
.entity-card__copy small {
  color: var(--muted);
  font-size: 11px;
}
.entity-card__copy b {
  color: var(--brand);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}
.entity-card__actions {
  display: flex;
  grid-column: 1 / -1;
  flex-wrap: wrap;
  gap: 6px;
  border-top: 1px solid var(--line);
  padding-top: 10px;
}
.entity-card__actions .button,
.entity-card__actions .table-action {
  flex: 1 1 auto;
}
/* Filters */
.segmented {
  display: inline-flex;
  max-width: 100%;
  overflow-x: auto;
  gap: 2px;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: var(--bg-muted);
  padding: 3px;
  scrollbar-width: none;
}
.segmented::-webkit-scrollbar {
  display: none;
}
.segmented button {
  min-height: 34px;
  flex: 0 0 auto;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--muted);
  padding: 0 11px;
  font-size: 11px;
  font-weight: 720;
}
.segmented button:hover {
  color: var(--brand-strong);
}
.segmented button.is-active {
  background: var(--surface);
  color: var(--brand-strong);
  box-shadow: 0 1px 4px rgba(11, 47, 34, 0.12);
}
/* Empty and loading states */
.empty-state {
  display: grid;
  min-height: 260px;
  place-items: center;
  padding: 40px;
  text-align: center;
}
.empty-state > div {
  max-width: 420px;
}
.empty-state strong {
  display: block;
  margin-bottom: 7px;
  color: var(--brand-strong);
  font-size: 18px;
}
.empty-state p {
  margin: 0 0 18px;
  color: var(--muted);
}
.skeleton {
  position: relative;
  overflow: hidden;
  border-radius: 7px;
  background: var(--bg-muted);
}
.skeleton::after {
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.72), transparent);
  content: "";
  transform: translateX(-100%);
  animation: shimmer 1.1s infinite;
}
.skeleton--panel {
  height: 320px;
}
@keyframes shimmer {
  to { transform: translateX(100%); }
}
@media (max-width: 1180px) {
  .stats-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .entity-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (max-width: 760px) {
  .page-container {
    padding: 22px 16px 48px;
  }
  .dashboard-grid {
    grid-template-columns: 1fr;
  }
  .toolbar {
    align-items: stretch;
  }
  .toolbar input,
  .toolbar select {
    width: 100%;
  }
  .toolbar > .button:first-of-type {
    margin-left: 0;
  }
  .panel__header {
    padding: 14px 16px;
  }
}
@media (max-width: 620px) {
  .stats-grid,
  .entity-grid,
  .field-grid {
    grid-template-columns: 1fr;
  }
  .stat-card {
    min-height: 124px;
  }
  input,
  select,
  textarea {
    font-size: 16px;
  }
  .table-action {
    min-height: 42px;
  }
  .data-table th,
  .data-table td {
    padding: 12px 13px;
  }
  .empty-state {
    min-height: 210px;
    padding: 28px 18px;
  }
}
@media (max-width: 420px) {
  .login-layout {
    align-items: start;
    padding: 12px;
  }
  .login-card {
    margin-block: auto;
    padding: 26px 20px;
  }
  .brand-logo--login {
    width: 64px;
    height: 64px;
    margin-bottom: 22px;
  }
  .page-container {
    padding-inline: 12px;
  }
  .toolbar {
    padding: 10px;
  }
  .toolbar > .button {
    width: 100%;
  }
  .entity-card {
    grid-template-columns: 72px minmax(0, 1fr);
  }
  .entity-card img,
  .entity-image {
    width: 72px;
    height: 72px;
  }
}
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    scroll-behavior: auto !important;
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
  }
}
@media (prefers-contrast: more), (forced-colors: active) {
  .login-card,
  .stat-card,
  .panel,
  .toolbar,
  .entity-card {
    box-shadow: none;
  }
  .status-pill,
  .button,
  .table-action,
  input,
  select,
  textarea {
    border-width: 2px;
  }
}

/* ── Brand voice ─────────────────────────────────────────────────────────────
   Headings and figures in the display face, body copy left in the UI sans where
   density and legibility matter more than character. */
.topbar h1,
.login-card h1,
.sidebar__brand strong,
.panel__header h2,
.stat-card strong,
.entity-card__copy strong,
.empty-state strong {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.01em;
}
.topbar h1 {
  font-size: clamp(19px, 1.6vw, 24px);
}
.panel__header h2 {
  font-size: 17px;
}
/* Figures the operator compares down a column: one glyph width, so the digits line up
   and a changed total is visible as a changed shape. */
.stat-card strong,
.data-table td,
.money,
.ops-metric__copy strong {
  font-variant-numeric: tabular-nums;
}
.stat-card strong,
.ops-metric__copy strong {
  font-family: var(--font-display);
}

/* ── Icon discs ──────────────────────────────────────────────────────────────
   The storefront marks a category with a filled terracotta disc and a white glyph.
   Pale rounded squares here were the same idea drawn in a different language. */
.activity-icon {
  border-radius: 50%;
  background: var(--brand-accent);
  color: #ffffff;
}
.activity-icon svg {
  color: #ffffff;
}

/* ── Action hierarchy ────────────────────────────────────────────────────────
   Row actions used to be one weight, so a card with five of them read as a wall
   rather than as a choice. One action leads; the rest recede until wanted. */
.table-action--primary {
  border-color: var(--brand);
  background: var(--brand);
  color: #ffffff;
}
.table-action--primary:hover:not(:disabled) {
  border-color: var(--brand-strong);
  background: var(--brand-strong);
}
.table-action--quiet {
  border-color: transparent;
  background: transparent;
  color: var(--muted);
}
.table-action--quiet:hover:not(:disabled) {
  border-color: var(--line-strong);
  background: var(--bg-muted);
  color: var(--ink);
}

/* ── Entity cards ────────────────────────────────────────────────────────────
   Status and action are different kinds of thing and now sit in different rows:
   what is true about the dish, then what can be done to it. */
/* Both rows span the whole card. Left in the implicit flow they landed in the 82px
   thumbnail column, which is why two short pills stacked instead of sitting side by
   side — the container, not the content, was the constraint. */
.entity-card__status,
.entity-card__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  grid-column: 1 / -1;
  gap: 6px;
}
.entity-card__status {
  margin-block-start: -4px;
}
.entity-card__actions {
  border-block-start: 1px solid var(--line);
  padding-block-start: 9px;
}
.entity-card__copy b {
  font-family: var(--font-display);
  font-size: 15px;
  font-variant-numeric: tabular-nums;
}

/* ── Kategoriyalar ───────────────────────────────────────────────────────────
   A row action is sometimes a link — a dish is edited on the catalog page, not
   where it is listed. An inline anchor ignores min-height and vertical padding,
   so the class has to draw the box itself or the target collapses to text height. */
a.table-action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
}
/* This page is worked from a phone, where the 34px row action of a desk-bound table is
   a miss as often as a hit. 44px is the smallest target a thumb lands on reliably; it is
   scoped to the route so the denser tables elsewhere keep their rhythm. */
[data-route="categories"] .button,
[data-route="categories"] .table-action {
  min-height: 44px;
}
/* A category has a glyph name and a sort order where a dish has a photo, so the 82px
   thumbnail column would only leave a hole. */
.entity-card--category {
  grid-template-columns: minmax(0, 1fr);
}
/* The selected card is the source of the dish list below it; without the tie the panel
   reads as a second, unrelated list. */
.entity-card--category.is-selected,
[data-route="sets"] .entity-card.is-selected {
  border-color: var(--brand);
  box-shadow: inset 0 0 0 1px var(--brand);
}
/* A set has no photo of its own on this page either — the wells and their dish lists are
   what the operator reads. Same 44px targets as the categories page, for the same reason:
   this is edited from a phone in the restaurant. */
[data-route="sets"] .entity-card {
  grid-template-columns: minmax(0, 1fr);
}
[data-route="sets"] .button,
[data-route="sets"] .table-action {
  min-height: 44px;
}
/* One well inside the set panel. Indented and quieter than the page-level panel so the
   nesting is visible without a second border weight competing with the table inside it. */
.panel--nested {
  border-radius: 10px;
  margin-bottom: 12px;
}
.panel--nested:last-child {
  margin-bottom: 0;
}
.panel--nested .panel__header {
  min-height: 52px;
  gap: 8px;
  padding: 10px 14px;
}
.panel--nested .panel__header h3 {
  min-width: 0;
  flex: 1 1 180px;
  margin: 0;
  color: var(--brand-strong);
  font-size: 15px;
  font-weight: 760;
  overflow-wrap: anywhere;
}
.panel--nested .panel__body {
  padding: 12px 14px;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ── A card you press, not a card with a row of buttons under it ─────────────
   The catalogue used to end every card with Tahrirlash · Rasm · Filiallar · Arxivlash.
   Forty-one dishes made a hundred and seventy buttons on one screen, and the four looked
   equally important when only one of them is the thing an operator wants. The card itself
   is the primary action now — a real button, stretched over the card so the keyboard and
   the screen reader reach it the same way a finger does — and the other three moved into
   the ⋯ menu at the corner. */
.entity-card {
  position: relative;
}

.entity-card__open {
  position: absolute;
  z-index: 1;
  border: 0;
  border-radius: inherit;
  background: none;
  inset: 0;
}

.entity-card__open:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

.entity-card:has(.entity-card__open) {
  cursor: pointer;
}

.entity-card__more {
  position: absolute;
  z-index: 2;
  top: 8px;
  right: 8px;
  display: grid;
  width: 32px;
  height: 32px;
  place-items: center;
  border: 1px solid transparent;
  border-radius: 9px;
  background: none;
  color: var(--muted);
  opacity: 0;
  transition: opacity 140ms ease, border-color 140ms ease, background 140ms ease;
}

.entity-card:hover .entity-card__more,
.entity-card__more:focus-visible,
.entity-card__more[aria-expanded='true'] {
  opacity: 1;
}

.entity-card__more:hover,
.entity-card__more[aria-expanded='true'] {
  border-color: var(--line);
  background: var(--bg-muted);
  color: var(--ink);
}

.entity-card__more .ui-icon {
  width: 18px;
  height: 18px;
}

/* Touch has no hover, so on a phone the menu button is simply always there. */
@media (hover: none) {
  .entity-card__more {
    opacity: 1;
  }
}

.action-menu {
  position: fixed;
  z-index: 60;
  display: grid;
  min-width: 208px;
  gap: 2px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface);
  box-shadow: 0 18px 44px rgba(11, 47, 34, 0.18);
  padding: 6px;
}

.action-menu button {
  min-height: 40px;
  border: 0;
  border-radius: 8px;
  background: none;
  padding: 0 10px;
  color: var(--ink);
  font-size: 12px;
  font-weight: 700;
  text-align: start;
}

.action-menu button:hover,
.action-menu button:focus-visible {
  background: var(--bg-muted);
}

.action-menu button[data-tone='danger'] {
  color: var(--danger);
}

.action-menu button[data-tone='danger']:hover,
.action-menu button[data-tone='danger']:focus-visible {
  background: rgba(180, 35, 24, 0.08);
}

/* The primary action sits at the far end of the same row as the filters — a second toolbar
   underneath was a whole row of chrome to hold one button. */
.toolbar__end {
  margin-inline-start: auto;
}

/* A long dish name must stop before the ⋯ button, not run underneath it. */
.entity-card:has(.entity-card__more) .entity-card__copy strong {
  padding-inline-end: 26px;
}

/* A row action reduced to its ⋯ glyph. Square, so it does not read as a truncated label. */
.table-action--icon {
  display: inline-grid;
  width: 34px;
  min-width: 34px;
  height: 34px;
  place-items: center;
  padding: 0;
}

.table-action--icon .ui-icon {
  width: 17px;
  height: 17px;
}

/* On the sets page the card is not itself a button, so its ⋯ has nothing to hover out of. */
[data-route='sets'] .entity-card__more {
  opacity: 1;
}

/* ── The action menu on a phone ──────────────────────────────────────────────
   A popover anchored to a card near the bottom of a 568px screen had nowhere to open:
   its last item sat below the fold and nothing scrolled it into view. At phone widths it
   is a sheet on the bottom edge instead — always reachable, always thumb-sized. */
@media (max-width: 620px) {
  .action-menu {
    top: auto;
    right: 8px;
    bottom: max(8px, env(safe-area-inset-bottom));
    left: 8px;
    max-height: 60vh;
    overflow-y: auto;
    border-radius: 16px;
    padding: 8px;
  }

  .action-menu button {
    min-height: 52px;
    padding: 0 14px;
    font-size: 14px;
  }
}

/* A 32px glyph is a desktop hover target. A thumb needs the whole 44. */
@media (hover: none), (max-width: 620px) {
  .entity-card__more {
    width: 44px;
    height: 44px;
  }

  .table-action--icon {
    width: 44px;
    min-width: 44px;
    height: 44px;
  }
}

/* ── Toolbars on a phone ─────────────────────────────────────────────────────
   At 320px the filter row stacked into four full-width bands — search, category,
   Qidirish, Yangi taom — and pushed the first dish nearly off the screen. The two
   buttons share a line instead; `margin-inline-start: auto` is what forced the break,
   since an auto margin claims the rest of the line and wraps whatever follows. */
@media (max-width: 620px) {
  .toolbar {
    margin-bottom: 12px;
    gap: 8px;
    padding: 10px;
  }

  .toolbar input,
  .toolbar select {
    width: 100%;
    min-width: 0;
  }

  .toolbar > .button:first-of-type,
  .toolbar__end {
    margin-inline-start: 0;
    margin-left: 0;
  }

  .toolbar .button {
    min-width: 0;
    min-height: 44px;
    flex: 1 1 40%;
  }
}

/* ── One rule for thumb-sized controls, instead of one per page ──────────────
   Three pages had already been given 44px targets by hand, scoped to their route, because
   each was reported separately from a phone. Everything else kept the 34px row action and
   the 34px segmented tab of a desk-bound table — Restoran, Mijozlar, Sozlamalar and the
   dashboard's queue buttons all miss under a thumb. The panel is worked standing up in a
   restaurant, so below the phone breakpoint every control clears 44 without being asked. */
@media (max-width: 620px) {
  .button,
  .table-action,
  .segmented button,
  .ops-panel__action {
    min-height: 44px;
  }

  .ops-queue__action {
    width: 44px;
    height: 44px;
  }
}
