// hr-pages.jsx — Персонал: Профілі · Час · Відпустки · Документи

// ============ ПРОФІЛІ ============
function ProfilesPage({ tasks, role, onPromote, onGoToTasks }) {
  const team = window.DATA.TEAM;
  const [openId, setOpenId] = React.useState(null);
  const [certFor, setCertFor] = React.useState(null); // людина для довідки про доходи
  const [view, setView] = React.useState("table"); // table | cards
  const canSeeSalary = role === "director" || role === "accountant";

  // КЕП, що потребують уваги (для шапки)
  const kepExpiring = team.filter(p => p.kep && window.kepStatus(p.kep.validUntil).state === "expiring").length;
  const kepExpired  = team.filter(p => p.kep && window.kepStatus(p.kep.validUntil).state === "expired").length;

  // Сортування
  const [sort, setSort] = React.useState("role");
  const sorted = React.useMemo(() => {
    const arr = [...team];
    if (sort === "name") arr.sort((a,b) => a.name.localeCompare(b.name));
    if (sort === "load") arr.sort((a,b) => b.load - a.load);
    if (sort === "role") arr.sort((a,b) => a.role.localeCompare(b.role));
    return arr;
  }, [sort]);

  return (
    <div className="page">
      <div className="page-head">
        <h1 className="page-h1">Профілі</h1>
        <div className="page-sub">
          <span>{team.length} {window.plural(team.length, "людина", "людини", "людей")} у штаті</span>
          <span className="dot"></span>
          <span>{team.filter(t => t.employment === "staff").length} штат</span>
          <span className="dot"></span>
          <span>{team.filter(t => t.employment === "part").length} часткова</span>
          <span className="dot"></span>
          <span>{team.filter(t => t.employment === "contractor").length} субпідряд</span>
          {(kepExpiring + kepExpired) > 0 && <>
            <span className="dot"></span>
            <span style={{color: kepExpired > 0 ? "var(--late)" : "var(--warn, #b8860b)"}}>
              <window.Ico name="lock" size={13} style={{verticalAlign: "-0.15em"}} /> {kepExpired > 0 ? `${kepExpired} КЕП прострочено` : `${kepExpiring} КЕП завершується`}
            </span>
          </>}
        </div>
      </div>

      <div className="toolbar">
        <div className="filter-pill" role="tablist">
          <button className={`filter-pill-item ${sort === "role" ? "is-active" : ""}`} onClick={() => setSort("role")}>За роллю</button>
          <button className={`filter-pill-item ${sort === "name" ? "is-active" : ""}`} onClick={() => setSort("name")}>За прізвищем</button>
          <button className={`filter-pill-item ${sort === "load" ? "is-active" : ""}`} onClick={() => setSort("load")}>За завантаженням</button>
        </div>

        <div className="filter-pill" role="tablist" style={{marginLeft: "auto"}}>
          <button className={`filter-pill-item ${view === "table" ? "is-active" : ""}`} onClick={() => setView("table")}>Таблиця</button>
          <button className={`filter-pill-item ${view === "cards" ? "is-active" : ""}`} onClick={() => setView("cards")}>Картки</button>
        </div>
      </div>

      {view === "table" && (
        <table className="data-table">
          <thead>
            <tr>
              <th></th>
              <th>Прізвище ім'я</th>
              <th>Статус</th>
              <th>Активних задач</th>
              <th>Завантаження</th>
              <th>КЕП</th>
              <th>Телефон</th>
              <th>Email</th>
              <th></th>
            </tr>
          </thead>
          <tbody>
            {sorted.map(p => {
              const empl = window.EMPLOYMENT_LABELS[p.employment];
              const active = tasks.filter(t => t.assignee === p.id && t.status !== "done").length;
              const late = tasks.filter(t => t.assignee === p.id && t.status === "late").length;
              return (
                <tr key={p.id} onClick={() => setOpenId(p.id)} className="is-clickable">
                  <td>
                    <div className="team-avatar" style={{width: 32, height: 32, fontSize: 11.5}}>{p.initials}</div>
                  </td>
                  <td>
                    <div className="cell-name">{p.name}</div>
                    <div className="cell-sub">{p.role}</div>
                  </td>
                  <td>
                    <span className={`empl-chip empl-${p.employment}`}>{empl?.label}</span>
                  </td>
                  <td>
                    <span style={{fontVariantNumeric: "tabular-nums", fontWeight: 500}}>{active}</span>
                    {late > 0 && <span style={{color: "var(--late)", fontSize: 11, marginLeft: 6, fontWeight: 600}}>+{late} прострочено</span>}
                  </td>
                  <td>
                    <div className="load-bar">
                      <div className="load-bar-track">
                        <div
                          className={`load-bar-fill ${p.load >= 90 ? "is-high" : ""}`}
                          style={{width: p.load + "%"}}
                        ></div>
                      </div>
                      <span className="load-bar-val">{p.load}%</span>
                    </div>
                  </td>
                  <td>
                    <KepCell person={p} />
                  </td>
                  <td className="td-mono" style={{whiteSpace: "nowrap"}}>{p.phone}</td>
                  <td style={{whiteSpace: "nowrap"}}>
                    <a href={`mailto:${p.email}`} className="td-link" onClick={(e) => e.stopPropagation()}>{p.email}</a>
                  </td>
                  <td>
                    <button className="btn btn-ghost" style={{padding: "4px 8px"}}>Відкрити →</button>
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      )}

      {view === "cards" && (
        <div className="profile-grid">
          {sorted.map(p => {
            const empl = window.EMPLOYMENT_LABELS[p.employment];
            const active = tasks.filter(t => t.assignee === p.id && t.status !== "done").length;
            return (
              <div key={p.id} className="profile-card" onClick={() => setOpenId(p.id)}>
                <div className="profile-card-head">
                  <div className="team-avatar" style={{width: 48, height: 48, fontSize: 16}}>{p.initials}</div>
                  <span className={`empl-chip empl-${p.employment}`}>{empl?.label}</span>
                </div>
                <div className="profile-card-name">{p.name}</div>
                <div className="profile-card-role">{p.role}</div>
                <div className="profile-card-meta">
                  <div><span>Активних:</span> <b>{active}</b></div>
                  <div><span>Завантаження:</span> <b className={p.load >= 90 ? "high" : ""}>{p.load}%</b></div>
                </div>
                <div className="profile-card-foot">
                  <span>{p.phone}</span>
                  <KepCell person={p} compact />
                </div>
              </div>
            );
          })}
        </div>
      )}

      {openId && (
        <ProfileDrawer
          person={team.find(p => p.id === openId)}
          tasks={tasks}
          canSeeSalary={canSeeSalary}
          onClose={() => setOpenId(null)}
          onIssueCert={(p) => setCertFor(p)}
          onPromote={onPromote}
          onGoToTasks={onGoToTasks}
        />
      )}

      {certFor && (
        <IncomeCertificate person={certFor} onClose={() => setCertFor(null)} />
      )}
    </div>
  );
}

// ============ КЕП — компактний індикатор статусу ============
function KepCell({ person, compact }) {
  const kep = person.kep;
  if (!kep) return <span style={{color: "var(--ink-4)", fontSize: 12}}>—</span>;
  const st = window.kepStatus(kep.validUntil);
  const title = st.state === "expired"
    ? `Прострочено ${formatDate(kep.validUntil)}`
    : `Дійсний до ${formatDate(kep.validUntil)} · залишилось ${st.days} дн.`;
  if (compact) {
    return (
      <span className={`kep-dot-wrap tone-${st.tone}`} title={title}>
        <span className="kep-dot"></span>
        <span>{st.state === "expired" ? "КЕП прострочено" : `до ${shortDate(kep.validUntil)}`}</span>
      </span>
    );
  }
  return (
    <div className="kep-cell" title={title}>
      <span className={`kep-dot-wrap tone-${st.tone}`}>
        <span className="kep-dot"></span>
        <span className="td-mono" style={{fontSize: 11.5}}>{shortDate(kep.validUntil)}</span>
      </span>
      {st.state !== "active" && (
        <span className={`kep-mini-tag tone-${st.tone}`}>
          {st.state === "expired" ? "прострочено" : `${st.days} дн.`}
        </span>
      )}
    </div>
  );
}

// ============ КЕП — секція в профілі з нагадуванням ============
function KepSection({ kep }) {
  const st = window.kepStatus(kep.validUntil);
  return (
    <div className="drawer-section">
      <div className="drawer-section-h" style={{display: "flex", alignItems: "center", justifyContent: "space-between"}}>
        <span>КЕП — електронний підпис</span>
        <span className={`status-tag tone-${st.tone}`}>{st.label}</span>
      </div>

      <div className={`kep-banner tone-${st.tone}`}>
        <div className="kep-banner-icon"><window.Ico name="lock" /></div>
        <div style={{flex: 1, minWidth: 0}}>
          <div className="kep-banner-title">
            {st.state === "expired"
              ? `Прострочено ${Math.abs(st.days)} дн. тому — потрібно перевипустити`
              : st.state === "expiring"
                ? `Завершується через ${st.days} дн. — час оновити`
                : `Дійсний ще ${st.days} дн.`}
          </div>
          <div className="kep-banner-sub">
            {st.state === "active"
              ? "Сповіщення прийде автоматично за 30 днів до завершення."
              : "Перевипуск через Дія.Підпис або АЦСК провайдера."}
          </div>
        </div>
        {st.state !== "active" && <button className="btn btn-primary" style={{flexShrink: 0}}>Оновити КЕП</button>}
      </div>

      <dl className="info-grid" style={{marginTop: 12}}>
        <div><dt>Тип</dt><dd>{kep.type}</dd></div>
        <div><dt>Провайдер</dt><dd>{kep.provider}</dd></div>
        <div><dt>Серійний №</dt><dd className="td-mono">{kep.serial}</dd></div>
        <div><dt>Видано</dt><dd>{formatDate(kep.issuedDate)}</dd></div>
        <div><dt>Дійсний до</dt><dd className={st.state !== "active" ? "" : ""} style={{color: st.tone === "live" ? "var(--ink)" : "var(--late)", fontWeight: st.state !== "active" ? 600 : 400}}>{formatDate(kep.validUntil)}</dd></div>
      </dl>
    </div>
  );
}

// ============ Кваліфікаційний сертифікат — картка в профілі ============
function QualCertCard({ qc }) {
  const training = window.qualTrainingStatus(qc);
  const cont = window.edessbContinuityStatus(qc);
  const upgrade = window.qualUpgrade(qc);
  return (
    <div className="qual-card">
      <div className="qual-card-head">
        <div style={{minWidth: 0}}>
          <div className="qual-card-kind">{qc.kind}</div>
          <div className="qual-card-sub">№{qc.number}{qc.scope ? ` · ${qc.scope}` : ""}</div>
        </div>
        <QualClassChip cls={qc.class} upgrade={upgrade} />
      </div>

      {upgrade && (
        <div className="qual-upgrade-note">
          Можливе підвищення класу наслідків: <b>{upgrade.current} → {upgrade.next}</b>
        </div>
      )}

      <div className="qual-card-rows">
        <div className={`qual-card-row tone-${training.tone}`}>
          <div className="qual-card-row-main">
            <span className="qual-card-row-label">Підвищення кваліфікації</span>
            <span className="qual-card-row-meta">раз на 5 років · дедлайн {formatDate(training.dueDate)}</span>
          </div>
          <span className={`status-tag tone-${training.tone}`}>
            {training.state === "expired" ? "Прострочено" : training.state === "expiring" ? `${training.days} дн.` : "За графіком"}
          </span>
        </div>
        <div className={`qual-card-row tone-${cont.tone}`}>
          <div className="qual-card-row-main">
            <span className="qual-card-row-label">Безперервність стажу · ЄДЕССБ</span>
            <span className="qual-card-row-meta">щороку · наступне до {formatDate(cont.dueDate)}</span>
          </div>
          <span className={`status-tag tone-${cont.tone}`}>
            {cont.state === "expired" ? "Час подавати" : cont.state === "expiring" ? `${cont.days} дн.` : "Подано"}
          </span>
        </div>
      </div>

      {qc.scan && (
        <div className="qual-card-scan">
          <span className="qual-card-row-label">Сканкопія сертифіката</span>
          <ScanChip scan={qc.scan} />
        </div>
      )}
    </div>
  );
}

// ============ КАР'ЄРА ТА РОЗВИТОК ============
// Драбина інженерної категорії — візуальна шкала
function EngineerLadder({ person }) {
  const ladder = window.ENGINEER_LADDER || [];
  const curRank = (function () {
    const r = (person.positionOfficial || person.role || "").toLowerCase();
    if (/провідн/.test(r)) return 3;
    if (/(іі|ii|2)\s*катег/.test(r)) return 1;
    if (/(і|i|1)\s*катег/.test(r)) return 2;
    return 0;
  })();
  return (
    <div className="career-ladder">
      {ladder.map((step, i) => (
        <div key={i} className={`career-rung ${i === curRank ? "is-current" : ""} ${i < curRank ? "is-passed" : ""}`}>
          <div className="career-rung-dot">{i <= curRank ? <window.Icon.Check /> : null}</div>
          <div className="career-rung-body">
            <div className="career-rung-label">{i === 3 ? "Провідний інженер-проєктувальник" : (i === 0 ? "Без категорії" : `${step.label}`)}</div>
            {step.needs && <div className="career-rung-need">потрібен сертифікат {step.needs}</div>}
          </div>
        </div>
      ))}
    </div>
  );
}

function CareerSection({ person, canSeeSalary, onPromote, onGoToTasks }) {
  const [done, setDone] = React.useState(null);
  const st = window.careerState(person);
  const promo = st.promotion;
  const tpl = promo ? window.getHrProcessTemplate(promo.templateId) : null;
  const part = person.partRate || 1;
  const curOklad = (person.baseSalary || 0) * part;
  const newOklad = curOklad + (promo ? promo.salaryDelta : 0) * part;

  const apply = () => {
    if (!promo) return;
    const summary = {
      kind: promo.kind,
      target: promo.targetPosition,
      delta: promo.salaryDelta,
      tasks: tpl ? tpl.taskTemplateIds.length : 0,
      tplName: tpl ? tpl.name : "",
    };
    onPromote && onPromote(person.id);
    setDone(summary);
  };

  const trackChip = (
    <span className="career-track-chip">{st.trackLabel}</span>
  );

  return (
    <div className="drawer-section">
      <div className="drawer-section-h" style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
        <span>Кар'єра та розвиток</span>
        {trackChip}
      </div>

      {/* Після оформлення */}
      {done && (
        <div className="career-card is-applied">
          <div className="career-card-top">
            <span className="career-badge is-done"><window.Icon.Check /> Оформлено</span>
          </div>
          <div className="career-applied-txt">
            {done.kind === "cert"
              ? <>Нараховано надбавку за кваліфікаційний сертифікат.</>
              : <>Працівника переведено на посаду <b>{done.target}</b>.</>}
            {canSeeSalary && done.delta > 0 && <> Оклад підвищено на <b>{formatMoney(done.delta)} ₴</b>.</>}
          </div>
          <div className="career-applied-sub">
            Створено <b>{done.tasks}</b> {window.plural(done.tasks, "задачу-супровід", "задачі-супровід", "задач-супровід")} ({done.tplName}).
          </div>
          {onGoToTasks && <button className="btn btn-sm" style={{ marginTop: 10 }} onClick={onGoToTasks}>Перейти до задач →</button>}
        </div>
      )}

      {/* Доступне підвищення */}
      {!done && promo && (
        <div className="career-card is-promo">
          <div className="career-card-top">
            <span className="career-badge"><window.Ico name="trending" size={13} /> {promo.badge}</span>
          </div>
          <div className="career-transition">
            <div className="career-pos">
              <span className="career-pos-k">Зараз</span>
              <span className="career-pos-v">{st.currentPosition}</span>
            </div>
            <div className="career-arrow">→</div>
            <div className="career-pos is-target">
              <span className="career-pos-k">{promo.kind === "cert" ? "Посада без змін" : "Нова посада"}</span>
              <span className="career-pos-v">{promo.kind === "cert" ? st.currentPosition : promo.targetPosition}</span>
            </div>
          </div>
          <div className="career-reason">{promo.reason}</div>
          {canSeeSalary && promo.salaryDelta > 0 && (
            <div className="career-salary">
              <span className="career-salary-k">Оклад</span>
              <span className="career-salary-old">{formatMoney(curOklad)} ₴</span>
              <span className="career-arrow sm">→</span>
              <span className="career-salary-new">{formatMoney(newOklad)} ₴</span>
              <span className="career-salary-delta">+{formatMoney(promo.salaryDelta * part)} ₴</span>
            </div>
          )}
          {tpl && (
            <div className="career-tpl">
              <window.Ico name="clipboard" size={13} />
              <span>Оформлення за шаблоном <b>«{tpl.name}»</b> — {tpl.taskTemplateIds.length} {window.plural(tpl.taskTemplateIds.length, "задача", "задачі", "задач")}-супровід</span>
            </div>
          )}
          <button className="btn btn-primary" style={{ marginTop: 12, width: "100%" }} onClick={apply}>
            {promo.kind === "gap" ? "Перевести на посаду ГАП" : promo.kind === "category" ? "Підвищити категорію" : "Нарахувати надбавку"}
          </button>
        </div>
      )}

      {/* Наступний крок (без поточного підвищення) */}
      {!done && !promo && st.nextStep && (
        <div className="career-next">
          <span className="career-next-k">Наступний щабель</span>
          <div className="career-next-txt">{st.nextStep.text}</div>
          <div className="career-next-req">{st.nextStep.requires}</div>
        </div>
      )}

      {/* Вершина / поза прогресією */}
      {!done && !promo && !st.nextStep && (st.topNote || st.note) && (
        <div className="career-note">{st.topNote || st.note}</div>
      )}

      {/* Драбина для інженерів */}
      {st.track === "engineer" && <EngineerLadder person={person} />}

      {/* Історія переходів */}
      {person.careerLog && person.careerLog.length > 0 && (
        <div className="career-log">
          <div className="career-log-h">Історія</div>
          {person.careerLog.map((l, i) => (
            <div key={i} className="career-log-row">
              <span className="career-log-date">{formatDate(l.date)}</span>
              <span className="career-log-txt">{l.kind === "cert" ? "Надбавка за сертифікат" : `${l.from} → ${l.to}`}{l.delta ? `, +${formatMoney(l.delta)} ₴` : ""}</span>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

// ============ DRAWER ПРОФІЛЮ ============
function ProfileDrawer({ person, tasks, canSeeSalary, onClose, onIssueCert, onPromote, onGoToTasks }) {
  const cashVisible = window.useCashVisible();
  React.useEffect(() => {
    const onKey = (e) => e.key === "Escape" && onClose();
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [onClose]);

  if (!person) return null;
  const empl = window.EMPLOYMENT_LABELS[person.employment];
  const active = tasks.filter(t => t.assignee === person.id && t.status !== "done");
  const late = active.filter(t => t.status === "late");
  const vacations = window.DATA.VACATIONS.filter(v => v.who === person.id);
  const career = window.careerState ? window.careerState(person) : null;

  return (
    <>
      <div className="drawer-overlay" onClick={onClose}></div>
      <aside className="drawer" style={{width: "min(680px, 95vw)"}}>
        <div className="drawer-head">
          <button className="drawer-close" onClick={onClose}><window.Icon.X /></button>
          <span className={`empl-chip empl-${person.employment}`}>{empl?.label}</span>
        </div>

        <div className="drawer-body">
          <div style={{display: "flex", alignItems: "center", gap: 16, marginBottom: 20}}>
            <div className="team-avatar" style={{width: 56, height: 56, fontSize: 19}}>{person.initials}</div>
            <div>
              <h1 className="drawer-h1" style={{marginBottom: 4}}>{person.name}</h1>
              <div style={{fontSize: 13, color: "var(--ink-3)", display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap"}}>
                {person.role}
                {person.edessbRegistrar && <span className="status-tag tone-blue">Реєстратор ЄДЕССБ</span>}
              </div>
            </div>
          </div>

          {career && career.promotion && (
            <div className="career-banner">
              <span className="career-banner-dot"></span>
              <span className="career-banner-txt">{career.promotion.badge}</span>
              <span className="career-banner-go">нижче в розділі «Кар'єра» ↓</span>
            </div>
          )}

          <div className="kpi-row" style={{marginBottom: 24, gridTemplateColumns: "repeat(3, 1fr)"}}>
            <div className="kpi"><div className="kpi-label">Активних задач</div><div className="kpi-value">{active.length}</div></div>
            <div className={`kpi ${late.length > 0 ? "is-warn" : ""}`}><div className="kpi-label">Прострочено</div><div className="kpi-value">{late.length}</div></div>
            <div className="kpi"><div className="kpi-label">Завантаження</div><div className="kpi-value">{person.load}%</div></div>
          </div>

          <div className="drawer-section">
            <div className="drawer-section-h">Контакти</div>
            <dl className="info-grid">
              <div><dt>Телефон</dt><dd className="td-mono">{person.phone}</dd></div>
              <div><dt>Email</dt><dd><a className="td-link" href={`mailto:${person.email}`}>{person.email}</a></dd></div>
              <div><dt>Адреса</dt><dd>{person.address}</dd></div>
              <div><dt>День народження</dt><dd>{formatDate(person.birthDate)}</dd></div>
            </dl>
          </div>

          <div className="drawer-section">
            <div className="drawer-section-h">Працевлаштування</div>
            <dl className="info-grid">
              <div><dt>Тип</dt><dd>{empl?.label}</dd></div>
              <div><dt>Офіційна посада</dt><dd>{person.positionOfficial || person.role}</dd></div>
              <div><dt>Прийнято</dt><dd>{formatDate(person.hireDate)}</dd></div>
              <div><dt>Стаж у компанії</dt><dd>{yearsBetween(person.hireDate, window.SYS_DATE)} р.</dd></div>
              <div><dt>Вид договору</dt><dd>{person.contractType || "—"}</dd></div>
              <div><dt>Підстава</dt><dd>{person.hireOrder || "—"}</dd></div>
              <div><dt>Модель ЗП</dt><dd>{window.SALARY_MODEL_LABELS[person.salaryModel]}</dd></div>
              {person.edessbRegistrar && <div><dt>Реєстратор ЄДЕССБ</dt><dd>окрема погодинна посада · з {formatDate(person.edessbRegistrar.since)}</dd></div>}
            </dl>
          </div>

          <CareerSection person={person} canSeeSalary={canSeeSalary} onPromote={onPromote} onGoToTasks={onGoToTasks} />

          <div className="drawer-section">
            <div className="drawer-section-h">Особисті та податкові дані</div>
            <dl className="info-grid">
              <div><dt>РНОКПП (ІПН)</dt><dd className="td-mono">{person.taxId || "—"}</dd></div>
              <div><dt>{person.idDoc?.kind || "Документ"}</dt><dd className="td-mono">{person.idDoc?.number || "—"}</dd></div>
              <div><dt>Ким виданий</dt><dd>{person.idDoc?.issuedBy || "—"}</dd></div>
              <div><dt>Дата видачі</dt><dd>{person.idDoc ? formatDate(person.idDoc.issuedDate) : "—"}</dd></div>
            </dl>
          </div>

          {person.kep && <KepSection kep={person.kep} />}

          {canSeeSalary && (
            <div className="drawer-section">
              <div className="drawer-section-h">Зарплата</div>
              <dl className="info-grid info-grid-salary">
                {person.salaryModel === "fixed" || person.salaryModel === "fixed_bonus" ? (
                  <>
                    <div><dt>Оклад</dt><dd className="num">{formatMoney(person.baseSalary * (person.partRate || 1))} ₴</dd></div>
                    {person.partRate && <div><dt>Частка ставки</dt><dd>{Math.round(person.partRate * 100)}%</dd></div>}
                    {person.salaryModel === "fixed_bonus" && <div><dt>Бонус</dt><dd>{(person.bonusRate*100).toFixed(1)}% від договору</dd></div>}
                  </>
                ) : (
                  <div><dt>Гонорар</dt><dd className="num">{formatMoney(person.taskRate)} ₴/год</dd></div>
                )}
                <div><dt>IBAN</dt><dd className="td-mono" style={{fontSize: 11.5}}>{person.iban}</dd></div>
              </dl>
              {person.edessbRegistrar && person.edessbRegistrar.rate && (
                <div className="edessb-job">
                  <div className="edessb-job-head">
                    <span className="status-tag tone-blue">Реєстратор ЄДЕССБ</span>
                    <span className="edessb-job-type">{person.edessbRegistrar.contractType} · погодинно</span>
                  </div>
                  <dl className="info-grid info-grid-salary" style={{marginTop: 10}}>
                    <div><dt>Ставка</dt><dd className="num">{formatMoney(person.edessbRegistrar.rate)} ₴/год</dd></div>
                    <div><dt>Годин за період</dt><dd>{person.edessbRegistrar.hours} год</dd></div>
                    <div><dt>Нараховано</dt><dd className="num" style={{fontWeight: 600, color: "var(--c-green-deep)"}}>{formatMoney(person.edessbRegistrar.hours * person.edessbRegistrar.rate)} ₴</dd></div>
                  </dl>
                </div>
              )}
              {cashVisible && person.cashSalary > 0 && (
                <div className="cash-split">
                  <div className="cash-split-row">
                    <span className="cash-split-tag">Офіційно</span>
                    <span className="cash-split-note">оклад на карту</span>
                    <span className="cash-split-val">{formatMoney(person.baseSalary * (person.partRate || 1))} ₴</span>
                  </div>
                  <div className="cash-split-row">
                    <span className="cash-split-tag is-cash">Готівкою</span>
                    <span className="cash-split-note">в конверті, поза обліком</span>
                    <span className="cash-split-val">{formatMoney(person.cashSalary)} ₴</span>
                  </div>
                  <div className="cash-split-row is-total">
                    <span className="cash-split-tag">Разом на руки</span>
                    <span className="cash-split-note"></span>
                    <span className="cash-split-val">{formatMoney(person.baseSalary * (person.partRate || 1) + person.cashSalary)} ₴</span>
                  </div>
                </div>
              )}
            </div>
          )}

          {person.qualCerts && person.qualCerts.length > 0 && (
            <div className="drawer-section">
              <div className="drawer-section-h">Кваліфікаційні сертифікати</div>
              {person.qualCerts.map((qc, i) => <QualCertCard key={i} qc={qc} />)}
            </div>
          )}

          {(person.insurance || person.membership) && (
            <div className="drawer-section">
              <div className="drawer-section-h">Страхування та членські внески</div>
              {person.insurance && (() => {
                const st = window.insuranceStatus(person.insurance);
                return (
                  <div className="qual-card" style={{marginBottom: 10}}>
                    <div className="qual-card-head">
                      <div style={{minWidth: 0}}>
                        <div className="qual-card-kind">Страхування профвідповідальності</div>
                        <div className="qual-card-sub">{person.insurance.insurer} · №{person.insurance.policyNumber}</div>
                      </div>
                      <span className={`status-tag tone-${st.tone}`}>{st.label}</span>
                    </div>
                    <dl className="info-grid" style={{marginTop: 10}}>
                      <div><dt>Страхова сума</dt><dd className="num">{formatMoney(person.insurance.sumInsured)} ₴</dd></div>
                      <div><dt>Премія / рік</dt><dd className="num">{formatMoney(person.insurance.premium)} ₴</dd></div>
                      <div><dt>Період</dt><dd>{formatDate(person.insurance.startDate)} – {formatDate(person.insurance.endDate)}</dd></div>
                      <div><dt>Поновити до</dt><dd style={{color: st.state !== "active" ? "var(--late)" : "var(--ink)", fontWeight: 600}}>{formatDate(person.insurance.endDate)}</dd></div>
                    </dl>
                    {person.insurance.scan && <div className="qual-card-scan"><span className="qual-card-row-label">Скан поліса</span><ScanChip scan={person.insurance.scan} /></div>}
                  </div>
                );
              })()}
              {person.membership && (() => {
                const st = window.membershipStatus(person.membership);
                return (
                  <div className="qual-card">
                    <div className="qual-card-head">
                      <div style={{minWidth: 0}}>
                        <div className="qual-card-kind">Членські внески</div>
                        <div className="qual-card-sub">{person.membership.org} · з {person.membership.memberSince}</div>
                      </div>
                      <span className={`status-tag tone-${st.tone}`}>{st.label}</span>
                    </div>
                    <dl className="info-grid" style={{marginTop: 10}}>
                      <div><dt>Внесок / рік</dt><dd className="num">{formatMoney(person.membership.feeAmount)} ₴</dd></div>
                      <div><dt>Останній платіж</dt><dd>{formatDate(person.membership.lastPaid)}</dd></div>
                      <div><dt>Сплачено до</dt><dd style={{color: st.state !== "active" ? "var(--late)" : "var(--ink)", fontWeight: 600}}>{formatDate(person.membership.paidUntil)}</dd></div>
                    </dl>
                    {person.membership.scan && <div className="qual-card-scan"><span className="qual-card-row-label">Квитанція про сплату</span><ScanChip scan={person.membership.scan} /></div>}
                  </div>
                );
              })()}
            </div>
          )}

          <div className="drawer-section">
            <div className="drawer-section-h">Освіта і кваліфікація</div>
            <div style={{fontSize: 13, color: "var(--ink-2)", marginBottom: 8}}>{person.education}</div>
            <ul style={{display: "flex", flexDirection: "column", gap: 6, paddingLeft: 0}}>
              {person.certs.map((c, i) => (
                <li key={i} style={{fontSize: 12.5, color: "var(--ink-3)", display: "flex", gap: 8, alignItems: "flex-start"}}>
                  <span style={{color: "var(--accent)", flexShrink: 0}}>•</span>
                  <span>{c}</span>
                </li>
              ))}
            </ul>
          </div>

          <div className="drawer-section">
            <div className="drawer-section-h">Відпустки і лікарняні</div>
            <dl className="info-grid" style={{marginBottom: 12}}>
              <div><dt>Залишок відпустки</dt><dd className="num">{person.vacationBalance} дн.</dd></div>
              <div><dt>Лікарняних цього року</dt><dd className="num">{person.sickBalance} дн.</dd></div>
            </dl>
            {vacations.length > 0 && (
              <div className="mini-list">
                {vacations.map(v => (
                  <div key={v.id} className="mini-list-item">
                    <span>{v.type === "vacation" ? "Відпустка" : "Лікарняний"} · {formatDate(v.from)} – {formatDate(v.to)} ({v.days} дн.)</span>
                    <span className={`status-tag tone-${v.status === "approved" ? "live" : "warn"}`}>
                      {v.status === "approved" ? "затверджено" : "очікує"}
                    </span>
                  </div>
                ))}
              </div>
            )}
          </div>
        </div>

        <div className="drawer-foot">
          <button className="btn btn-primary" onClick={() => onIssueCert && onIssueCert(person)}>Довідка про доходи</button>
          <button className="btn">Редагувати</button>
          <button className="btn">Призначити задачу</button>
        </div>
      </aside>
    </>
  );
}

// ============ ДОВІДКА ПРО ДОХОДИ ============
function IncomeCertificate({ person, onClose }) {
  React.useEffect(() => {
    const onKey = (e) => e.key === "Escape" && onClose();
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [onClose]);

  const co = window.COMPANY;
  const rows = window.incomeRows(person, 6);
  const tot = rows.reduce((a, r) => ({
    gross: a.gross + r.gross, pdfo: a.pdfo + r.pdfo, vz: a.vz + r.vz, net: a.net + r.net,
  }), { gross: 0, pdfo: 0, vz: 0, net: 0 });
  const period = `${rows[0].label} – ${rows[rows.length - 1].label}`;
  const outNo = `${person.id.toUpperCase()}-${rows.length}/${new Date(window.SYS_DATE).getFullYear()}`;

  return (
    <>
      <div className="drawer-overlay" onClick={onClose} style={{zIndex: 200}}></div>
      <div className="report-modal" style={{zIndex: 201, maxWidth: 820, inset: "auto", top: 32, bottom: 32, left: "50%", transform: "translateX(-50%)", width: "calc(100% - 64px)"}}>
        <div className="report-toolbar">
          <button className="drawer-close" onClick={onClose}><window.Icon.X /></button>
          <div style={{flex: 1}}>
            <div style={{fontSize: 14, fontWeight: 600}}>Довідка про доходи</div>
            <div style={{fontSize: 11.5, color: "var(--ink-3)"}}>{person.name} · період {period}</div>
          </div>
          <button className="btn" onClick={() => window.print()}>Друк / PDF</button>
          <button className="btn btn-primary">Підписати КЕП</button>
        </div>

        <div className="report-page cert-page">
          <div className="report-doc-head">
            <div>
              <div style={{fontSize: 16, fontWeight: 700, color: "var(--ink)"}}>{co.shortName}</div>
              <div style={{fontSize: 12, color: "var(--ink-3)", marginTop: 4, lineHeight: 1.6}}>
                ЄДРПОУ {co.edrpou}<br />
                {co.address}<br />
                IBAN {co.iban}, {co.bank}<br />
                Тел. {co.phone}
              </div>
            </div>
            <div style={{textAlign: "right", fontSize: 12, color: "var(--ink-3)", lineHeight: 1.7}}>
              <div>Вих. № {outNo}</div>
              <div>від {formatLongDate(window.SYS_DATE)}</div>
            </div>
          </div>

          <h2 style={{textAlign: "center", fontSize: 18, fontWeight: 700, letterSpacing: "0.02em", margin: "8px 0 24px"}}>
            ДОВІДКА ПРО ДОХОДИ
          </h2>

          <p style={{fontSize: 13.5, lineHeight: 1.8, color: "var(--ink-2)", marginBottom: 8, textWrap: "pretty"}}>
            Видана <b style={{color: "var(--ink)"}}>{person.name}</b> (РНОКПП {person.taxId}) про те, що
            він/вона {person.employment === "contractor" ? "співпрацює з" : "працює в"} {co.fullName} на посаді
            «{person.positionOfficial || person.role}» з {formatLongDate(person.hireDate)}
            {person.hireOrder ? ` (${person.hireOrder})` : ""}.
          </p>
          <p style={{fontSize: 13.5, lineHeight: 1.8, color: "var(--ink-2)", marginBottom: 18}}>
            Розмір нарахованого доходу за період <b style={{color: "var(--ink)"}}>{period}</b> наведено в таблиці:
          </p>

          <table className="report-info-table cert-table">
            <thead>
              <tr>
                <th>Місяць</th>
                <th style={{textAlign: "right"}}>Нараховано, ₴</th>
                <th style={{textAlign: "right"}}>ПДФО (18%)</th>
                <th style={{textAlign: "right"}}>Військовий збір (5%)</th>
                <th style={{textAlign: "right"}}>До виплати, ₴</th>
              </tr>
            </thead>
            <tbody>
              {rows.map((r, i) => (
                <tr key={i}>
                  <td style={{textTransform: "capitalize"}}>{r.label}</td>
                  <td className="num-col">{formatMoney(r.gross)}</td>
                  <td className="num-col">{formatMoney(r.pdfo)}</td>
                  <td className="num-col">{formatMoney(r.vz)}</td>
                  <td className="num-col" style={{fontWeight: 600}}>{formatMoney(r.net)}</td>
                </tr>
              ))}
            </tbody>
            <tfoot>
              <tr>
                <td style={{fontWeight: 700}}>Усього</td>
                <td className="num-col" style={{fontWeight: 700}}>{formatMoney(tot.gross)}</td>
                <td className="num-col" style={{fontWeight: 700}}>{formatMoney(tot.pdfo)}</td>
                <td className="num-col" style={{fontWeight: 700}}>{formatMoney(tot.vz)}</td>
                <td className="num-col" style={{fontWeight: 700}}>{formatMoney(tot.net)}</td>
              </tr>
            </tfoot>
          </table>

          <p style={{fontSize: 12.5, color: "var(--ink-3)", margin: "18px 0 0", lineHeight: 1.7}}>
            Середньомісячний дохід — <b style={{color: "var(--ink)"}}>{formatMoney(Math.round(tot.gross / rows.length))} ₴</b>.
            Податки та збори утримано й перераховано до бюджету в повному обсязі.
            Довідку видано для подання за місцем вимоги.
          </p>

          <div className="report-signature" style={{marginTop: 40}}>
            <div>
              <div style={{fontSize: 12.5, color: "var(--ink-3)", marginBottom: 28}}>Директор</div>
              <div style={{borderTop: "1px solid var(--ink-3)", paddingTop: 6, fontSize: 12.5, color: "var(--ink-2)", minWidth: 200}}>
                {co.director}
              </div>
            </div>
            <div>
              <div style={{fontSize: 12.5, color: "var(--ink-3)", marginBottom: 28}}>Головний бухгалтер</div>
              <div style={{borderTop: "1px solid var(--ink-3)", paddingTop: 6, fontSize: 12.5, color: "var(--ink-2)", minWidth: 200}}>
                {co.accountant}
              </div>
            </div>
            <div className="cert-seal">М.П.</div>
          </div>
        </div>
      </div>
    </>
  );
}

// ============ СКАНКОПІЇ ДОКУМЕНТІВ ============
function ScanViewer({ scan, onClose }) {
  React.useEffect(() => {
    const onKey = (e) => e.key === "Escape" && onClose();
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [onClose]);
  return (
    <>
      <div className="drawer-overlay" onClick={onClose} style={{zIndex: 200}}></div>
      <div className="report-modal scan-modal" style={{zIndex: 201, maxWidth: 560, inset: "auto", top: 32, bottom: 32, left: "50%", transform: "translateX(-50%)", width: "calc(100% - 64px)"}}>
        <div className="report-toolbar">
          <button className="drawer-close" onClick={onClose}><window.Icon.X /></button>
          <div style={{flex: 1, minWidth: 0}}>
            <div style={{fontSize: 14, fontWeight: 600, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis"}}>{scan.name}</div>
            <div style={{fontSize: 11.5, color: "var(--ink-3)"}}>{scan.uploaded ? `Завантажено ${formatDate(scan.uploaded)}` : "Перетягніть файл, щоб додати скан"}</div>
          </div>
          <button className="btn">Завантажити</button>
        </div>
        <div className="scan-modal-body">
          <image-slot id={scan.slot} fit="contain" radius="8"
            placeholder="Перетягніть скан (PDF/JPG) сюди або натисніть"
            style={{width: "100%", aspectRatio: "1 / 1.414", display: "block"}}></image-slot>
        </div>
      </div>
    </>
  );
}

function ScanChip({ scan }) {
  const [open, setOpen] = React.useState(false);
  if (!scan) return null;
  return (
    <>
      <button className="scan-chip" onClick={() => setOpen(true)} title={scan.name}>
        <span className="scan-chip-ic">PDF</span>
        <span className="scan-chip-name">{scan.name}</span>
      </button>
      {open && <ScanViewer scan={scan} onClose={() => setOpen(false)} />}
    </>
  );
}

// ============ КВАЛІФІКАЦІЙНІ СЕРТИФІКАТИ ============
function QualClassChip({ cls, upgrade }) {
  return (
    <span className="qual-class-chip" title={upgrade ? `Можливе підвищення: ${upgrade.current} → ${upgrade.next}` : "Найвищий клас наслідків"}>
      {cls}
      {upgrade && <span className="qual-class-next">→ {upgrade.next}</span>}
    </span>
  );
}

function QualificationsPage({ role }) {
  const team = window.DATA.TEAM;
  // розгортаємо в плоский список сертифікатів
  const certs = [];
  team.forEach(p => (p.qualCerts || []).forEach(qc => {
    certs.push({
      person: p, qc,
      training: window.qualTrainingStatus(qc),
      cont: window.edessbContinuityStatus(qc),
      upgrade: window.qualUpgrade(qc),
    });
  }));
  const without = team.filter(p => !p.qualCerts || p.qualCerts.length === 0);

  // фахівці з сертифікатами — для контролю страхування та членських внесків
  const specialists = team
    .filter(p => p.qualCerts && p.qualCerts.length > 0)
    .map(p => ({
      person: p,
      ins: window.insuranceStatus(p.insurance),
      mem: window.membershipStatus(p.membership),
    }));

  // нагадування — усе, що прострочено або скоро
  const order = { expired: 0, expiring: 1, active: 2 };
  const reminders = [];
  certs.forEach(c => {
    if (c.training.state !== "active") reminders.push({ ...c, kind: "training", st: c.training });
    if (c.cont.state !== "active")     reminders.push({ ...c, kind: "cont", st: c.cont });
  });
  specialists.forEach(s => {
    if (s.ins && s.ins.state !== "active") reminders.push({ person: s.person, kind: "insurance", st: s.ins, ref: s.person.insurance });
    if (s.mem && s.mem.state !== "active") reminders.push({ person: s.person, kind: "membership", st: s.mem, ref: s.person.membership });
  });
  reminders.sort((a, b) => order[a.st.state] - order[b.st.state] || a.st.days - b.st.days);

  return (
    <div className="page">
      <div className="page-head">
        <h1 className="page-h1">Кваліфікаційні сертифікати</h1>
        <div className="page-sub">
          <span>{certs.length} {window.plural(certs.length, "сертифікат", "сертифікати", "сертифікатів")} у {certs.length ? new Set(certs.map(c => c.person.id)).size : 0} фахівців</span>
          <span className="dot"></span>
          <span>{without.length} без сертифіката</span>
          {reminders.length > 0 && <>
            <span className="dot"></span>
            <span style={{color: "var(--late)"}}>{reminders.length} {window.plural(reminders.length, "нагадування", "нагадування", "нагадувань")}</span>
          </>}
        </div>
      </div>

      <div className="hint-box">
        <b>Правила:</b> підвищення кваліфікації — раз на 5 років від останньої атестації; відомості про
        безперервність стажу до ЄДЕССБ подаються щороку. Договір страхування професійної відповідальності
        та членські внески у профоб'єднанні поновлюються <b>щороку</b> — без них сертифікат може втратити чинність.
      </div>

      {reminders.length > 0 && (
        <section className="section">
          <div className="section-head">
            <h2 className="section-h2">Потребує уваги</h2>
            <span className="section-sub">{reminders.length}</span>
          </div>
          <div className="qual-reminders">
            {reminders.map((r, i) => {
              const tagLabel = { training: "Підвищення", cont: "ЄДЕССБ", insurance: "Страхування", membership: "Внесок" }[r.kind];
              const btnLabel = { training: "Записати на атестацію", cont: "Подати в ЄДЕССБ", insurance: "Поновити поліс", membership: "Сплатити внесок" }[r.kind];
              let sub;
              if (r.kind === "training") {
                sub = r.st.state === "expired"
                  ? `Підвищення кваліфікації прострочено на ${Math.abs(r.st.days)} дн. (дедлайн ${formatDate(r.st.dueDate)})`
                  : `Підвищення кваліфікації — дедлайн ${formatDate(r.st.dueDate)} (через ${r.st.days} дн.)`;
              } else if (r.kind === "cont") {
                sub = r.st.state === "expired"
                  ? `Відомості в ЄДЕССБ не подані — термін минув ${formatDate(r.st.dueDate)}`
                  : `Відомості в ЄДЕССБ подати до ${formatDate(r.st.dueDate)} (через ${r.st.days} дн.)`;
              } else if (r.kind === "insurance") {
                sub = r.st.state === "expired"
                  ? `Поліс ${r.ref.insurer} (${r.ref.policyNumber}) недійсний з ${formatDate(r.st.dueDate)}`
                  : `Поліс ${r.ref.insurer} спливає ${formatDate(r.st.dueDate)} (через ${r.st.days} дн.)`;
              } else {
                sub = r.st.state === "expired"
                  ? `Членський внесок (${r.ref.org}) не сплачено з ${formatDate(r.st.dueDate)}`
                  : `Членський внесок ${formatMoney(r.ref.feeAmount)} ₴ сплатити до ${formatDate(r.st.dueDate)} (через ${r.st.days} дн.)`;
              }
              return (
                <div key={i} className={`qual-reminder tone-${r.st.tone}`}>
                  <div className="team-avatar" style={{width: 34, height: 34, fontSize: 12, flexShrink: 0}}>{r.person.initials}</div>
                  <div style={{flex: 1, minWidth: 0}}>
                    <div className="cell-name">{r.person.name}{r.qc ? <> · <span style={{fontWeight: 500, color: "var(--ink-3)"}}>{r.qc.number}</span></> : null}</div>
                    <div className="cell-sub">{sub}</div>
                  </div>
                  <span className={`status-tag tone-${r.st.tone}`}>{tagLabel}</span>
                  <button className="btn btn-primary" style={{flexShrink: 0, padding: "5px 12px"}}>{btnLabel}</button>
                </div>
              );
            })}
          </div>
        </section>
      )}

      <section className="section">
        <div className="section-head">
          <h2 className="section-h2">Усі сертифікати</h2>
          <span className="section-sub">{certs.length}</span>
        </div>
        <table className="data-table">
          <thead>
            <tr>
              <th></th>
              <th>Фахівець / сертифікат</th>
              <th>Клас наслідків</th>
              <th>Отримано</th>
              <th>Підвищення кваліфікації</th>
              <th>Безперервність (ЄДЕССБ)</th>
            </tr>
          </thead>
          <tbody>
            {certs.map((c, i) => (
              <tr key={i}>
                <td><div className="team-avatar" style={{width: 30, height: 30, fontSize: 11}}>{c.person.initials}</div></td>
                <td>
                  <div className="cell-name">{c.person.name}</div>
                  <div className="cell-sub">{c.qc.kind} · №{c.qc.number}</div>
                  {c.qc.scan && <div style={{marginTop: 6}}><ScanChip scan={c.qc.scan} /></div>}
                </td>
                <td><QualClassChip cls={c.qc.class} upgrade={c.upgrade} /></td>
                <td className="td-mono" style={{fontSize: 12, color: "var(--ink-3)"}}>{formatDate(c.qc.issuedDate)}</td>
                <td>
                  <div className="qual-due">
                    <span className="td-mono" style={{fontSize: 12, color: c.training.state !== "active" ? "var(--late)" : "var(--ink)"}}>{formatDate(c.training.dueDate)}</span>
                    <span className={`status-tag tone-${c.training.tone}`}>{c.training.label}</span>
                  </div>
                </td>
                <td>
                  <div className="qual-due">
                    <span className="td-mono" style={{fontSize: 12, color: c.cont.state !== "active" ? "var(--late)" : "var(--ink)"}}>{formatDate(c.cont.dueDate)}</span>
                    <span className={`status-tag tone-${c.cont.tone}`}>{c.cont.label}</span>
                  </div>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </section>

      {specialists.length > 0 && (
        <section className="section">
          <div className="section-head">
            <h2 className="section-h2">Страхування та членські внески</h2>
            <span className="section-sub">щорічний контроль · {specialists.length}</span>
          </div>
          <table className="data-table ins-table">
            <thead>
              <tr>
                <th></th>
                <th>Фахівець</th>
                <th>Страхування профвідповідальності</th>
                <th>Чинний до</th>
                <th>Членські внески</th>
                <th>Сплачено до</th>
              </tr>
            </thead>
            <tbody>
              {specialists.map((s, i) => (
                <tr key={i}>
                  <td><div className="team-avatar" style={{width: 30, height: 30, fontSize: 11}}>{s.person.initials}</div></td>
                  <td>
                    <div className="cell-name">{s.person.name}</div>
                    <div className="cell-sub">{s.person.role}</div>
                  </td>
                  <td>
                    {s.person.insurance ? (
                      <div>
                        <div className="cell-name" style={{fontWeight: 500}}>{s.person.insurance.insurer}</div>
                        <div className="cell-sub td-mono">{s.person.insurance.policyNumber} · {formatMoney(s.person.insurance.sumInsured)} ₴</div>
                        {s.person.insurance.scan && <div style={{marginTop: 6}}><ScanChip scan={s.person.insurance.scan} /></div>}
                      </div>
                    ) : <span className="cell-sub">—</span>}
                  </td>
                  <td>
                    {s.ins ? (
                      <div className="qual-due">
                        <span className="td-mono" style={{fontSize: 12, color: s.ins.state !== "active" ? "var(--late)" : "var(--ink)"}}>{formatDate(s.ins.dueDate)}</span>
                        <span className={`status-tag tone-${s.ins.tone}`}>{s.ins.label}</span>
                      </div>
                    ) : <span className="cell-sub">—</span>}
                  </td>
                  <td>
                    {s.person.membership ? (
                      <div>
                        <div className="cell-name" style={{fontWeight: 500}}>{s.person.membership.org}</div>
                        <div className="cell-sub">{formatMoney(s.person.membership.feeAmount)} ₴ / рік · з {s.person.membership.memberSince}</div>
                        {s.person.membership.scan && <div style={{marginTop: 6}}><ScanChip scan={s.person.membership.scan} /></div>}
                      </div>
                    ) : <span className="cell-sub">—</span>}
                  </td>
                  <td>
                    {s.mem ? (
                      <div className="qual-due">
                        <span className="td-mono" style={{fontSize: 12, color: s.mem.state !== "active" ? "var(--late)" : "var(--ink)"}}>{formatDate(s.mem.dueDate)}</span>
                        <span className={`status-tag tone-${s.mem.tone}`}>{s.mem.label}</span>
                      </div>
                    ) : <span className="cell-sub">—</span>}
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </section>
      )}

      {without.length > 0 && (
        <section className="section">
          <div className="section-head">
            <h2 className="section-h2">Без кваліфікаційного сертифіката</h2>
            <span className="section-sub">{without.length}</span>
          </div>
          <div className="qual-without">
            {without.map(p => (
              <div key={p.id} className="qual-without-item">
                <div className="team-avatar" style={{width: 28, height: 28, fontSize: 10}}>{p.initials}</div>
                <div>
                  <div className="cell-name">{p.name}</div>
                  <div className="cell-sub">{p.role}</div>
                </div>
              </div>
            ))}
          </div>
        </section>
      )}
    </div>
  );
}

// ============ ОБЛІК ЧАСУ ============
function TimePage({ tasks, role }) {
  const team = window.DATA.TEAM;

  // Тижні рахуються від ПОТОЧНОГО (window.CURRENT_WEEK з бекенду), а не захардкоджені.
  const MON_UA = ["січ", "лют", "бер", "кві", "трав", "черв", "лип", "серп", "вер", "жовт", "лист", "груд"];
  const isoMonday = (y, w) => { const d = new Date(Date.UTC(y, 0, 4)); const dn = (d.getUTCDay() + 6) % 7; d.setUTCDate(d.getUTCDate() - dn + (w - 1) * 7); return d; };
  const isoWeekOf = (d) => { const t = new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate())); const dn = (t.getUTCDay() + 6) % 7; t.setUTCDate(t.getUTCDate() - dn + 3); const ft = new Date(Date.UTC(t.getUTCFullYear(), 0, 4)); const w = 1 + Math.round(((t - ft) / 864e5 - 3 + ((ft.getUTCDay() + 6) % 7)) / 7); return { y: t.getUTCFullYear(), w }; };
  const curM = /(\d{4})-W(\d{2})/.exec(window.CURRENT_WEEK || "");
  const baseMon = curM ? isoMonday(+curM[1], +curM[2])
    : (() => { const t = new Date((window.SYS_DATE || new Date().toISOString().slice(0, 10)) + "T00:00:00Z"); const dn = (t.getUTCDay() + 6) % 7; t.setUTCDate(t.getUTCDate() - dn); return t; })();
  const weekFor = (offset) => {
    const mon = new Date(baseMon); mon.setUTCDate(baseMon.getUTCDate() - offset * 7);
    const wk = isoWeekOf(mon), nums = [], iso = [];
    for (let i = 0; i < 5; i++) { const dd = new Date(mon); dd.setUTCDate(mon.getUTCDate() + i); nums.push(String(dd.getUTCDate())); iso.push(dd.toISOString().slice(0, 10)); }
    const fri = new Date(mon); fri.setUTCDate(mon.getUTCDate() + 4);
    return { id: `${wk.y}-W${String(wk.w).padStart(2, "0")}`, nums, iso,
             label: `W${String(wk.w).padStart(2, "0")} · ${mon.getUTCDate()}–${fri.getUTCDate()} ${MON_UA[fri.getUTCMonth()]}` };
  };
  const weekList = [weekFor(0), weekFor(1), weekFor(2)];
  weekList[0].label = "Поточний · " + weekList[0].label;
  weekList[1].label = "Попередній · " + weekList[1].label;

  const [week, setWeek] = React.useState(weekList[0].id);
  const sheet = window.TIMESHEET[week] || {};
  const selected = weekList.find(x => x.id === week) || weekList[0];
  const dayNames = ["Пн", "Вт", "Ср", "Чт", "Пт"];
  const dayNums = selected.nums;
  const todayIdx = selected.iso.indexOf(window.SYS_DATE);

  // загальні підсумки
  const totals = team.map(p => {
    const row = sheet[p.id];
    if (!row) return { person: p, sum: 0, planned: 0 };
    const sum = row.hours.reduce((a,b) => a + b, 0);
    return { person: p, sum, planned: row.planned, note: row.note };
  });

  const sumAll = totals.reduce((s, r) => s + r.sum, 0);
  const planAll = totals.reduce((s, r) => s + r.planned, 0);

  const weeks = weekList;

  return (
    <div className="page">
      <div className="page-head">
        <h1 className="page-h1">Облік часу</h1>
        <div className="page-sub">
          <span>тижневий timesheet</span>
          <span className="dot"></span>
          <span>відпрацьовано <b style={{color: "var(--ink)"}}>{sumAll}</b> з {planAll} планових год</span>
        </div>
      </div>

      <div className="toolbar">
        <div className="filter-pill" role="tablist">
          {weeks.map(w => (
            <button
              key={w.id}
              className={`filter-pill-item ${week === w.id ? "is-active" : ""}`}
              onClick={() => setWeek(w.id)}
            >
              {w.label}
            </button>
          ))}
        </div>
      </div>

      <table className="data-table timesheet-table">
        <thead>
          <tr>
            <th style={{width: 220}}>Працівник</th>
            {dayNames.map((d, i) => (
              <th key={d} className={`ts-day ${i === todayIdx ? "is-today" : ""}`}>
                <div className="ts-day-name">{d}</div>
                <div className="ts-day-num">{dayNums[i]}</div>
              </th>
            ))}
            <th className="ts-total">Сума</th>
            <th>План</th>
            <th style={{width: 100}}></th>
          </tr>
        </thead>
        <tbody>
          {team.map(p => {
            const row = sheet[p.id];
            if (!row) return null;
            const sum = row.hours.reduce((a,b) => a + b, 0);
            const pct = row.planned > 0 ? Math.round((sum / row.planned) * 100) : 0;
            return (
              <tr key={p.id}>
                <td>
                  <div style={{display: "flex", alignItems: "center", gap: 10}}>
                    <div className="team-avatar" style={{width: 28, height: 28, fontSize: 10}}>{p.initials}</div>
                    <div>
                      <div className="cell-name">{p.name}</div>
                      <div className="cell-sub">{p.role}</div>
                    </div>
                  </div>
                </td>
                {row.hours.map((h, i) => (
                  <td key={i} className={`ts-cell ${i === todayIdx ? "is-today" : ""}`}>
                    {h > 0 ? <span className="ts-h">{h}</span> : <span className="ts-empty">—</span>}
                  </td>
                ))}
                <td className="ts-total">
                  <span style={{fontWeight: 600, fontVariantNumeric: "tabular-nums"}}>{sum}</span>
                </td>
                <td>
                  {row.planned > 0
                    ? <div className="load-bar">
                        <div className="load-bar-track">
                          <div className={`load-bar-fill ${pct >= 100 ? "is-high" : ""}`} style={{width: Math.min(pct, 100) + "%"}}></div>
                        </div>
                        <span className="load-bar-val">{row.planned}</span>
                      </div>
                    : <span style={{color: "var(--ink-4)", fontSize: 12}}>—</span>
                  }
                </td>
                <td>
                  <button className="btn btn-ghost" style={{padding: "4px 8px", fontSize: 12}}>Деталі</button>
                </td>
              </tr>
            );
          })}
        </tbody>
        <tfoot>
          <tr>
            <td><b>Усього</b></td>
            <td colSpan={5} className="ts-total"><b style={{fontVariantNumeric: "tabular-nums"}}>{sumAll}</b></td>
            <td><span style={{color: "var(--ink-3)"}}>{planAll}</span></td>
            <td></td>
          </tr>
        </tfoot>
      </table>

      <div style={{marginTop: 20, fontSize: 12.5, color: "var(--ink-3)", padding: "12px 16px", background: "var(--bg-sunken)", borderRadius: 8, lineHeight: 1.5}}>
        <b style={{color: "var(--ink-2)"}}>Як працює timesheet:</b> кожен працівник заповнює фактичні години в кінці дня.
        Для штатних — порівнюємо з планом (40 год/тиждень) та коригуємо ЗП. Для субпідрядників — це години для розрахунку гонорару за задачами.
      </div>
    </div>
  );
}

// ============ ВІДПУСТКИ ============
function VacationPage({ role }) {
  const team = window.DATA.TEAM;
  const vacations = window.DATA.VACATIONS;
  const pending = vacations.filter(v => v.status === "pending");
  const approved = vacations.filter(v => v.status === "approved");

  return (
    <div className="page">
      <div className="page-head">
        <h1 className="page-h1">Відпустки і лікарняні</h1>
        <div className="page-sub">
          <span>{pending.length} {window.plural(pending.length, "заявка", "заявки", "заявок")} очікують</span>
          <span className="dot"></span>
          <span>{approved.length} затверджено</span>
        </div>
      </div>

      {/* Баланс по людях */}
      <section className="section">
        <div className="section-head">
          <h2 className="section-h2">Баланс днів</h2>
          <span className="section-sub">залишок на 2026 рік</span>
        </div>
        <table className="data-table compact-table">
          <thead>
            <tr>
              <th></th>
              <th>Працівник</th>
              <th>Залишок відпустки</th>
              <th>Лікарняних взято</th>
              <th>Запланована відпустка</th>
            </tr>
          </thead>
          <tbody>
            {team.map(p => {
              const upcoming = vacations.find(v => v.who === p.id && v.type === "vacation" && v.status === "approved" && v.from > "2026-05-26");
              return (
                <tr key={p.id}>
                  <td><div className="team-avatar" style={{width: 28, height: 28, fontSize: 10}}>{p.initials}</div></td>
                  <td>
                    <div className="cell-name">{p.name}</div>
                    <div className="cell-sub">{p.role}</div>
                  </td>
                  <td><span style={{fontVariantNumeric: "tabular-nums", fontWeight: 600}}>{p.vacationBalance}</span> <span style={{color: "var(--ink-3)"}}>дн.</span></td>
                  <td>
                    {p.sickBalance > 0
                      ? <span><span style={{fontVariantNumeric: "tabular-nums", fontWeight: 500}}>{p.sickBalance}</span> <span style={{color: "var(--ink-3)"}}>дн.</span></span>
                      : <span style={{color: "var(--ink-4)"}}>—</span>
                    }
                  </td>
                  <td>
                    {upcoming
                      ? <span style={{fontSize: 12.5}}>{formatDate(upcoming.from)} – {formatDate(upcoming.to)} <span style={{color: "var(--ink-3)"}}>({upcoming.days} дн.)</span></span>
                      : <span style={{color: "var(--ink-4)", fontSize: 12.5}}>немає</span>
                    }
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </section>

      {/* Очікують підтвердження */}
      {pending.length > 0 && (
        <section className="section">
          <div className="section-head">
            <h2 className="section-h2">Очікують підтвердження</h2>
            <span className="section-sub">{pending.length}</span>
          </div>
          <div className="vacation-list">
            {pending.map(v => {
              const p = window.getTeam(v.who);
              return (
                <div key={v.id} className="vacation-row is-pending">
                  <div className="team-avatar" style={{width: 36, height: 36}}>{p?.initials}</div>
                  <div className="vacation-main">
                    <div className="cell-name">{p?.name}</div>
                    <div className="cell-sub">{v.note}</div>
                  </div>
                  <div className="vacation-dates">
                    <div className="vacation-period">{formatDate(v.from)} – {formatDate(v.to)}</div>
                    <div className="cell-sub">{v.days} {window.plural(v.days, "день", "дні", "днів")} · {v.type === "vacation" ? "відпустка" : "лікарняний"}</div>
                  </div>
                  <div className="vacation-actions">
                    <button className="btn btn-primary" style={{padding: "5px 12px"}}>Затвердити</button>
                    <button className="btn" style={{padding: "5px 12px"}}>Відхилити</button>
                  </div>
                </div>
              );
            })}
          </div>
        </section>
      )}

      {/* Затверджені — короткий список */}
      <section className="section">
        <div className="section-head">
          <h2 className="section-h2">Затверджені</h2>
          <span className="section-sub">{approved.length}</span>
        </div>
        <div className="vacation-list">
          {approved.map(v => {
            const p = window.getTeam(v.who);
            return (
              <div key={v.id} className="vacation-row">
                <div className="team-avatar" style={{width: 36, height: 36}}>{p?.initials}</div>
                <div className="vacation-main">
                  <div className="cell-name">{p?.name}</div>
                  <div className="cell-sub">{v.note}</div>
                </div>
                <div className="vacation-dates">
                  <div className="vacation-period">{formatDate(v.from)} – {formatDate(v.to)}</div>
                  <div className="cell-sub">{v.days} {window.plural(v.days, "день", "дні", "днів")} · {v.type === "vacation" ? "відпустка" : "лікарняний"}</div>
                </div>
                <span className="status-tag tone-live">затверджено</span>
              </div>
            );
          })}
        </div>
      </section>
    </div>
  );
}

// ============ ДОКУМЕНТИ ============
function DocumentsPage({ role }) {
  const docs = window.DATA.DOCUMENTS;
  const [filter, setFilter] = React.useState("all");
  const filtered = filter === "all" ? docs : docs.filter(d => d.type === filter);

  return (
    <div className="page">
      <div className="page-head">
        <h1 className="page-h1">Документи</h1>
        <div className="page-sub">
          <span>{docs.length} {window.plural(docs.length, "документ", "документи", "документів")}</span>
          <span className="dot"></span>
          <span>{docs.filter(d => d.status === "draft").length} чернеток</span>
          <span className="dot"></span>
          <span>{docs.filter(d => d.status === "pending").length} на підписанні</span>
        </div>
      </div>

      {/* Drive integration banner */}
      <div className="drive-banner">
        <div className="drive-banner-icon"><window.Ico name="folder" /></div>
        <div style={{flex: 1, minWidth: 0}}>
          <div style={{fontSize: 13.5, fontWeight: 600, color: "var(--ink)"}}>Усі документи зберігаються в Google Drive</div>
          <div style={{fontSize: 12, color: "var(--ink-3)", marginTop: 2}}>
            Папка <code>HR / Накази 2026</code> · автоматична синхронізація · підписання через Дія.Підпис
          </div>
        </div>
        <button className="btn">Відкрити папку в Drive ↗</button>
      </div>

      <div className="toolbar">
        <div className="filter-pill" role="tablist">
          <button className={`filter-pill-item ${filter === "all" ? "is-active" : ""}`} onClick={() => setFilter("all")}>Усі</button>
          <button className={`filter-pill-item ${filter === "order" ? "is-active" : ""}`} onClick={() => setFilter("order")}>Накази</button>
          <button className={`filter-pill-item ${filter === "contract" ? "is-active" : ""}`} onClick={() => setFilter("contract")}>Договори</button>
          <button className={`filter-pill-item ${filter === "request" ? "is-active" : ""}`} onClick={() => setFilter("request")}>Заяви</button>
        </div>
        <button className="btn btn-primary" style={{marginLeft: "auto"}}>
          <window.Icon.Plus /> Новий документ
        </button>
      </div>

      <table className="data-table">
        <thead>
          <tr>
            <th style={{width: 100}}>Тип</th>
            <th>Назва</th>
            <th>Стосується</th>
            <th>Дата</th>
            <th>Статус</th>
            <th>Файл</th>
            <th></th>
          </tr>
        </thead>
        <tbody>
          {filtered.map(d => {
            const st = window.DOC_STATUS_LABELS[d.status];
            return (
              <tr key={d.id} className="is-clickable">
                <td><span className="doc-type">{window.DOC_TYPE_LABELS[d.type]}</span></td>
                <td>
                  <div className="cell-name">{d.title}</div>
                  <div className="cell-sub">{d.note}</div>
                </td>
                <td>
                  <div className="avatar-stack" style={{paddingLeft: 4}}>
                    {d.who.slice(0,3).map((id, i) => {
                      const p = window.getTeam(id);
                      return <span key={id} className="av" style={{zIndex: 10 - i, width: 24, height: 24, fontSize: 10}}>{p?.initials[0]}</span>;
                    })}
                    {d.who.length > 3 && <span className="av av-more" style={{width: 24, height: 24, fontSize: 9.5}}>+{d.who.length - 3}</span>}
                  </div>
                </td>
                <td className="td-mono" style={{fontSize: 12}}>{formatDate(d.date)}</td>
                <td><span className={`status-tag tone-${st?.tone}`}>{st?.label}</span></td>
                <td>
                  <span className="drive-link">
                    <span className="drive-link-icon"><window.Ico name={d.type === "order" ? "book" : "file"} size={13} /></span>
                    <span style={{fontSize: 11.5, color: "var(--ink-3)"}}>в Drive</span>
                  </span>
                </td>
                <td>
                  <button className="btn btn-ghost" style={{padding: "4px 8px", fontSize: 12}}>Відкрити ↗</button>
                </td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

// ============ HELPERS ============
function formatDate(iso) {
  if (!iso) return "—";
  const [y, m, d] = iso.split("-");
  const months = ["січ", "лют", "бер", "квіт", "трав", "черв", "лип", "серп", "вер", "жовт", "лист", "груд"];
  return `${parseInt(d, 10)} ${months[parseInt(m, 10) - 1]} ${y}`;
}
function shortDate(iso) {
  if (!iso) return "—";
  const [y, m, d] = iso.split("-");
  return `${d}.${m}.${y.slice(2)}`;
}
function formatLongDate(iso) {
  if (!iso) return "—";
  const [y, m, d] = iso.split("-");
  const months = ["січня","лютого","березня","квітня","травня","червня","липня","серпня","вересня","жовтня","листопада","грудня"];
  return `${parseInt(d, 10)} ${months[parseInt(m, 10) - 1]} ${y} р.`;
}
function yearsBetween(fromIso, toIso) {
  const [fy, fm, fd] = fromIso.split("-").map(Number);
  const [ty, tm, td] = toIso.split("-").map(Number);
  let y = ty - fy;
  if (tm < fm || (tm === fm && td < fd)) y--;
  return y;
}
function formatMoney(n) {
  return new Intl.NumberFormat("uk-UA", { minimumFractionDigits: 0, maximumFractionDigits: 0 }).format(n);
}

window.ProfilesPage = ProfilesPage;
window.QualificationsPage = QualificationsPage;
window.TimePage = TimePage;
window.VacationPage = VacationPage;
window.DocumentsPage = DocumentsPage;
window.formatDate = formatDate;
window.formatMoney = formatMoney;
window.yearsBetween = yearsBetween;
