/* ==========================================================
   OMS ENTERPRISE — DESIGN SYSTEM
   Premium SaaS UI (HubSpot / Zoho / Linear inspired)
   Frontend-only redesign — no backend logic touched.
   ========================================================== */


/* ==========================================================
   1. VARIABLES
   ========================================================== */
:root{
  /* ---- surfaces ---- */
  --bg:             #F5F7FB;
  --card:           #FFFFFF;
  --border:         #E5E7EB;
  /* A field filled in from another record (the lead form Company Information, read from
     the selected customer) - the box is tinted and its border softened so it reads as not
     typable, while the VALUE keeps full --text strength. The value is real data someone
     has to read; greying the text out made a correctly filled form look disabled. */
  --readonly-bg:     #F1F2F6;
  --readonly-border: #E8EAF0;

  /* ---- sidebar ---- */
  --sidebar-bg:     #111827;
  --sidebar-hover:  #1F2937;
  --sidebar-text:   #9CA3AF;
  --sidebar-text-active: #FFFFFF;

  /* ---- brand ---- */
  --primary:        #4F46E5;
  --primary-dark:   #4338CA;
  --primary-light:  #EEF2FF;
  --secondary:      #06B6D4;
  --secondary-light:#ECFEFF;

  /* ---- semantic ---- */
  --success:        #22C55E;
  --success-bg:     #ECFDF3;
  --warning:        #F59E0B;
  --warning-bg:     #FFFBEB;
  --danger:         #EF4444;
  --danger-bg:      #FEF2F2;
  --info:           #06B6D4;
  --info-bg:        #ECFEFF;
  --purple:         #8B5CF6;
  --purple-bg:      #F5F3FF;

  /* ---- text ---- */
  --text:           #111827;
  --text-muted:     #64748B;
  --text-light:     #9CA3AF;

  /* ---- radius ---- */
  --radius-sm:  10px;
  --radius:     14px;
  --radius-lg:  18px;
  --radius-pill: 999px;

  /* ---- shadow (layered, softer falloff = more "premium" than a single hard shadow) ---- */
  --shadow-xs:  0 1px 2px rgba(15,23,42,.04);
  --shadow-sm:  0 1px 2px rgba(15,23,42,.04), 0 4px 10px rgba(15,23,42,.04);
  --shadow:     0 2px 4px rgba(15,23,42,.04), 0 10px 30px rgba(15,23,42,.08);
  --shadow-lg:  0 8px 16px rgba(15,23,42,.06), 0 24px 48px rgba(15,23,42,.16);

  /* ---- reusable gradients (one accent doing the work, consistently) ---- */
  --grad-primary:       linear-gradient(135deg, #6D65EE 0%, var(--primary) 55%, var(--primary-dark) 100%);
  --grad-primary-hover: linear-gradient(135deg, #7A72F2 0%, var(--primary-dark) 55%, #3730A3 100%);
  --grad-sidebar:       linear-gradient(180deg, #0D1220 0%, var(--sidebar-bg) 55%, #0B0F19 100%);

  /* ----------------------------------------------------------------------
     Interface scale.

     One dial for how large the whole application renders. The design system is
     built in px - cards, icons, paddings and type alike - so there is no single
     font size that shrinks all of it proportionally; scaling the shell is what
     keeps every element in the same relation to every other.

     1 is the size the layout was drawn at. Lower values render everything
     smaller, fitting more on screen; raise it for a larger display or for
     someone who wants bigger text. Change this number alone - nothing else
     needs touching.
     ---------------------------------------------------------------------- */
  --app-scale: 0.9;

  /* ---- spacing (8px system) ---- */
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 16px;
  --sp-4: 24px;
  --sp-5: 32px;
  --sp-6: 40px;

  /* ---- typography scale ---- */
  --fs-page-title:    32px;
  --fs-section-title: 22px;
  --fs-card-number:   36px;
  --fs-sidebar:       15px;
  --fs-text:          15px;
  --fs-small:         13px;
  --fs-button:        14px;

  /* ---- motion ---- */
  --ease: cubic-bezier(.4,0,.2,1);
  --fast: .15s;
  --med:  .25s;
}

/* Dark mode variable structure — values swapped later via [data-theme="dark"] */
[data-theme="dark"]{
  --bg:            #0B0F19;
  --card:          #111827;
  --border:        #1F2937;
  /* Darker than --card, not lighter: the light values would paint a near-white box behind
     light text. Same intent as the light theme - tinted away from an editable field. */
  --readonly-bg:     #0E1420;
  --readonly-border: #263041;
  --text:          #F3F4F6;
  --text-muted:    #9CA3AF;
  --sidebar-bg:    #05070D;
  --sidebar-hover: #111827;
}


/* ==========================================================
   2. RESET
   ========================================================== */
*, *::before, *::after{ box-sizing:border-box; margin:0; padding:0; }

html{ -webkit-text-size-adjust:100%; }

body{
  font-family:'Inter','Segoe UI',-apple-system,BlinkMacSystemFont,sans-serif;
  background:
    radial-gradient(circle at 12% 0%, rgba(79,70,229,.05), transparent 40%),
    radial-gradient(circle at 100% 30%, rgba(6,182,212,.04), transparent 45%),
    var(--bg);
  background-attachment:fixed;
  color:var(--text);
  font-size:var(--fs-text);
  line-height:1.5;
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
}

a{ text-decoration:none; color:inherit; }
ul{ list-style:none; }
button{ font-family:inherit; cursor:pointer; border:none; background:none; color:inherit; }
input, select, textarea{ font-family:inherit; font-size:var(--fs-text); color:inherit; }
img{ max-width:100%; display:block; }
svg{ display:block; }
::selection{ background:var(--primary); color:#fff; }

a:focus-visible, button:focus-visible, .btn:focus-visible{
  outline:2px solid var(--primary); outline-offset:2px; border-radius:6px;
}

/* thin, tasteful scrollbars */
::-webkit-scrollbar{ width:8px; height:8px; }
::-webkit-scrollbar-track{ background:transparent; }
::-webkit-scrollbar-thumb{ background:#D1D5DB; border-radius:var(--radius-pill); }
::-webkit-scrollbar-thumb:hover{ background:#9CA3AF; }


/* ==========================================================
   3. LAYOUT
   ========================================================== */
/* Scales the sidebar and the whole working area together - see --app-scale.
   Applied here rather than on body so the login screen, which sits outside the
   shell and is already sized for a single centred card, is left alone.
   Viewport units and the fixed sidebar resolve against the scaled coordinate
   system, so 100vh still means a full screen and the sidebar still spans it. */
.app-shell{ display:flex; min-height:100vh; zoom:var(--app-scale); }

.main{
  margin-left:264px;
  flex:1;
  /* A flex item defaults to min-width:auto, which refuses to shrink below its
     content's intrinsic width - so a wide table (long text, several action
     buttons) pushed the WHOLE page wider than the viewport instead of
     scrolling inside its own .table-wrap (which already has overflow-x:auto).
     That stretched everything sharing this column, including the toolbar
     above the table, which is how a table got wide enough to clip a button
     that has nothing to do with it off the right edge of the screen. */
  min-width:0;
  min-height:100vh;
  display:flex;
  flex-direction:column;
  transition: margin-left var(--med) var(--ease);
}

.content{
  padding:var(--sp-4) var(--sp-5) 56px;
  flex:1;
  animation: fadeIn .35s var(--ease);
}

@keyframes fadeIn{
  from{ opacity:0; transform:translateY(6px); }
  to{ opacity:1; transform:translateY(0); }
}


/* ==========================================================
   4. SIDEBAR
   ========================================================== */
.sidebar{
  width:264px;
  background:var(--grad-sidebar);
  color:var(--sidebar-text);
  flex-shrink:0;
  position:fixed;
  top:0; left:0; bottom:0;
  overflow-y:auto;
  z-index:100;
  display:flex;
  flex-direction:column;
  box-shadow:1px 0 0 rgba(255,255,255,.04), 8px 0 30px rgba(0,0,0,.15);
  transition: transform var(--med) var(--ease);
}

.sidebar-brand{
  display:flex; align-items:center; gap:12px;
  padding:24px 22px;
  border-bottom:1px solid rgba(255,255,255,.06);
}
.sidebar-brand .logo-badge{
  width:38px; height:38px; border-radius:11px;
  background:linear-gradient(135deg, var(--primary), var(--secondary));
  display:flex; align-items:center; justify-content:center;
  font-weight:700; color:#fff; font-size:16px;
  box-shadow:0 6px 16px rgba(79,70,229,.4);
}
.sidebar-brand span{ font-size:16px; font-weight:700; color:#fff; letter-spacing:.1px; }
.sidebar-brand small{ display:block; font-size:11.5px; color:var(--text-light); font-weight:400; margin-top:1px; }

/* This is the gap between one section's last item and the next section's
   label - e.g. between Dashboard (Overview) and Leads (Sales Pipeline) - and
   it is fixed at this size no matter how many items sit in either section, so
   every role sees the same rhythm whether Custom Role access grants it one
   module or ten. Originally 20px+8px, which read as a whole extra empty row. */
.nav-section-label{
  font-size:11px; text-transform:uppercase; letter-spacing:.09em;
  color:#4B5563; font-weight:600;
  padding:12px 22px 4px;
}
/* The very first section (Overview) sits right under the brand, which already
   has its own padding and a bottom border for separation - a second helping
   of top padding here on top of that would be redundant. */
.sidebar-brand + .nav-section-label{ padding-top:8px; }

/* No flex:1 here - .sidebar-footer's margin-top:auto already pushes it to the bottom on
   its own. flex:1 on every section's <ul> made each one stretch to soak up whatever
   vertical space was left over, which showed up as a growing blank gap after a section's
   last item whenever a user had few enough modules enabled that the nav didn't fill the
   sidebar - the fewer the modules, the bigger the gaps. */
.sidebar-nav{ padding:2px 14px; }
.sidebar-nav li{ margin-bottom:3px; position:relative; }

.sidebar-nav a{
  display:flex; align-items:center; gap:13px;
  padding:11px 14px; border-radius:10px;
  color:var(--sidebar-text); font-size:var(--fs-sidebar); font-weight:500;
  transition: background var(--fast) var(--ease), color var(--fast) var(--ease), padding-left var(--fast) var(--ease);
  position:relative;
}
.sidebar-nav a .icon{
  font-size:16px; width:20px; text-align:center; flex-shrink:0;
  color:var(--text-light); transition:color var(--fast) var(--ease);
}
.sidebar-nav a:hover{ background:var(--sidebar-hover); color:#fff; padding-left:18px; }
.sidebar-nav a:hover .icon{ color:#fff; }

.sidebar-nav a.active{
  background:var(--grad-primary);
  color:#fff;
  box-shadow:0 6px 16px rgba(79,70,229,.35), inset 0 1px 0 rgba(255,255,255,.15);
}
.sidebar-nav a.active .icon{ color:#fff; }
.sidebar-nav a.active::before{
  content:'';
  position:absolute; left:-14px; top:50%; transform:translateY(-50%);
  width:4px; height:60%; border-radius:0 4px 4px 0;
  background:#fff;
}

.sidebar-nav a.badge-count::after{
  content:attr(data-count);
  margin-left:auto;
  background:rgba(255,255,255,.15);
  padding:1px 9px; border-radius:var(--radius-pill); font-size:11px; font-weight:600;
}

/*
 * Collapsible sidebar groups (e.g. CRM -> Leads/Deals, with Reports nested a level
 * further in) - see sbNavGroup() in includes/sidebar.php. The toggle's onclick there
 * only ever flips the .open class; every bit of actual show/hide and the caret
 * rotation lives here, which is why the dropdown looked completely inert (click did
 * nothing visible) before these rules existed at all - .nav-sub had no display:none
 * to begin with, so there was nothing for .open to meaningfully change.
 */
.nav-caret{
  margin-left:auto; font-size:12px; color:var(--text-light);
  transition:transform var(--fast) var(--ease), color var(--fast) var(--ease);
}
.nav-group.open > .nav-group-toggle .nav-caret{ transform:rotate(180deg); }
.nav-group-toggle.group-active{ color:#fff; }
.nav-group-toggle.group-active .icon,
.nav-group-toggle.group-active .nav-caret{ color:#fff; }

.nav-sub{
  max-height:0; overflow:hidden;
  transition:max-height var(--med) var(--ease);
}
.nav-group.open > .nav-sub{ max-height:1000px; }

.nav-sub li{ margin-bottom:0; }
.nav-sub > li > a{ padding-left:48px; font-size:calc(var(--fs-sidebar) - 1px); }
.nav-sub > li > a:hover{ padding-left:52px; }
.nav-sub > li > a.active::before{ left:-14px; }
/* A second-level group (CRM -> Reports -> Lead/Deal Reports) nests one more
   level of indentation and reuses the same caret/collapse rules above - the
   selectors are written generically (.nav-group/.nav-sub) rather than only
   matching the top level for exactly that reason. */
.nav-sub .nav-group > .nav-group-toggle{ padding-left:48px; font-size:calc(var(--fs-sidebar) - 1px); }
.nav-sub .nav-sub > li > a{ padding-left:62px; }
.nav-sub .nav-sub > li > a:hover{ padding-left:66px; }

.sidebar-footer{
  padding:16px 22px 22px;
  border-top:1px solid rgba(255,255,255,.06);
  margin-top:auto;
}


/* ==========================================================
   5. TOPBAR
   ========================================================== */
.topbar{
  height:72px;
  background:var(--card);
  box-shadow:0 1px 0 var(--border), 0 4px 16px rgba(15,23,42,.03);
  display:flex; align-items:center; justify-content:space-between;
  padding:0 var(--sp-5);
  position:sticky; top:0; z-index:50;
  backdrop-filter:saturate(180%) blur(6px);
}
.topbar-left{ display:flex; align-items:center; gap:16px; }
.menu-toggle{
  display:none; font-size:18px; color:var(--text);
  width:38px; height:38px; align-items:center; justify-content:center;
  border-radius:10px; transition:background var(--fast);
}
.menu-toggle:hover{ background:var(--bg); }

.breadcrumb{ display:flex; align-items:center; gap:6px; font-size:12.5px; color:var(--text-muted); margin-bottom:2px; }
.breadcrumb .sep{ opacity:.5; }
.breadcrumb .current{ color:var(--text); font-weight:600; }

.page-title{ font-size:19px; font-weight:700; letter-spacing:-.2px; }
.page-subtitle{ font-size:12.5px; color:var(--text-muted); margin-top:2px; }

.search-box{
  display:flex; align-items:center; gap:10px;
  background:var(--bg); border:1px solid var(--border);
  border-radius:var(--radius-sm); padding:9px 14px; width:300px;
  transition:border-color var(--fast), box-shadow var(--fast);
}
.search-box:focus-within{ border-color:var(--primary); box-shadow:0 0 0 3px var(--primary-light); background:var(--card); }
.search-box input{ border:none; background:none; outline:none; width:100%; color:var(--text); font-size:13.5px; }
.search-box .icon{ color:var(--text-muted); font-size:14px; }

.topbar-right{ display:flex; align-items:center; gap:16px; }

.icon-btn{
  width:40px; height:40px; border-radius:11px;
  display:flex; align-items:center; justify-content:center;
  background:var(--bg); color:var(--text-muted); font-size:16px;
  position:relative; transition:background var(--fast), color var(--fast), transform var(--fast);
}
.icon-btn:hover{ background:var(--primary-light); color:var(--primary); transform:translateY(-1px); }
.icon-btn .dot{
  position:absolute; top:7px; right:8px;
  width:8px; height:8px; border-radius:50%; background:var(--danger);
  border:2px solid var(--card);
}
.icon-btn .count-badge{
  position:absolute; top:1px; right:1px;
  min-width:16px; height:16px; padding:0 4px; box-sizing:border-box;
  border-radius:999px; background:var(--danger); color:#fff;
  border:2px solid var(--card);
  display:flex; align-items:center; justify-content:center;
  font-size:10px; font-weight:700; line-height:1;
}

/* dropdown shell used for notifications / messages / profile */
.dropdown{ position:relative; }
.dropdown-menu{
  position:absolute; top:calc(100% + 10px); right:0;
  background:var(--card); border:1px solid var(--border); border-radius:var(--radius);
  box-shadow:var(--shadow-lg); width:320px; z-index:200; overflow:hidden;
  opacity:0; visibility:hidden; transform:translateY(-6px);
  transition:opacity var(--fast) var(--ease), transform var(--fast) var(--ease), visibility var(--fast);
}
.dropdown-menu.open{ opacity:1; visibility:visible; transform:translateY(0); }
.dropdown-menu .dd-head{ padding:14px 16px; border-bottom:1px solid var(--border); font-weight:700; font-size:13.5px; }

/* A long list (notifications returns up to 20) would otherwise run off the bottom of the
   viewport with nothing to scroll - the menu is absolutely positioned, so the overflow is
   simply unreachable. Cap the list itself rather than the menu, so .dd-head and its
   "Mark all read" action stay pinned while the items scroll under it. */
.dropdown-menu .dd-scroll{ max-height:min(380px, calc(100vh - 140px)); overflow-y:auto; overscroll-behavior:contain; }
.dropdown-menu .dd-item{ display:flex; gap:12px; padding:12px 16px; border-bottom:1px solid var(--border); transition:background var(--fast); }
.dropdown-menu .dd-item:hover{ background:var(--bg); }
.dropdown-menu .dd-item:last-child{ border-bottom:none; }
.dropdown-menu .dd-foot{ padding:10px 16px; text-align:center; font-size:12.5px; font-weight:600; color:var(--primary); }

.user-chip{ display:flex; align-items:center; gap:10px; cursor:pointer; padding:4px; border-radius:12px; transition:background var(--fast); }
.user-chip:hover{ background:var(--bg); }
.user-avatar{
  width:40px; height:40px; border-radius:50%;
  background:linear-gradient(135deg, var(--primary), var(--secondary));
  color:#fff; display:flex; align-items:center; justify-content:center;
  font-weight:700; font-size:14px; flex-shrink:0; overflow:hidden;
}
.user-avatar img{ width:100%; height:100%; object-fit:cover; border-radius:50%; }
.user-meta{ line-height:1.25; }
.user-meta .u-name{ font-size:13.5px; font-weight:600; }
.user-meta .u-role{ font-size:11.5px; color:var(--text-muted); }

/* profile avatar upload widget (used in the "My Profile" modal) */
.avatar-upload{ position:relative; width:96px; height:96px; }
.avatar-upload-preview{
  width:96px; height:96px; border-radius:50%; overflow:hidden;
  background:linear-gradient(135deg, var(--primary), var(--secondary));
  display:flex; align-items:center; justify-content:center;
  color:#fff; font-weight:700; font-size:28px;
  border:3px solid var(--card); box-shadow:var(--shadow-sm);
}
.avatar-upload-preview img{ width:100%; height:100%; object-fit:cover; }
.avatar-upload-btn{
  position:absolute; bottom:-2px; right:-2px;
  width:32px; height:32px; border-radius:50%;
  background:var(--primary); color:#fff; display:flex; align-items:center; justify-content:center;
  font-size:13px; cursor:pointer; border:3px solid var(--card);
  transition:background var(--fast), transform var(--fast);
}
.avatar-upload-btn:hover{ background:var(--primary-dark); transform:scale(1.06); }


/* ==========================================================
   6. CARDS
   ========================================================== */
.grid{ display:grid; gap:var(--sp-4); }
.grid-4{ grid-template-columns:repeat(4,1fr); }
.grid-3{ grid-template-columns:repeat(3,1fr); }
.grid-2{ grid-template-columns:repeat(2,1fr); }
.grid-span-2{ grid-column:span 2; }

.card{
  background:var(--card); border-radius:var(--radius-lg); padding:var(--sp-4);
  box-shadow:var(--shadow-sm); border:1px solid var(--border);
  position:relative; overflow:hidden;
  transition: box-shadow var(--med) var(--ease), transform var(--med) var(--ease);
}
.card::before{
  content:''; position:absolute; top:0; left:0; right:0; height:1px;
  background:linear-gradient(90deg, transparent, rgba(255,255,255,.9), transparent);
}
.card:hover{ box-shadow:var(--shadow); transform:translateY(-2px); }

/* card rendered as an <a> - a clickable KPI card that drills into a details page */
a.card-link{ display:block; color:inherit; text-decoration:none; cursor:pointer; }
a.card-link:hover{ border-color:var(--primary); }
a.card-link .card-link-hint{
  font-size:11px; font-weight:600; color:var(--primary); margin-top:10px;
  display:flex; align-items:center; gap:4px; opacity:0; transform:translateX(-4px);
  transition:opacity var(--fast) var(--ease), transform var(--fast) var(--ease);
}
a.card-link:hover .card-link-hint{ opacity:1; transform:translateX(0); }

.card-title{ font-size:var(--fs-section-title); font-weight:700; letter-spacing:-.3px; }
.card-sub{ font-size:12.5px; color:var(--text-muted); margin-top:2px; }
.card-head{ display:flex; align-items:center; justify-content:space-between; margin-bottom:var(--sp-3); gap:12px; }

.kpi-card{ display:flex; align-items:flex-start; justify-content:space-between; gap:14px; }
/* higher specificity than `a.card-link` alone, so a clickable KPI card keeps its flex layout
   instead of falling back to card-link's block display */
a.card-link.kpi-card{ display:flex; align-items:flex-start; justify-content:space-between; gap:14px; }
/* text side must be allowed to shrink/wrap so a long value never pushes the icon past
   the card's own padding — a flex item's default min-width is auto (its content's natural
   width), which is what let the icon get shoved to the edge or clipped by .card's overflow */
.kpi-card > div:first-child{ min-width:0; flex:1 1 auto; }
.kpi-value{ overflow-wrap:break-word; }
.kpi-icon{
  width:48px; height:48px; border-radius:13px;
  display:flex; align-items:center; justify-content:center; font-size:19px;
  transition:transform var(--med) var(--ease);
  flex-shrink:0;
}
.card:hover .kpi-icon{ transform:scale(1.08) rotate(-4deg); }
.kpi-icon.purple{ background:radial-gradient(circle at 30% 25%, #F1EEFF, var(--purple-bg)); color:var(--purple); box-shadow:inset 0 0 0 1px rgba(139,92,246,.12); }
.kpi-icon.blue{ background:radial-gradient(circle at 30% 25%, #F0FDFF, var(--info-bg)); color:var(--info); box-shadow:inset 0 0 0 1px rgba(6,182,212,.12); }
.kpi-icon.green{ background:radial-gradient(circle at 30% 25%, #F2FFF7, var(--success-bg)); color:var(--success); box-shadow:inset 0 0 0 1px rgba(34,197,94,.12); }
.kpi-icon.orange{ background:radial-gradient(circle at 30% 25%, #FFFCF0, var(--warning-bg)); color:var(--warning); box-shadow:inset 0 0 0 1px rgba(245,158,11,.12); }
.kpi-icon.red{ background:radial-gradient(circle at 30% 25%, #FFF3F3, var(--danger-bg)); color:var(--danger); box-shadow:inset 0 0 0 1px rgba(239,68,68,.12); }

.kpi-value{ font-size:var(--fs-card-number); font-weight:800; margin-top:16px; letter-spacing:-.6px; }
.kpi-label{ font-size:12.5px; color:var(--text-muted); margin-top:4px; font-weight:500; }
.kpi-trend{ font-size:11.5px; font-weight:700; margin-top:10px; display:inline-flex; align-items:center; gap:4px; }
.kpi-trend.up{ color:var(--success); }
.kpi-trend.down{ color:var(--danger); }

/* Compact stat rows - groups several related secondary metrics inside one card instead
   of a separate small box per number, so a dashboard reads as a few clear panels rather
   than a wall of identical tiles. */
.stat-list{ display:flex; flex-direction:column; }
.stat-row{
  display:flex; align-items:center; justify-content:space-between; gap:16px;
  padding:13px 2px; border-bottom:1px solid var(--border);
}
.stat-row:last-child{ border-bottom:none; padding-bottom:2px; }
.stat-row:first-child{ padding-top:10px; }
.stat-row-label{ display:flex; align-items:center; gap:10px; font-size:13.5px; color:var(--text); font-weight:500; }
.stat-row-label .dot{ width:8px; height:8px; border-radius:50%; flex-shrink:0; }
.stat-row-value{ font-weight:700; font-size:14px; text-align:right; white-space:nowrap; }
.stat-row-value .stat-sub{ display:block; font-size:11px; font-weight:500; color:var(--text-muted); margin-top:1px; }
/* highlight-on-change tuned for a flat row (background wash) rather than a floating card (box-shadow) */
.stat-row.kpi-flash{ animation:statRowFlash 1.2s var(--ease); border-radius:8px; }
.stat-row.clickable{ cursor:pointer; border-radius:8px; margin:0 -8px; padding-left:8px; padding-right:8px; transition:background var(--fast); }
.stat-row.clickable:hover{ background:var(--bg); }
@keyframes statRowFlash{
  0%{ background:var(--primary-light); }
  100%{ background:transparent; }
}

/* Lead Status card: each status as an icon-led row with a "N Leads" count, divided by hairlines. */
.lead-status-list{ display:flex; flex-direction:column; margin-top:10px; }
.lead-status-row{
  display:flex; align-items:center; gap:14px;
  padding:16px 10px; margin:0 -10px; border-radius:10px;
  border-bottom:1px solid var(--border);
  transition:background var(--fast) var(--ease);
}
.lead-status-row:hover{ background:var(--bg); }
.lead-status-row:last-child{ border-bottom:none; padding-bottom:8px; }
.lead-status-row:first-child{ padding-top:14px; }
.lead-status-icon{
  width:38px; height:38px; border-radius:11px; font-size:15px; flex-shrink:0;
  display:flex; align-items:center; justify-content:center;
  transition:transform var(--med) var(--ease);
}
.lead-status-row:hover .lead-status-icon{ transform:scale(1.08) rotate(-4deg); }
.lead-status-info{ display:flex; flex-direction:column; gap:4px; }
.lead-status-name{ font-size:13.5px; line-height:1.4; font-weight:600; color:var(--text); }
.lead-status-count{ font-size:12px; line-height:1.4; color:var(--text-muted); font-weight:500; }

/* Payment Status card: each row as a horizontal progress bar (share of total) instead
   of a dot + number, since a payment breakdown reads more clearly as a proportion. */
.progress-stat-list{ display:flex; flex-direction:column; gap:16px; }
.progress-stat-row:first-child{ margin-top:10px; }
.progress-stat-top{ display:flex; align-items:center; justify-content:space-between; gap:12px; margin-bottom:8px; }
.progress-stat-label{ font-size:13.5px; font-weight:600; color:var(--text); }
.progress-stat-value{ font-weight:700; font-size:14px; white-space:nowrap; }
/* thicker highlighted track + a glow on the fill so the active share stands out */
.progress-bar-highlight{ height:10px; }
.progress-bar-highlight > div{ position:relative; transition:width var(--med) var(--ease); }


/* ==========================================================
   7. TABLES
   ========================================================== */
.table-wrap{ overflow-x:auto; border-radius:var(--radius); }
table.data-table{ width:100%; border-collapse:separate; border-spacing:0; font-size:var(--fs-small); }
table.data-table thead th{
  position:sticky; top:0; z-index:1;
  text-align:left; padding:13px 16px; color:var(--text-muted); background:var(--card);
  font-weight:600; font-size:11.5px; text-transform:uppercase; letter-spacing:.04em;
  border-bottom:1px solid var(--border); white-space:nowrap;
}
table.data-table td{
  padding:14px 16px; border-bottom:1px solid var(--border); white-space:nowrap;
  transition:background var(--fast);
}
table.data-table tr:last-child td{ border-bottom:none; }
table.data-table tbody tr{ transition:background var(--fast); }
table.data-table tbody tr:hover td{ background:var(--bg); }

.cell-strong{ font-weight:600; }
.role-link{ color:var(--primary); font-weight:600; cursor:pointer; }
.role-link:hover{ text-decoration:underline; }
.cell-muted{ color:var(--text-muted); }
.row-actions{ display:flex; gap:6px; }
/* When .row-actions sits on the <td> itself, flex takes the cell out of table
   layout and its column stops sharing widths/baseline with the rest of the row. */
table.data-table td.row-actions{ display:table-cell; vertical-align:middle; white-space:nowrap; }
table.data-table td.row-actions > .btn{ vertical-align:middle; }
table.data-table td.row-actions > .btn + .btn{ margin-left:6px; }

/* Alignment helpers — apply the same class to the th and its tds so a column's
   header can never drift out of line with its own cells. */
table.data-table th.tcol-center, table.data-table td.tcol-center{ text-align:center; }
table.data-table th.tcol-right, table.data-table td.tcol-right{ text-align:right; }
/* Numeric columns: header and figures centred together, on every page */
table.data-table th.sm-num, table.data-table td.sm-num,
table.data-table th.sl-num, table.data-table td.sl-num,
table.data-table th.sr-num, table.data-table td.sr-num,
table.data-table th.rp-num, table.data-table td.rp-num,
table.data-table th.st-num, table.data-table td.st-num{ text-align:center; font-variant-numeric:tabular-nums; }
table.data-table td{ vertical-align:middle; }

/* Badge columns: a .badge carries 12px of its own left padding, so its text
   starts ~12px inside the cell while a plain-text column's starts at the cell
   edge. Left-aligned pill columns therefore look indented against their header
   and against their neighbours. Inset the header by the same amount so the
   header label and the pill label share one edge. */
table.data-table th.tcol-badge{ padding-left:28px; }
table.data-table th.tcol-badge, table.data-table td.tcol-badge{ text-align:left; }

/* Grouped tables: the spanning label row is a separator, not a data row. */
table.data-table tbody tr.group-row td{
  background:var(--bg); font-weight:700; font-size:12.5px;
  border-top:1px solid var(--border); padding-top:10px; padding-bottom:10px;
}
table.data-table tbody tr.group-row:first-child td{ border-top:none; }
table.data-table tbody tr.group-row:hover td{ background:var(--bg); }

/* One issued unit and its captured details, marked Matches / Doesn't match by
   the technician. Two layouts share these rules:
     div.unit-check - a card, used by the my_requests.php modal
     tr.unit-check  - a data-table row, used by Confirm Receipts
   A <tr> ignores border/padding/margin, so its confirmed/flagged state is
   carried on the cells instead. */
div.unit-check{
  border:1px solid var(--border); border-radius:8px; padding:12px 14px; margin-bottom:10px;
  background:var(--bg);
}
div.unit-check.is-confirmed{ border-color:#16a34a; background:rgba(22,163,74,.05); }
div.unit-check.is-flagged{ border-color:#ef4444; background:rgba(239,68,68,.05); }

tr.unit-check.is-confirmed > td{ background:rgba(22,163,74,.06); }
tr.unit-check.is-flagged > td{ background:rgba(239,68,68,.06); }
/* Beats the table's own row-hover, so a marked row keeps reading as marked. */
table.data-table tbody tr.unit-check.is-confirmed:hover > td{ background:rgba(22,163,74,.1); }
table.data-table tbody tr.unit-check.is-flagged:hover > td{ background:rgba(239,68,68,.1); }
tr.unit-check > td{ vertical-align:top; }

.unit-check .unit-check-head{ display:flex; justify-content:space-between; align-items:center; gap:8px; flex-wrap:wrap; }
.unit-check .unit-code{ font-weight:600; }
.unit-check .attr-list{ margin:10px 0 0 0; display:grid; grid-template-columns:repeat(auto-fit,minmax(190px,1fr)); gap:6px; }
/* In a table cell the column is already narrow, so the values stack rather
   than competing for width with the other columns. */
tr.unit-check .attr-list{ margin:0; grid-template-columns:1fr; min-width:180px; }
.unit-check .attr-list .attr{
  font-size:12.5px; background:var(--card); border:1px solid var(--border);
  border-radius:6px; padding:6px 9px;
}
.unit-check .attr .attr-label{ color:var(--text-muted); display:block; font-size:11px; }
.unit-check .attr .attr-value{ font-weight:600; word-break:break-all; }
.unit-check .flag-note-wrap{ margin-top:10px; display:none; }
.unit-check.is-flagged .flag-note-wrap{ display:block; }
tr.unit-check .flag-note-wrap{ min-width:200px; }
.confirm-hint{ font-size:12.5px; color:var(--text-muted); margin-bottom:12px; }

.table-toolbar{ display:flex; align-items:center; justify-content:space-between; gap:12px; margin-bottom:var(--sp-3); flex-wrap:wrap; }
.table-filter-bar{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; }

.pagination{ display:flex; align-items:center; justify-content:flex-end; gap:6px; margin-top:var(--sp-3); }
.pagination a, .pagination span{
  min-width:34px; height:34px; padding:0 6px; display:flex; align-items:center; justify-content:center;
  border-radius:9px; font-size:12.5px; font-weight:600; color:var(--text-muted); border:1px solid var(--border);
  transition:background var(--fast), color var(--fast), border-color var(--fast);
}
.pagination a:hover{ border-color:var(--primary); color:var(--primary); }
.pagination .active{ background:var(--primary); color:#fff; border-color:var(--primary); }


/* ==========================================================
   8. FORMS
   ========================================================== */
/* min-width:0 - a field in a .form-row grid column may shrink to the column; without it a long
   one-line value (a picked employee "Name · Role · Department") widened the column and pushed the
   row past its popup, which then scrolled sideways and cut fields off. */
.form-group{ margin-bottom:var(--sp-3); position:relative; min-width:0; }
.form-group label{ display:block; font-size:12.5px; font-weight:600; margin-bottom:6px; color:var(--text); }

.form-control{
  width:100%; padding:11px 14px; border:1px solid var(--border); border-radius:var(--radius-sm);
  background:#FBFBFE; outline:none; font-size:14px; color:var(--text); line-height:1.4;
  transition:border-color var(--fast) var(--ease), box-shadow var(--fast) var(--ease), background var(--fast);
}
.form-control:focus{ border-color:var(--primary); background:var(--card); box-shadow:0 0 0 4px var(--primary-light); }
/* A readonly field is filled in from somewhere else (the lead form's Company Information
   comes from the selected customer), so the BOX reads as not typable - tinted background,
   softened border, no focus ring, since nothing happens when you click it. The value itself
   keeps full --text strength: it is real data to be read, and dimming it made a correctly
   filled form look disabled or half-loaded. */
.form-control[readonly]{
  background:var(--readonly-bg); color:var(--text); cursor:not-allowed; border-color:var(--readonly-border);
}
.form-control[readonly]:focus{ border-color:var(--readonly-border); background:var(--readonly-bg); box-shadow:none; }
.form-control.is-invalid{ border-color:var(--danger); box-shadow:0 0 0 4px var(--danger-bg); }
.form-control.is-valid{ border-color:var(--success); box-shadow:0 0 0 4px var(--success-bg); }
textarea.form-control{ resize:vertical; min-height:90px; }
select.form-control{
  appearance:none; -webkit-appearance:none; -moz-appearance:none;
  padding-right:38px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%236B7280' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;
  background-position:right 14px center;
}
.form-row{ display:grid; grid-template-columns:1fr 1fr; gap:var(--sp-3); }
.form-hint{ font-size:11.5px; color:var(--text-muted); margin-top:5px; }
.form-error{ font-size:11.5px; color:var(--danger); margin-top:5px; font-weight:500; }

/* Phone field: country code + number as ONE control (see includes/phone_field.php).
   The wrapper carries the border so the pair reads as a single input and lines up with a
   plain .form-control next to it in a .form-row - two separate bordered boxes looked like
   two fields and stood taller than its neighbour. The inner select and input are stripped
   bare; the focus ring moves to the wrapper via :focus-within. */
.phone-field{
  display:flex; align-items:stretch; width:100%;
  border:1px solid var(--border); border-radius:var(--radius-sm);
  background:#FBFBFE; overflow:hidden;
  transition:border-color var(--fast) var(--ease), box-shadow var(--fast) var(--ease), background var(--fast);
}
.phone-field:focus-within{ border-color:var(--primary); background:var(--card); box-shadow:0 0 0 4px var(--primary-light); }
.phone-field.is-invalid{ border-color:var(--danger); box-shadow:0 0 0 4px var(--danger-bg); }
.phone-field .phone-dial-trigger,
.phone-field input{
  border:0; outline:none; background:transparent; font-size:14px; color:var(--text);
  line-height:1.4; padding:11px 0; min-width:0;
}
/* The native <select> is kept in the DOM as the value holder every script still reads, but
   it is never shown: its OS-drawn menu flips above the field low in a modal and is as wide
   as its widest option. The button below replaces it (see includes/phone_field_script.php). */
.phone-field select{ display:none; }
/* Fixed at the width of "+971" plus its chevron, so the control never jumps as the country
   changes and the number - the part anyone actually reads - keeps the rest of the field. */
.phone-field .phone-dial-trigger{
  flex:none; width:70px; padding-left:12px; padding-right:8px; font-weight:600;
  display:flex; align-items:center; gap:5px; cursor:pointer; text-align:left;
  font-family:inherit;
}
.phone-field .phone-dial-code{ flex:1; }
.phone-field .phone-dial-caret{
  flex:none; width:10px; height:6px;
  background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%236B7280' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat center;
  transition:transform var(--fast) var(--ease);
}
.phone-field .phone-dial-trigger[aria-expanded="true"] .phone-dial-caret{ transform:rotate(180deg); }
.phone-field input{ flex:1; padding-left:10px; padding-right:14px; }
.phone-field .phone-divider{ width:1px; background:var(--border); margin:7px 0; flex:none; }
/* Same treatment as .form-control[readonly] - the box tints as one piece so a phone filled
   in from the customer record does not look typable, and the number stays full strength. */
.phone-field:has(input:read-only){ background:var(--readonly-bg); border-color:var(--readonly-border); }
.phone-field:has(input:read-only):focus-within{ border-color:var(--readonly-border); box-shadow:none; }
.phone-field .phone-dial-trigger:disabled,
.phone-field input:read-only{ color:var(--text); cursor:not-allowed; }
/* Hidden until there is something wrong, so an empty message reserves NO height and the
   field stays exactly as tall as the input beside it. */
.phone-error{ display:none; font-size:11.5px; color:var(--danger); margin-top:5px; font-weight:500; }
.phone-error.show{ display:block; }

/* The open country list. Lives on <body> and is position:fixed - anchored to the field by
   script - so a modal's own overflow can never clip it, and it sits above the modal. Wide
   enough for the country name beside the code, which is the whole point of not using the
   native menu: "+91  India" instead of a bare "+91" nobody can read a tooltip on. */
.phone-dial-panel{
  display:none; position:fixed; z-index:2200; max-height:280px; overflow-y:auto;
  padding:6px; background:var(--card); border:1px solid var(--border);
  border-radius:var(--radius-sm); box-shadow:0 12px 32px rgba(16,24,40,.16);
}
.phone-dial-panel.show{ display:block; }
.phone-dial-option{
  display:flex; align-items:center; gap:10px; width:100%; padding:8px 10px;
  border:0; background:transparent; border-radius:var(--radius-sm);
  font-family:inherit; font-size:13.5px; color:var(--text); text-align:left; cursor:pointer;
  transition:background var(--fast) var(--ease);
}
.phone-dial-option:hover{ background:var(--bg); }
.phone-dial-option.is-selected{ background:var(--primary-light); color:var(--primary); font-weight:600; }
/* Fixed-width code column so the country names line up as one list rather than a ragged
   left edge that shifts with every "+1" / "+971". */
.phone-dial-option-code{ flex:none; width:46px; font-weight:600; font-variant-numeric:tabular-nums; }
.phone-dial-option-name{ flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }

/* Password field with a show/hide eye toggle - wrap the input in
   <div class="password-field">...<input>...<button class="password-toggle">...</button></div> */
.password-field{ position:relative; }
.password-field .form-control{ padding-right:42px; }
.password-toggle{
  position:absolute; right:4px; top:50%; transform:translateY(-50%);
  width:32px; height:32px; display:flex; align-items:center; justify-content:center;
  border:none; background:transparent; color:var(--text-muted); cursor:pointer;
  border-radius:var(--radius-sm); transition:color var(--fast) var(--ease), background var(--fast) var(--ease);
}
.password-toggle:hover{ color:var(--text); background:var(--bg); }
/* cursor:default, not not-allowed - the browser's "not-allowed" icon reads as a red
   error/blocked cue, but a disabled eye toggle isn't an error, just nothing-to-reveal yet */
.password-toggle:disabled{ opacity:.35; cursor:default; }
.password-toggle:disabled:hover{ background:transparent; }

/* floating label variant (opt-in via .form-group.floating) */
.form-group.floating{ padding-top:6px; }
.form-group.floating label{
  position:absolute; left:14px; top:17px; margin:0;
  font-size:14px; color:var(--text-muted); font-weight:400;
  background:transparent; pointer-events:none;
  transition:all var(--fast) var(--ease);
}
.form-group.floating .form-control:focus + label,
.form-group.floating .form-control:not(:placeholder-shown) + label{
  top:-8px; left:11px; font-size:11px; font-weight:600; color:var(--primary);
  background:var(--card); padding:0 5px;
}

.checkbox-row{ display:flex; align-items:center; gap:8px; font-size:13.5px; color:var(--text); }
.checkbox-row input[type="checkbox"]{ width:16px; height:16px; accent-color:var(--primary); }


/* ==========================================================
   9. BUTTONS
   ========================================================== */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:8px;
  padding:10px 18px; border-radius:var(--radius-sm); font-size:var(--fs-button); font-weight:600;
  transition:all var(--fast) var(--ease); white-space:nowrap; position:relative;
}
.btn:active{ transform:scale(.97); }

.btn-primary{ background:var(--grad-primary); color:#fff; box-shadow:0 4px 12px rgba(79,70,229,.3), inset 0 1px 0 rgba(255,255,255,.2); }
.btn-primary:hover{ background:var(--grad-primary-hover); transform:translateY(-1px); box-shadow:0 8px 20px rgba(79,70,229,.4), inset 0 1px 0 rgba(255,255,255,.25); }

.btn-secondary{ background:var(--secondary-light); color:var(--secondary); }
.btn-secondary:hover{ background:var(--secondary); color:#fff; }

.btn-outline{ background:var(--card); border:1px solid var(--border); color:var(--text); }
.btn-outline:hover{ border-color:var(--primary); color:var(--primary); transform:translateY(-1px); box-shadow:var(--shadow-sm); }

.btn-danger{ background:var(--danger-bg); color:var(--danger); }
.btn-danger:hover{ background:linear-gradient(135deg,#F87171,var(--danger)); color:#fff; box-shadow:0 6px 16px rgba(239,68,68,.3); }

.btn-ghost{ background:transparent; color:var(--text-muted); }
.btn-ghost:hover{ background:var(--bg); color:var(--text); }

.btn-sm{ padding:7px 13px; font-size:12.5px; border-radius:8px; }
.btn-lg{ padding:13px 24px; font-size:15px; }
.btn-icon{ width:38px; height:38px; padding:0; justify-content:center; border-radius:9px; }
.btn-block{ width:100%; }
.btn:disabled{ opacity:.5; cursor:not-allowed; transform:none !important; }

/* loading state: add .is-loading + keep label markup; spinner overlays via ::after */
.btn.is-loading{ color:transparent !important; pointer-events:none; }
.btn.is-loading::after{
  content:''; position:absolute; width:16px; height:16px; border-radius:50%;
  border:2px solid rgba(255,255,255,.4); border-top-color:#fff;
  animation:spin .6s linear infinite;
}
.btn-outline.is-loading::after, .btn-ghost.is-loading::after{ border-color:rgba(79,70,229,.25); border-top-color:var(--primary); }
@keyframes spin{ to{ transform:rotate(360deg); } }


/* ==========================================================
   10. MODALS
   ========================================================== */
.modal-overlay{
  position:fixed; inset:0; background:rgba(15,23,42,.55);
  backdrop-filter:blur(4px);
  display:none; align-items:center; justify-content:center; z-index:1000; padding:20px;
  animation:overlayIn var(--med) var(--ease);
}
.modal-overlay.open{ display:flex; }
@keyframes overlayIn{ from{ opacity:0; } to{ opacity:1; } }

.modal-box{
  background:var(--card); border-radius:var(--radius-lg); width:100%; max-width:520px;
  max-height:90vh; overflow-y:auto; box-shadow:var(--shadow-lg);
  animation:modalIn var(--med) var(--ease);
}
.modal-box.modal-lg{ max-width:760px; }
@keyframes modalIn{ from{ opacity:0; transform:translateY(16px) scale(.98); } to{ opacity:1; transform:translateY(0) scale(1); } }

.modal-head{ display:flex; align-items:center; justify-content:space-between; padding:20px 24px; border-bottom:1px solid var(--border); }
.modal-head h3{ font-size:16px; font-weight:700; }
.modal-close{
  font-size:16px; color:var(--text-muted); width:32px; height:32px; border-radius:9px;
  display:flex; align-items:center; justify-content:center; transition:background var(--fast), color var(--fast);
}
.modal-close:hover{ background:var(--danger-bg); color:var(--danger); }

/* Enable/Disable pill toggle - e.g. a record's Active/Inactive flag, distinct from its
   business workflow status. Wraps a real checkbox for keyboard/click semantics. */
.toggle-switch{ position:relative; display:inline-block; width:40px; height:22px; flex-shrink:0; }
.toggle-switch input{ position:absolute; opacity:0; width:100%; height:100%; margin:0; cursor:pointer; }
.toggle-switch .toggle-track{
  position:absolute; inset:0; background:var(--border); border-radius:999px;
  transition:background var(--fast) var(--ease);
}
.toggle-switch .toggle-thumb{
  position:absolute; top:2px; left:2px; width:18px; height:18px; border-radius:50%;
  background:#fff; box-shadow:var(--shadow-sm); transition:transform var(--fast) var(--ease);
}
.toggle-switch input:checked ~ .toggle-track{ background:var(--success); }
.toggle-switch input:checked ~ .toggle-track .toggle-thumb{ transform:translateX(18px); }
.toggle-switch input:disabled ~ .toggle-track{ opacity:.5; cursor:not-allowed; }

.modal-body{ padding:22px 24px; }
.modal-foot{ padding:16px 24px; border-top:1px solid var(--border); display:flex; justify-content:flex-end; gap:10px; }

/* Side drawer - e.g. the dashboard's status drill-down. Same overlay idea as a modal, but the
   panel slides in from the right and pins to the full height instead of centering. */
.drawer-overlay{
  position:fixed; inset:0; background:rgba(15,23,42,.55);
  display:none; z-index:1000;
  animation:overlayIn var(--med) var(--ease);
}
.drawer-overlay.open{ display:block; }
.drawer-panel{
  position:absolute; top:0; right:0; height:100%; width:100%; max-width:480px;
  background:var(--card); box-shadow:var(--shadow-lg);
  display:flex; flex-direction:column;
  animation:drawerIn var(--med) var(--ease);
}
@keyframes drawerIn{ from{ transform:translateX(100%); } to{ transform:translateX(0); } }
.drawer-head{ display:flex; align-items:center; justify-content:space-between; padding:20px 24px; border-bottom:1px solid var(--border); }
.drawer-head h3{ font-size:16px; font-weight:700; }
.drawer-body{ padding:20px 24px; overflow-y:auto; flex:1; }
.drawer-list-item{ padding:12px 0; border-bottom:1px solid var(--border); display:flex; align-items:center; justify-content:space-between; gap:10px; }
.drawer-list-item:last-child{ border-bottom:none; }


/* ==========================================================
   11. BADGES & ALERTS
   ========================================================== */
.badge{
  display:inline-flex; align-items:center; gap:5px;
  padding:4px 12px; border-radius:var(--radius-pill); font-size:11.5px; font-weight:700;
}
.badge-dot::before{ content:''; width:6px; height:6px; border-radius:50%; background:currentColor; }
.badge-green{ background:var(--success-bg); color:var(--success); }
.badge-orange{ background:var(--warning-bg); color:var(--warning); }
.badge-red{ background:var(--danger-bg); color:var(--danger); }
.badge-blue{ background:var(--info-bg); color:var(--info); }
.badge-purple{ background:var(--purple-bg); color:var(--purple); }
.badge-gray{ background:#F1F5F9; color:var(--text-muted); }

.alert{
  display:flex; align-items:flex-start; gap:10px;
  padding:14px 16px; border-radius:var(--radius); font-size:13.5px; margin-bottom:var(--sp-3);
  border:1px solid transparent; animation:fadeIn .3s var(--ease);
}
.alert-error{ background:var(--danger-bg); color:var(--danger); border-color:#FCA5A5; }
.alert-success{ background:var(--success-bg); color:#15803D; border-color:#86EFAC; }
.alert-warning{ background:var(--warning-bg); color:#B45309; border-color:#FCD34D; }
.alert-info{ background:var(--info-bg); color:#0E7490; border-color:#67E8F9; }


/* ==========================================================
   12. UTILITIES
   ========================================================== */
.toolbar{ display:flex; align-items:center; justify-content:space-between; margin-bottom:var(--sp-4); gap:12px; flex-wrap:wrap; }
.tabs{ display:flex; gap:4px; background:var(--bg); padding:5px; border-radius:var(--radius-sm); width:fit-content; }
.tabs a{ padding:8px 16px; border-radius:8px; font-weight:600; font-size:13px; color:var(--text-muted); transition:all var(--fast); }
.tabs a.active{ background:var(--card); color:var(--primary); box-shadow:var(--shadow-sm); }

.chart-legend{ display:flex; gap:16px; font-size:12px; color:var(--text-muted); margin-top:12px; flex-wrap:wrap; }
.chart-legend span{ display:inline-flex; align-items:center; gap:6px; }
.chart-legend .dot{ width:8px; height:8px; border-radius:50%; }

.progress-bar{ height:7px; border-radius:var(--radius-pill); background:var(--border); overflow:hidden; }
.progress-bar > div{ height:100%; background:linear-gradient(90deg, var(--primary), var(--secondary)); border-radius:var(--radius-pill); transition:width var(--med) var(--ease); }

.empty-state{ text-align:center; padding:56px 20px; color:var(--text-muted); }
.empty-state i{
  font-size:22px; color:var(--text-light); margin:0 auto 14px; display:flex;
  width:52px; height:52px; align-items:center; justify-content:center;
  border-radius:50%; background:var(--bg);
}

/* flashes a row that was landed on via a global search result */
tr.row-highlight{ animation:rowHighlight 2.2s ease; }
@keyframes rowHighlight{
  0%{ background:var(--primary-light); }
  100%{ background:transparent; }
}

.text-right{ text-align:right; }
.text-muted{ color:var(--text-muted); }
.font-semibold{ font-weight:600; }
.mt-8{ margin-top:8px; } .mt-16{ margin-top:16px; } .mt-24{ margin-top:24px; }
.mb-8{ margin-bottom:8px; } .mb-16{ margin-bottom:16px; } .mb-24{ margin-bottom:24px; }
.flex{ display:flex; } .items-center{ align-items:center; } .justify-between{ justify-content:space-between; }
.gap-8{ gap:8px; } .gap-12{ gap:12px; }
.stack-24{ display:flex; flex-direction:column; gap:24px; }

.animate-fade-in{ animation:fadeIn .3s var(--ease); }
.hover-lift{ transition:transform var(--med) var(--ease), box-shadow var(--med) var(--ease); }
.hover-lift:hover{ transform:translateY(-3px); box-shadow:var(--shadow); }


/* ==========================================================
   13. REAL-TIME DASHBOARD (live badge, refresh transition, skeletons)
   ========================================================== */
.live-status{
  display:inline-flex; align-items:center; gap:8px;
  font-size:12px; font-weight:600; color:var(--text-muted);
  background:var(--card); border:1px solid var(--border);
  padding:7px 14px; border-radius:var(--radius-pill);
  margin-bottom:var(--sp-4); box-shadow:var(--shadow-xs);
}
.live-dot{
  width:8px; height:8px; border-radius:50%; background:var(--success);
  box-shadow:0 0 0 0 rgba(34,197,94,.5);
  animation:livePulse 2s infinite;
}
@keyframes livePulse{
  0%{ box-shadow:0 0 0 0 rgba(34,197,94,.45); }
  70%{ box-shadow:0 0 0 7px rgba(34,197,94,0); }
  100%{ box-shadow:0 0 0 0 rgba(34,197,94,0); }
}

/* applied to #content while a poll is in flight — a soft dim instead of a jarring flash */
.content-refreshing{ opacity:.55; transition:opacity .2s var(--ease); pointer-events:none; }

/* momentary highlight on a KPI card whose value just changed */
.kpi-flash{ animation:kpiFlash 1s var(--ease); }
@keyframes kpiFlash{
  0%{ box-shadow:0 0 0 3px var(--primary-light), var(--shadow-sm); }
  100%{ box-shadow:var(--shadow-sm); }
}

/* skeleton loading shimmer for first paint */
.skeleton{
  background:linear-gradient(90deg, var(--border) 25%, var(--bg) 50%, var(--border) 75%);
  background-size:400% 100%; animation:skeletonWave 1.4s ease infinite; border-radius:8px;
}
@keyframes skeletonWave{ 0%{ background-position:100% 50%; } 100%{ background-position:-100% 50%; } }
.skeleton-card{ display:flex; align-items:center; }
.skeleton-line{ height:14px; }


/* ==========================================================
   14. LOGIN PAGE
   ========================================================== */
.login-wrap{
  min-height:100vh; display:flex; align-items:center; justify-content:center;
  background:
    radial-gradient(circle at 50% 50%, rgba(11,15,25,.5), rgba(5,7,13,.82)),
    url('../img/login-bg.svg') center center / cover no-repeat,
    radial-gradient(circle at 20% 20%, #1E1B4B, #05070D 65%);
  padding:20px;
}
.login-card{
  background:var(--card); border-radius:var(--radius-lg); width:100%; max-width:408px;
  padding:40px 36px; box-shadow:0 25px 60px rgba(0,0,0,.4);
  animation:modalIn var(--med) var(--ease);
}
.login-logo{ display:flex; align-items:center; gap:10px; margin-bottom:28px; }
.login-logo .logo-badge{
  width:44px; height:44px; border-radius:13px;
  background:linear-gradient(135deg, var(--primary), var(--secondary));
  color:#fff; display:flex; align-items:center; justify-content:center; font-weight:800;
  box-shadow:0 8px 20px rgba(79,70,229,.35);
}
.login-title{ font-size:21px; font-weight:800; margin-bottom:4px; letter-spacing:-.3px; }
.login-sub{ color:var(--text-muted); font-size:13px; margin-bottom:26px; }
.login-hint{ margin-top:18px; font-size:12px; color:var(--text-muted); background:var(--bg); border-radius:var(--radius-sm); padding:12px 14px; line-height:1.6; }
.login-hint b{ color:var(--text); }


/* ==========================================================
   15. RESPONSIVE
   ========================================================== */
@media (max-width:1100px){
  .grid-4{ grid-template-columns:repeat(2,1fr); }
  .grid-3{ grid-template-columns:repeat(2,1fr); }
  .form-row{ grid-template-columns:1fr; }
}
@media (max-width:900px){
  .sidebar{ transform:translateX(-100%); }
  .sidebar.open{ transform:translateX(0); box-shadow:var(--shadow-lg); }
  .main{ margin-left:0; }
  .menu-toggle{ display:flex; }
  .search-box{ display:none; }
  .grid-span-2{ grid-column:span 1; }
}
@media (max-width:640px){
  .grid-4, .grid-3, .grid-2{ grid-template-columns:1fr; }
  .content{ padding:18px; }
  .topbar{ padding:0 16px; }
  .page-title{ font-size:17px; }
  .dropdown-menu{ width:280px; right:-16px; }
  .login-card{ padding:32px 24px; }
}
    
/* ==========================================================
   Location picker (assets/js/location-picker.js) - the map used to capture and view where a
   customer or vendor is. Leaflet + OpenStreetMap, loaded only on the pages that use it.
   ========================================================== */
.loc-bar{ display:flex; gap:8px; flex-wrap:wrap; margin-bottom:8px; }
.loc-bar .loc-search{ flex:1 1 200px; min-width:160px; }
.loc-map{ position:relative; z-index:0; width:100%; height:260px; border:1px solid var(--border-color); border-radius:12px; overflow:hidden; background:var(--bg); }
.loc-map.loc-tall{ height:320px; }
.loc-meta{ display:flex; justify-content:space-between; align-items:center; gap:10px; flex-wrap:wrap; margin-top:8px; font-size:12.5px; color:var(--text-muted); }
.loc-meta a{ font-weight:600; }
.loc-pin{ background:transparent; border:0; }
.loc-pin i{ display:block; font-size:34px; line-height:1; text-align:center; color:var(--primary); filter:drop-shadow(0 2px 3px rgba(0,0,0,.35)); }
.loc-error{ padding:36px 16px; text-align:center; color:var(--text-muted); font-size:13px; }

/* ==========================================================
   Searchable dropdowns (omsSearchSelect in assets/js/app.js)
   Every select.form-control is shown as this button + panel. The native <select> stays in
   the DOM as the value holder every script and form post still uses; it is only hidden.
   ========================================================== */
.oms-ss-native{
  position:absolute !important; width:1px !important; height:1px !important; opacity:0 !important;
  pointer-events:none !important; padding:0 !important; margin:0 !important; border:0 !important;
}
.oms-ss-trigger{
  display:flex; align-items:center; gap:8px; text-align:left; cursor:pointer; font-family:inherit;
  padding-right:38px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%236B7280' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right 14px center;
}
.oms-ss-trigger.is-open{ border-color:var(--primary); background-color:var(--card); box-shadow:0 0 0 4px var(--primary-light); }
.oms-ss-trigger[hidden]{ display:none; }
.oms-ss-label{ flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.oms-ss-trigger.is-placeholder .oms-ss-label{ color:var(--text-muted); }
.oms-ss-trigger:disabled{ background-color:var(--readonly-bg); border-color:var(--readonly-border); color:var(--text); cursor:not-allowed; box-shadow:none; }

/* The open list lives on <body> and is position:fixed - anchored to the button by script - so
   a modal's own overflow can never clip it, and it sits above the modal. */
.oms-ss-panel{
  display:none; position:fixed; z-index:2300; flex-direction:column; min-width:160px;
  background:var(--card); border:1px solid var(--border); border-radius:var(--radius-sm);
  box-shadow:0 12px 32px rgba(16,24,40,.18); overflow:hidden;
}
.oms-ss-panel.show{ display:flex; }
.oms-ss-search{ position:relative; padding:8px; border-bottom:1px solid var(--border); flex:none; }
.oms-ss-search i{ position:absolute; left:20px; top:50%; transform:translateY(-50%); color:var(--text-light); font-size:12.5px; }
.oms-ss-search input{
  width:100%; padding:9px 12px 9px 32px; border:1px solid var(--border); border-radius:var(--radius-sm);
  font-size:13.5px; outline:none; background:#FBFBFE;
}
.oms-ss-search input:focus{ border-color:var(--primary); background:var(--card); }
.oms-ss-panel.no-search .oms-ss-search{ display:none; }
.oms-ss-list{ overflow-y:auto; padding:6px; flex:1; min-height:0; }
.oms-ss-group{ padding:8px 10px 4px; font-size:11px; font-weight:700; letter-spacing:.05em; text-transform:uppercase; color:var(--text-light); }
/* One line per option - a long one is cut with an ellipsis (full text on hover, title attribute),
   so the open list stays compact and lined up under its field instead of growing over the page. */
.oms-ss-option{
  padding:8px 10px; border-radius:var(--radius-sm); font-size:13.5px; color:var(--text); cursor:pointer;
  line-height:1.35; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.oms-ss-option.is-active{ background:var(--bg); }
.oms-ss-option.is-selected{ background:var(--primary-light); color:var(--primary); font-weight:600; }
.oms-ss-option.is-disabled{ color:var(--text-light); cursor:not-allowed; background:transparent; }
.oms-ss-option mark{ background:#FEF08A; color:inherit; padding:0; border-radius:2px; }
.oms-ss-empty{ display:none; padding:14px; text-align:center; font-size:13px; color:var(--text-muted); }
.oms-ss-count{ padding:6px 12px; font-size:11.5px; color:var(--text-light); border-top:1px solid var(--border); flex:none; }
