// ELS HRM — Module 06: Nghỉ Phép — All Screens — Tailwind utility classes
// Phân màn theo PERMISSION (không theo role): mỗi màn gắn dải permission gate + thanh
// điều hướng phụ lọc theo quyền; nút thao tác mở modal/dialog thật.

// shadcn table styling reproduced via arbitrary child variants (1 className, structure untouched)
const TABLE_CLS = "w-full border-collapse text-sm "
  + "[&_thead_th]:border-b [&_thead_th]:border-border [&_thead_th]:bg-muted [&_thead_th]:px-3.5 [&_thead_th]:py-2.5 [&_thead_th]:text-left [&_thead_th]:text-xs [&_thead_th]:font-semibold [&_thead_th]:uppercase [&_thead_th]:tracking-[0.04em] [&_thead_th]:text-muted-foreground [&_thead_th]:whitespace-nowrap "
  + "[&_tbody_td]:border-b [&_tbody_td]:border-border [&_tbody_td]:px-3.5 [&_tbody_td]:py-3 [&_tbody_td]:align-middle [&_tbody_td]:text-foreground "
  + "[&_tbody_tr:last-child_td]:border-0 [&_tbody_tr:hover]:bg-muted";

const CARD = "rounded-xl border border-border bg-card shadow-xs";
const INP  = "h-9 w-full rounded-md border border-input bg-transparent px-3 text-base text-foreground shadow-xs placeholder:text-muted-foreground transition-colors focus:border-primary focus:outline-none focus:ring-[3px] focus:ring-ring";
const TXT  = "h-20 w-full resize-none rounded-md border border-input bg-transparent px-3 pt-2 text-base text-foreground shadow-xs placeholder:text-muted-foreground transition-colors focus:border-primary focus:outline-none focus:ring-[3px] focus:ring-ring";
const LBL  = "mb-[5px] block text-xs font-medium";

// ─── Permission catalog (mã quyền — KHÔNG dùng tên role) ─────────────────────
const P = {
  SCREEN:'screen:leave', OWN:'data:leave:own', DEPT:'data:leave:dept', ALL:'data:leave:all',
  CREATE:'action:leave:create', DELETE:'action:leave:delete',
  APPROVE:'action:leave:approve', REJECT:'action:leave:reject', CONFIGURE:'action:leave:configure',
};
const PERMS_OWN  = [P.SCREEN, P.OWN, P.CREATE, P.DELETE];
const PERMS_DEPT = [P.SCREEN, P.OWN, P.CREATE, P.DELETE, P.DEPT, P.APPROVE, P.REJECT];
const PERMS_ALL  = [P.SCREEN, P.OWN, P.CREATE, P.DELETE, P.DEPT, P.ALL, P.APPROVE, P.REJECT, P.CONFIGURE];

const can = (perms, need) => need.every((n) => perms.includes(n) || (n === P.DEPT && perms.includes(P.ALL)));
const dcNav = (slot) => { try { window.postMessage({ type: '__dc_navigate', slotId: slot }, '*'); } catch (e) {} };

const LEAVE_NAV = [
  { id:'dashboard',     label:'Tổng quan',        slot:'manage/dashboard',     need:[P.DEPT]      },
  { id:'team-calendar', label:'Lịch nghỉ team',   slot:'manage/team-calendar', need:[P.DEPT]      },
  { id:'ess-dashboard', label:'Tổng quan của tôi', slot:'ess/ess-dashboard',   need:[P.OWN]       },
  { id:'balance',     label:'Số dư của tôi',    slot:'ess/balance',        need:[P.OWN]       },
  { id:'submit',      label:'Xin nghỉ',         slot:'ess/submit',         need:[P.CREATE]    },
  { id:'approve',     label:'Duyệt đơn',        slot:'manage/approve',     need:[P.APPROVE]   },
  { id:'delegation',  label:'Ủy quyền',         slot:'manage/delegation',  need:[P.APPROVE]   },
  { id:'config',      label:'Cấu hình',         slot:'config/config',      need:[P.CONFIGURE] },
  { id:'entitlement', label:'Điều chỉnh số dư', slot:'config/entitlement', need:[P.CONFIGURE] },
];

// Tab bar — nằm bên trong card của LeaveShell (giống AdminTabBar trong AdminShell)
const LeaveModuleNav = ({ active, perms }) => (
  <div className="flex shrink-0 flex-wrap items-center gap-0.5 border-b border-border bg-card px-2">
    {LEAVE_NAV.filter((n) => can(perms, n.need)).map((n) => {
      const on = n.id === active;
      return (
        <button key={n.id} onClick={() => !on && dcNav(n.slot)}
          className={"-mb-px border-b-2 px-3 py-2.5 text-sm font-medium transition-colors "
            + (on ? "border-primary text-primary" : "cursor-pointer border-transparent text-muted-foreground hover:text-foreground")}>
          {n.label}
        </button>
      );
    })}
  </div>
);

// ─── Nav groups (phải khai báo trước LeaveShell vì const không hoist) ────────
const LEAVE_NAV_GROUPS = [
  { title:'Tự phục vụ', items:[
    { id:'ess-dashboard', label:'Tổng quan của tôi', icon:'layout-dashboard', slot:'ess/ess-dashboard', need:[P.OWN]       },
    { id:'balance', label:'Số dư của tôi', icon:'umbrella',         slot:'ess/balance',        need:[P.OWN]       },
    { id:'submit',  label:'Xin nghỉ',     icon:'plus',             slot:'ess/submit',         need:[P.CREATE]    },
  ]},
  { title:'Quản lý đơn', items:[
    { id:'dashboard',  label:'Tổng quan',        icon:'layout-dashboard', slot:'manage/dashboard',   need:[P.DEPT]      },
    { id:'team-calendar', label:'Lịch nghỉ team', icon:'calendar',        slot:'manage/team-calendar', need:[P.DEPT]      },
    { id:'approve',    label:'Duyệt đơn',        icon:'check-circle',     slot:'manage/approve',     need:[P.APPROVE]   },
    { id:'delegation', label:'Ủy quyền',         icon:'users',            slot:'manage/delegation',  need:[P.APPROVE]   },
  ]},
  { title:'Cấu hình', items:[
    { id:'config',      label:'Cấu hình',         icon:'settings',         slot:'config/config',      need:[P.CONFIGURE] },
    { id:'entitlement', label:'Điều chỉnh số dư', icon:'edit',             slot:'config/entitlement', need:[P.CONFIGURE] },
  ]},
];
const visibleGroups = (perms) => LEAVE_NAV_GROUPS
  .map(g => ({ ...g, items: g.items.filter(n => can(perms, n.need)) }))
  .filter(g => g.items.length);

// ─── Leave Shell — HRMShell + horizontal grouped nav strip ──────────────────
// Không dùng nav rail dọc (w-52 = 208px lãng phí). Thay bằng pill strip ngang
// — nhóm theo scope, permission-aware, wrap tự nhiên khi màn nhỏ.
const LeaveShell = ({ active, perms, title, crumbs, actions, children, user, dark, meta }) => {
  const groups = visibleGroups(perms || []);
  return (
    <HRMShell active="leave" title={title} crumbs={crumbs} actions={actions} user={user} dark={dark} meta={meta}>
      {/* Module nav strip */}
      <div className="mb-4 flex flex-wrap items-center gap-1 rounded-xl border border-border bg-card px-2.5 py-2">
        {groups.map((g, gi) => (
          <React.Fragment key={g.title}>
            {gi > 0 && <div className="mx-2 h-5 w-px shrink-0 bg-border" />}
            <div className="flex items-center gap-0.5">
              <span className="mr-0.5 px-1 text-2xs font-bold uppercase tracking-[0.08em] text-muted-foreground" style={{opacity:0.5}}>{g.title}</span>
              {g.items.map(n => {
                const on = n.id === active;
                return (
                  <button key={n.id} onClick={() => !on && dcNav(n.slot)}
                    className={"flex items-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium transition-colors "
                      + (on ? "bg-primary text-primary-foreground" : "cursor-pointer text-muted-foreground hover:bg-muted hover:text-foreground")}>
                    <Icon name={n.icon} size={13} className="shrink-0" />{n.label}
                  </button>
                );
              })}
            </div>
          </React.Fragment>
        ))}
      </div>
      {children}
    </HRMShell>
  );
};

// ─── Modal + Toast (tương tác thật) ──────────────────────────────────────────
const Modal = ({ open, onClose, title, children, footer, width = "max-w-md" }) =>
  !open ? null : (
    <div className="absolute inset-0 z-50 flex items-center justify-center bg-black/40 p-6" onClick={onClose}>
      <div className={CARD + " w-full " + width + " p-5"} onClick={(e) => e.stopPropagation()}>
        <div className="mb-4 flex items-center justify-between border-b border-border pb-3">
          <div className="text-base font-bold">{title}</div>
          <Btn variant="ghost" size="sm" iconOnly icon="x" onClick={onClose} />
        </div>
        {children}
        {footer && <div className="mt-5 flex justify-end gap-2">{footer}</div>}
      </div>
    </div>
  );

const Toast = ({ msg, onClose }) =>
  !msg ? null : (
    <div className="absolute left-1/2 top-3 z-[60] flex -translate-x-1/2 items-center gap-2 rounded-md bg-foreground px-3.5 py-2 text-sm font-medium text-background shadow-lg">
      <Icon name="check-circle" size={14} /> {msg}
      <button onClick={onClose} className="ml-1 cursor-pointer opacity-70 hover:opacity-100"><Icon name="x" size={12} /></button>
    </div>
  );

// 9 loại phép — màu oklch thuần, không dùng CSS var để tránh phụ thuộc theme.
// Mỗi bg (nền selected) có L ≤ 0.94 → luôn phân biệt với card trắng (L=1).
// Hue trải đều 40–70° nhau; UNP/LWP dùng chroma thấp nhưng ấm/lạnh khác nhau.
const LEAVE_TYPES = [
  { code:'AL',   name:'Phép năm',          color:'oklch(0.60 0.19 41)',   bg:'oklch(0.93 0.07 47)',   paid:true,  days:18, attach:false, prorata:true  },
  { code:'SL',   name:'Phép bệnh',         color:'oklch(0.53 0.18 148)',  bg:'oklch(0.92 0.07 148)',  paid:true,  days:14, attach:true,  prorata:true  },
  { code:'MAT',  name:'Nghỉ thai sản',     color:'oklch(0.52 0.20 350)',  bg:'oklch(0.94 0.05 350)',  paid:true,  days:90, attach:true,  prorata:false },
  { code:'PAT',  name:'Thai sản (nam)',    color:'oklch(0.54 0.18 240)',  bg:'oklch(0.93 0.05 240)',  paid:true,  days:10, attach:true,  prorata:false },
  { code:'EXL',  name:'Nghỉ thi/học',     color:'oklch(0.49 0.17 80)',   bg:'oklch(0.94 0.07 85)',   paid:true,  days:5,  attach:false, prorata:false },
  { code:'COMP', name:'Nghỉ bù',          color:'oklch(0.50 0.16 195)',  bg:'oklch(0.92 0.05 195)',  paid:true,  days:0,  attach:false, prorata:false },
  { code:'BUR',  name:'Nghỉ tang',        color:'oklch(0.48 0.14 290)',  bg:'oklch(0.93 0.04 290)',  paid:true,  days:5,  attach:false, prorata:false },
  { code:'UNP',  name:'Nghỉ không lương', color:'oklch(0.44 0.018 40)',  bg:'oklch(0.92 0.012 40)',  paid:false, days:0,  attach:false, prorata:false },
  { code:'LWP',  name:'Nghỉ dài (KL)',    color:'oklch(0.41 0.014 250)', bg:'oklch(0.91 0.008 250)', paid:false, days:0,  attach:false, prorata:false },
];

const LEAVE_REQUESTS = [
  { id:'LR-001', emp:'Phạm Đức Long',  type:'AL',   from:'20/05/2026', to:'23/05/2026', days:4, status:'PENDING',  dept:'Kinh doanh',  reason:'Nghỉ phép gia đình',      submitted:'14/05/2026' },
  { id:'LR-002', emp:'Võ Thị Thu',     type:'SL',   from:'16/05/2026', to:'17/05/2026', days:2, status:'PENDING',  dept:'Tài chính',   reason:'Khám bệnh định kỳ',        submitted:'15/05/2026' },
  { id:'LR-003', emp:'Đỗ Văn Hùng',   type:'AL',   from:'01/06/2026', to:'05/06/2026', days:5, status:'APPROVED', dept:'Engineering', reason:'Đi du lịch',               submitted:'10/05/2026' },
  { id:'LR-004', emp:'Bùi Thị Linh',  type:'COMP', from:'18/05/2026', to:'18/05/2026', days:1, status:'APPROVED', dept:'Nhân sự',     reason:'Bù giờ tăng ca 12/05',     submitted:'13/05/2026' },
  { id:'LR-005', emp:'Ngô Minh Khoa', type:'UNP',  from:'25/05/2026', to:'29/05/2026', days:5, status:'REJECTED', dept:'Engineering', reason:'Việc cá nhân',              submitted:'08/05/2026' },
  { id:'LR-006', emp:'Lê Thị Hương',  type:'AL',   from:'10/06/2026', to:'14/06/2026', days:5, status:'PENDING',  dept:'Marketing',   reason:'Du lịch hè cùng gia đình', submitted:'15/05/2026' },
];

const LV_ST = {
  PENDING:  { label:'Chờ duyệt', v:'warning', icon:'clock'        },
  APPROVED: { label:'Đã duyệt',  v:'success', icon:'check-circle' },
  REJECTED: { label:'Từ chối',   v:'danger',  icon:'x-circle'     },
  CANCELLED:{ label:'Đã hủy',    v:'neutral', icon:'x'            },
};

const LeaveTypePill = ({ code }) => {
  const lt = LEAVE_TYPES.find(t => t.code === code) || LEAVE_TYPES[0];
  return (
    <span className="whitespace-nowrap rounded-full px-[9px] py-0.5 text-xs font-semibold"
      style={{ background: lt.bg, color: lt.color }}>
      {lt.name}
    </span>
  );
};

// ─── 01: Dashboard quản lý đơn (data:leave:dept/all) ─────────────────────────
const LeaveDashboardScreen = ({ dark = false }) => {
  const [dlg, setDlg]     = React.useState(null);
  const [toast, setToast] = React.useState('');
  const [reason, setReason] = React.useState('');
  const act = dlg;
  return (
    <LeaveShell active="dashboard" perms={PERMS_ALL} dark={dark}
      title="Quản lý nghỉ phép"
      crumbs={['Nghỉ phép', 'Tổng quan']}
      meta="Tháng 5/2026"
      user={{ name:'Trần Minh', role:'data:leave:all' }}
      actions={<>
        <Btn variant="outline" size="sm" icon="download" onClick={()=>setToast('Đang xuất báo cáo… (demo)')}>Xuất báo cáo</Btn>
        <Btn variant="primary"  size="sm" icon="plus" onClick={()=>setDlg({ kind:'grant' })}>Cấp phép thủ công</Btn>
      </>}>
      <Toast msg={toast} onClose={()=>setToast('')} />

      {/* Stats */}
      <div className="mb-4 grid grid-cols-4 gap-3">
        {[
          { label:'Chờ phê duyệt',    val:'8',  delta:'3 khẩn cấp',       dir:'down', icon:'clock',        ib:'var(--color-warning-soft)', ic:'oklch(0.55 0.158 65)'             },
          { label:'Đang nghỉ hôm nay', val:'12', delta:'4.8% nhân viên',   dir:'up',   icon:'umbrella',     ib:'var(--color-info-soft)',    ic:'var(--color-info)'                },
          { label:'Đã phê duyệt T5',   val:'34', delta:'+8 so với T4',     dir:'up',   icon:'check-circle', ib:'var(--color-success-soft)', ic:'var(--color-success)'             },
          { label:'Từ chối T5',        val:'5',  delta:'-2 so với T4',     dir:'up',   icon:'x-circle',     ib:'var(--color-muted)',        ic:'var(--color-muted-foreground)'    },
        ].map((s,i)=><StatCard key={i} label={s.label} value={s.val} delta={s.delta} deltaDir={s.dir} icon={s.icon} iconBg={s.ib} iconColor={s.ic} />)}
      </div>

      <div className="grid grid-cols-[1fr_320px] gap-4">
        <div>
          <div className={CARD + " mb-3 flex items-center gap-2.5 px-3.5 py-2.5"}>
            <div className="relative flex w-60 items-center">
              <Icon name="search" size={13} className="pointer-events-none absolute left-2.5 size-3.5 text-muted-foreground" />
              <input className="h-8 w-full rounded-md border border-input bg-transparent pl-8 pr-3 text-xs text-foreground shadow-xs transition-colors placeholder:text-muted-foreground focus:border-primary focus:outline-none focus:ring-[3px] focus:ring-ring" placeholder="Tìm nhân viên..." />
            </div>
            <Select className="h-8 text-xs" style={{width:140}} defaultValue="Tất cả trạng thái" options={['Tất cả trạng thái','Chờ duyệt','Đã duyệt','Từ chối']} />
            <Select className="h-8 text-xs" style={{width:140}} defaultValue="Tất cả loại phép" options={['Tất cả loại phép', ...LEAVE_TYPES.map(t=>t.name)]} />
            <div className="flex-1" />
            <span className="text-xs text-muted-foreground">{LEAVE_REQUESTS.length} yêu cầu</span>
          </div>
          <div className="overflow-hidden rounded-lg border border-border bg-card">
            <table className={TABLE_CLS}>
              <thead><tr><th>Nhân viên</th><th>Loại phép</th><th>Từ ngày</th><th>Đến ngày</th><th>Số ngày</th><th>Trạng thái</th><th>Thao tác</th></tr></thead>
              <tbody>
                {LEAVE_REQUESTS.map(r => {
                  const st = LV_ST[r.status];
                  return (
                    <tr key={r.id}>
                      <td><div className="flex items-center gap-[9px]"><Avatar name={r.emp} size="sm" /><div><div className="text-sm font-medium">{r.emp}</div><div className="text-xs text-muted-foreground">{r.dept}</div></div></div></td>
                      <td><LeaveTypePill code={r.type} /></td>
                      <td className="text-sm">{r.from}</td>
                      <td className="text-sm">{r.to}</td>
                      <td className="text-center text-sm font-semibold">{r.days}</td>
                      <td><Badge variant={st.v} dot>{st.label}</Badge></td>
                      <td>
                        <div className="flex gap-1">
                          {r.status==='PENDING' && <>
                            <Btn variant="soft" size="xs" onClick={()=>{ setReason(''); setDlg({ kind:'approve', req:r }); }}>Duyệt</Btn>
                            <Btn variant="outline" size="xs" onClick={()=>{ setReason(''); setDlg({ kind:'reject', req:r }); }}>Từ chối</Btn>
                          </>}
                          {r.status!=='PENDING' && <Btn variant="ghost" size="sm" iconOnly icon="eye" onClick={()=>dcNav('manage/approve')} />}
                        </div>
                      </td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
        </div>

        <div className="flex flex-col gap-3">
          <div className={CARD + " p-4"}>
            <div className="mb-3 flex items-center justify-between">
              <div className="text-sm font-bold">Tháng 5 · 2026</div>
              <div className="flex gap-1"><Btn variant="ghost" size="xs" iconOnly icon="chevron-left" /><Btn variant="ghost" size="xs" iconOnly icon="chevron-right" /></div>
            </div>
            <div className="grid grid-cols-7 gap-0.5 text-center text-xs">
              {['T2','T3','T4','T5','T6','T7','CN'].map(d=>(<div key={d} className="py-1 font-semibold text-muted-foreground">{d}</div>))}
              {[null,null,null,null,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31].map((d,i)=>{
                const off=d===null, today=d===16, hasLeave=[20,21,22,23,25,26,27,28,29].includes(d), isHoliday=d===1;
                return (
                  <div key={i} className={"relative rounded-sm py-[5px] text-xs " + (today?'font-bold':'font-normal') + (d?' cursor-pointer':' cursor-default')} style={{
                    background:today?'var(--color-primary)':isHoliday?'var(--color-destructive-soft)':hasLeave?'var(--color-primary-soft)':'transparent',
                    color:today?'#fff':isHoliday?'var(--color-destructive)':off?'transparent':'var(--color-foreground)',
                  }}>{d||''}{hasLeave && !today && <div className="absolute bottom-0.5 left-1/2 size-1 -translate-x-1/2 rounded-full bg-primary" />}</div>
                );
              })}
            </div>
            <div className="mt-2.5 flex gap-2.5 text-xs">
              <div className="flex items-center gap-1"><span className="size-2.5 rounded-[2px] bg-primary" /> Hôm nay</div>
              <div className="flex items-center gap-1"><span className="size-2.5 rounded-[2px] bg-primary-soft" /> Nghỉ phép</div>
              <div className="flex items-center gap-1"><span className="size-2.5 rounded-[2px] bg-destructive-soft" /> Ngày lễ</div>
            </div>
          </div>
          <div className={CARD + " p-4"}>
            <div className="mb-3 text-sm font-bold">Đang nghỉ hôm nay (16/05)</div>
            {[{ name:'Phạm Đức Long', type:'AL', dept:'Kinh doanh' },{ name:'Võ Thị Thu', type:'SL', dept:'Tài chính' },{ name:'Ngô Minh Khoa', type:'COMP', dept:'Engineering' }].map((a,i)=>(
              <div key={i} className={"flex items-center gap-[9px] py-2 " + (i<2?'border-b border-border':'')}>
                <Avatar name={a.name} size="sm" /><div className="flex-1"><div className="text-sm font-medium">{a.name}</div><div className="text-xs text-muted-foreground">{a.dept}</div></div><LeaveTypePill code={a.type} />
              </div>
            ))}
          </div>
        </div>
      </div>

      {/* Dialogs */}
      <Modal open={act?.kind==='approve'} onClose={()=>setDlg(null)} title="Phê duyệt đơn nghỉ"
        footer={<><Btn variant="outline" size="sm" onClick={()=>setDlg(null)}>Hủy</Btn><Btn variant="primary" size="sm" icon="check" onClick={()=>{ setDlg(null); setToast(`Đã duyệt đơn ${act?.req?.id} (demo)`); }}>Phê duyệt</Btn></>}>
        <div className="text-sm text-muted-foreground">Duyệt đơn <b className="text-foreground">{act?.req?.emp}</b> · <LeaveTypePill code={act?.req?.type||'AL'} /> · {act?.req?.from}–{act?.req?.to} ({act?.req?.days} ngày).</div>
        <div className="mt-3"><label className={LBL}>Ghi chú <span className="font-normal text-muted-foreground">(tùy chọn)</span></label><textarea className={TXT} placeholder="Ghi chú cho nhân viên…" /></div>
      </Modal>
      <Modal open={act?.kind==='reject'} onClose={()=>setDlg(null)} title="Từ chối đơn nghỉ"
        footer={<><Btn variant="outline" size="sm" onClick={()=>setDlg(null)}>Hủy</Btn><Btn variant="destructive" size="sm" icon="x" disabled={!reason.trim()} onClick={()=>{ setDlg(null); setToast(`Đã từ chối đơn ${act?.req?.id} (demo)`); }}>Từ chối</Btn></>}>
        <div className="mb-3 text-sm text-muted-foreground">Từ chối đơn <b className="text-foreground">{act?.req?.emp}</b> · {act?.req?.from}–{act?.req?.to}.</div>
        <label className={LBL}>Lý do từ chối <span className="text-destructive">*</span></label>
        <textarea className={TXT} value={reason} onChange={(e)=>setReason(e.target.value)} placeholder="Bắt buộc — nhân viên sẽ thấy lý do này…" />
        {!reason.trim() && <div className="mt-1.5 flex items-center gap-1 text-xs text-destructive"><Icon name="alert-circle" size={12} /> Bắt buộc nhập lý do khi từ chối.</div>}
      </Modal>
      <Modal open={act?.kind==='grant'} onClose={()=>setDlg(null)} title="Cấp phép thủ công"
        footer={<><Btn variant="outline" size="sm" onClick={()=>setDlg(null)}>Hủy</Btn><Btn variant="primary" size="sm" onClick={()=>{ setDlg(null); setToast('Đã ghi điều chỉnh số dư (demo)'); }}>Lưu</Btn></>}>
        <div className="grid grid-cols-2 gap-3">
          <div><label className={LBL}>Nhân viên</label><Select options={LEAVE_REQUESTS.map(r=>r.emp)} defaultValue="Phạm Đức Long" /></div>
          <div><label className={LBL}>Loại phép</label><Select options={LEAVE_TYPES.filter(t=>t.paid).map(t=>t.name)} defaultValue="Phép năm" /></div>
          <div><label className={LBL}>Giá trị điều chỉnh (adjusted_days)</label><input type="number" step="0.5" className={INP} defaultValue="2" /></div>
          <div><label className={LBL}>Lý do <span className="text-destructive">*</span></label><input className={INP} placeholder="VD: thưởng phép" /></div>
        </div>
        <div className="mt-2 flex items-center gap-1.5 text-xs text-muted-foreground"><Icon name="info" size={12} /> Ghi đè giá trị tuyệt đối cột adjusted_days (yêu cầu action:leave:configure).</div>
      </Modal>
    </LeaveShell>
  );
};

// ─── 02: Submit Leave Request (data:leave:own + action:leave:create) ─────────
const LeaveSubmitScreen = () => {
  const [type, setType]         = React.useState('AL');
  const [confirm, setConfirm]   = React.useState(false);
  const [toast, setToast]       = React.useState('');
  const [halfDay, setHalfDay]   = React.useState(false);
  // Ngày để ở state để chú thích "đơn vắt kỳ" bật/tắt THẬT khi đổi ngày. Mặc định
  // đặt vào ví dụ vắt kỳ 27/02–04/03/2026 = 1 ngày làm việc của tháng 2 + 3 của tháng 3.
  const [from, setFrom]         = React.useState('2026-02-27');
  const [to,   setTo]           = React.useState('2026-03-04');
  const sel   = LEAVE_TYPES.find(t => t.code === type) || LEAVE_TYPES[0];
  const cross = !halfDay && from.slice(0,7) !== to.slice(0,7);
  const days  = halfDay ? '0.5' : (cross ? '4' : '3');
  const dmy   = (s) => s.split('-').reverse().join('/');
  return (
    <LeaveShell active="submit" perms={PERMS_OWN}
      user={{ name:'Phạm Đức Long', role:'data:leave:own' }}
      title="Xin nghỉ phép"
      crumbs={['Nghỉ phép', 'Xin nghỉ']}
      actions={<Btn variant="primary" size="sm" icon="send" onClick={()=>setConfirm(true)}>Gửi yêu cầu</Btn>}>
      <Toast msg={toast} onClose={()=>setToast('')} />

      <div className="grid grid-cols-[1fr_300px] gap-[18px]">
        <div className="flex flex-col gap-3.5">
          <div className={CARD + " p-[22px]"}>
            <div className="mb-3.5 text-base font-bold">Loại nghỉ phép *</div>
            <div className="grid grid-cols-2 gap-2.5">
              {LEAVE_TYPES.map(lt=>{
                const sel = type === lt.code;
                return (
                  <label key={lt.code} onClick={()=>setType(lt.code)}
                    className="flex cursor-pointer items-center gap-3 rounded-md p-3.5 transition-colors"
                    style={{ border:`1px solid ${sel ? lt.color+'55' : 'var(--color-border)'}`, background: sel ? lt.bg : 'var(--color-card)' }}>
                    <div className="grid size-8 shrink-0 place-items-center rounded-md" style={{ background: lt.bg }}>
                      <Icon name="umbrella" size={14} style={{ color: lt.color }} />
                    </div>
                    <div className="flex-1 min-w-0">
                      <div className="text-sm font-semibold" style={{ color: sel ? lt.color : 'var(--color-foreground)' }}>{lt.name}</div>
                      <div className="text-xs text-muted-foreground">{lt.paid?'Có lương':'Không lương'} · {lt.days>0?`${lt.days} ngày/kỳ`:'Không giới hạn'}</div>
                    </div>
                    <div className="ml-auto grid size-4 shrink-0 place-items-center rounded-full"
                      style={{ background: sel ? lt.color : 'transparent', border: `1.5px solid ${sel ? lt.color : 'var(--color-border-strong)'}`, transition:'all .15s' }}>
                      {sel && <Icon name="check" size={9} style={{ color:'#fff' }} />}
                    </div>
                  </label>
                );
              })}
            </div>
            {!sel.paid && (
              <div className="mt-3.5 flex gap-2 rounded-md bg-muted px-3.5 py-3 text-xs text-muted-foreground">
                <Icon name="info" size={14} className="mt-0.5 shrink-0" /><span>Phép không lương không trừ vào số dư và không cần số dư khả dụng — đơn vẫn cần quản lý phê duyệt.</span>
              </div>
            )}
          </div>

          <div className={CARD + " p-[22px]"}>
            <div className="mb-3.5 text-base font-bold">Thời gian nghỉ</div>
            <div className="mb-4 grid grid-cols-2 gap-3.5">
              <div><label className={LBL}>Từ ngày *</label><input className={INP} type="date" value={from} onChange={(e)=>setFrom(e.target.value)} /></div>
              <div><label className={LBL}>Đến ngày *</label><input className={INP} type="date" value={to} onChange={(e)=>setTo(e.target.value)} /></div>
            </div>
            <label className="mb-4 flex cursor-pointer items-center gap-2 text-sm" onClick={()=>setHalfDay(v=>!v)}>
              <div className={"grid size-4 place-items-center rounded-sm border-[1.5px] " + (halfDay ? "border-primary bg-primary" : "border-border-strong")}>{halfDay && <Icon name="check" size={10} style={{ color:'#fff' }} />}</div>
              Nghỉ nửa ngày (chỉ áp dụng cho 1 ngày)
            </label>
            {halfDay && (
              <div className="mb-4 grid grid-cols-2 gap-3.5">
                <div><label className={LBL}>Giờ bắt đầu</label><input className={INP} type="time" defaultValue="08:00" /></div>
                <div><label className={LBL}>Giờ kết thúc</label><input className={INP} type="time" defaultValue="12:00" /></div>
              </div>
            )}
            {/* Số ngày nghỉ thực — mô phỏng realtime */}
            <div className="mb-4 rounded-md border border-border bg-muted px-3.5 py-3">
              <div className="flex items-end justify-between gap-2">
                <div>
                  <div className="text-xs font-medium text-muted-foreground">Số ngày nghỉ thực</div>
                  <div className="mt-1 flex items-baseline gap-2">
                    <span className="text-2xl font-extrabold text-primary">{days}</span>
                    <span className="text-xs text-muted-foreground">{halfDay ? 'ngày làm việc (nửa ngày)' : 'ngày làm việc · đã trừ cuối tuần và ngày lễ'}</span>
                  </div>
                </div>
                <span className="text-2xs text-muted-foreground" style={{opacity:0.7}}>tính tự động khi đổi ngày</span>
              </div>
              {sel.paid && !cross && (
                <div className="mt-2.5 flex items-center gap-1.5 rounded-md bg-success-soft px-2.5 py-1.5 text-xs font-medium text-success">
                  <Icon name="check-circle" size={12} className="shrink-0" />Số dư còn 5 ngày — đủ cho yêu cầu này
                </div>
              )}
              {/* Đơn vắt kỳ — khoảng ngày nằm vắt qua ranh giới hai kỳ phép. */}
              {sel.paid && cross && (
                <div className="mt-2.5 flex items-start gap-1.5 rounded-md bg-info-soft px-2.5 py-2 text-xs text-info">
                  <Icon name="info" size={12} className="mt-0.5 shrink-0" />
                  <span><span className="font-semibold">Đơn này trừ vào 2 kỳ: 1 ngày của 02/2026, 3 ngày của 03/2026.</span> Số dư kiểm ở <b>từng kỳ</b>, không cộng gộp — thiếu ở một kỳ là cả đơn bị từ chối, dù tổng hai kỳ vẫn đủ.</span>
                </div>
              )}
            </div>
            <div><label className={LBL}>Lý do nghỉ phép *</label><textarea className={TXT} defaultValue="Nghỉ phép gia đình — đi thăm người thân ở quê" /></div>
            <div className="mt-3.5"><label className={LBL}>Bàn giao công việc <span className="font-normal text-muted-foreground">(tùy chọn)</span></label><textarea className={TXT} placeholder="VD: Anh A xử lý đơn hàng tồn, chị B trực hotline trong thời gian tôi nghỉ…" /></div>
            {sel.attach && (
              <div className="mt-3.5 flex gap-2 rounded-md bg-warning-soft px-3.5 py-3 text-xs">
                <Icon name="alert-circle" size={14} style={{ color:'oklch(0.55 0.158 65)' }} className="mt-0.5 shrink-0" /><span style={{ color:'oklch(0.45 0.1 65)' }}>Loại phép này nên có giấy tờ đính kèm. Thiếu file chỉ là cảnh báo — đơn vẫn gửi được.</span>
              </div>
            )}
          </div>

          <div className={CARD + " p-[22px]"}>
            <div className="mb-2.5 text-base font-bold">Đính kèm <span className="text-xs font-normal text-muted-foreground">(tùy chọn)</span></div>
            <div className="cursor-pointer rounded-md border-2 border-dashed border-border-strong p-6 text-center"><Icon name="upload" size={20} style={{ color:'var(--color-muted-foreground)' }} className="mb-2" /><div className="mb-1 text-sm font-medium">Kéo thả file hoặc click để chọn</div><div className="text-xs text-muted-foreground">PDF, JPG, PNG · Tối đa 10MB</div></div>
          </div>
        </div>

        <div className="flex flex-col gap-3">
          <div className={CARD + " p-[18px]"}>
            <div className="mb-3.5 text-sm font-bold">Số dư kỳ hiện tại</div>
            {LEAVE_TYPES.slice(0,3).map((lt,i)=>{
              const used=[5,2,0][i], total=lt.days||14, rem=total-used, sel2=lt.code===type;
              return (
                <div key={lt.code} className="mb-3 rounded-md px-3 py-2.5" style={{ background:sel2?lt.bg:'transparent', border:`1px solid ${sel2?lt.color+'44':'var(--color-border)'}` }}>
                  <div className="mb-[5px] flex justify-between"><span className="text-sm" style={{ fontWeight:sel2?700:500, color:sel2?lt.color:'var(--color-foreground)' }}>{lt.name}</span><span className="text-sm font-bold" style={{ color:sel2?lt.color:'var(--color-foreground)' }}>{rem}/{total}</span></div>
                  <div className="h-[5px] overflow-hidden rounded-full bg-muted"><div className="h-full rounded-full" style={{ width:`${(used/total)*100}%`, background:lt.color }} /></div>
                  <div className="mt-1 text-xs text-muted-foreground">Đã dùng {used} · Còn lại {rem} ngày</div>
                </div>
              );
            })}
            {!sel.paid && <div className="rounded-md bg-muted px-3 py-2.5 text-xs text-muted-foreground">{sel.name} không theo dõi số dư (không lương).</div>}
          </div>

          <div className={CARD + " p-[18px]"} style={{ background:sel.bg, border:`1px solid ${sel.color}33` }}>
            <div className="mb-3 text-xs font-bold" style={{ color:sel.color }}>Xem trước yêu cầu</div>
            {[['Loại',sel.name],['Từ ngày',dmy(from)],['Đến ngày',dmy(to)],['Số ngày',`${days} ngày làm việc`],['Người duyệt','Quản lý trực tiếp (supervisor_id)'],['Trạng thái','Sẽ gửi chờ duyệt']].map(([l,v],i)=>(
              <div key={i} className="flex justify-between py-[5px] text-xs" style={{ borderBottom:i<5?`1px solid ${sel.color}22`:'none' }}><span style={{ color:sel.color, opacity:0.75 }}>{l}</span><span className="font-medium" style={{ color:sel.color }}>{v}</span></div>
            ))}
          </div>

          <div className={CARD + " p-3.5"}>
            <div className="mb-2 text-xs font-bold uppercase tracking-[0.07em] text-muted-foreground">Quy trình phê duyệt</div>
            {[{ n:'1', label:'Gửi yêu cầu' },{ n:'2', label:'Quản lý trực tiếp duyệt (1 cấp)' },{ n:'3', label:'Hoàn tất / Từ chối' }].map((s,i)=>(
              <div key={i} className={"flex gap-[9px] py-[7px] text-xs " + (i<2?'border-b border-dashed border-border':'')}><div className="grid size-5 shrink-0 place-items-center rounded-full bg-primary-soft text-xs font-bold text-primary">{s.n}</div>{s.label}</div>
            ))}
          </div>
        </div>
      </div>

      <Modal open={confirm} onClose={()=>setConfirm(false)} title="Gửi yêu cầu nghỉ phép"
        footer={<><Btn variant="outline" size="sm" onClick={()=>setConfirm(false)}>Hủy</Btn><Btn variant="primary" size="sm" icon="send" onClick={()=>{ setConfirm(false); setToast('Đã gửi yêu cầu — chờ quản lý duyệt (demo)'); }}>Gửi</Btn></>}>
        <div className="text-sm leading-[1.6] text-muted-foreground">Gửi đơn <b className="text-foreground">{sel.name}</b> · {dmy(from)}–{dmy(to)} ({days} ngày) tới quản lý trực tiếp để phê duyệt?</div>
      </Modal>
    </LeaveShell>
  );
};

// ─── 03: Approve/Reject — Queue + Detail (action:leave:approve / reject) ──────
// LeaveShell (nav strip ngang) + master-detail 2 cột: queue (340px) | detail (fills).
const LeaveApproveScreen = ({ demo }) => {
  const pendingReqs = LEAVE_REQUESTS.filter(r => r.status === 'PENDING');
  const [selectedId, setSelectedId] = React.useState(pendingReqs[0]?.id || LEAVE_REQUESTS[0].id);
  const [search,     setSearch]     = React.useState('');
  const [dlg,        setDlg]        = React.useState(demo || null);
  const [reason,     setReason]     = React.useState('');
  const [toast,      setToast]      = React.useState('');

  const req = LEAVE_REQUESTS.find(r => r.id === selectedId) || pendingReqs[0] || LEAVE_REQUESTS[0];
  const lt  = LEAVE_TYPES.find(t => t.code === req.type) || LEAVE_TYPES[0];

  const filtered = pendingReqs.filter(r =>
    !search || r.emp.toLowerCase().includes(search.toLowerCase()) || r.dept.toLowerCase().includes(search.toLowerCase())
  );

  const balances = [{ code:'AL', used:8, total:18 }, { code:'SL', used:0, total:14 }];

  return (
    <LeaveShell active="approve" perms={PERMS_DEPT}
      user={{ name:'Đỗ Thị Mai', role:'action:leave:approve' }}
      title="Duyệt đơn nghỉ phép"
      crumbs={['Nghỉ phép', 'Duyệt đơn', req.id]}
      actions={<>
        <Btn variant="outline" size="sm" icon="x"     onClick={()=>{ setReason(''); setDlg('reject'); }}>Từ chối</Btn>
        <Btn variant="primary" size="sm" icon="check" onClick={()=>setDlg('approve')}>Phê duyệt</Btn>
      </>}>
      <Toast msg={toast} onClose={()=>setToast('')} />

      {/* ── Master-Detail 2-col ── */}
      <div className="grid gap-4" style={{ gridTemplateColumns:'340px 1fr', alignItems:'start' }}>

        {/* ── Queue panel ── */}
        <div className={CARD + " flex flex-col overflow-hidden"} style={{ maxHeight:720 }}>

          {/* Queue header */}
          <div className="shrink-0 border-b border-border px-4 pb-3 pt-4">
            <div className="mb-3 flex items-center justify-between">
              <span className="text-sm font-semibold">Chờ phê duyệt</span>
              <Badge variant="warning">{pendingReqs.length}</Badge>
            </div>
            <div className="relative">
              <Icon name="search" size={13} className="pointer-events-none absolute left-2.5 top-1/2 -translate-y-1/2 text-muted-foreground" />
              <input value={search} onChange={e => setSearch(e.target.value)}
                className="h-8 w-full rounded-md border border-input bg-transparent pl-8 pr-3 text-xs text-foreground placeholder:text-muted-foreground focus:border-primary focus:outline-none focus:ring-[3px] focus:ring-ring"
                placeholder="Tìm nhân viên…" />
            </div>
          </div>

          {/* Queue list */}
          <div className="flex-1 overflow-auto divide-y divide-border">
            {filtered.length === 0 && (
              <div className="flex flex-col items-center justify-center py-10 text-sm text-muted-foreground">
                <Icon name="search" size={18} className="mb-2 opacity-30" />Không tìm thấy
              </div>
            )}
            {filtered.map(r => {
              const rlt = LEAVE_TYPES.find(t => t.code === r.type);
              const on  = r.id === selectedId;
              return (
                <button key={r.id} onClick={() => setSelectedId(r.id)}
                  className={"relative w-full cursor-pointer px-4 py-4 text-left transition-all " + (!on ? 'hover:bg-muted' : '')}
                  style={{ background: on ? rlt?.bg : 'transparent', borderLeft:`3px solid ${on ? rlt?.color : 'transparent'}` }}>
                  <div className="mb-2 flex items-start gap-2.5">
                    <Avatar name={r.emp} size="sm" />
                    <div className="min-w-0 flex-1">
                      <div className="truncate text-sm font-semibold"
                        style={{ color: on ? rlt?.color : 'var(--color-foreground)' }}>{r.emp}</div>
                      <div className="text-xs text-muted-foreground">{r.dept}</div>
                    </div>
                    <span className="shrink-0 rounded-md px-1.5 py-0.5 text-xs font-bold tabular-nums"
                      style={{ background: rlt?.bg, color: rlt?.color }}>{r.days}N</span>
                  </div>
                  <div className="flex flex-wrap items-center gap-1.5 pl-[34px]">
                    <LeaveTypePill code={r.type} />
                    <span className="text-xs text-muted-foreground">{r.from} – {r.to}</span>
                  </div>
                  <div className="mt-1.5 flex items-center gap-1 pl-[34px] text-xs text-muted-foreground">
                    <Icon name="clock" size={10} /><span>Nộp {r.submitted}</span>
                  </div>
                </button>
              );
            })}
          </div>
        </div>

        {/* ── Detail panel ── */}
        <div className="flex flex-col gap-3.5">

          {/* 1. Employee hero */}
          <div className={CARD + " p-5"}>
            <div className="flex items-center gap-4">
              <Avatar name={req.emp} size="xl" />
              <div className="min-w-0 flex-1">
                <div className="text-xl font-bold">{req.emp}</div>
                <div className="mt-0.5 text-sm text-muted-foreground">Phòng {req.dept}</div>
                <div className="mt-2.5 flex flex-wrap items-center gap-2">
                  <LeaveTypePill code={req.type} />
                  <Badge variant="warning" dot>Chờ phê duyệt</Badge>
                  <span className="text-xs text-muted-foreground">Nộp {req.submitted}</span>
                </div>
              </div>
              {/* Day count badge */}
              <div className="shrink-0 rounded-2xl px-6 py-4 text-center"
                style={{ background: lt.bg, border:`1.5px solid ${lt.color}33` }}>
                <div className="text-[40px] font-extrabold leading-none" style={{ color: lt.color }}>{req.days}</div>
                <div className="mt-1 text-xs font-medium" style={{ color: lt.color, opacity: 0.7 }}>ngày làm việc</div>
              </div>
            </div>
          </div>

          {/* 2. Dates + Reason — side by side */}
          <div className="grid grid-cols-[1fr_1fr_1fr_auto] gap-3" style={{ gridTemplateColumns:'1fr 1fr 1fr 280px' }}>
            {[
              { icon:'calendar', label:'Từ ngày',  val:req.from },
              { icon:'calendar', label:'Đến ngày', val:req.to   },
              { icon:'clock',    label:'Số ngày',  val:`${req.days} ngày làm việc` },
            ].map((f,i) => (
              <div key={i} className={CARD + " px-4 py-3.5"}>
                <div className="mb-1 flex items-center gap-1.5 text-xs text-muted-foreground">
                  <Icon name={f.icon} size={11} />{f.label}
                </div>
                <div className="text-base font-bold">{f.val}</div>
              </div>
            ))}
            {/* Reason as 4th cell spanning */}
            <div className={CARD + " px-4 py-3.5"} style={{ gridRow:'1', gridColumn:'1 / -1', marginTop:'0' }}>
              {/* skip — reason goes in its own row below */}
            </div>
          </div>

          {/* 3. Reason */}
          <div className={CARD + " px-5 py-4"}>
            <div className="mb-1.5 text-xs font-semibold uppercase tracking-[0.06em] text-muted-foreground">Lý do nghỉ phép</div>
            <div className="text-sm leading-[1.65]">{req.reason}</div>
          </div>

          {/* 4. Balance — horizontal 2 cards */}
          <div className={CARD + " p-5"}>
            <div className="mb-3.5 flex items-center justify-between">
              <div className="text-sm font-semibold">Số dư nghỉ phép · {req.emp}</div>
              <span className="flex items-center gap-1.5 rounded-full bg-success-soft px-2.5 py-1 text-xs font-medium text-success">
                <Icon name="check-circle" size={12} />Còn đủ số dư
              </span>
            </div>
            <div className="grid grid-cols-2 gap-3">
              {balances.map((b, i) => {
                const blt    = LEAVE_TYPES.find(t => t.code === b.code);
                const rem    = b.total - b.used;
                const after  = rem - (b.code === req.type ? req.days : 0);
                const isThis = b.code === req.type;
                return (
                  <div key={i} className="rounded-xl p-4"
                    style={{ background:isThis?blt.bg:'var(--color-muted)', border:`1px solid ${isThis?blt.color+'33':'var(--color-border)'}` }}>
                    <div className="mb-2 flex items-center justify-between">
                      <span className="text-sm font-medium" style={{ color:isThis?blt.color:'var(--color-foreground)' }}>{blt.name}</span>
                      <span className="text-lg font-extrabold tabular-nums" style={{ color:isThis?blt.color:'var(--color-foreground)' }}>
                        {rem}<span className="text-xs font-normal text-muted-foreground">/{b.total}</span>
                      </span>
                    </div>
                    <div className="mb-2 h-1.5 overflow-hidden rounded-full bg-card">
                      <div className="h-full rounded-full" style={{ width:`${(b.used/b.total)*100}%`, background:blt.color }} />
                    </div>
                    <div className="flex items-center justify-between text-xs text-muted-foreground">
                      <span>Đã dùng {b.used} · Còn {rem}</span>
                      {isThis && <span className="font-semibold" style={{ color:blt.color }}>→ Còn {after} sau duyệt</span>}
                    </div>
                  </div>
                );
              })}
            </div>
          </div>

          {/* 5. Team impact + History */}
          <div className="grid gap-3.5" style={{ gridTemplateColumns:'1fr 320px' }}>
            <div className={CARD + " p-5"}>
              <div className="mb-3 text-sm font-semibold">Ảnh hưởng đến team</div>
              <div className="flex flex-col gap-2">
                <div className="flex items-center gap-2.5 rounded-lg bg-warning-soft px-3.5 py-3 text-sm"
                  style={{ border:'1px solid oklch(0.835 0.158 80 / 0.25)' }}>
                  <Icon name="alert-circle" size={14} style={{ color:'oklch(0.55 0.158 65)' }} className="shrink-0" />
                  <Avatar name="Lê Thị Kim Anh" size="sm" />
                  <span><span className="font-semibold">Lê Thị Kim Anh</span> cũng nghỉ 18–22/05</span>
                  <LeaveTypePill code="AL" />
                </div>
                <div className="flex items-center gap-2 rounded-lg bg-success-soft px-3.5 py-3 text-sm text-success">
                  <Icon name="check-circle" size={14} className="shrink-0" />
                  Team đủ nhân lực trong khoảng thời gian này
                </div>
              </div>
            </div>
            <div className={CARD + " p-5"}>
              <div className="mb-3.5 text-sm font-bold uppercase tracking-[0.06em] text-muted-foreground">Lịch sử nghỉ phép</div>
              {[{ type:'AL', from:'01/02', to:'05/02', days:5, status:'APPROVED' },{ type:'SL', from:'15/03', to:'16/03', days:2, status:'REJECTED' }].map((h,i) => {
                const st = LV_ST[h.status];
                return (
                  <div key={i} className={"flex items-center gap-2.5 py-3 " + (i<1?'border-b border-border':'')}>
                    <LeaveTypePill code={h.type} />
                    <span className="flex-1 text-sm text-muted-foreground">{h.from}–{h.to} · {h.days} ngày</span>
                    <Badge variant={st.v} dot>{st.label}</Badge>
                  </div>
                );
              })}
            </div>
          </div>
        </div>
      </div>

      <Modal open={dlg==='approve'} onClose={()=>setDlg(null)} title="Phê duyệt đơn nghỉ"
        footer={<><Btn variant="outline" size="sm" onClick={()=>setDlg(null)}>Hủy</Btn><Btn variant="primary" size="sm" icon="check" onClick={()=>{ setDlg(null); setToast('Đã phê duyệt — số dư đã trừ (demo)'); }}>Phê duyệt</Btn></>}>
        <div className="text-sm text-muted-foreground">Duyệt đơn <b className="text-foreground">{req.emp}</b> · {req.from}–{req.to} ({req.days} ngày)?</div>
        <div className="mt-3"><label className={LBL}>Ghi chú <span className="font-normal text-muted-foreground">(tùy chọn)</span></label><textarea className={TXT} placeholder="Ghi chú cho nhân viên…" /></div>
      </Modal>
      <Modal open={dlg==='reject'} onClose={()=>setDlg(null)} title="Từ chối đơn nghỉ"
        footer={<><Btn variant="outline" size="sm" onClick={()=>setDlg(null)}>Hủy</Btn><Btn variant="destructive" size="sm" icon="x" disabled={!reason.trim()} onClick={()=>{ setDlg(null); setToast('Đã từ chối — đã trả lại pending (demo)'); }}>Từ chối</Btn></>}>
        <div className="mb-3 text-sm text-muted-foreground">Từ chối đơn <b className="text-foreground">{req.emp}</b> · {req.from}–{req.to}.</div>
        <label className={LBL}>Lý do từ chối <span className="text-destructive">*</span></label>
        <textarea className={TXT} value={reason} onChange={(e)=>setReason(e.target.value)} placeholder="Bắt buộc — nhân viên sẽ thấy lý do này…" />
        {!reason.trim() && <div className="mt-1.5 flex items-center gap-1 text-xs text-destructive"><Icon name="alert-circle" size={12} /> Bắt buộc nhập lý do khi từ chối.</div>}
      </Modal>
    </LeaveShell>
  );
};

// ─── 04: Leave Balance (data:leave:own) ──────────────────────────────────────
const MY_BALANCES = [
  { code:'AL',   entitled:18, used:8, pending:4, carry:2, cy:2026 },
  { code:'SL',   entitled:14, used:2, pending:0, carry:0, cy:2026 },
  { code:'COMP', entitled:3,  used:0, pending:0, carry:0, cy:2026 },
];
const LeaveBalanceScreen = () => {
  const [dlg, setDlg]     = React.useState(null);
  const [toast, setToast] = React.useState('');
  const history = LEAVE_REQUESTS.filter(r=>r.emp==='Phạm Đức Long').concat([
    { id:'LR-X1', type:'AL', from:'01/02/2026', to:'05/02/2026', days:5, status:'APPROVED', reason:'Tết Nguyên Đán', emp:'Phạm Đức Long' },
    { id:'LR-X2', type:'SL', from:'15/03/2026', to:'16/03/2026', days:2, status:'APPROVED', reason:'Sốt', emp:'Phạm Đức Long' },
  ]);
  // Đơn hủy được: pending, hoặc approved chưa qua ngày bắt đầu (mock theo trạng thái)
  const cancellable = (r) => r.status==='PENDING' || r.status==='APPROVED';
  return (
  <LeaveShell active="balance" perms={PERMS_OWN}
    user={{ name:'Phạm Đức Long', role:'data:leave:own' }}
    title="Số dư nghỉ phép của tôi"
    crumbs={['Nghỉ phép', 'Số dư của tôi']}
    actions={<Btn variant="primary" size="sm" icon="plus" onClick={()=>dcNav('ess/submit')}>Xin nghỉ phép</Btn>}>
    <Toast msg={toast} onClose={()=>setToast('')} />

    <div className="mb-[18px] grid grid-cols-3 gap-3.5">
      {MY_BALANCES.map((b,i)=>{
        const lt=LEAVE_TYPES.find(t=>t.code===b.code), total=b.entitled+b.carry, rem=total-b.used, pct=Math.round((b.used/total)*100);
        return (
          <div key={i} className={CARD + " p-[22px]"}>
            <div className="mb-3.5 flex items-center gap-2.5"><div className="grid size-9 place-items-center rounded-md" style={{ background:lt.bg }}><Icon name="umbrella" size={16} style={{ color:lt.color }} /></div><div><div className="text-base font-bold">{lt.name}</div><div className="text-xs text-muted-foreground">{lt.paid?'Có lương':'Không lương'} · Năm {b.cy}</div></div></div>
            <div className="mb-2.5 flex items-end gap-2"><div className="text-[42px] font-extrabold leading-none" style={{ color:lt.color }}>{rem}</div><div className="mb-1.5 text-base text-muted-foreground">/ {total} ngày còn lại</div></div>
            <div className="mb-2 h-[7px] overflow-hidden rounded-full bg-muted"><div className="h-full rounded-full" style={{ width:`${pct}%`, background:lt.color }} /></div>
            <div className="grid grid-cols-3 gap-2 text-xs">{[{ l:'Được cấp', v:b.entitled },{ l:'Đã dùng', v:b.used },{ l:'Đang chờ', v:b.pending }].map((s,j)=>(<div key={j} className="rounded-sm bg-muted p-[7px] text-center"><div className="text-md font-bold">{s.v}</div><div className="text-muted-foreground">{s.l}</div></div>))}</div>
          </div>
        );
      })}
    </div>

    {/* Bảng số dư chi tiết — Entitled / Used / Pending / Carry-over / Available */}
    <div className={CARD + " mb-[18px]"}>
      <div className="border-b border-border px-5 py-4"><div className="text-md font-semibold text-foreground">Chi tiết số dư theo loại phép</div></div>
      <table className={TABLE_CLS}>
        <thead><tr><th>Loại phép</th><th className="!text-right">Được cấp</th><th className="!text-right">Carry-over</th><th className="!text-right">Đã dùng</th><th className="!text-right">Đang chờ</th><th className="!text-right">Khả dụng</th></tr></thead>
        <tbody>
          {MY_BALANCES.map((b,i)=>{ const avail=b.entitled+b.carry-b.used-b.pending; return (
            <tr key={i}>
              <td><LeaveTypePill code={b.code} /></td>
              <td className="text-right tabular-nums">{b.entitled.toFixed(1)}</td>
              <td className="text-right tabular-nums">{b.carry.toFixed(1)}</td>
              <td className="text-right tabular-nums">{b.used.toFixed(1)}</td>
              <td className="text-right tabular-nums text-[oklch(0.55_0.158_65)]">{b.pending.toFixed(1)}</td>
              <td className="text-right font-bold tabular-nums text-primary">{avail.toFixed(1)}</td>
            </tr>
          ); })}
        </tbody>
      </table>
    </div>

    <div className={CARD}>
      <div className="flex items-center justify-between gap-3 border-b border-border px-5 py-4"><div className="text-md font-semibold text-foreground">Lịch sử yêu cầu nghỉ phép 2026</div><Btn variant="outline" size="sm" icon="download">Xuất PDF</Btn></div>
      {/* Hàng bộ lọc */}
      <div className="flex flex-wrap items-center gap-2.5 border-b border-border px-5 py-3">
        <Select className="h-8 text-xs" style={{width:150}} defaultValue="Tất cả loại phép" options={['Tất cả loại phép', ...LEAVE_TYPES.map(t=>t.name)]} />
        <Select className="h-8 text-xs" style={{width:140}} defaultValue="Tất cả trạng thái" options={['Tất cả trạng thái','Chờ duyệt','Đã duyệt','Từ chối','Đã hủy']} />
        <input type="date" className="h-8 rounded-md border border-input bg-transparent px-2.5 text-xs text-foreground shadow-xs focus:border-primary focus:outline-none focus:ring-[3px] focus:ring-ring" style={{width:140}} />
        <span className="text-xs text-muted-foreground">→</span>
        <input type="date" className="h-8 rounded-md border border-input bg-transparent px-2.5 text-xs text-foreground shadow-xs focus:border-primary focus:outline-none focus:ring-[3px] focus:ring-ring" style={{width:140}} />
        <div className="flex-1" />
        <span className="text-xs text-muted-foreground">{history.length} yêu cầu</span>
      </div>
      <table className={TABLE_CLS}>
        <thead><tr><th>Loại phép</th><th>Từ ngày</th><th>Đến ngày</th><th style={{ textAlign:'center' }}>Số ngày</th><th>Lý do</th><th>Trạng thái</th><th>Người duyệt</th><th className="!text-right">Thao tác</th></tr></thead>
        <tbody>
          {history.map(r=>{ const st=LV_ST[r.status]; const canCancel=cancellable(r); return (
            <tr key={r.id}><td><LeaveTypePill code={r.type} /></td><td className="text-sm">{r.from}</td><td className="text-sm">{r.to}</td><td className="text-center font-bold">{r.days}</td><td className="text-sm text-muted-foreground">{r.reason}</td><td><Badge variant={st.v} dot>{st.label}</Badge></td><td className="text-xs text-muted-foreground">Quản lý trực tiếp</td><td className="text-right"><Btn variant="outline" size="xs" icon="x" disabled={!canCancel} onClick={()=>setDlg(r)}>Hủy</Btn></td></tr>
          ); })}
        </tbody>
      </table>
      {/* Thanh phân trang */}
      <div className="flex items-center justify-between gap-3 border-t border-border px-5 py-3">
        <span className="text-xs text-muted-foreground">Hiển thị 1–{history.length} trên {history.length}</span>
        <div className="flex items-center gap-1">
          <Btn variant="outline" size="xs" iconOnly icon="chevron-left" disabled />
          <Btn variant="soft" size="xs">1</Btn>
          <Btn variant="ghost" size="xs">2</Btn>
          <Btn variant="ghost" size="xs">3</Btn>
          <Btn variant="outline" size="xs" iconOnly icon="chevron-right" />
        </div>
      </div>
    </div>

    <Modal open={!!dlg} onClose={()=>setDlg(null)} title="Hủy đơn nghỉ phép"
      footer={<><Btn variant="outline" size="sm" onClick={()=>setDlg(null)}>Đóng</Btn><Btn variant="destructive" size="sm" icon="x" onClick={()=>{ setDlg(null); setToast(`Đã hủy đơn ${dlg?.id} (demo)`); }}>Xác nhận hủy</Btn></>}>
      <div className="text-sm text-muted-foreground">Hủy đơn <LeaveTypePill code={dlg?.type||'AL'} /> · {dlg?.from}–{dlg?.to} ({dlg?.days} ngày)? Số dư đang giữ (nếu có) sẽ được hoàn lại.</div>
    </Modal>
  </LeaveShell>
  );
};

// ─── 05: Leave Configuration (action:leave:configure) — màn nhiều tab ─────────
const LEAVE_CONFIG_TABS = [
  { id:'types',     label:'Loại phép',     icon:'umbrella'      },
  { id:'holidays',  label:'Ngày lễ',       icon:'calendar'      },
  { id:'workweeks', label:'Tuần làm việc', icon:'calendar-days' },
  { id:'rules',     label:'Quy tắc',       icon:'shield'        },
  { id:'periods',   label:'Kỳ phép',       icon:'rotate-ccw'    },
];
const LeaveConfigTabBar = ({ active, onChange }) => (
  <div className="mb-4 flex items-center gap-0.5 border-b border-border">
    {LEAVE_CONFIG_TABS.map(t=>{ const on=t.id===active; return (
      <button key={t.id} onClick={()=>onChange&&onChange(t.id)} className={"-mb-px flex items-center gap-1.5 border-b-2 px-3.5 py-2.5 text-sm font-medium transition-colors " + (on ? "border-primary text-primary" : "cursor-pointer border-transparent text-muted-foreground hover:text-foreground")}><Icon name={t.icon} size={14} />{t.label}</button>
    ); })}
  </div>
);
const LeaveTypesConfig = ({ onEdit }) => (
  <div className="grid grid-cols-2 gap-3.5">
    {LEAVE_TYPES.map(lt=>(
      <div key={lt.code} className={CARD + " p-5"}>
        <div className="mb-3 flex items-start justify-between">
          <div className="flex items-center gap-3"><div className="grid size-[38px] place-items-center rounded-md" style={{ background:lt.bg }}><Icon name="umbrella" size={16} style={{ color:lt.color }} /></div><div><div className="text-base font-bold">{lt.name}</div><div className="font-mono text-xs text-muted-foreground">{lt.code}</div></div></div>
          <div className="flex gap-1"><Badge variant={lt.paid?'success':'neutral'}>{lt.paid?'Có lương':'KL'}</Badge><Btn variant="ghost" size="sm" iconOnly icon="edit" onClick={()=>onEdit&&onEdit(lt)} /></div>
        </div>
        <div className="grid grid-cols-2 gap-2">{[{ l:'Số ngày/kỳ', v:lt.days>0?`${lt.days}N`:'—' },{ l:'Trạng thái', v:'Kích hoạt' },{ l:'Yêu cầu PL', v:lt.attach?'Có':'Không' },{ l:'Theo tỷ lệ', v:lt.prorata?'Có':'Không' }].map((s,j)=>(<div key={j} className="rounded-sm bg-muted px-2.5 py-2 text-center"><div className="text-sm font-bold">{s.v}</div><div className="mt-0.5 text-xs text-muted-foreground">{s.l}</div></div>))}</div>
      </div>
    ))}
  </div>
);
const HOLIDAYS = [
  { name:'Tết Dương lịch',    date:'01/01/2026', country:'VNM', region:'—', recurring:true,  workday:false },
  { name:'Tết Nguyên Đán',    date:'17/02/2026', country:'VNM', region:'—', recurring:false, workday:false },
  { name:'Giỗ Tổ Hùng Vương', date:'26/04/2026', country:'VNM', region:'—', recurring:true,  workday:false },
  { name:'Giải phóng miền Nam',date:'30/04/2026', country:'VNM', region:'—', recurring:true,  workday:false },
  { name:'Quốc tế Lao động',  date:'01/05/2026', country:'VNM', region:'—', recurring:true,  workday:false },
  { name:'Quốc khánh',        date:'02/09/2026', country:'VNM', region:'—', recurring:true,  workday:false },
  { name:'Làm bù Tết',        date:'21/02/2026', country:'VNM', region:'—', recurring:false, workday:true  },
];
const HolidaysConfig = ({ onEdit }) => (
  <div className="flex flex-col gap-3">
    <div className={CARD + " flex items-center gap-2.5 px-3.5 py-2.5"}><Select className="h-8 text-xs" style={{width:160}} defaultValue="Việt Nam (VNM)" options={['Việt Nam (VNM)','Singapore (SGP)','Toàn cục (global)']} /><Select className="h-8 text-xs" style={{width:120}} defaultValue="Năm 2026" options={['Năm 2026','Năm 2027']} /><div className="flex-1" /><span className="text-xs text-muted-foreground">{HOLIDAYS.length} ngày lễ</span></div>
    <div className="overflow-hidden rounded-lg border border-border bg-card">
      <table className={TABLE_CLS}>
        <thead><tr><th>Tên ngày lễ</th><th>Ngày</th><th>Quốc gia / Vùng</th><th>Lặp hàng năm</th><th>Đi làm bù</th><th>Thao tác</th></tr></thead>
        <tbody>{HOLIDAYS.map((h,i)=>(<tr key={i}><td className="font-medium">{h.name}</td><td className="text-sm tabular-nums">{h.date}</td><td className="text-sm text-muted-foreground">{h.country} · {h.region}</td><td>{h.recurring ? <Badge variant="info">Hàng năm</Badge> : <Badge variant="neutral">Một lần</Badge>}</td><td>{h.workday ? <Badge variant="warning" dot>Đi làm bù</Badge> : <span className="text-xs text-muted-foreground">—</span>}</td><td><div className="flex gap-1"><Btn variant="ghost" size="sm" iconOnly icon="edit" onClick={()=>onEdit&&onEdit(h)} /><Btn variant="ghost" size="sm" iconOnly icon="trash" /></div></td></tr>))}</tbody>
      </table>
    </div>
  </div>
);
const WORK_WEEKS = [{ name:'Mon–Fri (chuẩn)', days:[1,2,3,4,5], hours:8, def:true, country:'Toàn cục' },{ name:'Sun–Thu (Trung Đông)', days:[0,1,2,3,4], hours:8, def:false, country:'ARE' }];
const DOW = ['CN','T2','T3','T4','T5','T6','T7'];
const WorkWeeksConfig = ({ onEdit }) => (
  <div className="flex flex-col gap-3.5">
    {WORK_WEEKS.map((w,i)=>(
      <div key={i} className={CARD + " p-5"}>
        <div className="mb-3 flex items-start justify-between"><div><div className="flex items-center gap-2"><div className="text-base font-bold">{w.name}</div>{w.def && <Badge variant="primary">Mặc định</Badge>}</div><div className="mt-0.5 text-xs text-muted-foreground">{w.country} · {w.hours} giờ/ngày</div></div><Btn variant="ghost" size="sm" iconOnly icon="edit" onClick={()=>onEdit&&onEdit(w)} /></div>
        <div className="flex gap-1">{DOW.map((d,j)=>{ const on=w.days.includes(j); return (<div key={j} className={"grid h-8 flex-1 place-items-center rounded-sm text-xs font-semibold " + (on ? "bg-primary-soft text-primary" : "bg-muted text-muted-foreground")}>{d}</div>); })}</div>
        <div className="mt-2.5 text-xs text-muted-foreground">Ngày làm việc dùng để loại trừ cuối tuần khi tính số ngày phép.</div>
      </div>
    ))}
  </div>
);
const RULES = [
  { name:'Báo trước phép năm',  scope:'AL · Toàn cục',    type:'min_notice_days',     val:'3 ngày'  },
  { name:'Tối đa liên tiếp AL', scope:'AL · Toàn cục',    type:'max_consecutive_days', val:'15 ngày' },
  { name:'Tối thiểu mỗi đơn',   scope:'Tất cả · Toàn cục',type:'min_leave_duration',  val:'0.5 ngày'},
  { name:'Tối đa đơn nghỉ ốm',  scope:'SL · VNM',         type:'max_leave_duration',  val:'30 ngày' },
];
const RulesConfig = ({ onEdit }) => (
  <div className="overflow-hidden rounded-lg border border-border bg-card">
    <table className={TABLE_CLS}>
      <thead><tr><th>Tên quy tắc</th><th>Áp dụng</th><th>Loại</th><th>Giá trị</th><th>Trạng thái</th><th>Thao tác</th></tr></thead>
      <tbody>{RULES.map((r,i)=>(<tr key={i}><td className="font-medium">{r.name}</td><td className="text-sm text-muted-foreground">{r.scope}</td><td><span className="font-mono text-xs text-muted-foreground">{r.type}</span></td><td className="text-sm font-semibold tabular-nums">{r.val}</td><td><Badge variant="success" dot>Đang áp dụng</Badge></td><td><div className="flex gap-1"><Btn variant="ghost" size="sm" iconOnly icon="edit" onClick={()=>onEdit&&onEdit(r)} /><Btn variant="ghost" size="sm" iconOnly icon="trash" /></div></td></tr>))}</tbody>
    </table>
  </div>
);
// Ba kỳ tháng cố ý dài khác nhau (28/31/30 ngày) — kỳ tháng chạy tới ngày cuối
// THẬT của từng tháng, không phải 30 ngày cố định.
const PERIODS = [
  { name:'2026 Cal. Year', type:'calendar_year', cycle:'Theo năm',   from:'01/01/2026', to:'31/12/2026', active:true  },
  { name:'2027 Cal. Year', type:'calendar_year', cycle:'Theo năm',   from:'01/01/2027', to:'31/12/2027', active:false },
  { name:'02/2026',        type:'monthly',       cycle:'Theo tháng', from:'01/02/2026', to:'28/02/2026', active:false },
  { name:'03/2026',        type:'monthly',       cycle:'Theo tháng', from:'01/03/2026', to:'31/03/2026', active:true  },
  { name:'04/2026',        type:'monthly',       cycle:'Theo tháng', from:'01/04/2026', to:'30/04/2026', active:false },
];
const PeriodsConfig = ({ onEdit }) => (
  <div className="flex flex-col gap-3">
    <div className="flex items-center gap-2 rounded-md bg-info-soft px-3.5 py-2.5 text-xs text-info"><Icon name="info" size={14} className="shrink-0" /><span><span className="font-semibold">Mỗi nhịp</span> chỉ có duy nhất một kỳ đang hoạt động (kỳ chứa hôm nay). Kỳ kế tạo trước ở trạng thái chờ, tự kích hoạt đúng ngày bắt đầu.</span></div>
    <div className="overflow-hidden rounded-lg border border-border bg-card">
      <table className={TABLE_CLS}>
        <thead><tr><th>Tên kỳ</th><th>Nhịp</th><th>Loại</th><th>Từ ngày</th><th>Đến ngày</th><th>Trạng thái</th><th>Thao tác</th></tr></thead>
        <tbody>{PERIODS.map((p,i)=>(<tr key={i}><td className="font-medium">{p.name}</td><td className="text-sm">{p.cycle}</td><td><span className="font-mono text-xs text-muted-foreground">{p.type}</span></td><td className="text-sm tabular-nums">{p.from}</td><td className="text-sm tabular-nums">{p.to}</td><td>{p.active ? <Badge variant="success" dot>Đang hoạt động</Badge> : <Badge variant="neutral" dot>Chờ kích hoạt</Badge>}</td><td><Btn variant="ghost" size="sm" iconOnly icon="edit" onClick={()=>onEdit&&onEdit(p)} /></td></tr>))}</tbody>
      </table>
    </div>
  </div>
);
// ─── Ô chọn kỳ phép — gom theo nhịp ──────────────────────────────────────────
// Select dùng chung (shared.jsx) chỉ nhận danh sách phẳng, chưa có cơ chế nhóm.
// Bản rút gọn ở đây thêm dòng tiêu đề nhóm KHÔNG bấm được; phần còn lại (trigger,
// popup, click ra ngoài, Esc) giữ nguyên hình dáng của Select để không lệch nhau.
// TODO: dọn về shared.jsx thành khả năng của chính Select khi có dịp sửa tệp đó.
const SEL_TRIG = "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";
const GroupedSelect = ({ groups = [], defaultValue, className = "", style }) => {
  const [open, setOpen]   = React.useState(false);
  const [value, setValue] = React.useState(defaultValue);
  const ref = React.useRef(null);
  // Giống Select: tôn trọng h-* / text-* nếu className đã chỉ định, chưa thì tự thêm cỡ form.
  const tok     = className.split(/\s+/).filter(Boolean);
  const textTok = tok.find((t) => /^text-(?:xs|sm|base|md|lg|xl)$/.test(t)) || "text-base";
  const sizeCls = (tok.some((t) => /^h-/.test(t)) ? "" : "h-9 ") + textTok;

  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]);

  return (
    <div ref={ref} className="relative" style={style}>
      <button type="button" onClick={()=>setOpen(o=>!o)} className={SEL_TRIG + " " + sizeCls + " " + className}>
        <span className="line-clamp-1 text-left">{value}</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">
          {groups.map((g)=>(
            <React.Fragment key={g.label}>
              <div className="px-2 pb-1 pt-1.5 text-2xs font-bold uppercase tracking-[0.06em] text-muted-foreground">{g.label}</div>
              {g.items.map((it)=>{
                const sel = it === value;
                return (
                  <div key={it} onClick={()=>{ setValue(it); setOpen(false); }}
                    className={"relative flex cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 " + textTok + " 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>}
                    {it}
                  </div>
                );
              })}
            </React.Fragment>
          ))}
        </div>
      )}
    </div>
  );
};
// Kỳ đang có (khớp bảng Kỳ phép ở trên) và kỳ đã đóng — chuyển phép tồn lấy
// kỳ NGUỒN là kỳ đã kết thúc nên cần danh sách riêng.
const PERIOD_GROUPS = [
  { label:'Theo năm',   items:['2026 Cal. Year','2027 Cal. Year'] },
  { label:'Theo tháng', items:['02/2026','03/2026','04/2026'] },
];
const PERIOD_GROUPS_SRC = [
  { label:'Theo năm',   items:['2025 Cal. Year','2026 Cal. Year'] },
  { label:'Theo tháng', items:['01/2026','02/2026','03/2026'] },
];

// ─── Shared config modal form bodies (dùng chung Tabs + Sidebar) ─────────────
// Toggle pill tái dùng (bật/tắt is_active, đặt mặc định…)
const Toggle = ({ on, onClick, disabled }) => (
  <button type="button" disabled={disabled} onClick={onClick}
    className={"relative inline-flex h-5 w-9 shrink-0 items-center rounded-full transition-colors " + (disabled ? "cursor-not-allowed opacity-60 " : "cursor-pointer ") + (on ? "bg-primary" : "bg-border-strong")}>
    <span className={"inline-block size-4 transform rounded-full bg-white shadow transition-transform " + (on ? "translate-x-[18px]" : "translate-x-0.5")} />
  </button>
);

// Form Loại phép — toggle is_active (UNP/LWP khóa), color, requires_attachment,
// allow_partial, min_notice_days, max_consecutive_days
const LeaveTypeForm = ({ editing }) => {
  const lt = editing || LEAVE_TYPES[0];
  const systemType = lt.code === 'UNP' || lt.code === 'LWP';
  const [active, setActive]   = React.useState(true);
  const [color, setColor]     = React.useState(lt.color);
  const [attach, setAttach]   = React.useState(lt.attach);
  const [partial, setPartial] = React.useState(true);
  const [prorata, setProrata] = React.useState(!!lt.prorata);
  return (
    <div className="grid grid-cols-2 gap-3">
      <div><label className={LBL}>Mã (code)</label><input className={INP} defaultValue={editing?lt.code:''} placeholder="VD: AL" /></div>
      <div><label className={LBL}>Tên hiển thị</label><input className={INP} defaultValue={editing?lt.name:''} placeholder="Phép năm" /></div>
      <div><label className={LBL}>Số ngày mỗi kỳ</label><input type="number" className={INP} defaultValue={editing?lt.days:0} /></div>
      {/* Nhịp quyết định "kỳ" ở nhãn bên cạnh là năm hay tháng, nên đặt liền nhau.
          Khoá sau khi đã phát sinh hạn mức — giải thích ngay dưới, giống pro_rata_enabled. */}
      <div>
        <label className={LBL}>Nhịp (period_cycle)</label>
        <Select options={['Theo năm','Theo tháng']} defaultValue="Theo năm" />
        <span className="mt-0.5 block text-xs font-normal text-muted-foreground">Khoá lại, không đổi được sau khi loại phép đã phát sinh hạn mức — đổi giữa chừng làm số dư của nhịp cũ mồ côi.</span>
      </div>
      <div><label className={LBL}>Có lương?</label><Select options={['Có lương','Không lương']} defaultValue={lt.paid?'Có lương':'Không lương'} /></div>
      {/* Công tắc bật/tắt is_active */}
      <div className="col-span-2 flex items-center justify-between rounded-md border border-border px-3.5 py-2.5">
        <div>
          <div className="text-sm font-medium">Kích hoạt loại phép</div>
          {systemType && <div className="mt-0.5 flex items-center gap-1 text-xs text-muted-foreground"><Icon name="lock" size={11} /> Không thể tắt — phép hệ thống</div>}
        </div>
        <Toggle on={systemType ? true : active} disabled={systemType} onClick={()=>setActive(v=>!v)} />
      </div>
      {/* Ô chọn màu */}
      <div className="col-span-2">
        <label className={LBL}>Màu hiển thị (color)</label>
        <div className="flex items-center gap-2.5">
          <input type="color" value="#c0562a" onChange={()=>{}} className="h-9 w-12 cursor-pointer rounded-md border border-input bg-transparent p-1" />
          <input className={INP} value={color} onChange={(e)=>setColor(e.target.value)} placeholder="oklch(...) hoặc #hex" />
        </div>
      </div>
      <div className="col-span-2 grid grid-cols-2 gap-3">
        <div><label className={LBL}>min_notice_days</label><input type="number" className={INP} defaultValue="3" /></div>
        <div><label className={LBL}>max_consecutive_days</label><input type="number" className={INP} defaultValue="15" /></div>
      </div>
      <label className="col-span-2 flex cursor-pointer items-center justify-between rounded-md border border-border px-3.5 py-2.5 text-sm">
        <span>Yêu cầu đính kèm (requires_attachment)</span>
        <Toggle on={attach} onClick={()=>setAttach(v=>!v)} />
      </label>
      <label className="col-span-2 flex cursor-pointer items-center justify-between rounded-md border border-border px-3.5 py-2.5 text-sm">
        <span>Cho phép nghỉ nửa ngày (allow_partial)</span>
        <Toggle on={partial} onClick={()=>setPartial(v=>!v)} />
      </label>
      {/* Chia hạn mức theo thời gian làm việc — nghĩa của cờ này không đọc ra được từ nhãn nên
          kèm câu giải thích, khác các toggle còn lại. Chỉ loại tích luỹ theo thời gian (AL/SL) bật. */}
      <label className="col-span-2 flex cursor-pointer items-center justify-between gap-3 rounded-md border border-border px-3.5 py-2.5 text-sm">
        <span>
          Chia theo thời gian làm việc (pro_rata_enabled)
          <span className="mt-0.5 block text-xs font-normal text-muted-foreground">Nhân viên vào làm giữa kỳ chỉ nhận số ngày tương ứng số tháng làm việc còn lại của kỳ.</span>
        </span>
        <Toggle on={prorata} onClick={()=>setProrata(v=>!v)} />
      </label>
    </div>
  );
};

// Form Tuần làm việc — 7 checkbox ngày + giờ/ngày + đặt mặc định
const WorkWeekForm = () => {
  const [days, setDays]   = React.useState([1,2,3,4,5]);
  const [def, setDef]     = React.useState(false);
  const toggle = (j) => setDays(d => d.includes(j) ? d.filter(x=>x!==j) : [...d, j]);
  return (
    <div className="flex flex-col gap-3.5">
      <div><label className={LBL}>Tên</label><input className={INP} placeholder="Mon–Fri (chuẩn)" /></div>
      <div>
        <label className={LBL}>Ngày làm việc</label>
        <div className="flex gap-1.5">
          {DOW.map((d,j)=>{ const on=days.includes(j); return (
            <button key={j} type="button" onClick={()=>toggle(j)}
              className={"grid h-9 flex-1 cursor-pointer place-items-center rounded-md text-xs font-semibold transition-colors " + (on ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground hover:bg-accent")}>{d}</button>
          ); })}
        </div>
      </div>
      <div><label className={LBL}>Số giờ làm việc / ngày</label><input type="number" step="0.5" className={INP} defaultValue="8" /></div>
      <label className="flex cursor-pointer items-center justify-between rounded-md border border-border px-3.5 py-2.5 text-sm">
        <span>Đặt làm mặc định</span>
        <Toggle on={def} onClick={()=>setDef(v=>!v)} />
      </label>
    </div>
  );
};

const CFG_ADD_LABEL = { types:'loại phép', holidays:'ngày lễ', workweeks:'tuần làm việc', rules:'quy tắc', periods:'kỳ phép' };

const LeaveConfigScreen = () => {
  const [tab, setTab]     = React.useState('types');
  const [dlg, setDlg]     = React.useState(null);
  const [toast, setToast] = React.useState('');
  const addAction = {
    types:    <Btn variant="primary" size="sm" icon="plus" onClick={()=>setDlg({ mode:'add' })}>Thêm loại phép</Btn>,
    holidays: <><Btn variant="outline" size="sm" icon="rotate-ccw" onClick={()=>setToast('Đã tạo lễ định kỳ cho năm sau (demo)')}>Tạo lễ định kỳ</Btn><Btn variant="primary" size="sm" icon="plus" onClick={()=>setDlg({ mode:'add' })}>Thêm ngày lễ</Btn></>,
    workweeks:<Btn variant="primary" size="sm" icon="plus" onClick={()=>setDlg({ mode:'add' })}>Thêm tuần làm việc</Btn>,
    rules:    <Btn variant="primary" size="sm" icon="plus" onClick={()=>setDlg({ mode:'add' })}>Thêm quy tắc</Btn>,
    periods:  <Btn variant="primary" size="sm" icon="plus" onClick={()=>setDlg({ mode:'add' })}>Thêm kỳ phép</Btn>,
  }[tab];
  const onEdit = (row) => setDlg({ mode:'edit', row });
  return (
    <LeaveShell active="config" perms={PERMS_ALL}
      title="Cấu hình nghỉ phép"
      crumbs={['Nghỉ phép', 'Cấu hình']}
      user={{ name:'Trần Minh', role:'action:leave:configure' }}
      actions={addAction}>
      <Toast msg={toast} onClose={()=>setToast('')} />

      <LeaveConfigTabBar active={tab} onChange={setTab} />
      {tab==='types'     && <LeaveTypesConfig onEdit={onEdit} />}
      {tab==='holidays'  && <HolidaysConfig   onEdit={onEdit} />}
      {tab==='workweeks' && <WorkWeeksConfig  onEdit={onEdit} />}
      {tab==='rules'     && <RulesConfig      onEdit={onEdit} />}
      {tab==='periods'   && <PeriodsConfig    onEdit={onEdit} />}

      <Modal open={!!dlg} onClose={()=>setDlg(null)} title={`${dlg?.mode==='edit'?'Sửa':'Thêm'} ${CFG_ADD_LABEL[tab]}`} width={tab==='types'?'max-w-lg':'max-w-md'}
        footer={<><Btn variant="outline" size="sm" onClick={()=>setDlg(null)}>Hủy</Btn><Btn variant="primary" size="sm" onClick={()=>{ setDlg(null); setToast(`Đã lưu ${CFG_ADD_LABEL[tab]} (demo)`); }}>Lưu</Btn></>}>
        {tab==='types'    && <LeaveTypeForm editing={dlg?.mode==='edit' ? dlg?.row : null} />}
        {tab==='holidays' && (<div className="grid grid-cols-2 gap-3"><div><label className={LBL}>Tên ngày lễ</label><input className={INP} placeholder="Quốc khánh" /></div><div><label className={LBL}>Ngày</label><input type="date" className={INP} /></div><div><label className={LBL}>Quốc gia</label><Select options={['VNM','SGP','global']} defaultValue="VNM" /></div><div><label className={LBL}>Lặp hàng năm?</label><Select options={['Một lần','Hàng năm']} defaultValue="Một lần" /></div></div>)}
        {tab==='workweeks'&& <WorkWeekForm />}
        {tab==='rules'    && (<div className="grid grid-cols-2 gap-3"><div><label className={LBL}>Loại quy tắc</label><Select options={['min_notice_days','max_consecutive_days','min_leave_duration','max_leave_duration']} defaultValue="min_notice_days" /></div><div><label className={LBL}>Giá trị</label><input type="number" className={INP} defaultValue="3" /></div></div>)}
        {tab==='periods'  && (<div className="grid grid-cols-2 gap-3"><div className="col-span-2"><label className={LBL}>Tên kỳ</label><input className={INP} placeholder="2028 Cal. Year" /></div><div><label className={LBL}>Nhịp</label><Select options={['Theo năm','Theo tháng']} defaultValue="Theo năm" /></div><div><label className={LBL}>Loại</label><Select options={['calendar_year','fiscal_year','monthly','custom']} defaultValue="calendar_year" /></div><div><label className={LBL}>Ngày bắt đầu</label><input type="date" className={INP} /></div><div><label className={LBL}>Ngày kết thúc</label><input type="date" className={INP} /></div><label className="col-span-2 flex items-center gap-2 text-sm"><input type="checkbox" className="size-4 accent-primary" /> Đặt làm kỳ đang hoạt động (active)</label></div>)}
      </Modal>
    </LeaveShell>
  );
};

// ─── 06: Entitlements & Manual Adjustment (action:leave:configure + data:leave:all) ──
const ENTITLEMENTS = [
  { emp:'Phạm Đức Long', dept:'Kinh doanh', type:'AL',   entitled:18, carry:2, used:8, pending:4, adjusted:0 },
  { emp:'Võ Thị Thu',   dept:'Tài chính',  type:'SL',   entitled:14, carry:0, used:2, pending:0, adjusted:0 },
  { emp:'Đỗ Văn Hùng',  dept:'Engineering',type:'AL',   entitled:18, carry:0, used:5, pending:0, adjusted:2 },
  { emp:'Bùi Thị Linh', dept:'Nhân sự',    type:'COMP', entitled:0,  carry:0, used:1, pending:0, adjusted:3 },
];
const CARRYOVER_CONFIGS = [
  { type:'AL',   maxDays:5,  expireMonths:3, mode:'Theo số ngày tối đa' },
  { type:'COMP', maxDays:0,  expireMonths:1, mode:'Không cho chuyển'   },
  { type:'SL',   maxDays:0,  expireMonths:0, mode:'Không cho chuyển'   },
];
const LeaveEntitlementScreen = () => {
  const [dlg, setDlg]       = React.useState(null);
  const [toast, setToast]   = React.useState('');
  const [reason, setReason] = React.useState('');
  return (
    <LeaveShell active="entitlement" perms={PERMS_ALL}
      title="Số dư & Điều chỉnh phép"
      crumbs={['Nghỉ phép', 'Điều chỉnh số dư']}
      user={{ name:'Trần Minh', role:'action:leave:configure' }}
      actions={<>
        <Btn variant="outline" size="sm" icon="dollar-sign" onClick={()=>setDlg({ kind:'encash' })}>Quy đổi tiền</Btn>
        <Btn variant="outline" size="sm" icon="rotate-ccw" onClick={()=>setDlg({ kind:'carryrun' })}>Chạy chuyển phép tồn</Btn>
        <Btn variant="outline" size="sm" icon="rotate-ccw" onClick={()=>setDlg({ kind:'auto' })}>Phân bổ tự động</Btn>
        <Btn variant="primary"  size="sm" icon="plus" onClick={()=>{ setReason(''); setDlg({ kind:'adjust' }); }}>Điều chỉnh thủ công</Btn>
      </>}>
      <Toast msg={toast} onClose={()=>setToast('')} />

      <div className="mb-3 flex items-center gap-2 rounded-md bg-muted px-3.5 py-2.5 text-xs text-muted-foreground"><Icon name="info" size={14} className="shrink-0" />Chỉ <span className="font-medium text-foreground">phép có lương</span> mới có số dư. Phép không lương (UNP/LWP) không hiển thị (không theo dõi quỹ ngày).</div>
      <div className={CARD + " mb-3 flex items-center gap-2.5 px-3.5 py-2.5"}>
        <div className="relative flex w-60 items-center"><Icon name="search" size={13} className="pointer-events-none absolute left-2.5 size-3.5 text-muted-foreground" /><input className="h-8 w-full rounded-md border border-input bg-transparent pl-8 pr-3 text-xs text-foreground shadow-xs placeholder:text-muted-foreground focus:border-primary focus:outline-none focus:ring-[3px] focus:ring-ring" placeholder="Tìm nhân viên..." /></div>
        <GroupedSelect className="h-8 text-xs" style={{width:140}} defaultValue="2026 Cal. Year" groups={PERIOD_GROUPS} />
        <Select className="h-8 text-xs" style={{width:130}} defaultValue="Tất cả loại phép" options={['Tất cả loại phép', ...LEAVE_TYPES.filter(t=>t.paid).map(t=>t.name)]} />
      </div>
      <div className="overflow-hidden rounded-lg border border-border bg-card">
        <table className={TABLE_CLS}>
          <thead><tr><th>Nhân viên</th><th>Loại phép</th><th className="!text-right">Được cấp</th><th className="!text-right">Carry-over</th><th className="!text-right">Đã dùng</th><th className="!text-right">Đang chờ</th><th className="!text-right">Điều chỉnh</th><th className="!text-right">Khả dụng</th><th>Thao tác</th></tr></thead>
          <tbody>
            {ENTITLEMENTS.map((e,i)=>{ const avail=e.entitled+e.carry-e.used-e.pending+e.adjusted; return (
              <tr key={i}>
                <td><div className="flex items-center gap-[9px]"><Avatar name={e.emp} size="sm" /><div><div className="text-sm font-medium">{e.emp}</div><div className="text-xs text-muted-foreground">{e.dept}</div></div></div></td>
                <td><LeaveTypePill code={e.type} /></td>
                <td className="text-right tabular-nums">{e.entitled.toFixed(1)}</td><td className="text-right tabular-nums">{e.carry.toFixed(1)}</td><td className="text-right tabular-nums">{e.used.toFixed(1)}</td>
                <td className="text-right tabular-nums text-[oklch(0.55_0.158_65)]">{e.pending.toFixed(1)}</td>
                <td className="text-right tabular-nums">{e.adjusted>0?`+${e.adjusted.toFixed(1)}`:e.adjusted.toFixed(1)}</td>
                <td className="text-right font-bold tabular-nums text-primary">{avail.toFixed(1)}</td>
                <td><Btn variant="outline" size="xs" icon="edit" onClick={()=>{ setReason(''); setDlg({ kind:'adjust', row:e }); }}>Điều chỉnh</Btn></td>
              </tr>
            ); })}
          </tbody>
        </table>
      </div>

      {/* ── Carry-over Configs (CRUD) ── */}
      <div className="mt-5 mb-3 flex items-center justify-between">
        <div>
          <div className="text-base font-bold">Cấu hình chuyển phép tồn (Carry-over)</div>
          <div className="mt-0.5 text-sm text-muted-foreground">Quy định số ngày tối đa được chuyển sang kỳ sau và thời hạn dùng phép chuyển.</div>
        </div>
        <Btn variant="primary" size="sm" icon="plus" onClick={()=>setDlg({ kind:'carrycfg', mode:'add' })}>Thêm cấu hình</Btn>
      </div>
      <div className="overflow-hidden rounded-lg border border-border bg-card">
        <table className={TABLE_CLS}>
          <thead><tr><th>Loại phép</th><th>Chế độ</th><th className="!text-right">Tối đa chuyển (ngày)</th><th className="!text-right">Hết hạn sau (tháng)</th><th>Thao tác</th></tr></thead>
          <tbody>
            {CARRYOVER_CONFIGS.map((c,i)=>(
              <tr key={i}>
                <td><LeaveTypePill code={c.type} /></td>
                <td className="text-sm text-muted-foreground">{c.mode}</td>
                <td className="text-right tabular-nums">{c.maxDays>0?c.maxDays.toFixed(1):'—'}</td>
                <td className="text-right tabular-nums">{c.expireMonths>0?c.expireMonths:'—'}</td>
                <td><div className="flex gap-1"><Btn variant="ghost" size="sm" iconOnly icon="edit" onClick={()=>setDlg({ kind:'carrycfg', mode:'edit', row:c })} /><Btn variant="ghost" size="sm" iconOnly icon="trash" /></div></td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>

      <Modal open={dlg?.kind==='adjust'} onClose={()=>setDlg(null)} title="Điều chỉnh số dư (thủ công)"
        footer={<><Btn variant="outline" size="sm" onClick={()=>setDlg(null)}>Hủy</Btn><Btn variant="primary" size="sm" disabled={!reason.trim()} onClick={()=>{ setDlg(null); setToast('Đã ghi điều chỉnh + audit (demo)'); }}>Lưu</Btn></>}>
        <div className="mb-3 grid grid-cols-2 gap-3">
          <div><label className={LBL}>Nhân viên</label><input className={INP} disabled defaultValue={dlg?.row?.emp || 'Phạm Đức Long'} /></div>
          <div><label className={LBL}>Loại phép</label><input className={INP} disabled defaultValue={(LEAVE_TYPES.find(t=>t.code===(dlg?.row?.type||'AL'))||{}).name} /></div>
        </div>
        <div className="mb-3"><label className={LBL}>Giá trị mới adjusted_days <span className="font-normal text-muted-foreground">(tuyệt đối, ±999.99)</span></label><input type="number" step="0.5" className={INP} defaultValue={(dlg?.row?.adjusted ?? 0).toString()} /></div>
        <label className={LBL}>Lý do <span className="text-destructive">*</span></label>
        <input className={INP} value={reason} onChange={(e)=>setReason(e.target.value)} placeholder="Bắt buộc — phục vụ đối soát & audit" />
        {!reason.trim() && <div className="mt-1.5 flex items-center gap-1 text-xs text-destructive"><Icon name="alert-circle" size={12} /> Bắt buộc nhập lý do.</div>}
      </Modal>
      <Modal open={dlg?.kind==='auto'} onClose={()=>setDlg(null)} title="Phân bổ entitlement tự động"
        footer={<><Btn variant="outline" size="sm" onClick={()=>setDlg(null)}>Hủy</Btn><Btn variant="primary" size="sm" icon="rotate-ccw" onClick={()=>{ setDlg(null); setToast('Đã chạy phân bổ tự động (demo)'); }}>Chạy</Btn></>}>
        <div className="mb-3"><label className={LBL}>Kỳ phép</label><GroupedSelect groups={PERIOD_GROUPS} defaultValue="2026 Cal. Year" /></div>
        <div className="flex gap-2 rounded-md bg-info-soft px-3 py-2.5 text-xs text-info"><Icon name="info" size={13} className="mt-0.5 shrink-0" /><span>Tạo entitlement còn thiếu cho mọi nhân viên active × loại phép <b>CÓ lương</b>. Bỏ qua bản ghi đã tồn tại.</span></div>
      </Modal>

      {/* Carry-over config add/edit */}
      <Modal open={dlg?.kind==='carrycfg'} onClose={()=>setDlg(null)} title={`${dlg?.mode==='edit'?'Sửa':'Thêm'} cấu hình chuyển phép`}
        footer={<><Btn variant="outline" size="sm" onClick={()=>setDlg(null)}>Hủy</Btn><Btn variant="primary" size="sm" onClick={()=>{ setDlg(null); setToast('Đã lưu cấu hình carry-over (demo)'); }}>Lưu</Btn></>}>
        <div className="grid grid-cols-2 gap-3">
          <div><label className={LBL}>Loại phép</label><Select options={LEAVE_TYPES.filter(t=>t.paid).map(t=>t.name)} defaultValue={(LEAVE_TYPES.find(t=>t.code===(dlg?.row?.type||'AL'))||{}).name} /></div>
          <div><label className={LBL}>Chế độ</label><Select options={['Theo số ngày tối đa','Không cho chuyển','Chuyển toàn bộ']} defaultValue={dlg?.row?.mode || 'Theo số ngày tối đa'} /></div>
          <div><label className={LBL}>Tối đa chuyển (ngày)</label><input type="number" step="0.5" className={INP} defaultValue={(dlg?.row?.maxDays ?? 5).toString()} /></div>
          <div><label className={LBL}>Hết hạn sau (tháng)</label><input type="number" className={INP} defaultValue={(dlg?.row?.expireMonths ?? 3).toString()} /></div>
        </div>
      </Modal>

      {/* Apply carry-over — chọn kỳ nguồn → kỳ đích */}
      <Modal open={dlg?.kind==='carryrun'} onClose={()=>setDlg(null)} title="Chạy chuyển phép tồn"
        footer={<><Btn variant="outline" size="sm" onClick={()=>setDlg(null)}>Hủy</Btn><Btn variant="primary" size="sm" icon="rotate-ccw" onClick={()=>{ setDlg(null); setToast('Đã chuyển phép tồn sang kỳ đích (demo)'); }}>Chạy</Btn></>}>
        <div className="mb-3 grid grid-cols-2 gap-3">
          <div><label className={LBL}>Kỳ nguồn</label><GroupedSelect groups={PERIOD_GROUPS_SRC} defaultValue="2025 Cal. Year" /></div>
          <div><label className={LBL}>Kỳ đích</label><GroupedSelect groups={PERIOD_GROUPS} defaultValue="2026 Cal. Year" /></div>
        </div>
        <div className="flex gap-2 rounded-md bg-info-soft px-3 py-2.5 text-xs text-info"><Icon name="info" size={13} className="mt-0.5 shrink-0" /><span>Chuyển số dư còn lại từ kỳ nguồn sang kỳ đích theo <b>cấu hình carry-over</b> của từng loại phép (giới hạn số ngày + thời hạn dùng).</span></div>
      </Modal>

      {/* Encash — quy đổi phép thành tiền */}
      <Modal open={dlg?.kind==='encash'} onClose={()=>setDlg(null)} title="Quy đổi phép thành tiền (Encash)"
        footer={<><Btn variant="outline" size="sm" onClick={()=>setDlg(null)}>Hủy</Btn><Btn variant="primary" size="sm" icon="dollar-sign" onClick={()=>{ setDlg(null); setToast('Đã ghi nhận quy đổi phép thành tiền (demo)'); }}>Quy đổi</Btn></>}>
        <div className="grid grid-cols-2 gap-3">
          <div><label className={LBL}>Nhân viên</label><Select options={ENTITLEMENTS.map(e=>e.emp)} defaultValue="Phạm Đức Long" /></div>
          <div><label className={LBL}>Loại phép</label><Select options={LEAVE_TYPES.filter(t=>t.paid).map(t=>t.name)} defaultValue="Phép năm" /></div>
          <div><label className={LBL}>Số ngày quy đổi</label><input type="number" step="0.5" className={INP} defaultValue="2" /></div>
          <div><label className={LBL}>Kỳ phép</label><GroupedSelect groups={PERIOD_GROUPS} defaultValue="2026 Cal. Year" /></div>
        </div>
        <div className="mt-2 flex items-center gap-1.5 text-xs text-muted-foreground"><Icon name="info" size={12} /> Số ngày quy đổi sẽ bị trừ khỏi số dư khả dụng và chuyển sang phần thanh toán.</div>
      </Modal>
    </LeaveShell>
  );
};

// ─── 07: Approval Delegation (action:leave:approve + data:leave:dept) ─────────
const DELEGATIONS = [
  { from:'Đỗ Thị Mai',   to:'Trần Quốc Bảo', start:'01/06/2026', end:'10/06/2026', reason:'Nghỉ phép năm', active:true  },
  { from:'Lý Văn Thành', to:'Phan Thu Hà',   start:'15/05/2026', end:'20/05/2026', reason:'Công tác',      active:false },
];
const LeaveDelegationScreen = () => {
  const [dlg, setDlg]     = React.useState(false);
  const [toast, setToast] = React.useState('');
  return (
    <LeaveShell active="delegation" perms={PERMS_DEPT}
      title="Ủy quyền phê duyệt"
      crumbs={['Nghỉ phép', 'Ủy quyền']}
      user={{ name:'Đỗ Thị Mai', role:'action:leave:approve' }}
      actions={<Btn variant="primary" size="sm" icon="plus" onClick={()=>setDlg(true)}>Tạo ủy quyền</Btn>}>
      <Toast msg={toast} onClose={()=>setToast('')} />

      <div className={CARD + " mb-3.5 flex gap-3 p-4"}>
        <div className="grid size-9 shrink-0 place-items-center rounded-md bg-info-soft"><Icon name="info" size={16} style={{ color:'var(--color-info)' }} /></div>
        <div className="text-sm leading-[1.6] text-muted-foreground"><span className="font-semibold text-foreground">Ủy quyền tạm thời</span> có thời hạn (từ/đến ngày) — đơn nộp trong thời gian này tự chuyển cho người được ủy quyền; lịch sử duyệt ghi rõ "thay mặt ai". Khác với <span className="font-medium text-foreground">Người duyệt thay thế dài hạn</span> (cấu hình cố định trong hồ sơ nhân sự — module PIM).</div>
      </div>
      <div className="overflow-hidden rounded-lg border border-border bg-card">
        <table className={TABLE_CLS}>
          <thead><tr><th>Người ủy quyền</th><th>Người nhận quyền</th><th>Từ ngày</th><th>Đến ngày</th><th>Lý do</th><th>Trạng thái</th><th>Thao tác</th></tr></thead>
          <tbody>{DELEGATIONS.map((d,i)=>(<tr key={i}><td><div className="flex items-center gap-[9px]"><Avatar name={d.from} size="sm" /><span className="text-sm font-medium">{d.from}</span></div></td><td><div className="flex items-center gap-[9px]"><Avatar name={d.to} size="sm" /><span className="text-sm font-medium">{d.to}</span></div></td><td className="text-sm tabular-nums">{d.start}</td><td className="text-sm tabular-nums">{d.end}</td><td className="text-sm text-muted-foreground">{d.reason}</td><td>{d.active ? <Badge variant="success" dot>Đang hiệu lực</Badge> : <Badge variant="neutral" dot>Hết hiệu lực</Badge>}</td><td><Btn variant="ghost" size="sm" iconOnly icon="ban" disabled={!d.active} onClick={()=>setToast('Đã vô hiệu hóa ủy quyền (demo)')} /></td></tr>))}</tbody>
        </table>
      </div>

      <Modal open={dlg} onClose={()=>setDlg(false)} title="Tạo ủy quyền duyệt tạm thời"
        footer={<><Btn variant="outline" size="sm" onClick={()=>setDlg(false)}>Hủy</Btn><Btn variant="primary" size="sm" onClick={()=>{ setDlg(false); setToast('Đã tạo ủy quyền (demo)'); }}>Tạo</Btn></>}>
        <div className="mb-3"><label className={LBL}>Người ủy quyền (delegator)</label><Select options={['Đỗ Thị Mai','Lý Văn Thành','Nguyễn Văn An']} defaultValue="Đỗ Thị Mai" placeholder="Chọn người ủy quyền" /></div>
        <div className="mb-3"><label className={LBL}>Ủy quyền cho (người nhận)</label><Select options={['Trần Quốc Bảo','Phan Thu Hà','Nguyễn Văn An']} placeholder="Chọn người nhận quyền" /></div>
        <div className="grid grid-cols-2 gap-3"><div><label className={LBL}>Từ ngày</label><input type="date" className={INP} /></div><div><label className={LBL}>Đến ngày</label><input type="date" className={INP} /></div></div>
        <div className="mt-3"><label className={LBL}>Lý do</label><input className={INP} placeholder="VD: nghỉ phép năm" /></div>
      </Modal>
    </LeaveShell>
  );
};

// ─── 08: Empty state ─────────────────────────────────────────────────────────
const LeaveEmptyScreen = () => (
  <LeaveShell active={null} perms={PERMS_OWN}
    title="Quản lý nghỉ phép"
    crumbs={['Nghỉ phép']}
    actions={<Btn variant="primary" size="sm" icon="plus" onClick={()=>dcNav('ess/submit')}>Xin nghỉ phép</Btn>}>
    <div className="flex min-h-[400px] flex-col items-center justify-center">
      <svg width="80" height="80" viewBox="0 0 80 80" fill="none" className="mb-6"><circle cx="40" cy="40" r="40" fill="var(--color-muted)" /><path d="M20 52 Q40 20 60 52" stroke="var(--color-border-strong)" strokeWidth="2.5" fill="none" /><rect x="36" y="52" width="8" height="14" rx="2" fill="var(--color-border-strong)" /><circle cx="59" cy="58" r="12" fill="var(--color-primary-soft)" stroke="var(--color-primary)" strokeWidth="2" /><path d="M55 58h8M59 54v8" stroke="var(--color-primary)" strokeWidth="2" strokeLinecap="round" /></svg>
      <div className="mb-2.5 text-xl font-bold">Chưa có yêu cầu nghỉ phép</div>
      <div className="mb-7 max-w-[400px] text-center text-base leading-[1.65] text-muted-foreground">Chưa có yêu cầu nghỉ phép nào. Nhân viên có thể gửi yêu cầu từ cổng self-service, hoặc HR có thể tạo thủ công.</div>
      <Btn variant="primary" icon="plus" onClick={()=>dcNav('ess/submit')}>Tạo yêu cầu đầu tiên</Btn>
    </div>
  </LeaveShell>
);

// ─── 09: Dark Mode ────────────────────────────────────────────────────────────
const LeaveDarkScreen = () => <LeaveDashboardScreen dark />;

// ─── 10: Showcase dialog — Từ chối (bắt buộc lý do) ──────────────────────────
const LeaveRejectDialogScreen = () => <LeaveApproveScreen demo="reject" />;

// ─── 11: Color Palette Reference ────────────────────────────────────────────
const LeaveColorPaletteScreen = () => (
  <HRMShell active="leave" title="Bảng màu loại nghỉ phép"
    crumbs={['Nghỉ phép', 'Bảng màu']}
    user={{ name:'Design Ref', role:'action:leave:configure' }}>
    <div className={CARD + " p-6"}>
      {/* Header */}
      <div className="mb-5 flex items-start justify-between gap-4">
        <div>
          <div className="text-lg font-bold mb-1">Bảng màu · 9 loại nghỉ phép</div>
          <div className="text-sm text-muted-foreground">Màu text và background riêng biệt, dùng oklch thuần. Nền selected (bg) có L ≤ 0.94 — luôn phân biệt với card trắng (L=1). Không có cặp nào trùng nhau.</div>
        </div>
        <div className="flex shrink-0 items-center gap-4 text-xs text-muted-foreground">
          <div className="flex items-center gap-1.5"><span className="inline-block size-3 rounded-sm bg-foreground opacity-60" />Foreground (text)</div>
          <div className="flex items-center gap-1.5"><span className="inline-block size-3 rounded-sm border border-border-strong" />Background (selected)</div>
        </div>
      </div>
      {/* Grid */}
      <div className="grid grid-cols-3 gap-3.5">
        {LEAVE_TYPES.map(lt => (
          <div key={lt.code} className="overflow-hidden rounded-lg border border-border">
            {/* Dual swatch bar */}
            <div className="flex h-11">
              <div className="flex flex-1 items-end px-2.5 pb-1.5" style={{ background: lt.color }}>
                <span className="text-[10px] font-bold text-white opacity-70">TEXT</span>
              </div>
              <div className="flex flex-1 items-end px-2.5 pb-1.5" style={{ background: lt.bg, borderLeft: '2px solid rgba(255,255,255,0.6)' }}>
                <span className="text-[10px] font-bold opacity-60" style={{ color: lt.color }}>BG</span>
              </div>
            </div>
            {/* Info */}
            <div className="bg-card p-3.5">
              <div className="mb-2.5 flex items-start justify-between gap-2">
                <div>
                  <div className="text-sm font-bold text-foreground">{lt.name}</div>
                  <div className="mt-0.5 font-mono text-xs text-muted-foreground">{lt.code} · {lt.paid ? 'Có lương' : 'Không lương'}</div>
                </div>
                <LeaveTypePill code={lt.code} />
              </div>
              {/* Selected state preview */}
              <div className="rounded-md p-2.5" style={{ background: lt.bg, border: `1px solid ${lt.color}55` }}>
                <div className="flex items-center gap-2">
                  <div className="grid size-6 shrink-0 place-items-center rounded-sm" style={{ background: lt.color }}>
                    <Icon name="umbrella" size={10} style={{ color:'#fff' }} />
                  </div>
                  <div className="flex-1 min-w-0">
                    <div className="truncate text-xs font-semibold" style={{ color: lt.color }}>{lt.name}</div>
                    <div className="text-xs text-muted-foreground">{lt.paid ? 'Có lương' : 'Không lương'}</div>
                  </div>
                  <div className="grid size-3.5 shrink-0 place-items-center rounded-full" style={{ background: lt.color }}>
                    <Icon name="check" size={8} style={{ color:'#fff' }} />
                  </div>
                </div>
              </div>
              {/* Color values */}
              <div className="mt-2.5 space-y-0.5">
                <div className="flex gap-2 text-xs"><span className="w-6 shrink-0 font-medium text-muted-foreground">fg</span><span className="font-mono text-muted-foreground truncate">{lt.color}</span></div>
                <div className="flex gap-2 text-xs"><span className="w-6 shrink-0 font-medium text-muted-foreground">bg</span><span className="font-mono text-muted-foreground truncate">{lt.bg}</span></div>
              </div>
            </div>
          </div>
        ))}
      </div>
    </div>
  </HRMShell>
);

// ─── 06b: Config — Sidebar Nav (đề xuất thay tabs) ───────────────────────────
// Pattern: left sidebar nav (Settings-style, like GitHub / Linear / Stripe).
// Giải quyết 2 vấn đề của tabs:
//   1. Data không đồng đều → sidebar không yêu cầu cân bằng visual giữa các mục.
//   2. Action bị đặt trên header → button nằm ngay trong section header, rõ ràng scope.
const SECTION_META = {
  types:    { title:'Loại phép',      desc:'Cấu hình loại nghỉ phép, nhịp kỳ, số ngày mỗi kỳ và chính sách lương.' },
  holidays: { title:'Ngày lễ',        desc:'Danh sách ngày nghỉ lễ theo quốc gia và năm.' },
  workweeks:{ title:'Tuần làm việc',  desc:'Định nghĩa các ngày làm việc trong tuần theo khu vực.' },
  rules:    { title:'Quy tắc',        desc:'Ràng buộc về thời gian báo trước, số ngày tối đa, v.v.' },
  periods:  { title:'Kỳ phép',        desc:'Kỳ phép — mỗi nhịp một kỳ hoạt động tại một thời điểm.' },
};

const LeaveConfigSidebarScreen = () => {
  const [tab, setTab]     = React.useState('types');
  const [dlg, setDlg]     = React.useState(null);
  const [toast, setToast] = React.useState('');
  const onEdit = (row) => setDlg({ mode:'edit', row });

  const sectionAction = {
    types:    <Btn variant="primary" size="sm" icon="plus" onClick={()=>setDlg({mode:'add'})}>Thêm loại phép</Btn>,
    holidays: <><Btn variant="outline" size="sm" icon="rotate-ccw" onClick={()=>setToast('Đã tạo lễ định kỳ (demo)')}>Tạo lễ định kỳ</Btn><Btn variant="primary" size="sm" icon="plus" onClick={()=>setDlg({mode:'add'})}>Thêm ngày lễ</Btn></>,
    workweeks:<Btn variant="primary" size="sm" icon="plus" onClick={()=>setDlg({mode:'add'})}>Thêm tuần làm việc</Btn>,
    rules:    <Btn variant="primary" size="sm" icon="plus" onClick={()=>setDlg({mode:'add'})}>Thêm quy tắc</Btn>,
    periods:  <Btn variant="primary" size="sm" icon="plus" onClick={()=>setDlg({mode:'add'})}>Thêm kỳ phép</Btn>,
  }[tab];

  const meta = SECTION_META[tab];

  return (
    <LeaveShell active="config" perms={PERMS_ALL}
      title="Cấu hình nghỉ phép"
      crumbs={['Nghỉ phép', 'Cấu hình', meta.title]}
      user={{ name:'Trần Minh', role:'action:leave:configure' }}>
      <Toast msg={toast} onClose={()=>setToast('')} />

      <div className="grid grid-cols-[188px_1fr] gap-6">

        {/* ── Sidebar nav ── */}
        <nav className="flex flex-col gap-0.5 pt-0.5">
          {LEAVE_CONFIG_TABS.map(t => {
            const on = t.id === tab;
            return (
              <button key={t.id} onClick={() => setTab(t.id)}
                className={"flex w-full cursor-pointer items-center gap-2.5 rounded-md px-3 py-[7px] text-sm transition-colors "
                  + (on ? "bg-accent font-semibold text-foreground" : "font-normal text-muted-foreground hover:bg-muted hover:text-foreground")}>
                <Icon name={t.icon} size={14} className="shrink-0" />
                {t.label}
              </button>
            );
          })}
        </nav>

        {/* ── Section content ── */}
        <div className="min-w-0">
          {/* Section header — title + description + scoped action */}
          <div className="mb-4 flex items-start justify-between gap-4 border-b border-border pb-4">
            <div>
              <div className="text-base font-bold">{meta.title}</div>
              <div className="mt-0.5 text-sm text-muted-foreground">{meta.desc}</div>
            </div>
            <div className="flex shrink-0 items-center gap-2">{sectionAction}</div>
          </div>

          {tab==='types'     && <LeaveTypesConfig onEdit={onEdit} />}
          {tab==='holidays'  && <HolidaysConfig   onEdit={onEdit} />}
          {tab==='workweeks' && <WorkWeeksConfig  onEdit={onEdit} />}
          {tab==='rules'     && <RulesConfig      onEdit={onEdit} />}
          {tab==='periods'   && <PeriodsConfig    onEdit={onEdit} />}
        </div>
      </div>

      <Modal open={!!dlg} onClose={()=>setDlg(null)} title={`${dlg?.mode==='edit'?'Sửa':'Thêm'} ${CFG_ADD_LABEL[tab]}`} width={tab==='types'?'max-w-lg':'max-w-md'}
        footer={<><Btn variant="outline" size="sm" onClick={()=>setDlg(null)}>Hủy</Btn><Btn variant="primary" size="sm" onClick={()=>{ setDlg(null); setToast(`Đã lưu ${CFG_ADD_LABEL[tab]} (demo)`); }}>Lưu</Btn></>}>
        {tab==='types'    && <LeaveTypeForm editing={dlg?.mode==='edit' ? dlg?.row : null} />}
        {tab==='holidays' && (<div className="grid grid-cols-2 gap-3"><div><label className={LBL}>Tên ngày lễ</label><input className={INP} placeholder="Quốc khánh" /></div><div><label className={LBL}>Ngày</label><input type="date" className={INP} /></div><div><label className={LBL}>Quốc gia</label><Select options={['VNM','SGP','global']} defaultValue="VNM" /></div><div><label className={LBL}>Lặp hàng năm?</label><Select options={['Một lần','Hàng năm']} defaultValue="Một lần" /></div></div>)}
        {tab==='workweeks'&& <WorkWeekForm />}
        {tab==='rules'    && (<div className="grid grid-cols-2 gap-3"><div><label className={LBL}>Loại quy tắc</label><Select options={['min_notice_days','max_consecutive_days','min_leave_duration','max_leave_duration']} defaultValue="min_notice_days" /></div><div><label className={LBL}>Giá trị</label><input type="number" className={INP} defaultValue="3" /></div></div>)}
        {tab==='periods'  && (<div className="grid grid-cols-2 gap-3"><div className="col-span-2"><label className={LBL}>Tên kỳ</label><input className={INP} placeholder="2028 Cal. Year" /></div><div><label className={LBL}>Nhịp</label><Select options={['Theo năm','Theo tháng']} defaultValue="Theo năm" /></div><div><label className={LBL}>Loại</label><Select options={['calendar_year','fiscal_year','monthly','custom']} defaultValue="calendar_year" /></div><div><label className={LBL}>Ngày bắt đầu</label><input type="date" className={INP} /></div><div><label className={LBL}>Ngày kết thúc</label><input type="date" className={INP} /></div><label className="col-span-2 flex items-center gap-2 text-sm"><input type="checkbox" className="size-4 accent-primary" /> Đặt làm kỳ đang hoạt động (active)</label></div>)}
      </Modal>
    </LeaveShell>
  );
};

// ─── ĐỀ XUẤT ĐIỀU HƯỚNG MODULE — tham khảo / archived ─────────────────────────
// LEAVE_NAV_GROUPS và visibleGroups đã chuyển lên trên LeaveShell.

// Option A — Top nav nhóm theo scope (giữ ngang, thêm label nhóm + divider)
const LeaveModuleNavGrouped = ({ active, perms }) => (
  <div className="flex flex-wrap items-center gap-y-2 border-b border-border bg-card px-3 py-2">
    {visibleGroups(perms || []).map((g, gi) => (
      <React.Fragment key={g.title}>
        {gi > 0 && <div className="mx-2 h-7 w-px bg-border" />}
        <div className="flex items-center gap-1.5">
          <span className="px-1 text-2xs font-bold uppercase tracking-[0.08em] text-muted-foreground">{g.title}</span>
          {g.items.map(n => {
            const on = n.id === active;
            return (
              <button key={n.id} onClick={() => !on && dcNav(n.slot)}
                className={"flex items-center gap-1.5 rounded-md px-2.5 py-1.5 text-sm font-medium transition-colors "
                  + (on ? "bg-primary-soft text-primary" : "cursor-pointer text-muted-foreground hover:bg-muted hover:text-foreground")}>
                <Icon name={n.icon} size={14} className="shrink-0" />{n.label}
              </button>
            );
          })}
        </div>
      </React.Fragment>
    ))}
  </div>
);

// Option B — Sidebar phụ nhóm (đúng pattern sidebar chính; scale tốt nhất)
const LeaveModuleNavRail = ({ active, perms }) => (
  <nav className="w-52 shrink-0 border-r border-border bg-card py-2">
    {visibleGroups(perms || []).map(g => (
      <div key={g.title} className="px-3 pb-1 pt-2">
        <div className="px-2 pb-1 text-2xs font-bold uppercase tracking-[0.1em] text-muted-foreground">{g.title}</div>
        {g.items.map(n => {
          const on = n.id === active;
          return (
            <button key={n.id} onClick={() => !on && dcNav(n.slot)}
              className={"relative my-px flex w-full items-center gap-2.5 rounded-md px-2.5 py-[7px] text-sm transition-colors "
                + (on ? "bg-primary-soft font-semibold text-primary" : "cursor-pointer font-medium text-foreground hover:bg-muted")}>
              {on && <span className="absolute -left-3 bottom-1.5 top-1.5 w-[3px] rounded-r-sm bg-primary" />}
              <Icon name={n.icon} size={15} className="shrink-0" />{n.label}
            </button>
          );
        })}
      </div>
    ))}
  </nav>
);

// Body chung cho các artboard so sánh (giữ cố định để chỉ khác phần nav)
const NavDemoBody = () => (
  <>
    <div className="mb-4 grid grid-cols-4 gap-3">
      {[['Chờ phê duyệt','8'],['Đang nghỉ hôm nay','12'],['Đã duyệt T5','34'],['Từ chối T5','5']].map(([l,v],i)=>(
        <div key={i} className={CARD + " p-4"}><div className="text-xs text-muted-foreground">{l}</div><div className="mt-1 text-2xl font-bold">{v}</div></div>
      ))}
    </div>
    <div className="overflow-hidden rounded-lg border border-border bg-card">
      <table className={TABLE_CLS}>
        <thead><tr><th>Nhân viên</th><th>Loại phép</th><th>Từ ngày</th><th>Đến ngày</th><th>Số ngày</th><th>Trạng thái</th></tr></thead>
        <tbody>
          {LEAVE_REQUESTS.slice(0,5).map(r=>{ const st=LV_ST[r.status]; return (
            <tr key={r.id}><td><div className="flex items-center gap-[9px]"><Avatar name={r.emp} size="sm" /><div><div className="text-sm font-medium">{r.emp}</div><div className="text-xs text-muted-foreground">{r.dept}</div></div></div></td><td><LeaveTypePill code={r.type} /></td><td className="text-sm">{r.from}</td><td className="text-sm">{r.to}</td><td className="text-center text-sm font-semibold">{r.days}</td><td><Badge variant={st.v} dot>{st.label}</Badge></td></tr>
          ); })}
        </tbody>
      </table>
    </div>
  </>
);

const NAV_DEMO_HEAD = {
  active:'leave', title:'Quản lý nghỉ phép', crumbs:['Nghỉ phép','Tổng quan'], meta:'Tháng 5/2026',
  actions:<><Btn variant="outline" size="sm" icon="download">Xuất báo cáo</Btn><Btn variant="primary" size="sm" icon="plus">Cấp phép thủ công</Btn></>,
};

// Hiện trạng — tab phẳng 7 mục (để so sánh trực tiếp, body giống nhau)
const LeaveNavFlatScreen = () => (
  <HRMShell {...NAV_DEMO_HEAD} user={{ name:'Trần Minh', role:'data:leave:all' }}>
    <div className="flex flex-col overflow-hidden rounded-xl border border-border bg-card shadow-xs">
      <LeaveModuleNav active="dashboard" perms={PERMS_ALL} />
      <div className="p-5"><NavDemoBody /></div>
    </div>
  </HRMShell>
);

// Option A
const LeaveNavGroupedScreen = () => (
  <HRMShell {...NAV_DEMO_HEAD} user={{ name:'Trần Minh', role:'data:leave:all' }}>
    <div className="flex flex-col overflow-hidden rounded-xl border border-border bg-card shadow-xs">
      <LeaveModuleNavGrouped active="dashboard" perms={PERMS_ALL} />
      <div className="p-5"><NavDemoBody /></div>
    </div>
  </HRMShell>
);

// Option B
const LeaveNavRailScreen = () => (
  <HRMShell {...NAV_DEMO_HEAD} user={{ name:'Trần Minh', role:'data:leave:all' }}>
    <div className="flex overflow-hidden rounded-xl border border-border bg-card shadow-xs">
      <LeaveModuleNavRail active="dashboard" perms={PERMS_ALL} />
      <div className="flex-1 p-5"><NavDemoBody /></div>
    </div>
  </HRMShell>
);

// Option B với user CHỈ có quyền ESS — chỉ còn nhóm "Tự phục vụ" (permission-aware)
const LeaveNavRailEssScreen = () => (
  <HRMShell active="leave" title="Nghỉ phép của tôi" crumbs={['Nghỉ phép','Số dư của tôi']}
    user={{ name:'Phạm Đức Long', role:'data:leave:own' }}
    actions={<Btn variant="primary" size="sm" icon="plus">Xin nghỉ phép</Btn>}>
    <div className="flex overflow-hidden rounded-xl border border-border bg-card shadow-xs">
      <LeaveModuleNavRail active="balance" perms={PERMS_OWN} />
      <div className="flex-1 p-5">
        <div className="mb-3 flex items-center gap-2 rounded-md bg-info-soft px-3.5 py-2.5 text-xs text-info">
          <Icon name="info" size={14} className="shrink-0" />User quyền <b>data:leave:own</b> chỉ thấy nhóm "Tự phục vụ" — nhóm Quản lý & Cấu hình bị ẩn hoàn toàn.
        </div>
        <NavDemoBody />
      </div>
    </div>
  </HRMShell>
);

// ─── DS-1: ESS Dashboard (NHÂN VIÊN — data:leave:own) ────────────────────────
// Khác LeaveDashboardScreen (của HR/manager): tập trung vào "của tôi".
const LeaveEssDashboardScreen = () => {
  const myBalances = [
    { code:'AL',   entitled:18, used:8, pending:4, carry:2 },
    { code:'SL',   entitled:14, used:2, pending:0, carry:0 },
    { code:'COMP', entitled:3,  used:0, pending:0, carry:0 },
  ];
  const myRecent = [
    { id:'LR-001', type:'AL', from:'20/05/2026', to:'23/05/2026', days:4, status:'PENDING'  },
    { id:'LR-X1',  type:'AL', from:'01/02/2026', to:'05/02/2026', days:5, status:'APPROVED' },
    { id:'LR-X2',  type:'SL', from:'15/03/2026', to:'16/03/2026', days:2, status:'APPROVED' },
    { id:'LR-X3',  type:'UNP',from:'25/05/2026', to:'29/05/2026', days:5, status:'REJECTED' },
  ];
  const myPending = myRecent.filter(r=>r.status==='PENDING').length;
  return (
    <LeaveShell active="ess-dashboard" perms={PERMS_OWN}
      user={{ name:'Phạm Đức Long', role:'data:leave:own' }}
      title="Nghỉ phép của tôi"
      crumbs={['Nghỉ phép', 'Tổng quan']}
      meta="Năm 2026"
      actions={<Btn variant="primary" size="sm" icon="plus" onClick={()=>dcNav('ess/submit')}>Xin nghỉ phép</Btn>}>

      {/* Hàng trên: thẻ đếm đơn chờ + tóm tắt nhanh */}
      <div className="mb-4 grid grid-cols-4 gap-3">
        <div className={CARD + " p-4"}>
          <div className="flex items-center gap-2.5"><div className="grid size-9 place-items-center rounded-md" style={{ background:'var(--color-warning-soft)' }}><Icon name="clock" size={16} style={{ color:'oklch(0.55 0.158 65)' }} /></div><div><div className="text-2xl font-extrabold leading-none">{myPending}</div><div className="mt-1 text-xs text-muted-foreground">Đơn đang chờ duyệt</div></div></div>
        </div>
        <div className={CARD + " p-4"}>
          <div className="flex items-center gap-2.5"><div className="grid size-9 place-items-center rounded-md" style={{ background:'var(--color-success-soft)' }}><Icon name="check-circle" size={16} style={{ color:'var(--color-success)' }} /></div><div><div className="text-2xl font-extrabold leading-none">{myRecent.filter(r=>r.status==='APPROVED').length}</div><div className="mt-1 text-xs text-muted-foreground">Đã duyệt năm nay</div></div></div>
        </div>
        <div className={CARD + " p-4"}>
          <div className="flex items-center gap-2.5"><div className="grid size-9 place-items-center rounded-md" style={{ background:'var(--color-info-soft)' }}><Icon name="umbrella" size={16} style={{ color:'var(--color-info)' }} /></div><div><div className="text-2xl font-extrabold leading-none">10</div><div className="mt-1 text-xs text-muted-foreground">Tổng ngày đã dùng</div></div></div>
        </div>
        <div className={CARD + " p-4"}>
          <div className="flex items-center gap-2.5"><div className="grid size-9 place-items-center rounded-md" style={{ background:'var(--color-primary-soft)' }}><Icon name="calendar" size={16} style={{ color:'var(--color-primary)' }} /></div><div><div className="text-2xl font-extrabold leading-none">12</div><div className="mt-1 text-xs text-muted-foreground">Ngày còn khả dụng</div></div></div>
        </div>
      </div>

      <div className="grid grid-cols-2 gap-4">
        {/* Thẻ số dư của tôi từng loại — thanh tiến trình */}
        <div className={CARD + " p-5"}>
          <div className="mb-4 text-sm font-bold">Số dư của tôi · từng loại phép</div>
          <div className="flex flex-col gap-4">
            {myBalances.map((b,i)=>{
              const lt=LEAVE_TYPES.find(t=>t.code===b.code), total=b.entitled+b.carry, avail=total-b.used-b.pending, pct=Math.round((b.used/total)*100), pendPct=Math.round((b.pending/total)*100);
              return (
                <div key={i}>
                  <div className="mb-1.5 flex items-center justify-between">
                    <div className="flex items-center gap-2"><span className="size-3 rounded-full" style={{ background:lt.color }} /><span className="text-sm font-medium">{lt.name}</span></div>
                    <span className="text-sm tabular-nums"><b style={{ color:lt.color }}>{avail.toFixed(0)}</b><span className="text-muted-foreground"> / {total.toFixed(0)} khả dụng</span></span>
                  </div>
                  <div className="flex h-2.5 overflow-hidden rounded-full bg-muted">
                    <div className="h-full" style={{ width:`${pct}%`, background:lt.color }} />
                    <div className="h-full opacity-40" style={{ width:`${pendPct}%`, background:lt.color }} />
                  </div>
                  <div className="mt-1 flex gap-3 text-xs text-muted-foreground"><span>Đã dùng {b.used}</span><span>Đang chờ {b.pending}</span>{b.carry>0 && <span>Carry-over {b.carry}</span>}</div>
                </div>
              );
            })}
          </div>
        </div>

        {/* Đơn gần đây của tôi */}
        <div className={CARD + " p-5"}>
          <div className="mb-3.5 flex items-center justify-between">
            <div className="text-sm font-bold">Đơn gần đây của tôi</div>
            <Btn variant="ghost" size="xs" onClick={()=>dcNav('ess/balance')}>Xem tất cả</Btn>
          </div>
          <div className="flex flex-col">
            {myRecent.map((r,i)=>{ const st=LV_ST[r.status]; return (
              <div key={r.id} className={"flex items-center gap-2.5 py-2.5 " + (i<myRecent.length-1?'border-b border-border':'')}>
                <LeaveTypePill code={r.type} />
                <div className="flex-1 min-w-0"><div className="text-xs text-muted-foreground">{r.from} – {r.to}</div><div className="text-xs font-medium">{r.days} ngày</div></div>
                <Badge variant={st.v} dot>{st.label}</Badge>
              </div>
            ); })}
          </div>
        </div>
      </div>
    </LeaveShell>
  );
};

// ─── DS-7: Team Calendar (HRM-281 — data:leave:dept) ─────────────────────────
// Lịch tháng: ai trong phòng nghỉ ngày nào, tô màu theo loại phép.
const TEAM_LEAVE = [
  { name:'Phạm Đức Long',  type:'AL',   days:[20,21,22,23] },
  { name:'Võ Thị Thu',     type:'SL',   days:[16,17]       },
  { name:'Ngô Minh Khoa',  type:'COMP', days:[18]          },
  { name:'Lê Thị Hương',   type:'AL',   days:[10,11,12,13,14] },
  { name:'Bùi Thị Linh',   type:'UNP',  days:[25,26,27]    },
];
const LeaveTeamCalendarScreen = () => {
  const [view, setView] = React.useState('month');
  // map ngày → danh sách {name,type}
  const byDay = {};
  TEAM_LEAVE.forEach(p => p.days.forEach(d => { (byDay[d] = byDay[d] || []).push(p); }));
  const usedTypes = [...new Set(TEAM_LEAVE.map(p=>p.type))];
  return (
    <LeaveShell active="team-calendar" perms={PERMS_DEPT}
      user={{ name:'Đỗ Thị Mai', role:'data:leave:dept' }}
      title="Lịch nghỉ phòng ban"
      crumbs={['Nghỉ phép', 'Lịch nhóm']}
      meta="Tháng 5/2026"
      actions={
        <div className="flex items-center gap-0.5 rounded-md border border-border p-0.5">
          <button onClick={()=>setView('month')} className={"cursor-pointer rounded-sm px-2.5 py-1 text-xs font-medium transition-colors " + (view==='month'?'bg-primary text-primary-foreground':'text-muted-foreground hover:text-foreground')}>Tháng</button>
          <button onClick={()=>setView('week')} className={"cursor-pointer rounded-sm px-2.5 py-1 text-xs font-medium transition-colors " + (view==='week'?'bg-primary text-primary-foreground':'text-muted-foreground hover:text-foreground')}>Tuần</button>
        </div>
      }>

      {/* Chú giải màu */}
      <div className={CARD + " mb-3 flex flex-wrap items-center gap-3 px-4 py-2.5"}>
        <span className="text-xs font-semibold text-muted-foreground">Chú giải:</span>
        {usedTypes.map(code=>{ const lt=LEAVE_TYPES.find(t=>t.code===code); return (
          <div key={code} className="flex items-center gap-1.5 text-xs"><span className="size-3 rounded-sm" style={{ background:lt.color }} />{lt.name}</div>
        ); })}
        <div className="flex-1" />
        <div className="flex items-center gap-1"><Btn variant="ghost" size="xs" iconOnly icon="chevron-left" /><span className="text-sm font-semibold">Tháng 5 · 2026</span><Btn variant="ghost" size="xs" iconOnly icon="chevron-right" /></div>
      </div>

      {view==='week' && (
        <div className="mb-3 flex items-center gap-2 rounded-md bg-info-soft px-3.5 py-2.5 text-xs text-info"><Icon name="info" size={14} className="shrink-0" />Chế độ xem <b>Tuần</b> (mock) — bên dưới minh họa dạng lưới Tháng.</div>
      )}

      {/* Lưới lịch tháng */}
      <div className={CARD + " p-4"}>
        <div className="grid grid-cols-7 gap-1 text-center">
          {['T2','T3','T4','T5','T6','T7','CN'].map(d=>(<div key={d} className="pb-1.5 text-xs font-semibold text-muted-foreground">{d}</div>))}
          {[null,null,null,null,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31].map((d,i)=>{
            const off=d===null, today=d===16, people=(d&&byDay[d])||[];
            return (
              <div key={i} className={"min-h-[78px] rounded-md border p-1.5 text-left align-top " + (off?'border-transparent':'border-border') + (today?' ring-1 ring-primary':'')} style={{ background: off?'transparent':'var(--color-card)' }}>
                {d && <div className={"mb-1 text-xs " + (today?'font-bold text-primary':'font-medium text-muted-foreground')}>{d}</div>}
                <div className="flex flex-col gap-0.5">
                  {people.slice(0,3).map((p,j)=>{ const lt=LEAVE_TYPES.find(t=>t.code===p.type); return (
                    <div key={j} className="truncate rounded-sm px-1 py-0.5 text-2xs font-medium" style={{ background:lt.bg, color:lt.color }}>{p.name.split(' ').slice(-1)[0]}</div>
                  ); })}
                  {people.length>3 && <div className="px-1 text-2xs text-muted-foreground">+{people.length-3} nữa</div>}
                </div>
              </div>
            );
          })}
        </div>
      </div>
    </LeaveShell>
  );
};

// ─── 06b: Chi tiết đơn nghỉ phép (data:leave:dept/all) — MÀN THUẦN ĐỌC ────────
// Mở từ nút "con mắt" ở bảng Tổng quan đơn vị. Route FE /leave/requests/:id.
// Mọi trạng thái (pending/approved/rejected/cancelled), KHÔNG có nút Duyệt/Từ chối
// (duyệt vẫn ở màn Duyệt đơn + bảng Tổng quan). Đính kèm: nội dung chỉ mở cho
// data:leave:all; data:leave:dept chỉ thấy cờ "đơn có kèm tệp".
const LeaveRequestDetailScreen = () => {
  // Đơn mẫu ĐÃ DUYỆT, loại Phép bệnh (có tệp đính kèm) — minh họa đủ timeline + đính kèm.
  // Khoảng ngày cố ý VẮT QUA hai kỳ tháng để thấy khối phân bổ; đơn thường chỉ có
  // một dòng phân bổ nên khối đó ẩn đi.
  const req = {
    id:'LR-003', emp:'Đỗ Văn Hùng', dept:'Engineering', type:'SL',
    from:'27/02/2026', to:'04/03/2026', days:4, status:'APPROVED',
    reason:'Điều trị theo chỉ định của bác sĩ, cần nghỉ để hồi phục.',
    handover:'Bàn giao module thanh toán cho Trần An; các PR đang mở đã ghi chú người tiếp nhận.',
    submitted:'20/02/2026', attach:'giay-nghi-om.pdf',
    allocations:[{ period:'02/2026', days:1 }, { period:'03/2026', days:3 }],
  };
  const lt = LEAVE_TYPES.find(t => t.code === req.type) || LEAVE_TYPES[0];
  const st = LV_ST[req.status];
  const timeline = [
    { action:'APPROVED', by:'Đỗ Thị Mai', at:'21/02/2026 · 09:12', comment:'Đã xác nhận giấy tờ hợp lệ.' },
  ];

  return (
    <LeaveShell active="dashboard" perms={PERMS_ALL}
      user={{ name:'Đỗ Thị Mai', role:'data:leave:all' }}
      title="Chi tiết đơn nghỉ phép"
      crumbs={['Nghỉ phép', 'Tổng quan', req.id]}
      actions={<Btn variant="outline" size="sm" icon="chevron-left" onClick={()=>dcNav('manage/dashboard')}>Về Tổng quan</Btn>}>

      <div className="mx-auto flex w-full max-w-[860px] flex-col gap-3.5">

        {/* 1. Hero — trạng thái động (KHÔNG hardcode "Chờ phê duyệt") */}
        <div className={CARD + " p-5"}>
          <div className="flex items-center gap-4">
            <Avatar name={req.emp} size="xl" />
            <div className="min-w-0 flex-1">
              <div className="text-xl font-bold">{req.emp}</div>
              <div className="mt-0.5 text-sm text-muted-foreground">Phòng {req.dept}</div>
              <div className="mt-2.5 flex flex-wrap items-center gap-2">
                <LeaveTypePill code={req.type} />
                <Badge variant={st.v} dot>{st.label}</Badge>
                <span className="text-xs text-muted-foreground">Nộp {req.submitted}</span>
              </div>
            </div>
            <div className="shrink-0 rounded-2xl px-6 py-4 text-center"
              style={{ background: lt.bg, border:`1.5px solid ${lt.color}33` }}>
              <div className="text-[40px] font-extrabold leading-none" style={{ color: lt.color }}>{req.days}</div>
              <div className="mt-1 text-xs font-medium" style={{ color: lt.color, opacity: 0.7 }}>ngày làm việc</div>
            </div>
          </div>
        </div>

        {/* 2. Thẻ ngày */}
        <div className="grid grid-cols-3 gap-3">
          {[
            { icon:'calendar', label:'Từ ngày',  val:req.from },
            { icon:'calendar', label:'Đến ngày', val:req.to   },
            { icon:'clock',    label:'Số ngày',  val:`${req.days} ngày làm việc` },
          ].map((f,i) => (
            <div key={i} className={CARD + " px-4 py-3.5"}>
              <div className="mb-1 flex items-center gap-1.5 text-xs text-muted-foreground">
                <Icon name={f.icon} size={11} />{f.label}
              </div>
              <div className="text-base font-bold">{f.val}</div>
            </div>
          ))}
        </div>

        {/* 2b. Phân bổ vào kỳ phép — chỉ hiện khi đơn vắt kỳ (nhiều hơn một dòng) */}
        {req.allocations.length > 1 && (
          <div className={CARD + " px-5 py-4"}>
            <div className="mb-2 text-xs font-semibold uppercase tracking-[0.06em] text-muted-foreground">Phân bổ vào kỳ phép</div>
            <div className="flex flex-col gap-1.5">
              {req.allocations.map((a,i) => (
                <div key={i} className="flex items-center justify-between rounded-md bg-muted px-3 py-2 text-sm">
                  <span className="font-medium">{a.period}</span>
                  <span className="font-semibold tabular-nums">{a.days} ngày</span>
                </div>
              ))}
            </div>
            <div className="mt-2 flex items-start gap-1.5 text-xs text-muted-foreground">
              <Icon name="info" size={12} className="mt-0.5 shrink-0" />
              <span>Đơn vắt qua ranh giới hai kỳ nên số ngày được chia về từng kỳ. Số dư kiểm ở <b>từng kỳ</b>, không cộng gộp. Đơn vẫn là <b>một</b> đơn — không tách thành hai.</span>
            </div>
          </div>
        )}

        {/* 3. Lý do */}
        <div className={CARD + " px-5 py-4"}>
          <div className="mb-1.5 text-xs font-semibold uppercase tracking-[0.06em] text-muted-foreground">Lý do nghỉ phép</div>
          <div className="text-sm leading-[1.65]">{req.reason}</div>
        </div>

        {/* 4. Ghi chú bàn giao */}
        <div className={CARD + " px-5 py-4"}>
          <div className="mb-1.5 text-xs font-semibold uppercase tracking-[0.06em] text-muted-foreground">Ghi chú bàn giao</div>
          <div className="text-sm leading-[1.65]">{req.handover}</div>
        </div>

        {/* 5. Tệp đính kèm — nội dung chỉ data:leave:all mở được */}
        <div className={CARD + " px-5 py-4"}>
          <div className="mb-2 flex items-center gap-1.5 text-xs font-semibold uppercase tracking-[0.06em] text-muted-foreground">
            <Icon name="paperclip" size={11} />Tệp đính kèm
          </div>
          <a className="inline-flex items-center gap-2 text-sm font-semibold text-primary hover:underline" href="#" onClick={(e)=>e.preventDefault()}>
            <Icon name="download" size={13} />{req.attach}
          </a>
          <div className="mt-2 flex items-start gap-1.5 rounded-md bg-info-soft px-3 py-2 text-xs text-info">
            <Icon name="info" size={13} className="mt-px shrink-0" />
            <span>Chỉ tài khoản có <b>data:leave:all</b> mở được nội dung tệp. Với <b>data:leave:dept</b>: chỉ hiện "đơn có kèm tệp", không mở được.</span>
          </div>
        </div>

        {/* 6. Lịch sử xử lý (timeline phê duyệt) */}
        <div className={CARD + " p-5"}>
          <div className="mb-3.5 text-sm font-semibold">Lịch sử xử lý</div>
          {timeline.length === 0 ? (
            <div className="text-sm text-muted-foreground">Chưa có quyết định.</div>
          ) : (
            <div className="flex flex-col gap-3">
              {timeline.map((t,i) => {
                const ok = t.action === 'APPROVED';
                return (
                  <div key={i} className="flex items-start gap-2.5">
                    <Icon name={ok?'check-circle':'x-circle'} size={16}
                      className={"mt-0.5 shrink-0 " + (ok?'text-success':'text-destructive')} />
                    <div className="min-w-0">
                      <div className="text-sm font-medium">{ok?'Đã phê duyệt':'Đã từ chối'}
                        <span className="font-normal text-muted-foreground"> · {t.by}</span>
                        <span className="ml-2 text-xs font-normal text-muted-foreground">{t.at}</span>
                      </div>
                      {t.comment && <div className="mt-0.5 text-xs text-muted-foreground">{t.comment}</div>}
                    </div>
                  </div>
                );
              })}
            </div>
          )}
        </div>
      </div>
    </LeaveShell>
  );
};

Object.assign(window, {
  LeaveDashboardScreen, LeaveRequestDetailScreen, LeaveSubmitScreen, LeaveApproveScreen, LeaveBalanceScreen,
  LeaveConfigScreen, LeaveConfigSidebarScreen, LeaveEntitlementScreen, LeaveDelegationScreen,
  LeaveEmptyScreen, LeaveDarkScreen, LeaveRejectDialogScreen, LeaveTypePill,
  LeaveColorPaletteScreen, LeaveEssDashboardScreen, LeaveTeamCalendarScreen,
});
