/* Global styles for Aamrapali Manager. Brand variables live here so every
   screen reuses the same palette instead of hardcoding colors. */

:root {
  --color-primary: #8B1A1A;
  --color-accent: #E8A33D;
  --color-bg: #FBF8F3;
  --color-wood: #7A5C3E;
  --color-bamboo: #E9DEC7;
  --color-success: #4F7A52;
  --color-error: #B33F32;
}

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  min-height: 100vh;
  font-family: sans-serif;
  background: var(--color-bg);
  color: var(--color-wood);
}

#app {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 16px;
}

/* ─── SHARED / REUSABLE PATTERNS ─────────────────────────────
   Generic building blocks every screen can reuse — not specific to any
   one screen. Combine with a screen's own layout class, e.g.
   class="home-header card-elevated". */

/* Raised white surface — the default "card" look going forward, in
   place of the old flat bamboo-tan bordered boxes. */
.card-elevated {
  background: #FFFFFF;
  border-radius: 14px;
  box-shadow: 0 2px 8px rgba(60, 40, 20, 0.06);
}

/* Small icon container, e.g. sitting above a label on a nav tile. */
.icon-badge {
  width: 44px;
  height: 44px;
  border-radius: 12px;
  background: var(--color-bamboo);
  color: var(--color-primary);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.icon-badge svg {
  width: 22px;
  height: 22px;
}

/* Small rounded badge for showing a user's role next to their name. */
.role-pill {
  display: inline-block;
  background: var(--color-bamboo);
  color: var(--color-wood);
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: capitalize;
  padding: 2px 10px;
  border-radius: 999px;
  margin-top: 4px;
}

/* Small circular icon button — language toggle, log out, and similar
   header actions across every screen. */
.btn-icon {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: #FFFFFF;
  border: none;
  box-shadow: 0 2px 8px rgba(60, 40, 20, 0.08);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.1rem;
  color: var(--color-primary);
  cursor: pointer;
}

.btn-icon svg {
  width: 20px;
  height: 20px;
}

.btn-icon:hover,
.btn-icon:focus-visible {
  background: var(--color-bamboo);
  outline: none;
}

/* Primary/secondary/danger action buttons — reused anywhere a screen
   needs a call-to-action, a lesser alternative action, or a destructive
   one (cancel/delete). */
.btn-primary,
.btn-secondary,
.btn-danger {
  border: none;
  border-radius: 10px;
  padding: 11px 20px;
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}

.btn-primary {
  background: var(--color-primary);
  color: #FFFFFF;
}

.btn-primary:disabled {
  opacity: 0.6;
  cursor: default;
}

.btn-secondary {
  background: var(--color-bamboo);
  color: var(--color-wood);
}

.btn-danger {
  background: var(--color-error);
  color: #FFFFFF;
}

.btn-danger:disabled {
  opacity: 0.6;
  cursor: default;
}

/* Plain text-style back/nav link, used above a card instead of inside it. */
.btn-back-link {
  background: none;
  border: none;
  color: var(--color-wood);
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
  padding: 4px 0;
  text-align: left;
}

.btn-back-link:hover,
.btn-back-link:focus-visible {
  color: var(--color-primary);
  outline: none;
}

/* Generic form field styling — label above input, reused by any screen
   with a data-entry form. */
.form-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  text-align: left;
}

.form-label {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--color-wood);
}

.form-input {
  font-size: 1rem;
  padding: 10px 12px;
  border-radius: 10px;
  border: 1px solid var(--color-wood);
  background: #FFFFFF;
  color: var(--color-wood);
}

.form-input:focus {
  outline: 2px solid var(--color-accent);
  outline-offset: 1px;
}

/* Small explanatory text under a form field. */
.field-hint {
  font-size: 0.78rem;
  color: var(--color-wood);
  opacity: 0.85;
}

/* Centered muted message for an empty list/grid. */
.empty-state {
  padding: 40px 16px;
  text-align: center;
  color: var(--color-wood);
  font-size: 0.95rem;
}

.empty-state .btn-primary {
  margin-top: 14px;
}

/* "Type X to confirm" box for destructive actions (cancel order, delete
   category, etc.) — the same pattern the backend's EXECUTE_ARCHIVE
   confirmation phrase check exists to support on the server side. */
.confirm-type-box {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px;
  border-radius: 10px;
  background: var(--color-bg);
}

.confirm-type-warning {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--color-error);
}

.confirm-type-actions {
  display: flex;
  gap: 10px;
  justify-content: flex-end;
}

/* Generic form container card — name/detail forms across screens. */
.form-card {
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  max-width: 420px;
  text-align: left;
}

/* Small rounded status badge — e.g. flags on a list row. Combine with a
   color variant. */
.badge {
  display: inline-block;
  font-size: 0.7rem;
  font-weight: 700;
  padding: 3px 10px;
  border-radius: 999px;
}

.badge-accent {
  background: var(--color-accent);
  color: #FFFFFF;
}

.badge-neutral {
  background: var(--color-bamboo);
  color: var(--color-wood);
}

.badge-success {
  background: var(--color-success);
  color: #FFFFFF;
}

/* Multi-select toggle button (independent on/off flags in a form, unlike
   the mutually-exclusive .order-type-toggle-btn pattern). */
.toggle-btn {
  border: 1px solid var(--color-wood);
  background: #FFFFFF;
  color: var(--color-wood);
  border-radius: 10px;
  padding: 10px 14px;
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
}

.toggle-btn.active {
  background: var(--color-bamboo);
  border-color: var(--color-primary);
  color: var(--color-primary);
}

/* Generic inline error text, e.g. under a form or list header. */
.error-text {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--color-error);
  text-align: center;
}

/* Simple tab switcher. */
.tab-bar {
  display: flex;
  gap: 8px;
}

.tab-bar-btn {
  border: none;
  background: var(--color-bamboo);
  color: var(--color-wood);
  border-radius: 10px;
  padding: 10px 18px;
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
}

.tab-bar-btn.active {
  background: var(--color-primary);
  color: #FFFFFF;
}

/* ─── LOGIN SCREEN ────────────────────────────────────────── */

.screen-login {
  width: 100%;
  display: flex;
  justify-content: center;
}

.login-card {
  background: var(--color-bamboo);
  border: 1px solid var(--color-wood);
  border-radius: 16px;
  padding: 32px 24px;
  width: 100%;
  max-width: 340px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
}

.login-header {
  text-align: center;
}

.restaurant-name-np {
  font-size: 1.4rem;
  font-weight: 700;
  color: var(--color-primary);
}

.restaurant-name-en {
  font-size: 0.95rem;
  color: var(--color-wood);
  margin-top: 4px;
}

.pin-dots {
  display: flex;
  gap: 16px;
  align-items: center;
  justify-content: center;
  min-height: 28px;
}

.pin-dot {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 2px solid var(--color-primary);
  background: transparent;
  transition: background 0.15s ease;
}

.pin-dot.filled {
  background: var(--color-accent);
  border-color: var(--color-accent);
}

.pin-dots.shake {
  animation: pin-shake 0.4s ease;
}

@keyframes pin-shake {
  10%, 90% { transform: translateX(-2px); }
  20%, 80% { transform: translateX(4px); }
  30%, 50%, 70% { transform: translateX(-8px); }
  40%, 60% { transform: translateX(8px); }
}

.pin-loading {
  color: var(--color-primary);
  font-size: 1.2rem;
  letter-spacing: 2px;
}

.login-error {
  font-size: 0.9rem;
  font-weight: 600;
  text-align: center;
  color: var(--color-error);
  min-height: 1.2em;
}

/* Shown only after a device/location rejection (Prompt 46) — a wrong PIN
   or a network error never shows this. */
.login-override-link {
  border: none;
  background: none;
  color: var(--color-primary);
  font-weight: 700;
  font-size: 0.85rem;
  text-decoration: underline;
  cursor: pointer;
  padding: 4px;
  margin-top: -8px;
}

.login-override-wrap {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 14px;
  text-align: center;
}

.login-override-title {
  font-weight: 700;
  color: var(--color-primary);
}

.login-override-input {
  text-align: center;
  font-size: 1.3rem;
  letter-spacing: 4px;
}

.login-override-actions {
  justify-content: center;
}

.numpad {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
  width: 100%;
}

.numpad-btn {
  font-size: 1.3rem;
  font-weight: 600;
  padding: 16px 0;
  border-radius: 12px;
  border: 1px solid var(--color-wood);
  background: var(--color-bg);
  color: var(--color-primary);
  cursor: pointer;
}

.numpad-btn:active {
  background: var(--color-primary);
  color: var(--color-bg);
}

.numpad-clear,
.numpad-backspace {
  font-size: 1rem;
  color: var(--color-wood);
}

/* ─── HOME SCREEN ─────────────────────────────────────────── */

.screen-home {
  width: 100%;
  max-width: 640px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 24px;
  text-align: left;
}

.home-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 18px 22px;
}

.home-restaurant-name {
  font-size: 1.3rem;
  font-weight: 800;
  color: var(--color-primary);
}

.home-user-name {
  font-size: 0.9rem;
  color: var(--color-wood);
  margin-top: 4px;
}

.home-header-actions {
  display: flex;
  align-items: center;
  gap: 10px;
}

.home-nav-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 16px;
}

.home-nav-btn {
  border: none;
  border-radius: 14px;
  padding: 22px 14px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  cursor: pointer;
  transition: transform 0.1s ease, box-shadow 0.15s ease;
}

.home-nav-label {
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--color-wood);
  text-align: center;
}

.home-nav-btn:hover,
.home-nav-btn:focus-visible {
  transform: translateY(-2px);
  box-shadow: 0 4px 14px rgba(60, 40, 20, 0.14);
  outline: none;
}

.home-nav-btn:active {
  transform: translateY(0);
  background: var(--color-bamboo);
}

/* ─── ORDERS BOARD ────────────────────────────────────────── */

.screen-orders {
  width: 100%;
  max-width: 900px;
  margin: 0 auto;
}

.orders-board-wrap,
.orders-subview-wrap {
  display: flex;
  flex-direction: column;
  gap: 16px;
  text-align: left;
}

.today-summary-strip {
  display: flex;
  gap: 24px;
  padding: 16px 22px;
}

.today-summary-stat {
  display: flex;
  flex-direction: column;
}

.today-summary-value {
  font-size: 1.3rem;
  font-weight: 800;
  color: var(--color-primary);
}

.today-summary-label {
  font-size: 0.8rem;
  color: var(--color-wood);
}

/* Persistent low/out-of-stock banner (Prompt 27) — no dismiss control by
   design; visibility is driven entirely by ordersState.lowStock having
   entries. Red and amber are two separate strips, never blended into
   one, so "out of stock" and "getting low" stay visually distinct at a
   glance. */
.low-stock-banner {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px;
  padding: 12px 18px;
  border-radius: 12px;
  font-size: 0.9rem;
  color: #FFFFFF;
}

.low-stock-banner + .low-stock-banner {
  margin-top: -6px;
}

.low-stock-banner-red {
  background: var(--color-error);
}

.low-stock-banner-amber {
  background: var(--color-accent);
}

.low-stock-banner-label {
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  font-size: 0.78rem;
  flex-shrink: 0;
}

.low-stock-banner-items {
  font-weight: 600;
}

.orders-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
  padding: 16px 22px;
}

.orders-header-title {
  font-size: 1.2rem;
  font-weight: 800;
  color: var(--color-primary);
}

.orders-header-controls {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.orders-search-input {
  min-width: 180px;
}

.orders-error {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--color-error);
  text-align: center;
}

.orders-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 16px;
}

.order-card {
  border: none;
  border-radius: 14px;
  padding: 18px;
  width: 100%;
  max-width: 270px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  cursor: pointer;
  text-align: left;
  transition: transform 0.1s ease, box-shadow 0.15s ease;
}

.order-card:hover,
.order-card:focus-visible {
  transform: translateY(-2px);
  box-shadow: 0 4px 14px rgba(60, 40, 20, 0.14);
  outline: none;
}

.order-card-type-badge {
  display: inline-block;
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 3px 10px;
  border-radius: 999px;
}

.order-card-type-badge.type-dinein {
  background: var(--color-bamboo);
  color: var(--color-wood);
}

.order-card-type-badge.type-takeaway {
  background: var(--color-accent);
  color: #FFFFFF;
}

.order-card-identity {
  font-size: 1.3rem;
  font-weight: 800;
  color: var(--color-primary);
}

.order-card-meta {
  font-size: 0.85rem;
  color: var(--color-wood);
}

.order-detail-card,
.new-order-card {
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  max-width: 420px;
}

.order-detail-row {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  font-size: 0.95rem;
  border-bottom: 1px solid var(--color-bamboo);
  padding-bottom: 8px;
}

.order-detail-label {
  color: var(--color-wood);
  font-weight: 600;
}

.order-detail-value {
  color: var(--color-primary);
  font-weight: 700;
}

/* ─── Order detail: editable table number, dine-in only (Prompt 19) ─── */

.order-detail-value-with-edit {
  display: flex;
  align-items: center;
  gap: 10px;
}

.order-detail-edit-form {
  display: flex;
  align-items: center;
  gap: 6px;
}

.order-detail-edit-input {
  width: 90px;
  padding: 6px 8px;
}

/* Wider variant for values that don't fit a table number's width — the
   customer phone field (Prompt 22). */
.order-detail-edit-input-wide {
  width: 140px;
}

.order-detail-value-empty {
  color: var(--color-wood);
  font-weight: 600;
  opacity: 0.7;
}

.order-detail-edit-form .btn-icon {
  width: 32px;
  height: 32px;
  font-size: 0.9rem;
  box-shadow: none;
  border: 1px solid var(--color-bamboo);
}

.form-section-title {
  font-size: 1.1rem;
  font-weight: 800;
  color: var(--color-primary);
}

.order-type-toggle {
  display: flex;
  gap: 10px;
}

.order-type-toggle-btn {
  flex: 1;
  border: 1px solid var(--color-wood);
  background: #FFFFFF;
  color: var(--color-wood);
  border-radius: 10px;
  padding: 10px;
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
}

.order-type-toggle-btn.active {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: #FFFFFF;
}

.token-preview {
  font-size: 1.4rem;
  font-weight: 800;
  color: var(--color-primary);
  letter-spacing: 0.04em;
}

.form-actions {
  display: flex;
  justify-content: flex-end;
}

/* ─── Order detail: item summary + menu picker (Prompt 13) ─── */

.order-summary-card,
.menu-picker-card {
  padding: 20px 22px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

/* ─── Order detail: two-column desktop layout (Prompt 15) ───
   Below 1100px this is just a plain flex column (identical spacing to
   the old flat stack of cards). At 1100px+ — deliberately past tablet
   landscape width so tablets keep the stacked layout — it becomes a
   grid: left column is the customer info card directly above the menu
   picker, right column is the sticky running order summary directly
   above the Cancel Order card (Prompt 15B). Pure layout; no
   markup/behavior other than the grid-area hooks changes. */
.order-detail-grid {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

@media (min-width: 1100px) {
  .order-detail-grid {
    display: grid;
    grid-template-columns: 2fr 1fr;
    grid-template-areas:
      "info summary"
      "picker cancel";
    align-items: start;
    gap: 20px;
  }

  .order-detail-info { grid-area: info; }
  .menu-picker-card { grid-area: picker; }
  .order-detail-cancel { grid-area: cancel; }

  /* Cards in this grid should fill their column, not stay capped at
     the narrow mobile width shared with .new-order-card. */
  .order-detail-grid .order-detail-card {
    max-width: none;
  }

  .order-summary-card {
    grid-area: summary;
    position: sticky;
    top: 20px;
  }
}

/* Capped + internally scrollable (same pattern as
   .menu-picker-category-list) so a long order — 10, 20+ items — can't
   push the total row, the menu picker, or the Complete & Take Payment /
   Cancel Order buttons an arbitrary distance down the page. Those stay
   reachable without scrolling past the whole item list first. */
.order-line-items {
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-height: 420px;
  overflow-y: auto;
}

.order-line-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--color-bamboo);
}

.order-line-item-name {
  flex: 1;
  font-weight: 600;
  color: var(--color-primary);
}

.order-line-item-controls {
  display: flex;
  align-items: center;
  gap: 6px;
}

.order-line-qty-btn {
  width: 28px;
  height: 28px;
  font-size: 0.95rem;
  box-shadow: none;
  border: 1px solid var(--color-bamboo);
}

.order-line-qty {
  min-width: 20px;
  text-align: center;
  font-weight: 700;
  color: var(--color-wood);
}

.order-line-item-price {
  min-width: 64px;
  text-align: right;
  font-weight: 600;
  color: var(--color-wood);
  font-size: 0.9rem;
}

.order-line-remove-btn {
  width: 28px;
  height: 28px;
  font-size: 0.85rem;
  box-shadow: none;
  border: 1px solid var(--color-bamboo);
}

/* ─── Order detail: per-item delivery tracking (Prompt 18) ─── */

.order-line-item-delivered {
  opacity: 0.7;
}

.order-line-deliver-btn {
  width: 28px;
  height: 28px;
  font-size: 1rem;
  box-shadow: none;
  border: 1px solid var(--color-bamboo);
  flex-shrink: 0;
}

.order-line-delivered-check {
  width: 28px;
  height: 28px;
  font-size: 0.95rem;
  box-shadow: none;
  border: 1px solid var(--color-success);
  color: #FFFFFF;
  background: var(--color-success);
  flex-shrink: 0;
}

.order-line-divider {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-wood);
  padding-top: 4px;
  margin-top: 2px;
  border-top: 1px dashed var(--color-bamboo);
}

.order-line-undo-confirm {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
}

.order-line-undo-label {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--color-wood);
  white-space: nowrap;
}

.order-line-undo-confirm-btn,
.order-line-undo-cancel-btn {
  width: 26px;
  height: 26px;
  font-size: 0.85rem;
  box-shadow: none;
  flex-shrink: 0;
}

.order-line-undo-confirm-btn {
  border: 1px solid var(--color-success);
  color: var(--color-success);
}

.order-line-undo-cancel-btn {
  border: 1px solid var(--color-error);
  color: var(--color-error);
}

.order-total-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-top: 10px;
  border-top: 2px solid var(--color-bamboo);
  font-weight: 700;
  color: var(--color-primary);
}

.order-total-value {
  font-size: 1.2rem;
}

/* ─── Payment (Orders Board Phase 3, Prompt 22) ─────────────── */
/* Full-screen modal (Prompt 26) — see renderPaymentModal()/
   openPaymentModal()/closePaymentModal() in orders.js. */

.payment-modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(43, 28, 15, 0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  /* Above everything else that uses position:fixed on this screen,
     including the Print Station badge (900, see below). */
  z-index: 1000;
}

.payment-modal {
  width: 100%;
  max-width: 480px;
  max-height: calc(100vh - 40px);
  overflow-y: auto;
  padding: 28px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.payment-modal .order-type-toggle {
  margin-top: 4px;
}

.quick-amount-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.quick-amount-btn {
  padding: 8px 14px;
  font-size: 0.85rem;
}

/* The real Fonepay QR (Prompt 32 — was a dashed-border text placeholder
   before). Deliberately large (Prompt 26's main point still applies):
   the modal gives it room a small inline panel never had, so it should
   read as the focal point of the QR path, not an afterthought. */
.qr-image-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  border-radius: 12px;
  background: #FFFFFF;
}

.qr-real-image {
  width: 100%;
  max-width: 320px;
  height: auto;
  border-radius: 8px;
}

/* ─── Bill Summary (Prompt 22) ───────────────────────────────── */

.bill-summary-card {
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  max-width: 480px;
}

.bill-summary-header {
  text-align: center;
  margin-bottom: 4px;
}

.bill-summary-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-width: 480px;
}

.bill-summary-actions .btn-primary {
  display: inline-block;
  text-align: center;
  text-decoration: none;
}

.menu-picker-category-list {
  display: flex;
  flex-direction: column;
  gap: 18px;
  max-height: 480px;
  overflow-y: auto;
}

.menu-picker-category-name {
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--color-primary);
  margin-bottom: 8px;
}

.menu-picker-tile-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
  gap: 10px;
}

.menu-picker-tile {
  position: relative;
  border: 1px solid var(--color-bamboo);
  background: #FFFFFF;
  border-radius: 12px;
  padding: 12px 10px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  cursor: pointer;
  text-align: left;
}

.menu-picker-tile:hover,
.menu-picker-tile:focus-visible {
  border-color: var(--color-primary);
  outline: none;
}

.menu-picker-tile-name {
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--color-primary);
}

.menu-picker-tile-meta {
  font-size: 0.78rem;
  color: var(--color-wood);
}

.menu-picker-tile-oos {
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--color-error);
}

/* Live remaining-stock count on a picker tile (Prompt 31) — only ever
   shown for track_inventory items with stock > 0; exactly 0 keeps the
   existing .menu-picker-tile-oos treatment above instead. Same
   green/amber semantics as the low-stock banner. */
.menu-picker-tile-stock {
  display: inline-block;
  align-self: flex-start;
  font-size: 0.72rem;
  font-weight: 800;
  padding: 2px 7px;
  border-radius: 999px;
  color: #FFFFFF;
}

.menu-picker-tile-stock.stock-badge-green {
  background: var(--color-success);
}

.menu-picker-tile-stock.stock-badge-amber {
  background: var(--color-accent);
}

/* Visibly disabled, not just a subtle color shift — greyscale + reduced
   opacity + no pointer, so out-of-stock items are unmistakable at a glance. */
.menu-picker-tile:disabled {
  cursor: not-allowed;
  opacity: 0.5;
  filter: grayscale(1);
  border-color: var(--color-bamboo);
}

/* Shared sticky quick-add surface — used by both the variant picker and
   search results (Prompt 14). Stays open across repeated taps; each tile
   inside gets a live count badge via .quick-add-count-badge. */
.quick-add-panel {
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  background: var(--color-bg);
  border: 2px solid var(--color-accent);
}

.quick-add-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.quick-add-panel-title {
  font-weight: 700;
  color: var(--color-primary);
}

.quick-add-count-badge {
  position: absolute;
  top: -8px;
  right: -8px;
  min-width: 20px;
  height: 20px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--color-primary);
  color: #FFFFFF;
  font-size: 0.72rem;
  font-weight: 800;
  display: flex;
  align-items: center;
  justify-content: center;
}

.order-summary-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.save-status-indicator {
  font-size: 0.78rem;
  font-weight: 600;
}

.save-status-saving {
  color: var(--color-wood);
}

.save-status-saved {
  color: var(--color-success);
}

.save-status-error {
  color: var(--color-error);
}

/* ─── MENU MANAGEMENT ─────────────────────────────────────── */

.screen-menu-mgmt {
  width: 100%;
  max-width: 720px;
  margin: 0 auto;
}

.menu-mgmt-wrap {
  display: flex;
  flex-direction: column;
  gap: 16px;
  text-align: left;
}

.section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
  padding: 16px 22px;
}

.section-header-title {
  font-size: 1.2rem;
  font-weight: 800;
  color: var(--color-primary);
}

.category-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.category-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
  padding: 16px 20px;
}

.category-row-main {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.category-row-name {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--color-primary);
}

.category-row-subname {
  font-size: 0.85rem;
  color: var(--color-wood);
}

.category-row-badges {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.category-actions {
  display: flex;
  gap: 10px;
  flex-shrink: 0;
}

.category-checking {
  font-size: 0.85rem;
  color: var(--color-wood);
  font-style: italic;
}

.toggle-group {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

/* ─── Items tab: collapsible category sections ─── */

.category-section-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.category-section {
  padding: 0;
  overflow: hidden;
}

.category-section-header {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 10px;
  border: none;
  background: none;
  padding: 16px 20px;
  cursor: pointer;
  text-align: left;
  font: inherit;
}

.category-section-name {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--color-primary);
  flex: 1;
}

.category-section-count {
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--color-wood);
  background: var(--color-bamboo);
  border-radius: 999px;
  padding: 2px 10px;
}

.category-section-chevron {
  color: var(--color-wood);
  font-size: 0.9rem;
}

.category-section-empty {
  padding: 0 20px 16px;
  color: var(--color-wood);
  font-size: 0.85rem;
  font-style: italic;
}

.item-list {
  display: flex;
  flex-direction: column;
}

.item-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
  padding: 14px 20px;
  border-top: 1px solid var(--color-bamboo);
}

.item-row-main {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.item-row-name {
  font-size: 1rem;
  font-weight: 700;
  color: var(--color-primary);
}

.item-row-subname {
  font-size: 0.8rem;
  color: var(--color-wood);
}

.item-row-price {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--color-wood);
}

.item-row-stock {
  font-size: 0.8rem;
  color: var(--color-wood);
}

.item-row-badges {
  display: flex;
  gap: 6px;
}

.tab-placeholder-wrap {
  display: flex;
  justify-content: center;
}

/* ─── RECIPES TAB (Prompt 40) ─────────────────────────────────── */

/* The whole dish row is a clickable <button> (opens the recipe editor),
   unlike .item-row elsewhere which just holds separate Edit/Delete
   buttons — these two rules strip the native button chrome so it reads
   identically to a plain .item-row. */
.recipe-dish-row {
  width: 100%;
  border: none;
  background: none;
  cursor: pointer;
  text-align: left;
  font: inherit;
}

.recipe-dish-row:hover,
.recipe-dish-row:focus-visible {
  background: var(--color-bg);
  outline: none;
}

.recipe-dish-reason {
  font-size: 0.78rem;
  color: var(--color-wood);
  opacity: 0.85;
  margin-top: 2px;
}

.recipe-editor-header {
  gap: 10px;
}

.recipe-status-row {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

.recipe-current-cost {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--color-wood);
}

.recipe-row-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 16px;
}

.recipe-row {
  padding: 16px 18px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.recipe-row-qty {
  display: flex;
  gap: 12px;
}

.recipe-row-qty .form-field {
  flex: 1;
}

.recipe-search-results {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 6px;
}

.recipe-linked-chip {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 12px;
  border-radius: 10px;
  background: var(--color-bamboo);
}

.recipe-linked-name {
  font-weight: 700;
  color: var(--color-primary);
}

.recipe-also-used {
  font-size: 0.78rem;
  color: var(--color-wood);
  opacity: 0.85;
}

.recipe-editor-actions {
  display: flex;
  justify-content: flex-start;
  margin-top: 4px;
}

/* ─── PLACEHOLDER SCREENS (not built yet) ─────────────────────
   Shared by every screen still awaiting its real implementation
   (see js/screens/placeholderScreen.js). */

.screen-placeholder {
  width: 100%;
  display: flex;
  justify-content: center;
}

.placeholder-card {
  padding: 40px 24px;
  width: 100%;
  max-width: 340px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  text-align: center;
}

.placeholder-title {
  font-size: 1.2rem;
  font-weight: 700;
  color: var(--color-primary);
}

.placeholder-message {
  font-size: 0.95rem;
  color: var(--color-wood);
}

.btn-placeholder-back {
  background: var(--color-primary);
  color: var(--color-bg);
  border: none;
  border-radius: 10px;
  padding: 10px 20px;
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
}

/* ─── DATA MANAGEMENT ─────────────────────────────────────── */

.screen-data-mgmt {
  width: 100%;
  max-width: 640px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 16px;
  text-align: left;
}

.data-mgmt-card {
  padding: 20px 22px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* Plain vertical field stack for a <form> that sits inside a card that
   already has its own padding — .form-card isn't used here since its
   padding/max-width would double up inside .data-mgmt-card. */
.form-stack {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* Cash Movements (Prompt 42B) signed-amount coloring — reuses
   .stock-history-row/.stock-history-row-main for the row layout itself. */
.cm-row-amount {
  font-size: 0.95rem;
  font-weight: 800;
  margin-top: 2px;
}

.cm-amount-positive {
  color: var(--color-success);
}

.cm-amount-negative {
  color: var(--color-error);
}

/* ─── REGISTERED DEVICES / OVERRIDE CODE (Prompt 46) ────────────── */

.device-status-active {
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--color-success);
}

.device-status-revoked {
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--color-error);
}

.device-already-badge {
  color: var(--color-success);
  font-weight: 600;
}

.override-code-display {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 16px;
  border-radius: 10px;
  background: var(--color-bg);
}

.override-code-value {
  font-size: 2rem;
  font-weight: 800;
  letter-spacing: 6px;
  color: var(--color-primary);
}

.toggle-group {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

/* ─── STOCK MANAGER (Prompt 33 — Add Entry tab) ───────────────── */

.screen-stock-mgmt {
  width: 100%;
  max-width: 480px;
  margin: 0 auto;
}

.stock-mgmt-wrap {
  display: flex;
  flex-direction: column;
  gap: 16px;
  text-align: left;
}

/* List of live search matches below the search box — Tier 1 (real
   tracked-inventory menu items) and Tier 2 (recent free-text expense
   descriptions) share the same row style, grouped under their own label. */
.stock-search-results {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.stock-search-group-label {
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--color-wood);
  opacity: 0.8;
  margin-top: 4px;
}

.stock-search-result-btn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  text-align: left;
  border: 1px solid var(--color-bamboo);
  background: #FFFFFF;
  border-radius: 10px;
  padding: 10px 14px;
  font: inherit;
  color: var(--color-wood);
  cursor: pointer;
}

.stock-search-result-btn:hover,
.stock-search-result-btn:focus-visible {
  border-color: var(--color-primary);
  outline: none;
}

.stock-search-result-name {
  font-weight: 700;
  color: var(--color-primary);
}

.stock-search-result-meta {
  font-size: 0.78rem;
  color: var(--color-wood);
}

/* Dashed border deliberately distinguishes "create something new" from
   the solid-bordered real matches above it. */
.stock-search-add-new-btn {
  border: 1px dashed var(--color-wood);
  background: var(--color-bg);
  color: var(--color-primary);
  border-radius: 10px;
  padding: 10px 14px;
  font-size: 0.9rem;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
}

.stock-search-add-new-btn:hover,
.stock-search-add-new-btn:focus-visible {
  border-color: var(--color-primary);
  outline: none;
}

/* Generic inline success text — mirrors .error-text. */
.success-text {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--color-success);
  text-align: center;
}

/* ─── STOCK MANAGER (Prompt 35 — Inventory tab) ───────────────── */
/* Same collapsible-section shape as Menu Management's Items tab
   (.category-section/.category-section-header) — one card per item,
   header button toggles a history list below it. */

.stock-inventory-item {
  padding: 0;
  overflow: hidden;
}

.stock-inventory-header {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 10px;
  border: none;
  background: none;
  padding: 16px 20px 4px;
  cursor: pointer;
  text-align: left;
  font: inherit;
}

.stock-inventory-name-block {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1;
}

.stock-inventory-name {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--color-primary);
}

.stock-inventory-subname {
  font-size: 0.85rem;
  color: var(--color-wood);
}

.stock-inventory-count {
  font-size: 0.78rem;
  font-weight: 800;
  color: var(--color-wood);
  background: var(--color-bamboo);
  border-radius: 999px;
  padding: 2px 10px;
  white-space: nowrap;
}

/* Adjust Stock's old->new delta preview (Prompt 50) — plain readout of
   what the entered absolute count actually implies. */
.adjust-stock-delta {
  font-weight: 700;
  color: var(--color-primary);
}

.stock-inventory-last {
  padding: 0 20px 16px;
  font-size: 0.85rem;
  color: var(--color-wood);
}

.stock-history-list {
  display: flex;
  flex-direction: column;
}

.stock-history-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
  padding: 14px 20px;
  border-top: 1px solid var(--color-bamboo);
}

.stock-history-row-main {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.stock-history-row-date {
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--color-primary);
}

.stock-history-row-meta {
  font-size: 0.82rem;
  color: var(--color-wood);
}

.stock-history-row-expiry {
  font-size: 0.76rem;
  color: var(--color-wood);
  opacity: 0.85;
}

.stock-history-row-editing {
  display: block;
}

.stock-history-edit-form {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

/* ─── DASHBOARD (Prompt 36 — Phase 1: KPI cards + recovery bar) ─── */

.screen-dashboard {
  width: 100%;
  max-width: 640px;
  margin: 0 auto;
}

.dashboard-wrap {
  display: flex;
  flex-direction: column;
  gap: 16px;
  text-align: left;
}

.kpi-row {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
}

.kpi-card {
  flex: 1;
  min-width: 140px;
  padding: 18px 16px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.kpi-card-label {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--color-wood);
}

.kpi-card-value {
  font-size: 1.5rem;
  font-weight: 800;
  color: var(--color-primary);
}

.recovery-card {
  padding: 20px 22px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.recovery-track {
  width: 100%;
  height: 14px;
  border-radius: 999px;
  background: var(--color-bamboo);
  overflow: hidden;
}

.recovery-fill {
  height: 100%;
  background: var(--color-success);
  border-radius: 999px;
  transition: width 0.3s ease;
}

.recovery-numbers {
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--color-wood);
}

/* ─── DASHBOARD (Prompt 37 — Phase 2: charts) ─────────────────
   Mobile-first: plain stacked column, same as everywhere else in this
   project. At 900px+ (past tablet portrait, room for two side-by-side
   donut charts to stay legible) it becomes a 2-column grid — same
   responsive approach as .order-detail-grid's 1100px breakpoint, just a
   width tuned to these specific cards rather than the identical value. */
.dashboard-charts-grid {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

@media (min-width: 900px) {
  .dashboard-charts-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-areas:
      "revenue revenue"
      "cashqr  dinein";
    gap: 16px;
  }

  .chart-card-revenue { grid-area: revenue; }
  .chart-card-cashqr { grid-area: cashqr; }
  .chart-card-dinein { grid-area: dinein; }
}

.chart-card {
  padding: 20px 22px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.chart-canvas-wrap {
  position: relative;
  width: 100%;
  height: 240px;
}

.split-chart-body {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}

.split-chart-canvas-wrap {
  position: relative;
  width: 100%;
  max-width: 200px;
  height: 190px;
}

.split-chart-legend {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
}

.split-legend-row {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.88rem;
  color: var(--color-wood);
}

.split-legend-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
}

.split-legend-label {
  font-weight: 600;
  flex: 1;
}

.split-legend-value {
  font-weight: 700;
  color: var(--color-primary);
  white-space: nowrap;
}

/* ─── DASHBOARD (Prompt 38 — Phase 3: insights + profit suggestions) ─── */

.dashboard-insights-grid {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

@media (min-width: 900px) {
  .dashboard-insights-grid {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: 16px;
    align-items: start;
  }
}

.top-items-columns {
  display: flex;
  gap: 20px;
  flex-wrap: wrap;
}

.top-items-col {
  flex: 1;
  min-width: 130px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.top-items-col-title {
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--color-wood);
  opacity: 0.8;
}

.top-items-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  list-style: none;
}

.top-items-row {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.85rem;
}

.top-items-rank {
  font-weight: 800;
  color: var(--color-accent);
  width: 16px;
  flex-shrink: 0;
}

.top-items-name {
  flex: 1;
  color: var(--color-wood);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.top-items-value {
  font-weight: 700;
  color: var(--color-primary);
  white-space: nowrap;
}

.expiring-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  list-style: none;
}

.expiring-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  font-size: 0.88rem;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--color-bamboo);
}

.expiring-row:last-child {
  border-bottom: none;
  padding-bottom: 0;
}

.expiring-name {
  color: var(--color-wood);
  font-weight: 600;
}

.expiring-date {
  color: var(--color-error);
  font-weight: 700;
  white-space: nowrap;
}

.margin-section {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.margin-section-title {
  padding: 0 4px;
}

.margin-card-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.margin-card {
  padding: 18px 20px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.margin-card-name {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--color-primary);
}

.margin-card-subname {
  font-size: 0.85rem;
  color: var(--color-wood);
  margin-top: -6px;
}

.margin-actions {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 6px;
}

/* Prompt 52 — purely informational, next to a manually-typed (never
   Recipe-calculated) cost figure. */
.margin-estimated-note {
  color: var(--color-error);
}

.margin-edit-row {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  align-items: center;
  margin-top: 6px;
}

.margin-edit-input {
  max-width: 140px;
}

/* ─── END OF DAY (Prompt 42D) ──────────────────────────────────
   Step 1 (blind count) shows only .eod-status-card + a plain form — no
   expected figure anywhere. Step 2 (reveal) adds .eod-result-card (color-
   coded by outcome) and a breakdown reusing .order-detail-row. */

.screen-end-of-day {
  width: 100%;
  max-width: 480px;
  margin: 0 auto;
}

.eod-wrap {
  display: flex;
  flex-direction: column;
  gap: 16px;
  text-align: left;
}

.eod-status-card {
  padding: 16px 20px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.eod-status-line {
  font-size: 0.88rem;
  color: var(--color-wood);
}

.eod-result-card {
  padding: 22px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  border-left: 6px solid var(--color-bamboo);
}

.eod-result-match { border-left-color: var(--color-success); }
.eod-result-shortage { border-left-color: var(--color-error); }
.eod-result-surplus { border-left-color: var(--color-accent); }

.eod-result-badge {
  font-size: 1.3rem;
  font-weight: 800;
}

.eod-result-match .eod-result-badge { color: var(--color-success); }
.eod-result-shortage .eod-result-badge { color: var(--color-error); }
.eod-result-surplus .eod-result-badge { color: var(--color-accent); }

.eod-breakdown-total {
  border-top: 2px solid var(--color-bamboo);
  padding-top: 10px;
  margin-top: 4px;
  font-weight: 800;
}

.eod-breakdown-total .order-detail-label,
.eod-breakdown-total .order-detail-value {
  color: var(--color-primary);
}

.eod-qr-card {
  padding: 16px 20px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.eod-qr-label {
  font-size: 0.9rem;
  color: var(--color-wood);
  font-weight: 600;
}

.eod-qr-value {
  font-size: 1.1rem;
  font-weight: 800;
  color: var(--color-wood);
}

/* ─── END OF DAY FOLLOW-UP (Prompt 44) ─────────────────────────
   The 3-option card that replaces the old single "Log Another Count"
   button under the reveal step, plus the Contact Admin box it can
   expand into in place. */

.eod-followup-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.eod-contact-textarea {
  min-height: 84px;
  resize: vertical;
  font-family: inherit;
}

.eod-contact-sent {
  color: var(--color-success);
  font-weight: 700;
  font-size: 0.9rem;
}

/* ─── NOTIFICATION BELL (Prompt 44, split Prompt 47) ────────────
   The bell + unread badge + small preview DROPDOWN (top 5) are mounted
   INSIDE Home's header (admin-only) by js/notifications.js — see that
   file for why. "See all" routes to the separate full-history screen
   (.notif-full-*, further below) instead of expanding in place. The
   severity popup lives OUTSIDE #app, same reasoning as Print Station's
   own badge/receipt hosts. */

.notif-bell-wrap {
  position: relative;
}

.notif-bell-btn {
  position: relative;
}

.notif-bell-badge {
  position: absolute;
  top: -4px;
  right: -4px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--color-error);
  color: #FFFFFF;
  font-size: 0.65rem;
  font-weight: 800;
  line-height: 16px;
  text-align: center;
}

.notif-dropdown-panel {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  width: 360px;
  max-width: 90vw;
  padding: 0;
  display: flex;
  flex-direction: column;
  z-index: 500;
  text-align: left;
}

.notif-dropdown-panel .quick-add-panel-header {
  padding: 14px 16px;
}

.notif-dropdown-list {
  overflow-y: auto;
  max-height: 50vh;
  padding: 4px 12px 8px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.notif-see-all-btn {
  border: none;
  border-top: 1px solid var(--color-bamboo);
  background: none;
  color: var(--color-primary);
  font-weight: 700;
  font-size: 0.85rem;
  padding: 12px 16px;
  cursor: pointer;
  text-align: center;
}

.notif-see-all-btn:hover {
  background: var(--color-bg);
}

.notif-date-separator {
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--color-wood);
  opacity: 0.8;
  padding: 8px 2px 2px;
}

.notif-row {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  padding: 10px;
  border-radius: 10px;
  background: var(--color-bg);
  border-left: 4px solid var(--color-bamboo);
}

.notif-row.severity-high {
  border-left-color: var(--color-error);
}

.notif-row.is-deleted {
  opacity: 0.45;
}

.notif-row-main {
  flex: 1;
  min-width: 0;
}

.notif-row-title {
  font-weight: 700;
  font-size: 0.85rem;
  color: var(--color-primary);
}

.notif-row-body {
  font-size: 0.8rem;
  color: var(--color-wood);
  white-space: pre-wrap;
  word-break: break-word;
}

.notif-row-side {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 6px;
  flex-shrink: 0;
}

.notif-row-time {
  font-size: 0.7rem;
  color: var(--color-wood);
  opacity: 0.75;
}

.notif-row-action {
  border: none;
  background: none;
  color: var(--color-primary);
  font-size: 0.72rem;
  font-weight: 700;
  cursor: pointer;
  padding: 2px 4px;
}

.notif-row-action:hover {
  text-decoration: underline;
}

.notif-feed-loading {
  text-align: center;
  padding: 8px 0;
}

/* ─── NOTIFICATIONS: FULL-HISTORY SCREEN (Prompt 47) ────────────
   Reached only via the dropdown's "See all" link — everything Prompt 44
   originally built (date separators, infinite scroll, full body text)
   now lives here instead of in the dropdown itself. */

.screen-notifications-full {
  width: 100%;
  max-width: 560px;
  margin: 0 auto;
}

.notif-full-wrap {
  display: flex;
  flex-direction: column;
  gap: 16px;
  text-align: left;
}

.notif-full-card {
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.notif-full-list {
  overflow-y: auto;
  max-height: 70vh;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* An actual interrupt — above everything else in the app, including the
   payment modal (z-index 1000), since it can legitimately appear on top
   of any screen. No backdrop-click handler: closes ONLY via Escape or
   the explicit X/OK buttons, same rule as the payment modal. */
.notif-popup-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2000;
  padding: 16px;
}

.notif-popup {
  width: 100%;
  max-width: 420px;
  padding: 0;
  text-align: left;
}

.notif-popup .quick-add-panel-header {
  padding: 16px 18px;
}

.notif-popup-body {
  padding: 4px 18px 18px;
  font-size: 0.95rem;
  color: var(--color-wood);
  white-space: pre-wrap;
}

.notif-popup .form-actions {
  padding: 0 18px 18px;
}

/* ─── PRINT STATION (Prompt 23) ───────────────────────────────
   The badge and the receipt host both live OUTSIDE #app, because
   main.js's route() wipes #app on every render(). See js/printStation.js. */

.print-station-badge {
  position: fixed;
  right: 16px;
  bottom: 16px;
  z-index: 900;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
}

.print-station-pill {
  display: flex;
  align-items: center;
  gap: 8px;
  border: none;
  border-radius: 999px;
  padding: 9px 16px;
  background: var(--color-success);
  color: #FFFFFF;
  font-size: 0.8rem;
  font-weight: 700;
  cursor: pointer;
  box-shadow: 0 3px 10px rgba(60, 40, 20, 0.22);
}

.print-station-pill.is-busy,
.print-station-pill.has-pending {
  background: var(--color-accent);
}

.print-station-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #FFFFFF;
  flex-shrink: 0;
}

.print-station-panel {
  background: #FFFFFF;
  border-radius: 12px;
  border: 1px solid var(--color-bamboo);
  box-shadow: 0 4px 14px rgba(60, 40, 20, 0.16);
  padding: 12px 14px;
  min-width: 230px;
  max-width: 300px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.print-station-panel-title {
  font-size: 0.78rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-primary);
}

.print-station-recent-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  font-size: 0.82rem;
  color: var(--color-wood);
}

.print-station-recent-label {
  font-weight: 600;
}

/* Sales detected but not yet printed (auto-print off, Prompt 25) — same
   row shape as a printed "recent" entry, distinguished with the accent
   color so it reads as still needing action. */
.print-station-recent-row.is-pending .print-station-recent-label {
  color: var(--color-accent);
}

.print-station-reprint {
  border: 1px solid var(--color-bamboo);
  background: var(--color-bg);
  color: var(--color-primary);
  border-radius: 8px;
  padding: 4px 9px;
  font-size: 0.74rem;
  font-weight: 700;
  cursor: pointer;
  white-space: nowrap;
}

.print-station-recent-row.is-pending .print-station-reprint {
  border-color: var(--color-accent);
  color: var(--color-accent);
}

.print-station-empty {
  font-size: 0.8rem;
  color: var(--color-wood);
  opacity: 0.8;
}

/* Hidden on screen — only ever visible to the printer (see @media print
   below). The @page size rule itself is injected at print time by
   printStation.js, since it varies with the paper-width setting. */
#printStationReceipt {
  display: none;
}

.ps-receipt {
  font-family: "Courier New", Courier, monospace;
  color: #000000;
  background: #FFFFFF;
  line-height: 1.35;
  box-sizing: border-box;
}

.ps-center { text-align: center; }
.ps-strong { font-weight: 700; }
.ps-title { font-weight: 700; }

.ps-rule {
  border-top: 1px dashed #000000;
  margin: 5px 0;
}

/* Fonepay QR on the printed receipt (Prompt 32) — actual printed size
   comes from the inline width/height (in mm, set per paper width by
   receiptMetrics() in printStation.js); this just keeps it undistorted. */
.ps-qr-image {
  object-fit: contain;
  margin: 4px 0;
}

.ps-table {
  width: 100%;
  border-collapse: collapse;
}

.ps-table td {
  padding: 1px 0;
  vertical-align: top;
}

.ps-qty { width: 12%; }
.ps-name { width: 63%; word-break: break-word; }
.ps-amt { width: 25%; text-align: right; white-space: nowrap; }

.ps-total {
  display: flex;
  justify-content: space-between;
  font-weight: 700;
}

@media print {
  /* Everything except the receipt is hidden rather than restyled — #app
     carries a flex/min-height/padding layout that would otherwise push
     the receipt off the roll. */
  body > *:not(#printStationReceipt) {
    display: none !important;
  }

  #printStationReceipt {
    display: block !important;
  }

  html, body {
    margin: 0 !important;
    padding: 0 !important;
    background: #FFFFFF !important;
  }
}
