// ELS HRM — Trung tâm Trợ giúp / Hướng dẫn sử dụng (Module 15)
// Nguồn yêu cầu: HRM-494 (Giai đoạn 1) — quyết định Đ1..Đ4.
//
// Ghi chú thiết kế quan trọng:
// - Trang /guidelines là route CÔNG KHAI, nằm NGOÀI app shell (Đ3) ⇒ nó KHÔNG có
//   HRMSidebar/HRMTopbar. Khung standalone dựng tại chỗ: GLPublicHeader.
// - Sidebar danh mục nhóm theo MODULE, lọc theo MÃ QUYỀN. Không có bộ lọc vai trò:
//   vai trò là dữ liệu DB tự tạo được nên "ESS/Manager/Admin" không phải tập đóng.
// - Khách chưa đăng nhập chỉ thấy bài KHÔNG gắn quyền (fail-closed) ⇒ màn 01.
// - Quick-help drawer (màn 04/05) sống TRONG app shell. Icon `?` đã nằm trong
//   HRMTopbar của hrm-shell.jsx dùng chung (mọi màn app đều có), nên ở đây chỉ
//   truyền `helpActive` để vẽ trạng thái đang mở.

// ─────────────────────────────────────────────────────────────
// Dữ liệu mẫu
// ─────────────────────────────────────────────────────────────

// Bài không gắn quyền — khách chưa đăng nhập cũng đọc được.
const GL_GROUP_START = {
  id: 'start',
  title: 'Bắt đầu',
  hint: 'Không cần đăng nhập',
  items: [
    { id: 'auth-login', label: 'Đăng nhập vào hệ thống' },
    { id: 'auth-forgot', label: 'Quên mật khẩu' },
    { id: 'auth-change', label: 'Đổi mật khẩu lần đầu' },
  ],
};

// Bài gắn mã quyền — chỉ hiện khi phiên đăng nhập có mã tương ứng.
const GL_GROUPS_SIGNED_IN = [
  GL_GROUP_START,
  {
    id: 'my-info', title: 'Hồ sơ của tôi', perm: 'data:employees:own',
    items: [
      { id: 'pim-view', label: 'Xem hồ sơ cá nhân' },
      { id: 'pim-request', label: 'Gửi yêu cầu sửa thông tin' },
      { id: 'pim-address', label: 'Cập nhật địa chỉ liên hệ' },
    ],
  },
  {
    id: 'leave', title: 'Nghỉ phép', perm: 'screen:leave',
    items: [
      { id: 'leave-submit', label: 'Tạo đơn xin nghỉ phép' },
      { id: 'leave-balance', label: 'Xem số dư ngày phép' },
      { id: 'leave-cancel', label: 'Huỷ đơn đã gửi' },
    ],
  },
  {
    id: 'attendance', title: 'Chấm công', perm: 'screen:attendance',
    items: [
      { id: 'att-punch', label: 'Chấm công vào và ra' },
      { id: 'att-correct', label: 'Xin điều chỉnh giờ chấm công' },
    ],
  },
  {
    id: 'timesheet', title: 'Bảng công', perm: 'screen:timesheet',
    items: [
      { id: 'ts-entry', label: 'Nhập giờ làm theo dự án' },
      { id: 'ts-submit', label: 'Gửi bảng công tuần' },
    ],
  },
  {
    id: 'account', title: 'Tài khoản của tôi', perm: 'data:employees:own',
    items: [
      { id: 'acc-language', label: 'Đổi ngôn ngữ hiển thị' },
      { id: 'acc-sessions', label: 'Quản lý phiên đăng nhập' },
    ],
  },
];

const GL_ART_LEAVE = {
  crumbs: ['Trung tâm Trợ giúp', 'Nghỉ phép'],
  title: 'Tạo đơn xin nghỉ phép',
  audience: 'Dành cho mọi nhân viên đã đăng nhập',
  summary: 'Cách gửi một đơn nghỉ phép, xem số ngày còn lại và theo dõi trạng thái duyệt.',
  steps: [
    'Mở Nghỉ phép, chọn thẻ Đơn của tôi rồi bấm Tạo đơn.',
    'Chọn loại phép. Số ngày còn lại của loại phép đó hiện ngay bên dưới ô chọn.',
    'Chọn khoảng ngày nghỉ. Ngày lễ và ngày cuối tuần không bị tính vào số ngày trừ.',
    'Nhập lý do, đính kèm giấy tờ nếu loại phép đó yêu cầu.',
    'Bấm Gửi đơn. Đơn chuyển sang trạng thái Chờ duyệt và người duyệt nhận thông báo.',
  ],
  fields: [
    ['Loại phép', 'required', 'Chỉ hiện loại phép bạn còn hạn mức trong kỳ hiện tại'],
    ['Từ ngày, Đến ngày', 'required', 'Không chọn ngày trong quá khứ. Đơn từ 3 ngày trở lên cần gửi trước 5 ngày làm việc'],
    ['Nghỉ nửa ngày', 'optional', 'Chỉ bật được khi Từ ngày và Đến ngày trùng nhau'],
    ['Lý do', 'required', 'Tối đa 500 ký tự'],
    ['Tệp đính kèm', 'conditional', 'Tuỳ loại phép. PDF hoặc ảnh, mỗi tệp tối đa 5 MB'],
  ],
  callouts: [
    ['tip', 'Xem trước khi tạo đơn', 'Mở Nghỉ phép, thẻ Số dư phép để biết còn bao nhiêu ngày ở từng loại phép.'],
    ['important', 'Đơn đã duyệt thì không sửa được', 'Cần đổi ngày hay lý do thì huỷ đơn rồi tạo đơn mới.'],
    ['warning', 'Huỷ muộn không hoàn ngày', 'Huỷ đơn sau ngày bắt đầu nghỉ sẽ không hoàn lại số ngày đã trừ.'],
  ],
  faqs: [
    ['Tôi gửi đơn nhưng người duyệt không thấy?',
      'Người duyệt là trưởng đơn vị của bạn. Nếu đơn vị chưa gán trưởng đơn vị thì đơn không có người nhận — liên hệ bộ phận nhân sự để gán.'],
    ['Vì sao tôi không chọn được loại phép nào?',
      'Hạn mức của kỳ chưa được cấp, hoặc bạn đã dùng hết. Mở thẻ Số dư phép để đối chiếu.'],
    ['Nghỉ nửa ngày có trừ 0,5 ngày không?',
      'Có. Số ngày trừ hiện ngay trên đơn trước khi bạn bấm Gửi.'],
    ['Tôi sửa được đơn đang Chờ duyệt không?',
      'Được. Mở đơn rồi bấm Sửa. Sau khi đơn được duyệt thì phải huỷ và tạo lại.'],
  ],
};

const GL_ART_LOGIN = {
  crumbs: ['Trung tâm Trợ giúp', 'Bắt đầu'],
  title: 'Đăng nhập vào hệ thống',
  audience: 'Không cần đăng nhập để đọc bài này',
  summary: 'Cách đăng nhập lần đầu, và xử lý khi không vào được.',
  steps: [
    'Mở địa chỉ hệ thống mà bộ phận nhân sự cấp cho bạn.',
    'Nhập email công việc và mật khẩu.',
    'Bấm Đăng nhập. Lần đầu vào, hệ thống yêu cầu bạn đổi mật khẩu trước khi dùng tiếp.',
  ],
  fields: [
    ['Email', 'required', 'Dùng email công việc do công ty cấp, không dùng email cá nhân'],
    ['Mật khẩu', 'required', 'Tối thiểu 8 ký tự, có chữ hoa, chữ thường và số'],
  ],
  callouts: [
    ['important', 'Sai mật khẩu 5 lần thì tài khoản bị khoá tạm thời',
      'Chờ hết thời gian khoá rồi thử lại, hoặc liên hệ bộ phận nhân sự để mở sớm.'],
    ['tip', 'Chưa nhận được email kích hoạt?',
      'Kiểm tra hộp thư rác trước. Sau đó nhờ bộ phận nhân sự gửi lại lời mời.'],
  ],
  faqs: [
    ['Tôi quên mật khẩu thì làm sao?',
      'Bấm Quên mật khẩu ở màn đăng nhập, nhập email công việc. Hệ thống gửi liên kết đặt lại mật khẩu, liên kết có hiệu lực trong 30 phút.'],
    ['Tôi đã thôi việc nhưng vẫn cần xem dữ liệu cũ?',
      'Tài khoản bị khoá khi hợp đồng chấm dứt. Liên hệ bộ phận nhân sự để được trích xuất dữ liệu cần thiết.'],
  ],
};

// ─────────────────────────────────────────────────────────────
// Khối dùng lại
// ─────────────────────────────────────────────────────────────

// Khung standalone của trang công khai — thay cho HRMTopbar (trang nằm ngoài app shell).
const GLPublicHeader = ({ signedIn }) => (
  <header className="flex h-14 shrink-0 items-center gap-3 border-b border-border bg-card px-6">
    <ElsLogoMark size={30} />
    <div className="flex items-baseline gap-2">
      <span className="text-md font-extrabold tracking-[-0.02em] text-foreground">Trung tâm Trợ giúp</span>
      <span className="text-xs text-muted-foreground">ELS HRM</span>
    </div>
    <div className="flex-1" />
    {/* Bộ chọn ngôn ngữ của trang này KHÔNG dùng lại LanguageMenu của header app: LanguageMenu
        luôn gọi PATCH /me/settings nên khách chưa đăng nhập nhận 401 mỗi lần đổi ngôn ngữ.
        Đã hiện thực (HRM-498): LUÔN setLanguage() — áp ngay + ghi cache localStorage theo §3.2
        nhánh 2 — và CHỈ khi có session mới gọi thêm PATCH để lưu về server.
        Thứ tự nhãn theo hằng LANGUAGE_OPTIONS của lib/i18n: VI, EN, ZH. */}
    <div className="flex items-center gap-0.5 rounded-md border border-border p-0.5">
      {['VI', 'EN', 'ZH'].map((code) => (
        <span key={code}
          className={'cursor-pointer rounded-sm px-2 py-1 text-xs font-semibold '
            + (code === 'VI' ? 'bg-primary text-primary-foreground' : 'text-muted-foreground hover:bg-accent')}>
          {code}
        </span>
      ))}
    </div>
    {signedIn
      ? <Btn variant="outline" size="sm" icon="arrow-right">Về ứng dụng</Btn>
      : <Btn variant="primary" size="sm" icon="lock">Đăng nhập</Btn>}
  </header>
);

const GLSearchBox = ({ value, results }) => (
  <div className="relative">
    <Icon name="search" size={14}
      className="pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground" />
    <input
      className="h-9 w-full rounded-md border border-input bg-transparent pl-9 pr-3 text-sm text-foreground shadow-xs placeholder:text-muted-foreground focus:border-primary focus:outline-none focus:ring-[3px] focus:ring-ring"
      value={value || ''}
      placeholder="Tìm bài viết hoặc câu hỏi..." />
    {results != null && value
      && <div className="mt-1.5 text-xs text-muted-foreground">{results} kết quả cho “{value}”</div>}
  </div>
);

const GLSidebar = ({ groups, activeId, note }) => (
  <aside className="flex w-64 shrink-0 flex-col gap-1 overflow-y-auto border-r border-border bg-card px-3 py-3">
    {groups.map((g) => (
      <div key={g.id} className="pb-1.5">
        <div className="flex items-baseline gap-1.5 px-2 pb-1 pt-1.5">
          <span className="text-2xs font-bold uppercase tracking-[0.1em] text-muted-foreground">{g.title}</span>
          {g.hint && <span className="text-2xs text-muted-foreground/70">· {g.hint}</span>}
        </div>
        {/* Mã quyền hiện cạnh nhóm CHỈ trong bản thiết kế, để người hiện thực biết
            gắn đúng mã. Giao diện thật không hiện mã quyền cho người dùng. */}
        {g.perm && (
          <div className="mb-0.5 px-2">
            <span className="rounded-sm bg-muted px-1.5 py-0.5 font-mono text-2xs text-muted-foreground">{g.perm}</span>
          </div>
        )}
        {g.items.map((it) => {
          const on = it.id === activeId;
          return (
            <div key={it.id}
              className={'my-px cursor-pointer rounded-sm px-2.5 py-[7px] text-sm '
                + (on ? 'bg-primary-soft font-semibold text-primary' : 'font-medium text-foreground hover:bg-accent')}>
              {it.label}
            </div>
          );
        })}
      </div>
    ))}
    {note && (
      <div className="mt-1 rounded-md border border-dashed border-border bg-muted/60 px-3 py-2.5">
        <div className="flex gap-2">
          <Icon name="lock" size={13} className="mt-px shrink-0 text-muted-foreground" />
          <span className="text-xs leading-[1.45] text-muted-foreground">{note}</span>
        </div>
      </div>
    )}
  </aside>
);

const GL_CALLOUT = {
  tip: { box: 'border-info/25 bg-info-soft', ic: 'info', icColor: 'text-info', label: 'Gợi ý' },
  important: { box: 'border-warning/30 bg-warning-soft', ic: 'alert-circle', icColor: 'text-[oklch(0.55_0.158_65)]', label: 'Lưu ý' },
  warning: { box: 'border-destructive/25 bg-destructive-soft', ic: 'alert-triangle', icColor: 'text-destructive', label: 'Cảnh báo' },
};

const GLCallout = ({ kind, title, children, compact }) => {
  const c = GL_CALLOUT[kind] || GL_CALLOUT.tip;
  return (
    <div className={'flex gap-2.5 rounded-md border px-3 ' + (compact ? 'py-2 ' : 'py-2.5 ') + c.box}>
      <Icon name={c.ic} size={15} className={'mt-px shrink-0 ' + c.icColor} />
      <div className="min-w-0">
        <div className="flex items-baseline gap-1.5">
          <span className={'text-2xs font-bold uppercase tracking-[0.08em] ' + c.icColor}>{c.label}</span>
          <span className="text-sm font-semibold text-foreground">{title}</span>
        </div>
        {children && <div className="mt-0.5 text-sm leading-[1.5] text-foreground/80">{children}</div>}
      </div>
    </div>
  );
};

// Số bước vẽ trong ô tròn ở bản thiết kế. Bản hiện thực (HRM-497) dùng <ol> có list-decimal để
// trình duyệt tự đánh số: xoá/chèn một bước không làm các số còn lại lệch, và trình đọc màn hình
// đọc đúng "1 trên 3". Khác biệt này là TRANG TRÍ, không phải lệch thiết kế.
const GLSteps = ({ steps, dense }) => (
  <ol className="flex flex-col gap-2">
    {steps.map((s, i) => (
      <li key={i} className="flex gap-2.5">
        <span className="mt-px grid size-[20px] shrink-0 place-items-center rounded-full bg-primary-soft text-2xs font-bold text-primary">
          {i + 1}
        </span>
        <span className={(dense ? 'text-xs' : 'text-sm') + ' leading-[1.55] text-foreground'}>{s}</span>
      </li>
    ))}
  </ol>
);

// Mức bắt buộc của một trường là MÃ, không phải câu tiếng Việt: nhãn hiện lên và màu badge tra từ
// bảng này. Bản hiện thực (HRM-498) giữ đúng cách đó — `requirement: 'required' | 'optional' |
// 'conditional'`, nhãn đi qua t(). Nếu để câu tiếng Việt rồi so chuỗi để chọn màu thì badge tô
// đúng ở tiếng Việt nhưng sai ngay ở tiếng Anh và tiếng Trung, và lỗi chỉ lộ khi đổi ngôn ngữ.
const GL_REQUIREMENT = {
  required: { label: 'Bắt buộc', variant: 'danger' },
  optional: { label: 'Không', variant: 'neutral' },
  conditional: { label: 'Tuỳ điều kiện', variant: 'warning' },
};

const GLFieldTable = ({ rows }) => (
  <div className="overflow-hidden rounded-md border border-border">
    <table className="w-full border-collapse text-left">
      <thead>
        <tr className="bg-muted">
          {['Trường', 'Bắt buộc', 'Quy định nhập liệu'].map((h, i) => (
            <th key={i} className="px-3 py-2 text-2xs font-bold uppercase tracking-[0.06em] text-muted-foreground">{h}</th>
          ))}
        </tr>
      </thead>
      <tbody>
        {rows.map((r, i) => {
          const req = GL_REQUIREMENT[r[1]] || GL_REQUIREMENT.optional;
          return (
            <tr key={i} className={i > 0 ? 'border-t border-border' : ''}>
              <td className="w-[26%] px-3 py-2 text-sm font-medium text-foreground">{r[0]}</td>
              <td className="w-[16%] px-3 py-2">
                <Badge variant={req.variant}>{req.label}</Badge>
              </td>
              <td className="px-3 py-2 text-sm leading-[1.5] text-foreground/80">{r[2]}</td>
            </tr>
          );
        })}
      </tbody>
    </table>
  </div>
);

// Accordion tự viết: components/ui/ của hrm-admin KHÔNG có primitive Accordion.
// Nút phải là <button>, có aria-expanded + aria-controls (xem HRM-497).
const GLFaq = ({ items, openIdx = 0 }) => (
  <div className="flex flex-col gap-1.5">
    {items.map((f, i) => {
      const open = i === openIdx;
      return (
        <div key={i} className="overflow-hidden rounded-md border border-border bg-card">
          <button type="button" aria-expanded={open} aria-controls={'gl-faq-p-' + i}
            className="flex w-full cursor-pointer items-center gap-2.5 px-3 py-2.5 text-left hover:bg-accent">
            <Icon name={open ? 'chevron-down' : 'chevron-right'} size={14} className="shrink-0 text-muted-foreground" />
            <span className="flex-1 text-sm font-semibold text-foreground">{f[0]}</span>
          </button>
          {open && (
            <div id={'gl-faq-p-' + i} className="border-t border-border px-3 py-2.5 pl-[2.3rem]">
              <p className="text-sm leading-[1.55] text-foreground/80">{f[1]}</p>
            </div>
          )}
        </div>
      );
    })}
  </div>
);

const GLArticle = ({ art, openFaq }) => (
  <div className="mx-auto flex max-w-[46rem] flex-col gap-5 px-8 py-6">
    <div>
      <div className="mb-2 flex items-center gap-1.5 text-xs text-muted-foreground">
        {art.crumbs.map((c, i) => (
          <React.Fragment key={i}>
            {i > 0 && <Icon name="chevron-right" size={10} />}
            <span className={i === art.crumbs.length - 1 ? 'font-medium text-foreground' : 'cursor-pointer'}>{c}</span>
          </React.Fragment>
        ))}
      </div>
      <h1 className="text-2xl font-bold tracking-[-0.015em] text-foreground">{art.title}</h1>
      {/* Diễn đạt theo VIỆC LÀM ĐƯỢC, không liệt kê tên vai trò (HRM-497). */}
      <div className="mt-1.5 flex items-center gap-2">
        <Icon name="user" size={13} className="text-muted-foreground" />
        <span className="text-xs font-medium text-muted-foreground">{art.audience}</span>
      </div>
      <p className="mt-3 text-md leading-[1.55] text-foreground/85">{art.summary}</p>
    </div>

    <section className="flex flex-col gap-2.5">
      <h2 className="text-md font-bold text-foreground">Các bước thực hiện</h2>
      <GLSteps steps={art.steps} />
    </section>

    <section className="flex flex-col gap-2.5">
      <h2 className="text-md font-bold text-foreground">Quy định thông tin nhập vào</h2>
      <GLFieldTable rows={art.fields} />
    </section>

    <section className="flex flex-col gap-2">
      {art.callouts.map((c, i) => <GLCallout key={i} kind={c[0]} title={c[1]}>{c[2]}</GLCallout>)}
    </section>

    <section className="flex flex-col gap-2.5">
      <h2 className="text-md font-bold text-foreground">Câu hỏi thường gặp</h2>
      <GLFaq items={art.faqs} openIdx={openFaq} />
    </section>
  </div>
);

// ─────────────────────────────────────────────────────────────
// 01 — Trang công khai, khách CHƯA đăng nhập
// ─────────────────────────────────────────────────────────────
const GuidelinesPublicAnonScreen = () => (
  <div className="flex h-full w-full flex-col overflow-hidden bg-background font-sans text-foreground">
    <GLPublicHeader signedIn={false} />
    <div className="flex min-h-0 flex-1">
      <div className="flex w-64 shrink-0 flex-col border-r border-border bg-card">
        <div className="border-b border-border p-3"><GLSearchBox /></div>
        <GLSidebar
          groups={[GL_GROUP_START]}
          activeId="auth-login"
          note="Đăng nhập để xem hướng dẫn cho những phần bạn được dùng: Nghỉ phép, Chấm công, Bảng công, Hồ sơ của tôi." />
      </div>
      <div className="min-w-0 flex-1 overflow-y-auto">
        <GLArticle art={GL_ART_LOGIN} openFaq={0} />
      </div>
    </div>
  </div>
);

// ─────────────────────────────────────────────────────────────
// 02 — Trang công khai, ĐÃ đăng nhập (đủ bài theo mã quyền)
// ─────────────────────────────────────────────────────────────
const GuidelinesPublicFullScreen = () => (
  <div className="flex h-full w-full flex-col overflow-hidden bg-background font-sans text-foreground">
    <GLPublicHeader signedIn />
    <div className="flex min-h-0 flex-1">
      <div className="flex w-64 shrink-0 flex-col border-r border-border bg-card">
        <div className="border-b border-border p-3"><GLSearchBox /></div>
        <GLSidebar groups={GL_GROUPS_SIGNED_IN} activeId="leave-submit" />
      </div>
      <div className="min-w-0 flex-1 overflow-y-auto">
        <GLArticle art={GL_ART_LEAVE} openFaq={0} />
      </div>
    </div>
  </div>
);

// ─────────────────────────────────────────────────────────────
// 03 — Kết quả tìm kiếm (gõ KHÔNG dấu vẫn khớp bài có dấu)
// ─────────────────────────────────────────────────────────────
const GL_HITS_ARTICLES = [
  ['Nghỉ phép', 'Tạo đơn xin nghỉ phép', 'Cách gửi một đơn nghỉ phép, xem số ngày còn lại và theo dõi trạng thái duyệt.'],
  ['Nghỉ phép', 'Xem số dư ngày phép', 'Số ngày còn lại theo từng loại phép trong kỳ hiện tại.'],
  ['Nghỉ phép', 'Huỷ đơn đã gửi', 'Điều kiện huỷ và ảnh hưởng tới số ngày đã trừ.'],
];
const GL_HITS_FAQ = [
  ['Nghỉ phép', 'Nghỉ nửa ngày có trừ 0,5 ngày không?'],
  ['Nghỉ phép', 'Tôi sửa được đơn đang Chờ duyệt không?'],
];

const GuidelinesSearchScreen = () => (
  <div className="flex h-full w-full flex-col overflow-hidden bg-background font-sans text-foreground">
    <GLPublicHeader signedIn />
    <div className="flex min-h-0 flex-1">
      <div className="flex w-64 shrink-0 flex-col border-r border-border bg-card">
        <div className="border-b border-border p-3"><GLSearchBox value="nghi phep" results={5} /></div>
        <GLSidebar groups={GL_GROUPS_SIGNED_IN} activeId={null} />
      </div>
      <div className="min-w-0 flex-1 overflow-y-auto">
        <div className="mx-auto flex max-w-[46rem] flex-col gap-5 px-8 py-6">
          <div>
            <h1 className="text-xl font-bold tracking-[-0.015em] text-foreground">Kết quả tìm kiếm</h1>
            <p className="mt-1.5 text-sm text-muted-foreground">
              5 kết quả cho “nghi phep” — tìm trong ngôn ngữ đang hiển thị (Tiếng Việt).
            </p>
          </div>

          <GLCallout kind="tip" title="Gõ không dấu vẫn tìm được" compact>
            Từ khoá được bỏ dấu trước khi so khớp, nên “nghi phep” khớp “nghỉ phép”.
          </GLCallout>

          <section className="flex flex-col gap-2.5">
            <h2 className="text-md font-bold text-foreground">Bài viết · 3</h2>
            <div className="flex flex-col gap-1.5">
              {GL_HITS_ARTICLES.map((h, i) => (
                <div key={i} className="cursor-pointer rounded-md border border-border bg-card px-3 py-2.5 hover:border-primary/40 hover:bg-accent">
                  <div className="flex items-center gap-2">
                    <Badge variant="neutral">{h[0]}</Badge>
                    <span className="text-sm font-semibold text-foreground">{h[1]}</span>
                  </div>
                  <p className="mt-1 text-xs leading-[1.5] text-muted-foreground">{h[2]}</p>
                </div>
              ))}
            </div>
          </section>

          <section className="flex flex-col gap-2.5">
            <h2 className="text-md font-bold text-foreground">Câu hỏi thường gặp · 2</h2>
            <div className="flex flex-col gap-1.5">
              {GL_HITS_FAQ.map((h, i) => (
                <div key={i} className="flex cursor-pointer items-center gap-2 rounded-md border border-border bg-card px-3 py-2.5 hover:border-primary/40 hover:bg-accent">
                  <Icon name="message-square" size={14} className="shrink-0 text-muted-foreground" />
                  <Badge variant="neutral">{h[0]}</Badge>
                  <span className="text-sm font-medium text-foreground">{h[1]}</span>
                </div>
              ))}
            </div>
          </section>
        </div>
      </div>
    </div>
  </div>
);

// ─────────────────────────────────────────────────────────────
// Quick-help drawer trong app shell
// ─────────────────────────────────────────────────────────────

// Bản hiện thực (HRM-498) KHÔNG vẽ lại khung này: nó dựng trên `Modal` của
// components/ui/dialog.tsx và chỉ đổi hình dáng panel (dán phải, cao hết màn hình). Lý do: Esc,
// bẫy tiêu điểm, khoá cuộn trang nền, role="dialog" + aria-modal và trả tiêu điểm khi đóng đều đã
// đúng ở Modal; nhân bản sang component thứ hai nghĩa là hai bản a11y phải sửa song song, mà bản
// sao sẽ là bản bị quên. Trong project thiết kế thì vẫn vẽ tay vì ở đây không có primitive Modal.
const GLDrawerShell = ({ subtitle, children, footer }) => (
  <>
    <div className="absolute inset-0 z-40 bg-black/40" />
    <aside role="dialog" aria-modal="true"
      className="absolute inset-y-0 right-0 z-50 flex w-[26rem] flex-col border-l border-border bg-card shadow-2xl">
      <div className="flex shrink-0 items-start gap-2.5 border-b border-border px-4 py-3">
        <Icon name="help-circle" size={17} className="mt-px shrink-0 text-primary" />
        <div className="min-w-0 flex-1">
          <div className="text-sm font-bold text-foreground">Hướng dẫn cho trang này</div>
          <div className="mt-px overflow-hidden text-ellipsis whitespace-nowrap text-xs text-muted-foreground">{subtitle}</div>
        </div>
        <div title="Đóng (Esc)" className="grid size-7 shrink-0 cursor-pointer place-items-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground">
          <Icon name="x" size={15} />
        </div>
      </div>
      <div className="min-h-0 flex-1 overflow-y-auto px-4 py-3.5">{children}</div>
      <div className="flex shrink-0 items-center justify-between gap-2 border-t border-border px-4 py-2.5">{footer}</div>
    </aside>
  </>
);

// Nội dung trang nền — chỉ để drawer có gì mà phủ lên.
const GLBackdropForm = () => (
  <div className="flex flex-col gap-3">
    <div className="rounded-lg border border-border bg-card p-4">
      <div className="mb-3 text-sm font-bold text-foreground">Thông tin đơn</div>
      <div className="grid grid-cols-2 gap-3">
        {['Loại phép', 'Số ngày trừ', 'Từ ngày', 'Đến ngày'].map((l) => (
          <div key={l} className="flex flex-col gap-1.5">
            <span className="text-xs font-medium text-foreground">{l}</span>
            <div className="h-9 rounded-md border border-input bg-muted/50" />
          </div>
        ))}
      </div>
      <div className="mt-3 flex flex-col gap-1.5">
        <span className="text-xs font-medium text-foreground">Lý do</span>
        <div className="h-20 rounded-md border border-input bg-muted/50" />
      </div>
    </div>
  </div>
);

// ─────────────────────────────────────────────────────────────
// 04 — Drawer KHỚP đường dẫn hiện tại (/leave/me/submit)
// ─────────────────────────────────────────────────────────────
const GuidelinesDrawerMatchScreen = () => (
  <div className="relative flex h-full w-full overflow-hidden bg-background font-sans text-foreground">
    <HRMSidebar active="leave" />
    <div className="flex min-w-0 flex-1 flex-col">
      <HRMTopbar helpActive />
      <HRMPageTitle title="Tạo đơn nghỉ phép" crumbs={['Nghỉ phép', 'Đơn của tôi', 'Tạo đơn']} />
      <div className="flex-1 overflow-auto bg-background p-5"><GLBackdropForm /></div>
    </div>
    <GLDrawerShell
      subtitle="Khớp đường dẫn /leave/me/submit"
      footer={
        <>
          <span className="text-xs text-muted-foreground">Nghỉ phép</span>
          <Btn variant="outline" size="sm" iconRight="arrow-right">Mở Trung tâm Trợ giúp</Btn>
        </>
      }>
      <div className="flex flex-col gap-3.5">
        <div>
          <h2 className="text-md font-bold leading-tight text-foreground">{GL_ART_LEAVE.title}</h2>
          <p className="mt-1.5 text-xs leading-[1.55] text-foreground/80">{GL_ART_LEAVE.summary}</p>
        </div>
        <div className="flex flex-col gap-2">
          <span className="text-2xs font-bold uppercase tracking-[0.08em] text-muted-foreground">Các bước</span>
          <GLSteps steps={GL_ART_LEAVE.steps} dense />
        </div>
        <GLCallout kind="important" title="Đơn đã duyệt thì không sửa được" compact>
          Cần đổi ngày hay lý do thì huỷ đơn rồi tạo đơn mới.
        </GLCallout>
        <div className="flex flex-col gap-1.5">
          <span className="text-2xs font-bold uppercase tracking-[0.08em] text-muted-foreground">Câu hỏi thường gặp</span>
          <GLFaq items={GL_ART_LEAVE.faqs.slice(0, 3)} openIdx={-1} />
        </div>
      </div>
    </GLDrawerShell>
  </div>
);

// ─────────────────────────────────────────────────────────────
// 05 — Drawer KHÔNG khớp đường dẫn (/roles) — không đoán bài gần nhất
// ─────────────────────────────────────────────────────────────
const GuidelinesDrawerNoMatchScreen = () => (
  <div className="relative flex h-full w-full overflow-hidden bg-background font-sans text-foreground">
    <HRMSidebar active="rbac" />
    <div className="flex min-w-0 flex-1 flex-col">
      <HRMTopbar helpActive />
      <HRMPageTitle title="Vai trò và quyền" crumbs={['Hệ thống', 'Vai trò và quyền']} />
      <div className="flex-1 overflow-auto bg-background p-5">
        <div className="rounded-lg border border-border bg-card p-4">
          <div className="mb-3 text-sm font-bold text-foreground">Danh sách vai trò</div>
          <div className="flex flex-col gap-2">
            {[0, 1, 2, 3].map((i) => <div key={i} className="h-9 rounded-md border border-border bg-muted/40" />)}
          </div>
        </div>
      </div>
    </div>
    <GLDrawerShell
      subtitle="Không có bài nào khai đường dẫn /roles"
      footer={
        <>
          <span className="text-xs text-muted-foreground">Chưa có bài cho trang này</span>
          <Btn variant="primary" size="sm" iconRight="arrow-right">Mở Trung tâm Trợ giúp</Btn>
        </>
      }>
      <div className="flex flex-col gap-3.5">
        <GLCallout kind="tip" title="Chưa có hướng dẫn riêng cho trang này">
          Giai đoạn 1 chỉ có bài cho 6 nhóm dành cho người dùng cuối. Dưới đây là các bài bạn xem được.
        </GLCallout>
        <div className="flex flex-col gap-2">
          <span className="text-2xs font-bold uppercase tracking-[0.08em] text-muted-foreground">Bài bạn xem được</span>
          {GL_GROUPS_SIGNED_IN.map((g) => (
            <div key={g.id} className="rounded-md border border-border bg-background px-3 py-2">
              <div className="mb-1 text-xs font-bold text-foreground">{g.title}</div>
              {g.items.map((it) => (
                <div key={it.id} className="flex cursor-pointer items-center gap-1.5 py-0.5 text-xs text-foreground/80 hover:text-primary">
                  <Icon name="chevron-right" size={11} className="shrink-0 text-muted-foreground" />
                  <span>{it.label}</span>
                </div>
              ))}
            </div>
          ))}
        </div>
      </div>
    </GLDrawerShell>
  </div>
);

Object.assign(window, {
  GuidelinesPublicAnonScreen,
  GuidelinesPublicFullScreen,
  GuidelinesSearchScreen,
  GuidelinesDrawerMatchScreen,
  GuidelinesDrawerNoMatchScreen,
});
