/* ============================================================
   ARMAAN PRESS ERP — Shared Stylesheet
   ============================================================ */

/* Kill the browser's own default mobile tap-highlight (the grey/blue
   rectangle that flashes over whatever you tap on Android Chrome/WebView).
   The app already has its own deliberate :active press-feedback everywhere
   (scale-down, background tint, etc.) — this was just an extra unstyled
   browser box on top of that, with nothing to do with any real feature. */
html {
  -webkit-tap-highlight-color: transparent;
}
a, button, input, select, textarea, label, [role="button"], .btn,
.sidebar-item, .mob-action-icon, .mob-order-card, .mtb-item, .tab-btn {
  -webkit-tap-highlight-color: transparent;
}

:root {
  --sidebar-bg: #111013;
  --sidebar-text: #898892;
  --sidebar-active-text: #ff2d62;
  --sidebar-active-bg: #22151e;

  --bg-main: #fdfdfd;
  --border-main: #ebedf2;

  --brand-pink: #d81142;
  --brand-pink-hover: #b00e35;

  --text-primary: #1a1a1f;
  --text-secondary: #45454e;
  --text-tertiary: #63636c;
  --white: #ffffff;
  --shadow-sm: 0 1px 2px rgba(17,16,19,0.04);
  --shadow-md: 0 4px 16px rgba(17,16,19,0.08);
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 16px;

  /* Height of the fixed top masthead (logo bar) — sidebar top-offset,
     body top-padding and the sticky .topbar all read from this single
     value so the two never drift out of sync. Shrunk on mobile below.
     --masthead-top-space is the blank breathing room reserved above the
     logo itself (black background, same bar) — like the gap above the
     header in native apps. It's carved out of --masthead-h via padding,
     so the logo's own size/position stays exactly as before; only the
     space above it grows. */
  --masthead-h: 90px;
  --masthead-top-space: 18px;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  /* v230: 'Inter Fallback' — Inter ke naap se milta-julta fallback,
     taaki Inter async load hote waqt table columns ki chaudai na
     badle (poori wajah includes/header.php ke @font-face comment me
     likhi hai). Ye stack wahi hai jo header.php ki inline critical
     CSS me hai — dono ka same hona zaroori hai, warna ye wali baad me
     load hokar us fix ko overwrite kar deti. */
  font-family: 'Inter', 'Inter Fallback', -apple-system, BlinkMacSystemFont, sans-serif;
  background: var(--bg-main);
  color: var(--text-primary);
  font-size: 14px;
}
/* Only pages that actually include the fixed masthead (the staff app and
   customer portal — see header.php / portal_header.php, both of which add
   this class to <body>) get pushed down to make room for it. Standalone
   pages sharing this stylesheet (login, invoices, label/print views) don't
   render .app-masthead and must not get this extra top padding, or they'd
   show a blank gap. */
body.has-masthead {
  padding-top: calc(var(--masthead-h) + env(safe-area-inset-top, 0px));
}

/* ---- Fixed top masthead: shows the workspace's horizontal logo, pinned
   above everything else, on every screen size — it never scrolls away. ---- */
.app-masthead {
  position: fixed;
  top: 0; left: 0; right: 0;
  height: calc(var(--masthead-h) + env(safe-area-inset-top, 0px));
  padding-top: calc(var(--masthead-top-space) + env(safe-area-inset-top, 0px));
  box-sizing: border-box;
  background: var(--sidebar-bg);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  box-shadow: 0 2px 10px rgba(0,0,0,0.18);
}
.app-masthead-desktop { display: flex; align-items: center; justify-content: center; width: 100%; }
.app-masthead-logo { display: flex; align-items: center; justify-content: center; max-width: 100%; }
.app-masthead-logo img { display: block; max-height: 40px; width: auto; }
.app-masthead-textonly {
  color: #fff; font-weight: 800; font-size: 17px; letter-spacing: 0.5px;
  text-align: center; line-height: 1.2;
}
.app-masthead-textonly small {
  display: block; font-weight: 500; font-size: 10.5px; letter-spacing: 1.5px;
  color: var(--sidebar-text); text-transform: uppercase; margin-top: 2px;
}

/* ---- Masthead hamburger (left) + profile avatar (right) — fixed on
   every page, next to the logo, matching the app's native-style header. ---- */
.masthead-menu-btn {
  position: absolute;
  left: 14px; top: 50%;
  transform: translateY(calc(-50% + (var(--masthead-top-space, 14px) / 2)));
  width: 38px; height: 38px;
  border: none; border-radius: 10px;
  background: rgba(255,255,255,0.08);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 4px; cursor: pointer; z-index: 2; flex-shrink: 0;
}
.masthead-menu-btn span { display: block; width: 18px; height: 2px; border-radius: 2px; background: #fff; }
.masthead-menu-btn:hover { background: rgba(255,255,255,0.14); }
/* Open-tickets badge — lives on the hamburger button itself, which is
   fixed in the masthead and always on screen (unlike the matching badge
   inside the sidebar drawer, which disappears whenever the menu/drawer
   is closed or hidden). z-index above the masthead (1000) so it's never
   covered, and a white ring so it reads clearly against any button state. */
.masthead-menu-ticket-badge {
  position: absolute; top: -5px; right: -5px; z-index: 1001;
  min-width: 18px; height: 18px; padding: 0 4px; border-radius: 9px;
  background: var(--brand-pink); color: #fff; font-size: 10.5px; font-weight: 800;
  display: flex; align-items: center; justify-content: center;
  border: 2px solid var(--sidebar-bg, #1a1a1f);
  box-shadow: 0 2px 6px rgba(0,0,0,0.3);
  pointer-events: none;
  animation: mastheadTicketBadgePulse 2.2s ease-in-out infinite;
}
@keyframes mastheadTicketBadgePulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.12); }
}
@media (prefers-reduced-motion: reduce) {
  .masthead-menu-ticket-badge { animation: none; }
}
.masthead-avatar {
  position: absolute;
  right: 14px; top: 50%;
  transform: translateY(calc(-50% + (var(--masthead-top-space, 14px) / 2)));
  display: inline-flex; z-index: 2; flex-shrink: 0;
  text-decoration: none;
}
.masthead-avatar img, .masthead-avatar span:first-child {
  border: 2px solid rgba(255,255,255,0.35);
  box-shadow: 0 2px 8px rgba(0,0,0,0.25);
}
.masthead-avatar-dot {
  position: absolute; right: 0; bottom: 0;
  width: 11px; height: 11px; border-radius: 50%;
  background: #0f9d58; border: 2px solid var(--sidebar-bg, #1a1a1f);
}
@media (max-width: 480px) {
  .masthead-menu-btn { left: 10px; width: 34px; height: 34px; }
  .masthead-avatar { right: 10px; }
}

/* ---- Mobile masthead: same full logo as desktop, centered — just at a
   size that fits the shorter mobile masthead bar. Hidden on desktop,
   which keeps the full banner above completely unchanged. ---- */
.app-masthead-mobile {
  display: none;
  align-items: center;
  justify-content: center;
  width: 100%;
  padding: 0 16px;
}
@media (max-width: 900px) {
  .app-masthead-desktop { display: none; }
  .app-masthead-mobile { display: flex; }
}

/* ---- Recycle bin FAB: on mobile, only show it on the Dashboard so it's
   not cluttering every page — desktop keeps showing it everywhere,
   exactly as before. ---- */
@media (max-width: 900px) {
  .recycle-bin-fab:not(.recycle-bin-fab-dashboard) { display: none !important; }
  .shortcuts-fab-trigger:not(.shortcuts-fab-dashboard) { display: none !important; }
}

a { text-decoration: none; color: inherit; }
ul { list-style: none; margin: 0; padding: 0; }

/* ============================================================
   DARK MODE
   Toggled by adding .dark-mode to <body> (staff: localStorage only;
   customer portal: DB-backed via customers.portal_dark_mode, mirrored
   to localStorage too). Redefining the core variables here is what makes
   most of the app adapt automatically, since components already read
   var(--white)/var(--text-primary)/etc. rather than hardcoded hex.
   Everything below the variable block is a targeted fix for the specific
   spots that DON'T use those variables (a hardcoded #fff background, a
   hardcoded dark-gray text color meant for a light page, etc) — this is
   exactly the "white box, unreadable gray text" bug this section exists
   to close out, one real occurrence at a time rather than a blanket
   filter/invert hack that would also wreck photos and logos.
   ============================================================ */
body.dark-mode {
  --bg-main: #121214;
  --border-main: #2c2c34;
  --text-primary: #f0f0f3;
  --text-secondary: #c2c2cb;
  --text-tertiary: #93939d;
  --white: #1c1c22;
  --shadow-sm: 0 1px 2px rgba(0,0,0,0.35);
  --shadow-md: 0 4px 18px rgba(0,0,0,0.5);
}

/* ---- Components with a hardcoded (non-variable) color of their own ---- */
body.dark-mode .btn-secondary { background: #26262e; color: var(--text-primary); }
body.dark-mode .btn-secondary:hover:not(:disabled) { background: #303039; }
body.dark-mode .modal-box { background: var(--white); }
body.dark-mode .modal-overlay { background: rgba(0,0,0,0.72); }
body.dark-mode .alert-success { background: #16301f; color: #4ade80; }
body.dark-mode .alert-danger { background: #3a1c26; color: #ff6b8f; }
body.dark-mode .topbar { background: var(--white); border-color: var(--border-main); }
body.dark-mode .data-table th { background: #1a1a20; color: var(--text-tertiary); }
body.dark-mode .data-table td { border-color: var(--border-main); }
body.dark-mode .form-input, body.dark-mode .form-select, body.dark-mode textarea.form-input {
  background: #1a1a20; border-color: #34343d; color: var(--text-primary);
}
body.dark-mode .form-label { color: var(--text-secondary); }
body.dark-mode ::placeholder { color: #55555f; opacity: 1; }
body.dark-mode .empty-state { color: var(--text-secondary); }
body.dark-mode .empty-state h3 { color: var(--text-primary); }

/* ---- Near-white panel backgrounds that slipped past the retrofit ----
   The bigger "hardcoded inline light box" retrofit lives further down
   (search "Retrofit the most common hardcoded inline") and already
   catches #fafafc/#f9f9fb/#f3f3f6/#e5e5ea etc. This one shade wasn't in
   that list because it's never written as a plain hex — it's always the
   fallback of an undefined CSS variable, background:var(--bg-tertiary,
   #f7f3fb), used by the voice-note and quick-add-customer panels.
   --bg-tertiary itself is never actually defined anywhere (light or
   dark mode), so it always fell through to this near-white fallback —
   same "white box, invisible gray text" bug as the others, just missed
   until now since the attribute selector needs the exact literal text. */
body.dark-mode [style*="var(--bg-tertiary,#f7f3fb)"] {
  background: #1a1a20 !important;
}

/* ---- Deliberately-white surfaces, dark mode ----
   A handful of spots keep a plain white card on purpose (voice-note
   transcript box, quick preset chips) rather than switching to a dark
   panel like the ones above — but the text on them still used the
   theme's grey/light variable, which in dark mode goes light and turns
   near-invisible on that white card. Background stays white as
   intended; only the text is pinned to a fixed dark color here. */
body.dark-mode .offer-mode-tab:not(.active),
body.dark-mode .offer-preset-btn,
body.dark-mode #voiceStatus,
body.dark-mode #voiceTimelineTranscript {
  color: #1a1a1f !important;
}
body.dark-mode .mobile-tab-bar { background: rgba(28,28,34,0.98); border-color: var(--border-main); }
body.dark-mode .staff-login-toggle { background: linear-gradient(135deg, rgba(255,255,255,0.06), rgba(255,255,255,0.02)); }

/* ---- Other CSS-class-level (not inline-style) hardcoded light colors ---- */
body.dark-mode .data-table tr:hover td { background: #1e1e24; }
body.dark-mode tr.row-link:hover { background: #26181d; }
body.dark-mode .kanban-col { background: #1a1a20; }
body.dark-mode .mob-action-icon { background: #26262e; }
body.dark-mode .mob-action-icon:active { background: #303039; }
body.dark-mode .mob-order-card:active { background: #1e1a1c; }
body.dark-mode .mob-payment-icon { background: #1a2e22; }
body.dark-mode .shortcuts-kbd { background: #26262e; border-color: #3a3a44; color: var(--text-primary); }
body.dark-mode .overdue-badge,
body.dark-mode .logo-shape-option.selected,
body.dark-mode .label-order-row.lbl-selected,
body.dark-mode .modal-close:hover,
body.dark-mode .login-error { background: #3a1c26; }
body.dark-mode .prod-countdown.tone-soon { background: #332d1c; color: #f0b849; }
body.dark-mode .prod-countdown.tone-late { background: #3a1c26; color: #ff6b8f; }

/* ---- Scrollbar polish ---- */
body.dark-mode ::-webkit-scrollbar { width: 10px; height: 10px; }
body.dark-mode ::-webkit-scrollbar-track { background: #1a1a20; }
body.dark-mode ::-webkit-scrollbar-thumb { background: #3a3a44; border-radius: 6px; }
body.dark-mode ::-webkit-scrollbar-thumb:hover { background: #4a4a55; }

/* ---- Theme toggle button ---- */
.theme-toggle-btn {
  width: 38px; height: 38px; border-radius: 10px;
  background: #1a1a1f; color: #fff; border: none;
  display: flex; align-items: center; justify-content: center;
  font-size: 15px; cursor: pointer; flex-shrink: 0;
  transition: transform 0.15s ease;
}
.theme-toggle-btn:active { transform: scale(0.9); }
.theme-toggle-icon-light { display: none; }
body.dark-mode .theme-toggle-icon-dark { display: none; }
body.dark-mode .theme-toggle-icon-light { display: inline; }

/* ---- Retrofit the most common hardcoded inline "light box" background
   colors used throughout the app (badges, subtle panels, status
   highlights) to a matching dark equivalent. Matched by hex value
   regardless of the exact inline spacing, so every occurrence of a shade
   gets one consistent replacement. This — not the variables above — is
   what actually fixes light, unreadable panels in dark mode. ---- */
body.dark-mode [style*="#f3f3f6"],
body.dark-mode [style*="#f0f0f3"] { background-color: #26262e !important; }
body.dark-mode [style*="#fafafc"],
body.dark-mode [style*="#f4f5f9"],
body.dark-mode [style*="#f9f9fb"],
body.dark-mode [style*="#f7f7fa"],
body.dark-mode [style*="#f4f4f6"] { background-color: #1e1e24 !important; }
body.dark-mode [style*="#e5e5ea"] { background-color: #2a2a32 !important; }
body.dark-mode [style*="#fdeaf0"],
body.dark-mode [style*="#fef5f7"] { background-color: #3a1c26 !important; }
body.dark-mode [style*="#f3effe"] { background-color: #2a2438 !important; }
body.dark-mode [style*="#eef4ff"] { background-color: #1c2636 !important; }
body.dark-mode [style*="#e7f8ee"],
body.dark-mode [style*="#e8f5e9"],
body.dark-mode [style*="#f0fdf4"] { background-color: #1a2e22 !important; }
body.dark-mode [style*="#fffdf6"],
body.dark-mode [style*="#fffaf0"],
body.dark-mode [style*="#fff8ed"],
body.dark-mode [style*="#fff7e6"] { background-color: #332d1c !important; }

/* ---- Same retrofit for hardcoded dark-gray text colors that were meant
   for a light background — on the new dark surfaces they'd otherwise be
   near-invisible (dark text on dark background). ---- */
body.dark-mode [style*="color:#3a3a42"],
body.dark-mode [style*="color: #3a3a42"],
body.dark-mode [style*="color:#2c2c34"],
body.dark-mode [style*="color: #2c2c34"] { color: #c8c8d0 !important; }
body.dark-mode [style*="color:#1a1a1f"],
body.dark-mode [style*="color: #1a1a1f"] { color: #f0f0f3 !important; }
body.dark-mode [style*="color:#6b6b76"],
body.dark-mode [style*="color: #6b6b76"],
body.dark-mode [style*="color:#8a8a94"],
body.dark-mode [style*="color: #8a8a94"],
body.dark-mode [style*="color:#45454e"],
body.dark-mode [style*="color: #45454e"] { color: #c2c2cb !important; }

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

.sidebar {
  width: 240px;
  min-width: 240px;
  max-width: 240px;
  box-sizing: border-box;
  background: var(--sidebar-bg);
  color: var(--sidebar-text);
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  padding: 20px 0;
  scrollbar-gutter: stable;
  overflow-x: hidden;
  /* Pinned to the viewport with its own fixed height, so a long page below
     never drags the sidebar (and its scrollbar) along with it — the sidebar
     stays put and only its own nav list scrolls internally. Previously
     .app-shell used min-height (not height), so the sidebar just stretched
     to match however tall the whole page was and the "scrollbar" never had
     a real boundary to scroll within. */
  position: sticky;
  top: calc(var(--masthead-h) + env(safe-area-inset-top, 0px));
  height: calc(100vh - var(--masthead-h) - env(safe-area-inset-top, 0px));
}
/* Transition only applies on desktop (see the hover rules below) — mobile's
   drawer open/close uses its own separate .sidebar.animate mechanism. */

.sidebar-brand {
  padding: 0 20px 20px;
  font-weight: 800;
  font-size: 17px;
  color: #fff;
  flex-shrink: 0;
  min-width: 0;
  overflow: hidden;
}
/* Full logo shows normally; compact icon only appears once the sidebar is
   resting in its icon-only rail width (a wide horizontal/vertical logo
   wouldn't fit in that 64px rail, so we swap to the dedicated square icon
   instead of trying to squeeze/clip the full logo). */
.brand-logo-icon { display: none; }

/* ---- Desktop (901px+), applies to any sidebar marked .sidebar-hover-rail
   (both the staff app and the customer portal use it): rests as an
   icon-only rail and expands on hover — no click, no remembered on/off
   state. Hovering ANYWHERE on the sidebar (background or an icon) reveals
   it; moving the mouse away collapses it back. Mobile is untouched — it
   keeps its own tap-to-open drawer exactly as before. ---- */
@media (min-width: 901px) {
  .sidebar-hover-rail {
    width: 64px;
    min-width: 64px;
    max-width: 64px;
    transition: width 0.18s ease, min-width 0.18s ease, max-width 0.18s ease;
  }
  .sidebar-hover-rail:hover {
    width: 240px;
    min-width: 240px;
    max-width: 240px;
    z-index: 950;
    box-shadow: 4px 0 24px rgba(0,0,0,0.14);
  }
  .sidebar-hover-rail:not(:hover) .sidebar-brand > div,
  .sidebar-hover-rail:not(:hover) .sidebar-item-label,
  .sidebar-hover-rail:not(:hover) .sidebar-item-badge,
  .sidebar-hover-rail:not(:hover) .sidebar-section-toggle,
  .sidebar-hover-rail:not(:hover) .sidebar-user,
  .sidebar-hover-rail:not(:hover) .sidebar-lang-switch,
  .sidebar-hover-rail:not(:hover) .sidebar-logout {
    display: none;
  }
  /* Icon-only resting mode ignores the accordion entirely — every item's
     icon must stay visible regardless of whether that category was
     expanded or collapsed before. This overrides the JS-set inline style,
     which is why it needs !important here specifically. */
  .sidebar-hover-rail:not(:hover) .sidebar-section-list {
    display: block !important;
  }
  .sidebar-hover-rail:not(:hover) .sidebar-brand { padding: 0 10px 20px; justify-content: center; }
  .sidebar-hover-rail:not(:hover) .sidebar-item { padding: 12px 0; justify-content: center; }
  .sidebar-hover-rail:not(:hover) .sidebar-item > span:first-child { width: 100%; text-align: center; }
  .sidebar-hover-rail:not(:hover) .sidebar-footer { padding: 12px 8px 0; text-align: center; }
  .sidebar-hover-rail:not(:hover) .sidebar-footer::after {
    content: '👤';
    display: block;
    font-size: 20px;
    color: var(--sidebar-text);
    padding: 6px 0;
  }
  .sidebar-hover-rail:not(:hover) .sidebar-scroll-btn { font-size: 9px; }
  /* Strict two-state toggle: when resting (not hovered) show ONLY the
     compact icon; the moment it's hovered/expanded, fall back to the base
     rule above which hides the icon again, so only the full logo shows. */
  .sidebar-hover-rail:not(:hover) .brand-logo-full { display: none !important; }
  .sidebar-hover-rail:not(:hover) .brand-logo-icon { display: inline-flex !important; }
  .sidebar-hover-rail:not(:hover) .sidebar-broadcast-link { justify-content: center; padding: 9px 0; }
}
/* ---- Floating keyboard-shortcuts (⌨️) button: on desktop, follow the
   menu bar's own hidden/shown state — hidden while the sidebar rests
   collapsed (icon-only "hidden" rail), shown once it's expanded/hovered.
   Body class is set by the small JS listener in includes/header.php,
   since this button sits outside the <aside> in the DOM and plain CSS
   :hover on the sidebar can't reach it directly. Mobile is untouched. ---- */
@media (min-width: 901px) {
  .shortcuts-fab-trigger { display: none; }
  body.sidebar-rail-expanded .shortcuts-fab-trigger { display: flex; }
}
.sidebar-brand > div {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  border-bottom: 1px solid #232227;
  padding-bottom: 12px;
}
.sidebar-brand span { display:block; font-size: 11px; font-weight: 500; color: var(--sidebar-text); margin-top:2px; }
/* ---- Explicit up/down "slide" buttons for the sidebar menu list ---- */
.sidebar-scroll-btn {
  display: none; /* shown via JS only when the nav actually overflows */
  width: 100%;
  background: transparent;
  border: none;
  color: rgba(255,255,255,0.45);
  font-size: 10px;
  padding: 4px 0 6px;
  cursor: pointer;
  flex-shrink: 0;
  transition: color 0.15s ease, background 0.15s ease;
}
.sidebar-scroll-btn:hover { color: #fff; background: rgba(255,255,255,0.06); }
.sidebar-scroll-btn.visible { display: block; }

.sidebar-nav {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-gutter: stable;
  min-width: 0;
  /* Firefox */
  scrollbar-width: thin;
  scrollbar-color: rgba(255,255,255,0.25) transparent;
}
/* Chrome/Edge/Safari — default sidebar scrollbar was nearly invisible
   against the dark background, making it hard to notice you could scroll
   for more menu items. This makes it a clearly visible "slide bar". */
.sidebar-nav::-webkit-scrollbar { width: 7px; }
.sidebar-nav::-webkit-scrollbar-track { background: transparent; }
.sidebar-nav::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.22); border-radius: 10px; }
.sidebar-nav::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.4); }
.sidebar-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 20px;
  font-size: 13.5px;
  font-weight: 500;
  color: var(--sidebar-text);
  cursor: pointer;
  border-left: 3px solid transparent;
  text-decoration: none;
  min-width: 0;
  /* Lock in a fixed weight so :hover/.active don't cause any width
     recomputation on the label text itself. */
  -webkit-font-smoothing: antialiased;
  transition: background-color 0.16s ease, color 0.16s ease, border-left-color 0.16s ease, padding-left 0.16s ease;
}
.sidebar-item:hover { padding-left: 23px; }
.sidebar-item-label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sidebar-item:hover,
.sidebar-item:focus,
.sidebar-item:active { color: #fff; outline: none; }
.sidebar-item.active {
  background: var(--sidebar-active-bg);
  color: var(--sidebar-active-text);
  border-left-color: var(--sidebar-active-text);
}
.sidebar-item svg { width: 18px; height: 18px; flex-shrink: 0; }
.sidebar-section-label {
  margin: 0;
  padding: 0;
  font-size: 10.5px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.9px;
  color: #9a99a3;
  transition: color 0.18s ease;
}
/* ---- Sidebar category accordion — premium pill-button style ---- */
.sidebar-section-toggle {
  display: flex; align-items: center; justify-content: space-between;
  width: calc(100% - 24px);
  margin: 14px 12px 6px;
  padding: 9px 11px 9px 12px;
  background: linear-gradient(180deg, rgba(255,255,255,0.05), rgba(255,255,255,0.014));
  border: 1px solid rgba(255,255,255,0.075);
  border-radius: 10px;
  cursor: pointer;
  box-shadow: 0 1px 2px rgba(0,0,0,0.18);
  transition: background 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease, transform 0.12s ease;
}
.sidebar-nav .sidebar-section-toggle:first-child { margin-top: 6px; }
.sidebar-section-toggle:hover {
  background: linear-gradient(180deg, rgba(255,255,255,0.078), rgba(255,255,255,0.024));
  border-color: rgba(255,255,255,0.13);
}
.sidebar-section-toggle:active { transform: scale(0.985); }
.sidebar-section-toggle:hover .sidebar-section-label { color: #e2e1e7; }
.sidebar-section-toggle.expanded {
  background: linear-gradient(180deg, rgba(255,45,98,0.16), rgba(255,45,98,0.045));
  border-color: rgba(255,45,98,0.32);
  box-shadow: 0 1px 2px rgba(0,0,0,0.18), 0 0 0 1px rgba(255,45,98,0.06) inset;
}
.sidebar-section-toggle.expanded .sidebar-section-label { color: #ff87a5; }
.sidebar-section-chevron {
  font-size: 9px;
  width: 18px; height: 18px;
  margin-right: 0;
  flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  color: #75747d;
  background: rgba(255,255,255,0.055);
  border-radius: 50%;
  transition: transform 0.2s ease, background 0.2s ease, color 0.2s ease;
  transform: rotate(-90deg); /* collapsed = pointing right */
}
.sidebar-section-toggle.expanded .sidebar-section-chevron {
  transform: rotate(0deg); /* expanded = pointing down */
  background: rgba(255,45,98,0.22);
  color: #ff87a5;
}
.sidebar-section-list { list-style: none; margin: 0; padding: 0; }
.sidebar-footer { padding: 12px 20px 0; border-top: 1px solid #232227; margin-top: 10px; flex-shrink: 0; }
.sidebar-user { font-size: 12.5px; color: #fff; margin-bottom: 8px; }
.sidebar-user small { display:block; color: var(--sidebar-text); font-weight:400; }
.sidebar-logout {
  display: block; text-align:center; padding: 8px; border-radius: var(--radius-sm);
  background: #22151e; color: var(--sidebar-active-text); font-weight:600; font-size:13px;
}

/* ---- Main area ---- */
.main-viewport { flex: 1; min-width: 0; display: flex; flex-direction: column; overflow-x: hidden; }
.topbar {
  padding: 18px 28px;
  border-bottom: 1px solid var(--border-main);
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  background: var(--white);
  /* Fixed (not sticky) — .main-viewport has overflow-x:hidden, which per
     spec forces its overflow-y to compute to 'auto', silently turning it
     into its OWN scroll container. That makes position:sticky here stick
     relative to .main-viewport instead of the actual (window) scroller,
     which is what caused the topbar to detach from the masthead with a
     gap above it. Fixed positioning sidesteps that entirely — it's always
     pinned to the viewport, full stop. See the header-offset-sync script
     in footer.php for how .page-content gets pushed down to match. */
  position: fixed;
  top: calc(var(--masthead-h) + env(safe-area-inset-top, 0px));
  left: 0;
  right: 0;
  z-index: 900;
}
@media (min-width: 901px) {
  /* .topbar position:fixed hai, isliye wo flex flow ka hissa NAHI hai.
     Sidebar hover par 64px se 240px expand hota hai aur .main-viewport
     (yaani page ka content) apne aap right shift ho jaata hai — par
     fixed topbar wahin ka wahin reh jaata tha, aur heading/subtitle
     expanded sidebar ke neeche chhup jaate the.

     Ab topbar bhi sidebar ke saath shift hota hai, ussi 0.18s timing
     par, taaki heading aur neeche ka content ek saath sarkein. */
  .topbar {
    left: 64px;                        /* sidebar ki resting icon-rail width */
    transition: left 0.18s ease;
  }
  .sidebar-hover-rail:hover ~ .main-viewport .topbar { left: 240px; }
}
.topbar h1 { font-size: 19px; margin: 0; font-weight: 700; }
.topbar p { font-size: 12.5px; color: var(--text-secondary); margin: 2px 0 0; }
.page-content { padding: 24px 28px; flex: 1; }

/* ================================================================
   PREMIUM BUTTON MOTION SYSTEM
   ----------------------------------------------------------------
   Applied to the shared .btn base class (and its variants) rather
   than to individual buttons on individual pages — every button in
   the app, on every current page AND any future page, uses these
   same classes, so this is the one place that guarantees the effect
   never gets lost when a page gets edited later.
   ================================================================ */
.btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 9px 16px; border-radius: var(--radius-sm); font-size: 13.5px;
  font-weight: 600; border: none; cursor: pointer;
  position: relative; overflow: hidden; isolation: isolate;
  transition: transform 0.16s cubic-bezier(0.34, 1.56, 0.64, 1),
              box-shadow 0.18s ease, background-color 0.18s ease,
              filter 0.18s ease, opacity 0.18s ease;
  will-change: transform;
}
.btn:hover:not(:disabled) { transform: translateY(-1.5px); box-shadow: 0 6px 16px rgba(0,0,0,0.12); filter: brightness(1.03); }
.btn:active:not(:disabled) { transform: translateY(0) scale(0.97); box-shadow: 0 1px 3px rgba(0,0,0,0.1); filter: brightness(0.97); transition-duration: 0.08s; }
.btn:disabled { cursor: not-allowed; opacity: 0.55; transform: none !important; box-shadow: none !important; }
.btn:focus-visible { outline: 2px solid var(--brand-pink); outline-offset: 2px; }
/* Subtle one-pass shine sweep on hover — quick highlight, not a looping
   animation, so it reads as "premium" rather than distracting on a button
   you might hover repeatedly while working. */
.btn::before {
  content: ''; position: absolute; top: 0; left: -75%; width: 50%; height: 100%;
  background: linear-gradient(115deg, transparent 0%, rgba(255,255,255,0.35) 50%, transparent 100%);
  transform: skewX(-20deg);
  transition: left 0.55s cubic-bezier(0.22, 1, 0.36, 1);
  pointer-events: none;
}
.btn:hover:not(:disabled)::before { left: 130%; }
@media (prefers-reduced-motion: reduce) {
  .btn, .btn:hover, .btn:active { transition: none !important; transform: none !important; }
  .btn::before { display: none; }
}

.btn-primary { background: var(--brand-pink); color: #fff; box-shadow: 0 2px 6px rgba(216,17,66,0.18); }
.btn-primary:hover:not(:disabled) { background: var(--brand-pink-hover); box-shadow: 0 8px 20px rgba(216,17,66,0.32); }
.btn-secondary { background: #f3f3f6; color: var(--text-primary); }
.btn-secondary:hover:not(:disabled) { background: #ebebef; }

/* ---- Cards / KPIs ---- */
.kpi-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px,1fr)); gap: 16px; margin-bottom: 24px; }
.kpi-card { background: var(--white); border: 1px solid var(--border-main); border-radius: var(--radius-lg); padding: 18px 20px; box-shadow: var(--shadow-sm); }
.kpi-card .label { font-size: 12.5px; color: var(--text-secondary); font-weight:600; }
.kpi-card .value { font-size: 24px; font-weight: 800; margin-top: 6px; }
.kpi-card .sub { font-size: 12px; color: var(--text-tertiary); margin-top: 4px; }
/* Clickable KPI cards (dashboard) — same look as a plain card, but with a
   hover lift + pointer cursor so it's obvious the whole card is a link. */
a.kpi-card-link { display: block; text-decoration: none; color: inherit; transition: transform 0.12s ease, box-shadow 0.12s ease; cursor: pointer; }
a.kpi-card-link:hover { transform: translateY(-2px); box-shadow: 0 6px 18px rgba(0,0,0,0.08); border-color: var(--brand-pink); }

.card { background: var(--white); border: 1px solid var(--border-main); border-radius: var(--radius-lg); box-shadow: var(--shadow-sm); }
.card-header { padding: 16px 20px; border-bottom: 1px solid var(--border-main); font-weight: 700; font-size: 14.5px; }
.card-body { padding: 16px 20px; }

/* ---- Tables ---- */
.data-table { width: 100%; border-collapse: collapse; }
.data-table th { text-align: left; font-size: 12px; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 0.03em; padding: 10px 12px; background: #fafafc; }
.data-table td { padding: 12px; border-top: 1px solid var(--border-main); font-size: 13.5px; }
.data-table tr:hover td { background: #fafafc; }

.badge { display: inline-block; padding: 3px 10px; border-radius: 20px; font-size: 11.5px; font-weight: 700; }

/* ---- Membership glass badge (customer profile page) — premium chip
   look matching the printable card's tier gradients, with a soft
   diagonal light sweep that loops every few seconds. ---- */
.membership-glass-badge {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  flex-wrap: wrap;
  margin-top: 10px;
  padding: 8px 14px;
  border-radius: 14px;
  color: #fff;
  box-shadow: 0 8px 22px rgba(17,16,19,0.22), inset 0 1px 0 rgba(255,255,255,0.16), inset 0 0 0 1px rgba(255,255,255,0.08);
}
/* GLITCH FIX: `left` ki jagah `transform` animate hota hai — GPU par
   chalta hai, layout ko har frame recalculate nahi karna padta. Ye
   animation `infinite` hai, isliye purana tareeka lagataar jank aur
   battery drain kar raha tha. */
.membership-glass-badge::before {
  content: '';
  position: absolute;
  top: 0; left: 0;
  width: 55%; height: 100%;
  background: linear-gradient(115deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0.55) 45%, rgba(255,255,255,0.05) 65%, rgba(255,255,255,0) 100%);
  transform: translateX(-290%) skewX(-20deg);
  animation: membershipGlassShine 3.6s ease-in-out infinite;
  animation-delay: 1.1s;
  pointer-events: none;
  z-index: 1;
  will-change: transform;
  backface-visibility: hidden;
}
.membership-glass-badge::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(255,255,255,0.14) 0%, rgba(255,255,255,0) 40%);
  pointer-events: none;
}
@keyframes membershipGlassShine {
  0%   { transform: translateX(-290%) skewX(-20deg); }
  30%  { transform: translateX(290%)  skewX(-20deg); }
  100% { transform: translateX(290%)  skewX(-20deg); }
}
.membership-glass-badge > * { position: relative; z-index: 2; }
.membership-glass-badge .mg-chip {
  width: 20px; height: 15px; border-radius: 3px; flex-shrink: 0;
  background: linear-gradient(135deg, #f4d97a, #c9a227);
  box-shadow: inset 0 0 0 1px rgba(0,0,0,0.18);
}
.membership-glass-badge .mg-tier {
  font-size: 11.5px; font-weight: 800; letter-spacing: 0.4px;
}
.membership-glass-badge .mg-code {
  font-size: 11px; color: rgba(255,255,255,0.75); font-family: 'Courier New', monospace; letter-spacing: 0.3px;
}
.membership-glass-badge .mg-pts {
  font-size: 11px; font-weight: 800; color: #fff; background: rgba(255,255,255,0.16); padding: 2px 8px; border-radius: 20px;
}
.membership-glass-badge .mg-status {
  font-size: 10px; font-weight: 800; padding: 2px 8px; border-radius: 20px; letter-spacing: 0.3px;
}
.membership-glass-badge .mg-status.is-active { background: rgba(15,157,88,0.28); color: #d7ffe9; }
.membership-glass-badge .mg-status.is-inactive { background: rgba(255,255,255,0.16); color: rgba(255,255,255,0.75); }
.membership-glass-badge .mg-status.is-expired { background: rgba(224,58,58,0.32); color: #ffd7d7; }
.membership-glass-badge a.mg-link {
  font-size: 11px; font-weight: 800; color: #fff; text-decoration: none; opacity: 0.9; border-bottom: 1px solid rgba(255,255,255,0.5);
}
.membership-glass-badge a.mg-link:hover { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .membership-glass-badge::before { animation: none; display: none; }
}

/* ---- Team page: category folders (grouped by role) ---- */
.team-cat-summary {
  display: flex; align-items: center; gap: 22px;
  margin-bottom: 18px; padding: 14px 20px;
  border-radius: 14px;
  background: linear-gradient(135deg, #1a1a22, #2b2b38);
  color: #fff;
  box-shadow: 0 8px 22px rgba(17,16,19,0.18), inset 0 1px 0 rgba(255,255,255,0.08);
}
.team-cat-summary-item { display: flex; flex-direction: column; line-height: 1.2; }
.team-cat-summary-num { font-size: 21px; font-weight: 800; }
.team-cat-summary-label { font-size: 11px; color: rgba(255,255,255,0.65); text-transform: uppercase; letter-spacing: 0.05em; font-weight: 700; margin-top: 2px; }
.team-cat-summary-divider { width: 1px; height: 30px; background: rgba(255,255,255,0.16); }

.team-cat-grid { display: flex; flex-direction: column; gap: 16px; }

.team-cat-folder {
  border-radius: 14px;
  background: #fff;
  border: 1px solid var(--border-main);
  overflow: hidden;
  box-shadow: 0 2px 8px rgba(17,16,19,0.04);
  transition: box-shadow 0.2s ease;
}
.team-cat-folder:hover { box-shadow: 0 6px 18px rgba(17,16,19,0.08); }

.team-cat-header {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  width: 100%;
  display: flex; align-items: center; gap: 12px;
  padding: 14px 18px;
  border: none; cursor: pointer;
  font: inherit; text-align: left;
  color: #fff;
  background: linear-gradient(120deg, var(--cat-color, #7a7a85), color-mix(in srgb, var(--cat-color, #7a7a85) 70%, #000 15%));
}
/* GLITCH FIX: `left` ki jagah `transform` animate hota hai — GPU par
   chalta hai, layout ko har frame recalculate nahi karna padta. Ye
   animation `infinite` hai, isliye purana tareeka lagataar jank aur
   battery drain kar raha tha. */
.team-cat-header::before {
  content: '';
  position: absolute;
  top: 0; left: 0;
  width: 45%; height: 100%;
  background: linear-gradient(115deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0.35) 45%, rgba(255,255,255,0.04) 65%, rgba(255,255,255,0) 100%);
  transform: translateX(-355%) skewX(-20deg);
  animation: teamCatShine 4.2s ease-in-out infinite;
  animation-delay: 0.6s;
  pointer-events: none;
  z-index: 1;
  will-change: transform;
  backface-visibility: hidden;
}
@keyframes teamCatShine {
  0%   { transform: translateX(-355%) skewX(-20deg); }
  35%  { transform: translateX(355%)  skewX(-20deg); }
  100% { transform: translateX(355%)  skewX(-20deg); }
}
@media (prefers-reduced-motion: reduce) {
  .team-cat-header::before { animation: none; display: none; }
}
.team-cat-header > * { position: relative; z-index: 2; }
.team-cat-icon { font-size: 18px; line-height: 1; flex-shrink: 0; }
.team-cat-title { font-weight: 800; font-size: 14.5px; flex: 1; letter-spacing: 0.01em; }
.team-cat-count {
  font-size: 11.5px; font-weight: 800;
  background: rgba(255,255,255,0.22);
  padding: 4px 12px; border-radius: 20px;
  white-space: nowrap;
}
.team-cat-chevron {
  font-size: 13px; transition: transform 0.2s ease; flex-shrink: 0; opacity: 0.9;
}
.team-cat-folder.is-collapsed .team-cat-chevron { transform: rotate(-90deg); }
/* ---- Stat indicator bar (Team / Customers pages) ---- */
.stat-indicator-bar {
  display: flex; flex-wrap: wrap; gap: 10px;
  margin-bottom: 18px;
}
.stat-indicator {
  flex: 1; min-width: 140px;
  display: flex; align-items: center; gap: 10px;
  background: var(--white); border: 1px solid var(--border-main);
  border-radius: 14px; padding: 12px 16px;
}
.stat-indicator-icon {
  width: 38px; height: 38px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 16px; flex-shrink: 0;
}
.stat-indicator-text { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
.stat-indicator-value { font-size: 19px; font-weight: 800; }
.stat-indicator-label { font-size: 11.5px; color: var(--text-secondary); white-space: nowrap; }

/* ---- Desktop-only refinement of the stat indicator bar (Team /
   Customers pages) — bigger, more premium cards on wide screens.
   Scoped ONLY to .stat-indicator-bar/.stat-indicator; nothing else on
   the page (header, sidebar, etc.) is touched by this block. ---- */
@media (min-width: 901px) {
  .stat-indicator-bar { gap: 18px; margin-bottom: 26px; }
  .stat-indicator {
    padding: 20px 26px;
    border-radius: 16px;
    gap: 16px;
    box-shadow: 0 2px 10px rgba(17,16,19,0.05);
    transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
  }
  .stat-indicator:hover {
    transform: translateY(-3px);
    box-shadow: 0 12px 28px rgba(17,16,19,0.10);
    border-color: transparent;
  }
  .stat-indicator-icon {
    width: 52px; height: 52px; font-size: 22px;
    box-shadow: inset 0 0 0 1px rgba(0,0,0,0.04);
  }
  .stat-indicator-value { font-size: 27px; }
  .stat-indicator-label { font-size: 12.5px; letter-spacing: 0.01em; }
}

/* ---- Member cards (grouped inside a category folder body) ---- */
.team-cat-body {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 14px;
  padding: 16px !important;
  background: #fafafc;
}
.member-card {
  background: var(--white);
  border: 1px solid var(--border-main);
  border-radius: 14px;
  padding: 16px;
  cursor: pointer;
  transition: box-shadow 0.15s ease, transform 0.15s ease, border-color 0.15s ease;
}
.member-card:hover { box-shadow: 0 8px 22px rgba(17,16,19,0.1); transform: translateY(-2px); border-color: rgba(0,0,0,0.14); }
.member-card-header { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.member-card-avatar-wrap { position: relative; flex-shrink: 0; }
.member-card-online-dot {
  position: absolute; right: -1px; bottom: -1px;
  width: 11px; height: 11px; border-radius: 50%;
  background: #0f9d58; border: 2px solid var(--white);
}
.member-card-id { flex: 1; min-width: 0; }
.member-card-name { font-weight: 800; font-size: 14.5px; line-height: 1.3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.member-card-username { font-size: 12px; color: var(--text-secondary); line-height: 1.3; margin-top: 1px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Grid columns use minmax(0, 1fr) instead of a bare 1fr — a bare 1fr
   track's implicit minimum is its content's natural width, so a long
   unbroken value (an email address, a long specialization) could force
   the track wider than the card and spill/overlap into the next column
   or row. minmax(0, ...) removes that content-based floor so the
   ellipsis/truncation on .mc-value can actually take effect. */
.member-card-grid {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 12px 16px;
  padding-top: 14px; margin-top: 2px; border-top: 1px solid var(--border-main);
}
.mc-field { display: flex; align-items: flex-start; gap: 8px; min-width: 0; }
.mc-icon {
  width: 26px; height: 26px; border-radius: 8px; background: #f3f3f6;
  display: flex; align-items: center; justify-content: center; font-size: 12px; flex-shrink: 0;
  margin-top: 1px;
}
/* This wrapper is itself a flex child of .mc-field — without an explicit
   min-width:0 + flex:1 here, a flex item's default min-width is "auto"
   (i.e. its content's width), so long text would push past the column
   edge instead of respecting it — the exact cause of the overlap. */
.mc-field-text { flex: 1; min-width: 0; }
.mc-label { font-size: 10.5px; color: var(--text-tertiary); text-transform: uppercase; letter-spacing: 0.03em; font-weight: 700; line-height: 1.3; }
.mc-value {
  font-size: 13px; font-weight: 600; line-height: 1.35; margin-top: 1px;
  display: block; width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mc-value code {
  font-size: 12px; font-family: 'Courier New', monospace; background: #f3f3f6;
  padding: 2px 6px; border-radius: 5px; display: inline-block; max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; box-sizing: border-box;
}
body.dark-mode .mc-icon { background: #26262e; }
body.dark-mode .mc-value code { background: #26262e; }
@media (max-width: 420px) {
  .member-card-grid { grid-template-columns: minmax(0, 1fr); }
}
.member-card-actions {
  display: flex; gap: 8px; flex-wrap: wrap;
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border-main);
}
.member-card-actions .btn { flex: 1; min-width: 90px; text-align: center; padding: 8px 10px; font-size: 12.5px; white-space: nowrap; }
.btn-danger { background: #fdeaf0; color: var(--brand-pink); }
.btn-danger:hover { background: var(--brand-pink); color: #fff; }

/* ---- Membership Cards list: inline manual tier-change control ---- */
.tier-inline-select {
  padding: 5px 6px; font-size: 12px; width: auto; min-width: 110px;
  border-radius: 7px; border: 1px solid var(--border-main); background: var(--white); color: var(--text-primary);
}
.tier-inline-save {
  padding: 5px 9px; font-size: 12px; line-height: 1; flex-shrink: 0;
}

/* ---- Kebab (⋮) quick-action menu on a card ---- */
.card-kebab { position: relative; flex-shrink: 0; }
.card-kebab-btn {
  width: 30px; height: 30px; border-radius: 8px; border: none;
  background: transparent; color: var(--text-secondary); font-size: 18px;
  cursor: pointer; line-height: 1;
}
.card-kebab-btn:hover { background: #f3f3f6; }
.card-kebab-menu {
  display: none; position: absolute; right: 0; top: 34px; z-index: 20;
  background: var(--white); border: 1px solid var(--border-main); border-radius: 10px;
  box-shadow: 0 8px 24px rgba(17,16,19,0.14); min-width: 160px; overflow: hidden;
}
.card-kebab-menu.show { display: block; }
.card-kebab-menu a {
  display: block; padding: 9px 14px; font-size: 12.5px; font-weight: 600;
  color: var(--text-primary); text-decoration: none; white-space: nowrap;
}
.card-kebab-menu a:hover { background: #f3f3f6; }
.card-kebab-menu a.danger { color: var(--brand-pink); }

/* ---- Forms ---- */
.form-group { margin-bottom: 16px; }
.form-label { display:block; font-size: 12.5px; font-weight: 600; margin-bottom: 6px; color: var(--text-secondary); }
.form-input, .form-select, textarea.form-input {
  width: 100%; padding: 10px 12px; border: 1px solid var(--border-main); border-radius: var(--radius-sm);
  font-size: 13.5px; font-family: inherit; background: var(--white); color: var(--text-primary);
}
.form-input:focus, .form-select:focus { outline: none; border-color: #2284e6; box-shadow: 0 0 0 3px rgba(34,132,230,0.12); }

/* ---- Password field with show/hide eye toggle ---- */
.password-field-wrap { position: relative; }
.password-field-wrap .form-input { padding-right: 42px; }
.password-toggle-btn {
  position: absolute; top: 50%; right: 4px; transform: translateY(-50%);
  width: 32px; height: 32px;
  display: flex; align-items: center; justify-content: center;
  background: none; border: none; cursor: pointer; border-radius: 8px;
  color: var(--text-tertiary);
  transition: color 0.15s ease, background 0.15s ease;
}
.password-toggle-btn:hover { color: var(--brand-pink, #ff2d62); background: rgba(0,0,0,0.045); }
.password-toggle-btn svg { width: 18px; height: 18px; display: block; }
.password-toggle-btn .eye-hide-icon { display: none; }
.password-toggle-btn.is-visible .eye-show-icon { display: none; }
.password-toggle-btn.is-visible .eye-hide-icon { display: block; }

/* ---- Login screen ---- */
/* ---- Logo shape picker (Settings > Branding) ---- */
.logo-shape-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
.logo-shape-option {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: 14px 8px; border: 2px solid var(--border-main); border-radius: 12px;
  cursor: pointer; text-align: center; transition: border-color 0.15s ease, background 0.15s ease;
}
.logo-shape-option:hover { border-color: #c9c9d1; }
.logo-shape-option.selected { border-color: var(--brand-pink); background: #fdeaf0; }
.logo-shape-swatch { background: linear-gradient(135deg, #d81142, #a10d33); flex-shrink: 0; }
.logo-shape-label { font-size: 12px; font-weight: 700; }
.logo-shape-desc { font-size: 10.5px; color: var(--text-tertiary); }
@media (max-width: 480px) {
  .logo-shape-grid { grid-template-columns: repeat(2, 1fr); }
  /* Refresh button: icon-only on narrow phones so it never competes with
     the heading for space. Wider mobile screens keep the full label. */
  .topbar-refresh-label { display: none; }
  .topbar-refresh-btn { padding: 8px 10px !important; }
}

/* ---- Customer portal: fixed floating "Pay" button, bottom-center ---- */
.portal-fab-pay {
  position: fixed;
  bottom: 22px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 90;
  display: flex;
  align-items: center;
  gap: 10px;
  background: linear-gradient(135deg, #d81142, #a10d33);
  color: #fff;
  font-size: 17px;
  font-weight: 800;
  padding: 18px 34px;
  border-radius: 100px;
  text-decoration: none;
  white-space: nowrap;
  /* No drop shadow — the button sits flat, the glass sweep below is what
     draws the eye instead. */
  box-shadow: none;
  transition: transform 0.15s ease;
  overflow: hidden; /* clips the sweeping shine to the pill shape */
  isolation: isolate; /* keeps the ::before sweep from bleeding into siblings */
}
.portal-fab-pay:hover { transform: translateX(-50%) translateY(-2px); }

/* Continuous "glass" shine sweeping left-to-right across the button —
   a soft diagonal band of light that loops forever, the same visual
   language as a shimmering CTA button, to nudge the customer toward it
   without needing a shadow or a bounce animation. */
/* GLITCH FIX: `left` ki jagah `transform` animate hota hai — GPU par
   chalta hai, layout ko har frame recalculate nahi karna padta. Ye
   animation `infinite` hai, isliye purana tareeka lagataar jank aur
   battery drain kar raha tha. */
.portal-fab-pay::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 45%;
  height: 100%;
  background: linear-gradient(115deg, transparent 0%, rgba(255,255,255,0.55) 50%, transparent 100%);
  transform: translateX(-180%) skewX(-20deg);
  animation: portalPayShine 2.8s ease-in-out infinite;
  pointer-events: none;
  will-change: transform;
  backface-visibility: hidden;
}
@keyframes portalPayShine {
  0%   { transform: translateX(-180%) skewX(-20deg); }
  55%  { transform: translateX(320%)  skewX(-20deg); }
  100% { transform: translateX(320%)  skewX(-20deg); }
}
@media (prefers-reduced-motion: reduce) {
  .portal-fab-pay::before { animation: none; display: none; }
}
@media (max-width: 640px) {
  .portal-fab-pay { bottom: 16px; font-size: 15px; padding: 15px 26px; }
}

/* ---- Admin/Staff: primary page action as a floating bottom-center
   button — same size, shape and "glass shine" language as the customer
   portal's Pay button, so both sides of the product feel like one
   consistent, premium system. ---- */
/* ---- Shared visual style for every floating action pill (both the
   single-button pages and the paired New Order + Scan Order layout) ---- */
.staff-fab-btn {
  display: flex;
  align-items: center;
  gap: 10px;
  background: linear-gradient(135deg, #d81142, #a10d33);
  color: #fff;
  font-size: 17px;
  font-weight: 800;
  padding: 18px 48px;
  border-radius: 100px;
  text-decoration: none;
  white-space: nowrap;
  box-shadow: none;
  transition: transform 0.15s ease;
  overflow: hidden;
  isolation: isolate;
  position: relative;
}
.staff-fab-btn:hover { transform: translateY(-2px); color: #fff; }
/* Shine sweep.
   GLITCH FIX: pehle ye `left` property ko animate karta tha. `left`
   badalne se browser har frame par layout dobara calculate karta hai,
   aur kyunki button `overflow:hidden` + `border-radius:100px` hai, us
   sweep ke waqt rounded corners par ek halki si seam/flicker dikhti thi
   (khaas kar mobile aur low-end screens par).
   Ab sirf `transform` animate hota hai — wo GPU par chalta hai, layout
   ko chhedta hi nahi, isliye sweep ekdum smooth aati hai. Sweep khatm
   hone par opacity 0 kar dete hain taaki kuch bhi kone me atka na rahe. */
.staff-fab-btn::before {
  content: '';
  position: absolute;
  top: 0; left: 0;
  width: 45%; height: 100%;
  background: linear-gradient(115deg, transparent 0%, rgba(255,255,255,0.55) 50%, transparent 100%);
  transform: translateX(-180%) skewX(-20deg);
  animation: apFabShine 2.8s ease-in-out 1 forwards;
  pointer-events: none;
  will-change: transform, opacity;
  backface-visibility: hidden;
}
@keyframes apFabShine {
  0%        { transform: translateX(-180%) skewX(-20deg); opacity: 1; }
  55%       { transform: translateX(320%)  skewX(-20deg); opacity: 1; }
  56%, 100% { transform: translateX(320%)  skewX(-20deg); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .staff-fab-btn::before { animation: none; display: none; }
}
/* Second, secondary-action pill (e.g. Scan Order) — same shape and shine,
   distinct color so it reads as "an alternative action", not a duplicate. */
.staff-fab-btn-secondary { background: linear-gradient(135deg, #2284e6, #1a5fa8); }

/* ---- Single-button pages (unchanged behaviour) ---- */
.staff-fab-action {
  position: fixed;
  bottom: 22px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 90;
}
.staff-fab-action:hover { transform: translateX(-50%) translateY(-2px); }
@media (max-width: 640px) {
  .staff-fab-action { bottom: 16px; }
  .staff-fab-action.staff-fab-btn { font-size: 15px; padding: 15px 36px; }
}
@media (max-width: 380px) {
  .staff-fab-action.staff-fab-btn { padding: 13px 28px; font-size: 13.5px; gap: 7px; }
}

/* ---- Paired buttons (e.g. Orders page: New Order + Scan Order) ----
   One fixed, centered flex group; each pill inside sizes down earlier
   than the single-button case so both stay side by side even on
   narrow phones instead of wrapping onto two lines. */
.staff-fab-group {
  position: fixed;
  bottom: 22px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 90;
  display: flex;
  gap: 10px;
}
.staff-fab-group .staff-fab-btn { font-size: 15px; padding: 15px 26px; }
@media (max-width: 640px) {
  .staff-fab-group { bottom: 16px; gap: 8px; }
  .staff-fab-group .staff-fab-btn { font-size: 15px; padding: 15px 22px; gap: 7px; }
}
@media (max-width: 380px) {
  .staff-fab-group .staff-fab-btn { font-size: 13.5px; padding: 13px 16px; gap: 6px; }
}

/* ---- Keyboard shortcuts: discoverable trigger (bottom-left) + help modal ---- */
.shortcuts-fab-trigger {
  position: fixed; left: 18px; bottom: 18px; z-index: 900;
  width: 44px; height: 44px; border-radius: 50%;
  background: #1a1a1f; color: #fff; border: none;
  display: flex; align-items: center; justify-content: center;
  font-size: 17px; cursor: pointer;
  box-shadow: 0 4px 14px rgba(0,0,0,0.28);
  transition: transform 0.15s ease, background 0.15s ease;
}
.shortcuts-fab-trigger:hover { background: #2a2a32; transform: translateY(-2px); }
.shortcuts-modal-grid { display: grid; grid-template-columns: 1fr; gap: 2px; }
.shortcuts-modal-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: 9px 4px; border-bottom: 1px solid var(--border-main);
  font-size: 13px;
}
.shortcuts-modal-row:last-child { border-bottom: none; }
.shortcuts-kbd {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 26px; height: 24px; padding: 0 7px;
  background: #f0f0f3; border: 1px solid var(--border-main); border-bottom-width: 2px;
  border-radius: 6px; font-size: 11.5px; font-weight: 800; color: var(--text-primary);
  font-family: inherit;
}
.shortcuts-kbd + .shortcuts-kbd { margin-left: 4px; }

/* ---- Customer portal sidebar item + tab pill (moved here from an inline
   <style> block so the same durable-base-class principle applies — these
   survive future page edits the same way .btn does) ---- */
.portal-sidebar-item {
  display:flex; align-items:center; gap:10px; padding:10px 16px; border-radius:8px;
  font-size:13.5px; font-weight:600; color:var(--sidebar-text); text-decoration:none;
  transition: background-color 0.16s ease, color 0.16s ease, padding-left 0.16s ease;
}
.portal-sidebar-item:hover { background:rgba(255,255,255,0.06); padding-left:19px; }
.portal-sidebar-item.active { color:var(--brand-pink); background:rgba(216,17,66,0.12); }
.portal-tab {
  padding:8px 16px; border-radius:20px; font-size:12.5px; font-weight:600;
  background:#f3f3f6; color:var(--text-secondary); text-decoration:none;
  display:inline-flex; align-items:center; transition: background-color 0.16s ease, color 0.16s ease, transform 0.16s cubic-bezier(0.34,1.56,0.64,1);
}
.portal-tab:hover { transform: translateY(-1px); }
.portal-tab.active { background:#1a1a1f; color:#fff; }

/* ---- Login pages: premium gradient background, replaces flat black ---- */
.login-wrap {
  min-height: 100vh;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 40px 16px;
  background:
    radial-gradient(circle at 15% 15%, rgba(216,17,66,0.35) 0%, transparent 45%),
    radial-gradient(circle at 85% 85%, rgba(99,102,241,0.28) 0%, transparent 45%),
    linear-gradient(160deg, #0d0d12 0%, #1a1a24 45%, #24141c 100%);
  background-attachment: fixed;
  position: relative;
  overflow: hidden;
}
/* Faint dot-grid texture for a subtle "tech/premium" feel without any image assets */
.login-wrap::before {
  content: '';
  position: absolute; inset: 0;
  background-image: radial-gradient(rgba(255,255,255,0.055) 1px, transparent 1px);
  background-size: 26px 26px;
  pointer-events: none;
}

/* ---- Ambient floating orbs — pure CSS, no images. Two soft blurred
   blobs drifting slowly behind the card for a premium "alive" feel.
   Decorative only: aria-hidden in markup, pointer-events off here. ---- */
.login-orb {
  position: absolute;
  border-radius: 50%;
  filter: blur(60px);
  pointer-events: none;
  z-index: 0;
  opacity: 0.55;
  will-change: transform;
}
.login-orb-1 {
  width: 280px; height: 280px; top: -60px; left: -60px;
  background: radial-gradient(circle, rgba(216,17,66,0.55) 0%, transparent 70%);
  animation: loginOrbFloat1 16s ease-in-out infinite;
}
.login-orb-2 {
  width: 320px; height: 320px; bottom: -80px; right: -80px;
  background: radial-gradient(circle, rgba(99,102,241,0.45) 0%, transparent 70%);
  animation: loginOrbFloat2 20s ease-in-out infinite;
}
@keyframes loginOrbFloat1 {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50% { transform: translate(40px, 30px) scale(1.12); }
}
@keyframes loginOrbFloat2 {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50% { transform: translate(-30px, -35px) scale(1.08); }
}
@media (max-width: 480px) {
  .login-orb { filter: blur(40px); opacity: 0.4; }
  .login-orb-1 { width: 200px; height: 200px; }
  .login-orb-2 { width: 220px; height: 220px; }
}
@media (prefers-reduced-motion: reduce) {
  .login-orb { animation: none; }
}

.login-stack {
  position: relative; z-index: 1; width: 100%; max-width: 400px;
  display: flex; flex-direction: column; gap: 18px;
  animation: loginStackIn 0.55s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.login-logo-standalone {
  display: flex; align-items: center; justify-content: center;
  animation: loginLogoIn 0.6s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.login-logo-standalone img { filter: drop-shadow(0 8px 20px rgba(0,0,0,0.35)); }
.login-box {
  background: var(--white);
  width: 100%;
  max-width: 400px;
  margin: 0 auto;
  border-radius: 18px;
  padding: 32px;
  box-shadow: 0 20px 60px rgba(0,0,0,0.35), 0 2px 8px rgba(0,0,0,0.15);
  text-align: center;
  position: relative;
  z-index: 1;
  animation: loginBoxIn 0.6s 0.08s cubic-bezier(0.22, 1, 0.36, 1) both;
  transition: box-shadow 0.35s ease, transform 0.35s ease;
}
.login-box:hover { box-shadow: 0 26px 70px rgba(0,0,0,0.4), 0 2px 8px rgba(0,0,0,0.18); }
@keyframes loginStackIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes loginLogoIn { from { opacity: 0; transform: translateY(-14px) scale(0.92); } to { opacity: 1; transform: translateY(0) scale(1); } }
@keyframes loginBoxIn { from { opacity: 0; transform: translateY(22px) scale(0.97); } to { opacity: 1; transform: translateY(0) scale(1); } }
@media (prefers-reduced-motion: reduce) {
  .login-stack, .login-logo-standalone, .login-box { animation: none; }
}
/* Inside the two-part stack, the box shouldn't also center itself again */
.login-stack .login-box { margin: 0; max-width: none; }
.login-box img { display: block; margin: 0 auto 14px; }
.login-box form { text-align: left; }
.login-box h2 { margin: 0 0 4px; font-size: 20px; font-weight: 800; }
.login-box p.sub { color: var(--text-secondary); font-size: 13px; margin: 0 0 20px; }
.login-error {
  background: #fdeaf0; color: var(--brand-pink); padding: 10px 14px; border-radius: var(--radius-sm);
  font-size: 13px; margin-bottom: 16px;
  animation: loginErrorIn 0.4s cubic-bezier(.36,.07,.19,.97) both;
}
@keyframes loginErrorIn {
  0% { opacity: 0; transform: translateY(-4px); }
  35% { opacity: 1; transform: translateX(-6px); }
  50% { transform: translateX(5px); }
  65% { transform: translateX(-3px); }
  80% { transform: translateX(2px); }
  100% { opacity: 1; transform: translateX(0); }
}
@media (prefers-reduced-motion: reduce) { .login-error { animation: none; } }

/* Smooth focus + hover lift for every field inside the login cards only
   (scoped to .login-box so the rest of the app's forms are untouched). */
.login-box .form-input, .login-box .form-select {
  transition: border-color 0.2s ease, box-shadow 0.25s ease, transform 0.15s ease;
}
.login-box .form-input:focus, .login-box .form-select:focus { transform: translateY(-1px); }
.login-box .btn-primary { transition: background-color 0.2s ease, box-shadow 0.25s ease, transform 0.15s ease; }
.login-box .btn-primary:hover:not(:disabled) { transform: translateY(-2px); }
.login-box .btn-primary:active:not(:disabled) { transform: translateY(0) scale(0.98); }

/* ---- Failed-attempt "points" — one dot per allowed try, filling
   left-to-right as attempts are used up. Color escalates from amber to
   red as the person gets closer to being locked out, and each newly
   used dot pops in with a small bounce so the change is unmistakable —
   all purely visual, next to the (unchanged) generic error text above. ---- */
.login-attempt-track {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  margin: -6px 0 16px;
  animation: loginAttemptTrackIn 0.35s ease both;
}
@keyframes loginAttemptTrackIn { from { opacity: 0; transform: translateY(-3px); } to { opacity: 1; transform: translateY(0); } }
.login-attempt-dots { display: flex; gap: 7px; }
.login-attempt-dot {
  position: relative;
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--border-main);
  box-shadow: inset 0 0 0 1px rgba(0,0,0,0.03);
  transition: background 0.25s ease, transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.25s ease;
}
.login-attempt-dot.is-used {
  background: linear-gradient(135deg, #ff8a3d, var(--brand-pink));
  transform: scale(1.15);
  box-shadow: 0 0 0 3px rgba(216,17,66,0.14);
  animation: loginAttemptPop 0.4s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
/* Last 2 dots escalate to a more urgent solid red + soft pulse — a quiet
   "you're close to being locked out" cue without any extra text. */
.login-attempt-dots .login-attempt-dot.is-used:nth-last-child(-n+2) {
  background: var(--brand-pink);
  animation: loginAttemptPop 0.4s cubic-bezier(0.34, 1.56, 0.64, 1) both, loginAttemptPulse 1.6s ease-in-out 0.4s infinite;
}
@keyframes loginAttemptPop {
  0% { transform: scale(0.4); opacity: 0.4; }
  60% { transform: scale(1.35); }
  100% { transform: scale(1.15); opacity: 1; }
}
@keyframes loginAttemptPulse {
  0%, 100% { box-shadow: 0 0 0 3px rgba(216,17,66,0.14); }
  50% { box-shadow: 0 0 0 6px rgba(216,17,66,0.05); }
}
@media (prefers-reduced-motion: reduce) {
  .login-attempt-track, .login-attempt-dot.is-used { animation: none; }
}
.login-attempt-label { font-size: 11.5px; font-weight: 700; color: var(--text-tertiary); white-space: nowrap; }

/* ---- Lockout countdown — replaces the form entirely while an account
   is locked, so the person can't keep hammering a doomed submit
   button and instead sees exactly how long is left. A ring drawn with
   a conic-gradient visually drains as the countdown ticks (kept in
   sync by the same inline script that updates the mm:ss text), and
   auto-reloads the instant it hits zero. ---- */
.login-lockout-box {
  text-align: center;
  padding: 24px 18px;
  border-radius: 14px;
  background: #fdeaf0;
  border: 1px solid rgba(216,17,66,0.18);
  animation: loginLockoutIn 0.4s cubic-bezier(0.22, 1, 0.36, 1) both;
}
@keyframes loginLockoutIn { from { opacity: 0; transform: scale(0.96); } to { opacity: 1; transform: scale(1); } }
.login-lockout-icon {
  font-size: 26px; margin-bottom: 10px;
  display: inline-flex; align-items: center; justify-content: center;
  width: 46px; height: 46px; border-radius: 50%;
  background: rgba(216,17,66,0.1);
  animation: loginLockoutIconPulse 2s ease-in-out infinite;
}
@keyframes loginLockoutIconPulse {
  0%, 100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(216,17,66,0.18); }
  50% { transform: scale(1.06); box-shadow: 0 0 0 8px rgba(216,17,66,0); }
}
.login-lockout-msg { font-size: 13px; font-weight: 600; color: var(--text-primary); line-height: 1.5; margin-bottom: 14px; }
/* Ring wraps the mm:ss timer — --pct (0 → 100) is written by JS every
   tick and drains as time runs out. */
.login-lockout-ring {
  --pct: 100;
  width: 96px; height: 96px; border-radius: 50%; margin: 0 auto;
  display: flex; align-items: center; justify-content: center;
  background: conic-gradient(var(--brand-pink) calc(var(--pct) * 1%), rgba(216,17,66,0.12) 0);
  transition: background 0.3s linear;
}
.login-lockout-ring-inner {
  width: 78px; height: 78px; border-radius: 50%;
  background: #fdeaf0;
  display: flex; align-items: center; justify-content: center;
}
.login-lockout-timer {
  font-family: 'JetBrains Mono', 'Courier New', monospace;
  font-size: 20px; font-weight: 800; letter-spacing: 0.5px;
  color: var(--brand-pink);
  font-variant-numeric: tabular-nums;
}
.login-lockout-sub { font-size: 11.5px; color: var(--text-tertiary); margin-top: 10px; }
body.dark-mode .login-lockout-box { background: #3a1c26; border-color: rgba(255,107,143,0.25); }
body.dark-mode .login-lockout-ring-inner { background: #3a1c26; }
@media (prefers-reduced-motion: reduce) {
  .login-lockout-box { animation: none; }
  .login-lockout-icon { animation: none; }
}

/* ---- Password / PIN / OTP mode tabs — the background/color per tab is
   still computed inline by PHP (unchanged), this just makes switching
   between them glide instead of snap. ---- */
.login-mode-tab { transition: background-color 0.2s ease, color 0.2s ease, box-shadow 0.2s ease, transform 0.15s ease; }
.login-mode-tab:hover { transform: translateY(-1px); }

/* ---- Smooth cross-fade between the Customer / Staff panels on
   login.php, replacing the old instant display:none ↔ block swap. ---- */
.login-panel-fade { animation: loginPanelIn 0.32s cubic-bezier(0.22, 1, 0.36, 1) both; }
@keyframes loginPanelIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
.login-panel-hidden { display: none !important; }
@media (prefers-reduced-motion: reduce) { .login-panel-fade { animation: none; } }

/* ---- Customer Portal: now the prominent top panel on the staff login
   page — same card chrome as .login-box, with its own hero icon and a
   single big CTA button instead of a form. ---- */
.login-box-customer { text-align: center; }
.customer-hero-icon {
  width: 56px; height: 56px; border-radius: 16px;
  margin: 0 auto 14px;
  background: linear-gradient(135deg, #ff2d62, #b0102e);
  display: flex; align-items: center; justify-content: center;
  font-size: 26px;
  box-shadow: 0 10px 22px rgba(216,17,66,0.32);
  animation: heroIconPulse 3.2s ease-in-out infinite;
}
@keyframes heroIconPulse {
  0%, 100% { box-shadow: 0 10px 22px rgba(216,17,66,0.32); transform: translateY(0); }
  50% { box-shadow: 0 14px 30px rgba(216,17,66,0.44); transform: translateY(-2px); }
}
@media (prefers-reduced-motion: reduce) { .customer-hero-icon { animation: none; } }

/* ---- Staff & Admin: compact, secondary panel below — the same fully
   functional form, just less visual weight (tighter padding, smaller
   heading) so it reads as the secondary option on this page. ---- */
.login-box-compact { padding: 24px 28px; }
.login-box-compact h2 { font-size: 16px; }
.login-box-compact p.sub { font-size: 12px; margin-bottom: 16px; }
.staff-hero-icon {
  width: 56px; height: 56px; border-radius: 16px;
  margin: 0 auto 14px;
  background: linear-gradient(135deg, #232634, #0a0a0f);
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 10px 22px rgba(0,0,0,0.35);
  animation: heroIconPulseDark 3.2s ease-in-out infinite;
}
@keyframes heroIconPulseDark {
  0%, 100% { box-shadow: 0 10px 22px rgba(0,0,0,0.35); transform: translateY(0); }
  50% { box-shadow: 0 14px 30px rgba(0,0,0,0.5); transform: translateY(-2px); }
}
@media (prefers-reduced-motion: reduce) { .staff-hero-icon { animation: none; } }
/* Staff Login submit button — black, scoped to this panel only so the
   rest of the app's .btn-primary buttons (customer login included) stay
   on the usual brand pink. */
#staffLoginPanel .btn-primary { background: linear-gradient(135deg, #1e2130, #0a0a0f); box-shadow: 0 4px 14px rgba(0,0,0,0.35); }
#staffLoginPanel .btn-primary:hover:not(:disabled) { background: linear-gradient(135deg, #292d40, #14141c); box-shadow: 0 8px 20px rgba(0,0,0,0.45); }
.staff-panel-back {
  display: block;
  background: none;
  border: none;
  color: var(--text-tertiary);
  font-size: 11.5px;
  font-weight: 600;
  cursor: pointer;
  padding: 0;
  margin-bottom: 10px;
  transition: color 0.15s ease;
}
.staff-panel-back:hover { color: var(--brand-pink); }

/* ---- "OR" divider between the two login panels ---- */
.login-divider { display: flex; align-items: center; gap: 12px; color: rgba(255,255,255,0.4); font-size: 11px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase; }
.login-divider::before, .login-divider::after { content: ''; flex: 1; height: 1px; background: rgba(255,255,255,0.15); }

/* ---- Customer portal call-to-action card (bottom panel on staff login) ---- */
.customer-login-card {
  background: linear-gradient(135deg, rgba(255,255,255,0.08), rgba(255,255,255,0.03));
  backdrop-filter: blur(6px);
  border: 1px solid rgba(255,255,255,0.14);
  border-radius: 18px;
  padding: 22px 26px;
  display: flex; align-items: center; gap: 16px;
  text-decoration: none;
  transition: transform 0.15s ease, border-color 0.15s ease, background 0.15s ease;
}
.customer-login-card:hover { transform: translateY(-2px); border-color: rgba(255,255,255,0.3); background: linear-gradient(135deg, rgba(255,255,255,0.12), rgba(255,255,255,0.05)); }
.customer-login-icon {
  width: 48px; height: 48px; border-radius: 12px; flex-shrink: 0;
  background: linear-gradient(135deg, #ff2d62, #b0102e);
  display: flex; align-items: center; justify-content: center; font-size: 22px;
}
.customer-login-text { flex: 1; text-align: left; }
.customer-login-text .title { color: #fff; font-size: 14.5px; font-weight: 800; }
.customer-login-text .sub { color: rgba(255,255,255,0.6); font-size: 12px; margin-top: 2px; }
.customer-login-arrow { color: rgba(255,255,255,0.5); font-size: 18px; flex-shrink: 0; }

/* Reciprocal "Staff Login" link shown at the bottom of the customer portal page */
.staff-login-back {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  color: rgba(255,255,255,0.55); font-size: 12.5px; text-decoration: none;
  padding: 12px; border-radius: 12px; transition: color 0.15s ease, background 0.15s ease;
}
.staff-login-back:hover { color: #fff; background: rgba(255,255,255,0.06); }

/* ---- Staff & Admin login: collapsed trigger button (login.php) ---- */
.staff-login-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  background: linear-gradient(135deg, rgba(255,255,255,0.09), rgba(255,255,255,0.03));
  backdrop-filter: blur(6px);
  border: 1px solid rgba(255,255,255,0.16);
  border-radius: 14px;
  padding: 14px 20px;
  color: rgba(255,255,255,0.75);
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  transition: transform 0.15s ease, border-color 0.15s ease, background 0.15s ease, color 0.15s ease;
}
.staff-login-toggle:hover {
  transform: translateY(-1.5px);
  color: #fff;
  border-color: rgba(255,255,255,0.32);
  background: linear-gradient(135deg, rgba(255,255,255,0.14), rgba(255,255,255,0.05));
}

/* ---- Flash / alerts ---- */
.alert { padding: 12px 16px; border-radius: var(--radius-sm); font-size: 13.5px; margin-bottom: 16px; }
.alert-success { background: #e7f8ee; color: #0f9d58; }
.alert-danger { background: #fdeaf0; color: var(--brand-pink); }

/* ---- Empty / coming soon ---- */
.empty-state { text-align: center; padding: 60px 20px; color: var(--text-secondary); }
.empty-state h3 { font-size: 17px; color: var(--text-primary); margin-bottom: 6px; }
.empty-state p { font-size: 13px; color: var(--text-tertiary); max-width: 320px; margin: 0 auto; line-height: 1.5; }

/* Stat-card icons (order page header, mobile only) — hidden by default so
   desktop, which never wraps these in a grid, doesn't show a stray emoji
   next to each amount. Only @media max-width:900px below turns it on. */
.order-stat-icon { display: none; }

/* New mobile-only order-page elements — hidden by default (desktop);
   only @media max-width:900px turns them on. */
.scope-header-mobile { display: none; }
.oc-edit-jump { display: none; }
.scope-footer-stats { display: none; }

/* Generic reusable visibility helpers — a plain table/list rendered for
   desktop can sit next to a purpose-built mobile card block; exactly one
   of the two is ever visible, decided purely by viewport width. */
.hide-on-mobile { }
.mobile-only-block { display: none; }

/* ---- Big-icon empty state: a soft circular badge with a large emoji icon,
   used wherever a section has nothing in it yet (order page tabs — Timeline,
   Measurements, Design/Reference/Media Files, Payments — and reusable
   anywhere else the same pattern fits). Purely CSS-variable driven so it
   renders correctly in both light and dark mode with zero extra rules, and
   needs no separate mobile treatment since it's already centered/fluid. ---- */
.empty-state-icon {
  width: 88px; height: 88px; margin: 0 auto 18px;
  border-radius: 50%;
  background: #f3f3f6;
  display: flex; align-items: center; justify-content: center;
  font-size: 38px; line-height: 1;
}

/* ============================================================
   Grand Total banner (Scope of Work) — premium redesign.
   Fixed maroon gradient + white text throughout, same as the app's
   other themed banners (Payment Completed, etc), so it renders
   identically in light mode and dark mode — nothing here reacts to
   body.dark-mode on purpose. One fluid flex layout covers desktop and
   mobile alike; the @media block below only trims sizing for very
   narrow phones so nothing overflows or wraps awkwardly.
   ============================================================ */
.grand-total-banner {
  position: relative;
  overflow: hidden;
  margin-top: 16px;
  border-radius: 18px;
  padding: 46px 24px 26px;
  background: linear-gradient(135deg, #b0102e 0%, #7d0e28 55%, #52091d 100%);
  box-shadow: 0 10px 32px rgba(176,16,46,0.32);
}
/* Decorative flowing lines, bottom-right — purely cosmetic, sits behind
   everything else and never intercepts clicks/taps. */
.grand-total-banner::before {
  content: '';
  position: absolute; inset: 0;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='420' height='220' viewBox='0 0 420 220'%3E%3Cpath d='M0,140 C110,90 210,175 420,70' stroke='rgba(255,255,255,0.14)' stroke-width='2' fill='none'/%3E%3Cpath d='M20,170 C130,115 230,195 420,110' stroke='rgba(255,255,255,0.09)' stroke-width='2' fill='none'/%3E%3Cpath d='M60,200 C160,150 260,215 420,150' stroke='rgba(255,80,120,0.22)' stroke-width='2' fill='none'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: bottom right;
  background-size: min(70%, 380px) auto;
  pointer-events: none;
}
.gtb-badge {
  position: absolute; top: 16px; right: 18px; z-index: 2;
  background: rgba(255,255,255,0.16);
  color: #fff;
  font-size: 10.5px; font-weight: 800; letter-spacing: 0.5px; text-transform: uppercase;
  padding: 6px 14px;
  border-radius: 100px;
  white-space: nowrap;
}
.gtb-row { position: relative; z-index: 2; display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.gtb-icon-wrap { position: relative; width: 68px; height: 68px; flex-shrink: 0; }
.gtb-icon-ring { position: absolute; inset: -6px; border-radius: 50%; border: 1.5px solid rgba(255,255,255,0.25); }
.gtb-icon {
  width: 100%; height: 100%; border-radius: 50%;
  background: linear-gradient(135deg, #ff2d62, #b0102e);
  display: flex; align-items: center; justify-content: center;
  font-size: 28px;
  box-shadow: 0 0 26px rgba(255,45,98,0.55), inset 0 0 0 1px rgba(255,255,255,0.15);
}
.gtb-glint {
  position: absolute; top: -3px; left: 4px;
  font-size: 13px; color: #fff;
  animation: gtbTwinkle 2.4s ease-in-out infinite;
}
@keyframes gtbTwinkle {
  0%, 100% { opacity: 0.25; transform: scale(0.85); }
  50% { opacity: 1; transform: scale(1.2); }
}
@media (prefers-reduced-motion: reduce) {
  .gtb-glint { animation: none; opacity: 0.8; }
}
.gtb-text { flex: 1; min-width: 150px; }
.gtb-title { color: #fff; font-size: 23px; font-weight: 800; line-height: 1.2; }
.gtb-sub { color: rgba(255,255,255,0.65); font-size: 12.5px; margin-top: 3px; }
.gtb-amount { color: #fff; font-size: 34px; font-weight: 800; white-space: nowrap; margin-left: auto; }

@media (max-width: 480px) {
  .grand-total-banner { padding: 42px 18px 22px; }
  .gtb-row { gap: 14px; }
  .gtb-icon-wrap { width: 56px; height: 56px; }
  .gtb-icon { font-size: 23px; }
  .gtb-title { font-size: 20px; }
  .gtb-amount { font-size: 27px; }
}

body.dark-mode .empty-state-icon { background: #1c1c22; }
.empty-state h3 { margin-top: 0; }

/* ---- Mobile: sidebar slides in from left over the page, with a dim backdrop ---- */
.menu-toggle { display: none; }
.sidebar-backdrop { display: none; }

@media (max-width: 900px) {
  :root {
    --masthead-h: 76px;
    --masthead-top-space: 14px;
    /* Native-app bottom tab bar height, plus the device's own safe-area
       inset (iPhone home-indicator strip) so the bar never sits under it. */
    --tab-bar-h: 60px;
  }
  .app-masthead-logo img { max-height: 32px; }
  .app-masthead-textonly { font-size: 15px; }
  .app-masthead-textonly small { font-size: 9px; }

  .app-shell { display: block; }
  .sidebar {
    position: fixed; top: calc(var(--masthead-h) + env(safe-area-inset-top, 0px)); left: -260px;
    width: 240px; height: calc(100vh - var(--masthead-h) - env(safe-area-inset-top, 0px));
    /* v2 fix: was 950 — .app-masthead is z-index:1000, so the fixed top
       bar (logo/hamburger/avatar) sat ABOVE the drawer+backdrop and
       intercepted outside taps there (clicks landed on masthead links
       instead of the backdrop, so the drawer never got the close call).
       Now above the masthead so the drawer is always the top layer. */
    z-index: 1050;
    /* Only animate WHILE the drawer is being toggled — not on every page
       load. Otherwise every navigation shows a "slide in from left" flash
       even though the sidebar should already be off-screen at load. */
    transition: none;
    box-shadow: 4px 0 24px rgba(0,0,0,0.25);
    overflow-y: auto;
    scrollbar-width: thin;
  }
  .sidebar.animate { transition: left 0.22s ease; }
  .sidebar.open { left: 0; }
  .sidebar-backdrop {
    display: none; position: fixed; inset: 0;
    background: rgba(0,0,0,0.45);
    /* v2 fix: was 945 (below .app-masthead's 1000) — same reasoning as
       .sidebar above: the masthead sat on top of the backdrop, so taps
       over the top bar never reached this element's onclick=closeSidebar()
       and instead hit whatever masthead link/button was under the finger. */
    z-index: 1040;
    pointer-events: auto; touch-action: manipulation; cursor: pointer;
  }
  .sidebar-backdrop.show { display: block; }
  .main-viewport { width: 100%; min-width: 0; }
  body.sidebar-open { overflow: hidden; }
  /* v3 fix: raising z-index alone wasn't reliable enough — while the
     drawer is open, take the masthead and bottom tab-bar OUT of hit
     testing entirely. Any tap in their area then falls straight through
     to the backdrop underneath (which closes the drawer), instead of
     activating whatever button/link was under the finger. */
  body.sidebar-open .app-masthead,
  body.sidebar-open .mobile-tab-bar { pointer-events: none; }
  /* The old top-bar hamburger is retired on mobile — the new bottom tab
     bar's "More" button opens the same drawer, and having only one menu
     trigger (at the bottom, thumb-reachable) reads as a proper native app
     instead of a shrunk-down desktop layout. Desktop is untouched: this
     rule only exists inside this max-width:900px block. */
  .menu-toggle { display: none; }
  .topbar { gap: 10px; padding: 14px 16px; flex-wrap: nowrap; align-items: center; }
  .topbar h1 { font-size: 17px; }
  .topbar p { font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .page-content { padding: 16px !important; }

  /* Ensure no page ever forces a horizontal scrollbar on the whole viewport —
     the #1 cause of "mobile me preview shi nahi khul raha". Individual
     scrollable regions (tables, chevron strips) still scroll internally. */
  html, body { max-width: 100vw; overflow-x: hidden; }
  .card, .card-body { max-width: 100%; box-sizing: border-box; }
  .page-content { padding: 12px !important; min-width: 0; overflow-x: hidden; }
  /* Separate rule (not folded into the shorthand above) purely so it wins
     the cascade for padding-bottom specifically without having to repeat
     the other three sides. Clears the fixed bottom tab bar, including the
     device's own safe-area inset (iPhone home-indicator strip). */
  .page-content { padding-bottom: calc(var(--tab-bar-h) + env(safe-area-inset-bottom, 0px) + 16px) !important; }
  .page-content > * { max-width: 100%; box-sizing: border-box; }

  /* ---- Generic desktop/mobile card-vs-table swap helper (Customers, and any
     future page using the same pattern). ---- */
  .hide-on-mobile { display: none !important; }
  .mobile-only-block { display: block !important; }

  /* ---- Customers: bespoke mobile card ---- */
  .party-mobile-card {
    position: relative;
    background: var(--bg-main);
    border: 1px solid var(--border-main);
    border-left: 3px solid var(--brand-pink);
    border-radius: 12px;
    padding: 14px;
    margin-bottom: 12px;
  }
  .party-mobile-card:last-child { margin-bottom: 0; }
  .pmc-top { display: flex; align-items: flex-start; gap: 10px; margin-bottom: 12px; }
  .pmc-avatar {
    width: 38px; height: 38px; border-radius: 50%; flex-shrink: 0;
    display: flex; align-items: center; justify-content: center;
    font-weight: 800; font-size: 13px;
  }
  .pmc-name-block { flex: 1; min-width: 0; }
  .pmc-name { font-size: 15px; font-weight: 800; color: var(--text-primary); }
  .pmc-type-badge { margin-top: 4px; font-size: 10.5px; }
  .pmc-top-right { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; flex-shrink: 0; }
  .pmc-menu-dots { color: var(--text-tertiary); font-size: 16px; line-height: 1; padding: 2px 4px; }
  .pmc-grid {
    display: grid; grid-template-columns: 1fr 1fr; gap: 10px 12px;
    padding: 12px 0; border-top: 1px solid var(--border-main); border-bottom: 1px solid var(--border-main);
    margin-bottom: 12px;
  }
  .pmc-value { font-size: 13.5px; font-weight: 700; color: var(--text-primary); }
  .pmc-value-sub { font-size: 11.5px; color: var(--text-tertiary); margin-top: 2px; }
  .pmc-actions { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px; }
  .pmc-actions .btn { padding: 8px 6px; font-size: 11.5px; justify-content: center; }
  .pmc-whatsapp-btn { border: 1.5px solid var(--brand-pink); color: var(--brand-pink); background: transparent; }

  /* KPI grid: 2 columns on mobile */
  .kpi-grid { grid-template-columns: repeat(2, 1fr) !important; gap: 10px !important; }
  .kpi-card { padding: 12px !important; }
  .kpi-card .value { font-size: 18px !important; }

  /* Dashboard: the fixed-ratio rows (charts, Staff/Growth/Machines,
     Production+Notifications, Inventory/Top lists) are 2 or 3 columns
     wide on desktop (e.g. "2fr 1fr", "1fr 1fr 1fr") — squeezed onto a
     phone screen that made every chart/card unreadably narrow. They
     now stack as full-width cards, one below another, like every other
     section on mobile. Desktop layout (min-width:901px) is untouched. */
  .dash-row-grid { grid-template-columns: 1fr !important; gap: 14px !important; }

  /* Ticket edit page: form + comments/history sidebar (1.3fr 1fr on
     desktop) stack into one column on mobile instead of squeezing
     side-by-side. */
  .ticket-edit-grid { grid-template-columns: 1fr !important; }

  /* Tables become cards on mobile instead of scrolling sideways —
     applies to EVERY .data-table across the app (Customers, Payments,
     Ledger, Bankbook, Expenses, Leads, GST Reports, Orders, Quotes,
     Tickets, Team, Stock, Payroll, Portal tables — every admin/staff
     page AND the customer portal, since they all share this same
     .data-table markup). assets/js/mobile-tables.js copies each
     column's <thead> text onto the matching <td> as a data-label
     attribute at page load; the rules below turn that into a
     professional, app-style card — colored accent edge, a bold
     "title" for the row's identifying field, clearer values, and a
     tidy action-button row — instead of a plain stacked list. Nothing
     here touches desktop (min-width:901px never sees this block) and
     nothing here changes any element's class/id/onclick, so existing
     row-click navigation, filters and JS keep working exactly as
     before. */
  .data-table { width: 100%; min-width: 0; font-size: 13px; border-spacing: 0; }
  .data-table thead { display: none; }
  .data-table, .data-table tbody { display: block; width: 100%; }
  .data-table tbody tr {
    position: relative;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 3px 14px;
    background: var(--bg-main);
    border: 1px solid var(--border-main);
    border-left: 3px solid var(--brand-pink);
    border-radius: var(--radius-md);
    padding: 13px 14px 13px 12px;
    margin-bottom: 10px;
    box-shadow: 0 1px 4px rgba(17,16,19,0.05);
  }
  .data-table tbody tr:last-child { margin-bottom: 0; }
  .data-table tbody tr.row-link:active { background: #fdf5f7; }
  .data-table tbody td {
    display: block;
    border-top: none !important;
    padding: 4px 0 !important;
    white-space: normal;
    font-size: 13.5px;
    font-weight: 600;
    color: var(--text-primary);
    min-width: 0;
  }
  /* Labeled cells: small uppercase caption above the value, same visual
     language as the app's existing form-label / stat-card captions. */
  .data-table tbody td[data-label]::before {
    content: attr(data-label);
    display: block;
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-tertiary);
    margin-bottom: 2px;
  }
  /* The first labeled field (Name, Payment ID, Order, SL No — whatever the
     table's identifying column is) is the card's "title" — its own
     full-width line, bigger and bolder than the rest, with no caption
     above it (matching the Due Payments / order-card style) — instead of
     being squeezed into half the card like every other field. */
  .data-table:not(.order-cards-scope):not(.order-cards-payments) tbody td[data-label]:first-child {
    grid-column: 1 / -1;
    font-size: 15px;
    font-weight: 800;
    padding-bottom: 6px !important;
    margin-bottom: 2px;
    border-bottom: 1px solid var(--border-main);
  }
  .data-table:not(.order-cards-scope):not(.order-cards-payments) tbody td[data-label]:first-child::before {
    display: none;
  }
  /* Unlabeled cells (blank <th> columns — icon buttons, ⋮ menus, action
     links) drop their own label and instead sit together as a tidy,
     evenly-spaced action-button row under the labeled fields, separated
     by a hairline — same pattern as the Call/WhatsApp row on Due Payments. */
  .data-table tbody td:not([data-label]) {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    grid-column: 1 / -1;
    margin-top: 6px;
    padding-top: 10px !important;
    border-top: 1px dashed var(--border-main) !important;
    width: 100%;
  }
  .data-table tbody td:not([data-label]) .btn { flex: 1 1 auto; justify-content: center; }

  /* Totals row (<tfoot>, e.g. GST Reports / Quotes "Grand Total") reads
     as a single summary bar — "Total" on the left, amount on the right —
     rather than another stacked card. colspan is irrelevant once the
     row is a flex bar, so it's simply ignored. */
  .data-table tfoot { display: block; width: 100%; }
  .data-table tfoot tr {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 10px;
    padding: 12px 14px;
    margin-top: 4px;
    background: var(--bg-main);
    border: 1px solid var(--border-main);
    border-radius: var(--radius-md);
  }
  .data-table tfoot td {
    display: block;
    border: none !important;
    padding: 0 !important;
    width: auto;
    white-space: normal;
    font-weight: 700;
  }

  .card-body { overflow-x: auto; -webkit-overflow-scrolling: touch; }

  /* Forms: stack fields instead of squeezing them side by side */
  .form-input, .form-select, .form-textarea { font-size: 16px; /* prevents iOS zoom on focus */ max-width:100%; box-sizing:border-box; }
  .form-group { margin-bottom: 12px; }
  /* Force flex-based side-by-side field rows to wrap on mobile */
  .form-group + .form-group, .card-body form > div[style*="display:flex"] { flex-wrap: wrap !important; }

  /* Modals: fullscreen-ish on mobile so nothing gets cut off */
  #ticketModalOverlay, #complaintModalOverlay { padding: 10px !important; align-items: flex-start !important; }
  #ticketModalOverlay > div, #complaintModalOverlay > div { max-width: 100% !important; margin: 0; border-radius: 10px; }
  /* Ticket modal: staff-side detail view has 2 columns on desktop — collapse to 1 on mobile */
  #ticketModalOverlay div[style*="grid-template-columns"] { grid-template-columns: 1fr !important; }

  /* Chevron strip stays horizontally scrollable but doesn't push page wide */
  .chevron-strip { max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; padding-bottom: 4px; }

  /* Login screen: full-width card on mobile, better padding */
  .login-wrap { padding: 16px; }
  .login-stack { max-width: 100%; }
  .login-box { padding: 24px 20px; }
  .customer-login-card { padding: 18px 20px; }

  /* Buttons: reasonable touch targets */
  .btn { min-height: 40px; }

  /* Invoice preview: the 794px canvas scrolls INSIDE its wrapper card,
     not on the whole page. */
  #invoicePrintArea { max-width: none; }

  .topbar .btn { padding: 8px 12px; font-size: 12.5px; }

  /* Tab strip (Sabhi/Open/In Progress etc) scrolls horizontally, not overflows */
  .tab-strip { overflow-x: auto; -webkit-overflow-scrolling: touch; flex-wrap: nowrap !important; max-width: 100%; }
  .tab-btn { flex-shrink: 0; white-space: nowrap; }

  /* Any inline-styled flex row inside cards should wrap on mobile */
  .card-body div[style*="display:flex"] { flex-wrap: wrap; }

  /* ---- Mobile bottom tab bar: native app-style navigation ---- */
  .mobile-tab-bar {
    display: flex;
    position: fixed;
    left: 0; right: 0; bottom: 0;
    height: var(--tab-bar-h);
    padding-bottom: env(safe-area-inset-bottom, 0px);
    background: rgba(255,255,255,0.98);
    backdrop-filter: blur(10px);
    border-top: 1px solid var(--border-main);
    box-shadow: 0 -2px 12px rgba(0,0,0,0.06);
    z-index: 940;
  }
  .mtb-item {
    flex: 1;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 2px;
    background: none; border: none;
    color: var(--text-tertiary);
    text-decoration: none;
    font-family: inherit;
    cursor: pointer;
    padding: 6px 2px 0;
    transition: color 0.15s ease;
  }
  .mtb-icon { font-size: 19px; line-height: 1; }
  .mtb-label { font-size: 10px; font-weight: 700; line-height: 1; }
  .mtb-item.active { color: var(--brand-pink); }
  .mtb-item:active { opacity: 0.6; }

  /* Every floating action button lifts above the tab bar instead of
     sitting underneath it. */
  .fab-above-tabbar {
    bottom: calc(var(--tab-bar-h) + env(safe-area-inset-bottom, 0px) + 14px) !important;
  }
}

/* ============================================================
   Order page — Scope of Work & Payments cards get a couple of extra
   refinements beyond the generic .data-table → card conversion above
   (2-column grid instead of a plain stack, since a "Description" row
   and a "Rate | Qty" row read better than five stacked lines). Scoped
   strictly to .order-cards-scope / .order-cards-payments, which only
   exist on order_view.php, so no other page is affected.
   ============================================================ */
@media (max-width: 900px) {
  .order-cards-scope tr,
  .order-cards-payments tr {
    display: grid !important;
    grid-template-columns: 1fr 1fr;
    gap: 10px 14px;
  }

  /* ---- Scope of Work: one compact card per job row — Description on
     its own line, Rate/Qty/Unit together on a single line, Amount on
     its own prominent line (3 rows total instead of stacking every
     field separately). ---- */
  .order-cards-scope tr {
    display: grid !important;
    grid-template-columns: repeat(3, 1fr);
    gap: 10px 10px;
    padding-right: 46px;
    position: relative;
  }
  .order-cards-scope td.oc-desc,
  .order-cards-scope td.oc-amount { grid-column: 1 / -1; }
  .order-cards-scope td.oc-desc input { font-size: 14.5px !important; font-weight: 600; }
  .order-cards-scope td.oc-rate,
  .order-cards-scope td.oc-qty,
  .order-cards-scope td.oc-unit { min-width: 0; }
  .order-cards-scope td.oc-rate input,
  .order-cards-scope td.oc-qty input,
  .order-cards-scope td.oc-unit input { padding: 6px 6px !important; font-size: 12.5px !important; }
  .order-cards-scope td.oc-amount {
    border-top: 1px dashed var(--border-main);
    padding-top: 10px !important;
    margin-top: 2px;
  }
  .order-cards-scope td.oc-amount.scope-amount { font-size: 19px !important; color: var(--brand-pink); }
  .order-cards-scope td.oc-del::before { content: none; }
  .order-cards-scope td.oc-del button { padding: 7px 10px !important; border-radius: 8px; min-height: 0; }

  /* ---- Payments: one card per payment ---- */
  .order-cards-payments td.oc-pid { font-size: 14.5px; font-weight: 800; }
  .order-cards-payments td.oc-amount {
    text-align: right; font-size: 17px; font-weight: 800; color: #0f9d58;
  }
  .order-cards-payments td.oc-note,
  .order-cards-payments td.oc-date { grid-column: 1 / -1; }
  .order-cards-payments td.oc-note[data-empty="1"] { display: none; }

  /* ---- Scope of Work card, extra polish: numbered badge (01, 02, 03…)
     top-left of every card via a CSS counter — stays correct automatically
     as rows are added/removed, no JS bookkeeping needed. Small icons
     added in front of the Rate/Qty/Unit labels. An "Edit" pill next to
     the amount jumps focus to that row's description field (a real
     action, not decorative). ---- */
  .order-cards-scope tbody { counter-reset: scopeRowNum; }
  .order-cards-scope tr { counter-increment: scopeRowNum; }
  .order-cards-scope tr::before {
    content: counter(scopeRowNum, decimal-leading-zero);
    position: absolute; top: 14px; left: 14px; z-index: 1;
    width: 28px; height: 28px;
    background: linear-gradient(135deg, #a5122f, #52091d);
    color: #fff; font-size: 11px; font-weight: 800;
    border-radius: 8px;
    display: flex; align-items: center; justify-content: center;
  }
  .order-cards-scope td.oc-desc { padding-left: 38px !important; }
  .order-cards-scope td.oc-rate[data-label]::before { content: "🏷️ " attr(data-label); }
  .order-cards-scope td.oc-qty[data-label]::before { content: "📦 " attr(data-label); }
  .order-cards-scope td.oc-unit[data-label]::before { content: "📐 " attr(data-label); }
  .order-cards-scope td.oc-amount {
    display: flex !important;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
  }
  .oc-edit-jump {
    display: inline-flex !important;
    align-items: center; gap: 4px;
    border: 1.5px solid var(--brand-pink);
    color: var(--brand-pink);
    background: transparent;
    font-size: 12px; font-weight: 700;
    padding: 6px 12px;
    border-radius: 9px;
    flex-shrink: 0;
  }
  .oc-edit-jump:active { background: rgba(216,17,66,0.12); }

  /* ---- Scope of Work header: rich mobile card replaces the plain
     "X line items" text row (which stays exactly as-is on desktop). ---- */
  .scope-header-desktop { display: none !important; }
  .scope-header-mobile {
    display: block !important;
    background: var(--bg-main);
    border: 1px solid var(--border-main);
    border-radius: 12px;
    padding: 14px;
    margin-bottom: 14px;
  }
  .scope-header-mobile-top { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
  .scope-header-icon {
    width: 40px; height: 40px; border-radius: 10px; flex-shrink: 0;
    background: rgba(216,17,66,0.14); color: var(--brand-pink);
    display: flex; align-items: center; justify-content: center;
    font-size: 18px;
  }
  .scope-header-text { min-width: 0; }
  .scope-header-title { font-size: 15px; font-weight: 800; color: var(--text-primary); }
  .scope-header-sub { font-size: 12px; color: var(--text-tertiary); margin-top: 1px; }
  .scope-header-addbtn { width: 100%; justify-content: center; }

  /* ---- Below Grand Total: a compact Total Paid / Remaining Balance
     recap, matching the reference design, so the payment status is
     visible without scrolling back up to the header stat cards. ---- */
  .scope-footer-stats {
    display: grid !important;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    margin-top: 10px;
  }
  .scope-footer-stat {
    background: var(--bg-main);
    border: 1px solid var(--border-main);
    border-radius: 12px;
    padding: 12px 14px;
  }

  /* ---- Order page tab strip: single-line horizontal slider instead of
     wrapping across multiple rows — smaller, tighter tabs, swipeable. ---- */
  .order-tab-strip {
    flex-wrap: nowrap !important;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .order-tab-strip::-webkit-scrollbar { display: none; }
  .order-tab-strip a {
    padding: 7px 10px 10px !important;
    font-size: 12px !important;
    flex-shrink: 0;
  }

  /* ---- Order page header: action buttons become a clean, guaranteed
     2-column grid instead of organic flex-wrap (which could land 1, 2,
     or 3 per row depending on button-label length/screen width). ---- */
  .order-action-buttons {
    display: grid !important;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
  }
  .order-action-buttons > .badge {
    display: flex; align-items: center; justify-content: center;
    width: 100%; box-sizing: border-box;
    padding: 10px 14px; font-size: 13px; border-radius: 10px;
  }
  .order-action-buttons > a,
  .order-action-buttons > form { width: 100%; margin-left: 0 !important; }
  .order-action-buttons > form { display: block; }
  .order-action-buttons > a,
  .order-action-buttons > form > button {
    width: 100%; box-sizing: border-box;
    justify-content: center;
  }

  /* ---- Order page header: Total/Paid/Remaining/Due Date become
     individual bordered stat cards in a 2x2 grid, each with a small
     icon bottom-right, instead of plain stacked text. ---- */
  .order-stat-grid { display: grid !important; grid-template-columns: 1fr 1fr; gap: 10px; }
  .order-stat-card {
    position: relative;
    background: var(--bg-main);
    border: 1px solid var(--border-main);
    border-radius: 12px;
    padding: 14px 14px 26px;
  }
  .order-stat-card > div:nth-child(2) { font-size: 17px !important; }
  .order-stat-icon { display: block; position: absolute; bottom: 8px; right: 10px; font-size: 13px; opacity: 0.7; }

  /* ---- Order page header: phone / production-days / assignee tags
     forced onto a single line (Phone → ⏱ days → Assignee), instead of
     wrapping across 2-3 lines. Compact sizing keeps all three tags on
     one row on typical phone widths; overflow-x is a safety net for
     very narrow screens instead of ever wrapping. Desktop is untouched
     since this whole block only applies below 900px. ---- */
  .order-tags-row {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: nowrap;
    overflow-x: auto;
    max-width: 100%;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .order-tags-row::-webkit-scrollbar { display: none; }
  .order-tags-row .badge,
  .order-tags-row a {
    font-size: 11px !important;
    padding: 4px 9px !important;
    white-space: nowrap;
    flex-shrink: 0;
  }

  /* ---- Scope of Work line-item card: delete button fix. The generic
     ".data-table tbody td:not([data-label])" rule (higher CSS
     specificity than the old ".order-cards-scope td.oc-del" rule) was
     forcing width:100% onto this cell, which — combined with
     position:absolute + right:12px and no "left" — pushed the visible
     button all the way to the card's LEFT edge, overlapping the 01/02/03
     number badge. Fixing it here: the button is taken out of absolute
     positioning entirely and placed as a normal grid cell that lands in
     the empty slot next to the Unit field, directly above the Amount
     row, right-aligned — same spot every card, no overlap possible. ---- */
  .order-cards-scope tbody td.oc-del {
    position: static !important;
    grid-row: 3 !important;
    grid-column: 2 !important;
    display: flex !important;
    align-items: center !important;
    justify-content: flex-end !important;
    width: auto !important;
    margin-top: 0 !important;
    padding-top: 0 !important;
    border-top: none !important;
  }
}

/* Desktop never renders the bottom tab bar at all. */
@media (min-width: 901px) {
  .mobile-tab-bar { display: none; }
}

/* iOS-safe input font size (prevents auto-zoom-in on focus) */
@media (max-width: 900px) and (hover: none) {
  input, select, textarea { font-size: 16px !important; }
}

/* ---- Desktop: eliminate any layout shift from active state ---- */
@media (min-width: 901px) {
  .sidebar {
    /* Contain the sidebar's own repaints so hovering/clicking a nav item
       never triggers a reflow of the main content area. Fixes the "menu
       ki size chhoti-badi ho rahi" bug on desktop. */
    contain: layout style;
  }
}

/* ---- Orders workspace: view tabs ---- */
.tab-strip { display: flex; gap: 4px; border-bottom: 1px solid var(--border-main); margin-bottom: 16px; }
.tab-btn {
  padding: 10px 16px; font-size: 13.5px; font-weight: 600; color: var(--text-secondary);
  background: none; border: none; border-bottom: 2px solid transparent; cursor: pointer;
  text-decoration: none; display: inline-flex; align-items: center; gap: 6px;
  transition: color 0.16s ease, border-bottom-color 0.16s ease;
}
.tab-btn:hover { color: var(--brand-pink); }
.tab-btn.active { color: var(--brand-pink); border-bottom-color: var(--brand-pink); }

/* ---- Chevron / stage filter strip (arrow-box style) ---- */
.chevron-strip { display: flex; gap: 0; overflow-x: auto; padding-bottom: 8px; margin-bottom: 16px; }
.chevron-item {
  flex-shrink: 0; display: inline-flex; align-items: center; gap: 8px;
  padding: 9px 20px 9px 26px; font-size: 12.5px; font-weight: 700;
  border: none; cursor: pointer; text-decoration: none; white-space: nowrap;
  clip-path: polygon(0 0, calc(100% - 14px) 0, 100% 50%, calc(100% - 14px) 100%, 0 100%, 14px 50%);
  margin-left: -8px;
  transition: background-color 0.16s ease, color 0.16s ease, transform 0.16s ease;
}
.chevron-item:hover { transform: translateY(-1px); }
.chevron-item:first-child {
  clip-path: polygon(0 0, calc(100% - 14px) 0, 100% 50%, calc(100% - 14px) 100%, 0 100%);
  border-radius: 8px 0 0 8px;
  padding-left: 18px; margin-left: 0;
}
.chevron-count { background: rgba(255,255,255,0.35); border-radius: 10px; padding: 1px 7px; font-size: 11px; }
.chevron-item:not(.active) .chevron-count { background: rgba(0,0,0,0.08); }

/* ---- Fully clickable table rows (Orders etc.) ---- */
tr.row-link { cursor: pointer; transition: background 0.12s; }
tr.row-link:hover { background: #fdf5f7; }

/* ---- Kanban board (Pipeline view) ---- */
.kanban-board { display: flex; gap: 14px; overflow-x: auto; padding-bottom: 12px; align-items: flex-start; }
.kanban-col { flex: 0 0 260px; background: #f7f7f9; border-radius: var(--radius-md); overflow: hidden; }
.kanban-col-head { padding: 10px 14px; display: flex; justify-content: space-between; align-items: center; color: #fff; font-weight: 700; font-size: 13px; }
.kanban-col-count { background: rgba(255,255,255,0.3); border-radius: 10px; padding: 1px 8px; font-size: 11.5px; }
.kanban-col-body { padding: 10px; display: flex; flex-direction: column; gap: 10px; min-height: 60px; }
.kanban-empty { text-align: center; color: var(--text-tertiary); font-size: 12.5px; padding: 16px 0; }
.kanban-card { background: var(--white); border-radius: var(--radius-sm); padding: 12px; box-shadow: var(--shadow-sm); text-decoration: none; display: block; color: inherit; }
.kanban-card-title { font-size: 13px; font-weight: 700; margin-bottom: 3px; }
.kanban-card-customer { font-size: 12px; color: var(--text-secondary); margin-bottom: 6px; }
.kanban-card-foot { display: flex; justify-content: space-between; align-items: center; margin-top: 4px; }
.kanban-card-amount { font-size: 13px; font-weight: 700; }

/* ---- Progressive view (order card list) ---- */
.order-card-list { display: flex; flex-direction: column; gap: 10px; }
.order-card {
  display: flex; align-items: center; gap: 14px; background: var(--white);
  border: 1px solid var(--border-main); border-radius: var(--radius-md);
  padding: 14px 16px; text-decoration: none; color: inherit; overflow: hidden; position: relative;
}
.order-card-stagebar { position: absolute; left: 0; top: 0; bottom: 0; width: 4px; }
.order-card-main { flex: 1; min-width: 0; padding-left: 8px; }
.order-card-title { font-size: 14px; font-weight: 700; }
.order-card-sub { font-size: 12.5px; color: var(--text-secondary); margin-top: 2px; }
.order-card-money { text-align: right; flex-shrink: 0; }
.order-card-stage { flex-shrink: 0; }
.overdue-badge { display: inline-block; background: #fdeaf0; color: var(--brand-pink); font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 20px; margin-left: 6px; }

/* ---- Shared "progressive view" card, mobile only (Due Payments and the
   customer portal's Recent Orders widget both render .order-card directly
   with no separate mobile version — Orders' own list and the portal's
   full "My Orders" tab already swap to .mob-order-card on mobile instead,
   so this never touches those). On a narrow screen, cramming the
   customer/order name, an amount, and Call/WhatsApp buttons into one
   unwrapping row was overlapping once the name ran long. Title/subtitle
   now always get their own full-width row first; whatever comes after
   (amount, stage badge, action buttons) wraps cleanly onto the row below
   with room to breathe — no markup changes needed on any of the pages
   that use this component. */
@media (max-width: 900px) {
  .order-card {
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    row-gap: 10px;
  }
  .order-card-main { flex-basis: 100%; }
}

/* ---- Orders: desktop view tabs vs mobile app-style card list ----
   Desktop always shows whichever tab is selected (Table/Pipeline/
   Progressive) exactly as before. Mobile always shows the dedicated
   card list below instead, regardless of which tab is technically
   selected in the URL — a data table or kanban board just doesn't work
   on a narrow phone screen, so there's no reason to make the person
   pick "the mobile-friendly view" manually. */
.mobile-order-view { display: none; }
@media (max-width: 900px) {
  .desktop-order-view { display: none; }
  .mobile-order-view { display: flex; flex-direction: column; gap: 10px; }
}

.mob-order-card {
  background: var(--white);
  border: 1px solid var(--border-main);
  border-radius: 14px;
  padding: 14px 16px;
  cursor: pointer;
  transition: transform 0.1s ease, box-shadow 0.15s ease;
}
.mob-order-card:active { transform: scale(0.985); background: #fdfaf9; }
.mob-order-card-top { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; }
.mob-order-card-title { font-size: 15px; font-weight: 800; color: var(--text-primary); line-height: 1.3; }
.mob-order-card-meta {
  flex-shrink: 0; text-align: right; display: flex; flex-direction: column; gap: 2px;
  font-size: 11px; color: var(--text-tertiary); font-weight: 600; white-space: nowrap;
}
.mob-order-card-badges { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 8px; }
.mob-stage-badge { color: #fff; font-size: 10.5px; padding: 3px 10px; }
.mob-order-card-customer { font-size: 12px; color: var(--text-secondary); font-weight: 600; }
.mob-order-card-bottom {
  display: flex; align-items: flex-end; justify-content: space-between;
  margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--border-main);
}
.mob-order-card-amounts { display: flex; gap: 22px; }
.mob-amount-block { display: flex; flex-direction: column; gap: 2px; }
.mob-amount-label { font-size: 10.5px; color: var(--text-tertiary); font-weight: 700; text-transform: uppercase; letter-spacing: 0.3px; }
.mob-amount-value { font-size: 15px; font-weight: 800; color: var(--text-primary); }
.mob-order-card-actions { display: flex; align-items: center; gap: 4px; }
.mob-action-icon {
  width: 34px; height: 34px; border-radius: 9px;
  display: flex; align-items: center; justify-content: center;
  font-size: 15px; color: var(--text-secondary);
  background: #f7f7f9; text-decoration: none;
  transition: background 0.12s ease;
}
.mob-action-icon:active { background: #ececf0; }

/* ---- Generic desktop/mobile visibility switch, reused wherever a
   customer-portal list gets a dedicated mobile card treatment (My
   Orders, Payment History, etc) alongside its unchanged desktop version. ---- */
.portal-mobile-only { display: none; }
@media (max-width: 900px) {
  .portal-desktop-only { display: none; }
  .portal-mobile-only { display: block; }
}

/* ---- Payment History: mobile card list ---- */
.mob-payment-list { display: flex; flex-direction: column; gap: 8px; }
.mob-payment-card {
  display: flex; align-items: center; gap: 12px;
  background: var(--white); border: 1px solid var(--border-main);
  border-radius: 12px; padding: 12px 14px;
}
.mob-payment-icon {
  width: 38px; height: 38px; border-radius: 10px; flex-shrink: 0;
  background: #e7f8ee; display: flex; align-items: center; justify-content: center; font-size: 17px;
}
.mob-payment-main { flex: 1; min-width: 0; }
.mob-payment-order { font-size: 13.5px; font-weight: 800; color: var(--text-primary); }
.mob-payment-meta { font-size: 11.5px; color: var(--text-tertiary); margin-top: 1px; }
.mob-payment-amount { font-size: 14.5px; font-weight: 800; color: #0f9d58; flex-shrink: 0; }

/* ---- Staff filter select ---- */
.staff-filter-wrap { display: flex; align-items: center; gap: 6px; background: var(--white); border: 1px solid var(--border-main); border-radius: var(--radius-sm); padding: 7px 10px; }
.staff-filter-wrap select { border: none; background: transparent; font-size: 12.5px; font-weight: 600; outline: none; cursor: pointer; max-width: 170px; }

/* ---- Label Print page ---- */
.label-two-col { display:flex; gap:20px; align-items:flex-start; flex-wrap:wrap; }
.label-order-list { display:flex; flex-direction:column; gap:8px; max-width:420px; }
.label-order-row { display:flex; align-items:center; gap:12px; background:var(--white); border:1px solid var(--border-main); border-radius:10px; padding:12px 14px; cursor:pointer; }
.label-order-row.lbl-selected { border-color:var(--brand-pink); background:#fef5f7; }
.lbl-checkbox { width:18px; height:18px; border-radius:5px; border:2px solid #c9c9d1; display:flex; align-items:center; justify-content:center; flex-shrink:0; color:var(--brand-pink); }
.lbl-selected .lbl-checkbox { border-color:var(--brand-pink); background:var(--brand-pink); color:#fff; }
.lbl-info { flex:1; min-width:0; }
.lbl-order-id { font-size:11px; font-weight:800; color:var(--brand-pink); }
.lbl-order-title { font-size:13px; font-weight:700; margin-top:1px; }
.lbl-order-meta { font-size:11.5px; color:var(--text-secondary); margin-top:2px; }

.label-preview-panel { flex:1; min-width:320px; }
.lbl-pos-picker { display:grid; grid-template-columns:repeat(3,56px); gap:8px; }
.lbl-pos-cell { width:56px; height:44px; border:1px solid var(--border-main); border-radius:7px; display:flex; align-items:center; justify-content:center; font-size:12.5px; font-weight:700; color:var(--text-secondary); cursor:pointer; background:var(--white); }
.lbl-pos-cell.lbl-pos-active { background:var(--brand-pink); color:#fff; border-color:var(--brand-pink); }
.lbl-mode-btn { border:none; background:transparent; padding:5px 12px; border-radius:6px; font-size:12px; font-weight:600; color:var(--text-secondary); cursor:pointer; }
.lbl-mode-btn.lbl-mode-active { background:var(--white); color:var(--brand-pink); box-shadow:0 1px 2px rgba(0,0,0,0.1); }
.lbl-pos-adv-row { display:flex; align-items:center; gap:12px; }
.lbl-pos-adv-info { width:110px; flex-shrink:0; }
.lbl-pos-adv-id { font-size:10.5px; font-weight:800; color:var(--brand-pink); }
.lbl-pos-adv-title { font-size:11.5px; font-weight:600; }
.lbl-pos-adv-mini-picker { display:grid; grid-template-columns:repeat(9,22px); gap:3px; }
.lbl-pos-adv-mini-cell { width:22px; height:18px; border:1px solid var(--border-main); border-radius:3px; font-size:8.5px; display:flex; align-items:center; justify-content:center; cursor:pointer; color:var(--text-tertiary); }
.lbl-pos-adv-mini-cell.lbl-pos-active { background:var(--brand-pink); color:#fff; border-color:var(--brand-pink); }
.lbl-pos-adv-mini-cell.lbl-pos-taken { background:#eee; cursor:not-allowed; }

.lbl-preview-sheet { display:flex; flex-wrap:wrap; gap:14px; }
.lbl-empty-preview { color:var(--text-tertiary); font-size:13px; padding:30px; text-align:center; width:100%; }

/* ---- Label design (matches reference SS: black rounded top bar) ---- */
.lbl-item {
  width: 240px;
  height: 175px;
  border: 1.5px solid #1a1a1f;
  border-radius: 10px;
  background: #fff;
  font-family: 'Inter', sans-serif;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
}
.lbl-brand-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  background: #1a1a1f;
  color: #fff;
  padding: 5px 12px;
  border-radius: 8px 8px 0 0;
}
.lbl-brand-name { font-size: 10.5px; font-weight: 800; letter-spacing: 0.6px; color: #fff; }
.lbl-ord-badge {
  background: #fff; color: #1a1a1f;
  font-size: 10px; font-weight: 800;
  padding: 2px 8px; border-radius: 100px;
  letter-spacing: 0.3px;
}
.lbl-ord-badge b { color: #ff2d62; }
.lbl-body { padding: 6px 12px 4px; flex: 1; display: flex; flex-direction: column; }
.lbl-tag { font-size: 8.5px; color: #1a1a1f; font-weight: 700; text-transform: uppercase; margin-right: 4px; letter-spacing: 0.2px; }
.lbl-row-client { font-size: 11px; margin-bottom: 3px; }
.lbl-client-name { font-weight: 800; font-size: 11.5px; }
.lbl-row-job { font-size: 10.5px; margin-bottom: 6px; color: #444; }
.lbl-row-job .lbl-tag { color: #ff2d62; }
.lbl-row-job b { color: #1a1a1f; font-weight: 700; }
.lbl-stats-row { display: flex; justify-content: space-between; gap: 6px; margin-top: auto; padding-bottom: 4px; }
.lbl-stat { flex: 1; }
.lbl-stat-label { font-size: 8px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.4px; color: #1a1a1f; }
.lbl-stat-order .lbl-stat-label { color: #2284e6; }
.lbl-stat-due .lbl-stat-label { color: #d81142; }
.lbl-stat-value { font-size: 10px; font-weight: 800; color: #1a1a1f; }
.lbl-stat-date { font-size: 10px; font-weight: 800; }
.lbl-urgent-dot { display: inline-block; width: 5px; height: 5px; border-radius: 50%; background: #d81142; margin-right: 2px; vertical-align: middle; }
.lbl-urgent-text { color: #d81142; font-weight: 800; font-size: 8px; }
.lbl-barcode-wrap { text-align: center; background: #fff; padding: 4px 8px 4px; margin: 0 -12px; border-top: 1px dashed #c9c9d1; }
.lbl-barcode-wrap svg { max-width: 100%; height: 30px; }
.lbl-batch-code { font-size: 7px; color: #666; letter-spacing: 0.3px; margin-top: 1px; font-weight: 700; }

/* ---- Live Progress stepper (Customer Portal + public order tracking) ---- */
.stepper { display: flex; align-items: flex-start; overflow-x: auto; padding: 10px 4px 4px; margin-top: -10px; -webkit-overflow-scrolling: touch; }
.stepper-node { display: flex; flex-direction: column; align-items: center; flex-shrink: 0; width: 64px; }
.stepper-circle {
  width: 26px; height: 26px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-size: 11px; font-weight: 800; flex-shrink: 0;
}
.stepper-label { font-size: 9px; font-weight: 600; color: var(--text-secondary); text-align: center; margin-top: 5px; line-height: 1.25; padding: 0 2px; }
.stepper-line { height: 2px; background: #d9d9e0; flex: 1; margin-top: 13px; min-width: 14px; }
.stepper-line.done { background: #0f9d58; }
@media (max-width: 640px) {
  .stepper-node { width: 52px; }
  .stepper-label { font-size: 8.5px; }
}
/* ================ Reusable Modal System ================ */
/* Matches the Ticket modal's design exactly — dimmed backdrop, centered
   white card, rounded corners, header with title + X, scrollable body.
   Used for New Ticket, Add Payment, Upload File, Add Party, Membership
   Card, and any future "action" page that should pop up over its list
   instead of navigating to a whole new page. */
.modal-overlay {
  display: flex; position: fixed; inset: 0;
  background: rgba(20,20,25,0.55);
  /* Comfortably above every fixed piece of app chrome (masthead/topbar/
     sidebar drawer/tab bar/toasts all sit at 1200 or below) so the
     backdrop always dims the whole screen, with room to spare below the
     image lightbox (2000) which should still be able to layer on top of
     an open modal. */
  z-index: 1500;
  align-items: flex-start; justify-content: center;
  padding: 30px 20px; overflow-y: auto;
}
.modal-box {
  background: #fff; border-radius: 14px; width: 100%;
  box-shadow: 0 20px 60px rgba(0,0,0,0.3);
}
.modal-box.modal-sm { max-width: 480px; }
.modal-box.modal-md { max-width: 600px; }
.modal-box.modal-lg { max-width: 780px; }
.modal-box.modal-xl { max-width: 920px; }
.modal-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 20px 24px; border-bottom: 1px solid var(--border-main);
}
.modal-header h3 { margin: 0; font-size: 17px; font-weight: 800; }
.modal-close {
  background: none; border: none; font-size: 22px; cursor: pointer;
  color: var(--text-tertiary); line-height: 1;
  width: 32px; height: 32px; border-radius: 8px;
  display: inline-flex; align-items: center; justify-content: center;
  transition: color 0.16s ease, background-color 0.16s ease, transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.modal-close:hover { color: var(--brand-pink); background: #fdeaf0; transform: rotate(90deg); }
.modal-body { padding: 20px 24px; }
.modal-footer {
  display: flex; gap: 10px; margin-top: 18px; padding-top: 16px;
  border-top: 1px solid var(--border-main);
}
@media (max-width: 640px) {
  .modal-overlay { padding: 10px; align-items: flex-start; }
  .modal-box { max-width: 100% !important; margin: 0; border-radius: 10px; }
}

/* ================ Mobile "App Page" modals ================
   Opt-in only: add class "app-fullpage-modal" to a .modal-overlay
   wrapper (New Order, New Quotation, Add/Edit Party, Measurement
   Entry currently use it). On phones it turns that one modal into
   a real fixed full-screen page with a slide-in-from-right motion,
   sticky header/footer and safe-area support — the way a native
   app screen behaves — while every OTHER modal on the site
   (delete confirms, notifications, quick-add dialogs, etc.) is
   completely unaffected since they never get this class. Desktop
   is untouched too: all of this lives inside max-width:900px,
   matching the same breakpoint the rest of the app already uses
   to detect "mobile" (masthead switch, recycle-bin FAB, etc). */
@media (max-width: 900px) {
  .modal-overlay.app-fullpage-modal {
    position: fixed;
    inset: 0;
    height: 100dvh;
    padding: 0;
    align-items: stretch;
    justify-content: stretch;
    overflow: hidden;
    background: var(--bg-main);
    animation: appPageSlideIn 0.32s cubic-bezier(0.22, 1, 0.36, 1) both;
  }
  .modal-overlay.app-fullpage-modal .modal-box {
    width: 100%;
    max-width: 100% !important;
    height: 100%;
    margin: 0;
    border-radius: 0;
    box-shadow: none;
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }
  .modal-overlay.app-fullpage-modal .modal-header {
    flex: 0 0 auto;
    position: sticky;
    top: 0;
    z-index: 2;
    padding: max(14px, env(safe-area-inset-top)) 18px 14px;
    background: var(--white);
  }
  .modal-overlay.app-fullpage-modal .modal-body {
    flex: 1 1 auto;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding: 16px 18px calc(16px + env(safe-area-inset-bottom));
  }
  .modal-overlay.app-fullpage-modal .modal-footer {
    flex: 0 0 auto;
    position: sticky;
    bottom: 0;
    margin-top: 0;
    padding: 12px 18px calc(12px + env(safe-area-inset-bottom));
    background: var(--white);
    z-index: 2;
  }
  .modal-overlay.app-fullpage-modal .modal-close {
    width: 38px;
    height: 38px;
  }
  body.dark-mode .modal-overlay.app-fullpage-modal { background: var(--bg-main); }
  body.dark-mode .modal-overlay.app-fullpage-modal .modal-header,
  body.dark-mode .modal-overlay.app-fullpage-modal .modal-footer { background: var(--white); }
}
@keyframes appPageSlideIn {
  from { transform: translateX(100%); }
  to   { transform: translateX(0); }
}
@media (prefers-reduced-motion: reduce) {
  .modal-overlay.app-fullpage-modal { animation: none; }
}

/* ================ App-page modal HEADER — maroon banner  (v216, v217) ================
   New Order Entry / New Quotation / Add-Edit Party / New Measurement /
   Add Payment — inn sabka header ab plain white patti nahi, balki
   ".grand-total-banner" jaisa hi maroon gradient hai. Title text/PHP
   markup me koi badlaav nahi — ye sirf styling hai.

   v217 REFINEMENT: pehle ek chhota blinking ✦ tha — ab uski jagah app
   ki apni already-established "premium glass shine" language use ki
   hai (wahi jo Membership badge par continuous diagonal sweep karti
   hai — `membershipGlassShine` keyframe, isi file me thodi upar
   defined). Ek poori patti par halki roshni guzarti hai, har ~4
   second me ek baar — zyada refined/professional motion, ek jagah
   blink karte star se. Sath me: thoda depth (soft shadow neeche),
   title par halka text-shadow, aur close (×) button ab hamesha ek
   halka glass circle ke saath dikhta hai (sirf hover par nahi) taaki
   maroon par saaf tarike se dikhe.

   Desktop AUR mobile app — dono par, isliye is baar JAAN-BOOJH KAR
   koi @media guard nahi hai. Dark mode me bhi grand-total-banner ki
   tarah hamesha yehi maroon rehta hai (themed maroon banners is app
   me kabhi dark-mode se badalte nahi, jaan-boojh kar). */
.modal-overlay.app-fullpage-modal .modal-header {
  overflow: hidden;
  isolation: isolate;
  background: linear-gradient(135deg, #b0102e 0%, #7d0e28 55%, #52091d 100%) !important;
  border-bottom: none !important;
  box-shadow: 0 4px 16px rgba(82,9,29,0.35);
}
/* Desktop par header ka apna `position` set nahi tha (static) — decorative
   pattern + shine sweep ko sahi se andar rakhne ke liye positioning
   context chahiye, isliye sirf desktop ke liye `position:relative` diya
   hai. Mobile ko bilkul nahi chheda — wahan header pehle se hi
   `position:sticky` hai (isi file me @media max-width:900px ke andar,
   thodi upar). Dono rule ek hi selector par hain (same specificity),
   isliye agar yahan bhi bina @media ke `position:relative` de dete, to
   source-order ki wajah se woh mobile ka `sticky` overwrite kar deta
   aur header scroll ke saath upar chipakna band ho jaata — isliye
   jaan-boojh kar sirf desktop tak seemit rakha hai. */
@media (min-width: 901px) {
  .modal-overlay.app-fullpage-modal .modal-header { position: relative; }
}
.modal-overlay.app-fullpage-modal .modal-header::before {
  content: '';
  position: absolute; inset: 0;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='420' height='220' viewBox='0 0 420 220'%3E%3Cpath d='M0,140 C110,90 210,175 420,70' stroke='rgba(255,255,255,0.14)' stroke-width='2' fill='none'/%3E%3Cpath d='M20,170 C130,115 230,195 420,110' stroke='rgba(255,255,255,0.09)' stroke-width='2' fill='none'/%3E%3Cpath d='M60,200 C160,150 260,215 420,150' stroke='rgba(255,80,120,0.22)' stroke-width='2' fill='none'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: bottom right;
  background-size: min(55%, 240px) auto;
  pointer-events: none;
  z-index: 1;
}
/* Motion — Membership badge wala hi continuous glass-shine sweep,
   reused (poori patti par ek halki roshni guzarti hai, loop me). */
.modal-overlay.app-fullpage-modal .modal-header::after {
  content: '';
  position: absolute;
  top: 0; left: 0;
  width: 45%; height: 100%;
  background: linear-gradient(115deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0.32) 45%, rgba(255,255,255,0.04) 65%, rgba(255,255,255,0) 100%);
  transform: translateX(-290%) skewX(-20deg);
  animation: membershipGlassShine 4s ease-in-out infinite;
  animation-delay: 0.8s;
  pointer-events: none;
  z-index: 1;
  will-change: transform;
  backface-visibility: hidden;
}
@media (prefers-reduced-motion: reduce) {
  .modal-overlay.app-fullpage-modal .modal-header::after { animation: none; opacity: 0; }
}
/* Header ke andar jo bhi ho (title, close button, ya quotes.php jaisa
   koi extra "AI Se Bharo" button) — sab hamesha decorative pattern +
   shine sweep ke UPAR render ho, isliye ek general rule (sirf h3/close
   specific nahi) — taaki koi bhi future/existing header-button chhoot
   na jaaye. */
.modal-overlay.app-fullpage-modal .modal-header > * {
  position: relative;
  z-index: 2;
}
.modal-overlay.app-fullpage-modal .modal-header h3 {
  color: #fff !important;
  letter-spacing: 0.2px;
  text-shadow: 0 1px 3px rgba(0,0,0,0.22);
}
.modal-overlay.app-fullpage-modal .modal-close {
  color: rgba(255,255,255,0.92) !important;
  background: rgba(255,255,255,0.14) !important;
}
.modal-overlay.app-fullpage-modal .modal-close:hover {
  color: #fff !important;
  background: rgba(255,255,255,0.26) !important;
}
body.dark-mode .modal-overlay.app-fullpage-modal .modal-header {
  background: linear-gradient(135deg, #b0102e 0%, #7d0e28 55%, #52091d 100%) !important;
}

/* ================ Advance Carry Forward card  (v220) ================
   Order View par wo card jo batata hai ki is customer ka advance kisi
   dusre order par pada hai (aur use is order me adjust karne deta hai),
   ya ye ki advance kahan se aaya / kahan chala gaya.

   Visual language jaan-boojh kar "money/green" rakhi hai — app me
   Paid/Advance hamesha green (#0f9d58) hai, aur ye card usi baare me
   hai. Privacy Note box ki tarah iske apne real CSS classes hain (koi
   hardcoded inline hex nahi), isliye dark mode me bhi theek dikhta hai. */
.adv-carry-card {
  border-left: 3px solid #0f9d58;
  background: rgba(15, 157, 88, 0.045);
}
.adv-carry-head {
  display: flex; align-items: flex-start; gap: 12px;
  margin-bottom: 14px;
}
.adv-carry-ico {
  font-size: 22px; line-height: 1;
  flex-shrink: 0;
}
.adv-carry-title {
  font-size: 14.5px; font-weight: 800;
  color: var(--text-primary);
}
.adv-carry-sub {
  font-size: 12.5px; color: var(--text-secondary);
  margin-top: 3px; line-height: 1.45;
}
.adv-carry-row {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 12px 14px;
  background: var(--white);
  border: 1px solid var(--border-main);
  border-radius: var(--radius-md);
  margin-bottom: 10px;
}
.adv-carry-row:last-child { margin-bottom: 0; }
.adv-carry-row-main { flex: 1; min-width: 180px; }
.adv-carry-oid {
  font-size: 13px; font-weight: 800;
  color: var(--brand-pink); text-decoration: none;
}
.adv-carry-oid:hover { text-decoration: underline; }
.adv-carry-otitle {
  font-size: 12.5px; color: var(--text-secondary);
  margin-left: 8px;
}
.adv-carry-amt {
  font-size: 13px; margin-top: 4px; color: var(--text-secondary);
}
.adv-carry-amt strong { color: #0f9d58; font-size: 15px; font-weight: 800; }
.adv-carry-actions {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.adv-carry-inline {
  display: flex; align-items: center; gap: 5px;
  font-size: 13px; font-weight: 700; color: var(--text-secondary);
}
.adv-carry-input {
  width: 108px !important;
  padding: 7px 9px !important;
  font-size: 13.5px !important;
  text-align: right;
}
.adv-carry-btn {
  padding: 8px 14px !important;
  font-size: 13px !important;
  white-space: nowrap;
}
.adv-carry-applied { margin-top: 10px; }
.adv-carry-row-done { background: rgba(15, 157, 88, 0.06); }
.adv-carry-done-line {
  font-size: 13px; font-weight: 600; line-height: 1.5;
  color: var(--text-primary);
}
.adv-carry-done-line strong { color: #0f9d58; font-weight: 800; }
.adv-carry-when {
  font-size: 11.5px; color: var(--text-tertiary); margin-top: 3px;
}
.adv-carry-muted {
  font-size: 12.5px; color: var(--text-secondary);
  padding: 10px 12px;
  background: var(--white);
  border: 1px dashed var(--border-main);
  border-radius: var(--radius-md);
  line-height: 1.5;
}
body.dark-mode .adv-carry-card { background: rgba(15, 157, 88, 0.09); }
body.dark-mode .adv-carry-row-done { background: rgba(15, 157, 88, 0.12); }

/* Mobile: har cheez apni poori chaudai le — buttons pass-pass squeeze
   hokar chhote na ho jayein (app ke baaki mobile action rows jaisa hi). */
@media (max-width: 900px) {
  .adv-carry-row { align-items: stretch; flex-direction: column; gap: 10px; }
  .adv-carry-actions { width: 100%; }
  .adv-carry-inline { flex: 1; min-width: 90px; }
  .adv-carry-input { width: 100% !important; font-size: 16px !important; }
  .adv-carry-actions .adv-carry-btn { flex: 1; justify-content: center; }
  .adv-carry-otitle { display: block; margin-left: 0; margin-top: 2px; }
}

/* ================ Flash message auto-hide  (v221) ================
   "Order update ho gaya" jaisi flash patti ~3 second baad apne aap
   fade + collapse hokar hat jaati hai (assets/js/flash-autohide.js).
   Sirf `.alert-flash-autohide` wale alerts par — baaki sab alerts
   pehle jaise permanent hi rehte hain.

   Yahan sirf transition define hai; jab tak JS `alert-flash-hiding`
   class nahi lagata tab tak alert bilkul normal dikhta hai. Matlab
   agar JS kisi wajah se load hi na ho, to alert pehle jaisa hi
   screen par rehta hai — kuch tootta nahi. */
.alert-flash-autohide {
  transition: opacity 400ms ease,
              height 400ms ease,
              margin 400ms ease,
              padding 400ms ease;
}
.alert-flash-autohide.alert-flash-hiding {
  opacity: 0;
  height: 0 !important;
  margin-top: 0 !important;
  margin-bottom: 0 !important;
  padding-top: 0 !important;
  padding-bottom: 0 !important;
  border-width: 0 !important;
}
@media (prefers-reduced-motion: reduce) {
  .alert-flash-autohide { transition: none; }
}

/* ============ Popup khule ya band — peeche kuch bhi na hile  (v229, v231) ============
   DIKKAT: New Order jaisa koi popup khulte/band hote waqt peeche wala
   page halka sa hil jaata tha.

   WAJAH: app ka masthead aur topbar `position: fixed; left:0; right:0`
   hain — inki chaudai viewport ki CLIENT width se aati hai, yaani
   scrollbar ki jagah nikaal kar. Jis pal scrollbar aata/jaata hai, us
   pal ye dono (aur page ka content bhi) ~15px chaude/patle ho jaate
   hain. Bas yehi halchal thi.

   v229 me `scrollbar-gutter: stable` use kiya tha. Wo theek tha PAR
   adhoora nikla — us property ka asar tabhi hota hai jab element ka
   overflow `auto`/`scroll` ho. Jaise hi humne lock ke liye
   `overflow: hidden` lagaya, gutter khud hi gayab ho gaya aur shift
   phir se ho gaya. Isliye ab do pakke tareeke:

   1. `overflow-y: scroll` — scrollbar ki patti HAMESHA dikhti hai,
      chahe page chhota ho ya bada, chahe modal khula ho ya band.
      Chaudai kabhi badalti hi nahi. Ye purana, har browser me kaam
      karne wala tareeka hai — koi support ki shart nahi.
      (`@media screen` me hai, isliye Invoice/Label print par asar nahi.)

   2. Lock ke liye ab `overflow: hidden` NAHI — balki body ko
      `position: fixed` kar dete hain. Isse page scroll to ruk jaata
      hai, par upar wali scrollbar patti apni jagah bani rehti hai —
      matlab chaudai phir bhi nahi badalti.

      JS (assets/js/modal-scroll-lock.js) lock se pehle scroll position
      yaad rakhta hai aur `top` me daal deta hai, taaki page apni jagah
      par hi dikhta rahe (warna wo upar kood jaata). Modal band hote hi
      wahi position wapas set kar deta hai — user ko lagta hai kuch hua
      hi nahi.

   Masthead/topbar/tab-bar/FAB sab `position: fixed` hain, yaani body ke
   fixed hone se unpar koi asar nahi padta — wo jahan the wahin rehte
   hain. */
@media screen { html { overflow-y: scroll; } }

body.modal-lock {
  position: fixed;
  left: 0;
  right: 0;
  width: 100%;
}

/* ============ Measurement sizes — labelled grid cards  (v240) ============
   Order Details ke Measurements tab me pehle har size sirf ek line me
   "37 × 52 in" likha aata tha. Dekhne wale ko pata hi nahi chalta tha ki
   37 WIDTH hai ya HEIGHT — aur print/production me yehi galti mehngi
   padti hai.

   Ab har size ek chhota card hai jisme Width aur Height apne-apne label
   ke saath alag-alag dikhte hain. Saari sizes ek grid me aati hain, jo
   jagah ke hisaab se apne aap column banata hai — desktop ki chaudi
   screen par 3-4 sizes ek line me, tablet par 2, phone par 1-2. Isse
   daayen-baayen ki khaali jagah bhi kaam aati hai aur 10-12 sizes wali
   sheet bhi ek nazar me padhi ja sakti hai.

   Desktop aur mobile dono ke liye — koi @media guard nahi, kyunki grid
   khud hi jagah ke hisaab se adjust ho jaata hai. */
.ms-size-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: 10px;
  margin-top: 4px;
}
.ms-size-card {
  border: 1px solid var(--border-main);
  border-left: 3px solid var(--brand-pink);
  border-radius: 12px;
  padding: 11px 12px;
  background: var(--white);
}
.ms-size-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 9px;
}
.ms-size-num {
  flex-shrink: 0;
  width: 22px; height: 22px;
  border-radius: 50%;
  background: linear-gradient(135deg, #b0102e 0%, #7d0e28 100%);
  color: #fff;
  font-size: 9.5px; font-weight: 800;
  display: inline-flex; align-items: center; justify-content: center;
}
.ms-size-label {
  flex: 1; min-width: 0;
  font-size: 13px; font-weight: 800;
  color: var(--text-primary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ms-size-thumb {
  width: 30px; height: 30px; flex-shrink: 0;
  object-fit: cover; border-radius: 7px;
  border: 1px solid var(--border-main);
  cursor: pointer;
}
.ms-size-dims {
  display: flex;
  align-items: flex-end;
  gap: 8px;
}
.ms-size-dim {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; gap: 2px;
  background: rgba(216,17,66,0.04);
  border-radius: 9px;
  padding: 7px 9px;
}
.ms-size-dim-key {
  font-size: 8.5px; font-weight: 800;
  letter-spacing: 0.5px; text-transform: uppercase;
  color: var(--text-tertiary);
}
.ms-size-dim-val {
  font-size: 16px; font-weight: 800;
  color: var(--text-primary);
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.ms-size-dim-val small {
  font-size: 10px; font-weight: 700;
  color: var(--text-secondary);
  margin-left: 3px;
}
.ms-size-x {
  flex-shrink: 0;
  font-size: 12px; font-weight: 700;
  color: var(--text-tertiary);
  padding-bottom: 9px;
}
body.dark-mode .ms-size-dim { background: rgba(216,17,66,0.10); }

/* ============ Measurement draft note  (v242) ============
   Jab adhoora bhara hua form wapas laaya jaata hai, uske upar ye chhoti
   patti dikhti hai — taaki user ko pata rahe ki ye purana draft hai,
   aur wo chahe to ek click me hata sake. */
.meas-draft-note {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  background: #fff8e6;
  border: 1px solid #f3dca6;
  color: #8a6100;
  border-radius: 10px;
  padding: 9px 12px;
  font-size: 12.5px;
  line-height: 1.45;
  margin-bottom: 14px;
}
.meas-draft-note strong { color: #6d4c00; }
.meas-draft-discard {
  margin-left: auto;
  background: rgba(138,97,0,0.10);
  border: 1px solid rgba(138,97,0,0.28);
  color: #6d4c00;
  font-size: 11.5px;
  font-weight: 700;
  padding: 5px 12px;
  border-radius: 8px;
  cursor: pointer;
  white-space: nowrap;
}
.meas-draft-discard:hover { background: rgba(138,97,0,0.18); }
body.dark-mode .meas-draft-note {
  background: rgba(243,220,166,0.12);
  border-color: rgba(243,220,166,0.30);
  color: #f0d9a0;
}
body.dark-mode .meas-draft-note strong { color: #ffe9b8; }
body.dark-mode .meas-draft-discard { color: #f0d9a0; }

/* ============ Inquiry (public form) — staff side  (v243) ============ */
.inq-badge {
  display: inline-block;
  font-size: 9.5px; font-weight: 800;
  letter-spacing: 0.3px;
  padding: 2px 7px;
  border-radius: 999px;
  background: rgba(75,162,243,0.14);
  color: #2a6fb0;
  vertical-align: middle;
  margin-left: 5px;
  white-space: nowrap;
}
/* Abhi confirm nahi hui — amber, taaki nazar me aa jaaye */
.inq-badge-new { background: rgba(240,160,20,0.16); color: #9a6400; }
/* Reject ho chuki — neutral grey, "dead" feel taaki confuse na ho ki ye active hai */
.inq-badge-rejected { background: rgba(60,60,67,0.14); color: #3c3c43; }

/* v253: content card ki baayi deewar se chipak raha tha. Wajah — is
   card par 3px ka accent border laga hai, jo card ki apni padding ke
   ANDAR se jagah kha jaata tha, aur text bilkul kinare aa jaata.
   Thodi extra padding de kar text ko saans dene ki jagah di. */
.inq-panel {
  border-left: 3px solid #4ba2f3;
  padding-left: 16px;
  padding-right: 16px;
}
.inq-panel-new { border-left-color: #f0a014; background: rgba(240,160,20,0.035); }
.inq-panel-rejected { border-left-color: #8a8a92; background: rgba(60,60,67,0.03); }
.inq-panel-rejreason { color: var(--brand-pink); font-style: italic; }
.inq-panel-head { display: flex; align-items: flex-start; gap: 11px; margin-bottom: 12px; flex-wrap: wrap; }
.inq-panel-back {
  margin-left: auto;
  flex-shrink: 0;
  font-size: 11.5px; font-weight: 700;
  color: var(--brand-pink);
  text-decoration: none;
  background: rgba(216,17,66,0.08);
  padding: 5px 11px;
  border-radius: 100px;
  white-space: nowrap;
}
.inq-panel-ico { font-size: 20px; line-height: 1; flex-shrink: 0; }
.inq-panel-title { font-size: 14px; font-weight: 800; color: var(--text-primary); }
.inq-panel-sub { font-size: 11.5px; color: var(--text-secondary); margin-top: 2px; }

.inq-panel-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 9px 12px;
}
.inq-panel-grid > div { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.inq-panel-grid span {
  font-size: 8.5px; font-weight: 800;
  letter-spacing: 0.5px; text-transform: uppercase;
  color: var(--text-tertiary);
}
.inq-panel-grid strong {
  font-size: 13px; font-weight: 700;
  color: var(--text-primary);
  overflow: hidden; text-overflow: ellipsis;
}
.inq-panel-grid strong a { color: var(--brand-pink); text-decoration: none; }

.inq-panel-msg {
  margin-top: 11px;
  padding: 10px 12px;
  background: var(--white);
  border: 1px solid var(--border-main);
  border-radius: 10px;
  font-size: 13px; line-height: 1.55;
  color: var(--text-primary);
  white-space: pre-wrap;
}
.inq-panel-photo {
  margin-top: 11px;
  max-width: 160px; width: 100%;
  border-radius: 10px;
  border: 1px solid var(--border-main);
  cursor: pointer;
  display: block;
}

/* Settings page ka switch-style checkbox */
.inq-switch {
  display: flex; align-items: flex-start; gap: 10px;
  font-size: 13px; line-height: 1.45;
  cursor: pointer;
}
.inq-switch input { margin-top: 3px; width: 17px; height: 17px; flex-shrink: 0; cursor: pointer; }

/* Inquiry QR codes (v246) */
.inq-qr-row { display: flex; gap: 16px; flex-wrap: wrap; }
.inq-qr-box {
  text-align: center;
  padding: 12px;
  border: 1px solid var(--border-main);
  border-radius: 12px;
  background: var(--white);
}
.inq-qr-box img, .inq-qr-box canvas { display: block; margin: 0 auto; }
.inq-qr-cap {
  margin-top: 8px;
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.3px;
  color: var(--text-secondary);
}

/* ============ Inquiry Inbox  (v251) ============
   Ek focused triage screen — Orders me se dhoondh kar kholne ki
   zaroorat nahi. Card-grid khud jagah ke hisaab se column banaata
   hai (desktop par 2, tablet par 1-2), isliye mobile ke liye alag
   CSS nahi likhni padi — sirf mobile-polish.css me thodi spacing
   tight ki gayi hai. */
.inbx-hint {
  background: rgba(75,162,243,0.07);
  border: 1px solid rgba(75,162,243,0.28);
  color: var(--text-secondary);
  font-size: 12.5px;
  line-height: 1.6;
}
.inbx-hint strong { color: var(--text-primary); }
.inbx-toolbar {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  justify-content: space-between;
}
.inbx-search { display: flex; gap: 8px; flex: 1; min-width: 240px; max-width: 380px; }
.inbx-search .form-input { flex: 1; }
.inbx-tabs { display: flex; gap: 8px; }
.inbx-tab {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 14px;
  border-radius: 100px;
  background: #f2f2f5;
  color: var(--text-secondary);
  font-size: 12.5px; font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
}
.inbx-tab.on { background: var(--brand-pink); color: #fff; }
.inbx-tab-count {
  background: rgba(255,255,255,0.28);
  border-radius: 100px;
  padding: 1px 7px;
  font-size: 11px; font-weight: 800;
}
.inbx-tab:not(.on) .inbx-tab-count { background: rgba(216,17,66,0.14); color: var(--brand-pink); }
.inbx-tab:not(.on) .inbx-tab-count-rej { background: rgba(60,60,67,0.14); color: #3c3c43; }

.inbx-empty { text-align: center; padding: 40px 20px; }
.inbx-empty-ico { font-size: 42px; line-height: 1; margin-bottom: 10px; }
.inbx-empty h3 { margin: 0 0 6px; font-size: 16px; }
.inbx-empty p { margin: 0; font-size: 13px; color: var(--text-secondary); max-width: 340px; margin: 0 auto; }

.inbx-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
  gap: 12px;
}
.inbx-card {
  background: var(--white);
  border: 1px solid var(--border-main);
  border-left: 3px solid var(--border-main);
  border-radius: 14px;
  padding: 14px 15px;
}
.inbx-card-new { border-left-color: #f0a014; background: rgba(240,160,20,0.03); }
.inbx-card-old { border-left-color: var(--brand-pink); background: rgba(216,17,66,0.03); }
.inbx-card-rejected { border-left-color: #8a8a92; background: rgba(60,60,67,0.03); opacity: 0.85; }
.inbx-card-rejreason { color: var(--brand-pink); font-style: italic; }

.inbx-card-top { display: flex; align-items: flex-start; gap: 11px; margin-bottom: 8px; }
.inbx-card-av {
  flex-shrink: 0;
  width: 38px; height: 38px;
  border-radius: 50%;
  background: linear-gradient(135deg, #b0102e 0%, #7d0e28 100%);
  color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-size: 15px; font-weight: 800;
}
.inbx-card-id { min-width: 0; flex: 1; }
.inbx-card-name {
  font-size: 14.5px; font-weight: 800;
  color: var(--text-primary);
  display: flex; align-items: center; gap: 7px; flex-wrap: wrap;
}
.inbx-badge {
  font-size: 9px; font-weight: 800;
  letter-spacing: 0.3px;
  padding: 2px 8px;
  border-radius: 999px;
  background: rgba(15,157,88,0.12);
  color: #0f9d58;
  white-space: nowrap;
}
.inbx-badge-new { background: rgba(240,160,20,0.16); color: #9a6400; }
.inbx-card-old .inbx-badge-new { background: rgba(216,17,66,0.14); color: var(--brand-pink); }
.inbx-badge-rejected { background: rgba(60,60,67,0.14); color: #3c3c43; }
.inbx-card-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 5px 8px;
  font-size: 11.5px;
  color: var(--text-secondary);
  margin-top: 4px;
  line-height: 1.4;
}
.inbx-meta-item { white-space: nowrap; }
.inbx-meta-dot { opacity: 0.4; }

.inbx-card-msg {
  font-size: 12.5px; line-height: 1.5;
  color: var(--text-primary);
  background: var(--bg-main);
  border-radius: 9px;
  padding: 8px 10px;
  margin-bottom: 10px;
}

.inbx-card-actions { display: flex; gap: 7px; flex-wrap: wrap; align-items: stretch; }
.inbx-act {
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px;
  border-radius: 10px;
  font-size: 16px;
  text-decoration: none;
  flex-shrink: 0;
}
.inbx-act-call { background: rgba(75,162,243,0.12); }
.inbx-act-wa { background: rgba(37,211,102,0.14); }
/* v359: toned down from a solid saturated green fill to the same
   soft-tint pill style as the rest of the action bar — one click
   still stands out as "the button that creates the customer + order",
   but a whole row of solid-colored blocks read as cluttered. */
.inbx-act-confirm-wa {
  background: rgba(37,211,102,0.12) !important;
  color: #128a43 !important;
  font-weight: 800 !important;
  border: 1px solid rgba(37,211,102,0.28);
  box-shadow: none !important;
}
.inbx-act-confirm-wa:hover:not(:disabled) { background: rgba(37,211,102,0.20) !important; }
/* Branded estimate (the WhatsApp PDF share) — matches the estimate
   page's orange accent, same soft-tint pill treatment. */
.inbx-act-estimate {
  background: rgba(245,129,15,0.10) !important;
  color: #d9660a !important;
  font-weight: 800 !important;
  border: 1px solid rgba(245,129,15,0.26);
}
.inbx-act-estimate:hover:not(:disabled) { background: rgba(245,129,15,0.18) !important; }
/* v259: mobile par Call/WhatsApp ke saath naam bhi dikhta hai (neeche
   mobile-polish.css me on karte hain) — desktop par icon-only compact
   square hi rehta hai, isliye label yahan default se hidden hai. */
.inbx-act-label { display: none; }
.inbx-act-form { display: contents; }
.inbx-act-btn { padding: 8px 12px !important; font-size: 12px !important; white-space: nowrap; }
/* v262: Confirm/Reject ab DOM me sabse pehle aate hain (upar), Call/
   WhatsApp/Customer banayein/Order ek "bottom row" wrapper me. Desktop
   par ye do wrapper `display:contents` se "invisible" rehte hain —
   yaani unke andar ke button seedhe .inbx-card-actions/.inbx-detail-actions
   ke hi flex-child ban jaate hain, jaisa pehle tha (sirf order badla,
   layout wahi). Mobile par neeche (mobile-polish.css) inhe asli grid
   row bana diya jaata hai. */
.inbx-act-row-top,
.inbx-act-row-bottom { display: contents; }

/* v257: poora card ab clickable hai — dabate hi poori inquiry ki
   detail modal me khul jaati hai (bina order_view.php khole). Sirf
   .inbx-card-actions (Call/WhatsApp/Confirm/etc.) ke andar click hone
   par apna normal kaam karte hain, card modal nahi kholta. */
.inbx-card-clickable { cursor: pointer; transition: box-shadow 0.15s ease, transform 0.1s ease; }
.inbx-card-clickable:hover { box-shadow: 0 6px 18px -8px rgba(17,16,19,0.18); }
.inbx-card-clickable:active { transform: scale(0.995); }

.inbx-detail-overlay {
  display: none;
  position: fixed; inset: 0;
  background: rgba(10,10,12,0.55);
  z-index: 1000;
  align-items: center;
  justify-content: center;
  padding: 16px;
}
.inbx-detail-overlay.show { display: flex; }
.inbx-detail-modal {
  background: var(--white);
  border-radius: 16px;
  width: 100%;
  max-width: 460px;
  max-height: 88vh;
  overflow-y: auto;
  padding: 20px;
  position: relative;
  box-shadow: 0 24px 60px rgba(17,16,19,0.28);
}
.inbx-detail-close {
  position: absolute;
  top: 12px; right: 12px;
  width: 30px; height: 30px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: #f2f2f5;
  color: var(--text-secondary);
  font-size: 15px; font-weight: 700;
  cursor: pointer; border: none;
}
.inbx-detail-close:hover { background: #e6e6ec; }
.inbx-detail-top { display: flex; align-items: flex-start; gap: 12px; margin-bottom: 14px; padding-right: 30px; }
.inbx-detail-av {
  flex-shrink: 0; width: 46px; height: 46px; border-radius: 50%;
  background: linear-gradient(135deg, #b0102e 0%, #7d0e28 100%);
  color: #fff; display: flex; align-items: center; justify-content: center;
  font-size: 18px; font-weight: 800;
}
.inbx-detail-name { font-size: 16.5px; font-weight: 800; color: var(--text-primary); display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.inbx-detail-order { font-size: 12px; color: var(--text-secondary); margin-top: 2px; }
.inbx-detail-fields { display: flex; flex-direction: column; gap: 10px; margin-bottom: 14px; }
.inbx-detail-field { display: flex; flex-direction: column; gap: 2px; }
.inbx-detail-field-label { font-size: 10.5px; font-weight: 800; letter-spacing: 0.4px; text-transform: uppercase; color: var(--text-secondary); }
.inbx-detail-field-val { font-size: 13.5px; color: var(--text-primary); line-height: 1.5; white-space: pre-wrap; word-break: break-word; }
.inbx-detail-actions { display: flex; gap: 8px; flex-wrap: wrap; padding-top: 12px; border-top: 1px solid var(--border-main); }

/* Inquiry Settings — quick stats row (v251) */
.inq-stats-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  margin-bottom: 16px;
}
.inq-stat-box {
  background: var(--white);
  border: 1px solid var(--border-main);
  border-radius: 14px;
  padding: 14px 12px;
  text-align: center;
  text-decoration: none;
  display: block;
}
.inq-stat-num { font-size: 24px; font-weight: 800; color: var(--text-primary); line-height: 1.1; font-variant-numeric: tabular-nums; }
.inq-stat-lbl { font-size: 10.5px; font-weight: 700; letter-spacing: 0.3px; color: var(--text-secondary); margin-top: 4px; }
.inq-stat-warn { border-color: rgba(240,160,20,0.4); background: rgba(240,160,20,0.05); }
.inq-stat-warn .inq-stat-num { color: #9a6400; }
.inq-stat-good .inq-stat-num { color: #0f9d58; }

/* ================ Privacy Note (staff/admin-only) ================ */
/* Same visual language as a ticket's "Internal Notes" — amber dashed
   border + cream panel so it reads as distinctly "sensitive/internal" at
   a glance, wherever it's used (Order Details, Customer Profile, and any
   future page). Colors are real CSS classes with their own dark-mode
   variant (not a hardcoded inline hex), so this one doesn't join the
   "white box, invisible text" bug list the rest of the app had.
   Collapsed by default — the toggle button IS the whole collapsed state,
   a single compact line, so it never eats space on a page that already
   has a lot on it. */
.privacy-note-card { border: 1px dashed #e0b84a; background: #fffdf6; margin-bottom: 16px; overflow: hidden; }
.privacy-note-toggle {
  width: 100%; display: flex; align-items: center; gap: 10px;
  padding: 12px 20px; background: none; border: none; cursor: pointer;
  font: inherit; text-align: left; color: var(--text-primary);
}
.privacy-note-title { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 800; }
.privacy-note-badge {
  font-size: 10px; font-weight: 800; letter-spacing: 0.3px; text-transform: uppercase;
  background: #e0b84a; color: #1a1a1f; padding: 3px 9px; border-radius: 100px;
}
.privacy-note-chevron { margin-left: auto; font-size: 11px; color: var(--text-tertiary); transition: transform 0.15s ease; }
.privacy-note-card.is-open .privacy-note-chevron { transform: rotate(180deg); }
.privacy-note-body { border-top: 1px dashed #f0e2b8; }
.privacy-note-hint { font-size: 12px; color: var(--text-tertiary); margin: 0 0 12px; }
.privacy-note-list { display: flex; flex-direction: column; gap: 0; margin-bottom: 12px; }
.privacy-note-item { padding: 10px 0; border-bottom: 1px dashed #f0e2b8; }
.privacy-note-item:last-child { border-bottom: none; }
.privacy-note-text { font-size: 15px; font-weight: 700; line-height: 1.5; white-space: pre-line; color: var(--text-primary); }
.privacy-note-meta {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin-top: 5px; font-size: 10.5px; color: var(--text-tertiary);
}
.privacy-note-actions { display: flex; align-items: center; gap: 2px; flex-shrink: 0; }
.privacy-note-action-btn {
  background: none; border: none; cursor: pointer; font-size: 12px;
  color: var(--text-tertiary); padding: 2px 6px; border-radius: 6px; line-height: 1;
  transition: color 0.15s ease, background-color 0.15s ease;
}
.privacy-note-action-btn:hover { color: var(--brand-pink); background: #fdeaf0; }
.privacy-note-empty { font-size: 12.5px; color: var(--text-tertiary); margin: 0 0 12px; }
.privacy-note-form { display: flex; flex-direction: column; gap: 8px; }
.privacy-note-form textarea { resize: vertical; min-height: 56px; }
.privacy-note-submit { align-self: flex-start; }
.privacy-note-edit-form { display: flex; flex-direction: column; gap: 8px; margin-top: 8px; }
.privacy-note-edit-form textarea { resize: vertical; min-height: 48px; }
.privacy-note-edit-actions { display: flex; gap: 8px; }
.privacy-note-edit-actions .btn { padding: 6px 14px; font-size: 12px; }
/* Dark mode: a clean neutral card (matching every other card's dark
   surface) with just the amber border/badge kept as the "sensitive"
   accent — the earlier full amber-tinted background read muddy and
   made the title text default to the browser's black button-text
   color, which never picks up the theme (buttons don't inherit color
   automatically) — fixed above by setting it explicitly. */
body.dark-mode .privacy-note-card { background: var(--white); border-color: #6b5522; }
body.dark-mode .privacy-note-body { border-top-color: #4a3d20; }
body.dark-mode .privacy-note-badge { background: #6b5522; color: #f0d99a; }
body.dark-mode .privacy-note-item { border-bottom-color: #4a3d20; }
body.dark-mode .privacy-note-action-btn:hover { background: #3a1c26; }

/* ---- Production countdown badge (customer portal + public tracking) ---- */
.prod-countdown { display: inline-flex; align-items: center; gap: 6px; padding: 6px 14px; border-radius: 100px; font-size: 12.5px; font-weight: 700; }
.prod-countdown.tone-normal { background: #eef4ff; color: #2284e6; }
.prod-countdown.tone-soon   { background: #fff7e6; color: #b45309; }
.prod-countdown.tone-late   { background: #fdeaf0; color: #d81142; }

/* ---- Work Types: card grid (matches reference design) ---- */
.wt-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 16px; }
.wt-card { background: var(--white); border: 1px solid var(--border-main); border-radius: var(--radius-lg); overflow: hidden; box-shadow: var(--shadow-sm); }
.wt-card-head { display: flex; align-items: flex-start; gap: 12px; padding: 16px 18px; border-bottom: 3px solid var(--wt-color, #4ba2f3); }
.wt-icon { width: 40px; height: 40px; border-radius: 10px; display: flex; align-items: center; justify-content: center; font-size: 18px; color: #fff; flex-shrink: 0; background: var(--wt-color, #4ba2f3); }
.wt-card-name { font-size: 15px; font-weight: 800; }
.wt-card-desc { font-size: 12.5px; color: var(--text-secondary); margin-top: 2px; }
.wt-card-stats { display: flex; align-items: center; padding: 14px 18px; gap: 10px; }
.wt-stat-num { font-size: 17px; font-weight: 800; }
.wt-stat-label { font-size: 9.5px; font-weight: 700; color: var(--text-tertiary); text-transform: uppercase; letter-spacing: 0.4px; margin-top: 1px; }
.wt-days-pill { margin-left: auto; display: inline-flex; align-items: center; gap: 4px; background: #e7f8ee; color: #0f9d58; font-size: 12px; font-weight: 700; padding: 5px 12px; border-radius: 100px; flex-shrink: 0; }
.wt-card-actions { display: flex; gap: 8px; padding: 0 18px 16px; }
.wt-card-actions .btn { flex: 1; justify-content: center; }

/* ---- Color swatch picker (Work Type modal) ---- */
.color-swatch-grid { display: flex; flex-wrap: wrap; gap: 10px; }
.color-swatch {
  width: 34px; height: 34px; border-radius: 9px; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  border: 2px solid transparent; color: #fff; font-size: 15px; font-weight: 800;
}
.color-swatch.selected { border-color: #1a1a1f; box-shadow: 0 0 0 2px #fff inset; }

/* ---- iOS-style toggle switch (Settings > Notifications, etc.) ---- */
.toggle-switch { position: relative; display: inline-block; width: 42px; height: 24px; flex-shrink: 0; }
.toggle-switch input { opacity: 0; width: 0; height: 0; }
.toggle-slider { position: absolute; cursor: pointer; inset: 0; background-color: #d9d9e0; transition: 0.2s; border-radius: 24px; }
.toggle-slider::before { position: absolute; content: ""; height: 18px; width: 18px; left: 3px; bottom: 3px; background-color: #fff; transition: 0.2s; border-radius: 50%; box-shadow: 0 1px 3px rgba(0,0,0,0.2); }
.toggle-switch input:checked + .toggle-slider { background-color: var(--brand-pink); }
.toggle-switch input:checked + .toggle-slider::before { transform: translateX(18px); }
.toggle-row { display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 12px 0; border-bottom: 1px solid var(--border-main); }
.toggle-row:last-child { border-bottom: none; }
.toggle-row-label { font-size: 13.5px; font-weight: 700; }
.toggle-row-sub { font-size: 11.5px; color: var(--text-tertiary); margin-top: 2px; }

/* ---- Measurement size photo: preview thumbnail + lightbox ---- */
.size-photo-preview { margin-top:8px; display:flex; align-items:center; gap:10px; }
.size-photo-preview img {
  width: 56px; height: 56px; object-fit: cover; border-radius: 8px;
  border: 1px solid var(--border-main); cursor: pointer; flex-shrink: 0;
  transition: transform 0.12s ease;
}
.size-photo-preview img:hover { transform: scale(1.06); }
.img-lightbox-overlay {
  display: none; position: fixed; inset: 0; background: rgba(10,10,14,0.88);
  z-index: 2000; align-items: center; justify-content: center; padding: 30px; cursor: zoom-out;
}
.img-lightbox-overlay.show { display: flex; }
.img-lightbox-overlay img { max-width: 90vw; max-height: 85vh; border-radius: 10px; box-shadow: 0 20px 60px rgba(0,0,0,0.5); }
.img-lightbox-close {
  position: absolute; top: 18px; right: 24px; color: #fff; font-size: 28px;
  background: rgba(255,255,255,0.12); width: 40px; height: 40px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; cursor: pointer; border: none;
}
.img-lightbox-download {
  position: absolute; bottom: 24px; left: 50%; transform: translateX(-50%);
  background: var(--brand-pink); color: #fff; padding: 10px 22px; border-radius: 100px;
  font-size: 13px; font-weight: 700; text-decoration: none; display: flex; align-items: center; gap: 6px;
}

/* ---- Scan Order page ---- */
.scan-two-col { display:flex; gap:24px; flex-wrap:wrap; align-items:flex-start; }
.scan-left { flex:1; min-width:320px; }
.scan-right { flex:1.4; min-width:360px; }

/* ---- Scan Order: manual entry with a fixed ORD- prefix — reads as one
   seamless input box, but only the number portion is ever editable. ---- */
.scan-id-input-group {
  display: flex;
  align-items: center;
  border: 1px solid var(--border-main);
  border-radius: var(--radius-sm);
  background: var(--white);
  max-width: 320px;
  flex: 1;
  overflow: hidden;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.scan-id-input-group:focus-within { border-color: #2284e6; box-shadow: 0 0 0 3px rgba(34,132,230,0.12); }
.scan-id-prefix {
  padding: 10px 0 10px 12px;
  font-size: 13.5px;
  font-weight: 700;
  color: var(--text-tertiary);
  user-select: none;
  flex-shrink: 0;
}
.scan-id-number {
  flex: 1;
  min-width: 0;
  border: none;
  outline: none;
  background: transparent;
  padding: 10px 12px 10px 2px;
  font-size: 13.5px;
  font-family: inherit;
  color: var(--text-primary);
}
.scan-empty { text-align:center; padding:40px 20px; color:var(--text-tertiary); }
/* ---- Scan Order — order detail card (dark header + clean white body) ---- */
.scan-card { background:var(--white); border-radius:14px; overflow:hidden; box-shadow:var(--shadow-md); border:1px solid var(--border-main); }
.scan-card-header { background:#1a1a1f; color:#fff; padding:18px 20px; }
.scan-card-id { font-size:10.5px; color:rgba(255,255,255,0.5); font-weight:700; letter-spacing:0.3px; }
.scan-card-title { font-size:17px; font-weight:800; margin-top:4px; }
.scan-card-customer { font-size:12px; color:rgba(255,255,255,0.65); margin-top:3px; display:flex; align-items:center; gap:5px; }
.scan-card-body { padding:16px 20px; }
.scan-info-row { display:flex; justify-content:space-between; align-items:center; padding:9px 0; border-bottom:1px solid var(--border-main); font-size:13px; }
.scan-info-row:last-of-type { border-bottom:none; }
.scan-info-label { color:var(--text-secondary); }
.scan-info-value { font-weight:700; text-align:right; }
.scan-items-label { font-size:10px; font-weight:700; color:var(--text-tertiary); text-transform:uppercase; letter-spacing:0.5px; margin:14px 0 6px; }
.scan-item-row { display:flex; justify-content:space-between; padding:6px 0; font-size:12.5px; }
.scan-btn-row { display:flex; gap:8px; margin-top:16px; }
.scan-btn-row .btn { flex:1; justify-content:center; white-space:nowrap; padding:10px 8px; font-size:12.5px; }

/* ---- Scan Order: quick-action buttons (Deliver / Payment / Mark Paid) ---- */
.scan-btn-row-quick { margin-top:10px; }
.scan-quick-btn {
  flex: 1;
  display: flex; align-items: center; justify-content: center; gap: 6px;
  padding: 11px 8px;
  font-size: 12.5px;
  font-weight: 800;
  border: none;
  border-radius: 10px;
  cursor: pointer;
  color: #fff;
  white-space: nowrap;
  transition: transform 0.12s ease, box-shadow 0.12s ease, opacity 0.12s ease;
  box-shadow: 0 2px 8px rgba(0,0,0,0.12);
}
.scan-quick-btn:hover:not(:disabled) { transform: translateY(-1.5px); box-shadow: 0 5px 14px rgba(0,0,0,0.18); }
.scan-quick-btn:active:not(:disabled) { transform: translateY(0) scale(0.97); }
.scan-quick-btn:disabled { opacity: 0.55; cursor: not-allowed; box-shadow: none; }
.scan-quick-btn-deliver { background: linear-gradient(135deg, #10b981, #059669); }
.scan-quick-btn-payment { background: linear-gradient(135deg, #2284e6, #1a68b8); }
.scan-quick-btn-paid    { background: linear-gradient(135deg, #0f9d58, #0f766e); }
@media (max-width: 640px) {
  .scan-btn-row-quick { flex-wrap: wrap; }
  .scan-quick-btn { flex: 1 1 100%; }
}

/* ---- Scan Order: toast feedback ---- */
/* Sits just above the Recycle Bin FAB (bottom:18px, 48px tall) instead
   of top-center, so it never covers the header logo. */
.scan-toast {
  position: fixed;
  right: 18px;
  bottom: 80px;
  left: auto;
  transform: translateY(10px);
  background: #1a1a1f;
  color: #fff;
  padding: 12px 22px;
  border-radius: 10px;
  font-size: 13px;
  font-weight: 700;
  box-shadow: 0 8px 24px rgba(0,0,0,0.25);
  z-index: 1200;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease, transform 0.2s ease;
}
.scan-toast-show { opacity: 1; transform: translateY(0); }
.scan-toast-success { background: #0f9d58; }
.scan-toast-error { background: var(--brand-pink); }
@media (max-width: 560px) {
  .scan-btn-row { flex-wrap:wrap; }
  .scan-btn-row .btn { flex:1 1 100%; }
}
#qrReaderBox { width:100%; border-radius:10px; overflow:hidden; margin-bottom:10px; }

/* ============================================================
   FIXED HEADER STACK — page-content top-offset
   ------------------------------------------------------------
   .app-masthead (logo bar) and .topbar (page title bar) are both
   position:fixed, stacked on top of each other, on EVERY screen size.
   Their combined real height varies per page (title length, whether a
   subtitle is set, wrapping on narrow screens), so rather than guess a
   single number here, header-offset-sync (in footer.php / portal_footer.php)
   measures it after render and writes it into --header-stack-h. This one
   unconditional rule (placed last, !important) is what actually applies
   that value to .page-content's top padding — it wins over both the plain
   desktop rule above AND the mobile "padding: ... !important" shorthand
   rules earlier in this file, on every screen size, without touching their
   left/right/bottom values. The 140px fallback only matters for the one
   frame before the sync script runs.
   ============================================================ */
.page-content { padding-top: var(--header-stack-h, 158px) !important; }

/* ============================================================
   FLOATING ACTION BUTTON(S) + MOBILE TAB BAR — page-content bottom-offset
   ------------------------------------------------------------
   .staff-fab-action / .staff-fab-group (the "+ New Order",
   "+ Add Party", "Scan Order" pills) are position:fixed at the
   bottom of the screen, floating on top of whatever is scrolled
   underneath them. On mobile, the fixed bottom tab bar does the
   same. Without reserving real space for them, the last rows of a
   table/list — or the last button on a page like Scan Order — end
   up physically underneath them and become unclickable. footer-
   offset-sync (in footer.php / portal_footer.php) measures the
   larger of the two after render and writes it into --footer-fab-h;
   this rule (placed last, !important) applies it as .page-content's
   bottom padding so content always scrolls clear. Default is 0 so
   desktop (no tab bar, usually no fab) isn't given extra empty space.
   ============================================================ */
.page-content {
  padding-bottom: max(
    var(--footer-fab-h, 0px),
    calc(var(--tab-bar-h, 0px) + env(safe-area-inset-bottom, 0px) + 16px)
  ) !important;
}

/* ============================================================
   OFFERS — animated promo banner (customer portal, all tabs).
   Colors come from the offer's own admin-chosen palette via
   inline --offer-start / --offer-end / --offer-text custom
   properties set per-instance in includes/portal_header.php —
   this stylesheet only supplies the shared structure + the four
   selectable animation styles (shimmer / pulse / glow / none).
   ============================================================ */
.offer-banner {
  position: relative;
  overflow: hidden;
  margin-bottom: 18px;
  border-radius: 16px;
  padding: 18px 20px;
  cursor: pointer;
  box-shadow: 0 8px 26px rgba(0,0,0,0.18);
  background: linear-gradient(135deg, var(--offer-start) 0%, var(--offer-end) 100%);
  color: var(--offer-text);
}
.offer-banner-close {
  position: absolute; top: 10px; right: 10px; z-index: 3;
  width: 24px; height: 24px; border-radius: 50%;
  background: rgba(255,255,255,0.2); color: inherit;
  display: flex; align-items: center; justify-content: center;
  font-size: 13px; border: none; cursor: pointer; line-height: 1;
}
.offer-banner-row { display: flex; align-items: center; gap: 14px; position: relative; z-index: 2; }
.offer-banner-icon {
  width: 48px; height: 48px; border-radius: 50%; background: rgba(255,255,255,0.18);
  display: flex; align-items: center; justify-content: center; font-size: 22px; flex-shrink: 0;
}
.offer-banner-text { flex: 1; min-width: 0; }
.offer-banner-title { font-weight: 800; font-size: 15.5px; line-height: 1.25; }
.offer-banner-sub { font-size: 12px; opacity: 0.85; margin-top: 2px; }
.offer-banner-badge {
  font-size: 10px; font-weight: 800; letter-spacing: 0.3px; padding: 3px 10px;
  border-radius: 100px; background: rgba(255,255,255,0.2); white-space: nowrap; flex-shrink: 0;
}
.offer-banner-cta { font-size: 11.5px; font-weight: 800; text-decoration: underline; margin-top: 8px; display: inline-block; position: relative; z-index: 2; }
.offer-banner-countdown { font-size: 11px; font-weight: 700; opacity: 0.85; margin-top: 6px; position: relative; z-index: 2; }

.offer-expand {
  margin-top: 14px; padding-top: 14px; border-top: 1px solid rgba(255,255,255,0.25);
  position: relative; z-index: 2; display: none;
}
.offer-expand.open { display: block; }
.offer-expand-desc { font-size: 12.5px; line-height: 1.55; opacity: 0.92; margin-bottom: 10px; white-space: pre-line; }
.offer-expand textarea {
  width: 100%; border-radius: 10px; border: 1px solid rgba(255,255,255,0.4);
  background: rgba(255,255,255,0.12); color: inherit; padding: 10px 12px; font-size: 12.5px;
  font-family: inherit; resize: vertical; min-height: 56px; box-sizing: border-box;
}
.offer-expand textarea::placeholder { color: rgba(255,255,255,0.65); }
.offer-expand-actions { display: flex; align-items: center; gap: 10px; margin-top: 10px; flex-wrap: wrap; }
.offer-expand-btn {
  background: #fff; color: #b0102e; border: none;
  font-weight: 800; font-size: 12.5px; padding: 9px 20px; border-radius: 100px; cursor: pointer;
}
.offer-expand-btn:active { transform: scale(0.97); }
.offer-expand-code { font-size: 11px; font-weight: 700; opacity: 0.85; }

/* ---- Animation styles ---- */
/* GLITCH FIX: `left` ki jagah `transform` animate hota hai — GPU par
   chalta hai, layout ko har frame recalculate nahi karna padta. Ye
   animation `infinite` hai, isliye purana tareeka lagataar jank aur
   battery drain kar raha tha. */
.offer-anim-shimmer::before {
  content: '';
  position: absolute; top: 0; left: 0; width: 50%; height: 100%;
  background: linear-gradient(120deg, transparent, rgba(255,255,255,0.35), transparent);
  transform: translateX(-160%) skewX(-20deg);
  animation: offerShimmer 2.8s ease-in-out infinite;
  pointer-events: none; z-index: 1;
  will-change: transform;
  backface-visibility: hidden;
}
@keyframes offerShimmer {
  0%   { transform: translateX(-160%) skewX(-20deg); }
  60%  { transform: translateX(280%)  skewX(-20deg); }
  100% { transform: translateX(280%)  skewX(-20deg); }
}
.offer-anim-pulse { animation: offerPulse 1.9s ease-in-out infinite; }
@keyframes offerPulse {
  0%, 100% { box-shadow: 0 8px 26px rgba(0,0,0,0.18); }
  50%      { box-shadow: 0 8px 30px rgba(255,255,255,0.4), 0 8px 26px rgba(0,0,0,0.18); }
}
.offer-anim-glow { position: relative; }
.offer-anim-glow::after {
  content: '';
  position: absolute; inset: -4px; border-radius: 20px;
  background: linear-gradient(135deg, var(--offer-start), var(--offer-end));
  filter: blur(11px); opacity: 0.55; z-index: -1;
  animation: offerGlowPulse 2.4s ease-in-out infinite;
}
@keyframes offerGlowPulse {
  0%, 100% { opacity: 0.35; }
  50%      { opacity: 0.75; }
}
@media (prefers-reduced-motion: reduce) {
  .offer-anim-shimmer::before,
  .offer-anim-pulse,
  .offer-anim-glow::after { animation: none; }
}
@media (max-width: 480px) {
  .offer-banner { padding: 15px 16px; }
  .offer-banner-icon { width: 42px; height: 42px; font-size: 19px; }
  .offer-banner-title { font-size: 14px; }
}

/* ---- Offer modal: Color/Gradient vs Custom Image mode tabs ---- */
.offer-mode-tab {
  display: flex; align-items: center; gap: 6px;
  padding: 9px 16px; border-radius: 10px; border: 1.5px solid var(--border-main);
  background: #fff; color: var(--text-secondary); font-size: 12.5px; font-weight: 700;
  cursor: pointer; transition: all 0.15s ease;
}
.offer-mode-tab:hover { border-color: var(--brand-pink); }
.offer-mode-tab.active {
  background: var(--brand-pink); border-color: var(--brand-pink); color: #fff;
}

/* ============================================================
   OFFERS — compact staff-side awareness strip (admin panel).
   Shown at the top of every staff page (that the person has
   Offers permission for) so the whole team knows an offer is
   live, without the full animated customer-portal treatment —
   just a clear, professional, single-line banner that opens the
   full offer detail page on click. Reuses the same --offer-*
   custom properties / animation classes as the portal banner.
   ============================================================ */
.staff-offer-strip {
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 16px;
  padding: 11px 16px;
  border-radius: 12px;
  cursor: pointer;
  text-decoration: none;
  box-shadow: 0 4px 14px rgba(0,0,0,0.14);
  background: linear-gradient(135deg, var(--offer-start) 0%, var(--offer-end) 100%);
  color: var(--offer-text);
}
.staff-offer-strip-icon {
  width: 30px; height: 30px; border-radius: 50%; background: rgba(255,255,255,0.18);
  display: flex; align-items: center; justify-content: center; font-size: 15px; flex-shrink: 0;
  position: relative; z-index: 2;
}
.staff-offer-strip-text { flex: 1; min-width: 0; position: relative; z-index: 2; }
.staff-offer-strip-label { font-size: 9.5px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.5px; opacity: 0.75; }
.staff-offer-strip-title { font-size: 13px; font-weight: 800; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.staff-offer-strip-badge {
  font-size: 10px; font-weight: 800; padding: 3px 10px; border-radius: 100px;
  background: rgba(255,255,255,0.2); white-space: nowrap; flex-shrink: 0; position: relative; z-index: 2;
}
.staff-offer-strip-cta {
  font-size: 11px; font-weight: 800; white-space: nowrap; flex-shrink: 0; position: relative; z-index: 2;
  opacity: 0.9;
}
@media (max-width: 600px) {
  .staff-offer-strip-cta, .staff-offer-strip-label { display: none; }
}

/* ============================================================
   NEW ORDER FLAG — a fluttering flag badge on any order still in
   Inquiry or Quoted stage (i.e. genuinely "new, not yet worked
   on"). Shown across every orders.php view mode (table, pipeline,
   progressive, mobile card) and on order_view.php itself; vanishes
   automatically the moment the stage moves past Quoted, since it's
   driven purely by isNewOrder($order) in includes/functions.php —
   nothing to manually clear. Explicit light + dark-mode palettes
   (not just a fixed light-bg badge) since this needs to read
   clearly, with good contrast, in both themes.
   ============================================================ */
.new-order-flag {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.3px;
  padding: 3px 9px 3px 7px;
  border-radius: 20px;
  white-space: nowrap;
  vertical-align: middle;
  background: linear-gradient(135deg, #ffb020, #f59e0b);
  color: #4a2c02;
  box-shadow: 0 1px 4px rgba(245,158,11,0.45);
}
.new-order-flag-icon {
  display: inline-block;
  font-size: 11px;
  transform-origin: 20% 80%;
  animation: newOrderFlagWave 1.6s ease-in-out infinite;
}
@keyframes newOrderFlagWave {
  0%, 100% { transform: rotate(0deg); }
  25%      { transform: rotate(-14deg); }
  75%      { transform: rotate(10deg); }
}
@media (prefers-reduced-motion: reduce) {
  .new-order-flag-icon { animation: none; }
}
body.dark-mode .new-order-flag {
  background: linear-gradient(135deg, #f59e0b, #b45309);
  color: #fff7e6;
  box-shadow: 0 0 10px rgba(245,158,11,0.4), 0 1px 4px rgba(0,0,0,0.35);
}

/* Compact dot-only variant for tight spaces (kanban cards, chevron strip) */
.new-order-dot {
  display: inline-block;
  width: 8px; height: 8px; border-radius: 50%;
  background: #f59e0b;
  box-shadow: 0 0 0 2px rgba(245,158,11,0.25);
  animation: newOrderDotPulse 1.6s ease-in-out infinite;
  vertical-align: middle;
}
@keyframes newOrderDotPulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 0.55; transform: scale(1.25); }
}
@media (prefers-reduced-motion: reduce) {
  .new-order-dot { animation: none; }
}
body.dark-mode .new-order-dot { background: #ffb020; box-shadow: 0 0 0 2px rgba(255,176,32,0.3); }

/* Quick-filter chip (chevron-strip style) used on orders.php */
.new-order-filter-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 14px; border-radius: 100px; font-size: 12.5px; font-weight: 700;
  text-decoration: none; white-space: nowrap; flex-shrink: 0;
  background: linear-gradient(135deg, #ffb020, #f59e0b); color: #4a2c02;
  box-shadow: 0 1px 4px rgba(245,158,11,0.35);
}
.new-order-filter-chip.is-inactive {
  background: #e2e2e6; color: #000;
  box-shadow: none;
}
body.dark-mode .new-order-filter-chip.is-inactive { background: #26262e; color: var(--text-primary); }
.new-order-filter-chip-count {
  background: rgba(0,0,0,0.15); border-radius: 100px; padding: 1px 8px; font-size: 11px;
}
.new-order-filter-chip.is-inactive .new-order-filter-chip-count { background: rgba(0,0,0,0.08); }
body.dark-mode .new-order-filter-chip.is-inactive .new-order-filter-chip-count { background: rgba(255,255,255,0.1); }


/* ======================================================================
   ORDER REQUEST SOURCE CARD — professional order-view presentation
   Scoped to the source card only; existing order workflow remains intact.
   ====================================================================== */
.inq-order-request-panel {
  position: relative;
  overflow: hidden;
  border: 1px solid rgba(216,17,66,.14);
  border-left: 1px solid rgba(216,17,66,.14);
  border-radius: 16px;
  padding: 15px 16px 14px;
  background: linear-gradient(180deg, rgba(255,255,255,.99) 0%, rgba(255,249,251,.98) 100%);
  box-shadow: 0 8px 28px rgba(30,24,28,.055);
}
.inq-order-request-panel::before {
  content: "";
  position: absolute;
  left: 0; top: 0; right: 0;
  height: 3px;
  background: linear-gradient(90deg, var(--brand-pink), #ff5a7c 58%, rgba(255,90,124,.12));
}
.inq-order-request-panel.inq-panel-new {
  border-color: rgba(240,160,20,.24);
  background: linear-gradient(180deg,#fff 0%,rgba(255,250,239,.98) 100%);
}
.inq-order-request-panel.inq-panel-new::before { background: linear-gradient(90deg,#e59a13,#f6c45a 65%,rgba(246,196,90,.12)); }
.inq-order-request-panel.inq-panel-rejected {
  border-color: rgba(90,90,98,.18);
  background: linear-gradient(180deg,#fff 0%,rgba(248,248,249,.98) 100%);
}
.inq-order-request-panel.inq-panel-rejected::before { background: linear-gradient(90deg,#71717a,#b0b0b7 65%,rgba(176,176,183,.12)); }

.inq-order-request-panel .inq-panel-head {
  display: grid;
  grid-template-columns: 42px minmax(0,1fr) auto;
  align-items: center;
  gap: 11px;
  margin: 0 0 13px;
  padding-bottom: 12px;
  border-bottom: 1px solid rgba(27,31,36,.075);
}
.inq-order-request-panel .inq-panel-ico {
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  border-radius: 12px;
  background: rgba(216,17,66,.075);
  border: 1px solid rgba(216,17,66,.13);
  color: var(--brand-pink);
}
.inq-order-request-panel .inq-panel-ico svg { width: 21px; height: 21px; display:block; }
.inq-panel-heading { min-width: 0; }
.inq-panel-kicker {
  margin-bottom: 2px;
  color: var(--brand-pink);
  font-size: 8px;
  line-height: 1.1;
  font-weight: 900;
  letter-spacing: .11em;
}
.inq-order-request-panel .inq-panel-title {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  font-size: 14px;
  line-height: 1.25;
  font-weight: 850;
}
.inq-order-request-panel .inq-badge {
  margin-left: 0;
  display: inline-flex;
  align-items: center;
  min-height: 20px;
  padding: 3px 8px;
  border: 1px solid transparent;
  font-size: 9px;
  letter-spacing: .02em;
}
.inq-order-request-panel .inq-badge-confirmed {
  color: #087a47;
  background: #e9f8f0;
  border-color: #bee8d1;
}
.inq-order-request-panel .inq-badge-confirmed::before {
  content: "";
  width: 6px; height: 6px;
  margin-right: 5px;
  border-radius: 50%;
  background: #16a765;
  box-shadow: 0 0 0 3px rgba(22,167,101,.11);
}
.inq-order-request-panel .inq-panel-sub {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 5px;
  margin-top: 4px;
  font-size: 10.5px;
  line-height: 1.35;
}
.inq-panel-dot { width:3px; height:3px; border-radius:50%; background:var(--text-tertiary); opacity:.7; }
.inq-order-request-panel .inq-panel-back {
  margin-left: 0;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 32px;
  padding: 7px 10px;
  border: 1px solid rgba(216,17,66,.13);
  background: rgba(216,17,66,.055);
  transition: transform .16s ease, background .16s ease, border-color .16s ease;
}
.inq-order-request-panel .inq-panel-back svg { width:15px; height:15px; }
.inq-order-request-panel .inq-panel-back:hover {
  transform: translateY(-1px);
  background: rgba(216,17,66,.09);
  border-color: rgba(216,17,66,.22);
}

.inq-order-request-panel .inq-panel-grid {
  display: grid;
  grid-template-columns: repeat(5,minmax(0,1fr));
  gap: 8px;
}
.inq-order-request-panel .inq-info-item {
  min-width: 0;
  padding: 9px 10px;
  border-radius: 11px;
  border: 1px solid rgba(25,28,33,.075);
  background: rgba(255,255,255,.82);
}
.inq-order-request-panel .inq-info-item span {
  font-size: 7.7px;
  letter-spacing: .08em;
  color: var(--text-tertiary);
}
.inq-order-request-panel .inq-info-item strong {
  margin-top: 1px;
  font-size: 12px;
  line-height: 1.35;
}
.inq-panel-msg-wrap { margin-top: 10px; }
.inq-panel-msg-label {
  margin: 0 0 5px 2px;
  color: var(--text-tertiary);
  font-size: 8px;
  font-weight: 900;
  letter-spacing: .085em;
  text-transform: uppercase;
}
.inq-order-request-panel .inq-panel-msg {
  margin-top: 0;
  padding: 10px 12px;
  border-radius: 11px;
  border-color: rgba(216,17,66,.11);
  background: rgba(216,17,66,.035);
  font-size: 12px;
  line-height: 1.5;
}
.inq-order-request-panel .inq-panel-actions {
  margin-top: 10px !important;
  padding-top: 10px;
  border-top: 1px solid rgba(27,31,36,.07);
}
body.dark-mode .inq-order-request-panel {
  background: linear-gradient(180deg,rgba(30,30,34,.98),rgba(35,27,31,.98));
  border-color: rgba(255,94,128,.18);
  box-shadow: none;
}
body.dark-mode .inq-order-request-panel .inq-panel-head,
body.dark-mode .inq-order-request-panel .inq-panel-actions { border-color: rgba(255,255,255,.08); }
body.dark-mode .inq-order-request-panel .inq-info-item {
  background: rgba(255,255,255,.035);
  border-color: rgba(255,255,255,.08);
}
body.dark-mode .inq-order-request-panel .inq-panel-msg {
  background: rgba(216,17,66,.07);
  border-color: rgba(255,94,128,.14);
}

@media (max-width: 1050px) {
  .inq-order-request-panel .inq-panel-grid { grid-template-columns: repeat(3,minmax(0,1fr)); }
}
@media (max-width: 700px) {
  .inq-order-request-panel { padding: 13px 12px 12px; border-radius: 15px; }
  .inq-order-request-panel .inq-panel-head {
    grid-template-columns: 38px minmax(0,1fr) auto;
    gap: 9px;
    padding-bottom: 10px;
    margin-bottom: 10px;
  }
  .inq-order-request-panel .inq-panel-ico { width:36px; height:36px; border-radius:11px; }
  .inq-order-request-panel .inq-panel-title { font-size:13px; gap:5px; }
  .inq-order-request-panel .inq-panel-sub { font-size:9.5px; }
  .inq-order-request-panel .inq-panel-back { width:32px; height:32px; min-height:32px; padding:0; justify-content:center; border-radius:10px; }
  .inq-order-request-panel .inq-panel-back span { display:none; }
  .inq-order-request-panel .inq-panel-grid { grid-template-columns: repeat(2,minmax(0,1fr)); gap:7px; }
  .inq-order-request-panel .inq-info-item { padding:8px 9px; }
  .inq-order-request-panel .inq-info-item strong { font-size:11.5px; }
}

/* Order Request source card — compact collapsible header (Privacy Note pattern) */
.inq-order-request-panel .inq-panel-head-actions {
  display: flex;
  align-items: center;
  gap: 7px;
  justify-self: end;
}
.inq-order-request-panel .inq-panel-toggle {
  width: 32px;
  height: 32px;
  flex: 0 0 32px;
  display: inline-grid;
  place-items: center;
  padding: 0;
  border: 1px solid rgba(216,17,66,.13);
  border-radius: 10px;
  background: rgba(216,17,66,.055);
  color: var(--brand-pink);
  cursor: pointer;
  transition: transform .16s ease, background .16s ease, border-color .16s ease;
}
.inq-order-request-panel .inq-panel-toggle:hover {
  background: rgba(216,17,66,.10);
  border-color: rgba(216,17,66,.24);
}
.inq-order-request-panel .inq-panel-toggle:active { transform: scale(.96); }
.inq-order-request-panel .inq-panel-toggle svg {
  width: 17px;
  height: 17px;
  transition: transform .18s ease;
}
.inq-order-request-panel.is-open .inq-panel-toggle svg { transform: rotate(180deg); }
.inq-order-request-panel .inq-panel-body { animation: inqPanelOpen .16s ease-out; }
.inq-order-request-panel:not(.is-open) .inq-panel-head {
  margin-bottom: 0;
  padding-bottom: 0;
  border-bottom-color: transparent;
}
@keyframes inqPanelOpen {
  from { opacity: 0; transform: translateY(-3px); }
  to { opacity: 1; transform: translateY(0); }
}
body.dark-mode .inq-order-request-panel .inq-panel-toggle {
  background: rgba(255,94,128,.07);
  border-color: rgba(255,94,128,.16);
}
@media (max-width: 700px) {
  .inq-order-request-panel .inq-panel-head-actions { gap: 5px; }
  .inq-order-request-panel .inq-panel-toggle { width: 32px; height: 32px; flex-basis: 32px; }
}

/* Order Request + Privacy Note — visual breathing space */
.inq-order-request-panel + .privacy-note-card {
  margin-top: 12px;
}
@media (max-width: 700px) {
  .inq-order-request-panel + .privacy-note-card {
    margin-top: 10px;
  }
}

/* Order Request + Privacy Note — final spacing / flat cards */
.inq-order-request-panel {
  box-shadow: none !important;
}
.inq-order-request-panel + .privacy-note-card {
  margin-top: 18px !important;
}
.privacy-note-card {
  box-shadow: none !important;
}
@media (max-width: 700px) {
  .inq-order-request-panel + .privacy-note-card {
    margin-top: 14px !important;
  }
}

/* ======================================================================
   ORDER VIEW — MOBILE EDGE-TO-EDGE HEADER (v264)
   ----------------------------------------------------------------------
   Mobile app par order ke top detail section ke bahar jo generic .card
   shell/border tha, usse hata kar useful content ko left/right zyada
   width di gayi hai. Desktop (901px+) bilkul untouched hai.
   ====================================================================== */
@media (max-width: 900px) {
  body.ap-page-order_view .ov-head-card {
    background: transparent !important;
    border: 0 !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    overflow: visible !important;
  }

  body.ap-page-order_view .ov-head-card::before {
    display: none !important;
  }

  body.ap-page-order_view .ov-head-card > .card-body {
    padding-left: 0 !important;
    padding-right: 0 !important;
    background: transparent !important;
    overflow: visible !important;
  }

  /* Hero/details/actions ab outer shell ke extra 20px side padding ke
     bina page ki available mobile width use karte hain. */
  body.ap-page-order_view .ov-head-card .ov-hero {
    margin-left: 0 !important;
    margin-right: 0 !important;
  }

  /* Card-body padding hatne ke baad delete action ko hero ke andar hi
     balanced inset par rakho; desktop placement par iska koi asar nahi. */
  body.ap-page-order_view .ov-head-card a[href^="order_delete.php"] {
    right: 12px !important;
  }
}

/* ======================================================================
   ORDER REQUEST FILES — always-visible download panel on order details
   ====================================================================== */
.inq-order-request-panel .inq-request-files-strip {
  display:grid;
  grid-template-columns:190px minmax(0,1fr);
  gap:12px;
  align-items:stretch;
  margin-top:12px;
  padding:12px;
  border:1px solid rgba(216,17,66,.12);
  border-radius:14px;
  background:linear-gradient(135deg,#fff8fa 0%,#fff 68%);
}
.inq-order-request-panel .inq-request-files-lead {
  display:flex;
  align-items:center;
  gap:11px;
  min-width:0;
  padding-right:12px;
  border-right:1px solid rgba(27,31,36,.075);
}
.inq-order-request-panel .inq-request-files-bigicon {
  width:58px;
  height:58px;
  flex:0 0 58px;
  display:grid;
  place-items:center;
  border-radius:16px;
  color:#fff;
  background:linear-gradient(145deg,#ef164b,#a90d36);
  box-shadow:0 8px 18px rgba(183,13,57,.18);
}
.inq-order-request-panel .inq-request-files-bigicon svg { width:29px;height:29px; }
.inq-order-request-panel .inq-request-files-lead strong {
  display:block;
  color:var(--text-primary);
  font-size:12.5px;
  font-weight:850;
  line-height:1.25;
}
.inq-order-request-panel .inq-request-files-lead small {
  display:block;
  margin-top:3px;
  color:var(--text-tertiary);
  font-size:9.5px;
  font-weight:700;
}
.inq-order-request-panel .inq-request-files-list {
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(265px,1fr));
  gap:8px;
  min-width:0;
}
.inq-order-request-panel .inq-request-file-item {
  display:flex;
  align-items:center;
  gap:9px;
  min-width:0;
  min-height:58px;
  padding:8px 9px;
  border:1px solid rgba(30,33,39,.075);
  border-radius:12px;
  background:rgba(255,255,255,.88);
}
.inq-order-request-panel .inq-request-file-type {
  flex:0 0 40px;
  height:40px;
  display:grid;
  place-items:center;
  border-radius:10px;
  background:#f5f1f3;
  color:#9d1236;
  font-size:8px;
  font-weight:900;
  letter-spacing:.03em;
}
.inq-order-request-panel .inq-request-file-copy { min-width:0; flex:1 1 auto; }
.inq-order-request-panel .inq-request-file-copy strong {
  display:block;
  overflow:hidden;
  text-overflow:ellipsis;
  white-space:nowrap;
  color:var(--text-primary);
  font-size:11px;
  font-weight:800;
}
.inq-order-request-panel .inq-request-file-copy small {
  display:block;
  margin-top:2px;
  color:var(--text-tertiary);
  font-size:8.7px;
}
.inq-order-request-panel .inq-request-file-actions {
  display:flex;
  align-items:center;
  gap:6px;
  flex:0 0 auto;
}
.inq-order-request-panel .inq-request-file-open,
.inq-order-request-panel .inq-request-file-download {
  min-height:34px;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  gap:6px;
  border-radius:9px;
  text-decoration:none;
  font-size:9.5px;
  font-weight:850;
}
.inq-order-request-panel .inq-request-file-open {
  width:34px;
  padding:0;
  color:#6d6670;
  border:1px solid rgba(27,31,36,.09);
  background:#f5f5f7;
}
.inq-order-request-panel .inq-request-file-download {
  padding:0 11px;
  color:#fff;
  border:1px solid #b40f39;
  background:linear-gradient(135deg,#e91449,#b30e39);
  box-shadow:0 4px 11px rgba(183,13,57,.12);
}
.inq-order-request-panel .inq-request-file-open svg,
.inq-order-request-panel .inq-request-file-download svg { width:14px;height:14px; }
.inq-order-request-panel .inq-request-file-download:active,
.inq-order-request-panel .inq-request-file-open:active { transform:scale(.97); }

body.dark-mode .inq-order-request-panel .inq-request-files-strip {
  background:linear-gradient(135deg,rgba(216,17,66,.07),rgba(255,255,255,.02));
  border-color:rgba(255,94,128,.14);
}
body.dark-mode .inq-order-request-panel .inq-request-files-lead { border-color:rgba(255,255,255,.08); }
body.dark-mode .inq-order-request-panel .inq-request-file-item {
  background:rgba(255,255,255,.035);
  border-color:rgba(255,255,255,.08);
}
body.dark-mode .inq-order-request-panel .inq-request-file-type { background:rgba(255,255,255,.06); color:#ff7596; }
body.dark-mode .inq-order-request-panel .inq-request-file-open { background:rgba(255,255,255,.05); border-color:rgba(255,255,255,.09); color:#d6d3d8; }

@media (max-width:700px) {
  .inq-order-request-panel .inq-request-files-strip {
    grid-template-columns:1fr;
    gap:9px;
    margin-top:10px;
    padding:9px;
    border-radius:12px;
  }
  .inq-order-request-panel .inq-request-files-lead {
    padding:0 0 8px;
    border-right:0;
    border-bottom:1px solid rgba(27,31,36,.07);
  }
  .inq-order-request-panel .inq-request-files-bigicon {
    width:44px;height:44px;flex-basis:44px;border-radius:12px;
  }
  .inq-order-request-panel .inq-request-files-bigicon svg { width:23px;height:23px; }
  .inq-order-request-panel .inq-request-files-lead strong { font-size:11.5px; }
  .inq-order-request-panel .inq-request-files-list { grid-template-columns:1fr; }
  .inq-order-request-panel .inq-request-file-item { min-height:54px; padding:7px; gap:7px; }
  .inq-order-request-panel .inq-request-file-type { flex-basis:36px;width:36px;height:36px;border-radius:9px;font-size:7.5px; }
  .inq-order-request-panel .inq-request-file-copy strong { font-size:10.5px; }
  .inq-order-request-panel .inq-request-file-download { min-height:32px;padding:0 9px;font-size:9px; }
  .inq-order-request-panel .inq-request-file-open { width:32px;min-height:32px; }
}
