// Person detail — compact row layout
// Rule: operator must OPEN the profile before Verify is enabled.
// Adjust = just edit the handle. Add = type a handle into an empty row.

const { useState: useStateV, useEffect: useEffectV, useMemo: useMemoV } = React;

function PersonDetail({ person, queue, onSelect, onUpdate, onUpdateProfile, onClose, onNextPerson, onPrevPerson, onToast, onSave, locks = {}, currentUser }) {
  const counts = computeCounts(person, PLATFORMS);
  const profCounts = computeProfileCounts(person);

  // Use predefined category list
  const categorySuggestions = CATEGORIES;

  const setProfileStatus = (key, newStatus) => {
    onUpdateProfile(person.id, key, (cur) => {
      const updated = { ...cur, status: newStatus };
      if (newStatus === 'verified') {
        updated.verified_by = currentUser?.id || null;
      } else if (newStatus !== 'qc') {
        updated.verified_by = null;
      }
      return updated;
    });
    onToast(`${key === 'country' ? 'Country' : 'Category'} → ${STATUS_META[newStatus].label}`);
  };
  const updateProfileMerged = (key, v) => {
    onUpdateProfile(person.id, key, (cur) => {
      const newProfile = { ...cur, merged: v };
      
      // Auto-set to trusted if tool, mc, and selected all match
      const { sports: tool, panel: mc } = newProfile;
      const selected = v;
      
      if (tool && mc && selected && tool === mc && mc === selected) {
        newProfile.status = 'trusted';
      } else if (cur.status === 'trusted' && !(tool === mc && mc === selected)) {
        // If it was trusted but values no longer match, reset to unverified
        newProfile.status = 'unverified';
      } else if (cur.status === 'qc' || cur.status === 'verified') {
        // Reset verified/qc to unverified when merged value changes
        newProfile.status = 'unverified';
      }
      
      return newProfile;
    });
  };
  const [opened, setOpened] = useStateV(() => {
    try { return JSON.parse(sessionStorage.getItem('shqt_opened') || '{}'); }
    catch { return {}; }
  });
  useEffectV(() => { sessionStorage.setItem('shqt_opened', JSON.stringify(opened)); }, [opened]);

  const openKey = (pid, plid, handleIndex, handle) => `${pid}:${plid}:${handleIndex}:${handle}`;
  const isOpened = (pl, handleIndex) => {
    const handles = person.handles[pl.id];
    const h = Array.isArray(handles) ? handles[handleIndex] : handles;
    return !!opened[openKey(person.id, pl.id, handleIndex, h?.merged || '')];
  };
  const markOpened = (pl, handleIndex) => {
    const handles = person.handles[pl.id];
    const h = Array.isArray(handles) ? handles[handleIndex] : handles;
    setOpened(o => ({ ...o, [openKey(person.id, pl.id, handleIndex, h?.merged || '')]: Date.now() }));
  };

  // "Searched" state for EMPTY rows — operator must run a platform search
  // for the person before confirming there's no account on that platform.
  // Keyed per (person, platform) since the handle itself is empty.
  const [searched, setSearched] = useStateV(() => {
    try { return JSON.parse(sessionStorage.getItem('shqt_searched') || '{}'); }
    catch { return {}; }
  });
  useEffectV(() => { sessionStorage.setItem('shqt_searched', JSON.stringify(searched)); }, [searched]);
  const searchKey = (pid, plid, handleIndex = 0) => `${pid}:${plid}:${handleIndex}`;
  const isSearched = (pl, handleIndex = 0) => !!searched[searchKey(person.id, pl.id, handleIndex)];
  const markSearched = (pl, handleIndex = 0) => setSearched(s => ({ ...s, [searchKey(person.id, pl.id, handleIndex)]: Date.now() }));
  const clearSearched = (pl, handleIndex = 0) => setSearched(s => {
    const n = { ...s }; delete n[searchKey(person.id, pl.id, handleIndex)]; return n;
  });

  useEffectV(() => {
    const handler = (e) => {
      if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;
      if (e.key === 'Escape') onClose();
      else if (e.key === ']') onNextPerson();
      else if (e.key === '[') onPrevPerson();
    };
    window.addEventListener('keydown', handler);
    return () => window.removeEventListener('keydown', handler);
  });

  const setStatus = (platformId, handleIndex, newStatus) => {
    onUpdate(person.id, platformId, handleIndex, (h) => {
      const updated = { ...h, status: newStatus };
      if (newStatus === 'verified') {
        updated.verified_by = currentUser?.id || null;
      } else if (newStatus !== 'qc') {
        // Clear verified_by when resetting to unverified/missing, but keep it for QC
        updated.verified_by = null;
      }
      return updated;
    });
    onToast(`${PLATFORMS.find(p=>p.id===platformId).name} #${handleIndex + 1} → ${STATUS_META[newStatus].label}`);
  };
  const updateMerged = (platformId, handleIndex, v) => {
    onUpdate(person.id, platformId, handleIndex, (h) => ({...h, merged: v, status: h.status === 'qc' ? 'unverified' : h.status === 'verified' ? 'unverified' : (h.status === 'missing' && v) ? 'unverified' : h.status }));
    // reset open state
    setOpened(o => {
      const n = {...o};
      Object.keys(n).forEach(k => { if (k.startsWith(`${person.id}:${platformId}:${handleIndex}:`)) delete n[k]; });
      return n;
    });
    // typing a handle invalidates any "searched (no account)" verification
    if (v) clearSearched({ id: platformId }, handleIndex);
  };

  const pct = (counts.qc + counts['non-existing']) / counts.total;

  return (
    <div className="detail">
      {/* LEFT: queue */}
      <aside className="queue">
        <div className="queue-head">
          <div className="q-title"><Icon name="inbox" size={14}/> Queue <Pill kind="neutral">{queue.length}</Pill></div>
          <div className="q-sub">People with work pending.</div>
        </div>
        <div className="queue-list">
          {queue.map(q => {
            const c = computeCounts(q, PLATFORMS);
            const active = q.id === person.id;
            const o = overallStatus(c);
            return (
              <div key={q.id} className={`queue-row ${active ? 'active' : ''}`} onClick={() => onSelect(q.id)}>
                <div className="qr-name">
                  <div className="nmavatar" style={{width: 22, height: 22, fontSize: 10}}>{q.name.split(' ').map(w=>w[0]).slice(0,2).join('')}</div>
                  <span style={{flex: 1}}>{q.name}</span>
                  {locks[q.id] && <LockChip lock={locks[q.id]} size={16}/>}
                  <Pill kind={o.kind}>{o.label}</Pill>
                </div>
                <div className="qr-tiles">
                  {PLATFORMS.map(pl => {
                    const handles = q.handles[pl.id];
                    const displayHandle = Array.isArray(handles) ? getMostAdvancedStatus(handles) : handles;
                    return (
                      <Tile 
                        key={pl.id} 
                        platform={pl.id} 
                        status={displayHandle.status}
                        title={Array.isArray(handles) && handles.length > 1 ? `${handles.length} handles` : undefined}
                      />
                    );
                  })}
                </div>
                <div className="qr-meta"><span>{q.category}</span> · <span>{q.country}</span> · <span>{c.qc + c['non-existing']}/{c.total}</span></div>
              </div>
            );
          })}
        </div>
      </aside>

      {/* RIGHT: verification */}
      <section className="verify">
        <div className="verify-head">
          <div style={{display: 'flex', alignItems: 'center', gap: 10}}>
            <button className="btn ghost sm" onClick={onClose}><Icon name="chevL" size={13}/> All records</button>
            <div style={{flex: 1}}/>
            <button className="btn sm" onClick={onPrevPerson} title="Previous ([)"><Icon name="chevL" size={13}/></button>
            <button className="btn sm" onClick={onNextPerson} title="Next (])">Next <Icon name="chevR" size={13}/></button>
          </div>
          <h1 className="vh-name">
            <div className="nmavatar" style={{width: 34, height: 34, fontSize: 13}}>{person.name.split(' ').map(w=>w[0]).slice(0,2).join('')}</div>
            {person.name}
            <Pill kind={overallStatus(counts).kind} dot>{overallStatus(counts).label}</Pill>
          </h1>
          <div className="vh-meta">
            <span>{person.category}{person.profile?.category?.status === 'qc' && <span title="QC passed" style={{color:'var(--ok)', marginLeft:4}}>✓</span>}</span>
            <span>{person.country}{person.profile?.country?.status === 'qc' && <span title="QC passed" style={{color:'var(--ok)', marginLeft:4}}>✓</span>}</span>
            <span>from {person.source}</span>
            <span>{counts.qc + counts['non-existing']} of {counts.total} handles · {profCounts.qc} of {profCounts.total} attributes</span>
          </div>
        </div>

        <div className="verify-body compact">
          {/* === Profile attributes === */}
          <div className="section-label">
            <Icon name="user" size={12}/> Profile
            <span className="section-hint">Confirm country and category — sources sometimes disagree.</span>
            <span className="section-progress">{profCounts.qc}/{profCounts.total} QC</span>
          </div>

          {/* Column header (shared with platforms below) */}
          <div className="prow head">
            <div className="prow-pl">Attribute</div>
            <div className="prow-src">SportsTool</div>
            <div className="prow-src">MC Info</div>
            <div className="prow-handle">Value used</div>
            <div className="prow-actions">Action</div>
          </div>

          {/* --- Country row --- */}
          {(() => {
            const c = person.profile?.country;
            if (!c) return null;
            const sportsHas = !!c.sports;
            const panelHas  = !!c.panel;
            const mismatch = sportsHas && panelHas && c.sports !== c.panel;
            const done = c.status === 'qc' || c.status === 'trusted';
            return (
              <div className={`prow attr ${c.status} ${done ? 'done' : ''}`}>
                <div className="prow-pl">
                  <div className="attr-icon" aria-hidden="true">🌐</div>
                  <div style={{display:'flex', flexDirection:'column', minWidth:0}}>
                    <span className="pl-name">Country</span>
                    <span className="pl-stat">
                      {c.status === 'qc' && '✓✓ QC passed'}
                      {c.status === 'verified' && '✓ Verified'}
                      {c.status === 'trusted' && 'Trusted'}
                      {c.status === 'unverified' && (mismatch ? 'Sources disagree' : 'Needs review')}
                    </span>
                  </div>
                </div>
                <div className={`prow-src ${mismatch ? 'mm' : ''}`}>
                  {sportsHas ? <span className="mono">{c.sports}</span> : <span className="none">—</span>}
                </div>
                <div className={`prow-src ${mismatch ? 'mm' : ''}`}>
                  {panelHas ? <span className="mono">{c.panel}</span> : <span className="none">—</span>}
                </div>
                <div className="prow-handle">
                  <div className="handle-input">
                    <select
                      className="attr-select"
                      value={c.merged || ''}
                      onChange={(e) => updateProfileMerged('country', e.target.value)}
                    >
                      <option value="">— select —</option>
                      {COUNTRIES.map(country => (
                        <option key={country} value={country}>{country}</option>
                      ))}
                    </select>
                    {sportsHas && c.sports !== c.merged && (
                      <button className="chip-mini" onClick={() => updateProfileMerged('country', c.sports)} title={`Use SportsTool: ${c.sports}`}>S</button>
                    )}
                    {panelHas && c.panel !== c.merged && (
                      <button className="chip-mini" onClick={() => updateProfileMerged('country', c.panel)} title={`Use MC: ${c.panel}`}>MC</button>
                    )}
                  </div>
                  {c.note && <div className="attr-note">{c.note}</div>}
                </div>
                <div className="prow-actions">
                  {c._updating ? (
                    <button className="btn ghost sm" disabled>
                      <Icon name="clock" size={12}/> Updating...
                    </button>
                  ) : c.status === 'verified' || c.status === 'qc' ? (
                    <>
                      <button className="btn ghost sm" onClick={() => setProfileStatus('country', 'unverified')}>Reset</button>
                      {c.status === 'verified' && (() => {
                        const selfVerified = c.verified_by && currentUser?.id && c.verified_by === currentUser.id;
                        return (
                          <button
                            className="btn ok sm"
                            disabled={!!selfVerified}
                            onClick={() => setProfileStatus('country', 'qc')}
                            title={selfVerified ? 'You verified this — a second reviewer must QC it' : 'Second-reviewer confirm'}
                          >
                            <Icon name="check" size={12}/> {selfVerified ? 'Need 2nd reviewer' : 'QC'}
                          </button>
                        );
                      })()}
                    </>
                  ) : (
                    <button
                      className={`btn ${c.status === 'trusted' ? 'neutral' : 'ok'} sm`}
                      disabled={!c.merged}
                      title={c.status === 'trusted' 
                        ? 'Reset to allow manual verification' 
                        : (!c.merged ? 'Pick a country first' : 'Confirm this is correct')}
                      onClick={() => setProfileStatus('country', c.status === 'trusted' ? 'unverified' : 'verified')}
                    >
                      <Icon name={c.status === 'trusted' ? 'refresh' : 'check'} size={12}/> 
                      {c.status === 'trusted' ? 'Reset' : 'Verify'}
                    </button>
                  )}
                </div>
              </div>
            );
          })()}

          {/* --- Category row --- */}
          {(() => {
            const c = person.profile?.category;
            if (!c) return null;
            const sportsHas = !!c.sports;
            const panelHas  = !!c.panel;
            const mismatch = sportsHas && panelHas && c.sports !== c.panel;
            const done = c.status === 'qc' || c.status === 'trusted';
            return (
              <div className={`prow attr ${c.status} ${done ? 'done' : ''}`}>
                <div className="prow-pl">
                  <div className="attr-icon" aria-hidden="true"><Icon name="bolt" size={14} stroke="var(--accent)"/></div>
                  <div style={{display:'flex', flexDirection:'column', minWidth:0}}>
                    <span className="pl-name">Category</span>
                    <span className="pl-stat">
                      {c.status === 'qc' && '✓✓ QC passed'}
                      {c.status === 'verified' && '✓ Verified'}
                      {c.status === 'trusted' && 'Trusted'}
                      {c.status === 'unverified' && (mismatch ? 'Sources disagree' : 'Needs review')}
                    </span>
                  </div>
                </div>
                <div className={`prow-src ${mismatch ? 'mm' : ''}`}>
                  {sportsHas ? <span className="mono">{c.sports}</span> : <span className="none">—</span>}
                </div>
                <div className={`prow-src ${mismatch ? 'mm' : ''}`}>
                  {panelHas ? <span className="mono">{c.panel}</span> : <span className="none">—</span>}
                </div>
                <div className="prow-handle">
                  <div className="handle-input">
                    <select
                      className="attr-select"
                      value={c.merged || ''}
                      onChange={(e) => updateProfileMerged('category', e.target.value)}
                    >
                      <option value="">— select —</option>
                      {CATEGORIES.map(category => (
                        <option key={category} value={category}>{category}</option>
                      ))}
                    </select>
                    {sportsHas && c.sports !== c.merged && (
                      <button className="chip-mini" onClick={() => updateProfileMerged('category', c.sports)} title={`Use SportsTool: ${c.sports}`}>S</button>
                    )}
                    {panelHas && c.panel !== c.merged && (
                      <button className="chip-mini" onClick={() => updateProfileMerged('category', c.panel)} title={`Use MC: ${c.panel}`}>MC</button>
                    )}
                  </div>
                  {c.note && <div className="attr-note">{c.note}</div>}
                </div>
                <div className="prow-actions">
                  {c._updating ? (
                    <button className="btn ghost sm" disabled>
                      <Icon name="clock" size={12}/> Updating...
                    </button>
                  ) : c.status === 'verified' || c.status === 'qc' ? (
                    <>
                      <button className="btn ghost sm" onClick={() => setProfileStatus('category', 'unverified')}>Reset</button>
                      {c.status === 'verified' && (() => {
                        const selfVerified = c.verified_by && currentUser?.id && c.verified_by === currentUser.id;
                        return (
                          <button
                            className="btn ok sm"
                            disabled={!!selfVerified}
                            onClick={() => setProfileStatus('category', 'qc')}
                            title={selfVerified ? 'You verified this — a second reviewer must QC it' : 'Second-reviewer confirm'}
                          >
                            <Icon name="check" size={12}/> {selfVerified ? 'Need 2nd reviewer' : 'QC'}
                          </button>
                        );
                      })()}
                    </>
                  ) : (
                    <button
                      className={`btn ${c.status === 'trusted' ? 'neutral' : 'ok'} sm`}
                      disabled={!c.merged}
                      title={c.status === 'trusted' 
                        ? 'Reset to allow manual verification'
                        : (!c.merged ? 'Pick a category first' : 'Confirm this is correct')}
                      onClick={() => setProfileStatus('category', c.status === 'trusted' ? 'unverified' : 'verified')}
                    >
                      <Icon name={c.status === 'trusted' ? 'refresh' : 'check'} size={12}/> 
                      {c.status === 'trusted' ? 'Reset' : 'Verify'}
                    </button>
                  )}
                </div>
              </div>
            );
          })()}

          {/* === Platforms === */}
          <div className="section-label" style={{marginTop: 18}}>
            <Icon name="bolt" size={12}/> Social handles
            <span className="section-hint">Open each profile, then verify or QC.</span>
            <span className="section-progress">{counts.qc + counts['non-existing']}/{counts.total} done</span>
          </div>

          {/* Column header */}
          <div className="prow head">
            <div className="prow-pl">Platform</div>
            <div className="prow-src">SportsTool</div>
            <div className="prow-src">MC Info</div>
            <div className="prow-handle">Handle used</div>
            <div className="prow-actions">Action</div>
          </div>

          {PLATFORMS.map((pl) => {
            const handles = person.handles[pl.id];
            const handlesArray = Array.isArray(handles) ? handles : [handles];
            
            return handlesArray.map((h, handleIndex) => {
              const sportsHas = !!h.sports;
              const panelHas  = !!h.panel;
              const handleOpened = isOpened(pl, handleIndex);
              const handleSearched = isSearched(pl, handleIndex);
              const isEmpty = !h.merged;
              const canVerify = !!h.merged && handleOpened;
              const canConfirmAbsent = isEmpty && handleSearched;
              const url = h.merged ? `https://${URL_ROOT[pl.id]}${h.merged}` : '';
              const searchUrl = buildSearchUrl(pl.id, person.name);
              const mismatch = sportsHas && panelHas && h.sports !== h.panel;
              const done = h.status === 'qc' || h.status === 'verified' || h.status === 'non-existing';
              const isMultipleHandles = handlesArray.length > 1;
              const isLastHandle = handleIndex === handlesArray.length - 1;

              return (
                <div key={`${pl.id}-${handleIndex}`} className={`prow ${h.status} ${done ? 'done' : ''}`}>
                  <div className="prow-pl">
                    <button
                      type="button"
                      className={`tile-toggle ${h.status === 'non-existing' ? 'off' : 'on'}`}
                      onClick={() => setStatus(pl.id, handleIndex, h.status === 'non-existing' ? 'unverified' : 'non-existing')}
                      title={h.status === 'non-existing' ? `Turn ${pl.name} back on` : `Quick toggle: mark as no account`}
                      aria-pressed={h.status !== 'non-existing'}
                    >
                      <Tile platform={pl.id} status={h.status}/>
                    </button>
                    <div style={{display: 'flex', flexDirection: 'column', minWidth: 0}}>
                      <span className="pl-name">
                        {pl.name}{isMultipleHandles && ` #${handleIndex + 1}`}
                      </span>
                      <span className="pl-stat">
                        {h.status === 'qc' && '✓✓ QC passed'}
                        {h.status === 'verified' && '✓ Verified'}
                        {h.status === 'unverified' && (isEmpty
                          ? (handleSearched ? 'Searched · confirm no account' : 'Empty — add handle or verify absent')
                          : 'Needs review')}
                        {h.status === 'missing' && (handleSearched ? 'Searched · confirm no account' : 'No data — add or verify absent')}
                        {h.status === 'non-existing' && (h.note ? '✓ Confirmed: no account' : '✓ Confirmed: no account')}
                      </span>
                    </div>
                  </div>

                  <div className={`prow-src ${mismatch ? 'mm' : ''}`}>
                    {sportsHas ? <span className="mono">{h.sports}</span> : <span className="none">—</span>}
                  </div>
                  <div className={`prow-src ${mismatch ? 'mm' : ''}`}>
                    {panelHas ? <span className="mono">{h.panel}</span> : <span className="none">—</span>}
                  </div>

                  <div className="prow-handle">
                    {h.status === 'non-existing' ? (
                      <span className="absent-note">
                        <Icon name="ban" size={11}/> No {pl.name} account · confirmed
                      </span>
                    ) : (
                      <div className="handle-input">
                        <span className="prefix">{URL_ROOT[pl.id]}</span>
                        <input
                          value={h.merged || ''}
                          placeholder={isEmpty ? 'add handle, or verify absent →' : 'handle'}
                          onChange={(e) => updateMerged(pl.id, handleIndex, e.target.value)}
                        />
                        {sportsHas && h.sports !== h.merged && (
                          <button className="chip-mini" onClick={() => updateMerged(pl.id, handleIndex, h.sports)} title="Use SportsTool value">S</button>
                        )}
                        {panelHas && h.panel !== h.merged && (
                          <button className="chip-mini" onClick={() => updateMerged(pl.id, handleIndex, h.panel)} title="Use MC value">MC</button>
                        )}
                      </div>
                    )}
                  </div>

                  <div className="prow-actions">
                    {h._updating ? (
                      <button className="btn ghost sm" disabled>
                        <Icon name="clock" size={12}/> Updating...
                      </button>
                    ) : h.status === 'non-existing' ? (
                      <>
                        <button
                          className="btn ghost sm"
                          onClick={() => { clearSearched(pl, handleIndex); setStatus(pl.id, handleIndex, 'unverified'); }}
                          title="Reopen for review"
                        >
                          Reset
                        </button>
                      </>
                    ) : h.status === 'verified' || h.status === 'qc' ? (
                      <>
                        <button className="btn ghost sm" onClick={() => setStatus(pl.id, handleIndex, 'unverified')}>Reset</button>
                        {h.status === 'verified' && (() => {
                          const selfVerified = h.verified_by && currentUser?.id && h.verified_by === currentUser.id;
                          return (
                            <button
                              className="btn ok sm"
                              disabled={!!selfVerified}
                              onClick={() => setStatus(pl.id, handleIndex, 'qc')}
                              title={selfVerified ? 'You verified this — a second reviewer must QC it' : 'Second-reviewer confirm'}
                            >
                              <Icon name="check" size={12}/> {selfVerified ? 'Need 2nd reviewer' : 'QC'}
                            </button>
                          );
                        })()}
                        {h.merged && <a className="btn sm" href={url} target="_blank" rel="noreferrer"><Icon name="ext" size={11}/></a>}
                      </>
                    ) : isEmpty ? (
                      /* Empty handle: prove absence via search, then confirm. */
                      <>
                        <a
                          className={`btn sm ${handleSearched ? '' : 'accent'}`}
                          href={searchUrl}
                          target="_blank"
                          rel="noreferrer"
                          onClick={() => markSearched(pl, handleIndex)}
                          title={`Search ${pl.name} for "${person.name}" to confirm no account exists`}
                        >
                          <Icon name="search" size={12}/> {handleSearched ? 'Re-search' : `Search ${pl.name}`}
                        </a>
                        <button
                          className="btn ok sm"
                          disabled={!canConfirmAbsent}
                          title={!handleSearched
                            ? `Search ${pl.name} first to confirm there's no account`
                            : `Confirm: ${person.name} has no ${pl.name} account`}
                          onClick={() => setStatus(pl.id, handleIndex, 'non-existing')}
                        >
                          <Icon name="check" size={12}/> No account
                        </button>
                      </>
                    ) : (
                      <>
                        <a className={`btn sm ${handleOpened ? '' : 'accent'}`}
                          href={url} target="_blank" rel="noreferrer"
                          onClick={() => markOpened(pl, handleIndex)}>
                          <Icon name="ext" size={12}/> {handleOpened ? 'Reopen' : 'Open'}
                        </a>
                        <button
                          className="btn ok sm"
                          disabled={!canVerify}
                          title={!handleOpened ? 'Open the profile to check it, then verify' : 'Confirm this is the right account'}
                          onClick={() => setStatus(pl.id, handleIndex, 'verified')}
                        >
                          <Icon name="check" size={12}/> Verify
                        </button>
                      </>
                    )}
                  </div>
                </div>
              );
            });
          })}

          <div style={{fontSize: 11, color: 'var(--muted)', padding: '10px 4px 2px', display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap'}}>
            <Icon name="ext" size={11}/> Open a profile to verify it.
            <span style={{color: 'var(--border-2)'}}>·</span>
            <span><Icon name="search" size={11}/> Empty rows: <b>Search</b> the platform first, then <b>No account</b> to confirm absence.</span>
            <span style={{color: 'var(--border-2)'}}>·</span>
            <span><b className="mono" style={{color:'var(--ink-2)'}}>S</b>/<b className="mono" style={{color:'var(--ink-2)'}}>P</b> chips copy the source value into the handle field.</span>
            <span style={{color: 'var(--border-2)'}}>·</span>
            <span>Editing a handle resets its verification.</span>
          </div>
        </div>

        <div className="verify-foot">
          <div className="progress-inline">
            <span>{counts.qc + counts['non-existing']}/{counts.total} done</span>
            <div className="bar"><span style={{width: `${pct*100}%`}}/></div>
            <span>{Math.round(pct * 100)}%</span>
          </div>
          <button className="btn" onClick={onPrevPerson}><Icon name="chevL" size={13}/> Prev</button>
          <button className="btn primary" onClick={onNextPerson}>Next person <span className="kbd-hint">]</span></button>
        </div>
      </section>
    </div>
  );
}

window.PersonDetail = PersonDetail;
