/* ===================================================================
   Kawa Lodge — Staff App
   Built on the same tokens as main.css (ink/parchment/brass/clay/moss).
   No new palette introduced — this file only adds dashboard layout.
   =================================================================== */

/* -------------------------------------------------------------
   Login page
   ------------------------------------------------------------- */
.login-page { background: var(--parchment-dim); min-height: 100vh; }

/* Used when the auth card sits inside the normal nav+footer page flow
   (guest login.php/signup.php) rather than as a standalone full-page
   document (staff-login.php uses .login-wrap directly on its own body). */
.w-auth-wrap { display: flex; justify-content: center; padding: 64px 20px 96px; }

.login-wrap {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.login-card {
  width: 100%;
  max-width: 380px;
  background: var(--parchment-flat);
}

.login-brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  margin-bottom: 28px;
}
.login-brand .w-wordmark-text { font-family: var(--font-display); font-weight: 600; color: var(--ink); font-size: 1.1rem; }

.login-title { margin-bottom: 22px; }

.login-form { display: flex; flex-direction: column; gap: 16px; }

/* Every form in the app uses <label class="field"><span class="field-label">
   Text</span><input></label> - main.css's .field only sets margin-bottom
   (it expects a nested <label>, which this markup doesn't have), so the
   container layout and label styling live here instead. Input/select/
   textarea styling itself (border, focus glow, sizing) comes from
   main.css's .field input rule - not redeclared here, so there's one
   definition to keep in sync instead of two silently fighting. */
.field { display: flex; flex-direction: column; gap: 6px; }
.field-label { font-size: 0.82rem; font-weight: 600; color: var(--ink-soft); }

.login-error {
  background: var(--danger-bg);
  color: var(--danger);
  font-size: 0.86rem;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  margin: 0;
}

.login-back { display: inline-block; margin-top: 18px; text-align: center; width: 100%; }
.login-alt { text-align: center; font-size: 0.88rem; color: var(--stone); margin: 18px 0 0; }
.login-alt a { color: var(--clay-dark); font-weight: 600; }

/* -------------------------------------------------------------
   App shell
   ------------------------------------------------------------- */
.app-body { margin: 0; background: var(--parchment-dim); }

.app-shell {
  display: flex;
  min-height: 100vh;
}

.app-sidebar {
  width: 224px;
  flex-shrink: 0;
  background: var(--primary);
  color: var(--parchment);
  display: flex;
  flex-direction: column;
  padding: 20px 14px;
  position: sticky;
  top: 0;
  height: 100vh;
}

.app-brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  padding: 0 8px;
  margin-bottom: 28px;
}
.app-brand .w-wordmark-text { font-family: var(--font-display); font-weight: 600; color: var(--parchment); font-size: 1.05rem; }

.app-nav { display: flex; flex-direction: column; gap: 12px; flex: 1; overflow-y: auto; }
.app-nav-section { min-width: 0; }
.app-nav-section-label {
  padding: 4px 10px 6px;
  color: rgba(243, 245, 249, 0.42);
  font-size: .66rem;
  font-weight: 800;
  letter-spacing: .11em;
  line-height: 1.2;
  text-transform: uppercase;
}
.app-nav-section-items { display: flex; flex-direction: column; gap: 3px; }

.app-nav-icon {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  opacity: 0.9;
}

.app-nav-link {
  font-family: var(--font-body);
  font-size: 0.92rem;
  font-weight: 400;
  text-align: left;
  background: transparent;
  border: none;
  color: rgba(243, 245, 249, 0.72);
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background .15s var(--ease), color .15s var(--ease);
  text-decoration: none;
  display: flex;
  align-items: center;
  gap: 10px;
}
.app-nav-link > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.app-nav-link:hover { background: rgba(173, 143, 67, 0.08); color: var(--parchment); }
.app-nav-link.is-active { background: var(--brass-light); color: var(--white); font-weight: 600; }
.app-nav-link.is-active .app-nav-icon { opacity: 1; }
.app-nav-link--muted { color: rgba(243, 245, 249, 0.45); font-size: 0.82rem; }
.app-nav-badge {
  margin-left: auto;
  background: var(--brass);
  color: var(--ink);
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1;
  padding: 3px 7px;
  border-radius: 999px;
  min-width: 18px;
  text-align: center;
}

/* Messages inbox */
.is-unread-row { font-weight: 600; }
.message-body-text { white-space: pre-wrap; line-height: 1.6; margin: 14px 0 20px; }

.app-sidebar-foot {
  border-top: 1px solid rgba(243, 245, 249, 0.12);
  padding-top: 12px;
  margin-top: 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.app-nav-link--profile {
  display: flex;
  align-items: center;
  gap: 10px;
  overflow: hidden;
}
.app-nav-link--profile .app-nav-icon { width: 18px; height: 18px; opacity: 1; }
.app-user-text { display: flex; flex-direction: column; gap: 1px; overflow: hidden; min-width: 0; }
.app-nav-link--muted { display: flex; align-items: center; gap: 8px; }
.app-nav-link--muted .app-nav-icon { width: 15px; height: 15px; }
.app-sidebar-foot .btn-ghost { color: var(--parchment); border-color: rgba(243, 245, 249, 0.3); }
.app-sidebar-foot .btn-ghost:hover { background: rgba(243, 245, 249, 0.1); color: var(--white); border-color: rgba(243, 245, 249, 0.5); }

.app-sidebar-backdrop {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(16, 24, 40, 0.45);
  z-index: 19;
}

.app-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.app-topbar {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 16px 28px;
  background: var(--white);
  border-bottom: 1px solid var(--parchment-dim);
  box-shadow: 0 1px 0 var(--brass);
  position: sticky;
  top: 0;
  z-index: 5;
}

.app-menu-toggle {
  display: none;
  flex-direction: column;
  gap: 4px;
  background: transparent;
  border: none;
  cursor: pointer;
  padding: 8px;
  border-radius: var(--radius-sm);
  flex-shrink: 0;
}
.app-menu-toggle:hover { background: var(--parchment-dim); }
.app-menu-toggle span { width: 20px; height: 2px; background: var(--ink); border-radius: 2px; }

.app-page-title { flex: 1; margin: 0; font-size: 1.3rem; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.app-connection-status {
  flex: 0 0 auto;
  margin-right: 10px;
  padding: 5px 9px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--parchment-flat);
  color: var(--accent-green);
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .02em;
  white-space: nowrap;
}
.app-connection-status.is-offline {
  color: var(--clay);
  border-color: rgba(177, 93, 65, .3);
  background: rgba(177, 93, 65, .07);
}

/* Sidebar-footer identity (name links to Profile, role shown beneath) */
.app-nav-link--profile .app-user-name {
  font-weight: 600;
  font-size: 0.92rem;
  color: var(--parchment);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.app-nav-link--profile .app-user-role {
  font-size: 0.74rem;
  color: rgba(243, 245, 249, 0.55);
  text-transform: capitalize;
}

.app-content { padding: 26px 28px; flex: 1; }

/* -------------------------------------------------------------
   Stat cards (Reports overview/revenue + Admin dashboard)
   ------------------------------------------------------------- */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 14px;
  margin-bottom: 22px;
  align-items: start;
}
.stat-card-icon {
  width: 28px;
  height: 28px;
  color: var(--primary);
  margin-bottom: 4px;
  flex-shrink: 0;
}

/* Even smaller for mobile */
@media (max-width: 640px) {
  .stat-card-icon {
    width: 20px;
    height: 20px;
  }
}

.stat-card {
  background: var(--white);
  border-radius: var(--radius);
  border-left: 4px solid var(--brass);
  box-shadow: var(--shadow-card);
  padding: 16px 18px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  transition: box-shadow .15s var(--ease), transform .15s var(--ease);
}
.stat-card:hover { box-shadow: 0 6px 20px rgba(16, 24, 40, 0.1); transform: translateY(-1px); }
.stat-card-value { font-family: var(--font-display); font-size: 1.7rem; font-weight: 600; color: var(--ink); line-height: 1.1; }
.stat-card-label { font-size: 0.82rem; color: var(--stone); }
/*
  The line under a stat card's figure that stops it being read as something it is not.
  Sits inside the card, so it moves with the figure rather than floating beside it.
*/
.stat-card-subtitle {
  display: block;
  font-size: 0.72rem;
  line-height: 1.4;
  color: var(--stone-light);
  margin-top: 2px;
}
.stat-card-sub { font-size: 0.76rem; color: var(--stone-light); }

/* Alert banners: pending items that want attention (booking requests,
   overdue guest balances) - same colored-strip + icon + chevron
   language as the stat cards, just full-width and actionable. */
.overview-alert {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 16px; border-radius: var(--radius-sm);
  margin-bottom: 10px; cursor: pointer; border: none; width: 100%;
  font-family: inherit; text-align: left;
  transition: filter .12s var(--ease);
}
.overview-alert:hover { filter: brightness(0.97); }
.overview-alert-icon { flex-shrink: 0; width: 20px; height: 20px; }
.overview-alert-text { flex: 1; font-size: 0.9rem; color: var(--ink); }
.overview-alert-text strong { font-weight: 600; }
.overview-alert-chevron { flex-shrink: 0; opacity: 0.5; }
.overview-alert--danger { background: var(--danger-bg); }
.overview-alert--danger .overview-alert-icon { color: var(--danger); }
.overview-alert--clay { background: var(--clay-bg); }
.overview-alert--clay .overview-alert-icon { color: var(--clay-dark); }

/* -------------------------------------------------------------
   Business breakdown cards (Reports > Business)
   ------------------------------------------------------------- */
.business-card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 14px;
  margin-bottom: 20px;
}
.business-card {
  background: var(--white);
  border-radius: var(--radius);
  border-top: 4px solid var(--brass);
  box-shadow: var(--shadow-card);
  padding: 18px 20px;
}
.business-card--bar        { border-top-color: var(--terracotta); }
.business-card--restaurant { border-top-color: var(--accent-green); }
.business-card--rooms      { border-top-color: var(--brass); }
.business-card--general    { border-top-color: var(--stone); }
.business-card-title { font-family: var(--font-display); font-weight: 600; font-size: 1.05rem; color: var(--ink); margin: 0 0 12px; }
.business-card-row { display: flex; justify-content: space-between; align-items: baseline; font-size: 0.85rem; color: var(--stone); padding: 4px 0; }
.business-card-row + .business-card-row { border-top: 1px solid var(--parchment-dim); }
.business-card-row .num { font-family: var(--font-mono); color: var(--ink); }
.business-card-row.is-net .num { font-weight: 600; font-size: 1rem; }
.business-card-row.is-net .num.is-negative { color: var(--danger); }
.business-delta {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 600;
  padding: 1px 6px;
  border-radius: 4px;
  margin-left: 6px;
}
.business-delta.is-up   { background: var(--moss-light); color: var(--accent-green-dark); }
.business-delta.is-down { background: var(--danger-bg); color: var(--danger); }
.business-delta.is-flat { background: var(--parchment-dim); color: var(--stone); }
#businessNarrative p { margin: 0 0 8px; font-size: 0.9rem; line-height: 1.6; color: var(--ink-soft); }
#businessNarrative p:last-child { margin-bottom: 0; }
#businessNarrative strong { color: var(--ink); }

.dashboard-section-head { display: flex; align-items: baseline; justify-content: space-between; margin: 24px 0 12px; }
.dashboard-section-head p { margin: 0; }
.stat-card .stat-card-value{
  display: flex;
  font-size: 20px;
}
/* -------------------------------------------------------------
   Room board (reception module)
   ------------------------------------------------------------- */
.board-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 20px;
}

.board-filters { display: flex; gap: 8px; flex-wrap: wrap; }

.board-filter {
  font-family: var(--font-body);
  font-size: 0.84rem;
  font-weight: 600;
  padding: 7px 14px;
  border-radius: 999px;
  border: 1.5px solid var(--stone-light);
  background: var(--white);
  color: var(--stone);
  cursor: pointer;
}
.board-filter.is-active { background: var(--ink); border-color: var(--ink); color: var(--parchment); }

.room-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 14px;
  align-items: start;
}

.room-card {
  position: relative;
  background: var(--white);
  border: 1px solid rgba(16,24,40,.08);
  border-left: 4px solid var(--stone-light);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  padding: 16px;
  min-height: 126px;
  overflow: hidden;
  transition: transform .15s var(--ease), box-shadow .15s var(--ease), border-color .15s var(--ease);
}
.room-card::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(135deg, rgba(255,255,255,.34), transparent 55%);
}
.room-card[data-status="vacant"] {
  border-left-color: var(--moss);
  background: #FBFCFA;
}
.room-card[data-status="occupied"] {
  border-left-color: var(--moss);
  background: var(--moss-light);
}
.room-card[data-status="dirty"] {
  border-left-color: #C47A22;
  background: #FFF6E8;
}
.room-card[data-status="maintenance"] {
  border-left-color: var(--danger);
  background: var(--danger-bg);
}
.room-card[data-status="reserved"] {
  border-left-color: #7356A8;
  background: #F5F0FB;
}
.room-card[data-status="cleaning"] {
  border-left-color: #4D79A8;
  background: #EEF5FB;
}
.room-card[data-status="clean"],
.room-card[data-status="inspected"] {
  border-left-color: var(--moss);
  background: #F3F9F4;
}

.room-card--clickable:hover { transform: translateY(-2px); box-shadow: 0 8px 22px rgba(16,24,40,.13); }
.room-card--clickable:active { transform: translateY(0); }

.room-card-number { font-family: var(--font-display); font-size: 1.5rem; font-weight: 600; color: var(--ink); margin-bottom: 4px; position: relative; z-index: 1; }
.room-card-type { font-size: 0.82rem; color: var(--stone); margin-bottom: 10px; position: relative; z-index: 1; }
.room-card .badge { position: relative; z-index: 1; }

/* Room preview modal (Reception) */
.room-preview-photo-wrap {
  width: 100%;
  height: 220px;
  border-radius: 10px;
  overflow: hidden;
  background: var(--parchment-dim);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: 4px;
}
.room-preview-photo-wrap img { width: 100%; height: 100%; object-fit: cover; }
.room-preview-photo-wrap .room-preview-photo-empty { color: var(--stone); font-size: 0.85rem; }
.room-preview-details { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 14px; margin-top: 16px; }
.room-preview-detail { display: flex; flex-direction: column; gap: 4px; }
.room-preview-detail span:last-child { font-weight: 600; color: var(--ink); }
.room-preview-notes { margin-top: 14px; padding: 10px 12px; background: var(--parchment-dim); border-radius: 8px; font-size: 0.86rem; color: var(--ink-soft); }

.room-card-empty { grid-column: 1 / -1; text-align: center; padding: 40px 0; color: var(--stone); }

/* -------------------------------------------------------------
   Reservation status badges (mirrors reservations.status vocabulary -
   distinct from the room-status badges above, so both can share a
   page without clashing).
   ------------------------------------------------------------- */
.badge-pending_approval { background: #e9e4f7; color: var(--brass-dark); }
.badge-booked           { background: var(--moss-light); color: var(--moss); }
.badge-checked_in       { background: var(--moss-light); color: var(--moss); }
.badge-checked_out      { background: #E7E2DB; color: var(--stone); }
.badge-cancelled        { background: var(--danger-bg); color: var(--danger); }
.badge-no_show          { background: var(--danger-bg); color: var(--danger); }
.badge-duplicate-room   { background: var(--danger-bg); color: var(--danger); }
.badge-sent             { background: #e9e4f7; color: var(--brass-dark); }
.badge-served           { background: var(--moss-light); color: var(--moss); }
.badge-paid             { background: #E7E2DB; color: var(--stone); }
.badge-payment          { background: #E7E2DB; color: var(--stone); }

/* -------------------------------------------------------------
   Guest account dashboard
   ------------------------------------------------------------- */
.account-head-actions { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.account-section { padding: 0 0 88px; }

.account-profile {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-bottom: 48px;
}
.account-profile-name { font-family: var(--font-display); font-weight: 600; font-size: 1.05rem; margin: 0 0 2px; }
.account-profile .mono { margin: 0; }

.account-section-head { margin-bottom: 20px; }
.account-section-head h2 { font-size: 1.4rem; }

.reservation-list { display: flex; flex-direction: column; gap: 14px; }

.reservation-card {
  padding: 20px 22px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
}
.reservation-card-main { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.reservation-card-type { font-family: var(--font-display); font-weight: 600; font-size: 1.05rem; margin-bottom: 4px; }
.reservation-card-dates { font-family: var(--font-mono); font-size: 0.86rem; color: var(--stone); }
.reservation-card-dates strong { color: var(--ink-soft); font-weight: 600; }
.reservation-card-meta { font-size: 0.84rem; color: var(--stone); margin-top: 4px; }
.reservation-card-rate { font-family: var(--font-mono); font-size: 1.05rem; color: var(--ink); text-align: right; white-space: nowrap; }
.reservation-card-rate span { display: block; font-size: 0.72rem; color: var(--stone); font-weight: 400; }

.reservation-empty { text-align: center; padding: 56px 20px; color: var(--stone); }
.reservation-empty .keytag { margin-bottom: 16px; }

/* -------------------------------------------------------------
   Topbar date (next to the page title)
   ------------------------------------------------------------- */
.app-topbar-date {
  font-family: var(--font-mono);
  font-size: 0.82rem;
  color: var(--stone);
  white-space: nowrap;
}

/* -------------------------------------------------------------
   Modal overlay
   main.css defines .modal itself (the white card: padding, radius,
   shadow, max-width). This is the backdrop that centers it — every
   modal in the app markup is <div class="modal-overlay" hidden>
   <div class="modal card">...</div></div>, toggled via the `hidden`
   attribute (not a class), so this only needs to handle positioning.
   ------------------------------------------------------------- */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(16, 24, 40, 0.5);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 60px 20px;
  overflow-y: auto;
  z-index: 100;
}
.modal-overlay[hidden] { display: none; }

.modal-lg { max-width: 640px; }

.modal-actions {
  display: flex;
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 8px;
}

/* -------------------------------------------------------------
   Receipt/confirmation preview modal (receipt-preview.js)
   ------------------------------------------------------------- */
.receipt-preview-frame {
  display: flex;
  justify-content: center;
  background: var(--parchment);
  border-radius: var(--radius);
  padding: 20px;
  margin: 4px 0 16px;
  max-height: 60vh;
  overflow-y: auto;
}
.receipt-preview-actions { justify-content: center; }
@media (max-width: 560px) {
  .receipt-preview-frame { padding: 10px; }
}

.modal-tabs {
  display: flex;
  gap: 4px;
  border-bottom: 1.5px solid var(--parchment-dim);
  margin-bottom: 18px;
}
.modal-tab {
  font-family: var(--font-body);
  font-size: 0.86rem;
  font-weight: 600;
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  padding: 8px 4px 10px;
  margin-right: 18px;
  color: var(--stone);
  cursor: pointer;
}
.modal-tab.is-active { color: var(--clay-dark); border-bottom-color: var(--clay-dark); }
.modal-pane { display: none; }
.modal-pane.is-active { display: block; }

/* -------------------------------------------------------------
   Form layout
   Markup pattern: <label class="field"><span class="field-label">
   Text</span><input></label> — .field/.field-label are already
   defined above (login form). These add the grid/inline layouts and
   error text used by every other form in the app.
   ------------------------------------------------------------- */
/* -------------------------------------------------------------
   Form layout
   ------------------------------------------------------------- */
.form-grid {
  display: block;
  max-width: 860px;
  margin: 0 auto;
  background: var(--white);
  border-radius: var(--radius);
  padding: 24px 28px;
  border: 1px solid rgba(16, 24, 40, 0.08);
  box-shadow: var(--shadow-card);
}
.form-grid--tight { grid-template-columns: repeat(3, 1fr); }
.field-wide { grid-column: 1 / -1; }
/* A run of guidance under a row of inputs. It has to claim the full width of
   the form, or a sentence of explanation ends up in a 200px column and wraps
   to two or three words a line. */
.payslip-hint {
  flex: 1 0 100%;
  margin: 2px 0 0;
  font-size: .8rem;
  line-height: 1.5;
}

.form-inline {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 18px;
}

/* Branded image/file picker shared by room and document uploads. */
.file-upload-row { display:flex; align-items:center; flex-wrap:wrap; gap:10px; }
.file-upload-input {
  position:absolute !important; width:1px !important; height:1px !important;
  padding:0 !important; margin:-1px !important; overflow:hidden !important;
  clip:rect(0,0,0,0) !important; white-space:nowrap !important; border:0 !important;
}
.file-upload-trigger {
  min-height:42px; display:inline-flex; align-items:center; justify-content:center; gap:9px;
  padding:9px 14px; border:1px solid var(--parchment-dim); border-radius:var(--radius-sm);
  color:var(--ink); background:var(--white); font-size:.86rem; font-weight:600;
  cursor:pointer; transition:background .16s var(--ease), border-color .16s var(--ease), transform .16s var(--ease);
}
.file-upload-trigger:hover { background:var(--parchment); border-color:var(--brass); }
.file-upload-trigger:active { transform:translateY(1px); }
.file-upload-trigger svg { width:18px; height:18px; fill:none; stroke:currentColor; stroke-width:1.7; stroke-linecap:round; stroke-linejoin:round; }
.file-upload-input:focus-visible + .file-upload-trigger { outline:3px solid rgba(201,162,39,.35); outline-offset:2px; border-color:var(--brass); }
.file-upload-name { min-width:120px; max-width:min(250px, 45vw); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:var(--stone); font-size:.8rem; }
.file-upload-row > .btn { margin-top:0; }

/* -------------------------------------------------------------
   Multi-step form (Manual entry)
   ------------------------------------------------------------- */
.step-progress {
  max-width: 860px;
  margin: 0 auto 28px;
  padding: 0 4px;
}

.step-progress-bar {
  height: 4px;
  background: var(--parchment-dim);
  border-radius: 4px;
  overflow: hidden;
  margin-bottom: 16px;
}

.step-progress-track {
  height: 100%;
  background: var(--brass);
  border-radius: 4px;
  transition: width 0.4s var(--ease);
  width: 0%;
}

.step-progress-steps {
  display: flex;
  justify-content: space-between;
  gap: 8px;
}

.step-progress-step {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
  font-size: 0.78rem;
  color: var(--stone);
  font-weight: 500;
  opacity: 0.5;
  transition: opacity 0.3s var(--ease), color 0.3s var(--ease);
}

.step-progress-step.is-active {
  opacity: 1;
  color: var(--ink);
}

.step-progress-step.is-complete {
  opacity: 0.7;
  color: var(--moss);
}

.step-progress-number {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--parchment-dim);
  color: var(--stone);
  font-weight: 600;
  font-size: 0.78rem;
  flex-shrink: 0;
  transition: background 0.3s var(--ease), color 0.3s var(--ease);
}

.step-progress-step.is-active .step-progress-number {
  background: var(--brass);
  color: var(--white);
}

.step-progress-step.is-complete .step-progress-number {
  background: var(--moss);
  color: var(--white);
}

.step-progress-label {
  display: none;
}

@media (min-width: 640px) {
  .step-progress-label {
    display: inline;
  }
}

/* Form steps - inside the white card */
.form-step {
  display: none;
  animation: content-in 0.25s var(--ease);
}

.form-step.is-active {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px 20px;
}

/* On smaller screens, single column */
@media (max-width: 640px) {
  .form-step.is-active {
    grid-template-columns: 1fr;
  }
}

.form-step .field-wide {
  grid-column: 1 / -1;
}

.form-step-head {
  grid-column: 1 / -1;
  margin-bottom: 4px;
}

.form-step-head .form-step-title {
  font-family: var(--font-display);
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--ink);
  margin: 0 0 2px;
}

.form-step-head .text-stone {
  margin: 0;
  font-size: 0.88rem;
}

.form-step-actions {
  grid-column: 1 / -1;
  display: flex;
  gap: 10px;
  justify-content: flex-end;
  padding-top: 12px;
  border-top: 1px solid var(--parchment-dim);
  margin-top: 8px;
}

.form-step-actions .btn-ghost {
  margin-right: auto;
}

/* Summary card (step 3) */
.summary-card {
  background: var(--parchment-flat);
  border-radius: var(--radius);
  padding: 16px 20px;
  border: 1px solid rgba(16, 24, 40, 0.08);
}

.summary-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 6px 0;
  font-size: 0.9rem;
  color: var(--ink-soft);
}

.summary-row + .summary-row {
  border-top: 1px solid rgba(16, 24, 40, 0.06);
}

.summary-row.summary-total {
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--ink);
  padding-top: 10px;
  margin-top: 4px;
  border-top: 2px solid rgba(16, 24, 40, 0.1);
}

.summary-label {
  color: var(--stone);
  font-weight: 500;
}

.summary-value {
  font-weight: 500;
  text-align: right;
  color: var(--primary);
}

/* Field hints */
.field-hint {
  font-size: 0.72rem;
  color: var(--stone-light);
  margin-top: 2px;
}

/* Responsive adjustments for form steps */
@media (max-width: 640px) {
  .form-grid {
    padding: 16px;
  }

  .step-progress-steps {
    flex-wrap: wrap;
    gap: 4px;
  }

  .step-progress-step {
    flex: 0 0 auto;
    font-size: 0.7rem;
  }

  .step-progress-number {
    width: 24px;
    height: 24px;
    font-size: 0.7rem;
  }

  .form-step-actions {
    flex-wrap: wrap;
  }

  .form-step-actions .btn {
    flex: 1;
    justify-content: center;
  }

  .form-step-actions .btn-ghost {
    order: 1;
    flex: 0 0 auto;
  }

  .summary-card {
    padding: 12px 14px;
  }
}
/* Buttons alongside labeled fields (e.g. Revenue's "View", Expenses'
   "Filter") have no label of their own, so they'd otherwise sit
   ~26px too high relative to the inputs next to them - that's the
   "off position" look. Push down by the label row's height (line
   height + .field's 6px gap) so button and input tops line up. */
.form-inline > .btn { margin-top: 26px; }
.field-inline { min-width: 160px; }
.order-table-field { min-width: 220px; }

/* ------------------------------------------------------ inline filter rows, measured ----
 *
 * .form-inline is `display:flex; flex-wrap:wrap` and its fields are `flex:1 1 180px`, so a field
 * that ends up ALONE on a wrapped line absorbs every spare pixel on that line. Two faults follow,
 * and both were measured rather than imagined.
 *
 * 1  A FIELD SWALLOWED A WHOLE LINE. Purchases has five fields and two buttons in 749px. Four
 *    fields fit at 181px each; the fifth wrapped alone and took the lot:
 *
 *        Search 181   Business unit 181   Supplier 181   From 181
 *        To     610                                       <- a date input 610px wide
 *
 *    The row above it reads fine, which is exactly why nobody had reported it as broken - one row
 *    of an otherwise tidy filter bar.
 *
 * 2  FIELDS GREW SO MUCH THEY PUSHED THE BUTTON OFF THE ROW. Suppliers has two fields and one
 *    button. The two fields grew from 180px to 336px each, and 336+336+60+24 gaps no longer fit
 *    749, so the button wrapped onto a line of its own - separated from the filters it acts on.
 *
 * There are only five .form-inline rows in the whole application, and these two accounted for
 * three of them. The other two (store, my-expenses) are already correct and must stay that way.
 *
 * The fix is two rules rather than a restructure:
 *
 *   max-width      a field may grow to SHARE a row, not to swallow one. 320px is a normal filter
 *                  width; the fields that legitimately share a row are nowhere near it, so this
 *                  changes nothing that was right.
 *   margin-left    a trailing button takes the free space on whichever line it lands on, so
 *   : auto         Filter and Reset sit at the right end instead of trailing a 320px field.
 */
.form-inline > .field-inline { max-width: 320px; }
.form-inline > .btn { margin-left: auto; }

.form-error {
  background: var(--danger-bg);
  color: var(--danger);
  font-size: 0.86rem;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  margin: 0;
}

/* -------------------------------------------------------------
   Module tabs (in-page sub-navigation within a loaded module —
   distinct from .app-nav-link in the sidebar, though visually related)
   ------------------------------------------------------------- */
.module-tabs {
  display: flex;
  gap: 6px;
  margin-bottom: 22px;
  border-bottom: 1.5px solid var(--parchment-dim);
}
.module-tab {
  font-family: var(--font-body);
  font-size: 0.9rem;
  font-weight: 600;
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  padding: 10px 6px 12px;
  margin-right: 20px;
  color: var(--stone);
  cursor: pointer;
}
.module-tab:hover { color: var(--ink); }
.module-tab.is-active { color: var(--clay-dark); border-bottom-color: var(--clay-dark); }
.module-pane { display: none; }
.module-pane.is-active { display: block; animation: content-in .18s var(--ease); }

/* -------------------------------------------------------------
   Admin / staff table
   ------------------------------------------------------------- */
.admin-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 20px;
  flex-wrap: wrap;
}
.admin-toolbar-title { margin: 0 0 4px; }
.admin-toolbar p { margin: 0; }

.admin-subhead {
  font-family: var(--font-mono);
  font-size: 0.76rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--stone);
  margin: 24px 0 10px;
  display: flex;
  align-items: center;
  gap: 7px;
}
.admin-subhead:first-child { margin-top: 0; }
.admin-subhead-icon { width: 15px; height: 15px; flex-shrink: 0; color: var(--primary); }

.table-wrap {
  overflow-x: auto;
  border-radius: var(--radius);
  -webkit-overflow-scrolling: touch;
}
.table-wrap.card { padding: 4px; }
.table-wrap .data-table thead th {
  position: sticky;
  top: 0;
  background: var(--primary);
  color: var(--white);
  z-index: 1;
}
.data-table .num { text-align: right; }
.capitalize { text-transform: capitalize; }

/* Pinned actions column — for wide tables (e.g. the stock report,
   which stacks four action buttons per row) where a row's actions
   would otherwise sit off the right edge, forcing a scroll-down-
   then-scroll-right hunt for every row. Pinning keeps them on
   screen while scrolling vertically; the column itself is capped
   narrow so it never balloons the table further. */
.stock-actions-col {
  position: sticky;
  right: 0;
  z-index: 1;
  background: var(--parchment-flat);
  box-shadow: -6px 0 6px -6px rgba(16, 24, 40, 0.18);
}
th.stock-actions-col { background: var(--primary); z-index: 2; }
.data-table tr:hover td.stock-actions-col { background: var(--parchment-dim); }
.stock-actions {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  width: 140px;
}
.stock-actions .btn-text { padding: 3px 4px; font-size: 0.82rem; white-space: nowrap; }

.btn-text--primary { color: var(--primary); }
.btn-text--primary:hover { color: var(--primary-dark); }

/* -------------------------------------------------------------
   Table toolbar (table-tools.js) — search + CSV/PDF/Print, dropped
   in above any .data-table. Sortable headers get a chevron that
   only appears active once that column is the current sort key.
   ------------------------------------------------------------- */
.table-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}
.table-toolbar-exports { display: flex; gap: 8px; }

/* Pagination. Injected by table-tools.js into the same toolbar as the search
   box, and hidden entirely when a table fits on one page. */
.table-toolbar-pager {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  font-size: 0.8rem;
  color: var(--text-muted);
}
/* [hidden] alone loses to the display:flex above, so restate it. */
.table-toolbar-pager[hidden] { display: none; }
.table-pager-count { white-space: nowrap; font-variant-numeric: tabular-nums; }
.table-pager-nav { display: flex; align-items: center; gap: 6px; }
.table-pager-page { white-space: nowrap; }
.table-pager-nav .btn { min-width: 32px; padding: 2px 8px; }
.table-pager-nav .btn:disabled { opacity: 0.4; cursor: default; }
.table-pager-limit {
  display: flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
}
.table-pager-limit select {
  font-family: var(--font-body);
  font-size: 0.8rem;
  padding: 3px 6px;
  border: 1.5px solid var(--parchment-dim);
  border-radius: var(--radius-sm);
  background: var(--surface, #fff);
  color: var(--text, inherit);
}

@media (max-width: 720px) {
  .table-toolbar-pager { width: 100%; justify-content: space-between; }
}
.table-toolbar-search input {
  font-family: var(--font-body);
  font-size: 0.85rem;
  border: 1.5px solid var(--parchment-dim);
  border-radius: var(--radius-sm);
  padding: 7px 12px;
  min-width: 200px;
  background: var(--white);
  color: var(--ink);
}
.table-toolbar-search input:focus { outline: none; border-color: var(--clay); }
.data-table thead th.is-sortable { cursor: pointer; user-select: none; white-space: nowrap; }
.data-table thead th.is-sortable::after { content: '\2195'; margin-left: 5px; opacity: .35; font-size: 0.85em; }
.data-table thead th.is-sortable:hover::after { opacity: .7; }
.data-table thead th.sort-asc::after { content: '\2191'; opacity: 1; color: var(--clay); }
.data-table thead th.sort-desc::after { content: '\2193'; opacity: 1; color: var(--clay); }
@media (max-width: 640px) {
  .table-toolbar { flex-direction: column; align-items: stretch; }
  .table-toolbar-search input { width: 100%; }
}

/* -------------------------------------------------------------
   Responsive card tables — opt in with .table-wrap--cards on the
   wrapper. Below 640px the table stops being a table and each row
   becomes a small card instead, which reads far better on a phone
   than a table you have to scroll sideways through. Every <td> that
   holds a real value needs data-label="<column header>" (added in
   the JS that renders the row) so its label can show next to it;
   an action-only cell should use data-label="" to right-align
   instead. Currently used by Staff and All reservations.
   ------------------------------------------------------------- */
@media (max-width: 640px) {
  .table-wrap--cards { overflow: visible; }
  .table-wrap--cards table.data-table,
  .table-wrap--cards table.data-table tbody,
  .table-wrap--cards table.data-table tr,
  .table-wrap--cards table.data-table td {
    display: block;
    width: 100%;
  }
  .table-wrap--cards table.data-table thead { display: none; }

  .table-wrap--cards table.data-table tr {
    background: var(--white);
    border-radius: var(--radius);
    box-shadow: var(--shadow-card);
    padding: 4px 14px;
    margin-bottom: 10px;
  }
  .table-wrap--cards table.data-table tr:last-child { margin-bottom: 0; }

  .table-wrap--cards table.data-table td {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 9px 0;
    border-bottom: 1px solid var(--parchment-dim);
    text-align: right;
  }
  .table-wrap--cards table.data-table td:last-child { border-bottom: none; }
  .table-wrap--cards table.data-table td::before {
    content: attr(data-label);
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--stone);
    text-align: left;
    flex-shrink: 0;
  }
  /* Action-only cells (data-label="") right-align their button with no label */
  .table-wrap--cards table.data-table td[data-label=""] { justify-content: flex-end; }
  .table-wrap--cards table.data-table td[data-label=""]::before { content: none; }

  /* Loading/empty-state rows: a single colspan cell, not a real row */
  .table-wrap--cards table.data-table td[colspan] {
    display: block;
    text-align: left;
    padding: 14px 0;
  }
  .table-wrap--cards table.data-table td[colspan]::before { content: none; }
}

/* -------------------------------------------------------------
   Order desk (Bar / Restaurant): queue grid + new-order form
   ------------------------------------------------------------- */
.new-order-block { margin-bottom: 18px; }

.order-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 14px;
  align-items: start;
}

.order-card {
  background: var(--white);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  padding: 16px;
}
.order-card-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 8px; }
.order-card-who { font-weight: 600; font-size: 0.92rem; color: var(--ink); }
.order-card-itemlist { margin: 0 0 12px; display: flex; flex-direction: column; gap: 3px; }
.order-card-item-line { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; font-size: 0.86rem; color: var(--ink-soft); }
.order-card-total { font-weight: 600; color: var(--ink); }
.order-card-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.order-card-actions { display: flex; gap: 6px; flex-wrap: wrap; }

/* Order status badges — distinct namespace (badge-order-*) so they
   never collide with room-status or reservation-status badges. */
.badge-order-open      { background: #E7E2DB; color: var(--stone); }
.badge-order-sent      { background: #e9e4f7; color: var(--brass-dark); }
.badge-order-served    { background: var(--moss-light); color: var(--moss); }
.badge-order-paid      { background: var(--moss-light); color: var(--moss); }
.badge-order-cancelled { background: var(--danger-bg); color: var(--danger); }

.menu-categories { display: flex; flex-direction: column; gap: 10px; margin: 16px 0; }

/* Order-picker accordion (New Order screen). Tag-scoped (details/
   summary) on purpose - Menu admin reuses .menu-category/.menu-
   category-head as plain <div>s for its own always-expanded cards,
   so these rules never touch that view. */
details.menu-category {
  background: var(--white);
  border: 1px solid var(--parchment-dim);
  border-radius: var(--radius);
  padding: 4px 16px;
}
/* Menu admin's own (always-expanded, non-collapsible) header - plain
   div, kept separate from summary.menu-category-head above. */
div.menu-category-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 8px; }

summary.menu-category-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 0;
  cursor: pointer;
  list-style: none;
  user-select: none;
}
summary.menu-category-head::-webkit-details-marker { display: none; }
summary.menu-category-head:hover .menu-category-name { color: var(--ink); }
.menu-category-count {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  color: var(--stone);
  background: var(--parchment-flat);
  border-radius: 20px;
  padding: 1px 8px;
}
.menu-category-chevron {
  width: 15px; height: 15px;
  color: var(--stone);
  margin-left: auto;
  transition: transform .2s var(--ease);
  flex-shrink: 0;
}
details.menu-category[open] > summary .menu-category-chevron { transform: rotate(180deg); }
.menu-category-body { padding-bottom: 10px; }

.menu-category-name {
  font-family: var(--font-mono);
  font-size: 0.74rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--stone);
  margin: 0;
  transition: color .15s var(--ease);
}
.menu-item-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 0;
  border-bottom: 1px solid var(--parchment-dim);
}
.menu-item-row:last-child { border-bottom: none; }
.menu-item-row.is-out-of-stock { opacity: 0.55; }
.menu-item-name { font-weight: 600; font-size: 0.9rem; color: var(--ink); }
.menu-item-stock {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--stone);
  margin-left: 6px;
}
.menu-item-stock.is-low { color: var(--brass-dark); }
.menu-item-stock.is-out { color: var(--danger); font-weight: 600; }

/*
 * The packaging chip on a menu-management row: "1 crate = 24 bottles", or a warning that the
 * pack size was never set.
 *
 * Added 2026-10-06 after two products were bought with no packaging set and nothing on screen
 * could tell. A product with no pack size looks exactly like a correct one, so the fault was
 * invisible until a transfer screen offered "1 unit (can) available" for a room holding 24.
 *
 * The unset state is a border and a tint as well as a colour, and it carries a symbol and the
 * words "Pack size not set" - never colour alone, because the whole point is that somebody
 * notices.
 */
.menu-packaging {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.02em;
  color: var(--stone);
  margin-left: 8px;
  padding: 2px 7px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--sand-50, rgba(0, 0, 0, 0.02));
  white-space: nowrap;
}
.menu-packaging.is-unset {
  color: var(--danger);
  border-color: var(--danger);
  border-style: dashed;
  font-weight: 600;
  text-transform: uppercase;
}
.menu-packaging-icon { width: 11px; height: 11px; flex: none; }

/*
 * The Catalogue tab inside the Stock module.
 *
 * The item rows reuse .menu-item-row and the packaging chip above, so a product looks the same
 * here as it does on the POS screen. Only the furniture around them is new.
 */
.stock-catalogue-head {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: 12px;
}
.stock-catalogue-head > div:first-child { flex: 1 1 320px; min-width: 0; }
.stock-catalogue-controls { margin-bottom: 12px; }
.stock-catalogue-controls .form-inline { align-items: flex-end; }

.stock-catalogue-summary {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 12px;
}
.stock-catalogue-stat {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  font-size: 0.78rem;
  color: var(--stone);
  background: var(--surface, #fff);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 4px 12px;
}
.stock-catalogue-stat strong { font-size: 0.9rem; color: var(--ink); }
/* A count that needs acting on, marked by its label and weight as well as its colour. */
.stock-catalogue-stat.is-alert {
  color: var(--danger);
  border-color: var(--danger);
  border-style: dashed;
  font-weight: 600;
}
.stock-catalogue-stat.is-alert strong { color: var(--danger); }

/* Which trade a category belongs to, so a product cannot be filed under the wrong one. */
.catalogue-module-tag {
  display: inline-block;
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--stone);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 1px 7px;
  margin-left: 4px;
  vertical-align: 1px;
}

.catalogue-unit-preview {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--stone);
  background: rgba(0, 0, 0, 0.02);
  border-left: 3px solid var(--line);
  padding: 6px 10px;
  margin: 0;
}

/* The Stock module used to be labelled "Stock Ledger", which is now only one of three tabs. */
.stock-toolbar h2 { margin-bottom: 2px; }

/* Attach-to-folio picker (New order) */
.folio-pick-list { display: flex; flex-direction: column; gap: 6px; margin: 12px 0; max-height: 260px; overflow-y: auto; }

/* Compact confirmation bar shown once a folio is picked - swaps in
   for the full picker so step 2 stays close by instead of getting
   pushed down the page on a long list of open rooms/tabs. */
.folio-selected-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 12px;
  padding: 12px 14px;
  border-radius: var(--radius-sm);
  background: var(--moss-light);
  color: var(--moss);
}
.folio-selected-bar svg { flex-shrink: 0; }
.folio-selected-bar span { flex: 1; font-weight: 600; color: var(--ink); font-size: 0.9rem; }
.folio-selected-bar .btn-text { color: var(--moss); }
.folio-selected-bar .btn-text:hover { color: var(--ink); }

/* Barcode scanner modal */
.scanner-viewport {
  width: 100%;
  aspect-ratio: 4 / 3;
  background: var(--ink);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.scanner-viewport video { width: 100%; height: 100%; object-fit: cover; }
.folio-pick-row-wrap { display: flex; align-items: stretch; gap: 6px; }
.folio-pick-row {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; border: 1.5px solid var(--parchment-dim); border-radius: var(--radius-sm);
  background: var(--white); cursor: pointer; text-align: left; flex: 1; min-width: 0;
  font-family: var(--font-body);
}
.folio-pick-row:hover { border-color: var(--brass); background: var(--parchment-flat); }
.folio-pick-row.is-selected { border-color: var(--brass); background: var(--parchment-flat); }
.folio-pick-icon { flex-shrink: 0; color: var(--primary); }
.folio-pick-row--walkin .folio-pick-icon { color: var(--clay-dark); }
.folio-pick-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; }
.folio-pick-name { font-weight: 600; color: var(--ink); font-size: 0.9rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.folio-pick-meta { font-size: 0.78rem; color: var(--stone); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.folio-pick-close {
  flex-shrink: 0; width: 38px;
  border: 1.5px solid var(--parchment-dim); border-radius: var(--radius-sm);
  background: var(--white); color: var(--stone); cursor: pointer;
  font-size: 1.1rem; line-height: 1; transition: background .15s var(--ease), color .15s var(--ease), border-color .15s var(--ease);
}
.folio-pick-close:hover { background: var(--danger-bg); color: var(--danger); border-color: var(--danger); }

.order-cart {
  padding: 16px;
  margin-top: 16px;
  position: sticky;
  bottom: 16px;
  z-index: 4;
  box-shadow: var(--shadow-modal);
}
.order-cart-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 4px; }
.cart-line {
  display: grid;
  grid-template-columns: auto 1fr auto auto;
  align-items: center;
  gap: 12px;
  padding: 10px 0;
  font-size: 0.88rem;
  border-bottom: 1px solid var(--parchment-dim);
}
.cart-line:last-child { border-bottom: none; }
.cart-line-remove {
  padding: 0;
  min-height: 0;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--danger-bg);
  color: var(--danger);
  flex-shrink: 0;
}
.cart-line-remove svg { width: 11px; height: 11px; }
.cart-line-remove:hover { background: var(--danger); color: var(--white); box-shadow: none; }
.cart-line-info { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cart-line-name { font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cart-line-unit { font-size: 0.76rem; color: var(--stone); }
.cart-line-qty { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.cart-line-qty-btn {
  padding: 0;
  min-height: 0;
  width: 24px;
  height: 24px;
  border-radius: var(--radius-sm);
  background: var(--parchment-dim);
  color: var(--ink);
  font-size: 1rem;
  line-height: 1;
}
.cart-line-qty-btn:hover { background: var(--clay-bg); color: var(--clay-dark); box-shadow: none; }
.cart-line-qty-value { min-width: 16px; text-align: center; }
.cart-line-total { font-weight: 600; color: var(--ink); flex-shrink: 0; }
.order-cart-total {
  display: flex;
  justify-content: space-between;
  font-weight: 600;
  border-top: 1.5px solid var(--parchment-dim);
  padding-top: 10px;
  margin: 10px 0 14px;
}

/* -------------------------------------------------------------
   Reports
   ------------------------------------------------------------- */
#expensesTotal {
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 600;
  color: var(--ink);
  margin: 14px 0 0;
}

.reports-columns {
  display: grid;
  /*
    minmax(0, 1fr), NOT `1fr 1fr`.
    A grid track cannot shrink below its content's min-content size unless it is written
    this way. Each column here holds a .data-table with min-width: 640px - deliberately, so
    a wide table scrolls rather than crushing its cells to one character per line - and that
    640px became the floor for the track. Measured at a 1000px viewport: two 641px columns
    plus a 20px gap inside a 691px parent, so the second column sat at right:1569 on a 985px
    screen. document.scrollWidth equalled clientWidth throughout, so the page reported no
    overflow while clipping the heading, hint, search box and table header off the side.
    A phone screenshot confirmed it: the section cut off mid-sentence with no way to scroll
    to the rest.

    minmax(0, 1fr) lets the column be as narrow as the space allows. The table keeps its
    640px and its own overflow-x: auto does the scrolling, inside a column that is now the
    right width. Both rules are needed and they no longer fight.
  */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 20px;
  margin-top: 24px;
  align-items: start;
}
/* The items, too: a grid item's automatic minimum size is min-content unless told otherwise,
   so the track alone is not enough. */
.reports-columns > * { min-width: 0; }

/* -------------------------------------------------------------
   Loyalty
   ------------------------------------------------------------- */
.loyalty-search-results { display: flex; flex-direction: column; gap: 8px; margin-top: 14px; }
.loyalty-search-result {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  border: 1.5px solid var(--parchment-dim);
  cursor: pointer;
  background: var(--white);
}
.loyalty-search-result:hover { border-color: var(--brass); }

.loyalty-balance { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; margin-left: auto; }
.loyalty-points { font-family: var(--font-display); font-size: 1.6rem; font-weight: 600; color: var(--ink); }
.loyalty-tier-badge { text-transform: capitalize; background: var(--parchment-dim); color: var(--brass-dark); }

/* -------------------------------------------------------------
   Profile module
   ------------------------------------------------------------- */
.profile-container {
  display: flex;
  flex-direction: column;
  gap: 22px;
  max-width: 640px;
  margin: 0 auto;
}

/* .account-profile's 48px margin-bottom was tuned for the guest
   account page, where it sits directly on the page background. Here
   it's nested in a .card inside .profile-container, which already
   provides spacing via gap - so flatten that margin. */
.profile-container .account-profile { margin-bottom: 0; gap: 20px; }
.profile-container .account-profile-name { font-size: 1.25rem; margin-bottom: 4px; }

.profile-details { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 32px; }
.profile-row {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 10px 0;
  border-bottom: 1px solid var(--parchment-dim);
}
.profile-row:last-child { border-bottom: none; }
.profile-row .text-stone { font-weight: 500; }
.profile-row .mono { font-family: var(--font-mono); font-weight: 400; }
.profile-footnote { font-size: 0.84rem; margin-top: 18px; }

/* -------------------------------------------------------------
   Room cards that act as buttons (housekeeping status change)
   ------------------------------------------------------------- */
.room-card--clickable { cursor: pointer; transition: transform .1s var(--ease), box-shadow .15s var(--ease); }
.room-card--clickable:hover { box-shadow: 0 4px 16px rgba(16,24,40,0.14); }
.room-card-meta { margin-top: 7px; color: var(--ink-soft); font-size: .78rem; line-height: 1.35; overflow-wrap: anywhere; }
.room-card-meta strong { color: var(--ink); }
.badge-resale { display: inline-flex; width: fit-content; margin-top: 6px; background: #fff2cf; color: #704f00; border: 1px solid #e7c66e; }
/* Matches the blue room-card state: neutral, "needs a look", not an alarm. */
.badge-balance-due { display: inline-flex; width: fit-content; margin-top: 6px; background: #dbe7f5; color: #1f4e8c; border: 1px solid #a9c3e0; }

/* A guest in house who has not settled yet is the NORMAL state, not an
   exception: check-in posts the whole stay to the folio and takes nothing, so
   balance_due is true for nearly every occupied room. Colouring those cards the
   same as a genuine exception made every occupied room look flagged, which is
   the same as flagging none - and reception reads the board by colour, so it
   stops seeing the one that matters.

   This chip is therefore quiet on purpose: it states the figure and when it is
   due, and nothing more. The overdue card keeps the strong treatment above. */
/* The player bar.
   Fixed to the bottom, so stop and pause are in the same place however the
   announcement was started - a control that moves between the header, the
   notification panel and the page is three controls to hunt for.
   It lifts the page with a body class while it is up, so it never sits across
   the last row of whatever table is underneath. */
.announcer-bar {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 900;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  padding-bottom: calc(10px + env(safe-area-inset-bottom, 0px));
  background: var(--parchment, #faf6ec);
  border-top: 1px solid var(--parchment-dim, #d8cbb4);
  box-shadow: 0 -2px 10px rgba(60, 48, 30, .10);
  font-size: 13px;
}
body.announcer-up { padding-bottom: 62px; }

.announcer-bar-btn {
  flex: 0 0 auto;
  min-width: 38px; height: 34px;
  border: 1px solid var(--parchment-dim, #d8cbb4);
  border-radius: 6px;
  background: var(--card, #fff);
  cursor: pointer;
  font-size: 13px;
  line-height: 1;
}
.announcer-bar-btn:hover { border-color: var(--clay, #a4552b); }
.announcer-bar-btn:disabled { opacity: .4; cursor: default; }

.announcer-bar-text {
  flex: 1 1 auto;
  /* min-width:0 is REQUIRED, not tidying. A flex item's default min-width is
     auto, meaning it refuses to shrink below its own content - and with
     white-space:nowrap the content is the whole sentence. Without this the
     caption pushed the "Greet me on arrival" checkbox off the right edge of the
     screen, which is where the only way to turn this off had gone. The caption
     is the part that may be truncated; the controls are not. */
  min-width: 0;
  margin: 0;
  color: var(--ink, #2c261e);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.announcer-bar-pref {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: 5px;
  color: var(--stone, #6b6257);
  font-size: 12px;
  white-space: nowrap;
}
.announcer-bar-pref input { margin: 0; }

/* The voice picker. Sized off the bar rather than given its own control style,
   so it reads as part of the same strip. max-width is set because a voice name
   is long ("Microsoft Zira - English (United States)") and an unbounded select
   pushes the caption - the information - off the left of the bar. */
.announcer-bar-voice { flex: 0 0 auto; display: flex; }
.announcer-bar-voice select {
  max-width: 180px;
  padding: 3px 6px;
  border: 1px solid var(--parchment-dim, #d8cbb4);
  border-radius: 5px;
  background: var(--card, #fff);
  color: var(--ink, #2c261e);
  font-size: 12px;
}
.announcer-bar-voice select:focus-visible { outline: 2px solid var(--clay, #a4552b); outline-offset: 1px; }
/* Hidden entirely when there is nothing to choose between - a one-option picker
   is a control that cannot be used. JS also sets hidden; this is the belt. */
.announcer-bar-voice[hidden] { display: none; }

/* A four-bar equaliser, alive only while something is actually being said.
   It is the one part of the bar that says "this is happening now" without
   needing to be read. */
.announcer-bar-wave { flex: 0 0 auto; display: flex; align-items: flex-end; gap: 2px; height: 16px; }
.announcer-bar-wave i { width: 3px; height: 4px; background: var(--clay, #a4552b); border-radius: 1px; opacity: .25; }
.announcer-bar-wave.is-live i { opacity: 1; animation: announcer-wave .9s ease-in-out infinite; }
.announcer-bar-wave.is-live i:nth-child(2) { animation-delay: .15s; }
.announcer-bar-wave.is-live i:nth-child(3) { animation-delay: .3s; }
.announcer-bar-wave.is-live i:nth-child(4) { animation-delay: .45s; }
@keyframes announcer-wave {
  0%, 100% { height: 4px; }
  50% { height: 16px; }
}
@media (prefers-reduced-motion: reduce) {
  .announcer-bar-wave.is-live i { animation: none; height: 10px; }
}

/* On a narrow phone the caption and the checkbox cannot both fit. The caption
   is the information, so it stays and the checkbox moves out of the way - the
   preference is still reachable, just not while it is talking. */
@media (max-width: 560px) {
  .announcer-bar-pref { position: absolute; top: -30px; right: 10px; background: var(--parchment, #faf6ec);
                        border: 1px solid var(--parchment-dim, #d8cbb4); border-radius: 6px; padding: 4px 8px; }
  /* The picker moves up with the preference: three controls will not fit on one
     phone-width row, and the caption is what must not be squeezed. */
  .announcer-bar-voice { position: absolute; top: -30px; left: 10px; }
  .announcer-bar-voice select { max-width: 190px; }
}

/* Spoken announcements.
   While a voice is actually speaking the button shows it, so a person who
   pressed it knows why the room is talking - and knows pressing again stops it.
   aria-disabled rather than disabled, so the button stays focusable and the
   title explaining WHY it cannot speak remains reachable by keyboard. */
.announcer-btn.is-speaking {
  border-color: var(--clay, #a4552b);
  box-shadow: 0 0 0 2px rgba(164, 85, 43, .18);
}
.announcer-btn[aria-disabled="true"] {
  opacity: .55;
  cursor: not-allowed;
}
.announcer-text {
  font-size: 12.5px; color: var(--stone, #6b6257);
  padding: 8px 12px; border-left: 2px solid var(--parchment-dim, #d8cbb4);
}

.badge-settling {
  display: inline-flex; width: fit-content; margin-top: 6px;
  background: transparent; color: #6b6257; border: 1px dashed #cfc3b2;
  font-weight: 500;
}
.room-preview-balance-due { color: #1f4e8c; font-weight: 600; }

/* -------------------------------------------------------------
   Room types admin (Rooms & Rates module)
   ------------------------------------------------------------- */
.room-type-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 16px; align-items: start; }
.room-type-card { padding: 0; overflow: hidden; }
.room-type-card-photo { width: 100%; height: 120px; object-fit: cover; display: block; }
.room-type-card-photo--empty {
  height: 120px; display: flex; align-items: center; justify-content: center;
  background: var(--parchment-dim); color: var(--stone); font-size: 0.82rem;
}
.room-type-card-body { padding: 16px; }
.room-type-card-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 6px; }
.room-type-card-meta { font-size: 0.86rem; color: var(--ink-soft); margin: 8px 0 12px; }
.room-type-photo-preview {
  width: 100%; max-width: 240px; min-height: 90px; border-radius: var(--radius-sm);
  overflow: hidden; background: var(--parchment-dim); margin-bottom: 10px;
  display: flex; align-items: center; justify-content: center;
}
.room-type-photo-preview img { width: 100%; height: auto; display: block; }
.mb-0 { margin-bottom: 0; }

/* -------------------------------------------------------------
   Profile module (quick-nav for admins)
   ------------------------------------------------------------- */
.login-success {
  color: var(--moss);
  padding: 8px;
  border-radius: var(--radius-sm);
  background: var(--moss-light);
}

.quick-nav-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 16px;
  margin-top: 8px;
  align-items: start;
}
.quick-nav-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 24px 16px;
  background: var(--parchment-flat);
  border-radius: var(--radius);
  text-decoration: none;
  color: var(--ink);
  transition: transform .15s var(--ease), box-shadow .15s var(--ease), border-color .15s var(--ease);
  border: 1px solid var(--parchment-dim);
}
.quick-nav-item:hover {
  border-color: var(--brass);
  transform: translateY(-2px);
  box-shadow: var(--shadow-card);
}
.quick-nav-icon { color: var(--primary); margin-bottom: 8px; }
.quick-nav-label { font-weight: 600; font-size: 0.9rem; }
.quick-nav-desc { font-size: 0.78rem; color: var(--stone); text-align: center; margin-top: 4px; }


/* Update existing stat-card styles */
.stat-card {
  background: var(--white);
  border-radius: var(--radius);
  border-left: 4px solid var(--brass);
  box-shadow: var(--shadow-card);
  padding: 16px 18px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  transition: box-shadow .15s var(--ease), transform .15s var(--ease);
}

/* Add icon wrapper if you want icons in all stat cards */
.stat-card .stat-card-icon-wrapper {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: var(--radius-sm);
  background: var(--parchment-flat);
  margin-bottom: 6px;
}

.stat-card .stat-card-icon {
  width: 18px;
  height: 18px;
  color: var(--brass);
}
@media (max-width: 768px) {
  .profile-details { grid-template-columns: 1fr; }
  .quick-nav-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
}
/* -------------------------------------------------------------
   Responsive
   ------------------------------------------------------------- */
/* -------------------------------------------------------------
   Overview (per-role landing page)
   ------------------------------------------------------------- */
.overview-hero {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 18px;
  background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%);
  border-radius: var(--radius);
  padding: 22px 26px;
  box-shadow: 0 8px 24px rgba(27, 42, 91, 0.18);
}
.overview-hero-main { display: flex; align-items: center; gap: 16px; }
/* The right-hand cluster of the greeting card: "Say that again" above the role
   badge. Right-aligned and allowed to shrink, because on a phone the name and
   the button compete for one row and the name is what matters. */
.overview-hero-side {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
  min-width: 0;
}
.overview-hero-side .btn {
  /* The card is a dark gradient. The default ghost button is near-invisible on
     it, so it is restyled here rather than relying on the ghost variant. */
  background: rgba(255,255,255,.12);
  border-color: rgba(255,255,255,.30);
  color: #fff;
  white-space: nowrap;
}
.overview-hero-side .btn:hover { background: rgba(255,255,255,.20); border-color: rgba(255,255,255,.45); }
.overview-hero-side .btn:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.overview-hero-tag { flex-shrink: 0; }
.overview-hero .text-stone {  color: var(--primary) }
.overview-hero-name { font-family: var(--font-display); font-size: 1.7rem; margin: 2px 0 0; color: var(--primary); }
.overview-hero .badge {
  background: rgba(243, 245, 249, 0.14);
  color: var(--primary);
  border: 1px solid rgba(243, 245, 249, 0.3);
}
.overview-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 16px; align-items: start; }
.overview-card { display: flex; flex-direction: column; gap: 10px; transition: box-shadow .15s var(--ease), transform .15s var(--ease); }
.overview-card:hover { box-shadow: 0 6px 20px rgba(16, 24, 40, 0.1); transform: translateY(-1px); }
.overview-card .btn { align-self: flex-start; margin-top: 4px; }

/* Colored icon variety per card, echoing the same accent each module
   already uses elsewhere (terracotta tags bar/restaurant, clay for
   gold highlights) rather than inventing a new color-per-card scheme. */
#ovRoomsCard .admin-subhead-icon { color: var(--accent-green); }
#ovBookingsCard .admin-subhead-icon { color: var(--clay-dark); }
#ovTodayCard .admin-subhead-icon { color: var(--stone); }
#ovBarCard .admin-subhead-icon { color: var(--terracotta); }
#ovRestaurantCard .admin-subhead-icon { color: var(--terracotta-dark); }
#ovHousekeepingCard .admin-subhead-icon { color: var(--moss); }
#ovManagementCard .admin-subhead-icon { color: var(--primary); }
/* Cards below the stats row are nav-only now (title + button), so they
   should all land at roughly the same height instead of the wide
   variance that came from some of them also carrying big numbers. */
.overview-card--compact { min-height: 0; }
.overview-chart-card { margin-bottom: 22px; }
.overview-chart-wrap { position: relative; height: 220px; }
.overview-big-number { font-family: var(--font-display); font-size: 2.4rem; margin: 2px 0 0; color: var(--ink); }
.overview-today-row { display: flex; align-items: center; justify-content: space-between; font-size: 0.92rem; }
.overview-quicklinks { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: 10px; }
.overview-quick-action {
  display: flex; flex-direction: column; align-items: flex-start; gap: 8px;
  padding: 14px; border-radius: var(--radius-sm); border: 1px solid rgba(16, 24, 40, 0.10);
  background: var(--white); cursor: pointer; font-family: inherit; text-align: left;
  transition: border-color .12s var(--ease);
}
.overview-quick-action:hover { border-color: var(--accent-green); }
.overview-quick-action-icon {
  width: 34px; height: 34px; border-radius: 8px;
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.overview-quick-action-icon svg { width: 18px; height: 18px; }
.overview-quick-action-label { font-size: 0.86rem; font-weight: 600; color: var(--ink); }
.overview-quick-action--accent .overview-quick-action-icon { background: rgba(63, 164, 91, 0.12); color: var(--accent-green-dark); }
.overview-quick-action--clay .overview-quick-action-icon { background: var(--clay-bg); color: var(--clay-dark); }
.overview-quick-action--terracotta .overview-quick-action-icon { background: var(--terracotta-bg); color: var(--terracotta-dark); }

@media (max-width: 860px) {
  .app-sidebar {
    position: fixed;
    left: 0; top: 0; bottom: 0;
    width: 260px;
    transform: translateX(-100%);
    transition: transform .2s var(--ease);
    z-index: 20;
    box-shadow: var(--shadow-modal);
  }
  .app-sidebar.is-open { transform: translateX(0); }
  .app-sidebar.is-open ~ .app-sidebar-backdrop,
  .app-sidebar.is-open + .app-sidebar-backdrop {
    display: block;
  }
  .app-menu-toggle { display: flex; }
  .app-topbar { padding: 14px 16px; gap: 12px; }
  .app-content { padding: 18px 16px; }
  .app-topbar-date { display: block; }

  .reports-columns { grid-template-columns: minmax(0, 1fr); }
  .form-grid,
  .form-grid--tight { grid-template-columns: repeat(2, 1fr); }

  .module-tabs {
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
    padding-bottom: 2px;
  }
  .module-tab { flex-shrink: 0; }
}

@media (max-width: 640px) {
  .app-page-title { font-size: 1.15rem; }
  .app-content { padding: 16px 14px; }

  .form-grid,
  .form-grid--tight { grid-template-columns: 1fr; }
  .field-inline { min-width: 0; width: 100%; }
  .form-inline { align-items: stretch; }
  .form-inline .field-inline { flex: 1 1 140px; }

  .board-toolbar, .admin-toolbar { flex-direction: column; align-items: stretch; }
  .board-filters { justify-content: flex-start; }

  .room-grid { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }
  .order-grid { grid-template-columns: 1fr; }
  .stat-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .reservation-card { flex-direction: column; align-items: flex-start; }
  .reservation-card-rate { text-align: left; }

  .modal-actions .btn { flex: 1 1 auto; }
}

@media (max-width: 400px) {
  .stat-grid { grid-template-columns: minmax(0, 1fr); }
}
/* -------------------------------------------------------------
   Flat/modern refresh (Linear/Stripe-style: whitespace, thin
   borders instead of shadows and gradients, no hover-lift).
   Deliberately placed at the END of this file - .stat-card,
   .app-topbar, .app-nav-link.is-active, .room-card, .order-card,
   .quick-nav-item and .overview-card are all declared more than
   once earlier in this same file, so an override placed anywhere
   else would just get silently re-overridden by one of those later
   in the cascade. Scoped entirely to app.css, which only ever loads
   on the staff shell - main.css itself (shared with the public
   marketing site) is untouched, so welcome/rooms/dining keep their
   current look until that's asked for separately. Same green brand
   color throughout, just flatter and quieter.
   ------------------------------------------------------------- */
:root {
  --radius: 8px;
  --radius-lg: 12px;
  --shadow-card: 0 1px 2px rgba(16, 24, 40, 0.05);
  --shadow-modal: 0 12px 32px rgba(16, 24, 40, 0.18);
}

.card {
  background: var(--white);
  border: 1px solid rgba(16, 24, 40, 0.10);
  border-top: 4px solid var(--brass);
  box-shadow: var(--shadow-card);
}
/* Modals already get their own color accent from .modal-head, which
   sits flush against the top edge - adding this too would show as an
   ugly extra stripe directly above it. Table cards likewise already
   get a color accent from the primary-green header row inside them. */
.modal.card, .table-wrap.card { border-top: 1px solid rgba(16, 24, 40, 0.10); }

.btn:hover { transform: none; }
.btn:active { transform: none; }
.btn-primary:hover { box-shadow: none; }
.btn-brass:hover { box-shadow: none; }

.app-topbar { box-shadow: none; border-bottom: 1px solid rgba(16, 24, 40, 0.10); }

/* Active sidebar item: a thin brand-green accent edge instead of a
   solid filled block - the link stays legible on the dark sidebar
   without becoming its own loud shape. */
.app-nav-link.is-active {
  background: rgba(255, 255, 255, 0.07);
  color: var(--white);
  font-weight: 600;
  box-shadow: inset 3px 0 0 var(--accent-green);
}
.app-nav-link.is-active .app-nav-icon { opacity: 1; color: var(--accent-green); }

.stat-card, .room-card, .order-card, .quick-nav-item, .overview-card {
  border: 1px solid rgba(16, 24, 40, 0.10);
  box-shadow: none;
}
.stat-card:hover { box-shadow: none; transform: none; border-color: rgba(16, 24, 40, 0.2); }
.room-card[data-status] { border-left-width: 3px; }
.room-card--clickable:hover { box-shadow: none; border-color: rgba(16, 24, 40, 0.24); }
.quick-nav-item:hover, .overview-card:hover {
  box-shadow: none;
  transform: none;
  border-color: var(--accent-green);
}

.table-wrap--cards table.data-table tr { box-shadow: none; border: 1px solid rgba(16, 24, 40, 0.10); }
/* -------------------------------------------------------------
   Business analytics dashboard (Reports > Business)
   ------------------------------------------------------------- */
/* Keep the analytics pane contained inside the flexible app column.
   Chart canvases and grid children can otherwise use their intrinsic
   width and make the entire page a few pixels wider than the viewport. */
#businessPane {
  min-width: 0;
  width: 100%;
  max-width: 100%;
  overflow-x: clip;
}

#businessPane .business-card-grid,
#businessPane .business-dashboard-grid,
#businessPane .business-detail-grid,
#businessPane .business-detail-charts,
#businessPane .business-detail-lists {
  min-width: 0;
  max-width: 100%;
}

#businessPane .business-detail-charts > div,
#businessPane .business-detail-lists > div,
#businessPane .business-dashboard-grid > section {
  min-width: 0;
}

#businessPane .business-chart-wrap {
  width: 100%;
  max-width: 100%;
  min-width: 0;
  overflow: hidden;
}

#businessPane .business-chart-wrap canvas {
  display: block !important;
  max-width: 100% !important;
}

.business-toolbar { align-items: flex-end; gap: 20px; }
.business-toolbar > div:first-child { min-width: 280px; flex: 1; }
.business-controls { align-items: flex-end; flex-wrap: wrap; }
.business-controls .field { margin: 0; }
.business-range { margin: 6px 0 0; font-size: .78rem; }
.business-card-head { display:flex; align-items:center; justify-content:space-between; gap:10px; margin-bottom: 12px; }
.business-card-head .business-card-title { margin:0; }
.business-status { font-size:.68rem; font-weight:700; text-transform:uppercase; letter-spacing:.04em; padding:3px 7px; border-radius:999px; }
.business-status.is-profit { background:var(--moss-light); color:var(--accent-green-dark); }
.business-status.is-loss { background:var(--danger-bg); color:var(--danger); }
.business-dashboard-grid { display:grid; grid-template-columns: minmax(0, 2fr) minmax(280px, 1fr); gap:20px; margin-bottom:20px; }
.business-analytics-card--wide { grid-column:1 / -1; }
.business-detail-head { display:flex; align-items:flex-start; justify-content:space-between; gap:18px; margin-bottom:14px; }
.business-detail-head h3 { margin:0 0 4px; font-family:var(--font-display); font-size:1.1rem; color:var(--ink); }
.business-detail-head p { margin:0; }
.business-detail-net { text-align:right; white-space:nowrap; }
.business-detail-net span { display:block; font-size:.72rem; color:var(--stone); text-transform:uppercase; letter-spacing:.05em; }
.business-detail-net strong { font-family:var(--font-mono); font-size:1.15rem; color:var(--ink); }
.business-detail-net strong.is-negative, .business-loss-text { color:var(--danger); }
.business-chart-wrap { position:relative; height:270px; min-height:220px; }
.business-chart-wrap--large { height:330px; }
.business-dashboard-grid .business-analytics-card { min-width:0; }
.business-detail-grid { display:grid; grid-template-columns:1fr 1fr; gap:20px; margin-bottom:20px; }
.business-detail-card { min-width:0; }
.business-detail-card--rooms { grid-column:1 / -1; }
.business-detail-charts { display:grid; grid-template-columns:minmax(0, 1.5fr) minmax(0, 1fr); gap:20px; margin-top:8px; }
.business-chart-title { margin:0 0 8px; font-size:.82rem; font-weight:700; color:var(--ink); }
.business-mini-stats { display:grid; grid-template-columns:repeat(4,1fr); gap:10px; margin-bottom:18px; }
.business-mini-stats > div { background:var(--parchment-dim); border-radius:var(--radius-sm); padding:10px 12px; min-width:0; }
.business-mini-stats strong { display:block; color:var(--ink); font-family:var(--font-mono); font-size:.92rem; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.business-mini-stats span { display:block; margin-top:3px; color:var(--stone); font-size:.7rem; }
.business-detail-lists { display:grid; grid-template-columns:minmax(0, 1fr) minmax(0, 1fr); gap:20px; margin-top:20px; }
.business-item-list { display:flex; flex-direction:column; gap:0; border:1px solid var(--parchment-dim); border-radius:var(--radius-sm); overflow:hidden; }
.business-item-list > div { display:grid; grid-template-columns:minmax(0,1fr) auto; column-gap:12px; padding:9px 11px; border-bottom:1px solid var(--parchment-dim); font-size:.8rem; }
.business-item-list > div:last-child { border-bottom:0; }
.business-item-list span { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:var(--ink); }
.business-item-list strong { font-family:var(--font-mono); color:var(--ink); white-space:nowrap; }
.business-item-list small { grid-column:1 / -1; color:var(--stone); margin-top:3px; font-size:.7rem; }
.business-insight { margin:16px 0 0; padding:11px 13px; border-left:3px solid var(--brass); background:var(--parchment-dim); color:var(--ink-soft); font-size:.8rem; line-height:1.55; border-radius:0 var(--radius-sm) var(--radius-sm) 0; }
.business-report-note { margin-top:0; }

@media (max-width: 1050px) {
  /* minmax(0, 1fr), not a bare 1fr - see the note on .reports-columns. A single track is
     still a track with a min-content floor, and the Business dashboard holds tables and
     charts wide enough to set it. */
  .business-dashboard-grid, .business-detail-grid { grid-template-columns:minmax(0, 1fr); }
  .business-detail-card--rooms, .business-analytics-card--wide { grid-column:auto; }
}
@media (max-width: 760px) {
  .business-toolbar { align-items:stretch; }
  .business-controls { align-items:stretch; }
  .business-controls .field-inline { min-width:140px; }
  .business-mini-stats { grid-template-columns:1fr 1fr; }
  .business-detail-charts, .business-detail-lists { grid-template-columns:1fr; }
  .business-chart-wrap--large { height:280px; }
}

/* =============================================================
   Suppliers module
   ============================================================= */
.supplier-toolbar { margin-top: 18px; }
/* Supplier forms / modals — keep inputs visually consistent and easy to scan. */
.supplier-form {
  max-width: none;
  margin: 0;
  padding: 4px 0 0;
  background: transparent;
  border: 0;
  box-shadow: none;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px 18px;
}
.supplier-form .field { min-width: 0; }
.supplier-form .field-wide { grid-column: 1 / -1; }
.supplier-form .field-label { font-size: .78rem; font-weight: 700; color: var(--ink-soft); }
.supplier-form input,
.supplier-form select,
.supplier-form textarea {
  width: 100%;
  background: var(--white);
  border: 1px solid var(--line);
  color: var(--ink);
  padding: 10px 12px;
  min-height: 42px;
}
.supplier-form textarea { min-height: 104px; resize: vertical; }
.supplier-form input::placeholder,
.supplier-form textarea::placeholder { color: var(--stone); opacity: .72; }
.supplier-form .modal-actions { margin-top: 2px; padding-top: 14px; border-top: 1px solid var(--parchment-dim); }
.supplier-detail-modal .supplier-detail-grid { margin-top: 4px; }
.supplier-detail-modal .supplier-detail-item { background: var(--white); box-shadow: 0 2px 8px rgba(16,24,40,.035); }
.supplier-filters { margin: 0; }
.supplier-detail-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  margin: 6px 0 22px;
}
.supplier-detail-item {
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 11px 13px;
  background: rgba(255,255,255,.35);
  min-width: 0;
}
.supplier-detail-item span {
  display: block;
  color: var(--stone);
  font-size: .76rem;
  margin-bottom: 4px;
}
.supplier-detail-item strong {
  display: block;
  color: var(--ink);
  overflow-wrap: anywhere;
}
.supplier-next-note {
  margin: 16px 0 0;
  padding: 12px 14px;
  border-left: 3px solid var(--clay);
  background: rgba(158, 3, 172, .045);
  color: var(--ink-soft);
  font-size: .88rem;
}
@media (max-width: 760px) {
  .supplier-form { grid-template-columns: 1fr; }
  .supplier-form .field-wide { grid-column: auto; }
  .supplier-detail-grid { grid-template-columns: 1fr; }
  .supplier-filters { width: 100%; }
}

/* =============================================================
   Purchases / supplier receiving module
   ============================================================= */
.purchase-toolbar-actions { display:flex; gap:8px; flex-wrap:wrap; justify-content:flex-end; }
.purchase-filter-toolbar { margin-top:18px; }
.purchase-filters { margin:0; }
/* A purchase row the endpoint rejected. Marked with a border AND a left rule, never colour
   alone, and the reason is always in the error line naming the row - the marker only points
   at it. Cleared on every submit and on reset, so a stale red row never outlives the fix. */
.purchase-item-card.is-error {
  border-color: var(--danger);
  box-shadow: inset 3px 0 0 var(--danger);
  background: var(--danger-bg);
}
.purchase-stats { margin-bottom:4px; }
.purchase-balance-due { color:var(--clay); font-weight:700; }
.purchase-head-grid { margin-bottom:18px; }
.purchase-items-head { display:flex; align-items:center; justify-content:space-between; gap:12px; margin:8px 0 10px; }
.purchase-cost-note {
  display:flex;
  align-items:flex-start;
  gap:8px;
  margin: 0 0 12px;
  padding: 10px 12px;
  border: 1px solid rgba(63,164,91,.16);
  border-left: 3px solid var(--accent-green);
  border-radius: var(--radius-sm);
  background: rgba(63,164,91,.055);
  color: var(--ink-soft);
  font-size: .82rem;
  line-height: 1.5;
}
.purchase-cost-note strong { color: var(--accent-green); white-space: nowrap; }
.purchase-items-table .purchase-item-cost { font-family: var(--font-mono); font-weight: 700; }
.purchase-cost-help, .purchase-item-cost-hint { display:block; margin-top:4px; color:var(--stone); font-size:.68rem; line-height:1.35; }
.purchase-item-cost-hint { margin-top:5px; }
.purchase-items-head h4 { margin:0; font-family:var(--font-display); color:var(--ink); }
.purchase-items-table-wrap { overflow:auto; border:1px solid var(--line); border-radius:var(--radius-sm); }
.purchase-items-table { min-width:760px; }
.purchase-items-table td { vertical-align:middle; }
.purchase-items-table select, .purchase-items-table input { width:100%; min-width:0; }
.purchase-summary-grid { display:grid; grid-template-columns:minmax(150px,220px) minmax(150px,220px) minmax(230px,1fr); gap:12px; margin:16px 0; align-items:end; }
.purchase-total-box { border:1px solid var(--line); border-radius:var(--radius-sm); padding:12px 14px; display:grid; grid-template-columns:1fr auto; gap:6px 16px; background:rgba(255,255,255,.35); }
.purchase-total-box span { color:var(--stone); font-size:.78rem; }
.purchase-total-box strong { font-family:var(--font-mono); color:var(--ink); }
.purchase-total-box strong:last-child { font-size:1.05rem; }
.purchase-detail-grid { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:10px; margin:6px 0 22px; }
@media (max-width:900px){ .purchase-summary-grid { grid-template-columns:1fr 1fr; } .purchase-total-box { grid-column:1/-1; } .purchase-detail-grid { grid-template-columns:1fr 1fr; } }
@media (max-width:760px){ .purchase-toolbar-actions { justify-content:flex-start; } .purchase-filters { width:100%; } .purchase-summary-grid,.purchase-detail-grid { grid-template-columns:1fr; } .purchase-total-box { grid-column:auto; } }

/* Automatic management intelligence */
.business-intelligence { margin-bottom:20px; }
.business-insight-grid { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:12px; }
.business-cross-intelligence { margin-top:18px; }
.business-cross-table th, .business-cross-table td { vertical-align:middle; }
.business-cross-table td:first-child { min-width:150px; }
.business-cross-signals { margin-top:14px; }
.business-signal { border:1px solid var(--parchment-dim); border-left:3px solid var(--stone); border-radius:var(--radius-sm); padding:12px 14px; background:var(--parchment-dim); }
.business-signal.is-warning { border-left-color:var(--terracotta); }
.business-signal.is-positive { border-left-color:var(--accent-green); }
.business-signal.is-info { border-left-color:var(--brass); }
.business-signal-type { font-size:.65rem; text-transform:uppercase; letter-spacing:.06em; font-weight:700; color:var(--stone); margin-bottom:5px; }
.business-signal strong { color:var(--ink); font-size:.86rem; }
.business-signal p { margin:6px 0 0; color:var(--ink-soft); font-size:.76rem; line-height:1.5; }
.business-inventory-head { margin-top:20px; }
.business-mini-stats--inventory { margin-top:12px; }
.business-inventory-lists { margin-top:14px; }
@media (max-width: 900px) { .business-insight-grid { grid-template-columns:1fr; } }

/* Phase 5: stock intelligence */
.business-stock-intelligence { margin-top: 24px; padding-top: 24px; border-top: 1px solid rgba(0,0,0,.08); }
.business-stock-table-wrap { overflow-x: auto; margin-top: 16px; }
.business-stock-table { min-width: 820px; }
.business-stock-table td small { display:block; color:var(--text-muted, #777); margin-top:3px; }

/* -------------------------------------------------------------
   Business report inner navigation
   Keeps the Business report compact: one detailed section visible
   at a time instead of making the admin scroll through every unit.
   ------------------------------------------------------------- */
.business-subtabs {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0 0 18px;
  padding: 6px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: color-mix(in srgb, var(--primary) 8%, var(--white));
  overflow-x: auto;
  scrollbar-width: thin;
}
.business-subtab {
  flex: 0 0 auto;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--stone);
  padding: 9px 13px;
  font: inherit;
  font-size: .78rem;
  font-weight: 700;
  cursor: pointer;
  white-space: nowrap;
  transition: background .18s ease, color .18s ease, box-shadow .18s ease;
}
.business-subtab:hover {
  color: var(--ink);
  background: rgba(255,255,255,.7);
}
.business-subtab.is-active {
  color: var(--white);
  background: var(--primary);
  box-shadow: 0 2px 6px rgba(16,24,40,.14);
}
.business-subpane {
  min-width: 0;
  animation: businessPaneIn .18s ease;
}
.business-subpane[hidden] { display: none !important; }
.business-subpane.is-active { display: block; }
.business-subpane > .business-detail-card,
.business-subpane > div > .business-detail-card { margin-bottom: 0; }

@keyframes businessPaneIn {
  from { opacity: .55; transform: translateY(3px); }
  to { opacity: 1; transform: translateY(0); }
}

@media (max-width: 760px) {
  .business-subtabs {
    margin-bottom: 14px;
    padding: 5px;
  }
  .business-subtab {
    padding: 8px 11px;
    font-size: .74rem;
  }
}


.business-supplier-intelligence { margin-top: 18px; }
.business-supplier-table { min-width: 1040px; }
.business-supplier-table td small { display:block; color:var(--text-muted, #777); margin-top:3px; }
.business-supplier-status {
  display:inline-flex; align-items:center; padding:4px 8px; border-radius:999px;
  background:var(--surface-muted, rgba(0,0,0,.05)); color:var(--stone); font-size:.7rem; font-weight:700;
}
.business-supplier-status.is-warning { background:color-mix(in srgb, var(--danger, #b42318) 12%, var(--white)); color:var(--danger, #b42318); }
.business-supplier-status.is-positive { background:color-mix(in srgb, var(--primary, #2563eb) 12%, var(--white)); color:var(--primary, #2563eb); }
.business-supplier-status.is-info { background:color-mix(in srgb, var(--primary, #2563eb) 9%, var(--white)); color:var(--primary, #2563eb); }
.business-positive-text { color:var(--primary, #2563eb); }
.business-intelligence-footnote { margin:12px 0 0; font-size:.75rem; }


/* Expense intelligence */
.business-expense-intelligence { margin-top:24px; padding-top:24px; border-top:1px solid rgba(0,0,0,.08); }
.business-expense-table { min-width: 900px; }
.business-expense-signals { margin-top:14px; }

/* Management briefing */
.business-management-briefing { margin-top:18px; padding-top:18px; border-top:1px solid rgba(0,0,0,.08); }
.business-briefing-grid { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:12px; margin-top:14px; }
.business-briefing-actions { margin-top:16px; }
.business-briefing-action { display:grid; grid-template-columns:1fr auto; gap:4px 12px; border-left:3px solid var(--accent-green); border-bottom:1px solid var(--parchment-dim); padding:10px 12px; }
.business-briefing-action.is-warning { border-left-color:var(--terracotta); }
.business-briefing-action.is-info { border-left-color:var(--brass); }
.business-briefing-action span { font-weight:700; color:var(--ink); font-size:.82rem; }
.business-briefing-action strong { font-size:.64rem; letter-spacing:.06em; color:var(--stone); }
.business-briefing-action small { grid-column:1/-1; color:var(--ink-soft); font-size:.75rem; line-height:1.45; }
.business-briefing-quality { margin-top:16px; }
.business-briefing-quality .business-signal { margin-top:8px; }
@media (max-width:900px){ .business-briefing-grid { grid-template-columns:1fr; } }




/* =============================================================
   KAWA UI MODERNIZATION — PHASE 1
   Additive layer: preserves existing module markup and business
   colors while tightening the shell, controls, cards and states.
   ============================================================= */
.app-body {
  background: #f5f7f3;
  color: var(--ink);
}

.app-sidebar {
  width: 238px;
  padding: 18px 12px 14px;
  background: linear-gradient(180deg, var(--primary) 0%, var(--primary-dark) 100%);
  box-shadow: 8px 0 28px rgba(16, 24, 40, .08);
  z-index: 20;
}
.app-brand {
  min-height: 48px;
  margin-bottom: 20px;
  padding: 0 10px;
  border-radius: 12px;
}
.app-brand:hover { background: rgba(255,255,255,.06); }
.app-nav { gap: 4px; padding-right: 2px; }
.app-nav-link {
  min-height: 42px;
  padding: 10px 12px;
  border: 1px solid transparent;
  border-radius: 10px;
  font-size: .88rem;
  font-weight: 500;
  transition: background .18s var(--ease), color .18s var(--ease), transform .18s var(--ease), border-color .18s var(--ease);
}
.app-nav-link:hover { transform: translateX(2px); background: rgba(255,255,255,.07); }
.app-nav-link.is-active {
  background: var(--primary-light);
  color: #fff;
  border-color: rgba(255,255,255,.12);
  box-shadow: 0 6px 16px rgba(0,0,0,.12);
}
.app-nav-icon { width: 17px; height: 17px; }
.app-sidebar-foot { gap: 5px; }

.app-topbar {
  min-height: 68px;
  padding: 13px 28px;
  background: rgba(251,252,254,.96);
  border-bottom: 1px solid rgba(16,24,40,.08);
  box-shadow: 0 1px 0 rgba(109,79,194,.35), 0 6px 20px rgba(16,24,40,.035);
  backdrop-filter: blur(12px);
  z-index: 10;
}
.app-page-title {
  font-size: 1.35rem;
  font-weight: 600;
  letter-spacing: -.015em;
}
.app-topbar-date {
  color: var(--stone);
  font-size: .76rem;
  font-family: var(--font-mono);
  padding: 7px 10px;
  border: 1px solid rgba(16,24,40,.08);
  border-radius: 999px;
  background: rgba(255,255,255,.7);
}
.app-content { padding: 28px; }
.app-content-inner { max-width: 1500px; margin: 0 auto; }

.stat-card, .business-card, .overview-card, .admin-card, .panel-card {
  transition: transform .18s var(--ease), box-shadow .18s var(--ease), border-color .18s var(--ease);
}
.stat-card:hover, .business-card:hover, .overview-card:hover, .admin-card:hover, .panel-card:hover {
  transform: translateY(-1px);
  box-shadow: 0 8px 24px rgba(16,24,40,.09);
}

.btn {
  min-height: 38px;
  border-radius: 9px;
  font-weight: 600;
  letter-spacing: -.005em;
  transition: transform .16s var(--ease), box-shadow .16s var(--ease), background .16s var(--ease), border-color .16s var(--ease);
}
.btn:hover:not(:disabled) { transform: translateY(-1px); }
.btn-primary { box-shadow: 0 4px 12px rgba(63,164,91,.16); }

/*
 * A BUTTON'S LABEL NEVER WRAPS. Not in a table cell, not anywhere.
 *
 * Found by measurement, 2026-10-06, sweeping every screen for buttons whose own label occupies
 * more than one line box. Three, all of them the same fault:
 *
 *     admin > Staff    "Manage"          43px wide, 95px tall, SIX lines - one letter a line
 *     Purchases        "Cancel purchase"  83px wide, 56px tall, three lines
 *     Store            "Print label"      57px wide, 69px tall, four lines
 *
 * All three are action buttons in a plain <td> with no wrapper. The table gives the action column
 * whatever the other columns leave, the button fills that cell, and its label wraps to fit -
 * silently, with no error and no overflow, just a button nobody can read.
 *
 * The whole of the fault is that a button's width was allowed to be decided by its container.
 * A button's width is its label. Setting nowrap here means the cell's minimum width becomes the
 * label, so the table grows and the wrapper scrolls sideways - which it already does, because
 * .table-wrap is overflow-x:auto - instead of crushing the control.
 *
 * This is the third instance of the same family in this codebase: a toolbar button that measured
 * its own text as a height, then a filter row that swallowed the line beneath it. All three were
 * invisible to assertions about behaviour and visible only in a screenshot or a computed width.
 *
 * Scoped on purpose, and the scope is a judgement worth recording. app.css already decides, at
 * line ~3804, that "long labels can wrap inside buttons; this is preferable to making the entire
 * application wider than the viewport" - which is right in general, and is left standing. A long
 * label on a free-standing button wrapping is a lesser evil than a page-wide scrollbar.
 *
 * What is wrong is narrower than that: a button whose width is decided for it, by a column the
 * browser sized to leave room for the others. There the choice is not "wrap or widen the page" -
 * the table is ALREADY inside a .table-wrap that scrolls sideways - it is "wrap, or be unusable".
 * So the exception is the places where something else sets the width:
 *
 *     .data-table td/th .btn   a table action column
 *     .menu-item-row .btn      the catalogue rows, which are divs laid out like a table
 *     .menu-admin-chip         a short count chip - "19 need a barcode" has no second line
 *
 * The chips and the catalogue rows were found by the same sweep, after the table rule was
 * written: fixing three screens and immediately producing two more of the same thing is what a
 * sweep is for.
 */
.data-table td .btn,
.data-table th .btn,
.menu-item-row .btn,
.menu-admin-chip,
.btn.menu-admin-chip {
  white-space: nowrap;
}

.module-tab, .business-subtab, .board-filter {
  border-radius: 9px !important;
  font-weight: 600;
  transition: background .16s var(--ease), color .16s var(--ease), border-color .16s var(--ease);
}

.data-table { border-radius: 10px; overflow: hidden; }
.data-table th { font-size: .72rem; letter-spacing: .04em; text-transform: uppercase; }
.data-table td { font-size: .82rem; }

input, select, textarea {
  border-radius: 9px;
  transition: border-color .16s var(--ease), box-shadow .16s var(--ease), background .16s var(--ease);
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--accent-green) !important;
  box-shadow: 0 0 0 3px rgba(63,164,91,.10);
}

.loading-state { min-height: 150px; }

/* Global Kawa AI */
.kawa-ai-fab {
  position: fixed;
  right: 24px;
  bottom: 24px;
  z-index: 35;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 48px;
  padding: 0 16px 0 11px;
  border: 1px solid rgba(255,255,255,.18);
  border-radius: 999px;
  color: #fff;
  background: linear-gradient(135deg, var(--primary) 0%, var(--accent-green) 100%);
  box-shadow: 0 12px 28px rgba(16,24,40,.24), 0 0 0 5px rgba(63,164,91,.08);
  cursor: pointer;
  font: 600 .78rem var(--font-body);
  transition: transform .18s var(--ease), box-shadow .18s var(--ease);
}
.kawa-ai-fab:hover { transform: translateY(-2px) scale(1.01); box-shadow: 0 16px 34px rgba(16,24,40,.28), 0 0 0 6px rgba(63,164,91,.10); }
.kawa-ai-fab:focus-visible { outline: 3px solid rgba(146,119,219,.75); outline-offset: 3px; }
.kawa-ai-fab-icon {
  display: grid; place-items: center;
  width: 27px; height: 27px;
  border-radius: 50%;
  background: rgba(255,255,255,.14);
  font-size: 1rem;
}
/*
  THE ASK KAWA BUTTON IS ALIVE, QUIETLY.

  It sits in the corner of every screen and most people never find it. A slow ring drifting outward
  says "there is something here" without a word, which is the whole job.

  THE RING IS A PSEUDO-ELEMENT, AND THAT IS THE POINT. The button already owns its transform -
  :hover does translateY(-2px) scale(1.01). Animating transform on the button itself would either
  fight that rule or replace it, and the hover would break. The ring scales instead, so the button
  keeps its own transform entirely and the two never collide.

  IT STOPS WHEN IT IS NOT WANTED. Not while the assistant is open, because a pulsing button behind
  an open panel is noise. And not after the first use - the ring exists to advertise something
  nobody has discovered yet, so once it has been discovered the advertisement has done its job and
  after that it only gets in the way.

  IT IS OPT-OUT FOR ANYONE WHO ASKED. prefers-reduced-motion is honoured outright below rather than
  being dialled down, because a gentle pulse is still motion and somebody who has turned motion off
  on this device meant it. With no animation at all the button is still perfectly usable: it carries
  a label and an icon, so nothing about it is ever conveyed by movement alone.

  The scale stops at 1.22 and the border fades to nothing, so it never grows enough to cover the
  table underneath - this button is fixed and already overlaps content on a short screen.
*/
.kawa-ai-fab::after {
  content: "";
  position: absolute;
  inset: 0;
  border: 2px solid rgba(63,164,91,.60);
  border-radius: 999px;
  pointer-events: none;
  opacity: 0;
  animation: kawaFabPulse 2.9s var(--ease) infinite;
}
.kawa-ai-fab .kawa-ai-fab-icon { animation: kawaFabBob 2.9s ease-in-out infinite; }
@keyframes kawaFabPulse {
  0%   { opacity: 0;    transform: scale(1); }
  30%  { opacity: .55; }
  100% { opacity: 0;    transform: scale(1.22); }
}
@keyframes kawaFabBob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-2px); }
}
/* open, or already used - the ring has said what it needed to say */
.kawa-ai-fab.is-open::after,
.kawa-ai-fab.is-used::after { animation: none; opacity: 0; }
.kawa-ai-fab.is-open .kawa-ai-fab-icon,
.kawa-ai-fab.is-used .kawa-ai-fab-icon { animation: none; }

/* Somebody asked for less motion. Honoured fully, not dialled down. Placed last so it wins. */
@media (prefers-reduced-motion: reduce) {
  .kawa-ai-fab::after,
  .kawa-ai-fab .kawa-ai-fab-icon { animation: none !important; }
  .kawa-ai-fab::after { opacity: 0; }
}
.kawa-ai-overlay { position: fixed; inset: 0; z-index: 50; display: grid; place-items: end; padding: 24px; }
.kawa-ai-backdrop { position: absolute; inset: 0; background: rgba(12,21,51,.38); backdrop-filter: blur(2px); }
.kawa-ai-modal {
  position: relative;
  width: min(460px, 100%);
  max-height: min(720px, calc(100vh - 48px));
  overflow: hidden;
  border: 1px solid rgba(16,24,40,.10);
  border-radius: 18px;
  background: var(--white);
  box-shadow: 0 28px 80px rgba(12,21,51,.28);
  animation: kawaAiIn .18s var(--ease) both;
}
@keyframes kawaAiIn { from { opacity: 0; transform: translateY(10px) scale(.985); } to { opacity: 1; transform: translateY(0) scale(1); } }
.kawa-ai-header { display:flex; align-items:center; justify-content:space-between; gap:14px; padding:16px 18px; background:linear-gradient(135deg,var(--primary),var(--accent-green)); color:#fff; }
.kawa-ai-heading { display:flex; align-items:center; gap:11px; min-width:0; }
.kawa-ai-mark { display:grid; place-items:center; width:38px; height:38px; flex-shrink:0; border-radius:12px; background:rgba(255,255,255,.14); font-size:1.15rem; }
.kawa-ai-header h2 { margin:0; font:600 1.05rem var(--font-display); }
.kawa-ai-header p { margin:2px 0 0; font-size:.7rem; color:rgba(255,255,255,.72); }
.kawa-ai-close { width:34px; height:34px; border:0; border-radius:9px; background:rgba(255,255,255,.10); color:#fff; cursor:pointer; font-size:1.35rem; line-height:1; }
.kawa-ai-close:hover { background:rgba(255,255,255,.18); }
.kawa-ai-body { padding:16px; overflow:auto; max-height:calc(100vh - 145px); }
.kawa-ai-welcome { display:flex; flex-direction:column; gap:4px; padding:12px 13px; border:1px solid rgba(16,24,40,.08); border-radius:12px; background:#f7f9fc; }
.kawa-ai-welcome strong { font-size:.84rem; }
.kawa-ai-welcome span { color:var(--stone); font-size:.74rem; line-height:1.5; }
.kawa-ai-quick { display:flex; flex-wrap:wrap; gap:7px; margin:12px 0; }
.kawa-ai-chip { border:1px solid rgba(16,24,40,.10); border-radius:999px; background:#fff; color:var(--ink); padding:7px 10px; font:600 .68rem var(--font-body); cursor:pointer; }
.kawa-ai-chip:hover { border-color:rgba(63,164,91,.32); background:rgba(63,164,91,.05); }
.kawa-ai-answer { min-height:96px; margin-bottom:12px; padding:13px; border-radius:12px; border:1px solid rgba(16,24,40,.08); background:#fff; }
.kawa-ai-answer-placeholder { color:var(--stone); font-size:.75rem; }
.kawa-ai-thinking { display:flex; align-items:center; gap:9px; color:var(--stone); font-size:.74rem; }
.kawa-ai-answer-head { display:flex; justify-content:space-between; gap:10px; margin-bottom:8px; font-size:.75rem; }
.kawa-ai-answer-head span { color:var(--stone); text-transform:uppercase; letter-spacing:.06em; font-size:.62rem; }
.kawa-ai-answer-body { font-size:.78rem; line-height:1.6; }
.kawa-ai-unavailable { padding:2px; }
.kawa-ai-unavailable strong { font-size:.78rem; }
.kawa-ai-unavailable p { margin:5px 0 0; color:var(--stone); font-size:.73rem; line-height:1.5; }
.kawa-ai-form { display:grid; grid-template-columns:1fr auto; gap:8px; align-items:end; }
.kawa-ai-input-wrap textarea { display:block; width:100%; min-height:62px; resize:vertical; padding:10px 11px; border:1px solid rgba(16,24,40,.12); background:#fff; font: .76rem/1.5 var(--font-body); color:var(--ink); }
.kawa-ai-submit { min-width:92px; min-height:62px; }
.kawa-ai-footnote { margin:9px 1px 0; color:var(--stone); font-size:.64rem; line-height:1.45; }
.sr-only { position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0; }

@media (max-width: 900px) {
  .app-sidebar { width: 238px; }
  .app-content { padding: 22px 18px; }
  .app-topbar { padding: 12px 18px; }
}
@media (max-width: 700px) {
  .app-nav { gap: 10px; }
  .app-nav-section-label { padding-left: 8px; }
  .app-topbar-date { display:none; }
  .kawa-ai-fab { right:16px; bottom:16px; }
  .kawa-ai-fab-label { display:none; }
  .kawa-ai-fab { width:48px; height:48px; padding:0; justify-content:center; }
  .kawa-ai-overlay { padding:10px; place-items:end center; }
  .kawa-ai-modal { width:100%; max-height:calc(100vh - 20px); border-radius:16px; }
  .kawa-ai-form { grid-template-columns:1fr; }
  .kawa-ai-submit { min-height:42px; }
}

/* ================================================================
   Phase 2 — Central Store
   ================================================================ */
.store-toolbar { align-items: flex-start; }
.store-toolbar-actions { display:flex; gap:8px; flex-wrap:wrap; }
.store-filter-toolbar { margin-top: 16px; }
.store-filters { align-items:flex-end; flex-wrap:wrap; gap:10px; }
.store-filters .field-inline { min-width:170px; }
.store-table-wrap { margin-top:16px; overflow-x:auto; }
.store-table { min-width:900px; }
.store-table td small { display:block; margin-top:3px; }
.store-transfer-head { margin-bottom:16px; }
.store-transfer-row .store-transfer-available { white-space:nowrap; min-width:80px; }
.store-transfer-row select { min-width:260px; }
@media (max-width: 760px) {
  .store-toolbar { flex-direction:column; }
  .store-toolbar-actions { width:100%; }
  .store-toolbar-actions .btn { flex:1; }
  .store-filters { display:grid; grid-template-columns:1fr 1fr; width:100%; }
  .store-filters .field-inline { min-width:0; }
}

/* Phase 3 barcode label controls */
.barcode-label-preview { display:flex; align-items:center; gap:10px; }

/* Phase 5 — edit authorization / notifications */
.app-notification-wrap{position:relative;margin-left:auto}.app-notification-btn{position:relative;border:0;background:transparent;cursor:pointer;padding:8px 10px;border-radius:10px;color:inherit}.app-notification-btn:hover{background:rgba(255,255,255,.08)}.app-notification-icon{font-size:18px}.app-notification-badge{position:absolute;top:1px;right:2px;min-width:17px;height:17px;padding:0 4px;border-radius:99px;background:#d33;color:#fff;font:700 10px/17px sans-serif;text-align:center}.app-notification-panel{position:absolute;right:0;top:44px;width:360px;max-width:calc(100vw - 30px);background:#fff;color:#222;border:1px solid rgba(0,0,0,.08);border-radius:14px;box-shadow:0 16px 45px rgba(0,0,0,.18);z-index:1000;overflow:hidden}.app-notification-head{display:flex;justify-content:space-between;align-items:center;padding:13px 15px;border-bottom:1px solid #eee}.app-notification-item{display:block;width:100%;text-align:left;border:0;background:transparent;padding:12px 15px;cursor:pointer;border-bottom:1px solid #f0f0f0}.app-notification-item:hover,.app-notification-item.is-unread{background:#f7f5fb}.app-notification-item strong,.app-notification-item span,.app-notification-item small{display:block}.app-notification-item span{font-size:12px;margin-top:4px}.app-notification-item small{font-size:10px;color:#888;margin-top:5px}.admin-control-card{margin-top:18px;padding:18px}.review-details{padding:12px;border:1px solid rgba(0,0,0,.08);border-radius:10px;margin-bottom:14px}.review-details div{margin:6px 0}.app-topbar{position:relative}

/* Phase 5B - controlled purchase correction notice */
.notice { margin: 0 0 18px; padding: 12px 14px; border: 1px solid var(--border); border-radius: 12px; background: var(--surface-soft); font-size: 13px; line-height: 1.55; }
.notice-warning { border-color: rgba(180, 120, 20, .28); background: rgba(180, 120, 20, .08); }

/* Phase 5C — fixed staff header and central stock-control modal. */
.app-topbar {
  position: fixed;
  top: 0;
  left: 238px;
  right: 0;
  z-index: 40;
}
.app-main { min-width: 0; }
.app-content { padding-top: 96px; }

/* Keep modal headings readable even when later module styles override
   generic heading colors. The header itself is the source of truth. */
.modal-overlay .modal-head,
.modal-overlay .modal-head h1,
.modal-overlay .modal-head h2,
.modal-overlay .modal-head h3,
.modal-overlay .modal-head .modal-subtitle {
  color: var(--white) !important;
}
.modal-overlay .modal-head h1,
.modal-overlay .modal-head h2,
.modal-overlay .modal-head h3 {
  opacity: 1 !important;
  visibility: visible !important;
}

.stock-control-modal { max-width: 720px; }
.stock-control-body { padding: 22px; }
.stock-control-summary {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 8px;
  margin-bottom: 14px;
}
.stock-control-summary > div {
  padding: 11px 10px;
  border: 1px solid rgba(16,24,40,.09);
  border-radius: 8px;
  background: var(--parchment-flat);
}
.stock-control-summary span,
.stock-control-summary strong { display: block; }
.stock-control-summary span { font-size: .68rem; color: var(--stone); text-transform: uppercase; letter-spacing: .04em; }
.stock-control-summary strong { margin-top: 4px; font-family: var(--font-mono); font-size: .82rem; color: var(--ink); }
.stock-control-help { margin: 0 0 16px; line-height: 1.55; }
.stock-control-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.stock-control-action {
  text-align: left;
  border: 1px solid rgba(16,24,40,.10);
  background: var(--white);
  border-radius: 9px;
  padding: 14px;
  cursor: pointer;
  font-family: var(--font-body);
}
.stock-control-action:hover { border-color: var(--primary); background: var(--parchment-flat); }
.stock-control-action strong { display:block; color: var(--primary); margin-bottom: 4px; }
.stock-control-action span { display:block; color: var(--stone); font-size: .78rem; line-height: 1.45; }
.stock-control-action--highlight { border-color: rgba(109,79,194,.45); }

@media (max-width: 900px) {
  .app-topbar { left: 0; }
  .app-content { padding-top: 90px; }
  .stock-control-summary { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .stock-control-summary { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .stock-control-grid { grid-template-columns: 1fr; }
}

/* =============================================================
   Control / edit-state clarity
   Make editable fields, permission states and edit actions obvious.
   ============================================================= */
.field input,
.field select,
.field textarea,
.supplier-form input,
.supplier-form select,
.supplier-form textarea {
  background: #FFFFFF;
  color: var(--ink);
  border-color: #b9c2d6;
}

.field input:not([disabled]):not([readonly]),
.field select:not([disabled]),
.field textarea:not([disabled]):not([readonly]) {
  box-shadow: inset 0 1px 2px rgba(16,24,40,.035);
}

.field input:disabled,
.field select:disabled,
.field textarea:disabled,
.field input[readonly],
.field textarea[readonly] {
  background: #eef1f6;
  color: var(--stone);
  border-color: #d3dae6;
  cursor: not-allowed;
}

.field input:not([disabled]):not([readonly]):focus,
.field select:not([disabled]):focus,
.field textarea:not([disabled]):not([readonly]):focus {
  border-color: var(--accent-green);
  box-shadow: 0 0 0 3px rgba(63,164,91,.13);
}

/* Explicit visual language for edit/configure actions. */
[data-edit-permission],
[data-detail-edit],
[data-purchase-correct],
[data-payment-correct],
[data-edit-item],
[data-edit-category],
[data-edit-room],
[data-edit-type] {
  background: var(--accent-green);
  color: var(--white);
  border-color: var(--accent-green);
}

[data-edit-permission]:hover,
[data-detail-edit]:hover,
[data-purchase-correct]:hover,
[data-payment-correct]:hover,
[data-edit-item]:hover,
[data-edit-category]:hover,
[data-edit-room]:hover,
[data-edit-type]:hover {
  background: var(--accent-green-dark);
  color: var(--white);
  border-color: var(--accent-green-dark);
}

/* Keep destructive/review actions unmistakable. */
#rejectEditBtn { background: var(--danger); color: var(--white); border-color: var(--danger); }
#rejectEditBtn:hover { background: #8A2A21; color: var(--white); }
#approveEditBtn,
#supplierSaveBtn { background: var(--primary); color: var(--white); }

/* Permission values rendered as compact state badges. */
.edit-state-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  min-width: 52px;
  justify-content: center;
  padding: 4px 8px;
  border-radius: 999px;
  font-size: .72rem;
  font-weight: 700;
  line-height: 1;
}
.edit-state-badge::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.edit-state-badge.is-yes { background: var(--moss-light); color: var(--accent-green-dark); }
.edit-state-badge.is-no { background: var(--danger-bg); color: var(--danger); }

/* Correction request details should read as a controlled record,
   not a plain block of text. */
.review-details {
  margin: 0 0 18px;
  padding: 14px 16px;
  background: #f7f9fc;
  border: 1px solid #D7DED4;
  border-left: 3px solid var(--accent-green);
  border-radius: var(--radius-sm);
  color: var(--ink-soft);
}
.review-details pre {
  margin: 8px 0 0;
  padding: 10px;
  background: #FFFFFF;
  border: 1px solid #D7DED4;
  border-radius: var(--radius-sm);
  overflow: auto;
  font-family: var(--font-mono);
  font-size: .72rem;
  color: var(--ink);
}

.supplier-detail-modal .modal-head .btn,
#supplierDetailOverlay .modal-head .btn {
  margin-left: auto;
  flex-shrink: 0;
}

@media (max-width: 760px) {
  .supplier-detail-modal .modal-head,
  #supplierDetailOverlay .modal-head { gap: 8px; }
  .supplier-detail-modal .modal-head .btn,
  #supplierDetailOverlay .modal-head .btn { font-size: .74rem; padding: 6px 10px; }
}

/* Dynamic purchase-item rows (created by purchases.js) */
.purchase-items-table tbody tr.purchase-item-row { background: #fbfcfe; }
.purchase-items-table tbody tr.purchase-item-row:hover { background: #f7f9fc; }
.purchase-items-table .purchase-item-row td { padding: 10px 9px; border-bottom: 1px solid #E1E7DF; }
.purchase-items-table .purchase-item-row .field-label,
.purchase-items-table .purchase-item-row label { margin: 0; }
.purchase-items-table .purchase-item-select,
.purchase-items-table .purchase-item-qty,
.purchase-items-table .purchase-item-cost {
  width: 100%; min-height: 38px; box-sizing: border-box;
  border: 1px solid #b9c2d6; border-radius: 8px;
  background: #FFFFFF; color: #152250; padding: 8px 10px;
  font: 500 .82rem var(--font-sans);
  outline: none; transition: border-color .15s ease, box-shadow .15s ease, background .15s ease;
}
.purchase-items-table .purchase-item-select:focus,
.purchase-items-table .purchase-item-qty:focus,
.purchase-items-table .purchase-item-cost:focus {
  border-color: var(--accent-green); box-shadow: 0 0 0 3px rgba(63,164,91,.12); background: #FFFFFF;
}
.purchase-items-table .purchase-item-qty,
.purchase-items-table .purchase-item-cost { font-family: var(--font-mono); }
.purchase-items-table .purchase-item-qty { min-width: 92px; }
.purchase-items-table .purchase-item-cost { min-width: 125px; }
.purchase-items-table .purchase-unit-cell { min-width: 150px; }
.purchase-items-table .purchase-unit-badge { display: inline-flex; }
.purchase-items-table .purchase-unit-help {
  display: block; margin-top: 5px; color: var(--stone); font-size: .66rem; line-height: 1.3;
}
.purchase-items-table .purchase-item-cost-hint,
.purchase-items-table .purchase-cost-help {
  display: block; margin-top: 5px; color: var(--stone); font-size: .67rem; line-height: 1.35;
}
.purchase-items-table .purchase-stock-preview {
  display: inline-flex; align-items: center; min-height: 30px; padding: 5px 9px;
  border-radius: 7px; background: #F0F5EF; border: 1px solid #D4E0D2;
  color: var(--primary); font: 700 .76rem var(--font-mono); white-space: nowrap;
}
.purchase-items-table .purchase-line-total {
  display: inline-block; min-width: 86px; padding-top: 9px; color: var(--primary); font-weight: 800; white-space: nowrap;
}
.purchase-items-table .purchase-remove-item {
  white-space: nowrap; color: var(--danger); border-color: #D7B7B2; background: #FFF8F6;
}
.purchase-items-table .purchase-remove-item:hover { background: #FCEDEA; border-color: var(--danger); color: var(--danger); }

/* Inventory unit + purchase packaging controls */
.unit-config-card {
  padding: 16px;
  border: 1px solid #D3DCCF;
  border-radius: 12px;
  background: #F8FAF6;
  margin-top: 2px;
}
.unit-config-heading { font-weight: 700; color: var(--primary); margin-bottom: 3px; }
.unit-config-help { margin-bottom: 12px; }
.unit-config-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
.unit-conversion-preview {
  margin-top: 12px;
  padding: 10px 12px;
  border-radius: 8px;
  background: #e9edf6;
  border: 1px solid #C5DCCB;
  color: var(--accent-green-dark);
  font: 600 .78rem var(--font-mono);
}
.field-label-note { font-size: .68rem; font-weight: 500; color: var(--stone); }
.purchase-items-table { min-width: 920px; }
.purchase-items-table th, .purchase-items-table td { vertical-align: top; }
.purchase-items-table .purchase-item-select { min-width: 210px; }
.purchase-unit-badge {
  display: inline-flex; align-items: center; min-height: 30px; padding: 5px 9px;
  border-radius: 999px; background: #e9edf6; border: 1px solid #C5DCCB;
  color: var(--accent-green-dark); font-size: .72rem; font-weight: 700; white-space: nowrap;
}
.purchase-stock-preview { display: inline-block; padding-top: 9px; font-weight: 700; color: var(--primary); white-space: nowrap; }
.purchase-cost-help, .purchase-item-cost-hint { display:block; margin-top:4px; color:var(--stone); font-size:.68rem; line-height:1.35; }
.modal-overlay .modal-head p.text-stone { color: rgba(255,255,255,.80) !important; font-size: .76rem; line-height: 1.45; margin-top: 4px; max-width: 760px; }
.modal-overlay .modal-head .text-stone { color: rgba(255,255,255,.80) !important; }

@media (max-width: 850px) {
  .unit-config-grid { grid-template-columns: 1fr; }
}

/* =============================================================
   KAWA SHELL FIX — fixed sidebar/header + independent scrolling
   ============================================================= */
.app-shell { min-height: 100vh; }
.app-sidebar {
  position: fixed;
  inset: 0 auto 0 0;
  width: 238px;
  height: 100vh;
  min-height: 0;
  overflow: hidden;
  box-sizing: border-box;
  z-index: 50;
}
.app-nav {
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: thin;
}
.app-sidebar-foot { flex-shrink: 0; }
.app-main {
  width: calc(100% - 238px);
  margin-left: 238px;
  min-width: 0;
  min-height: 100vh;
  box-sizing: border-box;
}
.app-topbar {
  position: fixed;
  top: 0;
  left: 238px;
  right: 0;
  width: auto;
  box-sizing: border-box;
  z-index: 40;
}
.app-content { padding-top: 96px; }

/* Correction modal source indicator */
#saleCorrectionSource { margin: 0; padding: 9px 11px; border-left: 3px solid var(--accent-green); background: #f3f7f2; border-radius: 7px; color: var(--primary); font-weight: 600; }
#saleCorrectionOriginal { margin: 0; padding: 9px 11px; background: var(--parchment-flat); border: 1px solid var(--line); border-radius: 7px; }

@media (max-width: 900px) {
  .app-sidebar { width: 238px; transform: translateX(-100%); }
  .app-main { width: 100%; margin-left: 0; }
  .app-topbar { left: 0; width: 100%; }
  .app-content { padding-top: 90px; }
}


/* Business date / Night Audit settings */
.business-day-settings-grid{display:grid;grid-template-columns:minmax(220px,.7fr) minmax(320px,1fr);gap:18px;align-items:stretch}
.business-day-current{display:flex;flex-direction:column;justify-content:center;gap:6px;padding:18px;border:1px solid #dde4ef;border-radius:14px;background:#f7f9fc}
.business-day-current strong{font-size:26px;letter-spacing:-.02em;color:#152250}
.business-day-current small{font-size:12px}
.business-day-form{padding:4px 0}
.business-day-meaning{margin:14px 0 0;padding:12px 14px;border-left:3px solid var(--accent-green);background:#f7f9fc;border-radius:8px}
@media(max-width:700px){.business-day-settings-grid{grid-template-columns:1fr}}

/* =============================================================
   NIGHT AUDIT / END-OF-DAY CONTROL
   ============================================================= */
.night-audit-toolbar{display:grid;grid-template-columns:minmax(180px,240px) minmax(260px,1fr) auto;gap:14px;align-items:end}
.night-audit-period{min-height:64px;padding:12px 14px;display:flex;flex-direction:column;justify-content:center;gap:3px;background:#f7f9fc;border:1px solid #dde4ef;border-radius:12px}
.night-audit-period strong{color:#152250;font-size:16px}.night-audit-period span{font-size:12px;color:var(--stone)}
.night-audit-actions{display:flex;gap:8px;align-items:center;padding-bottom:1px}
.night-audit-summary{display:grid;grid-template-columns:repeat(5,minmax(130px,1fr));gap:10px;margin:16px 0}
.night-audit-stat{padding:12px;border:1px solid #dde4ef;border-radius:11px;background:#fff;min-width:0}.night-audit-stat span{display:block;color:var(--stone);font-size:11px;margin-bottom:5px}.night-audit-stat strong{display:block;color:var(--primary);font-size:17px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.night-audit-alert{padding:12px 14px;border-radius:10px;margin-top:12px}.night-audit-alert ul{margin:7px 0 0 18px;padding:0}.night-audit-alert.is-blocker{background:#fff2f2;border:1px solid #efcaca;color:#8d2323}.night-audit-alert.is-warning{background:#fff9ed;border:1px solid #eed9a8;color:#765719}.night-audit-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-top:14px}.night-audit-panel{padding:14px}.night-audit-panel h4{margin:0 0 10px;color:var(--primary)}.night-audit-note-row{margin-top:14px}.night-audit-status{margin:10px 0 0;padding:10px 12px;background:#f7f9fc;border-left:3px solid var(--accent-green);border-radius:7px}
@media(max-width:1000px){.night-audit-summary{grid-template-columns:repeat(3,1fr)}}
@media(max-width:760px){.night-audit-toolbar,.night-audit-grid{grid-template-columns:1fr}.night-audit-actions{padding-bottom:0}.night-audit-summary{grid-template-columns:repeat(2,1fr)}}

/* Inventory unit controls */
.unit-config-card select,
.purchase-item-unit,
.purchase-custom-unit,
.purchase-custom-factor { width:100%; }
.purchase-item-unit { min-width:140px; }
.purchase-custom-unit { margin-top:6px; }
.purchase-custom-factor { margin-top:6px; }
.purchase-unit-help { display:block; margin-top:5px; color:var(--stone,#667085); font-size:12px; line-height:1.35; }
.purchase-unit-cell { min-width:190px; }


/* Inventory unit UX: make the stock/selling unit rule obvious without making
   every existing product look like a permanently disabled field. */
.unit-lock-note {
  display: inline-flex;
  width: fit-content;
  margin-top: 5px;
  padding: 4px 8px;
  border-radius: 999px;
  background: #eef1f6;
  color: #5b6472;
  border: 1px solid #D5DDD2;
  font-size: 11px;
  font-weight: 700;
}
.unit-config-card select[name="stock_unit"]:disabled {
  opacity: .82;
  background: #eef1f6;
  color: #414b5c;
  border-color: #d8dee9;
  cursor: not-allowed;
}

/* Reception workspace: compact operational layout */
.reception-toolbar{align-items:flex-start;gap:16px}
.reception-toolbar .section-title{margin:0 0 4px}
.reception-actions{display:flex;gap:8px;flex-wrap:wrap}
.reception-stat-grid{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:12px;margin:16px 0}
.reception-stat{background:var(--surface,#fff);border:1px solid var(--line,#d8dee9);border-radius:12px;padding:14px 16px}
.reception-stat span{display:block;font-size:12px;color:var(--stone,#667085);margin-bottom:5px}
.reception-stat strong{font-size:22px;color:var(--ink,#1a2433)}
.reception-stay-columns{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px}
.reception-list-card{overflow:hidden}
.reception-list-head{display:flex;align-items:center;justify-content:space-between;padding:15px 16px;border-bottom:1px solid var(--line,#d8dee9)}
.reception-list-head h4{margin:0}
.reception-stay-list{padding:4px 14px}
.reception-stay-item{display:flex;justify-content:space-between;gap:12px;padding:13px 2px;border-bottom:1px solid var(--line,#d8dee9)}
.reception-stay-item:last-child{border-bottom:0}
.reception-stay-right{display:flex;align-items:center;gap:7px;flex-wrap:wrap;justify-content:flex-end}
.reception-search-card{padding:18px}
.reception-search-row{display:flex;gap:10px;max-width:760px}
.reception-search-row input{flex:1;min-width:0}
.reception-search-card .table-wrap{margin-top:16px}
.reception-search-card .field-hint{margin-top:7px}
.empty-state{padding:24px;text-align:center;color:var(--stone,#667085)}
@media(max-width:1100px){
 .reception-stat-grid{grid-template-columns:repeat(3,minmax(0,1fr))}
 .reception-stay-columns{grid-template-columns:1fr}
}
@media(max-width:700px){
 .reception-stat-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
 .reception-toolbar,.reception-search-row{flex-direction:column}
 .reception-search-row .btn{width:100%}
}


/* Tables: calm hierarchy and easier scanning on dense operational screens. */
.data-table th {
  font-size: .72rem;
  letter-spacing: .045em;
  text-transform: uppercase;
  color: var(--stone);
  background: var(--moss-light);
}
.data-table td { vertical-align: middle; }
.data-table tbody tr:hover { background: rgba(232, 238, 228, .72); }
.data-table .num { font-variant-numeric: tabular-nums; }

/* Daily stock ledger */
.stock-ledger-shell{margin-top:16px}.stock-ledger-shell .section-title{margin:0 0 4px}.stock-ledger-shell .data-table{min-width:860px}.stock-ledger-shell .is-positive{color:#287342}.stock-ledger-shell .is-negative{color:#9a3030}
.stock-ledger-toggle-row{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:16px;padding:10px 12px;background:var(--moss-light);border:1px solid var(--line);border-radius:var(--radius-sm)}.stock-ledger-toggle-row .text-stone{font-size:.8rem}.stock-ledger-shell{margin-top:10px}

/* Purchase module — dynamic JavaScript controls polish */
.purchase-items-table tbody tr.purchase-item-row {
  transition: background .16s ease, box-shadow .16s ease;
}
.purchase-items-table tbody tr.purchase-item-row:focus-within {
  background: #F9FCF8;
  box-shadow: inset 3px 0 0 var(--accent-green);
}
.purchase-items-table .purchase-item-row td:first-child { min-width: 190px; }
.purchase-items-table .purchase-item-row td:nth-child(2) { min-width: 180px; }
.purchase-items-table .purchase-item-row td:nth-child(3) { min-width: 110px; }
.purchase-items-table .purchase-item-row td:nth-child(4) { min-width: 145px; }

.purchase-items-table .purchase-custom-unit,
.purchase-items-table .purchase-custom-factor {
  width: 100%;
  min-height: 36px;
  box-sizing: border-box;
  margin-top: 6px;
  padding: 8px 10px;
  border: 1px solid #b9c2d6;
  border-radius: 8px;
  background: #FFFFFF;
  color: #152250;
  font: 500 .78rem var(--font-sans);
  outline: none;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.purchase-items-table .purchase-custom-factor { font-family: var(--font-mono); }
.purchase-items-table .purchase-custom-unit:focus,
.purchase-items-table .purchase-custom-factor:focus {
  border-color: var(--accent-green);
  box-shadow: 0 0 0 3px rgba(63,164,91,.12);
}
.purchase-items-table .purchase-item-unit {
  width: 100%;
  min-height: 38px;
  box-sizing: border-box;
  border: 1px solid #b9c2d6;
  border-radius: 8px;
  background: #FFFFFF;
  color: #152250;
  padding: 8px 30px 8px 10px;
  font: 600 .78rem var(--font-sans);
  outline: none;
}
.purchase-items-table .purchase-item-unit:focus {
  border-color: var(--accent-green);
  box-shadow: 0 0 0 3px rgba(63,164,91,.12);
}
.purchase-items-table .purchase-unit-help {
  min-height: 17px;
}
.purchase-items-table .purchase-item-cost-hint:empty,
.purchase-items-table .purchase-unit-help:empty,
.purchase-items-table .purchase-cost-help:empty { display:none; }

.purchase-items-table .purchase-stock-preview {
  justify-content: center;
  min-width: 86px;
  font-size: .74rem;
}
.purchase-items-table .purchase-line-total {
  text-align: right;
  font-size: .82rem;
}
.purchase-items-table .purchase-remove-item {
  min-width: 68px;
  justify-content: center;
}
.purchase-items-table .purchase-remove-item:focus-visible,
.purchase-items-table .purchase-item-select:focus-visible,
.purchase-items-table .purchase-item-unit:focus-visible,
.purchase-items-table .purchase-item-qty:focus-visible,
.purchase-items-table .purchase-item-cost:focus-visible,
.purchase-items-table .purchase-custom-unit:focus-visible,
.purchase-items-table .purchase-custom-factor:focus-visible {
  outline: 2px solid rgba(63,164,91,.28);
  outline-offset: 1px;
}

@media (max-width: 760px) {
  .purchase-items-table { min-width: 900px; }
  .purchase-items-table .purchase-item-row td { padding: 9px 8px; }
}

/* Fix custom purchase-unit controls being visually buried by adjacent table content. */
.purchase-items-table-wrap { position: relative; }
.purchase-items-table tbody,
.purchase-items-table tbody tr,
.purchase-items-table tbody td { overflow: visible; }
.purchase-items-table .purchase-unit-cell { position: relative; z-index: 2; overflow: visible; }
.purchase-items-table .purchase-custom-unit,
.purchase-items-table .purchase-custom-factor {
  position: relative;
  z-index: 5;
  display: block;
  visibility: visible;
  opacity: 1;
}
.purchase-items-table .purchase-custom-unit[hidden],
.purchase-items-table .purchase-custom-factor[hidden] { display: none !important; }
.purchase-items-table tbody tr.purchase-item-row:focus-within { position: relative; z-index: 4; }

/* Purchase item editor — card layout (replaces the dynamic table rows) */
.purchase-items-editor {
  display: grid;
  gap: 14px;
  margin-top: 10px;
}
.purchase-item-card {
  position: relative;
  display: block;
  width: 100%;
  box-sizing: border-box;
  padding: 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: #fbfcfe;
  box-shadow: 0 4px 16px rgba(24, 39, 30, .05);
}
.purchase-item-card:focus-within {
  border-color: rgba(30, 112, 74, .38);
  box-shadow: 0 0 0 3px rgba(30, 112, 74, .08), 0 6px 20px rgba(24, 39, 30, .06);
}
.purchase-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  margin-bottom: 14px;
  padding-bottom: 11px;
  border-bottom: 1px solid var(--line);
}
.purchase-card-head > div { min-width: 0; }
.purchase-card-index {
  display: block;
  margin-bottom: 2px;
  color: var(--stone);
  font-size: .66rem;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
}
.purchase-card-title {
  display: block;
  overflow: hidden;
  color: var(--ink);
  font-family: var(--font-display);
  font-size: .98rem;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.purchase-card-grid {
  display: grid;
  gap: 14px;
}
.purchase-card-grid--top {
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
}
.purchase-card-grid--numbers {
  grid-template-columns: minmax(130px, .8fr) minmax(150px, .9fr) minmax(170px, 1fr) minmax(170px, 1fr);
  align-items: stretch;
  margin-top: 14px;
}
.purchase-item-card .field { min-width: 0; }
.purchase-item-card select,
.purchase-item-card input {
  width: 100%;
  min-width: 0;
  box-sizing: border-box;
}
.purchase-custom-fields {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
  gap: 8px;
  margin-top: 9px;
}
.purchase-custom-fields[hidden] { display: none !important; }
.purchase-custom-fields input { min-height: 42px; }
.purchase-unit-help,
.purchase-item-cost-hint,
.purchase-cost-help {
  display: block;
  margin-top: 5px;
  color: var(--stone);
  font-size: .69rem;
  line-height: 1.4;
}
.purchase-card-metric {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-width: 0;
  min-height: 74px;
  padding: 12px 14px;
  box-sizing: border-box;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: #f7f9fc;
}
.purchase-card-metric span {
  margin-bottom: 5px;
  color: var(--stone);
  font-size: .68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
}
.purchase-card-metric strong {
  color: var(--ink);
  font-size: .94rem;
}
.purchase-card-metric--total {
  background: #f8f3ff;
  border-color: #e5d8f3;
}
.purchase-card-metric--total strong { color: var(--primary-purple, #7b3f98); }
.purchase-item-card .purchase-remove-item {
  flex: 0 0 auto;
  color: var(--stone);
}
.purchase-item-card .purchase-remove-item:hover {
  color: var(--danger);
  border-color: var(--danger);
  background: var(--danger-bg);
}
@media (max-width: 900px) {
  .purchase-card-grid--top,
  .purchase-card-grid--numbers { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 620px) {
  .purchase-item-card { padding: 13px; }
  .purchase-card-grid--top,
  .purchase-card-grid--numbers,
  .purchase-custom-fields { grid-template-columns: 1fr; }
  .purchase-card-head { align-items: flex-start; }
  .purchase-item-card .purchase-remove-item { width: auto; }
}


/* -------------------------------------------------------------
   Room board — deep status cards
   Keep room status visually strong while preserving readable text.
   ------------------------------------------------------------- */
.room-card[data-status] {
  color: #fff;
  border: 1px solid transparent;
  border-left-width: 4px;
  border-left-color: rgba(255,255,255,.42);
}
.room-card[data-status]::after {
  background: linear-gradient(135deg, rgba(255,255,255,.08), transparent 58%);
}
.room-card[data-status] .room-card-number,
.room-card[data-status] .room-card-type {
  color: #fff;
}
.room-card[data-status] .room-card-type {
  opacity: .84;
}
.room-card[data-status] .badge {
  background: rgba(255,255,255,.16);
  color: #fff;
  border: 1px solid rgba(255,255,255,.24);
}
/* Room cards are drawn deep for every status, so the meta lines - room note,
   stay note, discount reason, and the booked-for line - were --ink-soft on a
   coloured background and effectively invisible. Only the
   occupied-with-balance card had been corrected, and only for its own copy.
   Without this the booking line is unreadable on the reserved purple, which
   defeats the point of printing it. */
.room-card[data-status] .room-card-meta,
.room-card[data-status] .room-card-meta strong { color: rgba(255,255,255,.94); }
.room-card[data-status="vacant"] {
  background: var(--accent-green);
  border-left-color: rgba(255,255,255,.5);
}
.room-card[data-status="occupied"] {
  background: var(--primary);
  border-left-color: rgba(255,255,255,.5);
}
.room-card[data-status="dirty"] {
  background: #8A4B08;
  border-left-color: #F4C36A;
}
.room-card[data-status="maintenance"] {
  background: #8B2424;
  border-left-color: #F2A0A0;
}
.room-card[data-status="reserved"] {
  background: #51327A;
  border-left-color: #CDB5EA;
}
.room-card[data-status="cleaning"] {
  background: #245A82;
  border-left-color: #A8D5F5;
}
.room-card[data-status="clean"],
.room-card[data-status="inspected"] {
  background: var(--accent-green-dark);
  border-left-color: #B7E1C5;
}

/* -------------------------------------------------------------
   In-house, but the folio still has money outstanding.

   This is the one room-card state that is NOT a saturated block with
   white text, so every colour has to be restated here. The block above
   forces `color: #fff` on the card, the number, the type line and every
   badge; on a pale background that text is invisible, which is exactly
   what happened the first time this state was added.

   Placed after the saturated block deliberately: this rule wins on
   specificity AND on source order, so it does not depend on which
   `.room-card[data-status]` block a future edit happens to move.

   Blue rather than another green or a red: the desk screen is often
   guest-visible, and a debt-warning colour across the counter invites
   the wrong conversation. Blue says "occupied, needs a look". The amount
   is not printed on the card at all - it is one click away in the room
   preview, beside the discount reason and the resale count.
   ------------------------------------------------------------- */
.room-card[data-status="occupied"][data-balance="due"] {
  background: #E4EDF8;
  border-color: #C3D6EE;
  border-left-color: #1F4E8C;
  color: #123A6B;
}
.room-card[data-status="occupied"][data-balance="due"]::after {
  background: linear-gradient(135deg, rgba(255,255,255,.55), transparent 58%);
}
.room-card[data-status="occupied"][data-balance="due"] .room-card-number,
.room-card[data-status="occupied"][data-balance="due"] .room-card-type {
  color: #123A6B;
  opacity: 1;
}
.room-card[data-status="occupied"][data-balance="due"] .room-card-meta,
.room-card[data-status="occupied"][data-balance="due"] .room-card-meta strong {
  color: #1B3A63;
}
/* Default chip: opaque, so it does not rely on a translucent white
   overlay that disappears on a light card. */
.room-card[data-status="occupied"][data-balance="due"] .badge {
  background: #FFFFFF;
  color: #1F4E8C;
  border-color: #A9C3E0;
}
/* Keep the resale and balance identities, but opaque so they stay legible
   and still read as different things from the plain status chip. */
.room-card[data-status="occupied"][data-balance="due"] .badge-resale {
  background: #FDF1CF;
  color: #6B4C00;
  border-color: #E0BD63;
}
.room-card[data-status="occupied"][data-balance="due"] .badge-balance-due {
  background: #123A6B;
  color: #FFFFFF;
  border-color: #123A6B;
}
.room-card--clickable:hover {
  border-color: rgba(255,255,255,.42);
  box-shadow: 0 8px 22px rgba(16,24,40,.18);
}

/* -------------------------------------------------------------
   Notification quick panel — bounded, independently scrollable list
   ------------------------------------------------------------- */
.app-notification-panel {
  max-height: calc(100vh - 92px);
  display: flex;
  flex-direction: column;
}
.app-notification-head {
  flex: 0 0 auto;
}
#appNotificationList {
  flex: 1 1 auto;
  min-height: 0;
  max-height: min(420px, calc(100vh - 150px));
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-gutter: stable;
  touch-action: pan-y;
}
#appNotificationList::-webkit-scrollbar { width: 7px; }
#appNotificationList::-webkit-scrollbar-thumb {
  background: rgba(16,24,40,.24);
  border-radius: 999px;
}
#appNotificationList::-webkit-scrollbar-track { background: transparent; }
@media (max-width: 560px) {
  .app-notification-panel {
    right: -8px;
    max-width: calc(100vw - 20px);
  }
  #appNotificationList {
    max-height: calc(100vh - 160px);
  }
}

/* -------------------------------------------------------------
   Reservation table: readable mobile cards
   Keep desktop as a compact table; on phones, turn each reservation
   into a labelled card so staff never have to horizontally scroll to
   reach the actions. The JS supplies data-label values for this view.
   ------------------------------------------------------------- */
.reservation-actions-cell { min-width: 170px; }
.reservation-actions-cell .btn { margin: 2px 2px 2px 0; }

@media (max-width: 640px) {
  .table-wrap--mobile-cards { overflow: visible; background: transparent; border: 0; padding: 0 !important; }
  .table-wrap--mobile-cards table.data-table,
  .table-wrap--mobile-cards table.data-table tbody,
  .table-wrap--mobile-cards table.data-table tr,
  .table-wrap--mobile-cards table.data-table td { display: block; width: 100%; }
  .table-wrap--mobile-cards table.data-table thead { display: none; }
  .table-wrap--mobile-cards table.data-table tr {
    background: var(--white);
    border: 1px solid rgba(16, 24, 40, 0.10);
    border-radius: var(--radius);
    margin-bottom: 10px;
    padding: 9px 12px;
  }
  .table-wrap--mobile-cards table.data-table td {
    display: grid;
    grid-template-columns: minmax(76px, 28%) 1fr;
    gap: 10px;
    align-items: start;
    padding: 8px 0;
    border-bottom: 1px solid var(--parchment-dim);
    text-align: left;
  }
  .table-wrap--mobile-cards table.data-table td:last-child { border-bottom: 0; }
  .table-wrap--mobile-cards table.data-table td::before {
    content: attr(data-label);
    color: var(--stone);
    font-size: .72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
  }
  .table-wrap--mobile-cards .reservation-actions-cell {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
  }
  .table-wrap--mobile-cards .reservation-actions-cell::before {
    width: 100%;
    margin-bottom: 2px;
  }
}

/* Sub-navigation remains usable with many tabs on small screens.
   A little breathing room makes the horizontal scroll affordance
   clearer without changing the desktop layout. */
@media (max-width: 640px) {
  .module-tabs {
    margin-right: -14px;
    padding-right: 14px;
    mask-image: linear-gradient(to right, #000 0 calc(100% - 20px), transparent 100%);
  }
  .module-tab { padding-top: 9px; padding-bottom: 11px; }
}

/* POS item search and focused empty state */
.pos-menu-tools {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  margin: 4px 0 2px;
}
.pos-menu-search { flex: 1; max-width: 420px; margin: 0; }
.pos-menu-search input { width: 100%; }
.pos-menu-search-status { margin: 6px 0 0; font-size: .78rem; }
.pos-empty-search {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 24px 16px;
  text-align: center;
  border: 1px dashed var(--parchment-dim);
  border-radius: var(--radius);
  color: var(--stone);
}
.pos-empty-search strong { color: var(--ink); }
@media (max-width: 640px) {
  .pos-menu-tools { align-items: stretch; }
  .pos-menu-search { max-width: none; }
  .pos-menu-tools > .btn { min-height: 42px; }
}


/* Stage 7 — stock search keeps a large inventory table useful without adding another pane. */
.stock-search-field{margin-left:auto;min-width:220px;max-width:320px}.stock-search-field input{width:100%}.stock-search-status{font-size:.78rem;white-space:nowrap}
@media(max-width:720px){.stock-search-field{order:10;min-width:100%;max-width:none;margin-left:0}.stock-search-status{width:100%}}


/* Reports and purchase filter UX */
.report-list-meta { display:flex; align-items:center; justify-content:space-between; gap:12px; min-height:28px; margin-top:8px; }
.report-list-meta p { margin:0; }
@media (max-width: 720px) {
  .report-list-meta { align-items:flex-start; flex-direction:column; gap:4px; }
}

/* Menu administration search */
.menu-admin-tools {
  display: flex;
  align-items: flex-end;
  gap: .6rem;
  margin: .75rem 0 .25rem;
  max-width: 620px;
}
.menu-admin-search {
  flex: 1 1 360px;
  margin: 0;
}
.menu-admin-search-status {
  margin: .15rem 0 .65rem;
}
@media (max-width: 640px) {
  .menu-admin-tools { max-width: none; }
  .menu-admin-tools .btn { align-self: flex-end; }
}

/* Stage 10: compact management search bars */
.board-toolbar--secondary { margin-top: .75rem; margin-bottom: .75rem; align-items: center; }
.board-toolbar--secondary .search-field { flex: 0 1 360px; }
.board-toolbar__actions { display: flex; align-items: center; gap: .5rem; }
.board-toolbar__actions .search-field { min-width: min(320px, 45vw); }
@media (max-width: 640px) {
  .board-toolbar--secondary .search-field,
  .board-toolbar__actions .search-field { flex: 1 1 100%; min-width: 0; }
  .board-toolbar__actions { flex: 1 1 100%; flex-wrap: wrap; }
}


/* Registered guest directory */
.guests-directory-toolbar {
  display:flex; align-items:flex-end; gap:16px; margin:16px 0; padding:14px 16px;
}
.guests-directory-toolbar .field { flex:1; margin:0; }
.guests-directory-toolbar .toolbar-meta { display:flex; align-items:center; gap:10px; white-space:nowrap; }
.registered-guests-table td small { display:block; margin-top:3px; }
@media (max-width: 720px) {
  .guests-directory-toolbar { flex-direction:column; align-items:stretch; }
  .guests-directory-toolbar .toolbar-meta { justify-content:space-between; }
}
@media (max-width: 640px) {
  .registered-guests-table thead { display:none; }
  .registered-guests-table, .registered-guests-table tbody, .registered-guests-table tr, .registered-guests-table td { display:block; width:100%; }
  .registered-guests-table tr { padding:12px 14px; border-bottom:1px solid rgba(0,0,0,.08); }
  .registered-guests-table td { display:grid; grid-template-columns:110px 1fr; gap:10px; padding:5px 0; border:0; }
  .registered-guests-table td::before { content:attr(data-label); font-weight:700; color:var(--text-stone, #70767f); }
}

/* -------------------------------------------------------------
   Staff guest profile — keep identity, stays and folios in one flow.
   The financial figures remain read-only here; payment actions stay
   inside the shared FolioModal so accounting controls are not duplicated.
   ------------------------------------------------------------- */
.guest-profile-modal { max-height: calc(100vh - 40px); overflow-y: auto; }
.guest-profile-summary { display: grid; grid-template-columns: minmax(0,1fr) auto; gap: 18px; align-items: center; margin-bottom: 22px; }
.guest-profile-identity { display: flex; align-items: center; gap: 14px; min-width: 0; }
.guest-profile-avatar { width: 52px; height: 52px; border-radius: 50%; display: grid; place-items: center; background: var(--moss-light); color: var(--moss); font-family: var(--font-display); font-size: 1.35rem; font-weight: 700; flex: 0 0 auto; }
.guest-profile-identity h4 { margin: 0 0 3px; font-family: var(--font-display); font-size: 1.2rem; }
.guest-profile-identity p { margin: 0 0 7px; font-size: .82rem; }
.guest-profile-metrics { display: flex; gap: 10px; flex-wrap: wrap; justify-content: flex-end; }
.guest-profile-metrics > div { min-width: 96px; padding: 10px 12px; border: 1px solid var(--parchment-dim); border-radius: 10px; background: var(--parchment-dim); }
.guest-profile-metrics span, .guest-profile-details span { display: block; color: var(--stone); font-size: .74rem; margin-bottom: 3px; }
.guest-profile-metrics strong { font-family: var(--font-mono); font-size: .95rem; }
.guest-profile-section { margin-top: 24px; }
.guest-profile-section-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; margin-bottom: 10px; }
.guest-profile-section-head h4 { margin: 0 0 3px; font-family: var(--font-display); font-size: 1rem; }
.guest-profile-section-head p { margin: 0; font-size: .8rem; }
.guest-profile-details { display: grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap: 10px; }
.guest-profile-details > div { padding: 10px 12px; border: 1px solid var(--parchment-dim); border-radius: 9px; min-width: 0; }
.guest-profile-details strong { display: block; overflow-wrap: anywhere; font-size: .86rem; }
.guest-profile-stays td small { display: block; margin-top: 2px; }
.guest-profile-folio-list { display: flex; flex-direction: column; gap: 10px; }
.guest-profile-folio-card { display: grid; grid-template-columns: minmax(0,1fr) auto auto; gap: 14px; align-items: center; padding: 13px 15px; }
.guest-profile-folio-main { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; min-width: 0; }
.guest-profile-folio-main strong { font-family: var(--font-mono); }
.guest-profile-folio-finance { display: flex; flex-direction: column; align-items: flex-end; gap: 3px; white-space: nowrap; }
.guest-profile-folio-finance .text-stone { font-size: .75rem; }
.guest-profile-balance--due { color: var(--danger); }
.guest-profile-balance--credit { color: var(--moss); }
.guest-profile-balance--paid { color: var(--stone); }

@media (max-width: 760px) {
  .guest-profile-summary { grid-template-columns: 1fr; }
  .guest-profile-metrics { justify-content: stretch; }
  .guest-profile-metrics > div { flex: 1 1 90px; }
  .guest-profile-details { grid-template-columns: 1fr 1fr; }
  .guest-profile-folio-card { grid-template-columns: 1fr; gap: 9px; }
  .guest-profile-folio-finance { align-items: flex-start; }
  .guest-profile-folio-card .btn { width: 100%; }
}
@media (max-width: 520px) {
  .guest-profile-details { grid-template-columns: 1fr; }
  .guest-profile-modal { max-height: calc(100vh - 20px); }
}

/* Guest profile/edit: keep dense operational details readable without letting
   long notes, folio lists or forms make the modal feel cramped. */
.guest-profile-modal, #guestProfileFolioOverlay .modal, #guestEditOverlay .modal { max-height: calc(100vh - 40px); overflow-y: auto; overscroll-behavior: contain; }
.guest-profile-section-head > .btn { flex: 0 0 auto; }
.guest-profile-details > div { min-height: 54px; }
.guest-profile-details > div:last-child { grid-column: 1 / -1; }
.guest-profile-details > div:last-child strong { white-space: pre-wrap; }
#guestEditForm { margin-top: 4px; }
#guestEditForm textarea { resize: vertical; min-height: 96px; }
@media (max-width: 700px) {
  .guest-profile-details > div:last-child { grid-column: auto; }
  #guestEditForm { grid-template-columns: 1fr; }
  #guestEditForm .field-wide { grid-column: auto; }
}

.guest-match-alert{margin-top:8px;padding:10px 12px;border:1px solid var(--brass);border-radius:10px;background:var(--parchment);font-size:.88rem;line-height:1.4}.guest-match-alert[hidden]{display:none}

/* Online booking request estimate + guest note */
.booking-estimate { margin: 14px 0 18px; }
.booking-estimate .field-hint { margin: 10px 0 0; }
.reservation-card-estimate { margin-top: 6px; font-size: .8rem; color: var(--stone); }
.reservation-card-note { margin: 10px 0 0; max-width: 62ch; white-space: pre-wrap; }
@media (max-width: 700px) {
  .reservation-card-note { max-width: none; }
}


/* Online booking approval review */
.approval-review-modal { max-height: min(92vh, 820px); overflow-y: auto; }
.approval-review-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.approval-review-item { padding: 12px 14px; border: 1px solid var(--line); border-radius: 10px; background: var(--paper); }
.approval-review-item span { display: block; font-size: .72rem; color: var(--stone); margin-bottom: 4px; }
.approval-review-item strong { font-size: .9rem; }
.approval-review-note { padding: 12px 14px; border-left: 3px solid var(--brass); background: var(--paper); border-radius: 0 8px 8px 0; }
.approval-review-note p { margin: 5px 0 0; white-space: pre-wrap; }
.approval-total { display: flex; justify-content: space-between; align-items: center; padding: 14px 0; border-top: 1px solid var(--line); font-family: var(--font-mono); }
.approval-total strong { font-size: 1.08rem; }
@media (max-width: 620px) { .approval-review-grid { grid-template-columns: 1fr; } }


/* Guest account reservation terms */
.account-reservation-finance { margin-top: 10px; display:flex; flex-direction:column; gap:2px; }
.account-reservation-finance span, .account-reservation-note > span { color:var(--stone); font-size:.66rem; text-transform:uppercase; letter-spacing:.05em; }
.account-reservation-finance strong { font-family:var(--font-mono); font-size:.92rem; }
.account-reservation-finance small { color:var(--stone); font-size:.68rem; line-height:1.4; }
.account-reservation-note { margin-top:9px; padding-top:9px; border-top:1px solid var(--parchment-dim); max-width:62ch; }
.account-reservation-note p { margin:3px 0 0; color:var(--ink-soft); font-size:.72rem; line-height:1.5; white-space:pre-wrap; }

/* Kawa AI: stronger lodge identity without competing with the app shell. */
.kawa-ai-header { background:linear-gradient(135deg, #101c42 0%, var(--primary) 62%, #4e3690 100%); border-bottom:1px solid rgba(146,119,219,.32); }
.kawa-ai-header h2 { color:#fff !important; opacity:1 !important; }
.kawa-ai-header p { color:rgba(255,255,255,.78) !important; }
.kawa-ai-header .kawa-ai-ai-status { color:#b9a4e8 !important; }
.kawa-ai-mark { background:linear-gradient(145deg, rgba(146,119,219,.30), rgba(255,255,255,.10)); border:1px solid rgba(146,119,219,.30); color:#b9a4e8; box-shadow:inset 0 0 0 1px rgba(255,255,255,.05); }
.kawa-ai-header p { color:rgba(255,255,255,.78); }
.kawa-ai-ai-status { display:inline-flex; align-items:center; gap:5px; margin-left:6px; font-size:.61rem; color:#b9a4e8; }
.kawa-ai-ai-status::before { content:''; width:6px; height:6px; border-radius:50%; background:#9277db; box-shadow:0 0 0 3px rgba(146,119,219,.12); }
.kawa-ai-local-note { margin-top:8px; padding:8px 10px; border-radius:9px; background:#fbf7ed; border:1px solid rgba(146,119,219,.24); color:var(--stone); font-size:.65rem; line-height:1.45; }

/* Kawa AI knowledge administration */
.kawa-ai-knowledge-grid { display:grid; grid-template-columns:minmax(0,1.35fr) minmax(300px,.8fr); gap:18px; }
.kawa-ai-knowledge-form { display:grid; grid-template-columns:1fr 1fr; gap:12px; align-content:start; }
.kawa-ai-knowledge-form .field-wide { grid-column:1 / -1; }
.kawa-ai-knowledge-form textarea { min-height:130px; resize:vertical; }
.admin-actions-row { display:flex; gap:8px; align-items:center; }
@media (max-width: 900px) { .kawa-ai-knowledge-grid { grid-template-columns:1fr; } }
@media (max-width: 600px) { .kawa-ai-knowledge-form { grid-template-columns:1fr; } .kawa-ai-knowledge-form .field-wide { grid-column:auto; } .admin-actions-row { flex-wrap:wrap; } }


/* Standalone stock ledger */
.stock-ledger-filter-grid { align-items: end; gap: 12px; }
.stock-ledger-search { min-width: 260px; flex: 1 1 260px; }
.stock-ledger-controls .field-help { margin: 10px 0 0; }
.stock-ledger-table-wrap { overflow-x: auto; }
.stock-ledger-table-wrap .data-table { min-width: 1050px; }
.stock-ledger-note { max-width: 28ch; white-space: pre-wrap; }
.stock-ledger-alerts { margin-top: 14px; }
@media (max-width: 900px) { .stock-ledger-filter-grid .field-inline { min-width: 145px; } .stock-ledger-search { min-width: 220px; } }
@media (max-width: 640px) { .stock-ledger-filter-grid { display: grid; grid-template-columns: 1fr 1fr; } .stock-ledger-search { grid-column: 1 / -1; min-width: 0; } .stock-ledger-filter-grid > .btn { width: 100%; } }


/* Kawa AI header contrast guard — must remain light on the green header. */
.kawa-ai-header h2,
.kawa-ai-header p,
.kawa-ai-header .kawa-ai-ai-status,
.kawa-ai-header .kawa-ai-close {
  color: #fff !important;
}
.kawa-ai-header .kawa-ai-ai-status { color: #b9a4e8 !important; }

/* Z7 ZRA management console */
.zra-management-grid { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:16px; margin-top:16px; }
.zra-readiness-list { display:flex; flex-direction:column; gap:8px; }
.zra-readiness-row { display:flex; align-items:center; justify-content:space-between; gap:12px; padding:10px 12px; border:1px solid var(--line,#e6e9f0); border-radius:10px; }
.zra-readiness-row strong { display:block; font-size:.9rem; }
.zra-readiness-row small { display:block; margin-top:3px; color:var(--stone,#777); }
.zra-mini-list { display:grid; gap:8px; color:var(--stone,#777); }
@media (max-width: 800px) { .zra-management-grid { grid-template-columns:1fr; } }
.zra-payload-preview{margin-top:12px;max-height:420px;overflow:auto;padding:14px;border:1px solid var(--line,#e6e9f0);border-radius:10px;background:var(--surface-muted,#f5f7fa);font-size:.78rem;line-height:1.45;white-space:pre-wrap;word-break:break-word;}

/* ZRA Smart Invoice management UI */
.zra-page-header { align-items:flex-start; }
.zra-header-actions { flex:0 0 auto; }
.zra-management-grid > .card-soft { min-width:0; }
.zra-action-grid {
  display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));
  gap:10px;
  margin-top:12px;
}
.zra-action-grid .btn {
  width:100%;
  min-width:0;
  white-space:normal;
  min-height:42px;
}
#zraStatusStats {
  grid-template-columns:repeat(4,minmax(0,1fr));
}
#zraStatusStats .stat-card { min-width:0; }
.zra-readiness-row > div { min-width:0; flex:1 1 auto; }
.zra-readiness-row small { overflow-wrap:anywhere; }
#zraManagementStatus { margin:14px 0 0; }
#zraTestRunsBody td:last-child { min-width:220px; }
@media (max-width:1100px) {
  #zraStatusStats { grid-template-columns:repeat(3,minmax(0,1fr)); }
}
@media (max-width:800px) {
  .zra-page-header { align-items:flex-start; }
  .zra-header-actions { width:100%; }
  .zra-header-actions .btn { flex:1 1 0; }
  .zra-action-grid { grid-template-columns:1fr 1fr; }
  #zraStatusStats { grid-template-columns:repeat(2,minmax(0,1fr)); }
}
@media (max-width:520px) {
  .zra-action-grid { grid-template-columns:1fr; }
  #zraStatusStats { grid-template-columns:1fr 1fr; }
}
.zra-management-grid { min-width:0; }
.zra-management-grid .card-soft { overflow:hidden; }
.zra-action-grid + .field-help { max-width:72ch; }
#zraTestRunsBody td { vertical-align:middle; }
@media (max-width:640px) {
  .zra-header-actions { display:grid; grid-template-columns:1fr 1fr; }
  .zra-header-actions .btn { width:100%; }
}

/* Smart Invoice management-facing dashboard */
.zra-business-summary {
  margin-top:16px;
  padding:18px;
  border:1px solid var(--line,#e6e9f0);
  border-radius:14px;
  background:var(--surface-muted,#f5f7fa);
}
.zra-business-summary-head { display:flex; align-items:flex-start; justify-content:space-between; gap:16px; }
.zra-business-summary-head h4 { margin:3px 0 0; font-size:1.05rem; }
.zra-business-summary-head .eyebrow { font-size:.72rem; text-transform:uppercase; letter-spacing:.08em; color:var(--stone,#777); }
.zra-period-label { white-space:nowrap; padding:6px 10px; border:1px solid var(--line,#e6e9f0); border-radius:999px; font-size:.78rem; color:var(--stone,#777); background:#fff; }
.zra-business-metrics { display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:10px; margin-top:14px; }
.zra-business-metric { min-width:0; padding:13px 14px; background:#fff; border:1px solid var(--line,#e6e9f0); border-radius:11px; }
.zra-business-metric span,.zra-business-metric small { display:block; color:var(--stone,#777); }
.zra-business-metric span { font-size:.78rem; }
.zra-business-metric strong { display:block; margin:5px 0 2px; font-size:1.35rem; }
.zra-business-metric small { font-size:.72rem; }
.zra-business-foot { margin-top:12px; color:var(--stone,#777); font-size:.78rem; }
.zra-setup-summary { display:grid; gap:0; }
.zra-setup-row { display:flex; justify-content:space-between; gap:12px; padding:10px 0; border-bottom:1px solid var(--line,#e6e9f0); }
.zra-setup-row:last-child { border-bottom:0; }
.zra-advanced-tools { margin-top:16px; border-top:1px solid var(--line,#e6e9f0); padding-top:14px; }
.zra-advanced-tools summary { cursor:pointer; font-weight:600; color:var(--ink,#1f2430); }
.zra-advanced-body { padding-top:12px; }
@media (max-width:900px) { .zra-business-metrics { grid-template-columns:repeat(2,minmax(0,1fr)); } }
@media (max-width:520px) { .zra-business-metrics { grid-template-columns:1fr 1fr; } .zra-business-summary-head { display:block; } .zra-period-label { display:inline-block; margin-top:8px; } }

/* =============================================================
   Kawa UI/UX audit — pass 1
   Keep page-level layout stable, prevent accidental horizontal
   overflow, and make action groups adapt instead of pushing the
   whole application wider than the viewport.
   ============================================================= */
html, body { max-width: 100%; overflow-x: hidden; }
*, *::before, *::after { box-sizing: border-box; }
.app-main, .app-content, .app-content-inner, .module-pane, .card, .panel-card { min-width: 0; }

/* Toolbars should wrap as a group; individual controls may shrink. */
.board-toolbar,
.admin-toolbar,
.board-toolbar--secondary,
.zra-header-actions,
.form-inline {
  min-width: 0;
}
.board-toolbar > *,
.admin-toolbar > *,
.board-toolbar--secondary > *,
.form-inline > * { min-width: 0; max-width: 100%; }

/* Search/filter fields no longer force a minimum page width. */
.board-toolbar .field-inline,
.admin-toolbar .field-inline,
.board-toolbar--secondary .search-field,
.stock-search-field,
.pos-menu-search { flex: 1 1 180px; min-width: min(100%, 180px); }
.board-toolbar .btn,
.admin-toolbar .btn,
.board-toolbar--secondary .btn { flex: 0 0 auto; }

/* In-page tabs wrap on narrower screens instead of creating page scroll. */
.module-tabs {
  flex-wrap: wrap;
  row-gap: 2px;
  overflow: visible;
}
.module-tab {
  margin-right: 10px;
  white-space: normal;
}

/* Button clusters stay visually grouped and never become a single
   unbroken horizontal strip. */
.board-toolbar .form-inline,
.admin-toolbar .form-inline,
.board-toolbar__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

/* Long labels can wrap inside buttons; this is preferable to making
   the entire application wider than the viewport. */
.btn { max-width: 100%; white-space: normal; }

/* Tables may scroll inside their own container, never at body level. */
.table-wrap { max-width: 100%; overflow-x: auto; overflow-y: visible; }
.data-table { min-width: 640px; }
.table-wrap--mobile-cards .data-table { min-width: 0; }

/* Dense forms become one column sooner so controls remain comfortable. */
@media (max-width: 820px) {
  .app-content { padding: 22px 18px; }
  .board-toolbar,
  .admin-toolbar,
  .board-toolbar--secondary { align-items: stretch; }
  .board-toolbar > .field,
  .admin-toolbar > .field,
  .board-toolbar--secondary > .field { flex: 1 1 100%; }
  .board-toolbar > .btn,
  .admin-toolbar > .btn { align-self: flex-start; }
}

@media (max-width: 560px) {
  .app-content { padding: 18px 14px; }
  .module-tabs { gap: 2px 4px; margin-bottom: 18px; }
  .module-tab { flex: 0 1 auto; padding: 9px 7px 10px; margin-right: 3px; font-size: .84rem; }
  .form-inline { gap: 9px; }
  .form-inline > .field,
  .form-inline > input,
  .form-inline > select { flex: 1 1 100%; min-width: 0; width: 100%; }
  .form-inline > .btn { margin-top: 0; }
  .board-toolbar .btn,
  .admin-toolbar .btn,
  .board-toolbar__actions .btn { width: 100%; }
  .board-toolbar .form-inline,
  .admin-toolbar .form-inline,
  .board-toolbar__actions { width: 100%; }
  .board-toolbar .form-inline .btn,
  .admin-toolbar .form-inline .btn,
  .board-toolbar__actions .btn { flex: 1 1 140px; width: auto; }
}

/* Consistent section rhythm: avoid oversized blank areas while keeping
   clear separation between functional groups. */
.card + .card,
.panel-card + .panel-card { margin-top: 14px; }

/* -------------------------------------------------------------
   UI/UX pass 2 — Overview / dashboard
   ------------------------------------------------------------- */
.overview-hero {
  background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%);
}
.overview-hero .text-stone,
.overview-hero-name { color: #fff; }
.overview-hero .text-stone { opacity: .78; }
.overview-hero-name { margin-top: 3px; }
.overview-hero .badge { color: #fff; background: rgba(255,255,255,.10); border-color: rgba(255,255,255,.22); }
.overview-section-heading {
  display:flex; align-items:flex-end; justify-content:space-between; gap:16px;
  margin: 22px 0 10px;
}
.overview-section-heading--modules { margin-top: 26px; }
.overview-eyebrow {
  margin:0 0 3px; text-transform:uppercase; letter-spacing:.08em;
  font-size:.68rem; font-weight:700; color:var(--stone-light);
}
.overview-section-title {
  margin:0; font-size:1.08rem; font-weight:650; color:var(--ink);
}
.overview-alerts { display:grid; gap:8px; margin-bottom:4px; }
.overview-alert { min-width:0; }
#overviewStatsRow { margin-bottom: 0; }
.overview-chart-card { margin-top: 16px; }
.overview-grid { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.overview-card { min-height: 112px; justify-content:space-between; }
.overview-card .btn { width:100%; }
@media (max-width:640px) {
  .overview-hero { padding:18px; align-items:flex-start; }
  .overview-hero-main { gap:11px; min-width:0; }
  .overview-hero-name { font-size:1.35rem; }
  /* On a narrow phone the greeting card wraps to two rows: name on top, then
     the button and the badge beneath it, both left-aligned so they read as a
     pair. Right-aligning them under a wrapping name leaves the button floating
     in the middle of nothing. */
  .overview-hero { flex-wrap: wrap; }
  .overview-hero-side {
    flex: 1 0 100%;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
  }
  .overview-section-heading { margin-top:18px; }
  .overview-grid { grid-template-columns:1fr; }
}

/* UI/UX pass 3 — Reception + Reservations */
.reception-toolbar .overview-eyebrow,
.reservations-page-head .overview-eyebrow,
.reservation-form-head .overview-eyebrow { margin-bottom: 3px; }
.reception-toolbar .text-stone,
.reservations-page-head .text-stone { max-width: 720px; margin-top: 4px; }
.board-toolbar--room-filters { align-items: center; gap: 14px; margin-top: 10px; }
.board-filter-label { display:flex; flex-direction:column; min-width: 92px; gap:2px; }
.board-filter-label .field-label { margin:0; }
.reception-stat { min-height: 86px; display:flex; flex-direction:column; justify-content:center; }
.reception-stat strong { line-height:1.15; }
.reception-stay-item { min-height: 76px; align-items:center; }
.reception-search-card { padding: 20px; }
.reception-search-row { max-width: 900px; }
.reservations-page-head { align-items:flex-end; }
.reservations-page-head > div:first-child { min-width: 190px; margin-right:auto; }
.reservations-page-head .field { min-width: 210px; }
.reservations-page-head .board-toolbar__actions { flex-wrap:wrap; }
.reservation-list { gap: 10px; }
.reservation-form-head { display:flex; align-items:flex-start; justify-content:space-between; gap:18px; margin-bottom:18px; padding:18px 20px; background:var(--surface,#fff); border:1px solid var(--line,#d8dee9); border-radius:14px; }
.reservation-form-head .section-title { margin:0 0 4px; }
.reservation-form-head .text-stone { max-width:780px; margin:0; }
.reservation-form-head .badge { flex:0 0 auto; margin-top:2px; }
@media (max-width: 900px) {
  .reception-stat-grid { grid-template-columns:repeat(3,minmax(0,1fr)); }
  .reservations-page-head { align-items:stretch; }
  .reservations-page-head .field { min-width:0; }
}
@media (max-width: 640px) {
  .reception-stat-grid { grid-template-columns:repeat(2,minmax(0,1fr)); gap:9px; }
  .reception-stat { padding:12px 13px; min-height:76px; }
  .reception-stat strong { font-size:20px; }
  .board-toolbar--room-filters { align-items:stretch; }
  .board-filter-label { min-width:0; }
  .reception-search-card { padding:15px; }
  .reservations-page-head > div:first-child { min-width:0; }
  .reservation-form-head { padding:15px; flex-direction:column; }
  .reservation-form-head .badge { margin-top:0; }
}

/* UI/UX pass 4 — Bar + Restaurant POS */
.pos-page-intro {
  display:flex; align-items:flex-end; justify-content:space-between; gap:18px;
  margin: 0 0 18px;
  padding: 18px 20px;
  border: 1px solid var(--parchment-dim);
  border-radius: var(--radius);
  background: var(--white);
}
.pos-page-intro .overview-eyebrow,
.pos-section-heading .overview-eyebrow { margin-bottom:3px; }
.pos-page-title { margin:0; font-size:1.35rem; color:var(--ink); }
.pos-page-subtitle { margin:5px 0 0; max-width:700px; font-size:.86rem; }
.pos-section-heading {
  display:flex; align-items:flex-end; justify-content:space-between; gap:16px;
  margin: 6px 0 10px;
}
.pos-section-heading h3 { margin:0; font-size:1.04rem; color:var(--ink); }
.pos-section-note { font-size:.78rem; text-align:right; }
#orderQueuePane .board-toolbar { margin-bottom:12px; }
#orderQueuePane .board-filters { flex:1; }
.order-card { min-width:0; }
.order-card-head { align-items:flex-start; }
.order-card-who { min-width:0; overflow-wrap:anywhere; }
.order-card-foot { align-items:flex-end; flex-wrap:wrap; }
.order-card-actions { justify-content:flex-end; }
.order-card-actions .btn { min-height:34px; }
.order-card-more {
  margin-top:5px; border:0; background:none; color:var(--primary); padding:3px 0;
  font:inherit; font-size:.76rem; cursor:pointer;
}
.order-card-itemlist.is-collapsed { max-height:132px; overflow:hidden; }
.new-order-block { box-shadow:none; }
#newOrderPane .folio-input { min-height:40px; }
#newOrderPane .pos-menu-tools { margin-top:8px; }
#menuPane .board-toolbar { margin-bottom:12px; }
#menuPane .menu-admin-tools { margin-top:4px; }
.order-cart { border:1px solid var(--parchment-dim); }
@media (max-width:720px) {
  .pos-page-intro { align-items:stretch; flex-direction:column; padding:16px; }
  .pos-page-intro .btn { width:100%; }
  .pos-section-heading { align-items:flex-start; flex-direction:column; gap:3px; }
  .pos-section-note { text-align:left; }
}
@media (max-width:560px) {
  .pos-page-title { font-size:1.2rem; }
  .order-card-foot { align-items:stretch; }
  .order-card-actions { width:100%; justify-content:stretch; }
  .order-card-actions .btn { flex:1 1 120px; }
  .order-cart { position:relative; bottom:auto; }
}

/* UI/UX pass 5 — Store + Stock + Purchases */
.store-toolbar .overview-eyebrow,
.stock-toolbar .overview-eyebrow,
.purchases-toolbar .overview-eyebrow { margin-bottom: 3px; }
.store-section-heading,
.stock-ledger-section-heading,
.purchase-section-heading { margin-top: 18px; }
.store-section-heading,
.stock-ledger-section-heading,
.purchase-section-heading { display:flex; align-items:flex-end; justify-content:space-between; gap:16px; }
.store-section-heading .section-title,
.stock-ledger-section-heading .section-title,
.purchase-section-heading .section-title { margin:0; }
.section-note { margin:0; color:var(--stone); font-size:.84rem; max-width:48ch; text-align:right; }
.purchase-results-meta { margin: 8px 0 10px; }
.store-toolbar-actions .btn-primary,
.purchase-toolbar-actions .btn-primary { min-height:40px; }
.store-table-wrap, .stock-ledger-table-wrap, #purchasesTable { min-width:0; }
.store-transfer-head { align-items:end; }
.stock-ledger-controls { margin-top: 12px; }
.stock-ledger-controls .field-help { line-height:1.45; }
@media (max-width:760px) {
  .store-section-heading,
  .stock-ledger-section-heading,
  .purchase-section-heading { align-items:flex-start; flex-direction:column; gap:4px; }
  .section-note { max-width:none; text-align:left; }
  .store-toolbar-actions,
  .purchase-toolbar-actions { width:100%; }
  .store-toolbar-actions .btn,
  .purchase-toolbar-actions .btn { flex:1 1 180px; }
}
@media (max-width:560px) {
  .store-toolbar-actions .btn,
  .purchase-toolbar-actions .btn { flex-basis:100%; }
}

/* UI/UX pass 6 — Shared workflow buttons & tabs */
.module-tabs--workflow {
  align-items: center;
  gap: 6px;
  padding: 4px;
  border: 1px solid var(--parchment-dim);
  border-radius: 12px;
  background: rgba(245,247,250,.72);
}
.module-tabs--workflow .module-tab {
  margin-right: 0;
  border: 1px solid transparent;
  border-bottom-color: transparent;
  border-radius: 8px !important;
  padding: 9px 13px 10px;
  color: var(--stone);
  background: transparent;
  min-height: 38px;
}
.module-tabs--workflow .module-tab:hover:not(.is-active) { background: rgba(255,255,255,.72); color: var(--ink); border-color: var(--parchment-dim); }
.module-tabs--workflow .module-tab.is-active { color: var(--ink); background: #fff; border-color: var(--parchment-dim); box-shadow: 0 2px 8px rgba(16,24,40,.06); }
.module-tabs--workflow .module-tab--action { color: var(--accent-green-dark); background: rgba(63,164,91,.055); border-color: rgba(63,164,91,.13); }
.module-tabs--workflow .module-tab--action:hover:not(.is-active) { background: rgba(63,164,91,.10); border-color: rgba(63,164,91,.22); }
.module-tabs--workflow .module-tab--action.is-active { color: #fff; background: var(--accent-green); border-color: var(--accent-green); box-shadow: 0 4px 12px rgba(63,164,91,.16); }
.workflow-primary-action, .board-toolbar__actions .btn-primary { min-height: 40px; }
@media (max-width: 640px) {
  .module-tabs--workflow { margin-right: 0; padding: 4px; overflow-x: auto; flex-wrap: nowrap; scrollbar-width: thin; }
  .module-tabs--workflow .module-tab { flex: 0 0 auto; white-space: nowrap; padding: 9px 11px 10px; }
}


/* UI/UX pass 7 — Reports + Management */
.reports-page-intro,
.management-page-intro {
  display:flex; align-items:flex-start; justify-content:space-between; gap:20px;
  margin: 0 0 18px; padding:18px 20px;
  border:1px solid var(--parchment-dim); border-radius:14px;
  background:linear-gradient(135deg, rgba(63,164,91,.07), rgba(255,255,255,.9));
}
.reports-page-title, .management-page-title { margin:3px 0 5px; font-size:1.35rem; line-height:1.2; }
.reports-page-subtitle, .management-page-subtitle { margin:0; max-width:72ch; color:var(--stone); line-height:1.5; }
.report-section-intro, .management-section-intro { margin: 0 0 14px; }
.report-section-intro h3, .management-section-intro h3 { margin:3px 0 3px; font-size:1.08rem; }
.report-section-intro p, .management-section-intro p { margin:0; color:var(--stone); font-size:.86rem; max-width:70ch; }
.reports-module-tabs .module-tab, .module-tabs--management .module-tab { white-space:nowrap; }
.reports-module-tabs { margin-bottom:16px; }
.module-tabs--management { margin-bottom:16px; }
.report-primary-action { min-width:82px; }
#revenuePane .form-inline, #businessPane .business-controls, #stockPane > .form-inline, #expensesPane > .form-inline, #suppliersPane .business-controls { align-items:flex-end; }
#revenuePane .form-inline, #expensesPane .form-inline, #stockPane > .form-inline { padding:12px; border:1px solid var(--parchment-dim); border-radius:12px; background:rgba(245,247,250,.55); }
#businessPane .business-toolbar { padding:14px; border:1px solid var(--parchment-dim); border-radius:12px; background:rgba(245,247,250,.55); }
#businessPane .business-subtabs { margin-top:16px; }
#businessPane .business-report-note { margin-top:16px; }
#managementNightAuditPane .night-audit-toolbar, #managementBusinessDayPane .business-day-settings-grid { margin-top:4px; }
#managementStaffPane .table-wrap, #managementPermissionsPane .table-wrap, #managementCorrectionsPane .table-wrap { margin-top:10px; }
.admin-control-card { border-color:var(--parchment-dim); }
.management-section-intro + .admin-control-card, .management-section-intro + .admin-toolbar { margin-top:0; }
@media (max-width:720px) {
  .reports-page-intro, .management-page-intro { padding:15px 16px; }
  .reports-page-title, .management-page-title { font-size:1.2rem; }
  #revenuePane .form-inline, #expensesPane .form-inline, #stockPane > .form-inline { align-items:stretch; }
}
@media (max-width:560px) {
  .reports-page-intro, .management-page-intro { margin-bottom:14px; }
  .report-section-intro, .management-section-intro { margin-bottom:11px; }
}


/* UI/UX pass 8 — Guests + Housekeeping + Loyalty */
.guests-page-head { align-items:flex-start; }
.guests-page-head > div { min-width:0; }
.guests-search-panel { box-shadow:none; border-color:var(--parchment-dim); }
.guests-search-panel .field input[type="search"] { min-height:42px; }
.guests-search-panel .toolbar-meta { align-self:flex-end; }

.page-section-intro {
  display:flex; align-items:flex-start; justify-content:space-between; gap:16px;
  margin:0 0 14px; padding:15px 17px;
  border:1px solid var(--parchment-dim); border-radius:12px;
  background:rgba(245,247,250,.58);
}
.page-section-intro h2 { margin:2px 0 3px; font-size:1.08rem; }
.page-section-intro p { margin:0; color:var(--stone); font-size:.82rem; line-height:1.45; }
.housekeeping-tabs { margin-bottom:14px; }
.hk-search-field { min-width:min(320px,45vw); }
.hk-search-field .field-label { display:block; margin-bottom:5px; }
.hk-search-field input { width:100%; min-height:40px; }
.housekeeping-intro { align-items:center; }

.loyalty-search-panel { box-shadow:none; border-color:var(--parchment-dim); }
.loyalty-intro { margin:-2px 0 15px; padding:0 0 12px; border:0; border-bottom:1px solid var(--parchment-dim); background:transparent; }
.loyalty-search-panel .form-inline { align-items:flex-end; }
.loyalty-search-panel .field { min-width:0; }
.loyalty-search-panel #loyaltySearch { min-height:42px; }
.loyalty-search-panel #loyaltySearchBtn { min-height:40px; }
.loyalty-search-results { max-height:330px; overflow:auto; padding-right:2px; }
.loyalty-search-result { width:100%; text-align:left; font:inherit; color:var(--ink); line-height:1.35; min-height:44px; }
.loyalty-search-result:focus-visible { outline:3px solid rgba(63,164,91,.16); outline-offset:1px; border-color:var(--accent-green); }
.loyalty-search-result .mono { overflow-wrap:anywhere; }

/* Search controls are intentionally styled outside .field as well, because
   several modules create search controls directly or through JavaScript. */
.search-field input,
.stock-search-field input,
.pos-menu-search input,
.menu-admin-search input,
input[type="search"] {
  background:#fff;
  color:var(--ink);
  border:1px solid #b9c2d6;
  border-radius:9px;
  min-height:40px;
  padding:9px 11px;
  outline:none;
  box-shadow:inset 0 1px 2px rgba(16,24,40,.035);
  transition:border-color .15s ease, box-shadow .15s ease, background .15s ease;
}
.search-field input:focus,
.stock-search-field input:focus,
.pos-menu-search input:focus,
.menu-admin-search input:focus,
input[type="search"]:focus {
  border-color:var(--accent-green);
  box-shadow:0 0 0 3px rgba(63,164,91,.13);
}
.search-field input:disabled,
.stock-search-field input:disabled,
.pos-menu-search input:disabled,
.menu-admin-search input:disabled,
input[type="search"]:disabled { background:#eef1f6; color:var(--stone); cursor:not-allowed; }

/* Dynamically generated form controls should inherit the same Kawa field language. */
.module-pane input:not([type="hidden"]),
.module-pane select,
.module-pane textarea {
  max-width:100%;
}

@media (max-width:720px) {
  .page-section-intro { align-items:flex-start; flex-direction:column; }
  .housekeeping-intro { align-items:flex-start; }
  .hk-search-field { min-width:0; width:100%; }
  .guests-search-panel .toolbar-meta { align-self:stretch; }
}
@media (max-width:560px) {
  .page-section-intro { padding:13px 14px; }
  .loyalty-search-panel .form-inline .btn { width:100%; }
  .loyalty-search-results { max-height:280px; }
}

/* UI/UX quick pass — Reports section tabs + action buttons */
.reports-module-tabs {
  display:flex;
  align-items:center;
  gap:6px;
  margin-bottom:16px;
  padding:4px;
  border:1px solid var(--parchment-dim);
  border-radius:12px;
  background:rgba(245,247,250,.62);
  overflow-x:auto;
  scrollbar-width:thin;
}
.reports-module-tabs .module-tab {
  flex:0 0 auto;
  margin:0;
  padding:9px 13px 10px;
  min-height:38px;
  border:1px solid transparent;
  border-radius:8px;
  background:transparent;
  color:var(--stone);
  white-space:nowrap;
  line-height:1.1;
  transition:background .15s ease, border-color .15s ease, color .15s ease, box-shadow .15s ease;
  /*
    Inline-flex so the icon and the word sit on one baseline row and the tab keeps its
    height. line-height:1.1 above is tight, so the icon is aligned by its own box rather
    than by vertical-align, which is what made it sit low.
  */
  display:inline-flex;
  align-items:center;
  gap:7px;
}
/*
  The tab icons.

  currentColor means no second colour to keep in step: the icon draws in the tab's own text
  colour - grey when idle, white on the active navy - and it follows any future change to
  those colours for free. 15px against .84-.92rem text, which is the same optical weight as
  the .admin-subhead-icon used through this module.

  flex:0 0 auto so a long label like "Bar & Restaurant" cannot squash the icon, and
  aria-hidden is on every one in the markup so the label stays the only thing a screen
  reader announces. The icon is decoration; the word is the tab.
*/
.reports-module-tabs .module-tab .tab-icon {
  flex:0 0 auto;
  width:15px;
  height:15px;
  opacity:.82;
  transition:opacity .15s ease;
}
.reports-module-tabs .module-tab:hover:not(.is-active) .tab-icon { opacity:1; }
.reports-module-tabs .module-tab.is-active .tab-icon { opacity:1; }
.reports-module-tabs .module-tab:hover:not(.is-active) {
  color:var(--ink);
  background:rgba(255,255,255,.72);
  border-color:var(--parchment-dim);
}
.reports-module-tabs .module-tab:focus-visible {
  outline:3px solid rgba(63,164,91,.14);
  outline-offset:1px;
}
.reports-module-tabs .module-tab.is-active {
  color:#fff;
  background:var(--primary);
  border-color:var(--primary);
  box-shadow:0 4px 10px rgba(27,42,91,.18);
}
.reports-module-tabs .module-tab.is-active:hover {
  color:#fff;
  background:var(--primary-dark);
  border-color:var(--primary-dark);
}
@media (max-width:560px) {
  .reports-module-tabs {
    gap:4px;
    padding:4px;
    margin-bottom:14px;
    flex-wrap:nowrap;
  }
  .reports-module-tabs .module-tab {
    padding:9px 11px 10px;
    font-size:.84rem;
    gap:6px;
  }
  /* The strip scrolls sideways rather than wrapping, so the icons stay aligned down the
     column. Dropping them below ~360px would save a little width but leave seven
     unlabelled-looking pills to tell apart, and the label is the only thing carrying the
     meaning - the icon must never be it. */
  .reports-module-tabs .module-tab .tab-icon { width:14px; height:14px; }
}
@media (max-width:380px) {
  /* Seven tabs with icons need more room than a 360px screen gives. The labels go, the
     icons stay, and each tab keeps its accessible name through the visually-hidden text -
     which is why every icon in the markup is paired with a real word rather than being a
     bare glyph. Below this width the strip is a row of identifiable icons that scroll,
     not seven unreadable full words. */
  .reports-module-tabs .module-tab > span:not(.sr-only) {
    position:absolute; width:1px; height:1px; padding:0; margin:-1px;
    overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0;
  }
  .reports-module-tabs .module-tab { padding:9px 10px 10px; gap:0; }
}

/* UI/UX quick pass — Reports action buttons */
.reports-module-tabs + .reports-page-intro { margin-bottom: 16px; }
#overviewPane .board-toolbar,
#barRestaurantPane .board-toolbar,
#stockLedgerPanel .board-toolbar,
#suppliersPane .board-toolbar { gap: 12px; }

#overviewPane .board-toolbar .btn,
#barRestaurantPane .board-toolbar .btn,
#stockLedgerPanel .board-toolbar .btn,
#suppliersPane .board-toolbar .btn,
#expensesPane .form-inline > .btn,
#revenuePane .form-inline > .btn,
#stockPane > .form-inline > .btn,
#businessPane .business-controls > .btn {
  min-height: 38px;
  white-space: nowrap;
}

#revenuePane .form-inline,
#expensesPane .form-inline,
#stockPane > .form-inline,
#businessPane .business-controls {
  row-gap: 10px;
}

#stockPane > .form-inline .stock-search-field {
  flex: 1 1 220px;
}

@media (max-width: 640px) {
  #overviewPane .board-toolbar,
  #barRestaurantPane .board-toolbar,
  #stockLedgerPanel .board-toolbar,
  #suppliersPane .board-toolbar {
    align-items: stretch;
  }

  #overviewPane .board-toolbar .btn,
  #barRestaurantPane .board-toolbar .btn,
  #stockLedgerPanel .board-toolbar .btn,
  #suppliersPane .board-toolbar .btn,
  #revenuePane .form-inline > .btn,
  #expensesPane .form-inline > .btn,
  #stockPane > .form-inline > .btn,
  #businessPane .business-controls > .btn {
    width: 100%;
  }
}


/* =============================================================
   UI/UX AUDIT PASS 9 — Forms, Modals & UI States
   Shared visual language for editable controls, validation,
   confirmation dialogs, loading/empty/error/success states and
   dynamically generated controls. No business logic changes.
   ============================================================= */

/* Form field hierarchy */
.field { min-width: 0; }
.field-label {
  display: block;
  color: var(--ink-soft);
  font-size: .78rem;
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: .01em;
}
.field-label::after { content: ''; }
.field-required::after { content: ' *'; color: var(--danger); }
.field-help,
.field-hint { line-height: 1.45; }
.field input::placeholder,
.field textarea::placeholder,
.search-field input::placeholder,
input[type="search"]::placeholder {
  color: #8a93a3;
  opacity: 1;
}
.field input[aria-invalid="true"],
.field select[aria-invalid="true"],
.field textarea[aria-invalid="true"],
.input-error,
.input-error:focus {
  border-color: var(--danger) !important;
  box-shadow: 0 0 0 3px rgba(155, 51, 43, .10) !important;
}
.field-success,
.field input[aria-invalid="false"],
.field select[aria-invalid="false"],
.field textarea[aria-invalid="false"] {
  border-color: rgba(63,164,91,.55) !important;
}
.field-error {
  display: block;
  line-height: 1.4;
}

/* Dynamic controls: JS-created selects/inputs should never fall back to
   browser-default dimensions when they are inserted outside a .field. */
.module-pane input:not([type="hidden"]),
.module-pane select,
.module-pane textarea {
  font-family: var(--font-body);
  max-width: 100%;
}
.module-pane input:not([type="hidden"]):not(.btn),
.module-pane select,
.module-pane textarea {
  min-height: 40px;
}
.module-pane input[type="number"],
.module-pane input[type="date"],
.module-pane input[type="datetime-local"],
.module-pane input[type="time"],
.module-pane input[type="email"],
.module-pane input[type="text"],
.module-pane input[type="tel"] {
  padding: 9px 11px;
  border: 1px solid #b9c2d6;
  border-radius: 9px;
  background: #fff;
  color: var(--ink);
}
.module-pane select {
  padding: 9px 32px 9px 11px;
  border: 1px solid #b9c2d6;
  border-radius: 9px;
  background-color: #fff;
  color: var(--ink);
}
.module-pane textarea {
  padding: 10px 11px;
  border: 1px solid #b9c2d6;
  border-radius: 9px;
  background: #fff;
  color: var(--ink);
}
.module-pane input:not([type="hidden"]):focus,
.module-pane select:focus,
.module-pane textarea:focus {
  outline: none;
  border-color: var(--accent-green) !important;
  box-shadow: 0 0 0 3px rgba(63,164,91,.12);
}
.module-pane input:disabled,
.module-pane select:disabled,
.module-pane textarea:disabled,
.module-pane input[readonly],
.module-pane textarea[readonly] {
  background: #eef1f6;
  color: var(--stone);
  border-color: #d3dae6;
}

/* Central Store — JS-generated transfer-row controls */
.store-transfer-row td { vertical-align: middle; }
.store-transfer-row .store-transfer-item,
.store-transfer-row .store-transfer-qty {
  width: 100%;
  min-height: 40px;
  box-sizing: border-box;
  border: 1px solid #b9c2d6;
  border-radius: 8px;
  background: #FFFFFF;
  color: var(--ink);
  padding: 8px 10px;
  font: 500 .82rem var(--font-body);
  outline: none;
  transition: border-color .15s var(--ease), box-shadow .15s var(--ease), background .15s var(--ease);
}
.store-transfer-row .store-transfer-item { padding-right: 32px; }
.store-transfer-row .store-transfer-qty {
  min-width: 96px;
  font-family: var(--font-mono);
  text-align: right;
}
.store-transfer-row .store-transfer-item:focus,
.store-transfer-row .store-transfer-qty:focus {
  border-color: var(--accent-green) !important;
  box-shadow: 0 0 0 3px rgba(63,164,91,.12);
  background: #FFFFFF;
}
.store-transfer-row .store-transfer-item:disabled,
.store-transfer-row .store-transfer-qty:disabled {
  background: #eef1f6;
  color: var(--stone);
  border-color: #d3dae6;
  cursor: not-allowed;
}
.store-transfer-row .store-transfer-available {
  color: var(--ink-soft);
  font-family: var(--font-mono);
  font-weight: 600;
}

/* Buttons inside forms and modals */
.modal-actions { align-items: center; }
.modal-actions .btn { min-width: 92px; }
.btn:focus-visible,
.modal-close:focus-visible {
  outline: 3px solid rgba(63,164,91,.20);
  outline-offset: 2px;
}
.btn-danger:focus-visible,
.btn-danger-text:focus-visible {
  outline-color: rgba(155,51,43,.20);
}

/* Modal consistency */
.modal-overlay { backdrop-filter: blur(2px); }
.modal-overlay .modal,
.modal-backdrop .modal {
  width: min(100%, 760px);
  max-height: calc(100vh - 40px);
  overflow-y: auto;
  overscroll-behavior: contain;
}
.modal-overlay .modal-head,
.modal-backdrop .modal-head { position: sticky; top: 0; z-index: 2; }
.modal-overlay .modal-actions,
.modal-backdrop .modal-actions {
  position: sticky;
  bottom: -1px;
  z-index: 2;
  padding-top: 12px;
  margin-top: 14px;
  background: linear-gradient(to bottom, rgba(255,255,255,0), var(--white) 18px);
}
.modal-overlay .modal-head .modal-close:focus-visible { outline-color: rgba(255,255,255,.75); }

/* Reusable state blocks */
.empty-state,
.ui-empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 7px;
  min-height: 120px;
  padding: 24px 18px;
  text-align: center;
  color: var(--stone);
  background: rgba(245,247,250,.48);
  border: 1px dashed var(--parchment-dim);
  border-radius: 10px;
  line-height: 1.5;
}
.empty-state strong,
.ui-empty-state strong { color: var(--ink-soft); font-size: .88rem; }
.empty-state .btn,
.ui-empty-state .btn { margin-top: 5px; }

.error-state,
.ui-error-state,
.success-state,
.ui-success-state,
.info-state,
.ui-info-state {
  border-radius: 10px;
  padding: 13px 15px;
  line-height: 1.45;
  font-size: .84rem;
}
.error-state,
.ui-error-state {
  color: var(--danger);
  background: var(--danger-bg);
  border: 1px solid rgba(155,51,43,.15);
}
.success-state,
.ui-success-state {
  color: var(--primary-dark);
  background: rgba(63,164,91,.07);
  border: 1px solid rgba(63,164,91,.15);
}
.info-state,
.ui-info-state {
  color: var(--ink-soft);
  background: rgba(245,247,250,.70);
  border: 1px solid var(--parchment-dim);
}

.form-error,
.form-error-banner,
[role="alert"] {
  line-height: 1.45;
}
.form-error-banner.show { display: flex; align-items: flex-start; gap: 8px; }

.loading-state {
  min-height: 96px;
  border-radius: 10px;
}
.loading-state--row {
  min-height: 54px;
  margin: 0;
}
.loading-state .spinner { flex: 0 0 auto; }

/* Disabled/processing controls should communicate state without changing
   layout or making the whole toolbar jump. */
.btn.is-loading { min-width: 96px; }
.btn[aria-busy="true"] { cursor: progress; }

/* Search and filter controls stay usable when toolbars become narrow. */
.form-inline,
.board-toolbar,
.admin-toolbar,
.page-section-intro {
  min-width: 0;
}
.form-inline > .field,
.board-toolbar > .field,
.admin-toolbar > .field { min-width: 0; }

@media (max-width: 720px) {
  .modal-overlay .modal,
  .modal-backdrop .modal {
    max-height: calc(100vh - 20px);
  }
  .modal-actions .btn { flex: 1 1 130px; }
}
@media (max-width: 560px) {
  .modal-overlay .modal,
  .modal-backdrop .modal {
    max-height: 100vh;
  }
  .modal-overlay .modal-actions,
  .modal-backdrop .modal-actions {
    position: static;
    background: none;
  }
  .modal-actions .btn { width: 100%; }
  .empty-state,
  .ui-empty-state { min-height: 100px; padding: 20px 14px; }
}

/* =============================================================
   UI/UX AUDIT PASS 10 — FINAL MOBILE + RESPONSIVE REVIEW
   =============================================================
   Final responsive layer. Keeps the existing Kawa visual language,
   business logic, IDs and JS hooks intact while preventing common
   narrow-screen overflow and cramped controls.
   ============================================================= */

/* Global media safety inside the staff application. */
.app-main,
.app-content,
.app-content-inner,
.module-pane,
.module-pane > *,
.card,
.panel-card,
.modal,
.modal-body {
  min-width: 0;
}

.app-content img,
.app-content svg,
.app-content video,
.app-content canvas {
  max-width: 100%;
}

.app-content input,
.app-content select,
.app-content textarea,
.app-content button {
  max-width: 100%;
}

/* Long operational text should break inside cards instead of widening
   the page on phones. */
.app-content h1,
.app-content h2,
.app-content h3,
.app-content h4,
.app-content p,
.app-content td,
.app-content th,
.app-content .text-stone,
.app-content .section-note,
.app-content .card-note {
  overflow-wrap: anywhere;
}

/* Dense grids collapse progressively instead of waiting for the
   smallest breakpoint. */
@media (max-width: 980px) {
  .room-type-grid,
  .purchase-card-grid,
  .purchase-card-grid--top,
  .purchase-card-grid--numbers,
  .supplier-detail-grid,
  .unit-config-grid,
  .night-audit-grid,
  .approval-review-grid,
  .kawa-ai-knowledge-grid,
  .zra-management-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .business-dashboard-grid,
  .business-detail-grid,
  .business-detail-charts,
  .business-detail-lists {
    min-width: 0;
  }

  .pos-page-intro,
  .reservation-form-head,
  .business-detail-head {
    align-items: flex-start;
  }
}

/* Tablet / narrow desktop: make the shell and toolbars breathe. */
@media (max-width: 860px) {
  .app-topbar {
    min-width: 0;
  }

  .app-page-title {
    min-width: 0;
  }

  .app-connection-status {
    margin-right: 0;
  }

  .app-content-inner {
    width: 100%;
    max-width: 100%;
  }

  .board-toolbar,
  .board-toolbar--secondary,
  .admin-toolbar,
  .store-toolbar,
  .store-filter-toolbar,
  .stock-toolbar,
  .purchase-toolbar-actions,
  .purchases-toolbar,
  .supplier-toolbar,
  .reception-toolbar,
  .guests-directory-toolbar,
  .night-audit-toolbar,
  .business-toolbar,
  .table-toolbar {
    min-width: 0;
  }

  .board-toolbar > *,
  .board-toolbar--secondary > *,
  .admin-toolbar > *,
  .store-toolbar > *,
  .store-filter-toolbar > *,
  .stock-toolbar > *,
  .purchase-toolbar-actions > *,
  .purchases-toolbar > *,
  .supplier-toolbar > *,
  .reception-toolbar > *,
  .guests-directory-toolbar > *,
  .night-audit-toolbar > *,
  .business-toolbar > *,
  .table-toolbar > * {
    min-width: 0;
    max-width: 100%;
  }

  .pos-page-intro {
    flex-wrap: wrap;
  }

  .pos-page-intro .btn,
  .reservation-form-head .btn,
  .business-detail-head .btn {
    flex: 0 0 auto;
  }
}

/* Phone layout: controls become comfortably tappable and toolbars
   become vertical groups rather than squeezed horizontal rows. */
@media (max-width: 640px) {
  .app-topbar {
    padding: 11px 12px;
    gap: 8px;
  }

  .app-page-title {
    font-size: 1.05rem;
  }

  .app-connection-status {
    font-size: .62rem;
    padding: 4px 7px;
  }

  .app-content {
    padding: 14px 12px;
  }

  .app-content-inner {
    width: 100%;
  }

  .btn,
  .btn-primary,
  .btn-secondary,
  .btn-ghost,
  .btn-brass,
  .btn-danger {
    min-height: 40px;
  }

  .btn.btn-sm,
.btn-sm {
  min-height: 36px;
}

/* Small inputs, for a control that has to sit beside a .btn-sm without
   changing the height of the row. The height is stated rather than inherited
   because the global input rule sets padding but no height, so an input
   placed next to a 36px button came out taller and the toolbar read as
   ragged.

   Sized against .btn-sm (36px) rather than .btn (38px) because every toolbar
   that uses this pairs it with a .btn-sm, and a paired row has to match the
   smaller one or it still looks broken. Deliberately sets no background,
   border or colour, so it inherits whatever the surrounding module already
   does and only the box changes. */
.input-sm {
  min-height: 36px;
  padding: 5px 10px;
  font-size: 0.88rem;
}

  .board-toolbar,
  .board-toolbar--secondary,
  .admin-toolbar,
  .store-toolbar,
  .store-filter-toolbar,
  .stock-toolbar,
  .purchase-toolbar-actions,
  .purchases-toolbar,
  .supplier-toolbar,
  .reception-toolbar,
  .guests-directory-toolbar,
  .night-audit-toolbar,
  .business-toolbar,
  .table-toolbar,
  .form-inline {
    width: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 9px;
  }

  .board-toolbar > .field,
  .board-toolbar--secondary > .field,
  .admin-toolbar > .field,
  .store-toolbar > .field,
  .store-filter-toolbar > .field,
  .stock-toolbar > .field,
  .purchase-toolbar-actions > .field,
  .purchases-toolbar > .field,
  .supplier-toolbar > .field,
  .reception-toolbar > .field,
  .guests-directory-toolbar > .field,
  .night-audit-toolbar > .field,
  .business-toolbar > .field,
  .table-toolbar > .field,
  .form-inline > .field,
  .form-inline > input,
  .form-inline > select,
  .form-inline > textarea {
    width: 100%;
    min-width: 0;
    flex: 1 1 auto;
  }

  .board-toolbar > .btn,
  .board-toolbar--secondary > .btn,
  .admin-toolbar > .btn,
  .store-toolbar > .btn,
  .store-filter-toolbar > .btn,
  .stock-toolbar > .btn,
  .purchase-toolbar-actions > .btn,
  .purchases-toolbar > .btn,
  .supplier-toolbar > .btn,
  .reception-toolbar > .btn,
  .guests-directory-toolbar > .btn,
  .night-audit-toolbar > .btn,
  .business-toolbar > .btn,
  .form-inline > .btn {
    width: 100%;
    margin-top: 0;
  }

  /* Keep groups of action buttons together without forcing a single
     long row. */
  .board-toolbar__actions,
  .store-toolbar-actions,
  .purchase-toolbar-actions,
  .board-toolbar .form-inline,
  .admin-toolbar .form-inline,
  .table-toolbar-exports {
    width: 100%;
    flex-wrap: wrap;
    gap: 7px;
  }

  .board-toolbar__actions .btn,
  .store-toolbar-actions .btn,
  .purchase-toolbar-actions .btn,
  .board-toolbar .form-inline .btn,
  .admin-toolbar .form-inline .btn,
  .table-toolbar-exports .btn {
    flex: 1 1 140px;
    width: auto;
  }

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

  .module-tabs {
    max-width: 100%;
  }

  .module-tab {
    min-height: 38px;
  }

  /* POS inline fields contain legacy inline min-width values; the
     mobile rule intentionally wins so the fields remain usable. */
  .pos-menu-search,
  .pos-menu-search input,
  .folio-input,
  #openFolioSearch,
  #manualBarcodeInput,
  #stockAdjustManualInput {
    min-width: 0 !important;
    width: 100%;
    max-width: 100% !important;
  }

  .pos-menu-tools,
  .order-card-head,
  .order-card-foot,
  .menu-category-head,
  .pos-section-heading {
    flex-wrap: wrap;
  }

  .order-grid,
  .room-grid,
  .overview-grid,
  .purchase-card-grid,
  .purchase-card-grid--top,
  .purchase-card-grid--numbers,
  .supplier-detail-grid,
  .unit-config-grid,
  .night-audit-grid,
  .approval-review-grid,
  .kawa-ai-knowledge-grid,
  .zra-management-grid {
    grid-template-columns: 1fr;
  }

  .stat-grid,
  .reception-stat-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .business-mini-stats,
  .business-card-grid {
    grid-template-columns: 1fr 1fr;
  }

  .business-detail-net {
    text-align: left;
    white-space: normal;
  }

  .business-chart-wrap,
  .business-chart-wrap--large {
    height: 240px;
  }

  .modal-overlay,
  .modal-backdrop {
    padding: 10px;
  }

  .modal-overlay .modal,
  .modal-backdrop .modal {
    width: 100%;
    max-width: 100%;
    max-height: calc(100vh - 20px);
    overflow: hidden;
  }

  .modal-overlay .modal-body,
  .modal-backdrop .modal-body {
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }

  .modal-actions {
    flex-wrap: wrap;
    gap: 7px;
  }

  .modal-actions .btn {
    flex: 1 1 140px;
  }

  .table-wrap {
    max-width: 100%;
  }

  .data-table {
    font-size: .78rem;
  }

  .data-table th,
  .data-table td {
    padding: 8px 9px;
  }

  /* Do not shrink important monetary/status values into unreadable
     columns; allow the table wrapper to scroll instead. */
  .table-wrap:not(.table-wrap--cards):not(.table-wrap--mobile-cards) {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
}

@media (max-width: 420px) {
  .app-content {
    padding-left: 10px;
    padding-right: 10px;
  }

  .app-topbar {
    padding-left: 10px;
    padding-right: 10px;
  }

  .app-connection-status {
    display: none;
  }

  .stat-grid,
  .reception-stat-grid,
  .business-mini-stats,
  .business-card-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .module-tab {
    font-size: .8rem;
    padding-left: 9px;
    padding-right: 9px;
  }

  .modal-actions .btn {
    flex-basis: 100%;
  }
}

/* Respect reduced-motion preferences in the final responsive layer. */
@media (prefers-reduced-motion: reduce) {
  .module-pane.is-active,
  .app-sidebar,
  .module-tab,
  .btn,
  .modal {
    animation: none !important;
    transition: none !important;
  }
}

/* Reports PDF / toolbar actions */
/* ============================================================ toolbar control layout ==
 *
 * MEASURED, Suppliers tab, 800px viewport, 749px toolbar, before this fix:
 *
 *     descriptive block     580px at x=18     claims its max-content before shrinking
 *     .flex-gap             375px at y=534    <- second line, with a wide empty band left
 *       .field-inline       180px  flex: 1 1 180px, min-width min(100%,180px) so it cannot
 *                                    shrink below 180
 *       .toolbar-actions    185px  flex: 0 1 auto, flex-wrap: wrap
 *         Download PDF       118px at y=534
 *         Refresh             75px at y=580    <- and a third line
 *
 * THE FAULT IS A SIXTEEN-PIXEL SHORTFALL, NOT THE WRAP
 * ----------------------------------------------------
 * The two buttons need 118 + 75 + 8 = 201px. The box is 185px. It gets 185 because the field
 * beside it holds 180 and the gap between them is 10: 180 + 10 + 185 = 375, the group's width.
 *
 * .toolbar-actions is `flex: 0 1 auto` inside a nowrap group, so it is squeezed to whatever is
 * left - and because it was allowed to wrap, being squeezed made it WRAP rather than overflow.
 * Two buttons that fit on one line ended up on two. The field could not give the space back
 * because min-width floors it at 180, and that floor is deliberate: it is what stops a search
 * box collapsing to nothing.
 *
 * So a row of buttons stops being a paragraph. On its own that overflows the group by 16px,
 * which is why the second half of this fix exists.
 *
 * BOTH HALVES, OR NEITHER
 * -----------------------
 * The descriptive block needs a zero basis so it is out of the line-breaking sum and the group
 * gets a line of its own to be as wide as it needs. Flex decides line breaking BEFORE it
 * decides shrinking, and shrink only applies inside a line - so with the block measured at its
 * 580px max-content, 580 + 375 exceeds 749 and the group is moved to a new line, after which
 * there is nothing left to shrink. A 240px basis was tried and wrapped the Business toolbar by
 * two pixels (240 + 511 = 751 into 749). Zero is the only basis that cannot cause a wrap.
 *
 * The block shrinks before the buttons do, because a sentence re-wraps for free and a button
 * has nowhere to go.
 */
.toolbar-actions{display:flex;gap:8px;flex-wrap:nowrap;justify-content:flex-end;align-items:center;}

.board-toolbar > .flex-gap,
.board-toolbar > .toolbar-actions,
.admin-toolbar > .flex-gap,
.admin-toolbar > .toolbar-actions { flex: 0 1 auto; min-width: 0; max-width: 100%; }

/*
 * THE THING THAT WAS EATING THE ROOM, and the last of the three causes.
 *
 * With the buttons set not to wrap and the text block on a zero basis, the Suppliers toolbar
 * became one row and Refresh hung 16px off the right edge. Arithmetic of the shortfall:
 *
 *     field-inline   180px   flex 1 1 180px, min-width min(100%, 180px)
 *     gap            10px
 *     buttons        201px   118 + 75 + 8, now nowrap
 *                  ---
 *                  391px   needed, 375px available in the group. Sixteen over.
 *
 * Two things were tried for the group and neither works, and the reason is worth recording:
 *
 *   flex: 0 0 max-content   the toolbar collapsed to 691px while its controls ran to x=972
 *   min-width: max-content  IGNORED. Chrome reports this container's max-content as 357px when
 *                           its contents actually need 391px, so the floor it sets is 34px too
 *                           low to be the floor anyone wanted. A max-content floor on a group
 *                           whose children carry their own flex is not a reliable measurement.
 *
 * So the space is taken back from the only thing in the group that can afford it. The field
 * is a SELECT and it was being held at 180px by a min-width meant for search boxes; at 150px
 * "With a balance" fits comfortably, and:
 *
 *     150 + 10 + 201 = 361px   inside 375px. The buttons keep their width, which is the point.
 *
 * A select narrows gracefully. A button has nowhere narrower to go.
 */
.board-toolbar > .flex-gap > .field-inline,
.admin-toolbar > .flex-gap > .field-inline,
.board-toolbar > .flex-gap > .field,
.admin-toolbar > .flex-gap > .field { flex: 0 1 150px; min-width: 0; }

.board-toolbar > :first-child:not(.field):not(.field-inline):not(.flex-gap):not(.toolbar-actions),
.admin-toolbar > :first-child:not(.field):not(.field-inline):not(.flex-gap):not(.toolbar-actions) {
  flex: 1 1 0;
  min-width: 0;
  overflow-wrap: anywhere;
}

@media (max-width:760px){
  /* The buttons go full width here, and on a phone two of them do not always fit side by side.
     So wrapping comes back exactly where the room runs out, and nowhere else. */
  .toolbar-actions{width:100%;justify-content:flex-start;flex-wrap:wrap;}
  .toolbar-actions .btn{flex:1 1 auto;min-width:120px;}
}
/* ===== end toolbar control layout ===== */

/* ── Profile hero (2026 redesign) ─────────────────────────────── */
.profile-hero { position: relative; overflow: hidden; padding: 0; margin-bottom: 20px; }
.profile-hero-bg {
  position: absolute; inset: 0 0 auto 0; height: 84px; overflow: hidden;
  background: linear-gradient(120deg, var(--primary) 0%, var(--primary-dark) 55%, var(--clay-dark) 100%);
}
.profile-hero-bg::after {
  content: ''; position: absolute; right: -30px; top: -50px; width: 180px; height: 180px;
  border-radius: 50%; background: rgba(111, 92, 196, 0.35); filter: blur(6px);
}
.profile-hero-body {
  position: relative; display: flex; align-items: flex-end; gap: 18px;
  padding: 26px 24px 20px; flex-wrap: wrap;
}
.profile-avatar-wrap { position: relative; flex-shrink: 0; }
.profile-avatar {
  width: 96px; height: 96px; border-radius: 50%;
  border: 4px solid var(--white); box-shadow: var(--shadow-card);
  background: var(--clay-bg); color: var(--clay-dark);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display); font-size: 1.9rem; font-weight: 700;
  overflow: hidden; margin-top: 18px;
}
.profile-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.profile-avatar-edit {
  position: absolute; right: -2px; bottom: 2px; width: 30px; height: 30px;
  border-radius: 50%; border: 2px solid var(--white);
  background: var(--primary); color: #fff; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background .15s var(--ease), transform .15s var(--ease);
}
.profile-avatar-edit:hover { background: var(--clay); transform: scale(1.08); }
.profile-avatar-edit:disabled { opacity: .5; cursor: wait; }
.profile-hero-info { flex: 1 1 220px; padding-bottom: 6px; }
.profile-hero-name {
  margin: 0; font-family: var(--font-display); font-weight: 700;
  font-size: 1.45rem; color: #fff; line-height: 1.2;
  text-shadow: 0 1px 3px rgba(16, 24, 40, .45);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.profile-hero-title { margin: 2px 0 8px; color: var(--stone); font-size: .88rem; }
.profile-hero-badges { display: flex; gap: 8px; flex-wrap: wrap; }
.profile-role-badge {
  background: var(--primary); color: #fff; border-radius: 999px;
  padding: 3px 12px; font-size: .72rem; letter-spacing: .04em; text-transform: uppercase; font-weight: 600;
}
.profile-dept-badge {
  background: var(--clay-bg); color: var(--clay-dark); border-radius: 999px;
  padding: 3px 12px; font-size: .72rem; letter-spacing: .04em; text-transform: uppercase; font-weight: 600;
}
.profile-hero-actions { display: flex; flex-direction: column; align-items: flex-end; gap: 8px; padding-bottom: 6px; }
.profile-hero-hint { margin: 0; font-size: .7rem; }

/* Sidebar avatar (replaces the profile icon when a photo is set) */
.app-user-avatar {
  width: 22px; height: 22px; border-radius: 50%; overflow: hidden; flex-shrink: 0;
  border: 1px solid rgba(251, 252, 254, 0.4);
}
.app-user-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }

@media (max-width: 640px) {
  .profile-hero-body { padding: 20px 16px 16px; }
  .profile-avatar { width: 76px; height: 76px; font-size: 1.5rem; }
  .profile-hero-actions { align-items: flex-start; }
}

/* ── Staff mode: simplified flat "task bar" nav for non-management
   roles (bar, restaurant, housekeeping, reception). Bigger touch
   targets, one workspace list, primary station first. ─────────── */
.staff-mode .app-nav { gap: 8px; }
.staff-mode .app-nav-section-label {
  font-size: .68rem;
  letter-spacing: .14em;
  color: rgba(243, 245, 249, 0.55);
}
.staff-mode .app-nav-section-items { display: flex; flex-direction: column; gap: 6px; }
.staff-mode .app-nav-tile {
  border-radius: var(--radius);
  padding: 12px 14px;
  font-size: .95rem;
  font-weight: 500;
  background: rgba(251, 252, 254, 0.05);
  border: 1px solid rgba(251, 252, 254, 0.08);
  transition: background .15s var(--ease), border-color .15s var(--ease), transform .15s var(--ease);
}
.staff-mode .app-nav-tile .app-nav-icon { width: 20px; height: 20px; opacity: .9; }
.staff-mode .app-nav-tile:hover {
  background: rgba(251, 252, 254, 0.12);
  border-color: rgba(251, 252, 254, 0.2);
  transform: translateX(2px);
}
.staff-mode .app-nav-tile.is-active {
  background: linear-gradient(120deg, var(--accent-green), var(--accent-green-dark));
  border-color: transparent;
  color: #fff;
  font-weight: 600;
  box-shadow: 0 4px 14px rgba(63, 164, 91, 0.35);
}
.staff-mode .app-nav-tile.is-active .app-nav-icon { opacity: 1; }

/* ── POS tile grid (bar & restaurant New Order) ─────────────────── */
.pos-cat-chips {
  display: flex; gap: 8px; overflow-x: auto; padding: 2px 2px 8px;
  margin: 4px 0 10px; scrollbar-width: thin;
}
.pos-cat-chip {
  flex-shrink: 0; display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 14px; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--line); background: var(--white); color: var(--stone);
  font: inherit; font-size: .82rem; font-weight: 500;
  transition: all .15s var(--ease);
}
.pos-cat-chip:hover { border-color: var(--clay-light); color: var(--clay-dark); }
.pos-cat-chip.is-active {
  background: var(--primary); border-color: var(--primary); color: #fff; font-weight: 600;
}
.pos-cat-chip-count {
  font-size: .68rem; padding: 1px 7px; border-radius: 999px;
  background: rgba(16, 24, 40, 0.08);
}
.pos-cat-chip.is-active .pos-cat-chip-count { background: rgba(255, 255, 255, 0.22); }

.pos-item-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(148px, 1fr));
  gap: 10px;
}
.pos-item-tile {
  position: relative; display: flex; flex-direction: column; align-items: flex-start;
  gap: 4px; padding: 14px 13px 12px; min-height: 104px;
  border-radius: var(--radius); cursor: pointer; text-align: left;
  border: 1px solid var(--line); background: var(--white);
  font: inherit; color: var(--ink);
  transition: border-color .15s var(--ease), box-shadow .15s var(--ease), transform .1s var(--ease);
}
.pos-item-tile:hover {
  border-color: var(--accent-green);
  box-shadow: 0 6px 16px rgba(63, 164, 91, 0.16);
  transform: translateY(-2px);
}
.pos-item-tile:active { transform: scale(.97); }
.pos-item-tile.in-cart { border-color: var(--accent-green); background: #f2fbf5; }
.pos-item-tile.is-out-of-stock { opacity: .5; cursor: not-allowed; }
.pos-item-tile.is-out-of-stock:hover { transform: none; box-shadow: none; border-color: var(--line); }
.pos-tile-name { font-weight: 600; font-size: .9rem; line-height: 1.25; }
.pos-tile-price { font-size: 1rem; font-weight: 700; color: var(--primary); }
.pos-tile-stock { font-size: .68rem; color: var(--stone); }
.pos-item-tile.is-out-of-stock .pos-tile-stock { color: var(--danger); font-weight: 600; }
.pos-tile-cat {
  font-size: .64rem; color: var(--clay-dark); background: var(--clay-bg);
  padding: 1px 8px; border-radius: 999px;
}
.pos-tile-qty {
  position: absolute; top: -7px; right: -7px; min-width: 22px; height: 22px;
  border-radius: 999px; background: var(--accent-green); color: #fff;
  font-size: .72rem; font-weight: 700; display: flex; align-items: center; justify-content: center;
  padding: 0 5px; box-shadow: 0 2px 6px rgba(16, 24, 40, 0.3);
}
.pos-tile-flash { animation: posTileFlash .5s var(--ease); }
@keyframes posTileFlash {
  0% { box-shadow: 0 0 0 0 rgba(63, 164, 91, 0.55); }
  100% { box-shadow: 0 0 0 14px rgba(63, 164, 91, 0); }
}
@media (max-width: 640px) {
  .pos-item-grid { grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 8px; }
  .pos-item-tile { min-height: 92px; padding: 11px 10px; }
}

/* Bring back a little tactile feedback without making dense work screens jumpy. */
@media (hover: hover) and (pointer: fine) {
  .app-content .stat-card:hover,
  .app-content .business-card:hover,
  .app-content .overview-card:hover,
  .app-content .admin-card:hover,
  .app-content .panel-card:hover,
  .app-content .room-card--clickable:hover {
    transform: translateY(-2px);
    border-color: rgba(63, 164, 91, .48);
    box-shadow: 0 10px 24px rgba(16, 24, 40, .10);
  }
  .app-nav-link:hover:not(.is-active) { transform: translateX(2px); }
}

/* =====================================================================
   Stock screen - view tabs, and the expiry view added beside the ledger.

   The tabs are a plain two-button strip rather than a nav: there are only
   two views, and both live on one screen that staff already had open, so
   adding a top-level nav entry for expiry would have meant a second place
   to look and a second thing to learn.

   Colours reuse the existing danger / moss / brass tokens rather than
   introducing new ones, so the expiry chips read as part of the same
   system as the badges in the ledger beside them.

   On the chips: expired and expiring are toned, undated is neutral. A
   warning that looks alarming on every row trains people to stop reading
   the screen, and "nobody wrote the date down" is not the same kind of
   fact as "this is out of date" - it is a to-do, not a fault.
   ===================================================================== */

.stock-view-tabs {
  display: flex;
  gap: 4px;
  margin: 0 0 16px;
  border-bottom: 1px solid var(--line, #e7e5e4);
}

.stock-view-tab {
  appearance: none;
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  padding: 10px 16px;
  font: inherit;
  font-weight: 600;
  color: var(--stone, #78716c);
  cursor: pointer;
  margin-bottom: -1px;
}

.stock-view-tab:hover { color: var(--ink, #292524); }

.stock-view-tab.is-active {
  color: var(--ink, #292524);
  border-bottom-color: var(--brass, var(--primary));
}

.stock-view-tab:focus-visible {
  outline: 2px solid var(--brass, var(--primary));
  outline-offset: 2px;
}

.stock-expiry-window { max-width: 7rem; }

/* --- the date-left chip ------------------------------------------------- */

.expiry-chip {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: .78rem;
  font-weight: 600;
  white-space: nowrap;
  background: #f5f5f4;
  color: var(--stone, #78716c);
}

.expiry-chip--expired {
  background: var(--danger-bg, #F7E8E4);
  color: var(--danger, #A6342A);
}

.expiry-chip--soon {
  background: #e9e4f7;
  color: var(--brass-dark, #6b5a1f);
}

.expiry-chip--undated {
  background: #f5f5f4;
  color: var(--stone, #78716c);
  border: 1px dashed #d6d3d1;
}

/* --- inline date editor ------------------------------------------------- */

.stock-expiry-edit {
  display: inline-flex;
  gap: 6px;
  align-items: center;
}

/*
 * NEITHER CHILD MAY SHRINK.
 *
 * Measured 2026-10-06, and this is the reason the Save button read as a column of letters -
 * "S" over "a" over "v" over "e" in a 38px box, 69px tall.
 *
 * .stock-expiry-edit is display:inline-flex, so the date input and the Save button are flex
 * items. In a table cell the width available is whatever the other eight columns leave, which in
 * a nine-column table is not much, and a flex item with the default flex-shrink:1 gives up its
 * width to keep its neighbour. The input has a max-width so it gave up the smaller amount; the
 * button gave up all of it, collapsed to the width of a single character, and wrapped its own
 * label one letter per line.
 *
 * Nothing errored and nothing overflowed - the button simply became unreadable. Same family as
 * the toolbar button that measured its own text as a height, and the filter row that swallowed
 * the line below it: a layout fault that no assertion about behaviour will ever find, and that
 * only a screenshot or a computed width shows.
 *
 * The button is flex:none because a button's width is its label. The input is allowed to shrink
 * but no further than a date can usefully be, and nowrap is belt and braces so a button can never
 * stack its label again whatever else changes.
 */
.stock-expiry-edit > .btn {
  flex: none;
  white-space: nowrap;
}
.stock-expiry-date {
  flex: 0 1 auto;
  min-width: 8.5rem;
}

.stock-expiry-date {
  font: inherit;
  padding: 5px 8px;
  border: 1px solid #d6d3d1;
  border-radius: 6px;
  background: #fff;
  color: var(--ink, #292524);
  max-width: 10.5rem;
}

.stock-expiry-date:focus {
  outline: 2px solid var(--brass, var(--primary));
  outline-offset: 1px;
  border-color: var(--brass, var(--primary));
}

/* --- alert card --------------------------------------------------------- */

.stock-expiry-alert-list {
  margin: 8px 0 0;
  padding-left: 20px;
}

.stock-expiry-alert-list li { margin-bottom: 4px; }

/* --- stat cards --------------------------------------------------------- */

.stock-expiry-stat--soon .stat-value { color: var(--brass-dark, #6b5a1f); }

@media (max-width: 640px) {
  .stock-expiry-edit { flex-wrap: wrap; }
  .stock-expiry-date { max-width: 100%; width: 100%; }
}

/* =====================================================================
   Expiry warning on the POS tile.

   Deliberately a badge and not a disabled state. The lodge's rule is that
   expiry warns and never blocks: a barman who is shown a date can judge
   whether it is real, and if the data turns out to be wrong the cost is a
   surprised customer rather than a till that refuses the money.

   Sized to sit above the item name without pushing the price off the tile,
   and deliberately low-contrast for "expiring" - the thing staff should
   notice once, not something that shouts on every screen all day. Only
   genuinely expired stock gets the loud treatment, because that one does
   deserve to stop somebody mid-pour.
   ===================================================================== */

.pos-tile-expiry {
  display: inline-block;
  align-self: flex-start;
  font-size: .68rem;
  font-weight: 700;
  line-height: 1.2;
  padding: 2px 6px;
  border-radius: 4px;
  white-space: nowrap;
}

.pos-tile-expiry.is-expiring {
  background: #e9e4f7;
  color: var(--brass-dark, #6b5a1f);
}

.pos-tile-expiry.is-expired {
  background: var(--danger-bg, #F7E8E4);
  color: var(--danger, #A6342A);
  box-shadow: inset 0 0 0 1px rgba(166, 52, 42, .25);
}

/* A sold-out tile is already greyed out; the badge must not fight it. */
.pos-item-tile.is-out-of-stock .pos-tile-expiry { opacity: .55; }

/* =====================================================================
   Item form - "this product expires" checkbox and its explanation.
   ===================================================================== */

.expiry-track-option {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin-top: 2px;
}

.expiry-track-option input[type="checkbox"] { margin-top: 3px; }

.expiry-track-note {
  font-size: .82rem;
  color: var(--stone, #78716c);
  line-height: 1.45;
}

/* Expiry / lot inputs on a purchase line. Separate grid from the quantity
   and cost grid above it because it is optional and conditional - showing an
   empty "Expires" box next to the required price fields makes it read as
   another thing you have to fill in, and the whole point is that leaving it
   blank is allowed. */
.purchase-card-grid--expiry {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px dashed #d6d3d1;
}

.purchase-card-grid--expiry .field-label {
  font-weight: 500;
  color: var(--stone, #78716c);
  font-size: .85rem;
}

/* Expiry fields on the Receive stock dialog. A dashed top border marks them
   as a separate, optional part of the delivery rather than more of the same
   form - they only appear for a product that expires, and the note underneath
   is what stops a blank date reading as an oversight. */
.stock-receive-expiry {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 12px;
  padding-top: 12px;
  margin-top: 2px;
  border-top: 1px dashed #d6d3d1;
}

.stock-receive-expiry .field-help {
  font-size: .8rem;
  color: var(--stone, #78716c);
  line-height: 1.4;
}

.stock-receive-expiry-note {
  grid-column: 1 / -1;
  margin: 0;
}

/* =====================================================================
   Shelf switcher - Main bar vs Promo Section.

   Two buttons rather than a dropdown, because the shelf is the single
   biggest determinant of what a tap costs and it should take a deliberate
   press every time. A select would hide the current choice behind a closed
   control at the moment it matters most.
   ===================================================================== */

.pos-shelf-switch {
  display: inline-flex;
  gap: 4px;
  padding: 4px;
  border-radius: 999px;
  background: #f5f5f4;
  margin-bottom: 10px;
}

.pos-shelf-chip {
  appearance: none;
  border: 0;
  border-radius: 999px;
  padding: 7px 18px;
  font: inherit;
  font-weight: 600;
  font-size: .9rem;
  color: var(--stone, #78716c);
  background: transparent;
  cursor: pointer;
}

.pos-shelf-chip.is-active {
  background: #fff;
  color: var(--ink, #292524);
  box-shadow: 0 1px 2px rgba(0, 0, 0, .12);
}

.pos-shelf-chip:disabled { opacity: .5; cursor: not-allowed; }
.pos-shelf-chip:focus-visible { outline: 2px solid var(--brass, var(--primary)); outline-offset: 1px; }

/* Stands in for "the price is different here", which is the whole reason for
   switching and is not obvious from a struck-through figure alone. */
.pos-shelf-banner {
  background: #e9e4f7;
  color: var(--brass-dark, #6b5a1f);
  border-radius: 8px;
  padding: 10px 14px;
  margin-bottom: 12px;
  font-size: .88rem;
  line-height: 1.45;
}

/* --- promo price on a tile ------------------------------------------------ */

.pos-tile-price.is-promo { color: #6b5a1f; font-weight: 700; }

/* The price it replaced. Struck through rather than hidden: a guest should be
   able to see it came down, and staff should be able to see they are on the
   promo shelf and not the main bar. */
.pos-tile-was {
  display: block;
  font-size: .72rem;
  color: var(--stone, #78716c);
  text-decoration: line-through;
}

/* =====================================================================
   Deliveries list on the item form.

   The point is that management can see and correct the real dates for a
   product while they are already on its edit screen, rather than having to
   find them on the Stock screen. Tinted the same way the expiry chips are on
   that screen, so "this batch needs attention" reads identically in both
   places - two screens answering the same question should not look like two
   different questions.
   ===================================================================== */

.menu-deliveries {
  border: 1px solid #e7e5e4;
  border-radius: 10px;
  padding: 12px 14px;
  margin-top: 4px;
}

.menu-deliveries-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
}

.menu-deliveries-body { display: grid; gap: 8px; }

.menu-deliveries-empty { margin: 0; font-size: .88rem; }

.menu-delivery {
  border: 1px solid #ececea;
  border-left: 3px solid #d6d3d1;
  border-radius: 8px;
  padding: 8px 10px;
  background: #fdfdfc;
}

.menu-delivery.is-expired    { border-left-color: var(--danger, #A6342A); background: var(--danger-bg, #F7E8E4); }
.menu-delivery.is-expiring   { border-left-color: var(--brass-dark, #6b5a1f); background: #f6f3ec; }
.menu-delivery.is-undated    { border-left-color: #a8a29e; }

.menu-delivery-line {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: baseline;
  font-size: .84rem;
}

.menu-delivery-qty { font-weight: 600; }
.menu-delivery-received,
.menu-delivery-lot { color: var(--stone, #78716c); }

.menu-delivery-edit {
  display: flex;
  gap: 6px;
  align-items: center;
  margin-top: 6px;
}

.menu-delivery-date {
  font: inherit;
  padding: 4px 8px;
  border: 1px solid #d6d3d1;
  border-radius: 6px;
  background: #fff;
  max-width: 11rem;
}

.menu-delivery-date-static { font-size: .82rem; margin-top: 4px; }

/* =====================================================================
   Promotions module.

   The screen exists to make one specific failure visible: stock sitting in
   the Promo Section with no reduced price, so it sells at the full price in a
   place whose whole reason for existing is that it is cheaper. That is why
   "no offer set" is a counted stat and its own table rather than a footnote -
   it is the thing nobody would otherwise notice.
   ===================================================================== */

.promo-stat--warn .stat-value { color: var(--brass-dark, #6b5a1f); }

/* The offer itself. Heavier than a normal price so the eye lands on the
   number that differs, not the one it replaces. */
.promo-price {
  color: #6b5a1f;
  font-weight: 700;
}

/* An offer with no stock behind it. Not hidden and not greyed out - the
   setting is real and the gap is the finding, so both stay legible. */
.promo-row--nostock td { background: #fdfaf3; }

.promo-item-summary {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 14px;
  align-items: baseline;
  padding: 10px 12px;
  border-radius: 8px;
  background: #f5f5f4;
  font-size: .9rem;
}

/* The normal price is read-only in the form: a promotion is an override of it,
   not an edit of it, and letting it be typed would invite someone to change
   the real price by accident while setting a discount. */
#promoShelfPrice[readonly] {
  background: #f5f5f4;
  color: var(--stone, #78716c);
  font-weight: 600;
}

/* =====================================================================
   NARROW-SCREEN NAVIGATION - every sidebar link has to be reachable.

   A staff member on a handset could not reach the sidebar links. Two
   faults, both in the shell's responsive rules, and neither visible on a
   desktop, so neither had been caught.

   1. THE DRAWER COULD NOT BE OPENED AT ALL between 861px and 900px.
      Everything that makes the sidebar usable as a drawer lived in
      @media (max-width: 860px): the open state
      (.app-sidebar.is-open { transform: translateX(0) }) and the
      hamburger (.app-menu-toggle { display: flex }). The rule that HIDES
      the drawer lived in @media (max-width: 900px), further down this
      file. In the band between the two breakpoints the sidebar was
      translateX(-100%) with no rule able to undo it, and the button that
      would have added .is-open was itself display:none - so there was no
      sidebar AND no menu to press. Measured in Chrome: at an 878px and an
      893px viewport the drawer sat at left:-238px both closed and "open";
      at 858px and at 908px it behaved.

   2. BELOW 861px THE DRAWER OPENED, BUT PART OF IT SAT OFF-SCREEN WITH
      NO WAY TO BRING IT BACK. The shell fixes the sidebar with
      `height: 100vh` and clips it with `overflow: hidden`. On a phone
      100vh is the LARGEST viewport height - the one you get with the
      browser's URL bar and toolbars hidden - so the drawer is taller
      than the part of the screen a staff member can actually see. The
      sidebar is position:fixed, so the document never scrolls it back:
      the bottom of the drawer, which is where the nav list runs out and
      where Profile / Log out live, sat under the bottom edge of the
      screen with nothing left to move it. The list itself is ~1180px of
      22 rows, so something always has to scroll on a phone.

   The fix, deliberately narrow:

   - The open state is declared once, unguarded. `.app-sidebar.is-open`
     is two classes, so it outranks the one-class hiding rules wherever
     they sit in the file and whichever breakpoint each is in - the two
     can no longer drift apart and silently reopen this band. On a
     desktop there is no hiding transform to beat, so it changes nothing
     there.
   - Across the drawer range the sidebar becomes ONE scroll column sized
     to the visible viewport (100vh, then 100dvh where supported),
     instead of a clipped box with a second scroller nested inside it.
     Nested scrollers are also why the list felt stuck under a finger.
   - Nav rows get a 44px minimum height, the smallest comfortable touch
     target, rather than 42px.

   Everything below is inside @media (max-width: 900px), which is exactly
   the range where the sidebar is a drawer at all, so the desktop layout
   is untouched.
   ===================================================================== */

/* Unguarded on purpose - see fault 1 above. A one-class rule can never
   outrank this, whatever order it appears in. */
.app-sidebar.is-open { transform: translateX(0); }

@media (max-width: 900px) {
  /* The hamburger has to appear across the WHOLE drawer range, not just
     up to 860px. The sidebar is hidden by the max-width:900px rule higher
     up this file, so in the band between the two breakpoints there was a
     hidden sidebar and a hidden button that opens it - no navigation at
     all, and no way to reach it. This is the button that adds .is-open. */
  .app-menu-toggle { display: flex; }

  .app-sidebar {
    /* 100vh first, so a browser without dynamic viewport units still gets
       a working height; 100dvh then sizes the drawer to the part of the
       screen that is actually visible, so nothing is clipped away. */
    height: 100vh;
    height: 100dvh;
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    /* Opens with the slide it always had. The reduced-motion block above
       turns this off with !important for anyone who asked for that. */
    transition: transform .2s var(--ease);
    /* Clear of the home indicator on a phone, which is exactly where the
       last nav row and Log out end up. */
    padding-bottom: max(14px, env(safe-area-inset-bottom));
  }

  /* One scroller, not two. The nav takes its natural height and the
     sidebar scrolls as a single column, so the sections that run past
     the fold - and the footer below them - are all reachable. */
  .app-sidebar .app-nav {
    flex: 0 0 auto;
    overflow: visible;
    padding-bottom: 10px;
  }

  .app-nav-link { min-height: 44px; }
}
/* ---- What each revenue figure measures -----------------------------------
   The revenue report sums three different clocks into one table: cash on the
   calendar day it arrived, room charges on the night slept (rooms trading day
   10:00 to 09:59), bar and restaurant on the F&B trading day 08:00 to 08:00.
   That is deliberate and correct, and no two of them agree at the boundary - so
   the screen states which clock each figure reads on rather than leaving a
   manager to assume they are all the same thing and conclude the report is
   broken. */
.report-clocks {
  margin: 0 0 16px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm, 8px);
  background: var(--surface-subtle, rgba(0, 0, 0, .02));
}
.report-clocks-title {
  margin: 0 0 8px;
  font-size: .78rem;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-stone, #6b7280);
}
.report-clock {
  display: grid;
  grid-template-columns: minmax(120px, 190px) 1fr;
  gap: 4px 12px;
  padding: 4px 0;
}
.report-clock + .report-clock { border-top: 1px solid var(--border-subtle, rgba(0, 0, 0, .05)); }
.report-clock dt { margin: 0; font-weight: 600; }
.report-clock dd { margin: 0; color: var(--text-stone, #6b7280); line-height: 1.45; }
.report-notice { margin: 0 0 16px; }

/*
  These two are rendered INTO .stat-grid, alongside the stat cards - the notice and the
  "what each figure measures" explanation are built in reports.js and prepended to the same
  innerHTML as the cards.

  Without a full-width span they become grid CELLS. .stat-grid is
  `repeat(auto-fit, minmax(160px, 1fr))`, so each one was handed a single ~162px track, and
  measured at 1000px:

      .report-clocks   162px wide, 1186px TALL

  which rendered as one word per line and pushed the three real cards out of the first row.
  grid-column: 1 / -1 makes each span every track, so the explanation is a banner above the
  cards rather than a fourth figure competing with them for the same row.
*/
.report-clocks,
.report-notice { grid-column: 1 / -1; }

@media (max-width: 640px) {
  .report-clock { grid-template-columns: 1fr; gap: 2px; }
  .report-clock dd { margin-bottom: 6px; }
}

/* ---- Continuation badge --------------------------------------------------
   A guest who is still in-house, whose folio is settled, and whose money was
   collected before the rooms trading day opened (10:00 to 09:59). Their stay
   rolled over the cutover carrying tonight's payment, and the room card says so
   rather than showing an empty balance and being read as unpaid. */
.badge-continuation {
  background: rgba(31, 122, 99, .12);
  color: #1f7a63;
  border-color: rgba(31, 122, 99, .3);
}
.room-card[data-continuation="yes"] {
  box-shadow: inset 3px 0 0 rgba(31, 122, 99, .55);
}


/* -------------------------------------------------------------
   Fixed staff topbar clearance.

   .app-topbar is position: fixed with z-index 40, so the content has to
   start below it. That was declared twice, early:

       .app-content { padding-top: 96px; }
       @media (max-width: 900px) { .app-content { padding-top: 90px; }

   but three small-screen blocks later use the padding SHORTHAND, which
   resets padding-top along with the sides:

       @media (max-width: 820px) { .app-content { padding: 22px 18px; }
       @media (max-width: 560px) { .app-content { padding: 18px 14px; }
       @media (max-width: 640px) { .app-content { padding: 14px 12px; }

   A shorthand beats a longhand declared earlier, so at or below 820px the
   content had 14-22px of top padding beneath a topbar whose min-height is
   68px. Measured at 800px wide: topbar 69px, computed padding-top 22px,
   47px of overlap. .module-tabs is the first element in the content, so
   the module tab strip was underneath the nav and unreachable.

   Re-declared last, once, on purpose: fixing the three shorthands would
   hold only until the next small-screen block used `padding` again.
   .app-content is used by p/index.php alone - the staff shell, which
   always renders this topbar - so no public page moves.
   ------------------------------------------------------------- */
.app-content { padding-top: 96px; }

@media (max-width: 900px) {
  .app-content { padding-top: 90px; }
}

/* -------------------------------------------------------------
   Room advances table.

   Advance carried forward is the figure the table exists for, and it has
   two directions that must not look alike: money taken ahead of the
   nights still to come, and nights slept that nobody has paid for.
   Signed and coloured so neither can be skimmed past.
   ------------------------------------------------------------- */
.business-advance-block { margin-top: 24px; }
.business-room-advance-table td.is-advance { color: #1f7a63; font-weight: 600; }
.business-room-advance-table td.is-arrears { color: #8b2424; font-weight: 600; }
/*
  What happened to this room.

  Three per-room facts on the Business > Rooms table, and the styling exists to make the
  distinction readable WITHOUT relying on colour - a resale is the only one of the three that
  is an exception rather than a state, and it is the one that has to be noticed at a glance.

    .room-resale-tag       SOLD TWICE      words, not a colour. A red row would be invisible
                                           to a reader who cannot see red, and this is the
                                           one signal on the tab that must not be missed.
    .is-resold             row tint        supporting only; the words carry the meaning
    .room-advance-tag      + K held        money taken ahead of the nights slept
    .room-arrears-tag      K owed          the guest still owes - deliberately worded as a
                                           debt, and never merged into the advance styling
    .room-continuing-tag   in house: name  a guest is sleeping in the room right now
    .room-resale-note      the night count under the flag
*/
.business-room-profitability-table td .room-resale-tag {
  display: inline-block;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  padding: 2px 6px;
  border-radius: 4px;
  background: #8b2424;
  color: #fff;
  white-space: nowrap;
}
.business-room-profitability-table tr.is-resold { background: rgba(139, 36, 36, 0.05); }
.business-room-profitability-table tr.is-resold td:first-child { box-shadow: inset 3px 0 0 #8b2424; }

.room-resale-note { display: block; font-size: 0.68rem; color: var(--stone-light); margin-top: 2px; }

/* Resale panel - the money behind the SOLD TWICE flag, at the top of the Rooms
   pane. A plain card in the same language as the rest of the reports rather than
   a chart: it is one money figure with a list under it, and a chart would make it
   harder to read off, not easier. */
.resale-panel { margin-bottom: 16px; }
.resale-panel .business-detail-head { align-items: flex-start; }
.resale-panel .data-table td { font-size: 0.92rem; }
.resale-panel .data-table td:first-child { font-weight: 600; }
/* An unattributable discount is shown, not hidden. The tint is the same one the
   rooms table uses for a resold row, so the panel and the table read as one thing. */
.resale-panel-warn {
  margin: 0 0 12px;
  padding: 9px 12px;
  border-left: 3px solid #8b2424;
  background: rgba(139, 36, 36, 0.05);
  color: var(--ink);
  font-size: 0.85rem;
}
.room-advance-tag { color: #1f7a63; font-weight: 600; }
.room-arrears-tag { color: #8b2424; font-weight: 600; }
.room-continuing-tag { font-weight: 600; color: var(--ink); }

/* Searchable selects.
   A native <select> offers no way to find an item by typing. For lists of
   options that outgrow the screen (180+ items in the Central Store transfer
   modal), an attendant must scroll and read. This upgrades those to a combobox:
   type to filter, pick from the filtered list.

   The native select stays in the DOM, hidden but functional - every existing
   piece of JS that reads .value or listens for change keeps working. The
   wrapper is styled to match a normal input so the till layout does not change. */
.searchable-select { position: relative; display: block; }
.searchable-select select.is-searchable-select {
  position: absolute !important; width: 100% !important; height: 100% !important;
  opacity: 0; z-index: -1; pointer-events: none;
}
.searchable-select-input {
  width: 100%; min-height: 40px; padding: 9px 34px 9px 11px;
  border: 1px solid #b9c2d6; border-radius: 9px; background: #fff; color: var(--ink, #2c261e);
  font-size: 0.92rem; line-height: 1.35; cursor: text;
}
.searchable-select-input:focus { outline: none; border-color: var(--primary, #1b2a5b); box-shadow: 0 0 0 2px rgba(27,42,91,.15); }
.searchable-select-caret {
  position: absolute; right: 10px; top: 50%; transform: translateY(-50%);
  color: var(--stone, #667085); font-size: 0.75rem; pointer-events: none;
}
.searchable-select-list {
  position: absolute; z-index: 1000; left: 0; right: 0; max-height: 260px; overflow-y: auto;
  background: #fff; border: 1px solid var(--parchment-dim, #d8cbb4); border-radius: 8px;
  box-shadow: 0 8px 24px rgba(27,42,91,.16); margin-top: 2px;
}
.searchable-select-item {
  padding: 8px 12px; cursor: pointer; font-size: 0.9rem; color: var(--ink, #2c261e);
}
.searchable-select-item.is-selected { background: var(--primary, #1b2a5b); color: #fff; }
.searchable-select-item.is-highlighted { background: #eef2fb; }
.searchable-select-item.is-disabled { color: var(--stone, #667085); opacity: .6; cursor: default; }
.searchable-select-empty { padding: 10px 12px; font-size: 0.85rem; color: var(--stone, #667085); }
@media (max-width: 560px) {
  .searchable-select-list { position: fixed; left: 12px; right: 12px; }
}
/* Short-time stays and timestamp readability on compact front-desk screens. */
.badge-short-time {
  background: #fff0d8;
  color: #70440c;
  border: 1px solid #e6c48d;
  font-weight: 700;
}
.short-time-clock {
  font-variant-numeric: tabular-nums;
  font-weight: 650;
  color: var(--ink, #1d2b5b);
  overflow-wrap: anywhere;
}
.short-time-clock.is-warning {
  color: #b4530a;
  font-weight: 800;
}
/* Room cards are saturated blocks with white copy, so the dark amber above
   disappears on them. The balance-due card is the pale exception and keeps it. */
.room-card[data-status] .short-time-clock.is-warning {
  color: #ffd08a;
}
.room-card[data-status="occupied"][data-balance="due"] .short-time-clock.is-warning {
  color: #8a4b08;
}
.reception-stay-times,
.reservation-stay-datetime {
  display: grid;
  gap: 3px;
  font-variant-numeric: tabular-nums;
  line-height: 1.45;
}
.reception-stay-times b,
.reservation-stay-datetime b {
  display: inline-block;
  min-width: 2.2em;
  color: var(--ink, #1d2b5b);
}
.reservation-stay-meta {
  display: inline-block;
  margin: 3px 0;
  color: var(--stone, #687185);
}
.short-time-modal {
  width: min(520px, calc(100vw - 24px));
  max-height: calc(100dvh - 24px);
  overflow-y: auto;
}
.short-time-form { display: grid; gap: 14px; }
.short-time-price {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 12px 14px;
  border-radius: var(--radius-sm, 8px);
  background: var(--parchment, #f6f3eb);
}
.short-time-price strong { font-size: 1.25rem; color: var(--ink, #1d2b5b); }
.short-time-price span { color: var(--stone, #687185); font-size: .9rem; }
.short-time-error { color: var(--danger, #9d3427); }

/* Manual Entry stay-type toggle + short-time explainer panel. */
.stay-type-toggle {
  display: inline-flex;
  align-items: stretch;
  gap: 4px;
  padding: 4px;
  border: 1px solid var(--line, #ddd6c8);
  border-radius: 10px;
  background: var(--parchment, #f6f3eb);
}
.stay-type-option {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 8px 18px;
  border-radius: 7px;
  cursor: pointer;
  font-weight: 600;
  font-size: .92rem;
  line-height: 1.2;
  color: var(--stone, #687185);
  white-space: nowrap;
  user-select: none;
  transition: background .15s ease, color .15s ease, box-shadow .15s ease;
}
/* The radio stays in the DOM for keyboard + form semantics but is never drawn;
   the label paints the state instead, so the control reads as one segmented
   unit rather than two boxes with stray circles. */
.stay-type-option input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  opacity: 0;
  cursor: inherit;
}
.stay-type-option > span { position: relative; }
.stay-type-option:has(input:checked) {
  background: var(--ink, #1d2b5b);
  color: #fff;
  box-shadow: 0 1px 3px rgba(20, 26, 60, .28);
}
.stay-type-option:has(input:focus-visible) {
  outline: 2px solid var(--brass-dark, #7a5b16);
  outline-offset: 2px;
}
.stay-type-option.is-disabled {
  opacity: .45;
  cursor: not-allowed;
}
.short-time-panel {
  display: grid;
  gap: 8px;
  padding: 14px 16px;
  border: 1px solid #e6c48d;
  border-left: 4px solid #e6c48d;
  border-radius: var(--radius-sm, 8px);
  background: #fff8e8;
}
.short-time-panel-head {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 1.02rem;
  color: var(--ink, #1d2b5b);
}
.short-time-expiry {
  font-variant-numeric: tabular-nums;
  font-weight: 650;
  color: var(--ink, #1d2b5b);
}
.short-time-expiry.is-invalid { color: var(--danger, #9d3427); }
.reception-toolbar .reception-actions { flex-wrap: wrap; gap: 8px; }
@media (max-width: 640px) {
  .reception-stay-times,
  .reservation-stay-datetime { min-width: 0; font-size: .92rem; }
  .short-time-clock { font-size: .84rem; }
  .short-time-modal .modal-actions { flex-wrap: wrap; }
  .short-time-modal .modal-actions .btn { flex: 1 1 130px; }
  .reception-toolbar .reception-actions { width: 100%; }
  .reception-toolbar .reception-actions .btn { flex: 1 1 145px; }
}
