// Shared HRM components — sidebar, topbar, common UI bits
// Tiếng Việt UI

// ─────────────────────────────────────────────────────────────
// Tailwind setup — inject @theme tokens + @tailwindcss/browser ONCE.
// shared.jsx is loaded by every mockup, so this makes Tailwind utility
// classes available everywhere without editing a single HTML file.
// (@tailwindcss/browser only processes inline <style type="text/tailwindcss">,
//  not <link> — so the theme is injected as such a <style>.)
// ─────────────────────────────────────────────────────────────
(function injectTailwind() {
  if (document.getElementById('els-tw-theme')) return;
  const style = document.createElement('style');
  style.id = 'els-tw-theme';
  style.setAttribute('type', 'text/tailwindcss');
  style.textContent = `
    @custom-variant dark (&:is(.dark *));
    @theme {
      --font-sans: 'Archivo', ui-sans-serif, system-ui, sans-serif;
      --font-mono: ui-monospace, 'Cascadia Code', 'Source Code Pro', monospace;
      --font-heading: var(--font-sans);
      --text-2xs: 0.625rem; --text-xs: 0.75rem; --text-sm: 0.8125rem; --text-base: 0.875rem;
      --text-md: 1rem; --text-lg: 1.125rem; --text-xl: 1.25rem; --text-2xl: 1.5rem;
      --text-3xl: 1.875rem; --text-4xl: 2.25rem; --text-5xl: 3rem;
      --color-primary: oklch(0.687 0.184 41); --color-primary-foreground: oklch(1 0 0);
      --color-primary-hover: oklch(0.640 0.184 41); --color-primary-soft: oklch(0.965 0.038 47);
      --color-secondary: oklch(0.385 0.062 222); --color-secondary-foreground: oklch(0.985 0 0);
      --color-secondary-soft: oklch(0.948 0.030 222);
      --color-destructive: oklch(0.601 0.215 12); --color-destructive-foreground: oklch(1 0 0);
      --color-destructive-soft: oklch(0.962 0.040 12);
      --color-success: oklch(0.711 0.180 148); --color-success-foreground: oklch(1 0 0);
      --color-success-soft: oklch(0.962 0.058 148);
      --color-warning: oklch(0.835 0.158 80); --color-warning-foreground: oklch(0.213 0.020 264);
      --color-warning-soft: oklch(0.972 0.052 86);
      --color-info: oklch(0.604 0.180 253); --color-info-foreground: oklch(1 0 0);
      --color-info-soft: oklch(0.958 0.030 253);
      --color-team: oklch(0.564 0.198 320); --color-team-foreground: oklch(1 0 0);
      --color-team-soft: oklch(0.958 0.030 320);
      --color-background: oklch(0.985 0 0); --color-foreground: oklch(0.213 0.020 264);
      --color-card: oklch(1 0 0); --color-card-foreground: oklch(0.213 0.020 264);
      --color-popover: oklch(1 0 0); --color-popover-foreground: oklch(0.213 0.020 264);
      --color-muted: oklch(0.962 0.003 264); --color-muted-foreground: oklch(0.554 0.012 264);
      --color-accent: oklch(0.948 0.003 264); --color-accent-foreground: oklch(0.213 0.020 264);
      --color-surface: oklch(0.985 0 0);
      --color-border: oklch(0.918 0.004 264); --color-border-strong: oklch(0.871 0.005 264);
      --color-input: oklch(0.918 0.004 264); --color-ring: oklch(0.687 0.184 41 / 0.35);
      --color-sidebar: oklch(1 0 0); --color-sidebar-foreground: oklch(0.213 0.020 264);
      --color-sidebar-muted: oklch(0.554 0.012 264); --color-sidebar-primary: oklch(0.687 0.184 41);
      --color-sidebar-primary-foreground: oklch(1 0 0); --color-sidebar-accent: oklch(0.948 0.003 264);
      --color-sidebar-accent-foreground: oklch(0.213 0.020 264); --color-sidebar-border: oklch(0.918 0.004 264);
      --color-chart-1: oklch(0.687 0.184 41); --color-chart-2: oklch(0.604 0.180 253);
      --color-chart-3: oklch(0.711 0.180 148); --color-chart-4: oklch(0.835 0.158 80);
      --color-chart-5: oklch(0.385 0.062 222); --color-chart-6: oklch(0.601 0.215 12);
      --color-chart-7: oklch(0.564 0.198 320);
      --color-selection: oklch(0.687 0.184 41 / 0.20); --color-selection-foreground: oklch(0.213 0.020 264);
      --radius-sm: 0.375rem; --radius-md: 0.5rem; --radius-lg: 0.625rem; --radius-xl: 0.875rem;
      --radius-2xl: 1.125rem; --radius-3xl: 1.375rem; --radius-full: 9999px;
      --shadow-2xs: 0 1px 0 0 rgb(0 0 0 / 0.04); --shadow-xs: 0 1px 2px 0 rgb(198 198 198 / 0.20);
      --shadow-sm: 0 1px 3px 0 rgb(0 0 0 / 0.08), 0 1px 2px -1px rgb(0 0 0 / 0.06);
      --shadow-md: 0 4px 8px -2px rgb(0 0 0 / 0.08), 0 2px 4px -2px rgb(0 0 0 / 0.06);
      --shadow-lg: 0 12px 20px -4px rgb(0 0 0 / 0.10), 0 4px 8px -4px rgb(0 0 0 / 0.08);
      --shadow-xl: 0 20px 32px -8px rgb(0 0 0 / 0.12); --shadow-2xl: 0 28px 56px -16px rgb(0 0 0 / 0.18);
    }
    .dark {
      --color-background: oklch(0.165 0.012 264); --color-foreground: oklch(0.962 0.003 264);
      --color-card: oklch(0.213 0.013 264); --color-card-foreground: oklch(0.962 0.003 264);
      --color-popover: oklch(0.231 0.013 264); --color-popover-foreground: oklch(0.962 0.003 264);
      --color-primary: oklch(0.722 0.184 41); --color-primary-foreground: oklch(0.165 0.012 264);
      --color-primary-hover: oklch(0.770 0.184 41); --color-primary-soft: oklch(0.300 0.080 41);
      --color-secondary: oklch(0.554 0.082 222); --color-secondary-foreground: oklch(0.962 0.003 264);
      --color-muted: oklch(0.269 0.012 264); --color-muted-foreground: oklch(0.708 0.005 264);
      --color-accent: oklch(0.310 0.012 264);
      --color-destructive: oklch(0.660 0.215 12); --color-destructive-soft: oklch(0.300 0.090 12);
      --color-success: oklch(0.740 0.180 148); --color-success-soft: oklch(0.280 0.080 148);
      --color-warning: oklch(0.850 0.158 80); --color-warning-soft: oklch(0.300 0.080 80);
      --color-info: oklch(0.650 0.180 253); --color-info-soft: oklch(0.280 0.080 253);
      --color-team: oklch(0.680 0.198 320); --color-team-soft: oklch(0.280 0.080 320);
      --color-border: oklch(1 0 0 / 0.07); --color-border-strong: oklch(1 0 0 / 0.13);
      --color-input: oklch(1 0 0 / 0.09); --color-ring: oklch(0.722 0.184 41 / 0.45);
      --color-sidebar: oklch(0.190 0.012 264); --color-sidebar-foreground: oklch(0.962 0.003 264);
      --color-sidebar-muted: oklch(0.620 0.008 264); --color-sidebar-primary: oklch(0.722 0.184 41);
      --color-sidebar-accent: oklch(0.269 0.012 264); --color-sidebar-border: oklch(1 0 0 / 0.06);
      --color-chart-1: oklch(0.722 0.184 41); --color-chart-2: oklch(0.650 0.180 253);
      --color-chart-3: oklch(0.740 0.180 148); --color-chart-4: oklch(0.850 0.158 80);
      --color-chart-5: oklch(0.554 0.082 222); --color-chart-6: oklch(0.660 0.215 12);
      --color-chart-7: oklch(0.620 0.198 320);
    }`;
  document.head.appendChild(style);
  // Plain base: Archivo font-face + 16px root (so the rem-based @theme maps to the
  // designed px). Kept here so the mockups still get the font + scale once the legacy
  // vanilla CSS is removed at the end of the migration.
  const base = document.createElement('style');
  base.textContent = `
    @font-face { font-family: 'Archivo'; font-style: normal; font-weight: 100 900;
      font-stretch: 62.5% 125%; font-display: swap;
      src: url('fonts/Archivo-VariableFont_wdth_wght.ttf') format('truetype-variations'); }
    html { font-size: 16px; }
    /* Alias token cũ (không prefix) → @theme --color-*. Để design-canvas.jsx (nav pill, chrome
       dùng var(--primary,#fallback)) + bất kỳ var(--X) legacy còn sót resolve đúng màu khi đã bỏ
       colors_and_type.css. Tự theo dark vì trỏ tới --color-* (mà .dark đã override). */
    :root {
      --background: var(--color-background); --foreground: var(--color-foreground);
      --card: var(--color-card); --card-foreground: var(--color-card-foreground);
      --popover: var(--color-popover); --popover-foreground: var(--color-popover-foreground);
      --primary: var(--color-primary); --primary-foreground: var(--color-primary-foreground);
      --primary-hover: var(--color-primary-hover); --primary-soft: var(--color-primary-soft);
      --secondary: var(--color-secondary); --secondary-foreground: var(--color-secondary-foreground);
      --muted: var(--color-muted); --muted-foreground: var(--color-muted-foreground);
      --accent: var(--color-accent); --accent-foreground: var(--color-accent-foreground);
      --success: var(--color-success); --success-soft: var(--color-success-soft);
      --warning: var(--color-warning); --warning-soft: var(--color-warning-soft);
      --info: var(--color-info); --info-soft: var(--color-info-soft);
      --destructive: var(--color-destructive); --destructive-soft: var(--color-destructive-soft);
      --border: var(--color-border); --border-strong: var(--color-border-strong);
      --input: var(--color-input); --ring: var(--color-ring);
      --chart-1: var(--color-chart-1); --chart-2: var(--color-chart-2); --chart-3: var(--color-chart-3);
      --chart-4: var(--color-chart-4); --chart-5: var(--color-chart-5); --chart-6: var(--color-chart-6); --chart-7: var(--color-chart-7);
      --sidebar: var(--color-sidebar); --sidebar-foreground: var(--color-sidebar-foreground);
      --sidebar-muted: var(--color-sidebar-muted); --sidebar-primary: var(--color-sidebar-primary);
      --sidebar-accent: var(--color-sidebar-accent); --sidebar-border: var(--color-sidebar-border);
      --selection: var(--color-selection); --selection-foreground: var(--color-selection-foreground);
      --font-label: var(--font-sans);
      --radius: 0.625rem;
      --space-1: 0.25rem; --space-2: 0.5rem; --space-3: 0.75rem; --space-4: 1rem;
      --space-5: 1.25rem; --space-6: 1.5rem; --space-8: 2rem; --space-10: 2.5rem; --space-12: 3rem;
      --h-xs: 1.5rem; --h-sm: 2rem; --h-md: 2.25rem; --h-lg: 2.5rem; --h-xl: 3rem;
    }`;
  document.head.appendChild(base);
  const sc = document.createElement('script');
  sc.src = 'https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4';
  document.head.appendChild(sc);
})();

const Icon = ({ name, size = 16, className = "", style = {} }) => {
  const paths = {
    'layout-dashboard': 'M3 3h7v9H3zM14 3h7v5h-7zM14 12h7v9h-7zM3 16h7v5H3z',
    'users': 'M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2 M12 7a4 4 0 1 1-8 0 4 4 0 0 1 8 0z M22 21v-2a4 4 0 0 0-3-3.87 M16 3.13a4 4 0 0 1 0 7.75',
    'user': 'M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2 M16 7a4 4 0 1 1-8 0 4 4 0 0 1 8 0z',
    'user-check': 'M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2 M11 7a4 4 0 1 1-8 0 4 4 0 0 1 8 0z M16 11l2 2 4-4',
    'briefcase': 'M20 7h-16a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2z M16 21V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16',
    'calendar': 'M3 4h18v18H3zM3 10h18M8 2v4M16 2v4',
    'calendar-days': 'M8 2v4M16 2v4M3 10h18M5 4h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2z M8 14h.01M12 14h.01M16 14h.01M8 18h.01M12 18h.01M16 18h.01',
    'clock': 'M12 22a10 10 0 1 0 0-20 10 10 0 0 0 0 20z M12 6v6l4 2',
    'dollar': 'M12 1v22 M17 5H9.5a3.5 3.5 0 1 0 0 7h5a3.5 3.5 0 1 1 0 7H6',
    'file-text': 'M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z M14 2v6h6 M16 13H8 M16 17H8 M10 9H8',
    'settings': 'M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09a1.65 1.65 0 0 0-1-1.51 1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09a1.65 1.65 0 0 0 1.51-1 1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33h0a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51h0a1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82v0a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6z',
    'search': 'M21 21l-4.35-4.35 M10 18a8 8 0 1 0 0-16 8 8 0 0 0 0 16z',
    'bell': 'M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9 M10.3 21a1.94 1.94 0 0 0 3.4 0',
    'plus': 'M12 5v14M5 12h14',
    'plus-circle': 'M12 22a10 10 0 1 0 0-20 10 10 0 0 0 0 20zM12 8v8M8 12h8',
    'filter': 'M22 3H2l8 9.46V19l4 2v-8.54L22 3z',
    'chevron-down': 'M6 9l6 6 6-6',
    'chevron-right': 'M9 18l6-6-6-6',
    'chevron-left': 'M15 18l-6-6 6-6',
    'arrow-up': 'M12 19V5M5 12l7-7 7 7',
    'arrow-down': 'M12 5v14M19 12l-7 7-7-7',
    'arrow-right': 'M5 12h14M12 5l7 7-7 7',
    'trending-up': 'M22 7l-9.5 9.5-5-5L1 18 M16 7h6v6',
    'trending-down': 'M22 17l-9.5-9.5-5 5L1 6 M16 17h6v-6',
    'more-horizontal': 'M12 13a1 1 0 1 0 0-2 1 1 0 0 0 0 2zM19 13a1 1 0 1 0 0-2 1 1 0 0 0 0 2zM5 13a1 1 0 1 0 0-2 1 1 0 0 0 0 2z',
    'more-vertical': 'M12 6a1 1 0 1 0 0-2 1 1 0 0 0 0 2zM12 13a1 1 0 1 0 0-2 1 1 0 0 0 0 2zM12 20a1 1 0 1 0 0-2 1 1 0 0 0 0 2z',
    'mail': 'M4 4h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2zM22 6l-10 7L2 6',
    'phone': 'M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.13.96.37 1.9.72 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.91.35 1.85.59 2.81.72A2 2 0 0 1 22 16.92z',
    'check': 'M20 6L9 17l-5-5',
    'x': 'M18 6L6 18M6 6l12 12',
    'edit': 'M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7 M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z',
    'trash': 'M3 6h18 M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6 M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2',
    'star': 'M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z',
    'building': 'M3 21h18M5 21V7l8-4v18M19 21V11l-6-4 M9 9v.01M9 12v.01M9 15v.01M9 18v.01',
    'map-pin': 'M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z M12 13a3 3 0 1 0 0-6 3 3 0 0 0 0 6z',
    'gift': 'M20 12v10H4V12 M2 7h20v5H2zM12 22V7 M12 7H7.5a2.5 2.5 0 0 1 0-5C11 2 12 7 12 7zM12 7h4.5a2.5 2.5 0 0 0 0-5C13 2 12 7 12 7z',
    'award': 'M12 15a7 7 0 1 0 0-14 7 7 0 0 0 0 14zM8.21 13.89L7 23l5-3 5 3-1.21-9.12',
    'log-out': 'M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4 M16 17l5-5-5-5 M21 12H9',
    'menu': 'M3 12h18M3 6h18M3 18h18',
    'check-circle': 'M22 11.08V12a10 10 0 1 1-5.93-9.14 M22 4L12 14.01l-3-3',
    'x-circle': 'M12 22a10 10 0 1 0 0-20 10 10 0 0 0 0 20zM15 9l-6 6 M9 9l6 6',
    'alert-circle': 'M12 22a10 10 0 1 0 0-20 10 10 0 0 0 0 20zM12 8v4M12 16h.01',
    'eye': 'M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6z',
    'download': 'M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4 M7 10l5 5 5-5 M12 15V3',
    'upload': 'M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4 M17 8l-5-5-5 5 M12 3v12',
    'cake': 'M20 21V11a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v10 M4 16s1.5-2 4-2 3.5 2 4 2 1.5-2 4-2 4 2 4 2 M2 21h20 M7 8V3M12 8V3M17 8V3',
    'home': 'M3 9l9-7 9 7v11a2 2 0 0 1-2 2h-4 M9 22V12h6v10',
    'inbox': 'M22 12h-6l-2 3h-4l-2-3H2 M5.45 5.11L2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z',
    'umbrella': 'M23 12a11.05 11.05 0 0 0-22 0zm-5 7a3 3 0 0 1-6 0v-7',
    'message-square': 'M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z',
    'globe': 'M12 22a10 10 0 1 0 0-20 10 10 0 0 0 0 20zM2 12h20 M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z',
    'sun': 'M12 17a5 5 0 1 0 0-10 5 5 0 0 0 0 10zM12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42',
    'moon': 'M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z',
    'help-circle': 'M12 22a10 10 0 1 0 0-20 10 10 0 0 0 0 20zM9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3M12 17h.01',
    'lock': 'M5 11h14a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2z M7 11V7a5 5 0 0 1 10 0v4',
    'shield': 'M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z',
    'info': 'M12 22a10 10 0 1 0 0-20 10 10 0 0 0 0 20zM12 16v-4M12 8h.01',
    'eye-off': 'M9.88 9.88a3 3 0 1 0 4.24 4.24 M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 11 7 11 7a13.16 13.16 0 0 1-1.67 2.68 M6.61 6.61A13.526 13.526 0 0 0 1 12s4 7 11 7a9.74 9.74 0 0 0 5.39-1.61 M2 2l20 20',
    'rotate-ccw': 'M3 2v6h6 M3.51 9a9 9 0 1 0 2.13-3.36L3 8',
    'paperclip': 'M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48',
    'image': 'M19 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2z M8.5 10a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3z M21 15l-5-5L5 21',
    'file': 'M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z M14 2v6h6',
    'pause-circle': 'M12 22a10 10 0 1 0 0-20 10 10 0 0 0 0 20z M10 15V9 M14 15V9',
    'minus-circle': 'M12 22a10 10 0 1 0 0-20 10 10 0 0 0 0 20z M8 12h8',
    'alert-triangle': 'M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z M12 9v4 M12 17h.01',
    'send': 'M22 2L11 13 M22 2l-7 20-4-9-9-4 20-7z',
    'key': 'M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3',
    'user-cog': 'M13 7a4 4 0 1 1-8 0 4 4 0 0 1 8 0z M10 15H6a4 4 0 0 0-4 4v2 M20.1 15a2.6 2.6 0 1 1-5.2 0 2.6 2.6 0 0 1 5.2 0z M20.1 15L21.7 15 M18.8 17.3L19.6 18.6 M16.2 17.3L15.4 18.6 M14.9 15L13.3 15 M16.2 12.8L15.4 11.4 M18.8 12.8L19.6 11.4',
    'shield-check': 'M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z M9 12l2 2 4-4',
    'list': 'M8 6h13 M8 12h13 M8 18h13 M3 6h.01 M3 12h.01 M3 18h.01',
  };
  const d = paths[name] || paths['help-circle'];
  return (
    <svg xmlns="http://www.w3.org/2000/svg" width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round" className={className} style={style}>
      {d.split(' M').map((seg, i) => <path key={i} d={(i === 0 ? '' : 'M') + seg} />)}
    </svg>
  );
};

const Avatar = ({ name = "AN", color = "#F26522", size, src, status, square }) => {
  const sizeCls = size === 'sm' ? 'size-6 text-2xs'
    : size === 'lg' ? 'size-12 text-md'
    : size === 'xl' ? 'size-[4.5rem] text-xl'
    : 'size-8 text-xs';
  const initials = name.split(' ').slice(0, 2).map(s => s[0]).join('').toUpperCase();
  // Deterministic hue from name
  let h = 0; for (let i = 0; i < name.length; i++) h = (h * 31 + name.charCodeAt(i)) % 360;
  const bg = src ? null : `oklch(0.92 0.05 ${h})`;
  const fg = src ? null : `oklch(0.4 0.12 ${h})`;
  return (
    <span className={`relative inline-flex shrink-0 items-center justify-center overflow-hidden font-semibold ${square ? 'rounded-md' : 'rounded-full'} ${sizeCls}`} style={{ background: bg, color: fg }}>
      {src ? <img src={src} alt={name} className="size-full object-cover" /> : initials}
      {status && <span className="absolute bottom-0 right-0 size-2 rounded-full border-2 border-card bg-success" />}
    </span>
  );
};

const BADGE_VARIANTS = {
  success: 'bg-success-soft text-success',
  warning: 'bg-warning-soft text-[oklch(0.55_0.158_65)]',
  info: 'bg-info-soft text-info',
  danger: 'bg-destructive-soft text-destructive',
  primary: 'bg-primary-soft text-primary',
  neutral: 'bg-muted text-muted-foreground',
  'solid-primary': 'bg-primary text-primary-foreground',
};
const Badge = ({ children, variant = "neutral", dot }) => (
  <span className={`inline-flex items-center gap-1 whitespace-nowrap rounded-md border border-transparent px-2.5 py-0.5 text-xs font-semibold leading-none ${BADGE_VARIANTS[variant] || BADGE_VARIANTS.neutral}`}>
    {dot && <span className="size-[0.3125rem] shrink-0 rounded-full bg-current" />}
    {children}
  </span>
);

const BTN_VARIANTS = {
  primary: 'bg-primary text-primary-foreground shadow-xs hover:bg-primary-hover',
  secondary: 'bg-secondary text-secondary-foreground shadow-xs hover:brightness-110',
  outline: 'border-border bg-background text-foreground shadow-xs hover:bg-accent hover:text-accent-foreground',
  'outline-primary': 'border-primary bg-background text-primary shadow-xs hover:bg-primary-soft',
  ghost: 'bg-transparent text-foreground hover:bg-accent hover:text-accent-foreground',
  soft: 'bg-primary-soft text-primary hover:bg-[oklch(0.945_0.045_47)]',
  destructive: 'bg-destructive text-destructive-foreground shadow-xs hover:brightness-90',
};
const Btn = ({ children, variant = "primary", size, iconOnly, icon, iconRight, className = "", ...rest }) => {
  const base = "inline-flex items-center justify-center whitespace-nowrap rounded-md border border-transparent font-medium leading-none cursor-pointer select-none transition-colors focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring focus-visible:border-primary disabled:pointer-events-none disabled:opacity-50";
  const sz = size === 'xs' ? (iconOnly ? 'h-6 w-6 p-0 gap-1 text-xs' : 'h-6 gap-1 px-2 text-xs')
    : size === 'sm' ? (iconOnly ? 'h-8 w-8 p-0 gap-1.5 text-xs' : 'h-8 gap-1.5 px-3 text-xs')
    : size === 'lg' ? (iconOnly ? 'h-10 w-10 p-0 gap-2 text-md' : 'h-10 gap-2 px-6 text-md')
    : (iconOnly ? 'h-9 w-9 p-0 gap-2 text-base' : 'h-9 gap-2 px-4 text-base');
  return (
    <button className={`${base} ${BTN_VARIANTS[variant] || ''} ${sz} ${className}`} {...rest}>
      {icon && <Icon name={icon} size={14} />}
      {!iconOnly && children}
      {iconRight && <Icon name={iconRight} size={14} />}
    </button>
  );
};

const StatCard = ({ label, value, delta, deltaDir = "up", icon, iconBg = "var(--color-primary-soft)", iconColor = "var(--color-primary)" }) => (
  <div className="flex flex-col gap-2 rounded-lg border border-border bg-card p-4">
    <div className="flex items-center justify-between">
      <span className="text-xs font-medium uppercase tracking-[0.04em] text-muted-foreground">{label}</span>
      <span className="grid size-9 place-items-center rounded-md" style={{ background: iconBg, color: iconColor }}>
        <Icon name={icon} size={18} />
      </span>
    </div>
    <div className="text-2xl font-bold leading-none tabular-nums text-foreground">{value}</div>
    {delta && (
      <span className={"inline-flex items-center gap-1 text-xs font-medium " + (deltaDir === 'up' ? 'text-success' : 'text-destructive')}>
        <Icon name={deltaDir === 'up' ? 'trending-up' : 'trending-down'} size={12} />
        {delta}
      </span>
    )}
  </div>
);

// Mini bar/area chart with SVG
const MiniChart = ({ data, color = "var(--color-primary)", height = 64, width = "100%", filled = true }) => {
  const max = Math.max(...data);
  const w = 280, h = height;
  const step = w / (data.length - 1);
  const points = data.map((v, i) => [i * step, h - (v / max) * (h - 6) - 3]);
  const path = points.map((p, i) => (i === 0 ? `M${p[0]},${p[1]}` : `L${p[0]},${p[1]}`)).join(' ');
  const area = `${path} L${w},${h} L0,${h} Z`;
  return (
    <svg viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="none" style={{ width, height, display: 'block' }}>
      {filled && <path d={area} fill={color} opacity="0.12" />}
      <path d={path} fill="none" stroke={color} strokeWidth="2" strokeLinejoin="round" strokeLinecap="round" />
    </svg>
  );
};

const Bars = ({ data, color = "var(--color-primary)", height = 64, gap = 4 }) => {
  const max = Math.max(...data);
  return (
    <div style={{ display: 'flex', alignItems: 'flex-end', gap, height }}>
      {data.map((v, i) => (
        <div key={i} style={{ flex: 1, height: `${(v / max) * 100}%`, background: color, borderRadius: 2, opacity: 0.4 + (v / max) * 0.6 }} />
      ))}
    </div>
  );
};

const Donut = ({ segments, size = 120, stroke = 14 }) => {
  const r = (size - stroke) / 2;
  const c = 2 * Math.PI * r;
  const total = segments.reduce((a, b) => a + b.value, 0);
  let offset = 0;
  return (
    <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`} style={{ transform: 'rotate(-90deg)' }}>
      <circle cx={size/2} cy={size/2} r={r} fill="none" stroke="var(--color-muted)" strokeWidth={stroke} />
      {segments.map((s, i) => {
        const len = (s.value / total) * c;
        const el = (
          <circle key={i} cx={size/2} cy={size/2} r={r} fill="none"
            stroke={s.color} strokeWidth={stroke}
            strokeDasharray={`${len} ${c - len}`}
            strokeDashoffset={-offset} strokeLinecap="butt" />
        );
        offset += len;
        return el;
      })}
    </svg>
  );
};

// ─────────────────────────────────────────────────────────────
// Select — dropdown mockup ĐỒNG BỘ với @radix-ui Select của hrm-admin
// (apps/hrm-admin/src/components/ui/select.tsx · bản tiện dùng SimpleSelect).
// Mức "đủ giống": trigger khớp recipe input của mockup + popup tuỳ biến khớp
// SelectContent/SelectItem của code (thay menu native do hệ điều hành vẽ).
// Có mở/đóng, chọn, click-outside, Esc. KHÔNG làm điều hướng bàn phím / portal /
// chống tràn viewport — thừa cho mockup tĩnh.
//   options : ['Văn bản', ...] HOẶC [{ label, value }, ...]
//   uncontrolled-friendly: tự giữ lựa chọn khi không truyền `value`
//     (mockup hiện dùng <select defaultValue> không có state riêng).
// ─────────────────────────────────────────────────────────────
// font-sans explicit: <button> không kế thừa font theo chuẩn HTML — không dựa vào Tailwind
// Preflight để có Archivo (Preflight có thể chưa/không áp trong môi trường render design).
const SELECT_TRIGGER = "font-sans flex w-full cursor-pointer items-center justify-between gap-2 rounded-md border border-input bg-transparent px-3 text-foreground shadow-xs transition-colors focus:border-primary focus:outline-none focus:ring-[3px] focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50";
function Select({ options = [], value, onValueChange, placeholder, defaultValue, disabled, className = "", style }) {
  const norm = options.map((o) => (typeof o === 'string' ? { label: o, value: o } : o));
  // Cỡ mặc định = form (h-9 text-base). Nếu className đã chỉ định h-* / text-* (vd filter
  // "h-8 text-xs") thì tôn trọng; nếu chưa, tự thêm — TRÁNH việc truyền className phụ
  // (w-full, cursor-pointer, mb-*) vô tình ghi đè mất cỡ form → chữ kế thừa sai cỡ.
  const _tok = className.split(/\s+/).filter(Boolean);
  const _textTok = _tok.find((t) => /^text-(?:xs|sm|base|md|lg|xl)$/.test(t));
  const _sizeCls = (_tok.some((t) => /^h-/.test(t)) ? "" : "h-9 ") + (_textTok || "text-base");
  const [open, setOpen] = React.useState(false);
  const [internal, setInternal] = React.useState(defaultValue);
  const ref = React.useRef(null);
  const isControlled = value !== undefined;
  const current = isControlled ? value : internal;
  const selected = norm.find((o) => o.value === current);

  React.useEffect(() => {
    if (!open) return;
    const onDown = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    const onKey = (e) => { if (e.key === 'Escape') setOpen(false); };
    document.addEventListener('pointerdown', onDown, true);
    document.addEventListener('keydown', onKey);
    return () => {
      document.removeEventListener('pointerdown', onDown, true);
      document.removeEventListener('keydown', onKey);
    };
  }, [open]);

  const pick = (v) => {
    if (!isControlled) setInternal(v);
    if (onValueChange) onValueChange(v);
    setOpen(false);
  };

  return (
    <div ref={ref} className="relative" style={style}>
      <button type="button" disabled={disabled} onClick={() => setOpen((o) => !o)}
        className={SELECT_TRIGGER + " " + _sizeCls + " " + className}>
        <span className={"line-clamp-1 text-left " + (selected ? "" : "text-muted-foreground")}>
          {selected ? selected.label : (placeholder || "")}
        </span>
        <Icon name="chevron-down" size={16} className="shrink-0 opacity-50" />
      </button>
      {open && (
        <div className="font-sans absolute left-0 top-full z-50 mt-1 max-h-80 w-full min-w-[8rem] overflow-auto rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md">
          {norm.map((o) => {
            const sel = o.value === current;
            return (
              <div key={o.value} onClick={() => pick(o.value)}
                className={"relative flex cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 " + (_textTok || "text-base") + " outline-none hover:bg-accent hover:text-accent-foreground " + (sel ? "font-medium" : "")}>
                {sel && (
                  <span className="absolute left-2 flex size-3.5 items-center justify-center">
                    <Icon name="check" size={16} />
                  </span>
                )}
                {o.label}
              </div>
            );
          })}
        </div>
      )}
    </div>
  );
}

Object.assign(window, { Icon, Avatar, Badge, Btn, StatCard, MiniChart, Bars, Donut, Select });

// ─────────────────────────────────────────────────────────────
// HRM Module Navigator — floating pill, auto-mounts on every page.
// ─────────────────────────────────────────────────────────────
// `file` PHẢI khớp ĐÚNG tên tệp .html có thật trong project: pill so khớp bằng tên tệp
// lấy từ location.pathname. Lệch một ký tự thì currentIdx = -1 và pill hiện chữ "ELS HRM"
// thay vì tên module, mũi tên trước/sau cũng nhảy sai — không có lỗi nào báo ra.
// Đã đồng bộ 2026-08-04: sửa 'HRM-12-Cau-Hinh.html' (tệp không còn tồn tại) và bổ sung
// Danh Mục (12), Tài Khoản (13), Cấu Hình (14), Hướng Dẫn (15).
const HRM_MODULES_LIST = [
  { file: 'HRM-00-Login.html',               label: 'Login',           num: 'L'  },
  { file: 'HRM-01-Dashboard.html',           label: 'Dashboard',       num: '01' },
  { file: 'HRM-02-RBAC.html',                label: 'Phân Quyền',      num: '02' },
  { file: 'HRM-03-Cau-Truc-To-Chuc.html',    label: 'Tổ Chức',         num: '03' },
  { file: 'HRM-04-Quan-Ly-Nguoi-Dung.html',  label: 'Người Dùng',      num: '04' },
  { file: 'HRM-05-Nhan-Vien-PIM.html',       label: 'Nhân Viên',       num: '05' },
  { file: 'HRM-06-Nghi-Phep.html',           label: 'Nghỉ Phép',       num: '06' },
  { file: 'HRM-07-Bang-Cong.html',           label: 'Bảng Công',       num: '07' },
  { file: 'HRM-08-Cham-Cong.html',           label: 'Chấm Công',       num: '08' },
  { file: 'HRM-09-Tuyen-Dung.html',          label: 'Tuyển Dụng',      num: '09' },
  { file: 'HRM-10-Ung-Vien.html',            label: 'Ứng Viên',        num: '10' },
  { file: 'HRM-11-Lich-Phong-Van.html',      label: 'Lịch Phỏng Vấn', num: '11' },
  { file: 'HRM-12-Danh-Muc.html',            label: 'Danh Mục',        num: '12' },
  { file: 'HRM-13-Tai-Khoan.html',           label: 'Tài Khoản',       num: '13' },
  { file: 'HRM-14-Cau-Hinh.html',            label: 'Cấu Hình',        num: '14' },
  { file: 'HRM-15-Huong-Dan-Su-Dung.html',   label: 'Hướng Dẫn',       num: '15' },
];

function HRMNavArrowBtn({ children, onClick, disabled, title }) {
  const [hov, setHov] = React.useState(false);
  return (
    <button
      onClick={onClick}
      disabled={disabled}
      title={title}
      onMouseEnter={() => setHov(true)}
      onMouseLeave={() => setHov(false)}
      style={{
        width: 32, height: 32,
        border: 'none', borderRadius: '50%',
        background: hov && !disabled ? 'var(--accent,#f4f4f5)' : 'transparent',
        cursor: disabled ? 'default' : 'pointer',
        color: disabled ? 'var(--muted-foreground,#a1a1aa)' : 'var(--foreground,#18181b)',
        opacity: disabled ? 0.35 : 1,
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        flexShrink: 0,
        transition: 'background .12s, opacity .12s',
      }}>
      {children}
    </button>
  );
}

function HRMModuleNavigator() {
  const decoded = (() => {
    try { return decodeURIComponent(location.pathname.split('/').pop() || ''); } catch { return ''; }
  })();
  const currentIdx = HRM_MODULES_LIST.findIndex(m => decoded === m.file);
  const current = HRM_MODULES_LIST[currentIdx];
  const prev    = currentIdx > 0 ? HRM_MODULES_LIST[currentIdx - 1] : null;
  const next    = currentIdx < HRM_MODULES_LIST.length - 1 ? HRM_MODULES_LIST[currentIdx + 1] : null;

  const [open, setOpen] = React.useState(false);
  const [labelHov, setLabelHov] = React.useState(false);
  const rootRef = React.useRef(null);

  React.useEffect(() => {
    if (!open) return;
    const h = (e) => { if (rootRef.current && !rootRef.current.contains(e.target)) setOpen(false); };
    document.addEventListener('pointerdown', h, true);
    return () => document.removeEventListener('pointerdown', h, true);
  }, [open]);

  const navigate = (file) => {
    const base = location.pathname.substring(0, location.pathname.lastIndexOf('/') + 1);
    window.location.href = base + encodeURIComponent(file);
  };

  return (
    <div ref={rootRef} style={{
      position: 'fixed', bottom: 24, left: '50%',
      transform: 'translateX(-50%)',
      zIndex: 99999,
      fontFamily: 'var(--font-sans,system-ui,sans-serif)',
      display: 'flex', flexDirection: 'column', alignItems: 'center',
    }}>

      {/* ── Module picker ── */}
      {open && (
        <div style={{
          marginBottom: 8,
          background: 'var(--popover,#fff)',
          border: '1px solid var(--border,#e5e7eb)',
          borderRadius: 14,
          boxShadow: '0 12px 40px rgba(0,0,0,.16), 0 2px 8px rgba(0,0,0,.06)',
          padding: 6,
          display: 'grid', gridTemplateColumns: '1fr 1fr',
          gap: 2, minWidth: 300,
        }}>
          {HRM_MODULES_LIST.map((m, i) => {
            const isCur = i === currentIdx;
            return (
              <button key={m.file}
                onClick={() => { setOpen(false); if (!isCur) navigate(m.file); }}
                onMouseEnter={(e) => { if (!isCur) e.currentTarget.style.background = 'var(--accent,#f4f4f5)'; }}
                onMouseLeave={(e) => { if (!isCur) e.currentTarget.style.background = 'transparent'; }}
                style={{
                  display: 'flex', alignItems: 'center', gap: 8,
                  padding: '8px 10px', borderRadius: 8,
                  border: 'none',
                  cursor: isCur ? 'default' : 'pointer',
                  background: isCur ? 'var(--primary,#18181b)' : 'transparent',
                  color: isCur ? 'var(--primary-foreground,#fff)' : 'var(--foreground,#18181b)',
                  fontFamily: 'inherit', fontSize: 13,
                  fontWeight: isCur ? 600 : 400,
                  textAlign: 'left', width: '100%',
                  transition: 'background .12s',
                }}>
                <span style={{
                  width: 26, height: 18, flexShrink: 0,
                  background: isCur ? 'rgba(255,255,255,.2)' : 'var(--muted,#f4f4f5)',
                  color: isCur ? '#fff' : 'var(--muted-foreground,#71717a)',
                  borderRadius: 4, fontSize: 10, fontWeight: 700,
                  display: 'flex', alignItems: 'center', justifyContent: 'center',
                }}>{m.num}</span>
                <span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{m.label}</span>
              </button>
            );
          })}
        </div>
      )}

      {/* ── Pill ── */}
      <div style={{
        display: 'flex', alignItems: 'center', gap: 2,
        background: 'var(--background,#fff)',
        border: '1px solid var(--border,#e5e7eb)',
        borderRadius: 999,
        boxShadow: '0 4px 20px rgba(0,0,0,.12), 0 1px 4px rgba(0,0,0,.07)',
        padding: '4px 4px',
      }}>
        {/* Prev */}
        <HRMNavArrowBtn disabled={!prev} title={prev ? `← ${prev.label}` : ''} onClick={() => prev && navigate(prev.file)}>
          <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
            <path d="M9 3L5 7l4 4"/>
          </svg>
        </HRMNavArrowBtn>

        {/* Label / picker trigger */}
        <button
          onClick={() => setOpen(o => !o)}
          onMouseEnter={() => setLabelHov(true)}
          onMouseLeave={() => setLabelHov(false)}
          style={{
            display: 'flex', alignItems: 'center', gap: 8,
            padding: '5px 10px 5px 8px',
            borderRadius: 999, border: 'none',
            background: open || labelHov ? 'var(--accent,#f4f4f5)' : 'transparent',
            cursor: 'pointer',
            fontFamily: 'inherit', fontSize: 13, fontWeight: 500,
            color: 'var(--foreground,#18181b)',
            transition: 'background .12s',
          }}>
          {current ? (
            <>
              <span style={{
                background: 'var(--primary,#18181b)',
                color: 'var(--primary-foreground,#fff)',
                borderRadius: 6, fontSize: 11, fontWeight: 700,
                padding: '2px 6px', flexShrink: 0,
              }}>{current.num}</span>
              <span>{current.label}</span>
            </>
          ) : (
            <span style={{ color: 'var(--muted-foreground,#71717a)', padding: '0 4px' }}>ELS HRM</span>
          )}
          <svg width="10" height="10" viewBox="0 0 10 10" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round"
            style={{ opacity: 0.45, flexShrink: 0, transform: open ? 'rotate(180deg)' : 'rotate(0)', transition: 'transform .15s' }}>
            <path d="M2 4l3 3 3-3"/>
          </svg>
        </button>

        {/* Next */}
        <HRMNavArrowBtn disabled={!next} title={next ? `${next.label} →` : ''} onClick={() => next && navigate(next.file)}>
          <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
            <path d="M5 3l4 4-4 4"/>
          </svg>
        </HRMNavArrowBtn>
      </div>
    </div>
  );
}

// Self-mount after all Babel scripts have run
(() => {
  const div = document.createElement('div');
  div.id = '__hrm-module-nav';
  document.body.appendChild(div);
  setTimeout(() => {
    ReactDOM.createRoot(div).render(React.createElement(HRMModuleNavigator));
  }, 0);
})();
