/* ============================================================
   VLF 2026 · OPS APP ROOT — App riêng cho Đội vận hành
   Login Zalo (trượt lên) → tự nạp vai trò đã mapping.
   Stack nav theo luật footer: L1 tab có tabbar; L2 chi tiết ẩn
   tabbar + header back. Tabs: Tổng quan · Nhiệm vụ · Điều phối
   · Sổ tay · Tài khoản.
   ============================================================ */
const OPS_TABS = ['hub', 'tasks', 'coord', 'book', 'me'];

function OpsRoot() {
  const O = window.VLF.ops;
  const [role, setRole] = useState(null); // null = login (staffRole id)
  const [lang, setLang] = useState('vi');
  const [account, setAccount] = useState('coord');
  const [perm, setPerm] = useState(false);
  const [loading, setLoading] = useState(false);
  const [notifSeen, setNotifSeen] = useState(false);
  const [stack, setStack] = useState([{ s: 'hub', p: {} }]);
  const [phase, setPhaseRaw] = useState('live');     // pre | live | post (panel demo)
  const [staffState, setStaffState] = useState('onduty'); // new | kit | onduty | offduty
  O.applyPhase(phase);                                // đồng bộ ngày/ROS/chủ đề theo giai đoạn

  // ---- store vận hành (trạng thái nhiệm vụ · sự cố · onboard) ----
  const [taskStatus, setTaskStatus] = useState(() => Object.fromEntries(O.tasks.map((t) => [t.id, t.status])));
  const [taskSteps, setTaskSteps] = useState(() => Object.fromEntries(O.tasks.map((t) => [t.id, t.steps.map((s) => s.done)])));
  const [doneAt, setDoneAt] = useState(() => Object.fromEntries(O.tasks.filter((t) => t.status === 'done').map((t) => [t.id, t.window && t.window.includes('–') ? t.window.split('–')[1] : window.OPS_NOW])));
  const [reports, setReports] = useState({}); // taskId -> [{id, by, at, note, photos:[dataURL]}]
  const [incStatus, setIncStatusMap] = useState(() => Object.fromEntries(O.incidents.map((i) => [i.id, i.status])));
  const [extraInc, setExtraInc] = useState([]);
  const [onbSteps, setOnbSteps] = useState(() => O.onboarding.steps.map(() => false));
  const [reqStatus, setReqStatusMap] = useState(() => Object.fromEntries(O.requests.map((rq) => [rq.id, rq.status])));
  const [extraReq, setExtraReq] = useState([]);
  // ---- vòng đời nhân sự (kit · điểm danh vào/tan ca) ----
  const [kit, setKit] = useState(() => O.kit.map(() => true));
  const [shiftIn, setShiftIn] = useState('06:05');
  const [shiftOut, setShiftOut] = useState(null);
  // ---- LỚP GIỮ CONNECT (offline · outbox · sync · audit) — học từ Field App ----
  const [online, setOnline] = useState(true);
  const [queue, setQueue] = useState([]);
  const [toasts, setToasts] = useState([]);
  const _tt = (vi, en) => (lang === 'en' ? en : vi);
  function pushToast(o) { const id = Date.now() + Math.random(); setToasts((s) => [...s, { ...o, id }]); setTimeout(() => setToasts((s) => s.filter((x) => x.id !== id)), 2600); }
  function commitAction(label, apply, opts = {}) {
    if (apply) apply();
    if (online) pushToast({ title: label, sub: _tt('\u0110\u00e3 \u0111\u1ed3ng b\u1ed9 control tower \u00b7 ghi audit', 'Synced to control tower \u00b7 audited'), tone: opts.tone || 'ok' });
    else { setQueue((q) => [...q, { t: window.OPS_NOW, label }]); pushToast({ title: label, sub: _tt('\u0110\u00e3 l\u01b0u offline \u00b7 ch\u1edd \u0111\u1ed3ng b\u1ed9', 'Saved offline \u00b7 queued'), tone: 'warn' }); }
  }
  function syncNow() { if (!queue.length) return; const n = queue.length; setOnline(true); setQueue([]); pushToast({ title: _tt('\u0110\u00e3 \u0111\u1ed3ng b\u1ed9 ' + n + ' thao t\u00e1c', 'Synced ' + n + ' actions'), sub: _tt('Control tower \u0111\u00e3 c\u1eadp nh\u1eadt', 'Control tower updated'), tone: 'ok' }); }
  function applyStaffState(id) {
    setStaffState(id);
    if (id === 'new') { setKit(O.kit.map(() => false)); setShiftIn(null); setShiftOut(null); }
    else if (id === 'kit') { setKit(O.kit.map(() => true)); setShiftIn(null); setShiftOut(null); }
    else if (id === 'onduty') { setKit(O.kit.map(() => true)); setShiftIn('06:05'); setShiftOut(null); }
    else if (id === 'offduty') { setKit(O.kit.map(() => true)); setShiftIn('06:05'); setShiftOut('12:02'); }
  }

  const store = {
    meRole: role,
    taskStatus, taskSteps, doneAt,
    setTStatus: (id, st) => {
      setTaskStatus((s) => ({ ...s, [id]: st }));
      if (st === 'done') setDoneAt((d) => (d[id] ? d : { ...d, [id]: window.OPS_NOW }));
      else setDoneAt((d) => { if (!d[id]) return d; const n = { ...d }; delete n[id]; return n; });
    },
    toggleStep: (id, i) => setTaskSteps((s) => ({ ...s, [id]: s[id].map((v, j) => (j === i ? !v : v)) })),
    reports,
    addReport: (taskId, o) => setReports((s) => ({ ...s, [taskId]: [{ ...o }, ...(s[taskId] || [])] })),
    incStatus,
    setIncStatus: (id, st) => setIncStatusMap((s) => ({ ...s, [id]: st })),
    extraInc, addInc: (o) => { setExtraInc((s) => [o, ...s]); setIncStatusMap((s) => ({ ...s, [o.id]: o.status })); },
    onbSteps, toggleOnb: (i) => setOnbSteps((s) => s.map((v, j) => (j === i ? !v : v))),
    reqStatus,
    setReqStatus: (id, st) => setReqStatusMap((s) => ({ ...s, [id]: st })),
    extraReq, addReq: (o) => { setExtraReq((s) => [o, ...s]); setReqStatusMap((s) => ({ ...s, [o.id]: o.status })); },
    kit, toggleKit: (i) => setKit((s) => s.map((v, j) => (j === i ? !v : v))),
    shiftIn, shiftOut, setShiftIn, setShiftOut,
    online, setOnline, queue, syncNow, commit: commitAction, pushToast,
  };

  const opsPanel = ReactDOM.createPortal(
    <OpsDemoPanel {...{ phase, setPhase: setPhaseRaw, lang, setLang, staffState, applyStaffState, role, account, setAccount: switchAccount, online, setOnline, queue, syncNow, onRelogin: () => { setRole(null); setStack([{ s: 'hub', p: {} }]); setPerm(false); setLoading(false); } }} />,
    document.getElementById('vlf-ops-panel-root'));
  function switchAccount(id) {
    setAccount(id);
    if (role) { setRole(id); setStack([{ s: 'hub', p: {} }]); setNotifSeen(false); }
  }

    function zaloAuth() {
    setPerm(false);
    setLoading(true);
    setTimeout(() => { setRole(account); setStack([{ s: 'hub', p: {} }]); setNotifSeen(false); setLoading(false); }, 1500);
  }

  const T = (vi, en) => (lang === 'en' ? en : vi);
  const r = role ? window.VLF.staffRoleById(role) : null;
  const isBtc = r && r.group === 'btc';
  const team = role ? O.teamForRole(role) : null;

  function nav(s, p = {}) {
    if (s === 'back') { setStack((st) => (st.length > 1 ? st.slice(0, -1) : st)); return; }
    if (OPS_TABS.includes(s)) { setStack([{ s, p }]); return; }
    setStack((st) => [...st, { s, p }]);
  }

  // ---- LOGIN ----
  if (!role) {
    return (
      <>
      {opsPanel}
      <div className="za-frame" data-scheme="dark" data-variant="fullscreen"
        style={{ position: 'relative', '--zalo-header-bg': '#31153D', '--zalo-header-fg': '#fff', '--zalo-statusbar-fg': '#fff' }}>
        <div className="za-phone"><div className="za-island" /><div className="za-screen">
          <div className="za-content" style={{ padding: 0 }}>
            <OpsLogin lang={lang} account={account} setAccount={setAccount} perm={perm} loading={loading} onLogin={() => setPerm(true)} onAuth={zaloAuth} T={T} />
          </div>
          <ZaloChrome variant="fullscreen" scheme="dark" time="06:18" battery={82} />
        </div></div>
      </div>
      </>);
  }

  const cur = stack[stack.length - 1];
  const rootTab = stack[0].s;
  const isTab = OPS_TABS.includes(cur.s);
  const variant = isTab ? 'home' : 'page';
  const notifs = O.notifsFor(role);
  const notifUnread = notifSeen ? 0 : notifs.filter((n) => n.unread).length;

  function screen() {
    switch (cur.s) {
      case 'hub': return <OpsHub nav={nav} role={r} isBtc={isBtc} phase={phase} store={store} />;
      case 'tasks': return <OpsTasksBoard nav={nav} store={store} team={team} isBtc={isBtc} initTeam={cur.p.team} phase={phase} />;
      case 'coord': return <OpsCoord nav={nav} store={store} team={team} isBtc={isBtc} reportOpen={cur.p.report} />;
      case 'book': return <OpsBook nav={nav} store={store} team={team} role={r} />;
      case 'me': return <OpsMe role={r} team={team} isBtc={isBtc} lang={lang} setLang={setLang} nav={nav} onLogout={() => { setRole(null); setStack([{ s: 'hub', p: {} }]); setPerm(false); setLoading(false); }} T={T} />;
      case 'task': return <TaskDetail id={cur.p.id} nav={nav} store={store} />;
      case 'incident': return <IncidentDetail id={cur.p.id} nav={nav} store={store} />;
      case 'sop': return <SopDetail id={cur.p.id} nav={nav} />;
      case 'onboard': return <OnboardFlow nav={nav} store={store} />;
      case 'brief': return <BriefingDetail />;
      case 'emg': return <EmergencyRef />;
      case 'notifs': return <OpsNotifications nav={nav} role={role} onSeen={() => setNotifSeen(true)} />;
      case 'guide': return <OpsGuide nav={nav} />;
      case 'comments': return <CommentsFeed nav={nav} store={store} team={team} isBtc={isBtc} />;
      case 'requests': return <RequestsScreen nav={nav} store={store} team={team} isBtc={isBtc} role={r} />;
      case 'newrequest': return <NewRequest nav={nav} store={store} team={team} role={r} />;
      case 'checkin': return <ShiftCheckin nav={nav} store={store} team={team} role={r} />;
      default: return <OpsHub nav={nav} role={r} isBtc={isBtc} />;
    }
  }

  const titles = {
    hub: T('Tổng quan vận hành', 'Operations'), tasks: T('Bảng nhiệm vụ', 'Task board'),
    coord: T('Điều phối trực tiếp', 'Live coordination'), book: T('Sổ tay công việc', 'Handbook'),
    me: T('Tài khoản', 'Account'), task: T('Chi tiết nhiệm vụ', 'Task'), incident: T('Chi tiết sự cố', 'Incident'),
    sop: T('Sổ tay', 'Handbook'), onboard: T('Onboard nhân sự', 'Onboarding'), brief: T('Briefing sáng', 'Briefing'), emg: T('Khẩn cấp', 'Emergency'),
    notifs: T('Thông báo', 'Notifications'), guide: T('Hướng dẫn dùng app', 'How to use the app'),
    comments: T('Trao đổi & nhắc tên', 'Comments & mentions'), requests: T('Đơn từ', 'Requests'), newrequest: T('Tạo đơn', 'New request'),
    checkin: T('Vào ca & điểm danh', 'Shift & roll-call'),
  };
  const TABS = [
    { id: 'hub', ic: isBtc ? 'shield' : 'user', label: T('Tổng quan', 'Overview') },
    { id: 'tasks', ic: 'check', label: T('Nhiệm vụ', 'Tasks') },
    { id: 'coord', ic: 'bell', label: T('Điều phối', 'Coord') },
    { id: 'book', ic: 'survey', label: T('Sổ tay', 'Handbook') },
    { id: 'me', ic: 'user', label: T('Tài khoản', 'Account') },
  ];

  return (
    <LangCtx.Provider value={lang}>
      {opsPanel}
      <div className="za-frame" data-scheme="dark" data-variant={variant}
        style={{ position: 'relative', '--zalo-header-bg': '#31153D', '--zalo-header-fg': '#fff', '--zalo-statusbar-fg': '#fff' }}>
        <div className="za-phone"><div className="za-island" /><div className="za-screen">
          <div className="za-content" key={cur.s + JSON.stringify(cur.p)} style={{ paddingBottom: 0 }}>
            <div className="v-screen" data-screen-label={cur.s + ' · ' + (isBtc ? 'BTC' : 'TNV')} style={{ paddingBottom: isTab ? 'calc(64px + var(--zalo-safe-bottom))' : 'calc(22px + var(--zalo-safe-bottom))' }}>
              <div className="v-pad"><ConnectStrip store={store} />{screen()}</div>
            </div>
          </div>
          {isTab && (
            <div className="v-tabbar v-tabbar--ops">
              {TABS.map((tb) => (
                <div key={tb.id} className={'v-tab' + (rootTab === tb.id ? ' on' : '')} onClick={() => nav(tb.id)}>
                  <span className="ic"><Icon name={tb.ic} size={22} sw={rootTab === tb.id ? 2 : 1.6} /></span>
                  <span>{tb.label}</span>
                </div>
              ))}
            </div>
          )}
          <ZaloChrome variant={variant} appName={titles[cur.s]} appSub={isTab ? (isBtc ? 'BTC · ' + r.me : 'TNV · ' + r.me) : ''} title={titles[cur.s]} onBack={() => nav('back')} logo={<VLFOpsLogo />} scheme="dark" time="06:18" battery={82} />
          {cur.s !== 'notifs' && <OpsBell count={notifUnread} onClick={() => nav('notifs')} />}
          {cur.s !== 'guide' && <OpsHelpBtn onClick={() => nav('guide')} />}
          <OpsToasts toasts={toasts} />
        </div></div>
      </div>
    </LangCtx.Provider>);
}

/* logo ops */
function VLFOpsLogo() {
  return <svg viewBox="0 0 36 36" aria-hidden="true"><rect width="36" height="36" fill="#31153D" /><text x="18" y="24" textAnchor="middle" fontFamily="'Be Vietnam Pro',sans-serif" fontWeight="800" fontSize="13" fill="#E8CE8B">OPS</text></svg>;
}

/* ---------- LOGIN: đăng nhập Zalo (trượt lên) → tự nạp vai trò đã mapping ---------- */
function OpsLogin({ lang, account, setAccount, perm, loading, onLogin, onAuth, T }) {
  const roles = window.VLF.staffRoles;
  const acc = window.VLF.staffRoleById(account);
  const isBtc = acc.group === 'btc';

  if (loading) {
    return (
      <div className="v-onboard v-ops-onboard">
        <div className="inner" style={{ justifyContent: 'center', alignItems: 'center', textAlign: 'center' }}>
          <div className="v-ops-spin" />
          <div className="kk" style={{ color: 'var(--vlf-gold-300)', marginTop: 26 }}>{T('Đã xác thực Zalo', 'Zalo verified')}</div>
          <h1 style={{ marginTop: 6 }}>{T('Đang tải vai trò…', 'Loading your role…')}</h1>
          <p className="lede" style={{ margin: '12px auto 0', textAlign: 'center' }}>
            {T('Tài khoản Zalo của bạn đã được gán sẵn:', 'Your Zalo account is mapped to:')}<br />
            <b style={{ color: 'var(--vlf-gold-300)' }}>{(isBtc ? 'BTC · ' : 'TNV · ') + window.VLF.L(lang, acc, 'name')}</b>
            {acc.zone ? ' · ' + window.VLF.L(lang, acc, 'zone') : ''}
          </p>
        </div>
      </div>);
  }

  return (
    <div className="v-onboard v-ops-onboard">
      <div className="inner">
        <div style={{ marginBottom: 22 }}><OrgLogos /></div>
        <div className="kk" style={{ color: 'var(--vlf-gold-300)' }}>VLF 2026 · {T('Vận hành', 'Operations')}</div>
        <h1>{T('App Đội vận hành', 'Operations app')}</h1>
        <p className="lede">{T('Dành riêng cho Ban tổ chức & Tình nguyện viên. Đăng nhập bằng Zalo — app tự nhận đúng vai trò, tiểu ban và khu vực đã gán cho tài khoản của bạn.', 'For the Organising Committee & Volunteers. Sign in with Zalo — the app loads the role, subcommittee and zone mapped to your account.')}</p>

        <div className="v-ops-maprow">
          <div className="ic" style={isBtc ? undefined : { background: 'rgba(201,162,75,.18)', color: 'var(--vlf-gold-300)' }}><Icon name={isBtc ? 'shield' : 'user'} size={18} sw={1.7} /></div>
          <div className="tx">
            <div className="lbl">{T('Tài khoản Zalo · đã mapping', 'Zalo account · mapped')}</div>
            <b>{acc.me}</b>
            <span>{(isBtc ? 'BTC' : 'TNV') + ' · ' + window.VLF.L(lang, acc, 'name')}{acc.zone ? ' · ' + window.VLF.L(lang, acc, 'zone') : ''}</span>
          </div>
        </div>

        <div className="foot">
          <button className="v-btn v-ops-zalo" onClick={onLogin}>
            <span className="zg" aria-hidden="true"><svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M12 3C6.5 3 2 6.6 2 11.1c0 2.5 1.4 4.7 3.6 6.2-.1.9-.5 2.1-1.2 3.1-.2.3.1.7.4.6 1.8-.5 3.2-1.3 4.1-1.9 1 .2 2 .3 3.1.3 5.5 0 10-3.6 10-8.4S17.5 3 12 3z" /></svg></span>
            {T('Đăng nhập bằng Zalo', 'Continue with Zalo')}
          </button>
          <div className="v-ops-demo">
            <label>{T('Demo · chọn tài khoản Zalo đã mapping', 'Demo · pick a mapped Zalo account')}</label>
            <select value={account} onChange={(e) => setAccount(e.target.value)}>
              <optgroup label="BTC">
                {roles.filter((x) => x.group === 'btc').map((x) => <option key={x.id} value={x.id}>{window.VLF.L(lang, x, 'name')} · {x.me}</option>)}
              </optgroup>
              <optgroup label="TNV">
                {roles.filter((x) => x.group === 'tnv').map((x) => <option key={x.id} value={x.id}>{window.VLF.L(lang, x, 'name')} · {x.me}</option>)}
              </optgroup>
            </select>
          </div>
        </div>
      </div>

      {perm &&
        <ZaloPermissionSheet
          appName={T('VLF 2026 · Vận hành', 'VLF 2026 · Operations')}
          appearance="light"
          userName={acc.me}
          logo={<VLFOpsLogo />}
          onDeny={onAuth}
          onAllow={onAuth} />
      }
    </div>);
}

/* ---------- TÀI KHOẢN ops (mở rộng: đội · roster · liên hệ · onboard) ---------- */
function OpsMe({ role, team, isBtc, lang, setLang, onLogout, nav, T }) {
  const O = window.VLF.ops;
  return (
    <>
      <div className="v-card ops-rolecard" style={{ marginTop: 4 }}>
        <OpsAva name={role.me} size={48} />
        <div style={{ flex: 1, minWidth: 0 }}>
          <div className="ops-rc-name">{role.me}</div>
          <div className="ops-rc-sub">{window.VLF.L(lang, role, 'name')}{role.zone ? ' · ' + window.VLF.L(lang, role, 'zone') : ''}</div>
          <div className="ops-rc-team"><i style={{ background: team.color }} />{team.members.length} {trL(lang, { vi: 'thành viên', en: 'members' })} · {trL(lang, { vi: 'Bộ đàm', en: 'Radio' })} {team.radio}</div>
        </div>
        <span className="v-tag" style={{ color: isBtc ? 'var(--vlf-purple-700)' : 'var(--vlf-gold-700)' }}>{isBtc ? 'BTC' : 'TNV'}</span>
      </div>

      <div className="v-card ops-onb-mini" onClick={() => nav('onboard')}>
        <div className="ops-onb-mini-ic"><Icon name="survey" size={18} sw={1.7} /></div>
        <div style={{ flex: 1 }}><div className="t">{trL(lang, { vi: 'Onboard & sổ tay của tôi', en: 'My onboarding & handbook' })}</div><div className="s">{O.onboarding.steps.length} {trL(lang, { vi: 'bước chuẩn bị vào ca', en: 'steps to be shift-ready' })}</div></div>
        <Icon name="chev" size={18} className="chev" />
      </div>

      <div className="v-me-group" style={{ marginTop: 18 }}><div className="lbl">{trL(lang, { vi: 'Công việc của tôi', en: 'My workspace' })}</div>
        <div className="v-card">
          <div className="v-row" onClick={() => nav('checkin')}>
            <div className="ops-guide-ic" style={{ background: 'rgba(31,138,91,.12)', color: '#1F8A5B' }}><Icon name="qr" size={18} sw={1.7} /></div>
            <div style={{ flex: 1, minWidth: 0 }}><div className="t">{trL(lang, { vi: 'Vào ca & điểm danh', en: 'Shift & roll-call' })}</div><div className="s">{trL(lang, { vi: 'Nhận kit · check-in đầu ca · tan ca', en: 'Get kit · check in · check out' })}</div></div>
            <Icon name="chev" size={18} className="chev" />
          </div>
          <div className="v-row" onClick={() => nav('requests')}>
            <div className="ops-guide-ic" style={{ background: 'var(--vlf-purple-50)', color: 'var(--vlf-purple-700)' }}><Icon name="calendar" size={18} sw={1.7} /></div>
            <div style={{ flex: 1, minWidth: 0 }}><div className="t">{trL(lang, { vi: 'Đơn từ của tôi', en: 'My requests' })}</div><div className="s">{trL(lang, { vi: 'Xin nghỉ · đổi ca · đến muộn · vắng', en: 'Time-off · swap · late · absence' })}</div></div>
            <Icon name="chev" size={18} className="chev" />
          </div>
          <div className="v-row" onClick={() => nav('comments')}>
            <div className="ops-guide-ic" style={{ background: 'rgba(201,162,75,.16)', color: 'var(--vlf-gold-700)' }}><Icon name="survey" size={18} sw={1.7} /></div>
            <div style={{ flex: 1, minWidth: 0 }}><div className="t">{trL(lang, { vi: 'Trao đổi & nhắc tên', en: 'Comments & mentions' })}</div><div className="s">{trL(lang, { vi: 'Bình luận theo nhiệm vụ liên quan đến bạn', en: 'Task comments involving you' })}</div></div>
            <Icon name="chev" size={18} className="chev" />
          </div>
        </div>
      </div>

      <div className="v-me-group" style={{ marginTop: 18 }}><div className="lbl">{trL(lang, { vi: 'Đội của tôi · ' + team.members.length + ' người', en: 'My team · ' + team.members.length })}</div>
        <div className="v-card" style={{ padding: '12px 14px' }}>
          <div className="ops-roster">
            {team.members.map((m, i) => (
              <span className="ops-roster-p" key={i}>
                <OpsAva name={m} size={30} />
                <span className="nm">{m}{m === team.lead && <i className="ops-leadbadge">{trL(lang, { vi: 'đội trưởng', en: 'lead' })}</i>}</span>
              </span>
            ))}
          </div>
          {(team.role || team.note) && (
            <div className="ops-team-meta">
              {team.role && <div className="r"><span className="k">{trL(lang, { vi: 'Vai trò kênh ' + team.radio, en: 'Channel ' + team.radio })}</span>{trL(lang, team.role)}</div>}
              {team.note && <div className="n"><Icon name="info" size={12} sw={2} />{trL(lang, team.note)}</div>}
            </div>
          )}
        </div>
      </div>

      <div className="v-me-group"><div className="lbl">{trL(lang, { vi: 'Liên hệ điều phối', en: 'Coordination' })}</div>
        <div className="v-card">
          <div className="v-row" style={{ cursor: 'default' }}><div style={{ flex: 1 }}><div className="t">{trL(lang, { vi: 'Đội trưởng trực', en: 'Shift lead' })}</div><div className="s">{team.lead} · 094 552 028</div></div><Icon name="bell" size={18} className="chev" /></div>
          <div className="v-row" style={{ cursor: 'default' }}><div style={{ flex: 1 }}><div className="t">{trL(lang, { vi: 'Tổng đài vận hành', en: 'Ops hotline' })}</div><div className="s">1900 6026 · CH1</div></div><Icon name="bell" size={18} className="chev" /></div>
          <div className="v-row" onClick={() => nav('emg')}><div style={{ flex: 1 }}><div className="t">{trL(lang, { vi: 'Tham chiếu khẩn cấp', en: 'Emergency reference' })}</div><div className="s">{trL(lang, { vi: 'Số gọi · sơ tán · bộ đàm', en: 'Hotlines · evac · radio' })}</div></div><Icon name="chev" size={18} className="chev" /></div>
        </div>
      </div>

      <div className="v-me-group"><div className="lbl">{trL(lang, { vi: 'Ngôn ngữ', en: 'Language' })}</div>
        <div className="v-lang"><button className={lang === 'vi' ? 'on' : ''} onClick={() => setLang('vi')}>Tiếng Việt</button><button className={lang === 'en' ? 'on' : ''} onClick={() => setLang('en')}>English</button></div>
      </div>
      <button className="v-btn v-btn-ghost" onClick={onLogout}>{trL(lang, { vi: 'Đổi vai trò / Đăng xuất', en: 'Switch role / Sign out' })}</button>
      <p className="v-muted" style={{ fontSize: 11, textAlign: 'center', lineHeight: 1.5, marginTop: 14 }}>VLF 2026 · {trL(lang, { vi: 'App nội bộ đội vận hành', en: 'Internal operations app' })}</p>
    </>);
}

ReactDOM.createRoot(document.getElementById('vlf-ops-root')).render(<OpsRoot />);

/* ---------- DEMO PANEL (thanh điều khiển bên trái · ẩn trên màn nhỏ) ---------- */
function OpsDemoPanel({ phase, setPhase, lang, setLang, staffState, applyStaffState, role, account, setAccount, online, setOnline, queue, syncNow, onRelogin }) {
  const O = window.VLF.ops;
  const roles = window.VLF.staffRoles;
  const acc = window.VLF.staffRoleById(account);
  const T = (vi, en) => (lang === 'en' ? en : vi);
  return (
    <div className="vlf-panel">
      <div className="kk">App Đội vận hành · {T('Bản demo', 'Demo')}</div>
      <h1>VLF 2026 <em>Operations</em></h1>
      <p className="lede">{T('App nội bộ cho đội vận hành hiện trường — BTC, cộng tác viên & tình nguyện viên. Điều khiển dưới đây để xem app theo từng giai đoạn & trạng thái nhân sự.', 'Internal app for the on-site operations crew — OC, collaborators & volunteers. Use the controls to preview each phase & staff state.')}</p>

      <div className="vlf-grp"><div className="lbl">{T('Giai đoạn vận hành', 'Operations phase')}</div>
        <div className="vlf-seg" style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 3 }}>
          {O.phaseMeta.map((p) => (
            <button key={p.id} className={phase === p.id ? 'on' : ''} onClick={() => setPhase(p.id)}>{trL(lang, p.label)}<small>{trL(lang, p.sub)}</small></button>
          ))}
        </div>
        <div className="vlf-panel-hint">{T('Đổi giai đoạn → Biến thể nhiệm vụ, run-of-show & KPI thay theo: trước · trong · sau giải.', 'Switch phase → tasks, run-of-show & KPIs change across pre · live · post.')}</div>
      </div>

      <div className="vlf-grp"><div className="lbl">{T('Tài khoản Zalo · đã mapping', 'Zalo account · mapped')}</div>
        <select value={account} onChange={(e) => setAccount(e.target.value)} className="vlf-panel-sel">
          <optgroup label="BTC">{roles.filter((x) => x.group === 'btc').map((x) => <option key={x.id} value={x.id}>{window.VLF.L(lang, x, 'name')} · {x.me}</option>)}</optgroup>
          <optgroup label="TNV">{roles.filter((x) => x.group === 'tnv').map((x) => <option key={x.id} value={x.id}>{window.VLF.L(lang, x, 'name')} · {x.me}</option>)}</optgroup>
        </select>
        <div className="vlf-panel-hint">{role ? T('Đang đăng nhập', 'Signed in') + ': ' + role.me : T('Đăng nhập để áp tài khoản này', 'Sign in to apply this account')}</div>
      </div>

      <div className="vlf-grp"><div className="lbl">{T('Trạng thái nhân sự · vòng đời ca', 'Staff lifecycle state')}</div>
        <div className="vlf-seg" style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 3 }}>
          <button className={staffState === 'new' ? 'on' : ''} onClick={() => applyStaffState('new')}>{T('Nhân sự mới', 'New staff')}<small>{T('chưa nhận kit', 'no kit yet')}</small></button>
          <button className={staffState === 'kit' ? 'on' : ''} onClick={() => applyStaffState('kit')}>{T('Đã nhận kit', 'Kit ready')}<small>{T('chưa vào ca', 'not checked in')}</small></button>
          <button className={staffState === 'onduty' ? 'on' : ''} onClick={() => applyStaffState('onduty')}>{T('Đang trong ca', 'On duty')}<small>{T('đã điểm danh', 'rolled-call')}</small></button>
          <button className={staffState === 'offduty' ? 'on' : ''} onClick={() => applyStaffState('offduty')}>{T('Đã tan ca', 'Off duty')}<small>{T('đã báo về', 'checked out')}</small></button>
        </div>
      </div>

      <div className="vlf-grp"><div className="lbl">{T('Lớp giữ connect · demo', 'Connectivity layer · demo')}</div>
        <div className="vlf-conn-row">
          <button className={'vlf-conn-toggle' + (online ? '' : ' off')} onClick={() => setOnline(!online)} aria-label="online/offline" />
          <div className="vlf-conn-meta"><b>{online ? T('Trực tuyến · 4G', 'Online · 4G') : T('Mất sóng · ngoại tuyến', 'Offline')}</b><br />{T('Tắt mạng rồi thao tác — việc xếp hàng, tự đẩy khi có mạng.', 'Go offline, then act — actions queue and auto-push when back.')}</div>
        </div>
        <button className="vlf-conn-sync" disabled={!queue.length} onClick={syncNow}>{queue.length ? T('Đồng bộ ' + queue.length + ' thao tác chờ', 'Sync ' + queue.length + ' queued') : T('Hàng đợi trống', 'Queue empty')}</button>
        <div className="vlf-panel-hint">{T('Strip trạng thái hiện đầu màn khi offline hoặc còn hàng đợi. Thử: Worklist → “Mở” khi offline.', 'A status strip shows when offline or queued. Try the worklist offline.')}</div>
      </div>

      <div className="vlf-grp"><div className="lbl">{T('Ngôn ngữ', 'Language')}</div>
        <div className="vlf-seg">
          <button className={lang === 'vi' ? 'on' : ''} onClick={() => setLang('vi')}>Tiếng Việt</button>
          <button className={lang === 'en' ? 'on' : ''} onClick={() => setLang('en')}>English</button>
        </div>
      </div>

      <div className="vlf-grp"><div className="lbl">{T('Luồng vào app', 'Entry flow')}</div>
        <div className="vlf-seg" style={{ gridTemplateColumns: '1fr' }}>
          <button onClick={onRelogin}>{T('Chạy lại đăng nhập Zalo', 'Restart Zalo sign-in')}</button>
        </div>
      </div>

      <div className="vlf-note">
        <b>{T('Phân cấp điều hướng', 'Navigation by level')}:</b> {T('màn gốc (tab) có thanh điều hướng; đi sâu hay bắt đầu tác vụ thì bỏ tab, dùng header back. Footer:', 'root tabs keep the bottom bar; detail & task flows hide it and use a back header. Footer:')} <code>showTabbar</code>.
      </div>
    </div>
  );
}

/* scaler */
function opsFit() {
  const s = document.getElementById('vlf-ops-scaler'); if (!s) return;
  const panelW = window.innerWidth > 920 ? 362 : 0;
  const availW = window.innerWidth - panelW - 44;
  const scale = Math.min(availW / 390, (window.innerHeight - 40) / 844, 1.1);
  s.style.transform = 'scale(' + Math.max(scale, 0.3) + ')';
}
window.addEventListener('resize', opsFit); opsFit(); setTimeout(opsFit, 60);
