// Staff management (CRUD) + Knowledge Base / คลังความรู้

// ============== Staff Management ==============
const StaffProfile = ({ staff: s, onBack }) => {
  const supervised = D.SUPERVISION_RECORDS.filter(r => r.supervisee === s.id);
  const supervising = D.SUPERVISION_RECORDS.filter(r => r.supervisor === s.id);
  return (
    <div className="page">
      <div className="section-h" style={{ marginBottom: 16 }}>
        <button className="btn" onClick={onBack} style={{ flexShrink: 0 }}>
          ← กลับ
        </button>
        <div>
          <h2>{s.title}{s.name}</h2>
          <div className="sub">{D.POSITIONS[s.pos]} · {s.years} ปี · {s.role === 'supervisor' ? 'ผู้นิเทศ' : 'ผู้รับการนิเทศ'}</div>
        </div>
      </div>

      <div className="kpi-row" style={{ marginBottom: 16 }}>
        <div className="kpi">
          <div className="label">ระดับสมรรถนะ</div>
          <div style={{ marginTop: 6 }}><LevelChip level={s.level} /></div>
        </div>
        <div className="kpi">
          <div className="label">รับการนิเทศ</div>
          <div className="value">{supervised.length}</div>
          <div className="delta muted">ครั้ง</div>
        </div>
        {supervising.length > 0 && (
          <div className="kpi">
            <div className="label">นิเทศผู้อื่น</div>
            <div className="value">{supervising.length}</div>
            <div className="delta muted">ครั้ง</div>
          </div>
        )}
        {supervised.length > 0 && (
          <div className="kpi">
            <div className="label">คะแนนเฉลี่ย</div>
            <div className="value">{(supervised.reduce((t, r) => t + (Number(r.score) || 0), 0) / supervised.length).toFixed(2)}</div>
            <div className="delta muted">/ 5.0</div>
          </div>
        )}
      </div>

      <div className="card">
        <div className="card-header">
          <h3>ประวัติการนิเทศรายบุคคล</h3>
          <span className="sub">· {supervised.length} รายการ</span>
        </div>
        <div className="card-body" style={{ padding: 0 }}>
          {supervised.length === 0 ? (
            <div className="txt-sm muted" style={{ padding: 16 }}>ยังไม่มีบันทึกการนิเทศ</div>
          ) : supervised.map(r => (
            <div key={r.id} style={{ padding: '12px 16px', borderBottom: '1px solid var(--c-border-soft)' }}>
              <div className="flex-between" style={{ marginBottom: 4 }}>
                <span className="mono txt-xs muted">{r.date} · {r.shift}</span>
                <span className={`badge ${r.status === 'closed' ? 'ok' : 'warn'}`}>{r.status === 'closed' ? 'ปิดเคส' : 'ติดตาม'}</span>
              </div>
              <strong className="txt-sm">{r.topic}</strong>
              <div className="flex" style={{ marginTop: 6, gap: 8, flexWrap: 'wrap' }}>
                <span className="badge">{r.activity}</span>
                <span className="txt-xs muted">โดย: {staffShort(r.supervisor)}</span>
                <div className="flex" style={{ marginLeft: 'auto', gap: 6 }}>
                  <strong className="mono txt-sm">{Number(r.score).toFixed(1)}</strong>
                  <LevelChip level={r.score} />
                </div>
              </div>
              {r.strengths && <div className="txt-xs" style={{ marginTop: 6, color: 'var(--c-ok)' }}>✓ {r.strengths}</div>}
              {r.weaknesses && <div className="txt-xs" style={{ marginTop: 2, color: 'var(--c-warn)' }}>△ {r.weaknesses}</div>}
            </div>
          ))}
        </div>
      </div>
    </div>
  );
};

const StaffManagement = () => {
  const [, force] = useState(0);
  useEffect(() => window.LR_STAFF_STORE.subscribe(() => force(n => n + 1)), []);
  const staff = D.STAFF;
  const [search, setSearch] = useState('');
  const [filter, setFilter] = useState('all');
  const [editing, setEditing] = useState(null); // staff object or 'new'
  const [viewing, setViewing] = useState(null); // staff object for profile view

  if (viewing) return <StaffProfile staff={viewing} onBack={() => setViewing(null)} />;

  const filtered = staff.filter(s => {
    if (filter === 'supervisor' && s.role !== 'supervisor') return false;
    if (filter === 'supervisee' && s.role !== 'supervisee') return false;
    if (filter === 'rn' && !['snr_special','snr','operational','rn'].includes(s.pos)) return false;
    if (filter === 'aide' && !['assistant','aide'].includes(s.pos)) return false;
    if (search && !s.name.toLowerCase().includes(search.toLowerCase())) return false;
    return true;
  });

  return (
    <div className="page">
      <div className="section-h">
        <div>
          <h2>จัดการข้อมูลบุคลากร</h2>
          <div className="sub">เพิ่ม · แก้ไข · ลบรายชื่อพยาบาลและผู้ช่วยในงานห้องคลอด</div>
        </div>
        <div className="flex">
          <button className="btn"><Icon name="download" size={14} />Export CSV</button>
          <button className="btn btn-primary" onClick={() => setEditing('new')}>
            <Icon name="plus" size={14} />เพิ่มบุคลากร
          </button>
        </div>
      </div>

      <div className="kpi-row" style={{ marginBottom: 16 }}>
        <div className="kpi">
          <div className="label">บุคลากรทั้งหมด</div>
          <div className="value">{staff.length}</div>
          <div className="delta muted">คน</div>
        </div>
        <div className="kpi">
          <div className="label">พยาบาลวิชาชีพ</div>
          <div className="value">{staff.filter(s => ['snr_special','snr','operational','rn'].includes(s.pos)).length}</div>
          <div className="delta muted">รวมหัวหน้า/ปฏิบัติการ</div>
        </div>
        <div className="kpi">
          <div className="label">ผู้ช่วย / พนง.ช่วยเหลือ</div>
          <div className="value">{staff.filter(s => ['assistant','aide'].includes(s.pos)).length}</div>
          <div className="delta muted">สนับสนุนงาน</div>
        </div>
        <div className="kpi">
          <div className="label">อายุงานเฉลี่ย</div>
          <div className="value">{(staff.reduce((s, x) => s + x.years, 0) / staff.length).toFixed(1)}<small> ปี</small></div>
          <div className="delta muted">ทั้งทีม</div>
        </div>
      </div>

      <div className="card">
        <div className="card-header">
          <h3>รายชื่อบุคลากร</h3>
          <div className="flex" style={{ marginLeft: 'auto' }}>
            <div style={{ position: 'relative' }}>
              <Icon name="search" size={14} />
              <input
                value={search}
                onChange={(e) => setSearch(e.target.value)}
                placeholder="ค้นหาชื่อ..."
                style={{
                  padding: '7px 12px 7px 30px',
                  border: '1px solid var(--c-border)',
                  borderRadius: 8,
                  background: 'var(--c-surface)',
                  color: 'var(--c-ink)',
                  width: 200,
                  fontSize: 13,
                }}
              />
              <span style={{ position: 'absolute', left: 8, top: '50%', transform: 'translateY(-50%)', pointerEvents: 'none', color: 'var(--c-ink-muted)' }}>
                <Icon name="search" size={14} />
              </span>
            </div>
            <div className="chips" style={{ marginLeft: 8 }}>
              <button className={`chip ${filter==='all'?'active':''}`} onClick={() => setFilter('all')}>ทั้งหมด</button>
              <button className={`chip ${filter==='supervisor'?'active':''}`} onClick={() => setFilter('supervisor')}>ผู้นิเทศ</button>
              <button className={`chip ${filter==='supervisee'?'active':''}`} onClick={() => setFilter('supervisee')}>ผู้รับนิเทศ</button>
              <button className={`chip ${filter==='aide'?'active':''}`} onClick={() => setFilter('aide')}>ผู้ช่วย/พนง.</button>
            </div>
          </div>
        </div>
        <div className="card-body" style={{ padding: 0 }}>
          <table className="t">
            <thead>
              <tr>
                <th style={{ width: 50 }}>ลำดับ</th>
                <th>ชื่อ-สกุล</th>
                <th>ตำแหน่ง</th>
                <th>อายุงาน</th>
                <th>ระดับสมรรถนะ</th>
                <th>บทบาท</th>
                <th style={{ width: 110 }}></th>
              </tr>
            </thead>
            <tbody>
              {filtered.map((s, i) => (
                <tr key={s.id} style={{ cursor: 'pointer' }} onClick={() => setViewing(s)}>
                  <td className="mono muted">{String(i + 1).padStart(2, '0')}</td>
                  <td>
                    <div className="flex">
                      <Avatar name={s.name} size={28} />
                      <div>
                        <strong>{s.title}{s.name}</strong>
                        <div className="txt-xs muted mono">{s.id}</div>
                      </div>
                    </div>
                  </td>
                  <td><span className="txt-sm">{D.POSITIONS[s.pos]}</span></td>
                  <td className="mono">{s.years} ปี</td>
                  <td><LevelChip level={s.level} /></td>
                  <td>
                    <span className={`badge ${s.role === 'supervisor' ? 'info' : ''}`}>
                      {s.role === 'supervisor' ? 'ผู้นิเทศ' : 'ผู้รับนิเทศ'}
                    </span>
                  </td>
                  <td onClick={e => e.stopPropagation()}>
                    <div className="flex" style={{ gap: 4 }}>
                      <button className="btn btn-sm btn-ghost" onClick={() => setEditing(s)} title="แก้ไข">
                        <Icon name="edit" size={14} />
                      </button>
                      <button
                        className="btn btn-sm btn-ghost"
                        style={{ color: 'var(--c-danger)' }}
                        onClick={() => {
                          if (confirm(`ลบ ${s.title}${s.name} ?`)) window.LR_STAFF_STORE.remove(s.id);
                        }}
                        title="ลบ"
                      >ลบ</button>
                    </div>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>

      {editing && (
        <StaffEditModal
          staff={editing === 'new' ? null : editing}
          onClose={() => setEditing(null)}
          onSave={(data) => {
            if (editing === 'new') window.LR_STAFF_STORE.add(data);
            else window.LR_STAFF_STORE.update(editing.id, data);
            setEditing(null);
          }}
        />
      )}
    </div>
  );
};

const StaffEditModal = ({ staff, onClose, onSave }) => {
  const [form, setForm] = useState(staff || {
    title: 'น.ส.', name: '', pos: 'rn', years: 1, level: 'novice', role: 'supervisee',
  });
  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));

  return (
    <div style={{
      position: 'fixed', inset: 0, background: 'rgba(20, 40, 50, 0.45)',
      display: 'grid', placeItems: 'center', zIndex: 2000, padding: 24,
    }} onClick={onClose}>
      <div
        className="card"
        style={{ width: '100%', maxWidth: 560, boxShadow: 'var(--shadow-lg)' }}
        onClick={(e) => e.stopPropagation()}
      >
        <div className="card-header">
          <h3>{staff ? 'แก้ไขข้อมูลบุคลากร' : 'เพิ่มบุคลากรใหม่'}</h3>
          <button className="btn btn-sm btn-ghost" style={{ marginLeft: 'auto' }} onClick={onClose}>ปิด</button>
        </div>
        <div className="card-body stack">
          <div className="grid-2">
            <div>
              <label className="muted txt-xs">คำนำหน้า</label>
              <select
                value={form.title}
                onChange={(e) => set('title', e.target.value)}
                style={{ width: '100%', padding: 8, marginTop: 4, border: '1px solid var(--c-border)', borderRadius: 8, background: 'var(--c-surface)' }}
              >
                <option>น.ส.</option>
                <option>นาง</option>
                <option>นาย</option>
              </select>
            </div>
            <div>
              <label className="muted txt-xs">ชื่อ-สกุล</label>
              <input
                value={form.name}
                onChange={(e) => set('name', e.target.value)}
                placeholder="เช่น สมหญิง ใจดี"
                style={{ width: '100%', padding: 8, marginTop: 4, border: '1px solid var(--c-border)', borderRadius: 8, background: 'var(--c-surface)' }}
              />
            </div>
          </div>

          <div>
            <label className="muted txt-xs">ตำแหน่ง</label>
            <select
              value={form.pos}
              onChange={(e) => set('pos', e.target.value)}
              style={{ width: '100%', padding: 8, marginTop: 4, border: '1px solid var(--c-border)', borderRadius: 8, background: 'var(--c-surface)' }}
            >
              {Object.entries(D.POSITIONS).map(([k, v]) => <option key={k} value={k}>{v}</option>)}
            </select>
          </div>

          <div className="grid-2">
            <div>
              <label className="muted txt-xs">อายุงาน (ปี)</label>
              <input
                type="number"
                min={0}
                value={form.years}
                onChange={(e) => set('years', parseInt(e.target.value) || 0)}
                style={{ width: '100%', padding: 8, marginTop: 4, border: '1px solid var(--c-border)', borderRadius: 8, background: 'var(--c-surface)' }}
              />
            </div>
            <div>
              <label className="muted txt-xs">บทบาท</label>
              <div className="role-switcher" style={{ marginTop: 4, width: '100%' }}>
                <button
                  className={form.role === 'supervisor' ? 'active' : ''}
                  onClick={() => set('role', 'supervisor')}
                  style={{ flex: 1 }}
                >ผู้นิเทศ</button>
                <button
                  className={form.role === 'supervisee' ? 'active' : ''}
                  onClick={() => set('role', 'supervisee')}
                  style={{ flex: 1 }}
                >ผู้รับนิเทศ</button>
              </div>
            </div>
          </div>

          <div>
            <label className="muted txt-xs">ระดับสมรรถนะ (Benner)</label>
            <div className="rating-row" style={{ marginTop: 4 }}>
              {D.LEVELS.map(lv => (
                <label key={lv.id} className={form.level === lv.id ? 'active' : ''} onClick={() => set('level', lv.id)}>
                  <div className="mono" style={{ fontSize: 16, fontWeight: 700 }}>{lv.n}</div>
                  <div className="txt-xs">{lv.label}</div>
                </label>
              ))}
            </div>
          </div>
        </div>
        <div style={{ padding: 'var(--sp-4) var(--sp-5)', borderTop: '1px solid var(--c-border-soft)', display: 'flex', justifyContent: 'flex-end', gap: 8 }}>
          <button className="btn" onClick={onClose}>ยกเลิก</button>
          <button
            className="btn btn-primary"
            disabled={!form.name.trim()}
            onClick={() => onSave(form)}
          >บันทึก</button>
        </div>
      </div>
    </div>
  );
};

// ============== Knowledge Base / คลังความรู้ ==============
const KNOWLEDGE = [
  {
    id: 'k_manual', cat: 'คู่มือหลัก',
    title: 'คู่มือการนิเทศทางการพยาบาล งานห้องคลอด',
    sub: 'กลุ่มภารกิจด้านการพยาบาล · โรงพยาบาลศรีสะเกษ',
    type: 'PDF', pages: 38, updated: '2026-04-15',
    tags: ['Master', 'HA', 'PDPA'],
    desc: 'แนวทางและกระบวนการนิเทศ SPRDD พร้อม 7 กิจกรรมการนิเทศ และตัวอย่างประเมินผล',
  },
  {
    id: 'k_pph', cat: 'Emergency Protocol',
    title: 'PPH Management Bundle',
    sub: 'Postpartum Hemorrhage · กระบวนการ Active Management',
    type: 'PDF', pages: 12, updated: '2026-04-02',
    tags: ['High-Alert', 'Bundle'],
    desc: 'Active management ของระยะที่ 3 · การใช้ Oxytocin / Carbetocin · เกณฑ์ massive transfusion',
  },
  {
    id: 'k_shoulder', cat: 'Emergency Protocol',
    title: 'Shoulder Dystocia (HELPERR)',
    sub: 'การช่วยภาวะคลอดติดไหล่',
    type: 'Checklist', pages: 4, updated: '2026-03-22',
    tags: ['Drill', 'HELPERR'],
    desc: 'McRoberts maneuver, suprapubic pressure, internal rotation, ขั้นตอนการประเมินทารก',
  },
  {
    id: 'k_pih', cat: 'Emergency Protocol',
    title: 'Severe Pre-eclampsia / Eclampsia',
    sub: 'การให้ MgSO4 · เป้าหมาย BP control',
    type: 'Protocol', pages: 8, updated: '2026-02-18',
    tags: ['Magnesium', 'MgSO4'],
    desc: 'Loading dose, maintenance, antidote (calcium gluconate), monitoring DTR/RR/urine output',
  },
  {
    id: 'k_efm', cat: 'Skills Manual',
    title: 'EFM Interpretation Guide',
    sub: 'Category I/II/III และ Intrauterine Resuscitation',
    type: 'Manual', pages: 20, updated: '2026-03-10',
    tags: ['Category', 'LIONS'],
    desc: 'Baseline, variability, acceleration, deceleration, ขั้นตอน LIONS เมื่อเจอ Cat-II',
  },
  {
    id: 'k_ncpr', cat: 'Skills Manual',
    title: 'Neonatal Resuscitation (NCPR)',
    sub: 'ฟื้นคืนชีพทารกแรกเกิดตามแนวทาง AAP',
    type: 'Manual', pages: 24, updated: '2026-04-10',
    tags: ['NCPR', 'AAP'],
    desc: 'Initial steps, PPV, chest compression, การประเมิน Apgar score, drug therapy',
  },
  {
    id: 'k_isbar', cat: 'Communication',
    title: 'ISBAR Handover Template',
    sub: 'แบบฟอร์มส่งเวรมาตรฐาน',
    type: 'Template', pages: 2, updated: '2026-01-30',
    tags: ['Handover'],
    desc: 'Introduction · Situation · Background · Assessment · Recommendation',
  },
  {
    id: 'k_c3ther', cat: 'Quality Tool',
    title: 'C3THER Bedside Round Tool',
    sub: 'ทบทวนข้างเตียงตามแนวคิด C3THER',
    type: 'Worksheet', pages: 1, updated: '2026-02-05',
    tags: ['12 ทบทวน', 'Quality'],
    desc: 'Care · Communication · Continuity · Team · HR · Environment · Record',
  },
  {
    id: 'k_isbarlec', cat: 'Training',
    title: 'EFM Workshop (วิดีโอ + Cases)',
    sub: 'Workshop EFM 6 modules · 30 sample strips',
    type: 'Video', pages: null, duration: '2h 40m', updated: '2026-04-22',
    tags: ['In-service'],
    desc: 'การวิเคราะห์ FHR pattern พร้อมเคสตัวอย่างและ self-assessment',
  },
  {
    id: 'k_pdpa', cat: 'Policy',
    title: 'PDPA & Patient Confidentiality',
    sub: 'การคุ้มครองข้อมูลส่วนบุคคล',
    type: 'Policy', pages: 6, updated: '2026-01-01',
    tags: ['Legal', 'PDPA'],
    desc: 'ขอบเขตข้อมูลที่เก็บได้ · การเปิดเผยข้อมูลทางคลินิก · บทลงโทษ',
  },
  {
    id: 'k_rca', cat: 'Quality Tool',
    title: 'RCA Worksheet',
    sub: 'Root Cause Analysis template',
    type: 'Template', pages: 4, updated: '2026-03-01',
    tags: ['Risk Mgmt'],
    desc: 'ผังวิเคราะห์สาเหตุ · 5-why · Fishbone · แผนแก้ไขเชิงระบบ',
  },
  {
    id: 'k_breastfeed', cat: 'Skills Manual',
    title: 'Breastfeeding & Skin-to-skin Guide',
    sub: 'ส่งเสริมการเลี้ยงลูกด้วยนมแม่',
    type: 'Manual', pages: 14, updated: '2026-02-28',
    tags: ['Mother & Child'],
    desc: 'Latch-on, position, common problems, การประเมิน LATCH score',
  },
];

// ── ฟอร์มเพิ่มรายการความรู้ใหม่ ────────────────────────────
const KnowledgeAddModal = ({ onClose, onSaved }) => {
  const { useState: us, useRef: ur } = React;
  const TYPES = ['PDF','Manual','Protocol','Checklist','Template','Worksheet','Video','Policy','Link'];
  const CATS  = ['คู่มือหลัก','Emergency Protocol','Skills Manual','Communication','Quality Tool','Training','Policy'];
  const [form, setForm] = us({ cat:'คู่มือหลัก', title:'', sub:'', type:'PDF', pages:'', desc:'', tags:'' });
  const [attachments, setAttachments] = us([]);
  const [attMode, setAttMode] = us('link');
  const [linkDraft, setLinkDraft] = us({ name:'', url:'' });
  const [saving, setSaving] = us(false);
  const [err, setErr] = us('');
  const fileRef = ur(null);
  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));
  const inp = { padding:'8px 10px', border:'1px solid var(--c-border)', borderRadius:8, background:'var(--c-surface)', color:'var(--c-ink)', width:'100%', fontSize:13, boxSizing:'border-box' };

  const extIcon = (ext) => {
    if (ext === 'pdf') return '📕';
    if (['doc','docx'].includes(ext)) return '📄';
    if (['xls','xlsx'].includes(ext)) return '📊';
    if (['ppt','pptx'].includes(ext)) return '📋';
    if (['jpg','jpeg','png','gif'].includes(ext)) return '🖼';
    if (['mp4','mov','avi'].includes(ext)) return '🎬';
    return '📎';
  };

  const addLink = () => {
    if (!linkDraft.url.trim()) return;
    setAttachments(a => [...a, {
      attachment_type: 'link',
      name: linkDraft.name.trim() || linkDraft.url.trim(),
      url: linkDraft.url.trim(),
    }]);
    setLinkDraft({ name:'', url:'' });
  };

  const handleFiles = (files) => {
    Array.from(files).forEach(f => {
      const ext = f.name.split('.').pop().toLowerCase();
      setAttachments(a => [...a, {
        attachment_type: 'file',
        name: f.name,
        url: URL.createObjectURL(f),
        file_size: f.size,
        file_ext: ext,
      }]);
    });
    if (fileRef.current) fileRef.current.value = '';
  };

  const removeAtt = (i) => setAttachments(a => a.filter((_, j) => j !== i));

  async function save() {
    if (!form.title.trim()) { setErr('กรุณาใส่ชื่อรายการ'); return; }
    setSaving(true); setErr('');
    try {
      const result = await window.DB.knowledge.create({
        cat: form.cat, title: form.title.trim(), sub: form.sub.trim(),
        type: form.type, pages: form.pages ? parseInt(form.pages) : null,
        desc: form.desc.trim(),
        tags: form.tags.split(',').map(t => t.trim()).filter(Boolean),
      });
      const itemId = result?.id;
      if (itemId && attachments.length > 0) {
        for (const att of attachments) {
          await window.DB.knowledge.addAttachment(itemId, att);
        }
      }
      onSaved();
    } catch(e) { setErr(e.message); setSaving(false); }
  }

  return (
    <div style={{ position:'fixed', inset:0, background:'rgba(0,0,0,0.4)', zIndex:1000, display:'flex', alignItems:'center', justifyContent:'center', padding:20 }}>
      <div className="card" style={{ width:'100%', maxWidth:560, maxHeight:'92vh', overflowY:'auto' }}>
        <div className="card-header">
          <h3>เพิ่มรายการความรู้ใหม่</h3>
          <button className="btn btn-sm btn-ghost" style={{ marginLeft:'auto' }} onClick={onClose}>ยกเลิก</button>
        </div>
        <div className="card-body stack">
          <div className="grid-2">
            <div>
              <label className="muted txt-xs">หมวดหมู่</label>
              <select value={form.cat} onChange={e => set('cat', e.target.value)} style={{ ...inp, marginTop:4 }}>
                {CATS.map(c => <option key={c}>{c}</option>)}
              </select>
            </div>
            <div>
              <label className="muted txt-xs">ประเภท</label>
              <select value={form.type} onChange={e => set('type', e.target.value)} style={{ ...inp, marginTop:4 }}>
                {TYPES.map(t => <option key={t}>{t}</option>)}
              </select>
            </div>
          </div>
          <div>
            <label className="muted txt-xs">ชื่อเอกสาร / คู่มือ *</label>
            <input value={form.title} onChange={e => set('title', e.target.value)} placeholder="เช่น PPH Management Bundle" style={{ ...inp, marginTop:4 }} autoFocus />
          </div>
          <div>
            <label className="muted txt-xs">หัวข้อย่อย</label>
            <input value={form.sub} onChange={e => set('sub', e.target.value)} placeholder="เช่น Postpartum Hemorrhage · กระบวนการ Active Management" style={{ ...inp, marginTop:4 }} />
          </div>
          <div>
            <label className="muted txt-xs">รายละเอียด / เนื้อหาโดยย่อ</label>
            <textarea value={form.desc} onChange={e => set('desc', e.target.value)} rows={3} style={{ ...inp, marginTop:4, resize:'vertical', fontFamily:'inherit', lineHeight:1.6 }} />
          </div>
          <div className="grid-2">
            <div>
              <label className="muted txt-xs">จำนวนหน้า</label>
              <input type="number" min="1" value={form.pages} onChange={e => set('pages', e.target.value)} placeholder="เช่น 12" style={{ ...inp, marginTop:4 }} />
            </div>
            <div>
              <label className="muted txt-xs">Tags (คั่นด้วย ,)</label>
              <input value={form.tags} onChange={e => set('tags', e.target.value)} placeholder="เช่น Bundle, High-Alert" style={{ ...inp, marginTop:4 }} />
            </div>
          </div>

          {/* ── Attachment section ── */}
          <div style={{ borderTop:'1px solid var(--c-border-soft)', paddingTop:14 }}>
            <div className="flex" style={{ justifyContent:'space-between', alignItems:'center', marginBottom:10 }}>
              <span className="muted txt-xs" style={{ fontWeight:700 }}>ไฟล์ & ลิงก์แนบ</span>
              {attachments.length > 0 && <span className="txt-xs muted">{attachments.length} รายการ</span>}
            </div>

            {/* list of added attachments */}
            {attachments.length > 0 && (
              <div style={{ display:'flex', flexDirection:'column', gap:5, marginBottom:10 }}>
                {attachments.map((a, i) => (
                  <div key={i} style={{ display:'flex', alignItems:'center', gap:8, padding:'7px 10px', background:'var(--c-bg)', borderRadius:8, border:'1px solid var(--c-border-soft)' }}>
                    <span style={{ fontSize:16 }}>{a.attachment_type === 'link' ? '🔗' : extIcon(a.file_ext || '')}</span>
                    <span className="txt-sm" style={{ flex:1, minWidth:0, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{a.name}</span>
                    {a.file_size && <span className="txt-xs muted">{(a.file_size / 1024).toFixed(0)} KB</span>}
                    <button onClick={() => removeAtt(i)} style={{ background:'none', border:'none', cursor:'pointer', color:'var(--c-danger)', fontSize:18, lineHeight:1, padding:'0 2px', flexShrink:0 }}>✕</button>
                  </div>
                ))}
              </div>
            )}

            {/* mode toggle */}
            <div className="flex" style={{ gap:6, marginBottom:10 }}>
              <button className={`chip ${attMode==='link'?'active':''}`} onClick={() => setAttMode('link')}>🔗 ลิงก์</button>
              <button className={`chip ${attMode==='file'?'active':''}`} onClick={() => setAttMode('file')}>📎 ไฟล์</button>
            </div>

            {attMode === 'link' ? (
              <div style={{ display:'flex', flexDirection:'column', gap:6 }}>
                <input value={linkDraft.name} onChange={e => setLinkDraft(p => ({...p, name:e.target.value}))}
                  placeholder="ชื่อลิงก์ เช่น แนวทาง PPH 2566" style={{ ...inp }} />
                <div className="flex" style={{ gap:6 }}>
                  <input type="url" value={linkDraft.url} onChange={e => setLinkDraft(p => ({...p, url:e.target.value}))}
                    placeholder="https://..." style={{ ...inp, flex:1 }}
                    onKeyDown={e => e.key === 'Enter' && addLink()} />
                  <button className="btn btn-primary btn-sm" onClick={addLink} disabled={!linkDraft.url.trim()}
                    style={{ whiteSpace:'nowrap', flexShrink:0 }}>+ เพิ่ม</button>
                </div>
              </div>
            ) : (
              <div
                onClick={() => fileRef.current?.click()}
                onDragOver={e => e.preventDefault()}
                onDrop={e => { e.preventDefault(); handleFiles(e.dataTransfer.files); }}
                style={{ border:'2px dashed var(--c-border)', borderRadius:10, padding:'22px 16px', textAlign:'center', cursor:'pointer', background:'var(--c-bg)', transition:'border-color .15s' }}
              >
                <div style={{ fontSize:30, marginBottom:6 }}>📂</div>
                <div className="txt-sm" style={{ fontWeight:600, marginBottom:3 }}>คลิกเพื่อเลือกไฟล์ หรือลากวางที่นี่</div>
                <div className="txt-xs muted">PDF · Word · Excel · PowerPoint · รูปภาพ · วิดีโอ</div>
                <input ref={fileRef} type="file" multiple style={{ display:'none' }}
                  accept=".pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.jpg,.jpeg,.png,.gif,.mp4,.mov"
                  onChange={e => handleFiles(e.target.files)} />
              </div>
            )}
          </div>

          {err && <div style={{ background:'#fee2e2', color:'#991b1b', borderRadius:8, padding:'10px 12px', fontSize:13 }}>{err}</div>}
          <button className="btn btn-primary" onClick={save} disabled={saving}>{saving ? 'กำลังบันทึก…' : 'บันทึก'}</button>
        </div>
      </div>
    </div>
  );
};

// ── ฟอร์มเพิ่ม Attachment ────────────────────────────────
const AttachForm = ({ itemId, onAdded }) => {
  const { useState: us } = React;
  const [type, setType] = us('link');
  const [name, setName] = us('');
  const [url, setUrl]   = us('');
  const [saving, setSaving] = us(false);
  const inp = { padding:'7px 10px', border:'1px solid var(--c-border)', borderRadius:8, background:'var(--c-surface)', color:'var(--c-ink)', fontSize:13 };

  async function add() {
    if (!name.trim()) return;
    setSaving(true);
    try {
      await window.DB.knowledge.addAttachment(itemId, { attachment_type: type, name: name.trim(), url: url.trim() || null });
      setName(''); setUrl('');
      onAdded();
    } catch(e) { alert(e.message); }
    setSaving(false);
  }

  return (
    <div style={{ background:'var(--c-surface-raised, var(--c-surface))', borderRadius:10, padding:12, border:'1px dashed var(--c-border)', marginTop:8 }}>
      <div className="flex" style={{ gap:6, marginBottom:8 }}>
        <button className={`chip ${type==='link'?'active':''}`} onClick={() => setType('link')}>🔗 Link</button>
        <button className={`chip ${type==='file'?'active':''}`} onClick={() => setType('file')}>📄 ไฟล์</button>
      </div>
      <div className="flex" style={{ gap:6, flexWrap:'wrap' }}>
        <input value={name} onChange={e => setName(e.target.value)}
          placeholder={type==='link' ? 'ชื่อ Link เช่น คู่มือ PPH Bundle' : 'ชื่อไฟล์ เช่น PPH_Checklist.pdf'}
          style={{ ...inp, flex:2, minWidth:120 }} />
        {type === 'link' && (
          <input type="url" value={url} onChange={e => setUrl(e.target.value)}
            placeholder="https://..." style={{ ...inp, flex:3, minWidth:160 }} />
        )}
        <button className="btn btn-primary btn-sm" onClick={add} disabled={saving || !name.trim()}>
          {saving ? '…' : '+ เพิ่ม'}
        </button>
      </div>
    </div>
  );
};

const KnowledgeBase = ({ role } = {}) => {
  const { useState: us, useEffect: ue } = React;
  const [cat, setCat]         = us('all');
  const [search, setSearch]   = us('');
  const [items, setItems]     = us(KNOWLEDGE.map(k => ({ ...k, attachments: [] })));
  const [selected, setSelected] = us(null);
  const [showAdd, setShowAdd] = us(false);

  // Use role prop if given, else fall back to JWT decode
  const canEdit = (() => {
    if (role !== undefined) return window.isSupervisorRole ? window.isSupervisorRole(role) : false;
    try {
      const tk = localStorage.getItem('lr_token');
      if (!tk) return true; // demo mode
      const p = JSON.parse(atob(tk.split('.')[1]));
      return window.isSupervisorRole ? window.isSupervisorRole(p.role) : true;
    } catch { return true; }
  })();
  const isSupervisor = canEdit; // alias for existing references below

  async function loadItems() {
    try {
      const data = await window.DB.knowledge.list();
      setItems(data);
      setSelected(prev => prev ? (data.find(k => k.id === prev.id) || data[0]) : data[0]);
    } catch { /* keep static */ }
  }

  ue(() => { loadItems(); }, []);

  async function removeAttach(attachId) {
    if (!confirm('ลบ attachment นี้?')) return;
    await window.DB.knowledge.deleteAttachment(attachId);
    loadItems();
  }

  async function removeItem(id) {
    if (!confirm('ลบรายการนี้ออกจากคลังความรู้?')) return;
    await window.DB.knowledge.remove(id);
    loadItems();
  }

  const cats     = ['all', ...Array.from(new Set(items.map(k => k.cat)))];
  const filtered = items.filter(k => {
    if (cat !== 'all' && k.cat !== cat) return false;
    const tags = Array.isArray(k.tags) ? k.tags.join(' ') : k.tags || '';
    if (search && !(k.title + (k.desc||'') + tags).toLowerCase().includes(search.toLowerCase())) return false;
    return true;
  });

  const TypeIcon = ({ t }) => {
    const bg = { PDF:'var(--c-accent-red, #ef4444)', Video:'var(--c-accent-blue, #3b82f6)', Manual:'var(--c-primary)', Protocol:'#f59e0b', Checklist:'#10b981', Template:'#8b5cf6', Worksheet:'#06b6d4', Policy:'#6b7280', Link:'#0ea5e9' };
    return (
      <div style={{ width:44, height:54, borderRadius:6, background: bg[t] || 'var(--c-primary)',
        color:'white', display:'grid', placeItems:'center', flexShrink:0,
        fontSize:9, fontWeight:700, fontFamily:'var(--font-mono)', letterSpacing:0.5 }}>{t}</div>
    );
  };

  return (
    <div className="page">
      {showAdd && <KnowledgeAddModal onClose={() => setShowAdd(false)} onSaved={() => { setShowAdd(false); loadItems(); }} />}

      <div className="section-h">
        <div>
          <h2>คลังความรู้ & คู่มือ</h2>
          <div className="sub">Protocol · Bundle · Workshop · Template สำหรับการนิเทศ</div>
        </div>
        <div className="flex">
          <input value={search} onChange={e => setSearch(e.target.value)}
            placeholder="ค้นหาคู่มือ / โปรโตคอล..."
            style={{ padding:8, border:'1px solid var(--c-border)', borderRadius:8,
              background:'var(--c-surface)', color:'var(--c-ink)', width:240, fontSize:13 }} />
          {isSupervisor && (
            <button className="btn btn-primary" onClick={() => setShowAdd(true)}>
              <Icon name="plus" size={14} />เพิ่มรายการ
            </button>
          )}
        </div>
      </div>

      <div className="chips" style={{ marginBottom:16 }}>
        {cats.map(c => (
          <button key={c} className={`chip ${cat===c?'active':''}`} onClick={() => setCat(c)}>
            {c === 'all' ? `ทั้งหมด (${items.length})` : `${c} (${items.filter(k => k.cat===c).length})`}
          </button>
        ))}
      </div>

      <div className="split">
        {/* ── รายการ ─── */}
        <div style={{ display:'grid', gridTemplateColumns:'repeat(auto-fill, minmax(260px, 1fr))', gap:12 }}>
          {filtered.map(k => {
            const isSel = selected?.id === k.id;
            const tags  = Array.isArray(k.tags) ? k.tags : JSON.parse(k.tags || '[]');
            return (
              <div key={k.id} onClick={() => setSelected(k)} className="card"
                style={{ cursor:'pointer', borderColor: isSel ? 'var(--c-primary)' : undefined,
                  boxShadow: isSel ? '0 0 0 3px var(--c-primary-soft)' : undefined }}>
                <div className="card-body">
                  <div className="flex" style={{ alignItems:'flex-start', gap:10 }}>
                    <TypeIcon t={k.type} />
                    <div style={{ flex:1, minWidth:0 }}>
                      <div className="txt-xs muted">{k.cat}</div>
                      <h4 style={{ margin:'2px 0', fontSize:13, lineHeight:1.3 }}>{k.title}</h4>
                      <div className="txt-xs muted" style={{ marginTop:2 }}>
                        {k.pages ? `${k.pages} หน้า` : k.duration || '—'} · {k.updated}
                        {k.attachments?.length > 0 && <span style={{ marginLeft:6, color:'var(--c-primary)' }}>📎 {k.attachments.length}</span>}
                      </div>
                    </div>
                  </div>
                  <div className="flex" style={{ marginTop:8, gap:4, flexWrap:'wrap' }}>
                    {tags.map(t => <span key={t} className="badge">{t}</span>)}
                  </div>
                </div>
              </div>
            );
          })}
          {filtered.length === 0 && <div className="card" style={{ padding:40, textAlign:'center', color:'var(--c-ink-muted)' }}>ไม่พบคู่มือที่ค้นหา</div>}
        </div>

        {/* ── รายละเอียด ─── */}
        {selected && (() => {
          const tags = Array.isArray(selected.tags) ? selected.tags : JSON.parse(selected.tags || '[]');
          return (
            <div className="card" style={{ position:'sticky', top:16, alignSelf:'flex-start' }}>
              <div className="card-body">
                {/* Header */}
                <div className="flex" style={{ marginBottom:12, gap:12, alignItems:'flex-start' }}>
                  <TypeIcon t={selected.type} />
                  <div style={{ flex:1, minWidth:0 }}>
                    <div className="muted txt-xs">{selected.cat}</div>
                    <h3 style={{ margin:'2px 0 4px', fontSize:15, lineHeight:1.3 }}>{selected.title}</h3>
                    <div className="txt-xs muted">{selected.sub}</div>
                  </div>
                  {isSupervisor && (
                    <button className="btn btn-sm btn-ghost" style={{ color:'var(--c-danger,#ef4444)', padding:'4px 8px', fontSize:11 }}
                      onClick={() => removeItem(selected.id)}>ลบ</button>
                  )}
                </div>

                <div className="grid-2 txt-sm" style={{ marginBottom:14 }}>
                  <div><div className="muted txt-xs">อัปเดตล่าสุด</div><strong>{selected.updated}</strong></div>
                  <div><div className="muted txt-xs">ความยาว</div><strong>{selected.pages ? `${selected.pages} หน้า` : selected.duration || '—'}</strong></div>
                </div>

                {/* Description */}
                <div style={{ marginBottom:14 }}>
                  <div className="muted txt-xs" style={{ marginBottom:4 }}>รายละเอียด</div>
                  <p className="txt-sm" style={{ lineHeight:1.7, color:'var(--c-ink-soft)', margin:0 }}>{selected.desc}</p>
                </div>

                {/* Tags */}
                <div style={{ marginBottom:14 }}>
                  <div className="muted txt-xs" style={{ marginBottom:4 }}>Tags</div>
                  <div className="flex" style={{ gap:6, flexWrap:'wrap' }}>
                    {tags.map(t => <span key={t} className="badge info">{t}</span>)}
                  </div>
                </div>

                {/* เปิดดู link หลัก */}
                {selected.url && (
                  <a href={selected.url} target="_blank" rel="noopener noreferrer"
                    className="btn btn-primary" style={{ display:'flex', alignItems:'center', gap:6, marginBottom:10, textDecoration:'none', justifyContent:'center' }}>
                    <Icon name="externalLink" size={14} />เปิดดูเอกสาร
                  </a>
                )}

                {/* Attachments */}
                <div style={{ borderTop:'1px solid var(--c-border)', paddingTop:12 }}>
                  <div className="flex" style={{ marginBottom:8 }}>
                    <span className="muted txt-xs" style={{ fontWeight:600 }}>ไฟล์ & ลิงก์แนบ</span>
                    <span className="muted txt-xs" style={{ marginLeft:'auto' }}>{selected.attachments?.length || 0} รายการ</span>
                  </div>

                  {/* รายการ attachments */}
                  {(selected.attachments || []).length === 0 && (
                    <div className="muted txt-xs" style={{ padding:'8px 0', textAlign:'center' }}>ยังไม่มีไฟล์หรือลิงก์แนบ</div>
                  )}
                  {(selected.attachments || []).map(a => (
                    <div key={a.id} className="flex" style={{ padding:'8px 0', borderBottom:'1px solid var(--c-border-soft, var(--c-border))', gap:8, alignItems:'center' }}>
                      <span style={{ fontSize:16 }}>{a.attachment_type === 'link' ? '🔗' : '📄'}</span>
                      <div style={{ flex:1, minWidth:0 }}>
                        {a.url
                          ? <a href={a.url} target="_blank" rel="noopener noreferrer"
                              style={{ color:'var(--c-primary)', textDecoration:'none', fontSize:13, fontWeight:500 }}>
                              {a.name}
                            </a>
                          : <span style={{ fontSize:13, fontWeight:500 }}>{a.name}</span>
                        }
                        {a.file_size && <div className="txt-xs muted">{a.file_size} · {a.file_ext}</div>}
                      </div>
                      {isSupervisor && (
                        <button onClick={() => removeAttach(a.id)}
                          style={{ background:'none', border:'none', cursor:'pointer', color:'var(--c-ink-muted)', fontSize:16, padding:'0 4px' }}>×</button>
                      )}
                    </div>
                  ))}

                  {/* ฟอร์มเพิ่ม attachment */}
                  {isSupervisor && (
                    <AttachForm itemId={selected.id} onAdded={loadItems} />
                  )}
                </div>
              </div>
            </div>
          );
        })()}
      </div>
    </div>
  );
};

// ============== หัวข้อนิเทศ (Supervision Topics Admin) ==============
const SupervisionTopicsAdmin = () => {
  const [topics, setTopics] = useState(getTopics);
  const [expanded, setExpanded] = useState(null);
  const [addingGroup, setAddingGroup] = useState(false);
  const [newGroupName, setNewGroupName] = useState('');
  const [newTopicText, setNewTopicText] = useState({});

  const update = (t) => { setTopics(t); saveTopics(t); };

  const addGroup = () => {
    if (!newGroupName.trim()) return;
    update([...topics, { group: newGroupName.trim(), topics: [] }]);
    setNewGroupName('');
    setAddingGroup(false);
  };

  const removeGroup = (gi) => {
    if (confirm('ลบกลุ่มนี้ทั้งหมด?')) update(topics.filter((_, i) => i !== gi));
  };

  const addTopic = (gi) => {
    const t = (newTopicText[gi] || '').trim();
    if (!t) return;
    update(topics.map((g, i) => i === gi ? { ...g, topics: [...g.topics, t] } : g));
    setNewTopicText(p => ({ ...p, [gi]: '' }));
  };

  const removeTopic = (gi, ti) => {
    update(topics.map((g, i) => i === gi ? { ...g, topics: g.topics.filter((_, j) => j !== ti) } : g));
  };

  const resetDefaults = () => {
    if (confirm('รีเซตหัวข้อทั้งหมดกลับเป็นค่าเริ่มต้น?')) {
      localStorage.removeItem(TOPICS_STORAGE_KEY);
      setTopics(SUPERVISION_TOPICS);
    }
  };

  return (
    <div className="page">
      <div className="section-h">
        <div>
          <h2>หัวข้อนิเทศ</h2>
          <div className="sub">จัดการหัวข้อและกลุ่มที่ใช้ในแบบฟอร์มบันทึกการนิเทศ · {topics.reduce((n, g) => n + g.topics.length, 0)} หัวข้อใน {topics.length} กลุ่ม</div>
        </div>
        <div className="flex">
          <button className="btn" onClick={resetDefaults}>รีเซต</button>
          <button className="btn btn-primary" onClick={() => setAddingGroup(true)}>
            <Icon name="plus" size={14} />เพิ่มกลุ่มใหม่
          </button>
        </div>
      </div>

      <div className="stack">
        {topics.map((g, gi) => (
          <div key={gi} className="card">
            <div
              className="card-header"
              style={{ cursor: 'pointer' }}
              onClick={() => setExpanded(expanded === gi ? null : gi)}
            >
              <h3>{g.group}</h3>
              <span className="badge" style={{ marginLeft: 8 }}>{g.topics.length} หัวข้อ</span>
              <div style={{ marginLeft: 'auto', display: 'flex', gap: 8, alignItems: 'center' }}>
                <button
                  className="btn btn-sm btn-ghost"
                  style={{ color: 'var(--c-danger)' }}
                  onClick={e => { e.stopPropagation(); removeGroup(gi); }}
                >ลบกลุ่ม</button>
                <span style={{ fontSize: 12, color: 'var(--c-ink-muted)', transform: expanded === gi ? 'rotate(90deg)' : undefined, display: 'inline-block', transition: 'transform 0.15s' }}>▶</span>
              </div>
            </div>

            {expanded === gi && (
              <div className="card-body">
                <div className="stack">
                  {g.topics.length === 0 && (
                    <div className="txt-sm muted">ยังไม่มีหัวข้อในกลุ่มนี้</div>
                  )}
                  {g.topics.map((t, ti) => (
                    <div key={ti} className="flex-between" style={{ padding: '8px 12px', background: 'var(--c-surface-2)', borderRadius: 8 }}>
                      <span className="txt-sm">{t}</span>
                      <button
                        className="btn btn-sm btn-ghost"
                        style={{ color: 'var(--c-danger)', flexShrink: 0 }}
                        onClick={() => removeTopic(gi, ti)}
                        title="ลบหัวข้อ"
                      >×</button>
                    </div>
                  ))}
                  <div className="flex" style={{ gap: 8, marginTop: 4 }}>
                    <input
                      value={newTopicText[gi] || ''}
                      onChange={e => setNewTopicText(p => ({ ...p, [gi]: e.target.value }))}
                      onKeyDown={e => e.key === 'Enter' && addTopic(gi)}
                      placeholder="พิมพ์หัวข้อใหม่ แล้วกด Enter หรือ เพิ่ม..."
                      style={{ flex: 1, padding: '8px 12px', border: '1px solid var(--c-border)', borderRadius: 8, background: 'var(--c-surface)', color: 'var(--c-ink)', fontSize: 13 }}
                    />
                    <button className="btn btn-primary btn-sm" onClick={() => addTopic(gi)}>
                      <Icon name="plus" size={14} />เพิ่ม
                    </button>
                  </div>
                </div>
              </div>
            )}
          </div>
        ))}
      </div>

      {addingGroup && (
        <div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.45)', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 50 }}>
          <div className="card" style={{ width: 420 }}>
            <div className="card-header"><h3>เพิ่มกลุ่มหัวข้อใหม่</h3></div>
            <div className="card-body stack">
              <input
                value={newGroupName}
                onChange={e => setNewGroupName(e.target.value)}
                onKeyDown={e => e.key === 'Enter' && addGroup()}
                placeholder="ชื่อกลุ่ม เช่น การดูแลทารกแรกเกิด"
                autoFocus
                style={{ padding: '10px 12px', border: '1px solid var(--c-border)', borderRadius: 8, background: 'var(--c-surface)', color: 'var(--c-ink)' }}
              />
              <div className="flex" style={{ gap: 8, justifyContent: 'flex-end' }}>
                <button className="btn" onClick={() => { setAddingGroup(false); setNewGroupName(''); }}>ยกเลิก</button>
                <button className="btn btn-primary" onClick={addGroup}>เพิ่มกลุ่ม</button>
              </div>
            </div>
          </div>
        </div>
      )}
    </div>
  );
};

Object.assign(window, { StaffManagement, KnowledgeBase, KNOWLEDGE, SupervisionTopicsAdmin });

// ============== บันทึกการนิเทศ (Formal Supervision Records) ==============
const SupervisionRecords = ({ role, user } = {}) => {
  const canEdit = role !== undefined
    ? (window.isSupervisorRole ? window.isSupervisorRole(role) : false)
    : true;
  const [filter, setFilter] = useState('all');
  const [viewRecord, setViewRecord] = useState(null);
  const [creating, setCreating] = useState(false);
  const [localRecords, setLocalRecords] = useState(() => [...D.SUPERVISION_RECORDS]);

  // Supervisee sees only their own records (+ group records)
  const baseRecords = canEdit
    ? localRecords
    : localRecords.filter(r => r.supervisee === user || r.supervisee === 'group');

  const records = baseRecords.filter(r => {
    if (filter === 'in-progress') return r.status === 'in-progress';
    if (filter === 'closed') return r.status === 'closed';
    if (filter === 'low') return r.score <= 3;
    return true;
  });

  const THAI_MONTHS = ['ม.ค.','ก.พ.','มี.ค.','เม.ย.','พ.ค.','มิ.ย.','ก.ค.','ส.ค.','ก.ย.','ต.ค.','พ.ย.','ธ.ค.'];
  function thaiDate(d) {
    const [y, m, day] = d.split('-');
    return `${parseInt(day)} ${THAI_MONTHS[parseInt(m)-1]} ${parseInt(y)+543}`;
  }

  const ACT_COLORS = {
    Observation: '#2b6cb0', Teaching: '#6b46c1', Counseling: '#b7791f',
    'Nursing Round': '#2c7a7b', Participation: '#276749',
  };
  function actStyle(act) {
    const c = ACT_COLORS[act] || '#718096';
    return { fontSize: 10, fontWeight: 700, color: c, background: c+'15', padding: '2px 7px', borderRadius: 8, border: `1px solid ${c}33`, whiteSpace: 'nowrap' };
  }
  function scoreStyle(s) {
    const c = s >= 4.5 ? '#276749' : s >= 3.5 ? '#2c7a7b' : s >= 2.5 ? '#b7791f' : '#c53030';
    return { fontSize: 12, fontWeight: 700, color: c, background: c+'15', padding: '2px 9px', borderRadius: 8, whiteSpace: 'nowrap' };
  }

  const handleDelete = (id) => {
    if (!confirm('ลบบันทึกนี้?')) return;
    setLocalRecords(prev => prev.filter(r => r.id !== id));
    if (viewRecord?.id === id) setViewRecord(null);
  };

  return (
    <div className="page">
      <div className="section-h">
        <div>
          <h2>บันทึกการนิเทศทางการพยาบาล</h2>
          <div className="sub">ประวัติการนิเทศทั้งหมด — รายบุคคล รายหัวข้อ</div>
        </div>
        {canEdit && (
          <button className="btn btn-primary" onClick={() => setCreating(true)}>
            <Icon name="plus" size={14} />+ บันทึกการนิเทศใหม่
          </button>
        )}
      </div>

      <div className="kpi-row" style={{ marginBottom: 16 }}>
        <div className="kpi">
          <div className="label">บันทึกทั้งหมด</div>
          <div className="value">{baseRecords.length}</div>
          <div className="delta muted">เดือน พ.ค. 2569</div>
        </div>
        <div className="kpi">
          <div className="label">ปิดเคส</div>
          <div className="value">{baseRecords.filter(r => r.status === 'closed').length}</div>
          <div className="delta muted">ผ่านการประเมิน</div>
        </div>
        <div className="kpi">
          <div className="label">กำลังติดตาม</div>
          <div className="value">{baseRecords.filter(r => r.status === 'in-progress').length}</div>
          <div className="delta muted">มี follow-up</div>
        </div>
        <div className="kpi">
          <div className="label">คะแนนเฉลี่ย</div>
          <div className="value">{avg(baseRecords.map(r => r.score)).toFixed(2)}<small>/5</small></div>
          <div className="delta muted">ทั้งเดือน</div>
        </div>
      </div>

      <div className="card">
        <div className="card-header">
          <h3>รายการทั้งหมด</h3>
          <div className="chips" style={{ marginLeft: 'auto' }}>
            <button className={`chip ${filter==='all'?'active':''}`} onClick={() => setFilter('all')}>ทั้งหมด</button>
            <button className={`chip ${filter==='in-progress'?'active':''}`} onClick={() => setFilter('in-progress')}>ติดตาม</button>
            <button className={`chip ${filter==='closed'?'active':''}`} onClick={() => setFilter('closed')}>ปิดเคส</button>
            <button className={`chip ${filter==='low'?'active':''}`} onClick={() => setFilter('low')}>คะแนน ≤ 3</button>
          </div>
        </div>
        <div className="card-body" style={{ padding: 0, overflowX: 'auto' }}>
          <table className="t">
            <thead>
              <tr>
                <th style={{ minWidth: 95 }}>วันที่</th>
                <th style={{ minWidth: 140 }}>ผู้รับนิเทศ</th>
                <th>หัวข้อ</th>
                <th style={{ minWidth: 130 }}>ผู้นิเทศ</th>
                <th style={{ minWidth: 70, textAlign: 'center' }}>คะแนน</th>
                <th style={{ minWidth: 120 }}>หมายเหตุ</th>
                <th style={{ minWidth: 75, textAlign: 'center' }}>ไฟล์แนบ</th>
                <th style={{ width: canEdit ? 110 : 70 }}></th>
              </tr>
            </thead>
            <tbody>
              {records.length === 0 ? (
                <tr><td colSpan={8} style={{ textAlign: 'center', padding: 36, color: 'var(--c-ink-muted)' }}>ไม่มีรายการที่ตรงกับตัวกรอง</td></tr>
              ) : records.map(r => {
                const sv   = r.supervisor !== 'group' ? D.staffById(r.supervisor) : null;
                const svee = r.supervisee !== 'group' ? D.staffById(r.supervisee) : null;
                const atts = Array.isArray(r.attachments) ? r.attachments : [];
                return (
                  <tr key={r.id}>
                    <td>
                      <div className="txt-sm mono">{thaiDate(r.date)}</div>
                    </td>
                    <td>
                      {svee
                        ? <div className="txt-sm">{svee.title}{svee.name}</div>
                        : <div className="txt-sm muted">ทีมพยาบาล</div>}
                    </td>
                    <td>
                      <div className="flex" style={{ alignItems: 'flex-start', gap: 6, flexWrap: 'wrap' }}>
                        <span style={actStyle(r.activity)}>{r.activity}</span>
                        <span className="txt-sm" style={{ fontWeight: 600 }}>{r.topic}</span>
                      </div>
                    </td>
                    <td>
                      {sv ? <div className="txt-sm">{sv.title}{sv.name}</div> : <span className="muted txt-xs">—</span>}
                    </td>
                    <td style={{ textAlign: 'center' }}>
                      <span style={scoreStyle(r.score)}>{Number(r.score).toFixed(1)}/5</span>
                    </td>
                    <td>
                      <div className="txt-xs" style={{ color: 'var(--c-ink-soft)', maxWidth: 160, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                        {r.followup && r.followup !== '—' ? r.followup : '—'}
                      </div>
                    </td>
                    <td style={{ textAlign: 'center' }}>
                      {atts.length > 0
                        ? <span style={{ fontSize: 11, color: 'var(--c-primary)', background: 'var(--c-primary-soft)', padding: '2px 8px', borderRadius: 8 }}>{atts.length} ไฟล์</span>
                        : <span className="muted txt-xs">—</span>}
                    </td>
                    <td>
                      <div className="flex" style={{ gap: 5 }}>
                        <button
                          className="btn-outline txt-xs"
                          style={{ padding: '4px 12px', color: 'var(--c-primary)', borderColor: 'var(--c-primary)' }}
                          onClick={() => setViewRecord(r)}
                        >ดู</button>
                        {canEdit && (
                          <button
                            className="btn-outline txt-xs"
                            style={{ padding: '4px 12px', color: 'var(--c-danger)', borderColor: 'var(--c-danger)' }}
                            onClick={() => handleDelete(r.id)}
                          >ลบ</button>
                        )}
                      </div>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      </div>

      {/* Record Detail Modal */}
      {viewRecord && (
        <div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,.45)', zIndex: 9990, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '20px 16px' }} onClick={() => setViewRecord(null)}>
          <div style={{ background: 'var(--c-bg)', borderRadius: 14, width: 700, maxWidth: '100%', maxHeight: '90vh', overflowY: 'auto', boxShadow: '0 20px 60px rgba(0,0,0,.3)' }} onClick={e => e.stopPropagation()}>
            <div style={{ display: 'flex', justifyContent: 'flex-end', padding: '12px 16px 0', position: 'sticky', top: 0, background: 'var(--c-bg)', zIndex: 1 }}>
              <button onClick={() => setViewRecord(null)} style={{ background: 'none', border: '1px solid var(--c-border)', borderRadius: '50%', width: 30, height: 30, cursor: 'pointer', fontSize: 16, display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--c-ink-muted)' }}>×</button>
            </div>
            <RecordDetail record={viewRecord} canEdit={canEdit} />
          </div>
        </div>
      )}

      {creating && (
        <div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,.45)', zIndex: 9990, display: 'flex', alignItems: 'flex-start', justifyContent: 'center', padding: '20px 16px', overflowY: 'auto' }} onClick={() => setCreating(false)}>
          <div style={{ width: 720, maxWidth: '100%', marginTop: 20, marginBottom: 20 }} onClick={e => e.stopPropagation()}>
            <RecordCreateForm onClose={() => setCreating(false)} />
          </div>
        </div>
      )}
    </div>
  );
};

const RecordDetail = ({ record, canEdit = true }) => {
  const sv   = record.supervisor !== 'group' ? D.staffById(record.supervisor) : null;
  const svee = record.supervisee !== 'group' ? D.staffById(record.supervisee) : null;
  const atts = Array.isArray(record.attachments) ? record.attachments : [];

  const StaffCard = ({ staff, label, isGroup }) => (
    <div style={{ padding: '10px 12px', border: '1px solid var(--c-border)', borderRadius: 10, background: 'var(--c-surface)' }}>
      <div className="txt-xs muted" style={{ marginBottom: 6, fontWeight: 600 }}>{label}</div>
      {isGroup ? (
        <div className="flex" style={{ gap: 8, alignItems: 'center' }}>
          <div style={{ width: 36, height: 36, borderRadius: '50%', background: 'var(--c-primary-soft)', display: 'grid', placeItems: 'center', fontSize: 16 }}>👥</div>
          <div>
            <div className="txt-sm" style={{ fontWeight: 600 }}>ทีมพยาบาล</div>
            <div className="txt-xs muted">Group supervision</div>
          </div>
        </div>
      ) : staff ? (
        <div className="flex" style={{ gap: 8, alignItems: 'center' }}>
          <Avatar name={staff.name} size={36} />
          <div style={{ minWidth: 0 }}>
            <div className="txt-sm" style={{ fontWeight: 700 }}>{staff.title}{staff.name}</div>
            <div className="txt-xs muted" style={{ marginTop: 1 }}>{D.POSITIONS[staff.pos] || staff.pos}</div>
            <div className="flex" style={{ gap: 4, marginTop: 3, flexWrap: 'wrap' }}>
              {staff.level && <LevelChip level={staff.level} />}
              <span className="txt-xs muted mono">{staff.id}</span>
            </div>
          </div>
        </div>
      ) : (
        <div className="txt-sm muted">—</div>
      )}
    </div>
  );

  return (
    <div className="card">
      <div className="card-body">
        <div className="flex" style={{ marginBottom: 12, gap: 6, flexWrap: 'wrap' }}>
          <span className="badge info">{record.activity}</span>
          <span className="badge">{record.shift}</span>
          <span className={`badge ${record.status === 'closed' ? 'ok' : 'warn'}`}>
            {record.status === 'closed' ? 'ปิดเคส' : 'กำลังติดตาม'}
          </span>
          <span className="mono txt-xs muted" style={{ marginLeft: 'auto' }}>{record.date}</span>
        </div>
        <h3 style={{ margin: '0 0 14px' }}>{record.topic}</h3>

        {/* ── ผู้นิเทศ / ผู้รับการนิเทศ ── */}
        <div className="grid-2" style={{ gap: 10, marginBottom: 14 }}>
          <StaffCard staff={sv}   label="ผู้นิเทศ (Supervisor)"  isGroup={false} />
          <StaffCard staff={svee} label="ผู้รับการนิเทศ (Supervisee)" isGroup={record.supervisee === 'group'} />
        </div>

        {record.content && (
          <div className="form-section">
            <h4>เนื้อหาที่นิเทศ</h4>
            <p className="txt-sm" style={{ color: 'var(--c-ink-soft)', lineHeight: 1.7, whiteSpace: 'pre-wrap' }}>{record.content}</p>
          </div>
        )}
        <div className="form-section">
          <h4>วิธีการนิเทศ</h4>
          <p className="txt-sm" style={{ color: 'var(--c-ink-soft)' }}>{record.method || record.activity}</p>
        </div>
        <div className="form-section">
          <h4>ผลการประเมิน</h4>
          <div className="flex" style={{ alignItems: 'center', gap: 12 }}>
            <LevelChip level={record.score} />
            <span className="mono" style={{ fontSize: 18, fontWeight: 700 }}>{Number(record.score).toFixed(1)}<span className="muted txt-sm" style={{ fontWeight: 400 }}>/5.0</span></span>
            {record.result && <span className="txt-sm muted">— {record.result}</span>}
          </div>
        </div>

        {(record.strengths || record.weaknesses) && (
          <div className="grid-2" style={{ gap: 10, marginBottom: 12 }}>
            <div style={{ padding: 10, borderRadius: 8, background: 'var(--c-ok-soft)' }}>
              <div className="flex" style={{ marginBottom: 4 }}>
                <Icon name="sparkles" size={14} />
                <strong className="txt-xs" style={{ color: 'var(--c-ok)' }}>จุดแข็ง</strong>
              </div>
              <div className="txt-sm" style={{ whiteSpace: 'pre-wrap' }}>{record.strengths || '—'}</div>
            </div>
            <div style={{ padding: 10, borderRadius: 8, background: 'var(--c-warn-soft)' }}>
              <div className="flex" style={{ marginBottom: 4 }}>
                <Icon name="target" size={14} />
                <strong className="txt-xs" style={{ color: 'var(--c-warn)' }}>จุดที่ต้องพัฒนา</strong>
              </div>
              <div className="txt-sm" style={{ whiteSpace: 'pre-wrap' }}>{record.weaknesses || '—'}</div>
            </div>
          </div>
        )}

        {record.followup && (
          <div className="form-section">
            <h4>การติดตามผล</h4>
            <p className="txt-sm" style={{ color: 'var(--c-ink-soft)', whiteSpace: 'pre-wrap' }}>{record.followup}</p>
          </div>
        )}
        <div className="form-section">
          <h4>ความถี่</h4>
          <span className="badge">{record.frequency || '—'}</span>
        </div>

        {/* ── ไฟล์แนบ (แสดงเสมอ) ── */}
        <div className="form-section">
          <div className="flex" style={{ justifyContent: 'space-between', alignItems: 'center', marginBottom: 8 }}>
            <h4 style={{ margin: 0 }}>
              ไฟล์ & ลิงก์แนบ
              {atts.length > 0 && <span className="muted txt-xs" style={{ fontWeight: 400, marginLeft: 6 }}>({atts.length} รายการ)</span>}
            </h4>
          </div>
          {atts.length > 0 ? (
            <div className="stack" style={{ gap: 6 }}>
              {atts.map((a, i) => <AttachmentRow key={i} att={a} />)}
            </div>
          ) : (
            <div className="txt-xs muted" style={{ padding: '12px 0', textAlign: 'center', color: 'var(--c-ink-muted)' }}>
              ยังไม่มีไฟล์หรือลิงก์แนบ
            </div>
          )}
        </div>

        <div className="flex" style={{ gap: 8, marginTop: 16 }}>
          {canEdit && <button className="btn" style={{ flex: 1 }}><Icon name="edit" size={14} />แก้ไข</button>}
          <button className="btn" style={{ flex: canEdit ? undefined : 1 }}><Icon name="download" size={14} />PDF</button>
          {canEdit && <button className="btn btn-primary"><Icon name="signature" size={14} />ลงนาม</button>}
        </div>
      </div>
    </div>
  );
};

const AttachmentRow = ({ att, onRemove }) => {
  const isLink = att.type === 'link';
  const openUrl = att.url || att.blobUrl || null;

  const handleOpen = () => {
    if (isLink && openUrl) {
      const href = openUrl.startsWith('http') ? openUrl : 'https://' + openUrl;
      window.open(href, '_blank', 'noopener');
    } else if (!isLink && att.blobUrl) {
      const a = document.createElement('a');
      a.href = att.blobUrl;
      a.download = att.name;
      a.click();
    }
  };

  const canOpen = isLink ? !!openUrl : !!att.blobUrl;
  const typeColors = {
    PDF: ['#fee2e2', '#dc2626'],
    PNG: ['#ede9fe', '#7c3aed'], JPG: ['#ede9fe', '#7c3aed'], JPEG: ['#ede9fe', '#7c3aed'],
    LINK: ['#dbeafe', '#2563eb'],
    DOCX: ['#dbeafe', '#1d4ed8'], DOC: ['#dbeafe', '#1d4ed8'],
    XLSX: ['#dcfce7', '#16a34a'], XLS: ['#dcfce7', '#16a34a'],
  };
  const typeKey = isLink ? 'LINK' : (att.ext || 'FILE');
  const [bg, fg] = typeColors[typeKey] || ['var(--c-primary-soft)', 'var(--c-primary)'];

  return (
    <div
      className="flex"
      style={{ padding: '8px 10px', border: '1px solid var(--c-border)', borderRadius: 8, gap: 10, background: 'var(--c-surface)', alignItems: 'center' }}
    >
      <div style={{ width: 36, height: 36, borderRadius: 6, background: bg, color: fg, display: 'grid', placeItems: 'center', fontSize: 9, fontWeight: 700, fontFamily: 'var(--font-mono)', flexShrink: 0, letterSpacing: 0.3 }}>
        {typeKey}
      </div>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div className="txt-sm" style={{ fontWeight: 500, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
          {att.name}
        </div>
        <div className="txt-xs muted" style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
          {isLink ? (openUrl || 'ลิงก์') : (att.size || '')}
        </div>
      </div>
      <button
        className="btn btn-sm"
        title={isLink ? 'เปิดลิงก์' : 'ดาวน์โหลด'}
        onClick={handleOpen}
        disabled={!canOpen}
        style={{ opacity: canOpen ? 1 : 0.4, flexShrink: 0 }}
      >
        <Icon name={isLink ? 'chevronRight' : 'download'} size={14} />
        {isLink ? 'เปิด' : 'ดาวน์โหลด'}
      </button>
      {onRemove && (
        <button className="btn btn-sm btn-ghost" style={{ color: 'var(--c-danger)', flexShrink: 0 }} onClick={onRemove} title="ลบ">×</button>
      )}
    </div>
  );
};

const SUPERVISION_TOPICS = [
  { group: 'การบริหาร & กฎระเบียบ', topics: ['กฎ ระเบียบ การปฏิบัติงาน', 'อัตรากำลังและการมอบหมายงาน', 'การจัดการสิ่งแวดล้อมและความปลอดภัย', 'PDPA & การรักษาความลับผู้ป่วย'] },
  { group: 'กระบวนการพยาบาล & เอกสาร', topics: ['การประเมินผู้ป่วยแรกรับ (Risk Assessment)', 'การใช้กระบวนการพยาบาล (Nursing Process)', 'การบันทึกทางการพยาบาล', 'การส่งเวร ISBAR', 'C3THER Bedside Round'] },
  { group: 'ทักษะการทำคลอดปกติ', topics: ['การพยาบาลระยะรอคลอด (First Stage Care)', 'การทำคลอดปกติ (Normal Delivery)', 'คลอดรก ตัด-เย็บแผลฝีเย็บ', 'PPH Bundle — Active Management ระยะที่ 3', 'การพยาบาลมารดา-ทารก 2 ชม.แรกหลังคลอด', 'การส่งเสริมการเลี้ยงลูกด้วยนมแม่'] },
  { group: 'การจัดการภาวะฉุกเฉิน', topics: ['EFM Cat-II — Intrauterine Resuscitation (LIONS)', 'PPH > 1000 ml — Massive Transfusion Protocol', 'Shoulder Dystocia (HELPERR Mnemonic)', 'Eclampsia / Severe Pre-eclampsia — MgSO4 Protocol', 'Breech Delivery', 'Cord Prolapse — Emergency Management', 'NCPR — Neonatal Resuscitation'] },
  { group: 'การดูแลมารดาความเสี่ยงสูง', topics: ['PIH / Pre-eclampsia', 'GDM — มารดาเบาหวานร่วมกับการตั้งครรภ์', 'Fetal Distress', 'Preterm Labor'] },
  { group: 'หัตถการสูติศาสตร์', topics: ['เตรียมผ่าตัดคลอด (C/S Preparation)', 'Vacuum Extraction Assist'] },
  { group: 'การบริหารยา', topics: ['การบริหารยา High Alert — Oxytocin Titration', 'การบริหารยา High Alert — MgSO4', 'การบริหารยา High Alert — Carbetocin'] },
  { group: 'คุณภาพและความปลอดภัย', topics: ['Patient Safety Goal (2P Safety)', 'Near-miss / Incident Report', 'RCA / M&M Review', 'Drug Reconciliation'] },
];

const TOPICS_STORAGE_KEY = 'lr_supervision_topics';

function getTopics() {
  try {
    const s = localStorage.getItem(TOPICS_STORAGE_KEY);
    if (s) return JSON.parse(s);
  } catch {}
  return SUPERVISION_TOPICS;
}

function saveTopics(t) {
  localStorage.setItem(TOPICS_STORAGE_KEY, JSON.stringify(t));
}

const RecordCreateForm = ({ onClose }) => {
  const [topicMode, setTopicMode] = useState('select'); // 'select' | 'custom'
  const [availableTopics] = useState(getTopics);
  const [form, setForm] = useState({
    topic: '', content: '', method: '', result: '',
    frequency: 'รายเคส', score: null, supervisor: 'n01', supervisee: 'n11',
    activity: 'Nursing Round', shift: 'เช้า', strengths: '', weaknesses: '', followup: '',
    attachments: [],
  });
  const [linkDraft, setLinkDraft] = useState({ name: '', url: '' });
  const [showLinkAdd, setShowLinkAdd] = useState(false);
  const [saving, setSaving] = useState(false);
  const [saveErr, setSaveErr] = useState('');
  const fileInputRef = useRef(null);
  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));

  const handleSave = async () => {
    if (!form.topic.trim()) { setSaveErr('กรุณาเลือกหรือพิมพ์ประเด็นการนิเทศ'); return; }
    if (form.score == null) { setSaveErr('กรุณาใส่คะแนนผลการประเมิน'); return; }
    setSaving(true);
    setSaveErr('');
    try {
      const today = new Date().toISOString().slice(0, 10);
      const rec = {
        id: 'rec-' + Date.now() + '-' + Math.random().toString(36).slice(2, 6),
        date: today, shift: form.shift,
        topic: form.topic, content: form.content,
        method: form.activity, result: form.result,
        frequency: form.frequency, score: form.score,
        followup: form.followup,
        supervisor: form.supervisor, supervisee: form.supervisee,
        activity: form.activity,
        strengths: form.strengths, weaknesses: form.weaknesses,
        status: 'in-progress',
        attachments: form.attachments,
      };
      await window.DB.records.create(rec);
      onClose();
    } catch (err) {
      setSaveErr(err.message || 'บันทึกไม่สำเร็จ กรุณาลองใหม่');
      setSaving(false);
    }
  };

  const handleFiles = (fileList) => {
    const list = Array.from(fileList || []);
    const items = list.map(f => ({
      type: 'file',
      name: f.name,
      size: f.size < 1024 ? `${f.size} B` : f.size < 1024 * 1024 ? `${(f.size / 1024).toFixed(0)} KB` : `${(f.size / 1024 / 1024).toFixed(1)} MB`,
      ext: (f.name.split('.').pop() || 'FILE').toUpperCase(),
      blobUrl: URL.createObjectURL(f), // for in-session download
    }));
    setForm(f => ({ ...f, attachments: [...f.attachments, ...items] }));
  };
  const addLink = () => {
    if (!linkDraft.url.trim()) return;
    setForm(f => ({
      ...f,
      attachments: [...f.attachments, { type: 'link', name: linkDraft.name || linkDraft.url, url: linkDraft.url }],
    }));
    setLinkDraft({ name: '', url: '' });
    setShowLinkAdd(false);
  };
  const removeAtt = (i) => setForm(f => ({ ...f, attachments: f.attachments.filter((_, k) => k !== i) }));
  return (
    <div className="card" style={{ borderColor: 'var(--c-primary)' }}>
      <div className="card-header">
        <h3>บันทึกการนิเทศใหม่</h3>
        <button className="btn btn-sm btn-ghost" style={{ marginLeft: 'auto' }} onClick={onClose}>ยกเลิก</button>
      </div>
      <div className="card-body stack">
        <div className="grid-2">
          <div>
            <label className="muted txt-xs">ผู้นิเทศ (Supervisor)</label>
            <select value={form.supervisor} onChange={e => set('supervisor', e.target.value)}
              style={{ width: '100%', padding: 8, marginTop: 4, border: '1px solid var(--c-border)', borderRadius: 8, background: 'var(--c-surface)' }}>
              {D.STAFF.filter(s => window.isSupervisorRole ? window.isSupervisorRole(s.role) : true).map(s => (
                <option key={s.id} value={s.id}>{s.title}{s.name} — {D.POSITIONS[s.pos]}</option>
              ))}
            </select>
          </div>
          <div>
            <label className="muted txt-xs">ผู้รับการนิเทศ (Supervisee)</label>
            <select value={form.supervisee} onChange={e => set('supervisee', e.target.value)}
              style={{ width: '100%', padding: 8, marginTop: 4, border: '1px solid var(--c-border)', borderRadius: 8, background: 'var(--c-surface)' }}>
              <option value="group">ทีมพยาบาล (Group supervision)</option>
              {D.STAFF.map(s => (
                <option key={s.id} value={s.id}>{s.title}{s.name} — {D.POSITIONS[s.pos]} · {D.levelById(s.level).label}</option>
              ))}
            </select>
          </div>
        </div>

        <div>
          <label className="muted txt-xs">ประเด็นการนิเทศ</label>
          <select
            value={topicMode === 'custom' ? '__custom__' : (form.topic || '')}
            onChange={e => {
              if (e.target.value === '__custom__') {
                setTopicMode('custom');
                set('topic', '');
              } else {
                setTopicMode('select');
                set('topic', e.target.value);
              }
            }}
            style={{ width: '100%', padding: 8, marginTop: 4, border: '1px solid var(--c-border)', borderRadius: 8, background: 'var(--c-surface)' }}
          >
            <option value="">— เลือกหัวข้อการนิเทศ —</option>
            {availableTopics.map(g => (
              <optgroup key={g.group} label={g.group}>
                {g.topics.map(t => <option key={t} value={t}>{t}</option>)}
              </optgroup>
            ))}
            <option value="__custom__">✏️ พิมพ์เอง...</option>
          </select>
          {topicMode === 'custom' && (
            <input value={form.topic} onChange={e => set('topic', e.target.value)}
              placeholder="ระบุหัวข้อการนิเทศ..."
              style={{ width: '100%', padding: 8, marginTop: 6, border: '1px solid var(--c-primary)', borderRadius: 8, background: 'var(--c-surface)' }} />
          )}
        </div>
        <div>
          <label className="muted txt-xs">เนื้อหาที่นิเทศ</label>
          <textarea value={form.content} onChange={e => set('content', e.target.value)} rows={3}
            placeholder="รายละเอียดเคส · กระบวนการ · ขั้นตอน..."
            style={{ width: '100%', padding: 8, marginTop: 4, border: '1px solid var(--c-border)', borderRadius: 8, background: 'var(--c-surface)', resize: 'vertical' }} />
        </div>
        <div>
          <label className="muted txt-xs">วิธีการนิเทศ (7 ประการ)</label>
          <div className="chips" style={{ marginTop: 6 }}>
            {['Nursing Round','Nursing Conference','Teaching','Counseling','Problem-solving','Observation','Participation'].map(a => (
              <button key={a} className={`chip ${form.activity === a ? 'active' : ''}`} onClick={() => set('activity', a)}>{a}</button>
            ))}
          </div>
        </div>
        <div className="grid-2">
          <div>
            <label className="muted txt-xs">เวร</label>
            <div className="role-switcher" style={{ width: '100%', marginTop: 4 }}>
              {['เช้า','บ่าย','ดึก'].map(s => (
                <button key={s} className={form.shift === s ? 'active' : ''} style={{ flex: 1 }} onClick={() => set('shift', s)}>{s}</button>
              ))}
            </div>
          </div>
          <div>
            <label className="muted txt-xs">ความถี่</label>
            <select value={form.frequency} onChange={e => set('frequency', e.target.value)}
              style={{ width: '100%', padding: 8, marginTop: 4, border: '1px solid var(--c-border)', borderRadius: 8, background: 'var(--c-surface)' }}>
              <option>ทุกวัน</option>
              <option>ทุกเวร</option>
              <option>รายเคส</option>
              <option>รายสัปดาห์</option>
              <option>รายเดือน</option>
            </select>
          </div>
        </div>
        <div>
          <label className="muted txt-xs">ผลการประเมิน (0.0 – 5.0)</label>
          <div className="flex" style={{ alignItems: 'center', gap: 12, marginTop: 6 }}>
            <input
              type="range"
              min="0" max="5" step="0.1"
              value={form.score ?? 0}
              onChange={e => set('score', parseFloat(e.target.value))}
              style={{
                flex: 1, accentColor: 'var(--c-primary)',
                height: 24,
              }}
            />
            <input
              type="number"
              min="0" max="5" step="0.1"
              value={form.score ?? ''}
              placeholder="0.0"
              onChange={e => {
                const v = e.target.value === '' ? null : Math.max(0, Math.min(5, parseFloat(e.target.value) || 0));
                set('score', v);
              }}
              style={{
                width: 80, padding: '8px 10px',
                border: '1px solid var(--c-border)', borderRadius: 8,
                background: 'var(--c-surface)', color: 'var(--c-ink)',
                fontFamily: 'var(--font-mono)', fontWeight: 700, fontSize: 16, textAlign: 'center',
              }}
            />
            <span className="muted mono">/ 5.0</span>
            {form.score != null && <LevelChip level={Math.round(Math.max(1, form.score))} />}
          </div>
          <div className="flex" style={{ gap: 4, marginTop: 8, fontSize: 11, color: 'var(--c-ink-muted)' }}>
            {D.LEVELS.map((lv, i) => (
              <div key={lv.id} style={{ flex: 1, textAlign: i === 0 ? 'left' : i === 4 ? 'right' : 'center' }}>
                <strong className="mono">{lv.n}</strong> {lv.label}
              </div>
            ))}
          </div>
        </div>
        <div>
          <label className="muted txt-xs">ผลโดยรวม</label>
          <input value={form.result} onChange={e => set('result', e.target.value)} placeholder="เช่น ผ่าน — ทำตาม protocol ครบ"
            style={{ width: '100%', padding: 8, marginTop: 4, border: '1px solid var(--c-border)', borderRadius: 8, background: 'var(--c-surface)' }} />
        </div>
        <div className="grid-2">
          <div>
            <label className="muted txt-xs">จุดแข็ง</label>
            <textarea value={form.strengths} onChange={e => set('strengths', e.target.value)} rows={3}
              style={{ width: '100%', padding: 8, marginTop: 4, border: '1px solid var(--c-border)', borderRadius: 8, background: 'var(--c-ok-soft)', resize: 'vertical' }} />
          </div>
          <div>
            <label className="muted txt-xs">จุดที่ต้องพัฒนา</label>
            <textarea value={form.weaknesses} onChange={e => set('weaknesses', e.target.value)} rows={3}
              style={{ width: '100%', padding: 8, marginTop: 4, border: '1px solid var(--c-border)', borderRadius: 8, background: 'var(--c-warn-soft)', resize: 'vertical' }} />
          </div>
        </div>
        <div>
          <label className="muted txt-xs">การติดตามผล / Follow-up</label>
          <textarea value={form.followup} onChange={e => set('followup', e.target.value)} rows={2} placeholder="แผนติดตาม / กิจกรรมที่ต้องทำต่อ..."
            style={{ width: '100%', padding: 8, marginTop: 4, border: '1px solid var(--c-border)', borderRadius: 8, background: 'var(--c-surface)', resize: 'vertical' }} />
        </div>

        <div>
          <label className="muted txt-xs">เอกสาร · ลิงก์แนบ</label>
          {form.attachments.length > 0 && (
            <div className="stack" style={{ gap: 6, marginTop: 6, marginBottom: 8 }}>
              {form.attachments.map((a, i) => (
                <AttachmentRow key={i} att={a} onRemove={() => removeAtt(i)} />
              ))}
            </div>
          )}
          <input
            ref={fileInputRef}
            type="file"
            multiple
            style={{ display: 'none' }}
            onChange={e => { handleFiles(e.target.files); e.target.value = ''; }}
          />
          <div className="flex" style={{ gap: 8, marginTop: 6, flexWrap: 'wrap' }}>
            <button className="btn btn-sm" onClick={() => fileInputRef.current?.click()}>
              <Icon name="plus" size={12} />แนบไฟล์
            </button>
            <button className="btn btn-sm" onClick={() => setShowLinkAdd(v => !v)}>
              <Icon name="plus" size={12} />แนบลิงก์
            </button>
            <span className="txt-xs muted">รองรับ: PDF, รูปภาพ, EFM strip, checklist (≤ 10 MB)</span>
          </div>
          {showLinkAdd && (
            <div style={{ marginTop: 8, padding: 10, border: '1px solid var(--c-border)', borderRadius: 8, background: 'var(--c-surface-2)' }}>
              <div className="grid-2" style={{ gap: 6 }}>
                <input
                  placeholder="ชื่อลิงก์ (เช่น Protocol PPH)"
                  value={linkDraft.name}
                  onChange={e => setLinkDraft(d => ({ ...d, name: e.target.value }))}
                  style={{ padding: 8, border: '1px solid var(--c-border)', borderRadius: 6, background: 'var(--c-surface)', fontSize: 13 }}
                />
                <input
                  placeholder="https://..."
                  value={linkDraft.url}
                  onChange={e => setLinkDraft(d => ({ ...d, url: e.target.value }))}
                  style={{ padding: 8, border: '1px solid var(--c-border)', borderRadius: 6, background: 'var(--c-surface)', fontSize: 13 }}
                />
              </div>
              <div className="flex" style={{ marginTop: 6, justifyContent: 'flex-end', gap: 6 }}>
                <button className="btn btn-sm btn-ghost" onClick={() => { setShowLinkAdd(false); setLinkDraft({ name: '', url: '' }); }}>ยกเลิก</button>
                <button className="btn btn-sm btn-primary" onClick={addLink} disabled={!linkDraft.url.trim()}>เพิ่มลิงก์</button>
              </div>
            </div>
          )}
        </div>

        {saveErr && (
          <div style={{ background: '#fee2e2', color: '#991b1b', borderRadius: 8, padding: '10px 12px', fontSize: 13 }}>
            {saveErr}
          </div>
        )}
        <button
          className="btn btn-primary btn-lg"
          style={{ width: '100%' }}
          onClick={handleSave}
          disabled={saving}
        >
          <Icon name="check" size={14} />{saving ? 'กำลังบันทึก…' : 'บันทึกและขอลายเซ็น'}
        </button>
      </div>
    </div>
  );
};

Object.assign(window, { SupervisionRecords, SUPERVISION_TOPICS });
