/* ============================================================================
   NailGenius — Design Tokens & Modern Component Layer (Phase 1)
   ----------------------------------------------------------------------------
   Brand:   Indigo  #4f46e5  (primary)
            Rose    #e11d48  (accent, used sparingly)
   Neutral: Slate ramp
   ----------------------------------------------------------------------------
   HOW THIS WORKS
   - Themes are server-rendered as a body class: theme-light (default),
     theme-dark, theme-blue (Domain.theme). There is no JS theme toggle.
   - This file is loaded LAST in <head> (after every inline <style> and the
     JS-injected "immediate" style block), so it wins source-order ties.
   - The override layer below uses !important + theme-scoped selectors to beat
     the legacy !important rules in base_dashboard.html. This is deliberate and
     temporary: once the legacy inline CSS is deleted (Phase 4), the !important
     flags come off and only the :root token blocks remain.
   - Chrome (sidebar + topbar) is driven by --ng-chrome-* tokens. To switch to
     a light/white sidebar later, change those 5 values — nothing else.
   ============================================================================ */

/* ---------------------------------------------------------------------------
   1. TOKENS — LIGHT (default)
   --------------------------------------------------------------------------- */
:root,
body.theme-light {
  /* Brand — indigo */
  --ng-brand:        #4f46e5;
  --ng-brand-hover:  #4338ca;
  --ng-brand-active: #3730a3;
  --ng-brand-50:     #eef2ff;
  --ng-brand-100:    #e0e7ff;
  --ng-on-brand:     #ffffff;
  /* Brand text ON a --ng-brand-50 wash (the .st-pill.info pairing). Separate
     from --ng-brand because dark flips the wash to near-black indigo, where
     the brand ink itself is only 2.5:1. Mirrors --ng-success-fg & friends. */
  --ng-brand-fg:     #4f46e5;

  /* Accent — rose (highlights, never primary actions) */
  --ng-accent:       #e11d48;
  --ng-accent-hover: #be123c;
  --ng-accent-50:    #fff1f3;
  --ng-on-accent:    #ffffff;

  /* Neutrals — slate */
  --ng-text:           #0f172a;  /* primary text                       */
  --ng-text-secondary: #475569;  /* labels, secondary  (7.5:1 on #fff) */
  --ng-text-tertiary:  #5f6b7a;  /* hints, captions  (5.1:1 on bg, 5.4:1 on surface) */
  --ng-text-inverse:   #ffffff;

  --ng-bg:            #f7f8fa;    /* page background */
  --ng-surface:       #ffffff;    /* cards, panels   */
  --ng-surface-2:     #f1f5f9;    /* table head, hover, subtle fill */
  --ng-border:        #e2e8f0;
  --ng-border-strong: #cbd5e1;

  /* Chrome — light sidebar + topbar (matches the approved mockup) */
  --ng-chrome-bg:        #ffffff;
  --ng-chrome-bg-2:      #f8fafc;               /* accordion / fly-out panels */
  --ng-chrome-fg:        #334155;               /* nav text */
  --ng-chrome-fg-muted:  #64748b;               /* nav icons */
  --ng-chrome-hover-bg:  #f1f5f9;
  --ng-chrome-active-bg: #eef2ff;               /* indigo-50 wash */
  --ng-chrome-active-fg: #4f46e5;               /* active text/icon */
  --ng-chrome-active-bar:#4f46e5;
  --ng-chrome-border:    #e2e8f0;

  /* Semantic */
  --ng-success:#16a34a; --ng-success-strong:#15803d; --ng-success-bg:#dcfce7; --ng-success-fg:#15803d;
  --ng-warning:#d97706; --ng-warning-bg:#fef3c7; --ng-warning-fg:#b45309;
  --ng-danger: #dc2626; --ng-danger-bg: #fee2e2; --ng-danger-fg: #b91c1c;
  --ng-info:   #2563eb; --ng-info-bg:   #dbeafe; --ng-info-fg:   #1d4ed8;

  /* Typography. The color-emoji fonts sit BEFORE "Segoe UI": Segoe UI carries
     monochrome glyphs for many emoji codepoints and would otherwise render
     chat emojis as odd black-and-white symbols (Inter covers all letters and
     digits, so text never reaches the emoji fonts). */
  --ng-font: "Inter", "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  /* Radius */
  --ng-radius-sm:   6px;
  --ng-radius:      8px;    /* controls */
  --ng-radius-lg:   12px;   /* cards */
  --ng-radius-pill: 999px;

  /* Elevation */
  --ng-shadow-sm: 0 1px 2px rgba(16,24,40,.06), 0 1px 3px rgba(16,24,40,.10);
  --ng-shadow-md: 0 4px 6px -1px rgba(16,24,40,.08), 0 2px 4px -2px rgba(16,24,40,.06);
  --ng-shadow-lg: 0 12px 16px -4px rgba(16,24,40,.08), 0 4px 6px -2px rgba(16,24,40,.04);
  --ng-ring: 0 0 0 3px rgba(79,70,229,.25);

  /* Bridge to the existing unified-table variable names (free upgrade) */
  --card-bg:        var(--ng-surface);
  --text-primary:   var(--ng-text);
  --text-secondary: var(--ng-text-secondary);
  --border:         var(--ng-border);
  --input-bg:       var(--ng-surface);
}

/* ---------------------------------------------------------------------------
   2. TOKENS — DARK (overrides only what changes)
   --------------------------------------------------------------------------- */
body.theme-dark {
  --ng-text:           #f1f5f9;
  --ng-text-secondary: #cbd5e1;
  --ng-text-tertiary:  #94a3b8;
  --ng-text-inverse:   #0f172a;

  --ng-bg:            #0b1220;
  --ng-surface:       #111827;
  --ng-surface-2:     #1f2937;
  --ng-border:        #334155;
  --ng-border-strong: #475569;

  --ng-brand-50:  #1e1b4b;
  --ng-brand-100: #312e81;
  --ng-brand-fg:  #a5b4fc;   /* indigo-300: 8.0:1 on the #1e1b4b wash */

  --ng-chrome-bg:        #0b1220;
  --ng-chrome-bg-2:      #111827;
  --ng-chrome-fg:        #e2e8f0;               /* light text on the dark ink chrome */
  --ng-chrome-fg-muted:  #94a3b8;
  --ng-chrome-active-fg: #ffffff;
  --ng-chrome-hover-bg:  rgba(255,255,255,.06);
  --ng-chrome-active-bg: rgba(99,102,241,.22);
  --ng-chrome-border:    rgba(255,255,255,.07);

  --ng-success-bg:#052e1a; --ng-success-fg:#4ade80;
  --ng-warning-bg:#3a2a06; --ng-warning-fg:#fbbf24;
  --ng-danger-bg: #3a0d0d; --ng-danger-fg: #f87171;
  --ng-info-bg:   #0c2a52; --ng-info-fg:   #93c5fd;

  --ng-shadow-sm: 0 1px 2px rgba(0,0,0,.4), 0 1px 3px rgba(0,0,0,.5);
  --ng-shadow-md: 0 4px 6px -1px rgba(0,0,0,.5);
  --ng-shadow-lg: 0 12px 16px -4px rgba(0,0,0,.5);
  --ng-ring: 0 0 0 3px rgba(129,140,248,.35);
}

/* ---------------------------------------------------------------------------
   3. TOKENS — BLUE (light content + blue ink chrome)
   --------------------------------------------------------------------------- */
body.theme-blue {
  --ng-bg:            #eef4fb;
  --ng-surface:       #ffffff;
  --ng-surface-2:     #e3edf9;
  --ng-border:        #cfe0f2;
  --ng-border-strong: #b6cfeb;

  --ng-text:           #0f2540;
  --ng-text-secondary: #355074;
  --ng-text-tertiary:  #4c6b94;

  --ng-chrome-bg:        #14365d;
  --ng-chrome-bg-2:      #0f2c4d;
  --ng-chrome-fg:        #e2e8f0;               /* light text on the blue ink chrome */
  --ng-chrome-fg-muted:  #cbd5e1;
  --ng-chrome-active-fg: #ffffff;
  --ng-chrome-active-bg: rgba(255,255,255,.16);
  --ng-chrome-border:    rgba(255,255,255,.10);
}

/* ===========================================================================
   COMPONENT OVERRIDE LAYER
   (consumes the tokens above; !important beats the legacy inline CSS)
   =========================================================================== */

/* ---- 4. Base typography & surfaces ------------------------------------- */
body,
body.theme-light,
body.theme-dark,
body.theme-blue { font-family: var(--ng-font) !important; }

input, select, textarea, button,
.topbar, .sidebar, .main-content { font-family: var(--ng-font) !important; }

body.theme-light, body.theme-dark, body.theme-blue {
  background: var(--ng-bg) !important;
  color: var(--ng-text) !important;
}
body.theme-light .main-content,
body.theme-dark  .main-content,
body.theme-blue  .main-content {
  background: var(--ng-bg) !important;
  color: var(--ng-text) !important;
}

/* ---- 5. Chrome: topbar + sidebar --------------------------------------- */
.topbar,
body.theme-light .topbar,
body.theme-dark  .topbar,
body.theme-blue  .topbar {
  background: var(--ng-chrome-bg) !important;
  color: var(--ng-chrome-fg) !important;
  border-bottom: 1px solid var(--ng-chrome-border) !important;
  box-shadow: none !important;
}

.sidebar,
body.theme-light .sidebar,
body.theme-dark  .sidebar,
body.theme-blue  .sidebar {
  background: var(--ng-chrome-bg) !important;
  border-right: 1px solid var(--ng-chrome-border) !important;
}

/* Accordion + fly-out panels */
.sidebar-accordion-panel,
.sidebar-accordion-panel.floating,
.sidebar-language-floating,
body.theme-dark .sidebar-accordion-panel.floating,
body.theme-blue .sidebar-accordion-panel.floating {
  background: var(--ng-chrome-bg-2) !important;
  border-color: var(--ng-chrome-border) !important;
}

/* Hover / expanded nav state → subtle, with an indigo wash on expanded */
body .sidebar .sidebar-menu > li > a:hover,
body .sidebar .sidebar-accordion-btn:hover {
  background: var(--ng-chrome-hover-bg) !important;
}
body .sidebar .sidebar-accordion-btn[aria-expanded="true"] {
  background: var(--ng-chrome-active-bg) !important;
  box-shadow: inset 3px 0 0 var(--ng-chrome-active-bar) !important;
}

/* ---- 5b. Topbar inner elements — token-driven (all themes) ---------------- */
/* base_dashboard.html hardcodes rgba(255,255,255,…) colours for a dark topbar.
   These rules switch to --ng-chrome-* tokens so light, dark, and blue chrome
   all render correctly without repeating the full block per theme.
   Note: #ai-topbar-btn i has ID-level specificity in widget.html and keeps its
   white colour on the purple gradient button — only the bell <a> is affected. */

.topbar-search input {
  color:        var(--ng-chrome-fg) !important;
  border-color: var(--ng-chrome-border) !important;
}
.topbar-search input::placeholder {
  color: var(--ng-chrome-fg-muted) !important;
}
.topbar-search button,
.topbar-search button i {
  color:        var(--ng-chrome-fg-muted) !important;
  border-color: var(--ng-chrome-border) !important;
}
.topbar .notification-bell i {
  color: var(--ng-chrome-fg) !important;
}
/* Badge ring — match the topbar surface so the badge appears to float above
   the button instead of showing the old hardcoded #2c3e50 navy ring */
.topbar .notification-count {
  border-color: var(--ng-chrome-bg) !important;
}

/* Light chrome only (default + theme-light): solid white input, transparent button bg */
html body:not(.theme-dark):not(.theme-blue) .topbar-search input {
  background: var(--ng-surface) !important;
}
html body:not(.theme-dark):not(.theme-blue) .topbar-search button {
  background: transparent !important;
}
html body:not(.theme-dark):not(.theme-blue) .notification-bell:not(#ai-topbar-btn) {
  background: transparent !important;
  border-color: var(--ng-chrome-border) !important;
}

/* ---- 6. Buttons -------------------------------------------------------- */
/* Element defaults stay overridable: local components own their color pair.
   Only explicit semantic utility classes force a fill. This also keeps neutral
   submit buttons identical to their <a> and type="button" equivalents. */
button, input[type="submit"] {
  background: var(--ng-brand);
  border: 1px solid transparent;
  color: var(--ng-on-brand);
  border-radius: var(--ng-radius);
  transition: background .15s ease, box-shadow .15s ease;
}
button:where(:hover), input[type="submit"]:where(:hover) { background: var(--ng-brand-hover); }
a.button, .top-btn, .edit-btn, .btn-primary {
  background: var(--ng-brand) !important;
  border: 1px solid transparent !important;
  color: var(--ng-on-brand) !important;
  border-radius: var(--ng-radius) !important;
}
a.button:hover, .top-btn:hover, .edit-btn:hover, .btn-primary:hover {
  background: var(--ng-brand-hover) !important;
}

/* Disabled buttons must LOOK disabled: the brand fill above otherwise leaves them
   fully saturated with a pointer cursor, so a dead click reads as a broken button
   (reported on the knowledge-base "Analyze & draft" button with AI off). */
button:disabled,
input[type="submit"]:disabled,
.crm-btn:disabled,
.crm-btn[disabled] {
  opacity: .55 !important;
  cursor: not-allowed !important;
}

/* Success uses a darker green (--ng-success-strong) so white label text meets AA (5.0:1). */
.add-btn, .btn-success { background: var(--ng-success-strong) !important; border-color: var(--ng-success-strong) !important; color:#fff !important; }
.add-btn:hover, .btn-success:hover { background: #166534 !important; }

.delete-btn, .btn-danger { background: var(--ng-danger) !important; border-color: var(--ng-danger) !important; color:#fff !important; }
.delete-btn:hover, .btn-danger:hover { background: #b91c1c !important; }

/* Warning uses dark text — white on amber fails AA (3.2:1); #1f2937 on amber is 4.6:1. */
.btn-warning { background: var(--ng-warning) !important; border-color: var(--ng-warning) !important; color:#1f2937 !important; }
.btn-info    { background: var(--ng-info) !important;    border-color: var(--ng-info) !important;    color:#fff !important; }
.btn-secondary { background: #475569 !important; border-color: #475569 !important; color:#fff !important; }
.btn-secondary:hover { background: #334155 !important; }

/* Explicit solid utilities own their foreground, including nested icons.
   Keep these compatibility rules for legacy page styles; ordinary theme links
   now use low-specificity defaults instead of competing with components. */
body .main-content a.btn-primary,
body .main-content a.btn-success,
body .main-content a.btn-danger,
body .main-content a.btn-info,
body .main-content a.btn-secondary {
  color: var(--ng-on-brand, #fff) !important;
}
body .main-content a.btn-warning { color: #1f2937 !important; }
body .main-content a.btn-primary i,
body .main-content a.btn-success i,
body .main-content a.btn-danger i,
body .main-content a.btn-info i,
body .main-content a.btn-secondary i,
body .main-content a.btn-warning i { color: inherit !important; }

/* Secondary actions keep a neutral pair, including submit buttons and hover.
   This scoped utility also wins against older page-local action styles. */
.main-content .crm-btn.secondary,
.main-content .crm-btn.secondary:hover,
.main-content .crm-btn.secondary:focus {
  background: var(--ng-surface-2) !important;
  color: var(--ng-text-secondary) !important;
  border-color: var(--ng-border-strong) !important;
}
.main-content .crm-btn.secondary:hover { border-color: var(--ng-brand) !important; }

/* Legacy action utilities use the same semantic pairs in every theme.
   The :root/body scope wins over old theme-specific utility declarations;
   no geometry or display rules are changed here. */
:root body :is(a.button, .top-btn, .edit-btn) {
  background: var(--ng-brand) !important; color: var(--ng-on-brand) !important;
}
:root body :is(a.button, .top-btn, .edit-btn):hover {
  background: var(--ng-brand-hover) !important;
}
:root body .add-btn { background: var(--ng-success-strong) !important; color: #fff !important; }
:root body .add-btn:hover { background: #166534 !important; }
:root body .add-btn.secondary { background: #475569 !important; }
:root body .add-btn.secondary:hover { background: #334155 !important; }
:root body .delete-btn { background: var(--ng-danger) !important; color: #fff !important; }
:root body .delete-btn:hover { background: #b91c1c !important; }
:where(.crm-btn, .btn, .button, .top-btn, .add-btn, .edit-btn, .delete-btn) :is(i, span) {
  color: inherit;
}

/* ---- 7. Forms ---------------------------------------------------------- */
body.theme-light form input, body.theme-light form select, body.theme-light form textarea,
body.theme-dark  form input, body.theme-dark  form select, body.theme-dark  form textarea,
body.theme-blue  form input, body.theme-blue  form select, body.theme-blue  form textarea {
  background: var(--ng-surface) !important;
  color: var(--ng-text) !important;
  border: 1px solid var(--ng-border-strong) !important;
  border-radius: var(--ng-radius) !important;
}
body.theme-light form input:focus, body.theme-light form select:focus, body.theme-light form textarea:focus,
body.theme-dark  form input:focus, body.theme-dark  form select:focus, body.theme-dark  form textarea:focus,
body.theme-blue  form input:focus, body.theme-blue  form select:focus, body.theme-blue  form textarea:focus {
  border-color: var(--ng-brand) !important;
  box-shadow: var(--ng-ring) !important;
  outline: none !important;
}
.main-content form {
  background: var(--ng-surface) !important;
  border: 1px solid var(--ng-border) !important;
  border-radius: var(--ng-radius-lg) !important;
  box-shadow: var(--ng-shadow-sm) !important;
}
form label { color: var(--ng-text-secondary) !important; }

/* ---- 7b. Checkboxes & radios ------------------------------------------------
   ONE size for every tick box in the product. Before this, ~20 templates each
   picked their own (15 / 16 / 17 / 18 / 20px, 1rem, `width:auto`) and every page
   that picked none fell through to the UA default — ~13px on Chrome/Windows. So
   the public catalogue, the CCaaS AI settings and most of the portal drew boxes
   visibly smaller than pages sitting one click away, which is what the mismatch
   looks like to a user.

   The token gets its OWN `:root` block on purpose. The main token block is
   `:root, body.theme-light`, and `body.theme-light` (0,1,1) out-ranks a bare
   `:root` (0,1,0) — so declaring it up there would make the @media bump below a
   silent no-op on the default theme, where nearly every page renders.

   The selectors are wrapped in `:where()`, which zeroes their specificity, so
   this is a DEFAULT that every page rule beats rather than another global that
   out-ranks them. That is load-bearing, not tidiness: base_dashboard.html emits
   `{% block extra_head %}` at ~134 and this file at ~137, so tokens.css wins
   every source-order tie against a page's own <style>. A bare
   `input[type=checkbox]` here is (0,1,1) — exactly the specificity of the
   hidden-input half of a custom control — and would silently capture them:
     .cfg-switch input  (configuration.html)  width/height:100% of a 46x26 pill
     .opt-card input    (configuration.html)  the 1px visually-hidden radio
   Both would have been repainted to 18x18, shrinking the toggle's hit area to a
   corner of its own track. `:where()` also keeps the genuinely custom controls
   safe without naming them: the calendar-sync 40x23 switch, the Staff Desk
   selector that collapses to width:0, Bootstrap's .custom-control-input in the
   embedded admin. (Support is not a concern — the app already ships `:has()`
   rules, e.g. `.opt-card:has(input:checked)`, and `:has()` landed well AFTER
   `:where()` in every engine.)

   Deliberately NOT here: `!important`, `min-width`, and `margin`.
   - No `!important` / no `min-width`, for the same reason: a `min-width` would
     leak past the width the custom controls set for themselves (none of them
     declares one) and un-collapse them.
   - No `margin`, because the UA's ~3px is what separates the box from its text
     in the plain `<label><input> Text</label>` pattern this app uses
     everywhere; zeroing it globally would jam the two together on every such
     label. Flex rows that want the gap tighter already set `margin:0`. */
:root { --ng-check-size: 18px; }
/* Touch devices get a bigger target — WCAG 2.5.8 wants >= 24px, and 22px plus
   the UA margin clears that. Keyed on the POINTER, not the viewport: a phone
   gets it, while a narrow desktop window does not resize its boxes mid-drag. */
@media (pointer: coarse) { :root { --ng-check-size: 22px; } }

:where(input[type="checkbox"], input[type="radio"]) {
  width: var(--ng-check-size);
  height: var(--ng-check-size);
  flex: none;              /* a flex row must never squash it out of square */
  vertical-align: middle;  /* baseline would lift the taller box off the text */
  accent-color: var(--ng-brand);
  cursor: pointer;
}
:where(input[type="checkbox"]:disabled, input[type="radio"]:disabled) {
  cursor: not-allowed;
}

/* ---- 8. Tables --------------------------------------------------------- */
body.theme-light thead tr, body.theme-light th,
body.theme-dark  thead tr, body.theme-dark  th,
body.theme-blue  thead tr, body.theme-blue  th {
  background: var(--ng-surface-2) !important;
  color: var(--ng-text-secondary) !important;
  font-weight: 500 !important;
  text-transform: none !important;
  border-bottom: 1px solid var(--ng-border) !important;
}
body.theme-light td, body.theme-dark td, body.theme-blue td {
  color: var(--ng-text) !important;
  border-bottom: 1px solid var(--ng-border) !important;
}
/* Cleaner than zebra: borders + hover (Stripe/Linear style) */
body.theme-light tbody tr:nth-child(even) td,
body.theme-dark  tbody tr:nth-child(even) td,
body.theme-blue  tbody tr:nth-child(even) td { background: transparent !important; }
body.theme-light tbody tr:hover td,
body.theme-dark  tbody tr:hover td,
body.theme-blue  tbody tr:hover td { background: var(--ng-surface-2) !important; }

/* ---- 9. Cards & panels (surface normalization only — gradients untouched) */
.dashboard-card, .content-card, .info-panel, .lb-card, .cam-card, .cam-kpi,
.metric-card, .stat-card, .chart-card, .kpi-card, .performance-card,
.quick-actions-card, .recent-activity-card, .metric-group, .main-table {
  border-radius: var(--ng-radius-lg) !important;
  box-shadow: var(--ng-shadow-sm) !important;
}
.dashboard-card, .content-card, .info-panel, .lb-card, .cam-card, .cam-kpi,
.metric-group, .chart-card, .performance-card, .quick-actions-card, .recent-activity-card,
.modal-content, .modal-body {
  background: var(--ng-surface) !important;
  border: 1px solid var(--ng-border) !important;
  color: var(--ng-text) !important;
}
body.theme-dark .dashboard-card, body.theme-dark .content-card, body.theme-dark .info-panel,
body.theme-dark .lb-card, body.theme-dark .cam-card, body.theme-dark .cam-kpi,
body.theme-dark .metric-group, body.theme-dark .chart-card, body.theme-dark .performance-card,
body.theme-dark .quick-actions-card, body.theme-dark .recent-activity-card,
body.theme-dark .modal-content, body.theme-dark .modal-body {
  background: var(--ng-surface) !important;
  border-color: var(--ng-border) !important;
  color: var(--ng-text) !important;
}

/* ---- 10. Status / semantic badges -------------------------------------- */
.badge-success, .status-badge.success { background: var(--ng-success-bg) !important; color: var(--ng-success-fg) !important; }
.badge-warning, .status-badge.warning { background: var(--ng-warning-bg) !important; color: var(--ng-warning-fg) !important; }
.badge-danger,  .status-badge.danger  { background: var(--ng-danger-bg)  !important; color: var(--ng-danger-fg)  !important; }
.badge-primary, .status-badge.info    { background: var(--ng-info-bg)    !important; color: var(--ng-info-fg)    !important; }

/* ---- 11. Text & contrast fixes (WCAG AA) ------------------------------- */
.text-muted,
.kpi-subtitle, .metric-label, .activity-sub, .performer-label,
.dashboard-subtitle, .refresh-status, .privilege-labels,
.card-subtitle, .muted, small.text-muted {
  color: var(--ng-text-tertiary) !important;
}
/* Text link recolor (brand in light / readable blue in dark) is deferred to Phase 2 —
   indigo #4f46e5 fails contrast on the dark page bg, so links keep the legacy
   theme-aware colors for now. */

/* ---- 11b. LIGHT CHROME (theme-light) — match the approved mockup --------
   The legacy inline CSS + a JS-injected <style> force white sidebar/topbar text &
   icons with aggressive !important (up to ~0,5,3 specificity). The doubled/tripled
   class selectors below out-specify them so the light sidebar stays legible.
   Scoped to theme-light only; dark/blue keep their ink chrome. Phase 4 deletes the
   legacy rules and this whole block. */

/* nav text */
html body.theme-light.theme-light .sidebar.sidebar.sidebar .sidebar-menu > li > a,
html body.theme-light.theme-light .sidebar.sidebar.sidebar .sidebar-accordion-btn,
html body.theme-light.theme-light .sidebar.sidebar.sidebar .sidebar-toggle,
html body.theme-light.theme-light .sidebar.sidebar.sidebar .sidebar-language label,
html body.theme-light.theme-light .sidebar.sidebar.sidebar .sidebar-language-icon {
  color: var(--ng-chrome-fg) !important;
}
/* nav icons (muted) */
html body.theme-light.theme-light .sidebar.sidebar.sidebar [class*="fa-"],
html body.theme-light.theme-light .sidebar.sidebar.sidebar i.fas,
html body.theme-light.theme-light .sidebar.sidebar.sidebar i.far,
html body.theme-light.theme-light .sidebar.sidebar.sidebar i.fab,
html body.theme-light.theme-light .sidebar.sidebar.sidebar i {
  color: var(--ng-chrome-fg-muted) !important;
  fill: var(--ng-chrome-fg-muted) !important;
}
/* nav icon GLYPHS — FontAwesome draws the glyph in ::before, which the legacy CSS colors
   #fff. The <i> element color alone does NOT reach the glyph, so without targeting the
   pseudo-element every sidebar icon stays white/invisible on the light rail. */
html body.theme-light.theme-light .sidebar.sidebar.sidebar [class*="fa-"]::before,
html body.theme-light.theme-light .sidebar.sidebar.sidebar i.fas::before,
html body.theme-light.theme-light .sidebar.sidebar.sidebar i.far::before,
html body.theme-light.theme-light .sidebar.sidebar.sidebar i.fab::before,
html body.theme-light.theme-light .sidebar.sidebar.sidebar i::before {
  color: var(--ng-chrome-fg-muted) !important;
}
html body.theme-light .sidebar-accordion-panel [class*="fa-"]::before,
html body.theme-light .sidebar-accordion-panel a i::before {
  color: var(--ng-chrome-fg-muted) !important;
}
/* active accordion glyph → indigo (out-specifies the muted ::before rule above) */
html body.theme-light.theme-light .sidebar.sidebar.sidebar .sidebar-accordion-btn[aria-expanded="true"] [class*="fa-"]::before,
html body.theme-light.theme-light .sidebar.sidebar.sidebar .sidebar-accordion-btn[aria-expanded="true"] i::before {
  color: var(--ng-brand) !important;
}
/* hover */
html body.theme-light .sidebar .sidebar-menu > li > a:hover,
html body.theme-light .sidebar .sidebar-accordion-btn:hover {
  background: var(--ng-chrome-hover-bg) !important;
  color: var(--ng-brand) !important;
}
html body.theme-light .sidebar .sidebar-menu > li > a:hover i,
html body.theme-light .sidebar .sidebar-accordion-btn:hover i,
html body.theme-light .sidebar .sidebar-accordion-btn:hover [class*="fa-"] {
  color: var(--ng-brand) !important;
}
/* expanded / active accordion */
html body.theme-light .sidebar .sidebar-accordion-btn[aria-expanded="true"] {
  background: var(--ng-chrome-active-bg) !important;
  color: var(--ng-chrome-active-fg) !important;
  box-shadow: inset 3px 0 0 var(--ng-brand) !important;
}
html body.theme-light .sidebar .sidebar-accordion-btn[aria-expanded="true"] i,
html body.theme-light .sidebar .sidebar-accordion-btn[aria-expanded="true"] [class*="fa-"] {
  color: var(--ng-brand) !important;
}
/* fly-out / accordion panels + submenu links */
html body.theme-light .sidebar-accordion-panel,
html body.theme-light .sidebar-accordion-panel.floating,
html body.theme-light .sidebar-language-floating {
  background: var(--ng-chrome-bg-2) !important;
  border-color: var(--ng-border) !important;
}
html body.theme-light .sidebar-accordion-panel a,
html body.theme-light .sidebar-accordion-panel li a,
html body.theme-light .sidebar-accordion-panel.floating li a,
html body.theme-light .sidebar-accordion-panel .submenu-category {
  color: var(--ng-chrome-fg) !important;
}
html body.theme-light .sidebar-accordion-panel a i,
html body.theme-light .sidebar-accordion-panel a [class*="fa-"] {
  color: var(--ng-chrome-fg-muted) !important;
}
html body.theme-light .sidebar-accordion-panel a:hover {
  background: var(--ng-chrome-hover-bg) !important;
  color: var(--ng-brand) !important;
}
/* language select */
html body.theme-light .sidebar-language select,
html body.theme-light .sidebar-language-floating select {
  background: var(--ng-surface) !important;
  color: var(--ng-text) !important;
  border: 1px solid var(--ng-border) !important;
}

/* ---- light topbar ---- */
html body.theme-light .topbar { color: var(--ng-chrome-fg) !important; }
html body.theme-light .topbar .topbar-section-title { color: var(--ng-text) !important; }
html body.theme-light .topbar-search input {
  background: var(--ng-surface) !important;
  color: var(--ng-text) !important;
  border: 1px solid var(--ng-border) !important;
}
html body.theme-light .topbar-search input::placeholder { color: var(--ng-text-tertiary) !important; }
html body.theme-light .topbar-search button,
html body.theme-light .topbar-search button i {
  color: var(--ng-text-tertiary) !important;
  background: transparent !important;
  border-color: var(--ng-border) !important;
}
html body.theme-light .notification-bell,
html body.theme-light .notification-bell i { color: var(--ng-text-secondary) !important; }

/* ---- 11c. CALENDAR (theme-light) ---------------------------------------
   The booking calendar's topbar KPI pills (.topbar-kpi) and event cards (.bk-card)
   were styled white/translucent for the old dark topbar and as low-opacity status-
   colored text. On the light theme they wash out. These light-scoped overrides make
   them legible; dark/blue keep their existing (working) light-on-dark treatment. */

/* topbar KPI pills */
html body.theme-light .topbar-kpi {
  color: var(--ng-text-secondary) !important;
  background: var(--ng-surface-2) !important;
  border-color: var(--ng-border) !important;
}
html body.theme-light .topbar-kpi .kpi-val { color: var(--ng-text) !important; }
html body.theme-light .topbar .topbar-kpis .topbar-kpi i,
html body.theme-light .topbar .topbar-kpis .topbar-kpi i.fas { color: var(--ng-text-tertiary) !important; }
html body.theme-light .topbar-kpi .kpi-fill-bar { background: var(--ng-border) !important; }
/* accent / revenue / next: keep a soft tint but use a dark, readable value color */
html body.theme-light .topbar-kpi.kpi-accent { background:#eef2ff !important; border-color:#c7d2fe !important; }
html body.theme-light .topbar-kpi.kpi-accent .kpi-val { color:#4338ca !important; }
html body.theme-light .topbar-kpi.kpi-revenue { background:#dcfce7 !important; border-color:#bbf7d0 !important; }
html body.theme-light .topbar-kpi.kpi-revenue .kpi-val { color:#15803d !important; }
html body.theme-light .topbar .topbar-kpis .topbar-kpi.kpi-revenue i { color:#15803d !important; }
html body.theme-light .topbar-kpi.kpi-next { background:#e0f2fe !important; border-color:#bae6fd !important; }
html body.theme-light .topbar-kpi.kpi-next .kpi-val { color:#0369a1 !important; }
html body.theme-light .topbar .topbar-kpis .topbar-kpi.kpi-next i { color:#0369a1 !important; }

/* event cards — darker status text so the customer/service/time are legible on the light tint */
html body.theme-light .bk-card.st-booked      { color:#1d4ed8 !important; }
html body.theme-light .bk-card.st-confirmed   { color:#047857 !important; }
html body.theme-light .bk-card.st-in_progress { color:#b45309 !important; }
html body.theme-light .bk-card.st-completed   { color:#4338ca !important; }
html body.theme-light .bk-card.st-cancelled   { color:#b91c1c !important; }
html body.theme-light .bk-card.st-no_show     { color:#475569 !important; }

/* ---- 11d. CALENDAR (theme-blue) ----------------------------------------
   The calendar's own --cal-* blue scheme was designed DARK navy, but this revamp's
   blue theme is LIGHT (light-blue page, white cards). That mismatch left the calendar's
   top-bar text light-on-light (invisible) while the grid was dark. Realign the blue
   --cal-* to a light-blue scheme so the whole calendar is consistent with the app. */
body.theme-blue {
  --cal-bg:#ffffff; --cal-text:#0f2540; --cal-text-secondary:#355074;
  --cal-border:#cfe0f2; --cal-header-bg:#e7eef8; --cal-slot-hover:#eef4fb;
  --cal-accent:#2563eb; --cal-accent-light:#dbeafe;
  --cal-pill-bg:#e3edf9; --cal-pill-active:#2563eb; --cal-pill-text:#1e3a5f;
  --cal-modal-bg:#ffffff; --cal-input-bg:#f8fafc; --cal-input-border:#b6cfeb;
}
/* blue event cards → dark status text on a light tint (mirror the light theme) */
body.theme-blue .bk-card.st-booked      { background:rgba(59,130,246,.14) !important; color:#1d4ed8 !important; }
body.theme-blue .bk-card.st-confirmed   { background:rgba(16,185,129,.14) !important; color:#047857 !important; }
body.theme-blue .bk-card.st-in_progress { background:rgba(245,158,11,.14) !important; color:#b45309 !important; }
body.theme-blue .bk-card.st-completed   { background:rgba(99,102,241,.14) !important; color:#4338ca !important; }

/* ---- 12. Keyboard focus visibility (a11y) ------------------------------ */
a:focus-visible, button:focus-visible,
input:focus-visible, select:focus-visible, textarea:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--ng-brand) !important;
  outline-offset: 2px !important;
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* ---- 12. Page layout primitives (header / card / empty state) ---------- */
/* The dashboard header had no base layout (markup puts actions before the
   title), so the action button rendered ABOVE the heading. Make it a proper
   title/action row at every width; order:-1 floats the <h1> first. */
.dashboard-header {
  display: flex !important;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 24px;
}
.dashboard-header h1 {
  order: -1;
  margin: 0;
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--ng-text);
  display: inline-flex;
  align-items: center;
  gap: 10px;
}
.dashboard-header h1 i { color: var(--ng-brand); }
.dashboard-header .header-actions { display: inline-flex; gap: 8px; flex-wrap: wrap; align-items: center; }
@media (max-width: 640px) {
  .dashboard-header { align-items: flex-start; }
  .dashboard-header h1 { font-size: 1.25rem; }
}

/* Give the content card real interior padding (it only had surface styling). */
.content-card { padding: 24px 28px; }
@media (max-width: 640px) { .content-card { padding: 16px; } }

/* Empty-state block (no base styling existed). */
.empty-state { text-align: center; padding: 48px 24px; }
.empty-state i { color: var(--ng-text-tertiary); }
.empty-state h3 { margin: 12px 0 6px; color: var(--ng-text); }
.empty-state p { margin: 0 auto 18px; max-width: 420px; color: var(--ng-text-secondary); }

/* Re-brand the privilege badge from the off-brand teal to indigo tokens, and
   contain the list "badge soup" in a wrapping flex cell. Theme-scoped so it
   beats the legacy theme variants in base_dashboard.html. */
.privilege-badge,
body.theme-light .privilege-badge,
body.theme-dark .privilege-badge,
body.theme-blue .privilege-badge {
  display: inline-flex; align-items: center;
  background: var(--ng-brand-50) !important;
  color: var(--ng-brand-active) !important;
  border: 1px solid var(--ng-brand-100) !important;
  padding: 2px 9px; border-radius: var(--ng-radius-pill);
  font-size: 12px; font-weight: 600; line-height: 1.7;
}
.privilege-cell { display: flex; flex-wrap: wrap; gap: 4px 6px; max-width: 560px; }
.privilege-cell .text-muted { color: var(--ng-text-tertiary); }

/* Compact, consistent icon action buttons for table rows.
   .icon-btn works standalone OR inside .row-actions — one canonical 32x32 square
   so edit/delete/view actions are identical across every CRM list page. The
   selector is TRIPLED on purpose: !important alone loses to base_dashboard's
   legacy themed `body.theme-* form button[type="submit"]` (0,2,3), which was
   painting every delete/submit icon button #2980b9 while its sibling <a> stayed
   neutral. (0,3,0) out-ranks it for buttons AND out-ranks app-shell's
   `body.theme-* .main-content a` (0,2,2) for anchor ink. */
.row-actions { display: inline-flex; gap: 6px; align-items: center; }
.icon-btn.icon-btn.icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  /* Geometry is pinned !important + border-box: table_filters forces
     `padding:4px 8px !important` on td a/button, and with no global
     border-box reset an <a> is content-box — so the edit anchor rendered
     50x42 beside the 32x32 delete <button> (UA makes form controls
     border-box). Same declared size, two rendered sizes. */
  box-sizing: border-box !important;
  width: 32px !important; min-width: 32px !important; height: 32px !important;
  padding: 0 !important; border-radius: var(--ng-radius) !important;
  border: 1px solid var(--ng-border-strong) !important;
  background: var(--ng-surface) !important;
  color: var(--ng-text-secondary) !important;
  cursor: pointer; text-decoration: none; flex: none;
  font-size: .9rem !important; line-height: 1 !important;
  margin: 0 !important;
}
.icon-btn.icon-btn.icon-btn:hover {
  background: var(--ng-surface-2) !important;
  color: var(--ng-text) !important;
  border-color: var(--ng-brand) !important;
}
.icon-btn.icon-btn.icon-btn.danger:hover {
  color: var(--ng-danger-fg) !important;
  border-color: var(--ng-danger) !important;
}
/* Inline action forms (icon/text buttons inside tables & action bars) must NOT
   inherit the `.main-content form` card chrome (border/bg/shadow/padding) — that
   chrome is for page-level forms only. display:contents dissolves the form box so
   the button sits inline and aligns with sibling anchor buttons. */
.row-actions form,
.loy-rowact form,
.loy-actions form,
.inv-head-actions form,
.header-actions form,
.mr-actions form,
.main-content table td form,
.main-content .inv-table td form,
.main-content .loy-table td form,
.main-content .main-table td form,
.main-content .hr-table td form {
  display: contents !important;
}

/* Utility forms that hold ONLY hidden inputs (bulk-action submitters whose
   checkboxes/buttons live outside via form="…", csrf-only POST forms) must NOT
   inherit the `.main-content form` card chrome (border/bg/shadow + the legacy
   base_dashboard `.main-content form` 32px padding / 600px box) — otherwise they
   render as an empty bordered box mid-page. display:contents dissolves the box
   entirely, mirroring the inline-action-form exemption above. The `.ng-bare-form`
   arm is the explicit, no-:has() guarantee for known offenders; the `:has()` arm
   auto-covers any future stray hidden-only form on modern browsers. */
.main-content form.ng-bare-form,
.main-content form:not(:has(> *:not(input[type="hidden"]))) {
  display: contents !important;
}

/* CCaaS knowledge-base forms (train-from-website, quick-start buttons, add/edit
   entry, review/apply) are laid out entirely by their .kb- / .kbr- wrappers — the
   `.main-content form` card chrome (600px box, 32px padding, bg/shadow) would
   double-wrap them inside their own cards. Dissolve the form box like the
   inline-action exemption above. (No literal star-slash in this comment: it would
   end the comment early and the parser then eats the next rule.) */
.kb-card form,
.kb-quickcard form,
.kbr-card form {
  display: contents !important;
}

/* Neutral icon buttons rendered as <button> (e.g. .loy-iconbtn delete, the
   knowledge-base row actions) must beat the global
   `button{ background:var(--ng-brand)!important }` fill so they stay
   surface-colored, matching their <a> siblings. Lives here (static, always served)
   so it applies even when page templates are cached. */
button.loy-iconbtn, .loy-iconbtn,
button.kb-iconbtn, .kb-iconbtn,
.main-content a.kb-iconbtn {
  background: var(--ng-surface) !important;
  color: var(--ng-text-secondary) !important;
  border: 1px solid var(--ng-border) !important;
}
button.loy-iconbtn:hover, .loy-iconbtn:hover,
button.kb-iconbtn:hover, .kb-iconbtn:hover,
.main-content a.kb-iconbtn:hover {
  background: var(--ng-surface-2) !important; color: var(--ng-brand) !important; border-color: var(--ng-brand) !important;
}
button.loy-iconbtn.danger:hover, .loy-iconbtn.danger:hover,
button.kb-iconbtn.danger:hover, .kb-iconbtn.danger:hover {
  color: var(--ng-danger) !important; border-color: var(--ng-danger) !important;
}

/* Loyalty tabs are <a>, so the global `.main-content a { color:<link>!important }`
   rule hijacks their text — making the active (indigo) tab show grey/blue text that's
   nearly invisible. Exempt them: inactive = secondary text, active = white on brand.
   Same hijack hits the knowledge-base <a> edit icon (a.kb-iconbtn) — keep it
   neutral so it matches its <button> siblings in the row. */
body.theme-light .main-content a.kb-iconbtn,
body.theme-dark  .main-content a.kb-iconbtn,
body.theme-blue  .main-content a.kb-iconbtn { color: var(--ng-text-secondary) !important; }
body.theme-light .main-content a.kb-iconbtn:hover,
body.theme-dark  .main-content a.kb-iconbtn:hover,
body.theme-blue  .main-content a.kb-iconbtn:hover { color: var(--ng-brand) !important; }
body.theme-light .main-content a.loy-tab,
body.theme-dark  .main-content a.loy-tab,
body.theme-blue  .main-content a.loy-tab { color: var(--ng-text-secondary) !important; }
body.theme-light .main-content a.loy-tab.is-active,
body.theme-dark  .main-content a.loy-tab.is-active,
body.theme-blue  .main-content a.loy-tab.is-active { color: var(--ng-on-brand, #fff) !important; }
.main-content a.loy-tab i { color: inherit !important; }

/* Same link-hijack exemption for the other anchor-based tab/segment systems.
   White on a brand fill; brand-active on a light brand-50 fill. (Anchor selectors
   are inert when a given system uses <button> instead, so this is safe.) */
.main-content a.nge-tab.active, .main-content a.nge-pill.active { color: #fff !important; }
.main-content a.nge-tab.active i, .main-content a.nge-pill.active i { color: inherit !important; }
.main-content .hr-seg a.active, .main-content a.hr-seg.active,
.main-content a.exp-filter-pill.active { color: var(--ng-brand-active, #3730a3) !important; }

/* ---------------------------------------------------------------------------
   13. Legacy CSS variable bridges
   (payroll_month.html and other pages use these older names)
   --------------------------------------------------------------------------- */
:root,
body.theme-light,
body.theme-dark,
body.theme-blue {
  --border-color: var(--ng-border);
  --bg:           var(--ng-surface);
  --bg-secondary: var(--ng-surface-2);
  --text-muted:   var(--ng-text-tertiary);
  --hover-bg:     var(--ng-surface-2);
}

/* ---------------------------------------------------------------------------
   14. Shared page-form component layer  (.ng-pageform)
   Replaces per-template .ng-empform / .ng-userform scoped CSS so every
   add/edit form page shares one consistent look.
   --------------------------------------------------------------------------- */

/* Neutralise legacy ".main-content form" card-in-card when form lives inside
   a .content-card that is itself inside .ng-pageform. */
.main-content .ng-pageform > form,
body.theme-dark  .main-content .ng-pageform > form,
body.theme-blue  .main-content .ng-pageform > form {
  max-width: none !important; width: 100% !important; margin: 0 !important;
  padding: 26px 28px !important; background: transparent !important;
  box-shadow: none !important; border-radius: 0 !important;
}
@media (max-width: 640px) { .main-content .ng-pageform > form { padding: 18px !important; } }

/* Full-width add/edit forms (was 880px-centered, which read as "not using the
   page width"). The .ng-grid keeps fields in a readable 2-column layout. */
.ng-pageform { max-width: none; margin-inline: 0; }
.ng-pageform .ng-fieldset { border: 0; padding: 0; margin: 0 0 26px; }
.ng-pageform .ng-fieldset__head { display: flex; align-items: center; gap: 10px; margin-bottom: 4px; }
.ng-pageform .ng-fieldset__head h2 { font-size: 1.05rem; font-weight: 700; color: var(--ng-text); margin: 0; }
.ng-pageform .ng-step {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: var(--ng-radius-pill);
  background: var(--ng-brand); color: var(--ng-on-brand); font-size: .82rem; font-weight: 700; flex: none;
}
.ng-pageform .ng-fieldset__hint { color: var(--ng-text-tertiary); font-size: .85rem; margin: 0 0 14px 36px; }
.ng-pageform .ng-grid { display: grid; gap: 16px; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.ng-pageform .ng-col-full { grid-column: 1 / -1; }
.ng-pageform .ng-field label { display: block; font-weight: 600; font-size: .9rem; color: var(--ng-text-secondary); margin-bottom: 6px; }
.ng-pageform .ng-field input,
.ng-pageform .ng-field select,
.ng-pageform .ng-field textarea { width: 100%; padding: 10px 12px; box-sizing: border-box; }
.ng-pageform .ng-field .ng-help { display: block; margin-top: 6px; font-size: .8rem; color: var(--ng-text-tertiary); }
.ng-pageform .ng-field .ng-errors { margin: 6px 0 0; padding: 0; list-style: none; color: var(--ng-danger-fg); font-size: .82rem; }
.ng-pageform .ng-field.ng-field--error input,
.ng-pageform .ng-field.ng-field--error select,
.ng-pageform .ng-field.ng-field--error textarea { border-color: var(--ng-danger) !important; }
.ng-pageform .ng-alert {
  display: flex; gap: 10px; align-items: flex-start; padding: 12px 14px; border-radius: var(--ng-radius);
  background: var(--ng-danger-bg); border: 1px solid var(--ng-danger); color: var(--ng-danger-fg); margin-bottom: 20px; font-size: .9rem;
}
.ng-pageform .ng-note {
  display: flex; gap: 10px; align-items: flex-start; padding: 12px 14px; border-radius: var(--ng-radius);
  background: var(--ng-brand-50); border: 1px solid var(--ng-brand-100); color: var(--ng-brand-active); font-size: .88rem;
}
.ng-pageform .ng-form-actions {
  display: flex; gap: 12px; align-items: center; flex-wrap: wrap; margin-top: 8px; padding-top: 18px; border-top: 1px solid var(--ng-border);
}
.ng-pageform .ng-check-row { display: flex; align-items: center; gap: 10px; margin-top: 4px; }
.ng-pageform .ng-check-row input[type="checkbox"] { width: var(--ng-check-size,18px); height: var(--ng-check-size,18px); accent-color: var(--ng-brand); cursor: pointer; margin: 0; flex: none; }
.ng-pageform .ng-check-row label { font-weight: 500; font-size: .95rem; color: var(--ng-text); margin: 0; cursor: pointer; }
.ng-pageform select[multiple] { min-height: 130px; }
/* Amount-with-prefix layout */
.ng-pageform .ng-amount-wrap { display: flex; align-items: stretch; }
.ng-pageform .ng-amount-wrap .ng-amount-prefix {
  background: var(--ng-surface-2); border: 1px solid var(--ng-border-strong); border-right: none;
  padding: 10px 12px; border-radius: var(--ng-radius) 0 0 var(--ng-radius); font-weight: 700;
  color: var(--ng-text-secondary); display: flex; align-items: center; white-space: nowrap;
}
.ng-pageform .ng-amount-wrap input { border-radius: 0 var(--ng-radius) var(--ng-radius) 0 !important; }
@media (max-width: 720px) { .ng-pageform .ng-grid { grid-template-columns: 1fr; } }

/* ---------------------------------------------------------------------------
   15. Department dual-select employee picker
   --------------------------------------------------------------------------- */
.ng-emp-selector { border: 1px solid var(--ng-border); border-radius: var(--ng-radius); padding: 1rem; background: var(--ng-surface-2); margin-top: 8px; }
.ng-emp-selector .selector-row { display: flex; gap: 1rem; align-items: flex-start; justify-content: center; }
.ng-emp-selector .employee-column { flex: 1; max-width: 300px; display: flex; flex-direction: column; }
.ng-emp-selector .selector-label { font-weight: 600; font-size: .85rem; margin-bottom: 6px; text-align: center; color: var(--ng-text-secondary); }
.ng-emp-selector .employee-select { width: 100%; padding: .4rem; border: 1px solid var(--ng-border-strong); border-radius: var(--ng-radius); font-size: .88rem; background: var(--ng-surface); color: var(--ng-text); min-height: 260px; }
.ng-emp-selector .selector-buttons { display: flex; flex-direction: column; gap: .5rem; justify-content: center; align-items: center; min-width: 48px; padding: 2rem 0; }
.ng-emp-selector .move-btn { width: 36px; height: 36px; background: var(--ng-brand) !important; color: var(--ng-on-brand) !important; border: none !important; border-radius: var(--ng-radius) !important; cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: .9rem; }
.ng-emp-selector .move-btn:hover { background: var(--ng-brand-hover) !important; }
.ng-emp-selector .select-all-btn { margin-top: .4rem; padding: .3rem .6rem; background: var(--ng-surface) !important; color: var(--ng-text-secondary) !important; border: 1px solid var(--ng-border) !important; border-radius: var(--ng-radius) !important; cursor: pointer; font-size: .78rem; width: 100%; }
.ng-emp-selector .select-all-btn:hover { background: var(--ng-surface-2) !important; }
@media (max-width: 680px) {
  .ng-emp-selector .selector-row { flex-direction: column; align-items: stretch; }
  .ng-emp-selector .employee-column { max-width: none; }
  .ng-emp-selector .selector-buttons { flex-direction: row; padding: .5rem 0; }
}

/* ---------------------------------------------------------------------------
   16. Sales metric cards (dashboard improvements)
   --------------------------------------------------------------------------- */
.metrics-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; margin-bottom: 28px; }
.metric-card { background: var(--ng-surface) !important; border: 1px solid var(--ng-border) !important; border-radius: var(--ng-radius-lg) !important; padding: 20px; display: flex; align-items: center; gap: 16px; box-shadow: var(--ng-shadow-sm); transition: box-shadow .15s; }
.metric-card:hover { box-shadow: var(--ng-shadow-md); }
.metric-icon { width: 48px; height: 48px; border-radius: var(--ng-radius); display: flex; align-items: center; justify-content: center; font-size: 1.2rem; flex: none; background: var(--ng-brand-50); color: var(--ng-brand); }
.metric-icon.month    { background: #ecfdf5; color: #059669; }
.metric-icon.year     { background: #eff6ff; color: #2563eb; }
.metric-icon.average  { background: #fff7ed; color: #d97706; }
.metric-icon.employee { background: #fdf2f8; color: #db2777; }
.metric-icon.site     { background: #f0fdf4; color: #16a34a; }
.metric-content { min-width: 0; }
.metric-value  { font-size: 1.25rem; font-weight: 700; color: var(--ng-text) !important; margin: 0 0 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.metric-label  { font-size: .85rem; font-weight: 600; color: var(--ng-text-secondary) !important; margin: 0 0 2px; }
.metric-period { font-size: .75rem; color: var(--ng-text-tertiary) !important; }

/* ---------------------------------------------------------------------------
   17. Inline button spinner (FontAwesome-independent)
   A CSS-only spinner for AJAX buttons/status text — inherits the current text
   colour so it works in every theme with no per-theme rules and no glyph
   dependency. Usage: <span class="ng-btn-spin"></span>
   --------------------------------------------------------------------------- */
@keyframes ng-btn-spin-rot { to { transform: rotate(360deg); } }
.ng-btn-spin {
  display: inline-block; width: 1em; height: 1em; vertical-align: -.15em;
  border: 2px solid currentColor; border-right-color: transparent;
  border-radius: 50%; animation: ng-btn-spin-rot .7s linear infinite;
}
