// TicketViews — TicketList, TicketDetail, SubmitTicketModal, normalizeTicket, DeleteConfirmModal
// Exports: TicketList, TicketDetail, SubmitTicketModal, normalizeTicket, DeleteConfirmModal

function ListExportBtn({ tickets, filename }) {
  const [exporting, setExporting] = React.useState(false);
  async function handleExport() {
    setExporting(true);
    try {
      await window.exportTicketsToExcel(tickets, filename);
    } catch (e) { console.error('Export failed:', e); alert('Export failed — please try again.'); }
    finally { setExporting(false); }
  }
  return (
    <button onClick={handleExport} disabled={exporting}
      title="Export to Excel"
      onMouseEnter={e => { if (!exporting) { e.currentTarget.style.background = '#F0FDF4'; e.currentTarget.style.borderColor = '#16A34A'; }}}
      onMouseLeave={e => { e.currentTarget.style.background = '#fff'; e.currentTarget.style.borderColor = '#E2E8F0'; }}
      style={{
        display: 'flex', alignItems: 'center', gap: 6,
        padding: '10px 14px', borderRadius: 8,
        border: '1.5px solid #E2E8F0', background: '#fff',
        fontSize: 13, fontWeight: 600, color: exporting ? '#94A3B8' : '#15803D',
        cursor: exporting ? 'wait' : 'pointer', fontFamily: 'inherit',
        transition: 'all 0.15s', whiteSpace: 'nowrap',
      }}>
      <IC name="download" size={14} color={exporting ? '#94A3B8' : '#16A34A'} />
      {exporting ? 'Exporting…' : 'Export'}
    </button>
  );
}

function normalizeTicket(t) {
  function mkInitials(name) {
    return (name || '?').split(' ').filter(Boolean).map(n => n[0]).join('').toUpperCase().slice(0, 2);
  }
  function fmtDate(val) {
    if (!val) return '—';
    try { return new Date(val).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }); }
    catch { return String(val); }
  }
  return {
    dbId:        t.id,
    id:          t.ticket_no || `TKT-${String(t.id).padStart(4, '0')}`,
    categoryId:  t.category_id,
    teamId:      t.team_id || null,
    teamName:    t.team_name || null,
    title:       t.title,
    description: t.description || '',
    status:      t.status,
    priority:    t.priority,
    submittedBy: {
      id:       t.submitted_by,
      name:     t.submitted_by_name || 'Unknown',
      initials: mkInitials(t.submitted_by_name),
    },
    assignedTo: t.assigned_to ? {
      id:       t.assigned_to,
      name:     t.assigned_to_name || 'Unknown',
      initials: mkInitials(t.assigned_to_name),
    } : null,
    createdAt: fmtDate(t.created_at),
    updatedAt: fmtDate(t.updated_at),
    comments: (t.comments || []).map(c => ({
      author: { name: c.author_name || 'Unknown', initials: mkInitials(c.author_name) },
      text:   c.comment,
      time:   fmtDate(c.created_at),
    })),
  };
}

// ── Submit Ticket Modal ──────────────────────────────────────────────────────
const CATEGORY_FAQ = [
  { id: 'technical_support', color: '#60A5FA', bg: '#EFF6FF', label: 'IT Support',            team: 'IT Support Team',     desc: 'Any technical issue you are facing — laptop, software, VPN, network, email, access, hardware or anything tech-related' },
  { id: 'marketing',         color: '#A78BFA', bg: '#F5F3FF', label: 'Marketing',              team: 'Asura / Laura / Deepthi / Wade', desc: 'Campaigns, assets, brand guidelines, social media, web copy' },
  { id: 'onboarding_issues', color: '#34D399', bg: '#ECFDF5', label: 'Onboarding Issues',      team: 'HR Team',             desc: 'New hire setup, equipment, accounts, orientation, ID cards' },
  { id: 'training_issues',   color: '#FBBF24', bg: '#FEF3C7', label: 'Training Issues',        team: 'Training Team',       desc: 'LMS access, course completion, certificates, compliance training' },
  { id: 'payroll',           color: '#FB7185', bg: '#FFF1F2', label: 'Payroll',                team: 'HR Team',             desc: 'Salary slips, reimbursements, TDS, Form 16, expense claims' },
  { id: 'others',            color: '#94A3B8', bg: '#F1F5F9', label: 'People Related Issues',  team: 'Admin (Confidential)', desc: 'Any personal or sensitive issue faced within the organisation. Your name and details will NOT be shared — only the core admin team handles this privately' },
];

function SubmitTicketModal({ onClose, initialCategoryId, onSubmit }) {
  const { categories } = window.MOCK;
  const userCats = categories.filter(c => !c.adminOnly);
  const [showFaq, setShowFaq] = React.useState(!initialCategoryId);
  const [form, setForm] = React.useState({
    categoryId: initialCategoryId || userCats[0].id,
    title: '', description: '', priority: 'Medium', attachment: null,
    teamId: null,
  });
  const [submitted, setSubmitted]     = React.useState(false);
  const [submitting, setSubmitting]   = React.useState(false);
  const [submitError, setSubmitError] = React.useState(null);
  const [dragOver, setDragOver]       = React.useState(false);
  const [fileName, setFileName]       = React.useState(null);
  const [mktTeams, setMktTeams]       = React.useState([]);
  const fileRef = React.useRef(null);

  // Load marketing teams once
  React.useEffect(() => {
    fetch('/api/marketing-teams', {
      headers: { Authorization: 'Bearer ' + (localStorage.getItem('syn_token') || '') },
    })
      .then(r => r.ok ? r.json() : [])
      .then(setMktTeams)
      .catch(() => {});
  }, []);

  function set(key, val) { setForm(f => ({ ...f, [key]: val })); }

  function handleFile(file) {
    if (!file) return;
    setFileName(file.name);
    set('attachment', file);
  }

  async function handleSubmit(e) {
    e.preventDefault();
    if (!form.title.trim() || !form.description.trim()) return;
    setSubmitting(true);
    setSubmitError(null);
    try {
      const res = await fetch('/api/tickets', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': 'Bearer ' + (localStorage.getItem('syn_token') || ''),
        },
        body: JSON.stringify({
          category_id: form.categoryId,
          title:       form.title.trim(),
          description: form.description.trim(),
          priority:    form.priority,
          team_id:     form.teamId || null,
        }),
      });
      if (!res.ok) {
        const err = await res.json();
        throw new Error(err.error || 'Failed to submit concern');
      }
      onSubmit();
      setSubmitted(true);
    } catch (err) {
      setSubmitError(err.message);
    } finally {
      setSubmitting(false);
    }
  }

  const selectedCat  = userCats.find(c => c.id === form.categoryId);
  const selectedTeam = form.teamId ? mktTeams.find(t => t.id === form.teamId) : null;

  return (
    <div style={{
      position: 'fixed', inset: 0, background: 'rgba(15,37,64,0.55)', zIndex: 1000,
      display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 20,
    }} onClick={e => e.target === e.currentTarget && onClose()}>
      <div style={{
        background: '#fff', borderRadius: 16, width: '100%', maxWidth: 560,
        boxShadow: '0 24px 80px rgba(0,0,0,0.18)', overflow: 'hidden',
        display: 'flex', flexDirection: 'column', maxHeight: '90vh',
      }}>
        {/* Header */}
        <div style={{ background: '#0F2540', padding: '22px 28px', display: 'flex', alignItems: 'center', justifyContent: 'space-between', flexShrink: 0 }}>
          <div>
            <div style={{ color: '#fff', fontWeight: 800, fontSize: 17 }}>{showFaq ? 'Which concern do you have?' : 'Submit New Concern'}</div>
            <div style={{ color: 'rgba(255,255,255,0.5)', fontSize: 12, marginTop: 2 }}>{showFaq ? 'Select the right type so it reaches the correct team' : "We'll get back to you as soon as possible"}</div>
          </div>
          <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
            {!showFaq && !submitted && (
              <button onClick={() => setShowFaq(true)} title="View category guide" style={{
                background: 'rgba(255,255,255,0.12)', border: '1px solid rgba(255,255,255,0.2)',
                borderRadius: 8, padding: '6px 12px', cursor: 'pointer', color: '#fff',
                display: 'flex', alignItems: 'center', gap: 6, fontSize: 12, fontWeight: 600, fontFamily: 'inherit',
              }}>
                <span style={{ fontSize: 14 }}>?</span> Guide
              </button>
            )}
            <button onClick={onClose} style={{ background: 'rgba(255,255,255,0.1)', border: 'none', borderRadius: 8, padding: 8, cursor: 'pointer', color: '#fff', display: 'flex' }}>
              <IC name="x" size={16} color="#fff" />
            </button>
          </div>
        </div>

        {/* FAQ screen */}
        {showFaq && !submitted && (
          <div style={{ padding: '24px 28px', overflowY: 'auto' }}>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 10, marginBottom: 22 }}>
              {CATEGORY_FAQ.map(f => (
                <div key={f.id} onClick={() => { setShowFaq(false); set('categoryId', f.id); if (f.id !== 'marketing') set('teamId', null); }}
                  style={{
                    display: 'flex', alignItems: 'center', gap: 14, padding: '12px 16px',
                    border: `1.5px solid ${f.bg === '#F1F5F9' ? '#E2E8F0' : f.color}22`,
                    borderRadius: 10, cursor: 'pointer', background: f.bg,
                    transition: 'all 0.12s',
                  }}
                  onMouseEnter={e => e.currentTarget.style.boxShadow = `0 0 0 2px ${f.color}55`}
                  onMouseLeave={e => e.currentTarget.style.boxShadow = 'none'}>
                  <div style={{ width: 10, height: 10, borderRadius: '50%', background: f.color, flexShrink: 0 }} />
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontSize: 13, fontWeight: 700, color: '#1E293B' }}>{f.label}</div>
                    <div style={{ fontSize: 11, color: '#64748B', marginTop: 2 }}>{f.desc}</div>
                  </div>
                  <div style={{ fontSize: 11, fontWeight: 600, color: f.color, background: '#fff', padding: '3px 10px', borderRadius: 20, whiteSpace: 'nowrap', border: `1px solid ${f.color}44` }}>
                    → {f.team}
                  </div>
                </div>
              ))}
            </div>
          </div>
        )}

        {submitted ? (
          <div style={{ padding: '48px 28px', textAlign: 'center' }}>
            <div style={{ width: 56, height: 56, borderRadius: '50%', background: '#ECFDF5', display: 'flex', alignItems: 'center', justifyContent: 'center', margin: '0 auto 16px' }}>
              <IC name="check" size={28} color="#10B981" strokeWidth={2.5} />
            </div>
            <div style={{ fontSize: 18, fontWeight: 800, color: '#0F172A', marginBottom: 8 }}>Concern Raised!</div>
            <div style={{ color: '#64748B', fontSize: 14, marginBottom: 24 }}>Your concern has been raised and will be reviewed shortly.</div>
            <Btn onClick={onClose} variant="navy">Close</Btn>
          </div>
        ) : (!showFaq && (
          <form onSubmit={handleSubmit} style={{ padding: '24px 28px', display: 'flex', flexDirection: 'column', gap: 18, overflowY: 'auto', flex: 1 }}>
            {/* Category */}
            <div>
              <label style={labelStyle}>Category</label>
              <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 8, marginTop: 6 }}>
                {userCats.map(cat => (
                  <button key={cat.id} type="button" onClick={() => { set('categoryId', cat.id); if (cat.id !== 'marketing') set('teamId', null); }} style={{
                    padding: '8px 10px', border: `2px solid ${form.categoryId === cat.id ? cat.color : '#E2E8F0'}`,
                    borderRadius: 8, cursor: 'pointer', background: form.categoryId === cat.id ? cat.bg : '#fff',
                    fontFamily: 'inherit', fontSize: 11, fontWeight: 600, color: form.categoryId === cat.id ? cat.color : '#64748B',
                    transition: 'all 0.12s', textAlign: 'center', lineHeight: 1.3,
                  }}>
                    {cat.label}
                  </button>
                ))}
              </div>
            </div>

            {/* Marketing team selector — only when Marketing is selected */}
            {form.categoryId === 'marketing' && (
              <div style={{ display: 'flex', flexDirection: 'column', gap: 14, padding: '16px 18px', background: '#F8FAFF', borderRadius: 10, border: '1.5px solid #DBEAFE' }}>
                <div style={{ fontSize: 12, fontWeight: 700, color: '#1A5090', textTransform: 'uppercase', letterSpacing: '0.05em' }}>Marketing Team</div>

                {/* Team dropdown */}
                <div>
                  <label style={labelStyle}>Select Team <span style={{ color: BRAND_ORANGE }}>*</span></label>
                  <select
                    value={form.teamId || ''}
                    onChange={e => set('teamId', e.target.value ? Number(e.target.value) : null)}
                    required
                    style={{ ...inputStyle, marginTop: 6, cursor: 'pointer' }}>
                    <option value="">— Choose a team —</option>
                    {mktTeams.map(t => (
                      <option key={t.id} value={t.id}>Team {t.name}</option>
                    ))}
                  </select>
                </div>

              </div>
            )}

            {/* Title */}
            <div>
              <label style={labelStyle}>Subject <span style={{ color: BRAND_ORANGE }}>*</span></label>
              <input value={form.title} onChange={e => set('title', e.target.value)}
                placeholder="Brief summary of the issue..."
                required style={inputStyle} />
            </div>

            {/* Priority — admin only; non-admins always submit as Medium */}
            {window._synUser?.role === 'admin' && (
              <div>
                <label style={labelStyle}>Priority</label>
                <div style={{ display: 'flex', gap: 8, marginTop: 6 }}>
                  {['Low', 'Medium', 'High', 'Urgent'].map(p => {
                    const colors = { Low: '#64748B', Medium: '#B45309', High: '#B91C1C', Urgent: '#fff' };
                    const bgs    = { Low: '#F1F5F9', Medium: '#FFFBEB', High: '#FEF2F2', Urgent: '#DC2626' };
                    const active = form.priority === p;
                    return (
                      <button key={p} type="button" onClick={() => set('priority', p)} style={{
                        flex: 1, padding: '7px 0', border: active ? `2px solid ${bgs[p] === '#DC2626' ? '#DC2626' : colors[p]}` : '2px solid #E2E8F0',
                        borderRadius: 7, cursor: 'pointer',
                        background: active ? bgs[p] : '#fff',
                        color: active ? colors[p] : '#94A3B8',
                        fontFamily: 'inherit', fontSize: 12, fontWeight: 700, transition: 'all 0.12s',
                      }}>
                        {p}
                      </button>
                    );
                  })}
                </div>
              </div>
            )}

            {/* Description */}
            <div>
              <label style={labelStyle}>Description <span style={{ color: BRAND_ORANGE }}>*</span></label>
              <textarea value={form.description} onChange={e => set('description', e.target.value)}
                placeholder="Describe the issue in detail — steps to reproduce, expected outcome, and any other relevant information..."
                required rows={4}
                style={{ ...inputStyle, resize: 'vertical', lineHeight: 1.6 }} />
            </div>

            {/* Attachment */}
            <div
              onClick={() => fileRef.current.click()}
              onDragOver={e => { e.preventDefault(); setDragOver(true); }}
              onDragLeave={() => setDragOver(false)}
              onDrop={e => { e.preventDefault(); setDragOver(false); handleFile(e.dataTransfer.files[0]); }}
              style={{
                border: `2px dashed ${dragOver ? '#1A5090' : '#E2E8F0'}`, borderRadius: 10, padding: '14px 18px',
                display: 'flex', alignItems: 'center', gap: 10, cursor: 'pointer',
                background: dragOver ? '#EFF6FF' : '#FAFBFF', color: '#94A3B8',
                transition: 'border-color 0.15s, background 0.15s',
              }}>
              <input type="file" ref={fileRef} style={{ display: 'none' }}
                onChange={e => handleFile(e.target.files[0])} />
              <IC name="attachment" size={16} color={dragOver ? '#1A5090' : '#CBD5E1'} />
              {fileName
                ? <span style={{ fontSize: 13, color: '#1E293B', fontWeight: 600 }}>{fileName}</span>
                : <span style={{ fontSize: 13 }}>Drag & drop attachments or <span style={{ color: '#1A5090', fontWeight: 600 }}>browse files</span></span>
              }
            </div>

            {/* Actions */}
            <div style={{ display: 'flex', flexDirection: 'column', gap: 10, paddingTop: 4 }}>
              {submitError && (
                <div style={{ padding: '10px 14px', background: '#FEF2F2', border: '1.5px solid #FECACA', borderRadius: 8, fontSize: 13, color: '#B91C1C', fontWeight: 600 }}>
                  {submitError}
                </div>
              )}
              <div style={{ display: 'flex', gap: 10, justifyContent: 'flex-end' }}>
                <Btn variant="ghost" onClick={onClose} type="button" disabled={submitting}>Cancel</Btn>
                <Btn variant="primary" type="submit" icon={submitting ? undefined : 'send'} disabled={submitting}>
                  {submitting ? 'Submitting…' : 'Submit Concern'}
                </Btn>
              </div>
            </div>
          </form>
        ))}
      </div>
    </div>
  );
}

const labelStyle = { fontSize: 12, fontWeight: 700, color: '#374151', textTransform: 'uppercase', letterSpacing: '0.05em', display: 'block' };
const inputStyle = {
  width: '100%', padding: '10px 14px', borderRadius: 8, border: '1.5px solid #E2E8F0',
  fontSize: 14, fontFamily: 'inherit', color: '#1E293B', marginTop: 6, outline: 'none',
  boxSizing: 'border-box', background: '#FAFBFF',
};

// ── Delete Confirm Modal ─────────────────────────────────────────────────────
function DeleteConfirmModal({ count, onCancel, onConfirm, deleting }) {
  return (
    <div style={{
      position: 'fixed', inset: 0, background: 'rgba(15,37,64,0.6)', zIndex: 2000,
      display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 20,
    }} onClick={e => e.target === e.currentTarget && !deleting && onCancel()}>
      <div style={{ background: '#fff', borderRadius: 16, width: '100%', maxWidth: 440, boxShadow: '0 24px 80px rgba(0,0,0,0.2)', overflow: 'hidden' }}>
        <div style={{ background: '#0F2540', padding: '22px 28px', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
          <div>
            <div style={{ color: '#fff', fontWeight: 800, fontSize: 16 }}>Delete Concern{count > 1 ? 's' : ''}</div>
            <div style={{ color: 'rgba(255,255,255,0.5)', fontSize: 12, marginTop: 3 }}>This action cannot be undone</div>
          </div>
          <button onClick={onCancel} disabled={deleting} style={{ background: 'rgba(255,255,255,0.1)', border: 'none', borderRadius: 8, padding: 8, cursor: 'pointer', display: 'flex' }}>
            <IC name="x" size={16} color="#fff" />
          </button>
        </div>
        <div style={{ padding: '28px' }}>
          <div style={{ background: '#FEF2F2', border: '1.5px solid #FECACA', borderRadius: 10, padding: '14px 18px', marginBottom: 24, display: 'flex', gap: 12, alignItems: 'flex-start' }}>
            <IC name="alert" size={20} color="#B91C1C" style={{ flexShrink: 0, marginTop: 1 }} />
            <div>
              <div style={{ fontSize: 14, fontWeight: 700, color: '#B91C1C', marginBottom: 6 }}>
                You are about to permanently delete {count} concern{count > 1 ? 's' : ''}
              </div>
              <div style={{ fontSize: 13, color: '#991B1B', lineHeight: 1.5 }}>
                Once deleted, this data cannot be recovered. Are you sure you want to proceed?
              </div>
            </div>
          </div>
          <div style={{ display: 'flex', gap: 10, justifyContent: 'flex-end' }}>
            <Btn variant="ghost" onClick={onCancel} disabled={deleting}>Cancel</Btn>
            <Btn variant="danger" onClick={onConfirm} disabled={deleting}
              style={{ background: '#DC2626', color: '#fff', opacity: deleting ? 0.6 : 1 }}>
              {deleting ? 'Deleting…' : `Delete ${count > 1 ? count + ' Concerns' : 'Permanently'}`}
            </Btn>
          </div>
        </div>
      </div>
    </div>
  );
}

// ── Ticket Row ───────────────────────────────────────────────────────────────
function TicketRow({ ticket, onClick, isAdmin, isSelected, onToggle }) {
  const [hov, setHov] = React.useState(false);
  const cat = window.MOCK.categories.find(c => c.id === ticket.categoryId);
  const gridCols = isAdmin ? '28px 10px 1fr 36px 82px 115px 82px 20px' : '10px 1fr 36px 82px 115px 82px 20px';
  return (
    <div onClick={() => onClick(ticket)}
      onMouseEnter={() => setHov(true)} onMouseLeave={() => setHov(false)}
      style={{
        display: 'grid', gridTemplateColumns: gridCols,
        alignItems: 'center', gap: 12, padding: '11px 20px',
        background: isSelected ? '#FFF5F5' : hov ? '#FAFBFF' : '#fff', cursor: 'pointer',
        borderBottom: '1px solid #F1F5F9', transition: 'background 0.1s',
      }}>
      {isAdmin && (
        <div onClick={e => { e.stopPropagation(); onToggle(ticket.dbId); }}
          style={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
          <input type="checkbox" checked={!!isSelected} onChange={() => {}}
            style={{ cursor: 'pointer', width: 14, height: 14, accentColor: '#DC2626' }} />
        </div>
      )}
      {/* Category dot */}
      <div style={{ width: 8, height: 8, borderRadius: '50%', background: cat?.color || '#94A3B8', justifySelf: 'center' }} />
      {/* Title + meta line */}
      <div style={{ minWidth: 0 }}>
        <div style={{ fontSize: 13, fontWeight: 600, color: '#1E293B', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{ticket.title}</div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginTop: 2 }}>
          <span style={{ fontSize: 10, color: '#94A3B8', fontFamily: 'monospace' }}>{ticket.id}</span>
          <span style={{ fontSize: 10, color: '#CBD5E1' }}>·</span>
          <span style={{ fontSize: 10, color: cat?.color, fontWeight: 600 }}>{cat?.label}</span>
          {ticket.teamName && ticket.categoryId === 'marketing' && (
            <>
              <span style={{ fontSize: 10, color: '#CBD5E1' }}>·</span>
              <span style={{
                fontSize: 10, fontWeight: 600, color: '#1A5090',
                background: '#EFF6FF', padding: '1px 7px', borderRadius: 10,
              }}>{ticket.teamName}</span>
            </>
          )}
          <span style={{ fontSize: 10, color: '#CBD5E1' }}>·</span>
          <span style={{ fontSize: 10, color: '#94A3B8', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>by {ticket.submittedBy.name}</span>
        </div>
      </div>
      {/* Assigned To — avatar only with tooltip */}
      <div title={ticket.assignedTo ? ticket.assignedTo.name : 'Unassigned'}>
        {ticket.assignedTo
          ? <Avatar name={ticket.assignedTo.name} initials={ticket.assignedTo.initials} size={24} />
          : <span style={{ fontSize: 11, color: '#CBD5E1', fontStyle: 'italic' }}>—</span>}
      </div>
      {/* Priority */}
      <PriorityBadge priority={ticket.priority} />
      {/* Status */}
      <StatusBadge status={ticket.status} />
      {/* Updated */}
      <span style={{ fontSize: 11, color: '#64748B', whiteSpace: 'nowrap' }}>{ticket.updatedAt}</span>
      {/* Chevron */}
      <IC name="chevron_r" size={13} color="#CBD5E1" />
    </div>
  );
}

// ── Ticket List ──────────────────────────────────────────────────────────────
function TicketList({ tickets: allTickets, categoryId, onTicketClick, onNewTicket, onRefresh }) {
  const { categories } = window.MOCK;
  const cat = categories.find(c => c.id === categoryId);
  const visibleCats = categories.filter(c => !c.adminOnly);
  const [search, setSearch] = React.useState('');
  const [filterStatus, setFilterStatus] = React.useState('All');
  const [filterPriority, setFilterPriority] = React.useState('All');
  const [filterCategory, setFilterCategory] = React.useState('All');
  const [sortCol, setSortCol] = React.useState('status');
  const [sortDir, setSortDir] = React.useState('asc');
  const [perPage, setPerPage] = React.useState(10);
  const [perPageInput, setPerPageInput] = React.useState('10');
  const [currentPage, setCurrentPage] = React.useState(1);
  const [selected, setSelected] = React.useState(new Set());
  const [showDeleteConfirm, setShowDeleteConfirm] = React.useState(false);
  const [deleting, setDeleting] = React.useState(false);

  React.useEffect(() => { setCurrentPage(1); }, [search, filterStatus, filterPriority, filterCategory, sortCol, sortDir, perPage]);

  const isAdmin = window._synUser?.role === 'admin';
  const isMyTickets = categoryId === 'my_tickets';
  const source = isMyTickets
    ? allTickets
    : allTickets.filter(t => t.categoryId === categoryId);

  const STATUS_RANK    = { 'Open': 0, 'In Progress': 1, 'Resolved': 2, 'Closed': 3 };
  const PRIORITY_RANK  = { 'Urgent': 0, 'High': 1, 'Medium': 2, 'Low': 3 };

  function handleSort(col) {
    if (sortCol === col) setSortDir(d => d === 'asc' ? 'desc' : 'asc');
    else { setSortCol(col); setSortDir('asc'); }
  }

  const filtered = source.filter(t => {
    const matchSearch = !search || t.title.toLowerCase().includes(search.toLowerCase()) || t.id.toLowerCase().includes(search.toLowerCase());
    const matchStatus = filterStatus === 'All' || t.status === filterStatus;
    const matchPri    = filterPriority === 'All' || t.priority === filterPriority;
    const matchCat    = filterCategory === 'All' || t.categoryId === filterCategory;
    return matchSearch && matchStatus && matchPri && matchCat;
  }).sort((a, b) => {
    const dir = sortDir === 'asc' ? 1 : -1;
    if (sortCol === 'title')    return dir * a.title.localeCompare(b.title);
    if (sortCol === 'priority') return dir * ((PRIORITY_RANK[a.priority] ?? 99) - (PRIORITY_RANK[b.priority] ?? 99));
    if (sortCol === 'status')   return dir * ((STATUS_RANK[a.status] ?? 99) - (STATUS_RANK[b.status] ?? 99));
    if (sortCol === 'by')       return dir * (a.submittedBy?.name || '').localeCompare(b.submittedBy?.name || '');
    if (sortCol === 'date')     return dir * String(b.updatedAt).localeCompare(String(a.updatedAt));
    return 0;
  });

  const totalPages = Math.max(1, Math.ceil(filtered.length / perPage));
  const paginated  = filtered.slice((currentPage - 1) * perPage, currentPage * perPage);

  const allOnPageSelected = paginated.length > 0 && paginated.every(t => selected.has(t.dbId));
  const someOnPageSelected = paginated.some(t => selected.has(t.dbId));

  function authH() { return { Authorization: 'Bearer ' + (localStorage.getItem('syn_token') || '') }; }
  function toggleSelect(dbId) {
    setSelected(prev => { const s = new Set(prev); s.has(dbId) ? s.delete(dbId) : s.add(dbId); return s; });
  }
  function toggleSelectAll() {
    const allIds = paginated.map(t => t.dbId);
    setSelected(prev => {
      const s = new Set(prev);
      allIds.forEach(id => allOnPageSelected ? s.delete(id) : s.add(id));
      return s;
    });
  }
  async function handleBulkDelete() {
    setDeleting(true);
    try {
      await fetch('/api/tickets/bulk', {
        method: 'DELETE',
        headers: { 'Content-Type': 'application/json', ...authH() },
        body: JSON.stringify({ ids: [...selected] }),
      });
      setSelected(new Set());
      setShowDeleteConfirm(false);
      if (onRefresh) onRefresh();
    } catch (e) { console.error(e); }
    finally { setDeleting(false); }
  }

  const title = categoryId === 'my_tickets' ? 'My Tickets' : cat?.label || 'Tickets';
  const color = cat?.color || '#1A5090';
  const bg    = cat?.bg    || '#E8EFF8';

  const statusCounts = { All: source.length, Open: 0, 'In Progress': 0, Resolved: 0, Closed: 0 };
  source.forEach(t => { if (statusCounts[t.status] !== undefined) statusCounts[t.status]++; });

  return (
    <div>

      {/* Status tabs */}
      <div style={{ display: 'flex', gap: 4, marginBottom: 16, background: '#F1F5F9', borderRadius: 10, padding: 4, width: 'fit-content' }}>
        {['All', 'Open', 'In Progress', 'Resolved', 'Closed'].map(s => (
          <button key={s} onClick={() => setFilterStatus(s)} style={{
            padding: '6px 14px', borderRadius: 7, border: 'none', cursor: 'pointer',
            fontFamily: 'inherit', fontSize: 12, fontWeight: 600,
            background: filterStatus === s ? '#fff' : 'transparent',
            color: filterStatus === s ? '#1E293B' : '#64748B',
            boxShadow: filterStatus === s ? '0 1px 4px rgba(0,0,0,0.08)' : 'none',
            transition: 'all 0.12s',
          }}>
            {s} {s !== 'All' && statusCounts[s] > 0 && <span style={{ color: '#94A3B8', marginLeft: 3 }}>{statusCounts[s]}</span>}
          </button>
        ))}
      </div>

      {/* Search + filter bar */}
      <div style={{ display: 'flex', gap: 10, marginBottom: 16, alignItems: 'stretch' }}>
        <div style={{ flex: 1, position: 'relative' }}>
          <IC name="search" size={15} color="#94A3B8" style={{ position: 'absolute', left: 12, top: '50%', transform: 'translateY(-50%)', pointerEvents: 'none' }} />
          <input value={search} onChange={e => setSearch(e.target.value)}
            placeholder="Search concerns by title or ID..."
            style={{ ...inputStyle, paddingLeft: 36, marginTop: 0, width: '100%', height: '100%', boxSizing: 'border-box' }} />
        </div>
        {isMyTickets && (
          <select value={filterCategory} onChange={e => setFilterCategory(e.target.value)} style={{
            padding: '10px 14px', borderRadius: 8, border: '1.5px solid #E2E8F0',
            fontSize: 14, fontFamily: 'inherit', color: '#374151', background: '#fff', cursor: 'pointer',
          }}>
            <option value="All">All Categories</option>
            {visibleCats.map(c => <option key={c.id} value={c.id}>{c.label}</option>)}
          </select>
        )}
        {window._synUser?.role === 'admin' && (
          <select value={filterPriority} onChange={e => setFilterPriority(e.target.value)} style={{
            padding: '10px 14px', borderRadius: 8, border: '1.5px solid #E2E8F0',
            fontSize: 14, fontFamily: 'inherit', color: '#374151', background: '#fff', cursor: 'pointer',
          }}>
            <option value="All">All Priorities</option>
            {['Urgent', 'High', 'Medium', 'Low'].map(p => <option key={p} value={p}>{p}</option>)}
          </select>
        )}
        <ListExportBtn tickets={allTickets} filename={isMyTickets ? 'my-concerns' : (cat?.label || 'concerns').toLowerCase().replace(/\s+/g, '-')} />
        {isAdmin && selected.size > 0 && (
          <button onClick={() => setShowDeleteConfirm(true)} style={{
            padding: '10px 16px', borderRadius: 8, border: 'none',
            background: '#DC2626', color: '#fff',
            fontSize: 13, fontWeight: 700, fontFamily: 'inherit',
            cursor: 'pointer', display: 'flex', alignItems: 'center', gap: 8,
            whiteSpace: 'nowrap',
          }}>
            <IC name="trash" size={14} color="#fff" />
            Delete ({selected.size})
          </button>
        )}
      </div>

      {/* Table */}
      <div style={{ background: '#fff', borderRadius: 12, border: '1.5px solid #E2E8F0', overflow: 'hidden' }}>
        {/* Table header — sortable columns */}
        <div style={{
          display: 'grid', gridTemplateColumns: isAdmin ? '28px 10px 1fr 36px 82px 115px 82px 20px' : '10px 1fr 36px 82px 115px 82px 20px',
          alignItems: 'center', gap: 12, padding: '10px 20px', background: '#F8FAFC',
          borderBottom: '1.5px solid #E2E8F0',
        }}>
          {isAdmin && (
            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
              <input type="checkbox"
                checked={allOnPageSelected}
                ref={el => { if (el) el.indeterminate = someOnPageSelected && !allOnPageSelected; }}
                onChange={toggleSelectAll}
                style={{ cursor: 'pointer', width: 14, height: 14, accentColor: '#DC2626' }} />
            </div>
          )}
          {[
            { label: '',         col: null },
            { label: 'Concern',  col: 'title' },
            { label: 'Assgn.',   col: null },
            { label: 'Priority', col: 'priority' },
            { label: 'Status',   col: 'status' },
            { label: 'By',       col: 'by' },
            { label: 'Date',     col: 'date' },
          ].map(({ label, col }, i) => (
            <span key={i} onClick={col ? () => handleSort(col) : undefined} style={{
              fontSize: 10, fontWeight: 700, color: sortCol === col ? '#1A5090' : '#94A3B8',
              textTransform: 'uppercase', letterSpacing: '0.06em', whiteSpace: 'nowrap',
              cursor: col ? 'pointer' : 'default', userSelect: 'none',
              display: 'flex', alignItems: 'center', gap: 3,
            }}>
              {label}
              {col && sortCol === col && (
                <span style={{ fontSize: 9 }}>{sortDir === 'asc' ? '▲' : '▼'}</span>
              )}
            </span>
          ))}
        </div>
        {filtered.length === 0 ? (
          <div style={{ padding: '48px 28px', textAlign: 'center', color: '#94A3B8' }}>
            <IC name="inbox" size={36} color="#CBD5E1" style={{ display: 'block', margin: '0 auto 12px' }} />
            <div style={{ fontWeight: 600, color: '#CBD5E1' }}>No concerns found</div>
          </div>
        ) : (
          paginated.map(t => (
            <TicketRow key={t.id} ticket={t} onClick={onTicketClick}
              isAdmin={isAdmin} isSelected={selected.has(t.dbId)} onToggle={toggleSelect} />
          ))
        )}

        {/* Pagination footer */}
        {filtered.length > 0 && (
          <div style={{
            display: 'flex', alignItems: 'center', justifyContent: 'space-between',
            padding: '12px 20px', borderTop: '1.5px solid #F1F5F9', background: '#FAFBFF',
          }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <span style={{ fontSize: 12, color: '#64748B', fontWeight: 500 }}>Rows per page:</span>
              <input
                type="number" min="1" max="200"
                value={perPageInput}
                onChange={e => {
                  setPerPageInput(e.target.value);
                  const val = parseInt(e.target.value);
                  if (val > 0) { setPerPage(val); setCurrentPage(1); }
                }}
                style={{
                  width: 58, padding: '4px 8px', borderRadius: 6,
                  border: '1.5px solid #E2E8F0', fontSize: 13, fontFamily: 'inherit',
                  textAlign: 'center', outline: 'none',
                }}
              />
            </div>
            <span style={{ fontSize: 12, color: '#64748B' }}>
              {`${(currentPage - 1) * perPage + 1}–${Math.min(currentPage * perPage, filtered.length)} of ${filtered.length}`}
            </span>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <button
                onClick={() => setCurrentPage(p => Math.max(1, p - 1))}
                disabled={currentPage === 1}
                style={{
                  padding: '5px 12px', borderRadius: 7, border: '1.5px solid #E2E8F0',
                  background: currentPage === 1 ? '#F8FAFC' : '#fff',
                  color: currentPage === 1 ? '#CBD5E1' : '#374151',
                  fontSize: 12, fontWeight: 600, fontFamily: 'inherit',
                  cursor: currentPage === 1 ? 'not-allowed' : 'pointer',
                }}>← Prev</button>
              <span style={{ fontSize: 12, color: '#64748B', whiteSpace: 'nowrap' }}>
                Page {currentPage} of {totalPages}
              </span>
              <button
                onClick={() => setCurrentPage(p => Math.min(totalPages, p + 1))}
                disabled={currentPage === totalPages}
                style={{
                  padding: '5px 12px', borderRadius: 7, border: '1.5px solid #E2E8F0',
                  background: currentPage === totalPages ? '#F8FAFC' : '#fff',
                  color: currentPage === totalPages ? '#CBD5E1' : '#374151',
                  fontSize: 12, fontWeight: 600, fontFamily: 'inherit',
                  cursor: currentPage === totalPages ? 'not-allowed' : 'pointer',
                }}>Next →</button>
            </div>
          </div>
        )}
      </div>

      {showDeleteConfirm && (
        <DeleteConfirmModal
          count={selected.size}
          onCancel={() => setShowDeleteConfirm(false)}
          onConfirm={handleBulkDelete}
          deleting={deleting}
        />
      )}
    </div>
  );
}

// ── Ticket Detail ─────────────────────────────────────────────────────────────
function TicketDetail({ ticket: initialTicket, onBack, onRefresh }) {
  const [detail, setDetail]     = React.useState(null);
  const [comment, setComment]   = React.useState('');
  const [status, setStatus]     = React.useState(initialTicket.status);
  const [priority, setPriority] = React.useState(initialTicket.priority);
  const [posting, setPosting]         = React.useState(false);
  const [showDeleteTicket, setShowDeleteTicket] = React.useState(false);
  const [deletingTicket, setDeletingTicket]     = React.useState(false);
  const [assignableUsers, setAssignableUsers]   = React.useState([]);
  const [assignedTo, setAssignedTo]             = React.useState(initialTicket.assignedTo?.id || '');
  const [assigning, setAssigning]               = React.useState(false);

  const cat         = window.MOCK.categories.find(c => c.id === initialTicket.categoryId);
  const currentUser = window._synUser || {};
  const isAdmin     = currentUser.role === 'admin' || currentUser.role === 'coordinator';
  function authH()  { return { Authorization: 'Bearer ' + (localStorage.getItem('syn_token') || '') }; }

  // Load full ticket (with comments) from the API
  React.useEffect(() => {
    if (!initialTicket.dbId) return;
    fetch(`/api/tickets/${initialTicket.dbId}`, { headers: authH() })
      .then(r => r.ok ? r.json() : null)
      .then(data => {
        if (data) { const n = normalizeTicket(data); setDetail(n); setStatus(n.status); setPriority(n.priority); setAssignedTo(n.assignedTo?.id || ''); }
      })
      .catch(() => {});
  }, [initialTicket.dbId]);

  // Fetch assignable users for this ticket's category (admin/coordinator only)
  React.useEffect(() => {
    if (!isAdmin) return;
    fetch(`/api/users/assignable?categoryId=${initialTicket.categoryId}`, { headers: authH() })
      .then(r => r.ok ? r.json() : [])
      .then(setAssignableUsers)
      .catch(() => {});
  }, [initialTicket.categoryId]);

  async function handleAssign() {
    setAssigning(true);
    try {
      const body = assignedTo ? { assigned_to: Number(assignedTo) } : { assigned_to: null };
      const res = await fetch(`/api/tickets/${initialTicket.dbId}`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json', ...authH() },
        body: JSON.stringify(body),
      });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error || 'Failed');
      const updated = await fetch(`/api/tickets/${initialTicket.dbId}`, { headers: authH() }).then(r => r.json());
      const n = normalizeTicket(updated);
      setDetail(n);
      setAssignedTo(n.assignedTo?.id || '');
      if (onRefresh) onRefresh();
    } catch (e) { console.error(e); }
    finally { setAssigning(false); }
  }

  const ticket   = detail || initialTicket;
  const comments = ticket.comments || [];

  async function addComment() {
    if (!comment.trim() || posting) return;
    setPosting(true);
    try {
      const res = await fetch(`/api/tickets/${initialTicket.dbId}/comment`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', ...authH() },
        body: JSON.stringify({ comment: comment.trim() }),
      });
      if (!res.ok) throw new Error('Failed');
      setComment('');
      const data = await fetch(`/api/tickets/${initialTicket.dbId}`, { headers: authH() }).then(r => r.json());
      const n = normalizeTicket(data);
      setDetail(n);
      setStatus(n.status);
    } catch (e) { console.error(e); }
    finally { setPosting(false); }
  }

  async function changeStatus(newStatus) {
    try {
      await fetch(`/api/tickets/${initialTicket.dbId}`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json', ...authH() },
        body: JSON.stringify({ status: newStatus }),
      });
      setStatus(newStatus);
      setDetail(d => d ? { ...d, status: newStatus } : null);
      if (onRefresh) onRefresh();
    } catch (e) { console.error(e); }
  }

  async function changePriority(newPriority) {
    try {
      await fetch(`/api/tickets/${initialTicket.dbId}`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json', ...authH() },
        body: JSON.stringify({ priority: newPriority }),
      });
      setPriority(newPriority);
      setDetail(d => d ? { ...d, priority: newPriority } : null);
      if (onRefresh) onRefresh();
    } catch (e) { console.error(e); }
  }

  async function handleDeleteTicket() {
    setDeletingTicket(true);
    try {
      await fetch(`/api/tickets/${initialTicket.dbId}`, {
        method: 'DELETE',
        headers: authH(),
      });
      setShowDeleteTicket(false);
      if (onRefresh) onRefresh();
      onBack();
    } catch (e) { console.error(e); }
    finally { setDeletingTicket(false); }
  }

  const nextStatuses = {
    'Open':        ['In Progress', 'Closed'],
    'In Progress': ['Resolved', 'Open'],
    'Resolved':    ['Closed', 'Open'],
    'Closed':      ['Open'],
  };

  return (
    <div>
      {/* Back */}
      <button onClick={onBack} style={{
        display: 'flex', alignItems: 'center', gap: 6, background: 'none', border: 'none',
        cursor: 'pointer', fontFamily: 'inherit', fontSize: 13, fontWeight: 600,
        color: '#64748B', marginBottom: 20, padding: 0,
      }}>
        <IC name="chevron_r" size={14} color="#64748B" style={{ transform: 'rotate(180deg)' }} /> Back to list
      </button>

      <div style={{ display: 'grid', gridTemplateColumns: '1fr 300px', gap: 20, alignItems: 'start' }}>
        {/* Main content */}
        <div>
          {/* Title card */}
          <div style={{ background: '#fff', borderRadius: 12, border: '1.5px solid #E2E8F0', padding: '24px 28px', marginBottom: 16 }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 12 }}>
              <span style={{ fontSize: 12, fontFamily: 'monospace', fontWeight: 700, color: '#94A3B8', background: '#F1F5F9', padding: '3px 8px', borderRadius: 5 }}>{ticket.id}</span>
              {cat && <span style={{ fontSize: 12, fontWeight: 600, color: cat.color, background: cat.bg, padding: '3px 10px', borderRadius: 20 }}>{cat.label}</span>}
              <StatusBadge status={status} />
              <PriorityBadge priority={priority} />
            </div>
            <h2 style={{ margin: '0 0 14px', fontSize: 20, fontWeight: 800, color: '#0F172A', lineHeight: 1.3 }}>{ticket.title}</h2>
            <p style={{ margin: 0, fontSize: 14, color: '#475569', lineHeight: 1.7 }}>{ticket.description}</p>
          </div>

          {/* Comments */}
          <div style={{ background: '#fff', borderRadius: 12, border: '1.5px solid #E2E8F0', overflow: 'hidden' }}>
            <div style={{ padding: '16px 22px', borderBottom: '1px solid #F1F5F9', fontWeight: 700, color: '#0F172A', fontSize: 14 }}>
              Activity ({comments.length})
            </div>
            <div style={{ padding: '8px 0' }}>
              {!detail && comments.length === 0 && (
                <div style={{ padding: '20px 22px', color: '#94A3B8', fontSize: 13 }}>Loading activity…</div>
              )}
              {comments.map((c, i) => (
                <div key={i} style={{ padding: '14px 22px', display: 'flex', gap: 12, borderBottom: i < comments.length - 1 ? '1px solid #F8FAFC' : 'none' }}>
                  <Avatar name={c.author.name} size={32} />
                  <div style={{ flex: 1 }}>
                    <div style={{ display: 'flex', gap: 8, alignItems: 'baseline', marginBottom: 4 }}>
                      <span style={{ fontWeight: 700, fontSize: 13, color: '#1E293B' }}>{c.author.name}</span>
                      <span style={{ fontSize: 11, color: '#CBD5E1' }}>{c.time}</span>
                    </div>
                    <p style={{ margin: 0, fontSize: 13.5, color: '#475569', lineHeight: 1.6 }}>{c.text}</p>
                  </div>
                </div>
              ))}
            </div>
            {/* Add comment */}
            <div style={{ padding: '16px 22px', borderTop: '1.5px solid #F1F5F9', display: 'flex', gap: 10 }}>
              <Avatar name={currentUser.name || 'User'} size={32} color={BRAND_ORANGE} />
              <div style={{ flex: 1 }}>
                <textarea value={comment} onChange={e => setComment(e.target.value)}
                  placeholder="Add a comment or update..."
                  rows={3} style={{ ...inputStyle, marginTop: 0, width: '100%', boxSizing: 'border-box' }} />
                <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: 8 }}>
                  <Btn variant="navy" size="sm" onClick={addComment} disabled={posting || !comment.trim()}>
                    {posting ? 'Posting…' : 'Post Comment'}
                  </Btn>
                </div>
              </div>
            </div>
          </div>
        </div>

        {/* Sidebar details */}
        <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
          {/* Status actions */}
          <div style={{ background: '#fff', borderRadius: 12, border: '1.5px solid #E2E8F0', padding: '18px 20px' }}>
            <div style={{ fontSize: 11, fontWeight: 700, color: '#94A3B8', textTransform: 'uppercase', letterSpacing: '0.07em', marginBottom: 10 }}>Update Status</div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 7 }}>
              {(nextStatuses[status] || []).map(s => (
                <Btn key={s} variant={s === 'Resolved' ? 'navy' : 'ghost'} size="sm"
                  onClick={() => changeStatus(s)} style={{ width: '100%', justifyContent: 'center' }}>
                  Mark as {s}
                </Btn>
              ))}
            </div>
          </div>

          {/* Details */}
          <div style={{ background: '#fff', borderRadius: 12, border: '1.5px solid #E2E8F0', padding: '18px 20px' }}>
            <div style={{ fontSize: 11, fontWeight: 700, color: '#94A3B8', textTransform: 'uppercase', letterSpacing: '0.07em', marginBottom: 12 }}>Details</div>
            {[
              { label: 'Submitted by', content: (
                <div style={{ display: 'flex', alignItems: 'center', gap: 7 }}>
                  <Avatar name={ticket.submittedBy.name} size={24} />
                  <span style={{ fontSize: 13, color: '#1E293B', fontWeight: 600 }}>{ticket.submittedBy.name}</span>
                </div>
              )},
              { label: 'Assigned to', content: isAdmin && assignableUsers.length > 0
                ? (
                  <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
                    <select
                      value={assignedTo}
                      onChange={e => setAssignedTo(e.target.value)}
                      style={{
                        width: '100%', padding: '6px 10px', borderRadius: 7,
                        border: '1.5px solid #E2E8F0', fontSize: 13, fontFamily: 'inherit',
                        color: '#1E293B', background: '#FAFBFF', cursor: 'pointer',
                      }}
                    >
                      <option value="">— Unassigned —</option>
                      {assignableUsers.map(u => (
                        <option key={u.id} value={u.id}>{u.name} ({u.role})</option>
                      ))}
                    </select>
                    <Btn variant="navy" size="sm" onClick={handleAssign} disabled={assigning}
                      style={{ width: '100%', justifyContent: 'center' }}>
                      {assigning ? 'Saving…' : 'Save Assignment'}
                    </Btn>
                  </div>
                )
                : ticket.assignedTo
                  ? <div style={{ display: 'flex', alignItems: 'center', gap: 7 }}>
                      <Avatar name={ticket.assignedTo.name} size={24} />
                      <span style={{ fontSize: 13, color: '#1E293B', fontWeight: 600 }}>{ticket.assignedTo.name}</span>
                    </div>
                  : <span style={{ fontSize: 13, color: '#CBD5E1', fontStyle: 'italic' }}>Unassigned</span>
              },
              { label: 'Category',    content: <span style={{ fontSize: 13, color: cat?.color, fontWeight: 600 }}>{cat?.label}</span> },
              { label: 'Priority', content: currentUser.role === 'admin'
                ? (
                  <div style={{ display: 'flex', gap: 5, flexWrap: 'wrap' }}>
                    {['Low', 'Medium', 'High', 'Urgent'].map(p => {
                      const pColors = { Low: '#64748B', Medium: '#B45309', High: '#B91C1C', Urgent: '#fff' };
                      const pBgs    = { Low: '#F1F5F9', Medium: '#FFFBEB', High: '#FEF2F2', Urgent: '#DC2626' };
                      const active  = priority === p;
                      return (
                        <button key={p} type="button" onClick={() => changePriority(p)} style={{
                          padding: '3px 9px', border: active ? `2px solid ${p === 'Urgent' ? '#DC2626' : pColors[p]}` : '2px solid #E2E8F0',
                          borderRadius: 5, cursor: 'pointer',
                          background: active ? pBgs[p] : '#fff',
                          color: active ? pColors[p] : '#94A3B8',
                          fontFamily: 'inherit', fontSize: 11, fontWeight: 700, transition: 'all 0.12s',
                        }}>{p}</button>
                      );
                    })}
                  </div>
                )
                : <PriorityBadge priority={priority} />
              },
              { label: 'Created',     content: <span style={{ fontSize: 13, color: '#475569' }}>{ticket.createdAt}</span> },
              { label: 'Last update', content: <span style={{ fontSize: 13, color: '#475569' }}>{ticket.updatedAt}</span> },
            ].map(({ label, content }) => (
              <div key={label} style={{ marginBottom: 12 }}>
                <div style={{ fontSize: 11, color: '#94A3B8', fontWeight: 600, marginBottom: 4 }}>{label}</div>
                {content}
              </div>
            ))}
          </div>

          {/* Danger Zone — admin only */}
          {currentUser.role === 'admin' && (
            <div style={{ background: '#fff', borderRadius: 12, border: '1.5px solid #FECACA', padding: '18px 20px' }}>
              <div style={{ fontSize: 11, fontWeight: 700, color: '#B91C1C', textTransform: 'uppercase', letterSpacing: '0.07em', marginBottom: 10 }}>Danger Zone</div>
              <Btn variant="danger" size="sm" icon="trash" onClick={() => setShowDeleteTicket(true)}
                style={{ width: '100%', justifyContent: 'center', background: '#DC2626', color: '#fff' }}>
                Delete Concern
              </Btn>
            </div>
          )}
        </div>
      </div>

      {showDeleteTicket && (
        <DeleteConfirmModal
          count={1}
          onCancel={() => setShowDeleteTicket(false)}
          onConfirm={handleDeleteTicket}
          deleting={deletingTicket}
        />
      )}
    </div>
  );
}

Object.assign(window, { TicketList, TicketDetail, SubmitTicketModal, normalizeTicket, DeleteConfirmModal });
