// ── FormApp.jsx ────────────────────────────────────────────────
// Main form orchestration: steps, save/load, submission

const STEPS = [
  { id: 1, title: '신청자 정보', icon: '👤' },
  { id: 2, title: '항해 일정', icon: '🗓️' },
  { id: 3, title: '선박 정보', icon: '⛵' },
  { id: 4, title: '선주/선장', icon: '🧭' },
  { id: 5, title: '승선자', icon: '👥' },
  { id: 6, title: '첨부파일', icon: '📎' },
  { id: 7, title: '요약·제출', icon: '✅' },
];

function nowIso() {
  return new Date().toISOString();
}

function normalizeDraftRecord(id, raw = {}) {
  const data = raw.data || {};
  return {
    id,
    docName: raw.docName || '',
    pin: String(raw.pin || ''),
    data,
    files: raw.files || {},
    revisions: Array.isArray(raw.revisions) ? raw.revisions : [],
    createdAt: raw.createdAt || raw.updatedAt || nowIso(),
    updatedAt: raw.updatedAt || raw.createdAt || nowIso(),
  };
}

function readDraftRecord(id) {
  const raw = localStorage.getItem(`ciq_draft_${id}`);
  if (!raw) return null;
  return normalizeDraftRecord(id, JSON.parse(raw));
}

function saveDraftRecord(record) {
  localStorage.setItem(`ciq_draft_${record.id}`, JSON.stringify(record));
}

function getDraftRecords() {
  const records = [];
  for (let i = 0; i < localStorage.length; i++) {
    const key = localStorage.key(i);
    if (!key || !key.startsWith('ciq_draft_')) continue;
    try {
      const id = key.replace('ciq_draft_', '');
      records.push(normalizeDraftRecord(id, JSON.parse(localStorage.getItem(key))));
    } catch {}
  }
  return records.sort((a, b) => new Date(b.updatedAt) - new Date(a.updatedAt));
}

function findDraftRecord(query) {
  const trimmed = query.trim();
  if (!trimmed) return null;
  const idQuery = trimmed.toUpperCase();
  const nameQuery = trimmed.toLocaleLowerCase('ko-KR');
  return getDraftRecords().find(record =>
    record.id.toUpperCase() === idQuery ||
    (record.docName || '').toLocaleLowerCase('ko-KR') === nameQuery
  );
}

function makeDraftRevision(record) {
  const archivedAt = nowIso();
  return {
    id: record.id,
    docName: record.docName || '',
    data: record.data || {},
    files: record.files || {},
    updatedAt: record.updatedAt || record.createdAt || archivedAt,
    archivedAt,
  };
}

function defaultCrewMember() {
  return { legs: { koreaToJapan: true, japanToKorea: true } };
}

function normalizeCrewLegs(legs = {}) {
  return {
    koreaToJapan: typeof legs.koreaToJapan === 'boolean' ? legs.koreaToJapan : true,
    japanToKorea: typeof legs.japanToKorea === 'boolean' ? legs.japanToKorea : true,
  };
}

function normalizeFormData(data = {}) {
  const next = {
    applicant: {},
    voyage: {},
    vessel: {},
    captain: { crew: [] },
    crew: { crew: [defaultCrewMember()] },
    consent: {},
    ...data,
  };
  const crewList = next.crew?.crew && next.crew.crew.length ? next.crew.crew : [defaultCrewMember()];
  next.crew = {
    ...(next.crew || {}),
    crew: crewList.map(member => ({
      ...member,
      legs: normalizeCrewLegs(member.legs),
    })),
  };
  return next;
}

function countCrewByLeg(crewData, legKey) {
  return (crewData?.crew || [])
    .filter(member => normalizeCrewLegs(member.legs)[legKey])
    .length;
}

function fileMeta(fileRecord) {
  if (!fileRecord) return null;
  return {
    name: fileRecord.name || '',
    size: fileRecord.size || 0,
    type: fileRecord.type || '',
  };
}

function sanitizeFiles(files = {}) {
  return Object.fromEntries(
    Object.entries(files)
      .filter(([, item]) => item)
      .map(([key, item]) => [key, fileMeta(item)])
  );
}

function trimValue(value) {
  return String(value || '').trim();
}

function requiredError(errors, value, label) {
  if (!trimValue(value)) errors.push(`${label}을 입력해 주세요.`);
}

function validateBeforeSubmit(data, files) {
  const errors = [];
  requiredError(errors, data.applicant?.name, '신청자 성명');
  requiredError(errors, data.applicant?.phone, '신청자 연락처');
  requiredError(errors, data.applicant?.email, '신청자 이메일');
  requiredError(errors, data.voyage?.departPort, '한국 출항 항구');
  requiredError(errors, data.voyage?.departDate, '한국 출항일');
  requiredError(errors, data.voyage?.departTime, '한국 출항 시각');
  requiredError(errors, data.voyage?.departCiqPlace, '한국 출항 CIQ 장소');
  requiredError(errors, data.voyage?.departBerth, '한국 출항 선석/계선장소');
  requiredError(errors, data.voyage?.arrivePort, '일본 입항 항구');
  requiredError(errors, data.voyage?.arriveDate, '일본 입항일');
  requiredError(errors, data.voyage?.arriveTime, '일본 입항 시각');
  requiredError(errors, data.voyage?.returnDepartPort, '일본 출항 항구');
  requiredError(errors, data.voyage?.returnDepartDate, '일본 출항일');
  requiredError(errors, data.voyage?.returnDepartTime, '일본 출항 시각');
  requiredError(errors, data.voyage?.returnArrivePort, '한국 입항 항구');
  requiredError(errors, data.voyage?.returnArriveDate, '한국 입항일');
  requiredError(errors, data.voyage?.returnArriveTime, '한국 입항 시각');
  requiredError(errors, data.voyage?.returnCiqPlace, '한국 입항 CIQ 장소');
  requiredError(errors, data.voyage?.returnBerth, '한국 입항 선석/계선장소');
  requiredError(errors, data.vessel?.vesselNameEn, '선박 영문명');
  requiredError(errors, data.vessel?.regNum, '선박 등록번호');
  requiredError(errors, data.captain?.captainNameKo, '선장 한글명');
  requiredError(errors, data.captain?.captainNameEn, '선장 영문명');
  requiredError(errors, data.captain?.captainDob, '선장 생년월일');
  requiredError(errors, data.captain?.captainPassport, '선장 여권번호');
  requiredError(errors, data.captain?.captainSex, '선장 성별');

  const crew = data.crew?.crew || [];
  if (!crew.length) {
    errors.push('승선자 정보를 1명 이상 입력해 주세요.');
  }
  let koreaToJapan = 0;
  let japanToKorea = 0;
  crew.forEach((member, index) => {
    const label = `${index + 1}번 승선자`;
    requiredError(errors, member.nameKo, `${label} 한글명`);
    requiredError(errors, member.nameEn, `${label} 영문명`);
    requiredError(errors, member.dob, `${label} 생년월일`);
    requiredError(errors, member.passport, `${label} 여권번호`);
    requiredError(errors, member.sex, `${label} 성별`);
    const legs = normalizeCrewLegs(member.legs);
    if (legs.koreaToJapan) koreaToJapan += 1;
    if (legs.japanToKorea) japanToKorea += 1;
  });
  if (koreaToJapan === 0) errors.push('한국에서 일본으로 탑승하는 승선자가 1명 이상 필요합니다.');
  if (japanToKorea === 0) errors.push('일본에서 한국으로 탑승하는 승선자가 1명 이상 필요합니다.');

  if (!data.consent?.privacy || !data.consent?.sensitive || !data.consent?.ciq) {
    errors.push('필수 동의 항목을 모두 체크해 주세요.');
  }
  ['passport_all', 'captain_passport', 'vessel_reg', 'safety_cert'].forEach(key => {
    const label = {
      passport_all: '전 승선자 여권 사본',
      captain_passport: '선장 여권 사본',
      vessel_reg: '선박 등록증 사본',
      safety_cert: '안전검사증 사본',
    }[key];
    if (!(files[key]?.file instanceof File)) errors.push(`${label}을 새로 첨부해 주세요.`);
  });
  return [...new Set(errors)];
}

// ── Save/Load Modal ────────────────────────────────────────────
function SaveModal({ onClose, onSave, onLoad, savedId, savedPin, savedDocName, initialMode = 'save' }) {
  const [mode, setMode] = React.useState(initialMode); // 'save' | 'load'
  const [saveError, setSaveError] = React.useState('');
  const [loadQuery, setLoadQuery] = React.useState('');
  const [loadPin, setLoadPin] = React.useState('');
  const [loadError, setLoadError] = React.useState('');

  React.useEffect(() => {
    setMode(initialMode);
  }, [initialMode]);

  function handleSaveClick() {
    const error = onSave();
    if (error) {
      setSaveError(error);
      return;
    }
    setSaveError('');
    onClose();
  }

  function handleLoad() {
    const record = findDraftRecord(loadQuery);
    if (!record || record.pin !== loadPin.trim()) {
      setLoadError('저장 ID/서류 이름 또는 PIN을 확인해 주세요.');
      return;
    }
    try {
      onLoad(record.data, record.files, record.id, record.pin, record.docName);
      onClose();
    } catch {
      setLoadError('데이터를 불러오는 데 실패했습니다.');
    }
  }

  return (
    <div style={{
      position: 'fixed', inset: 0, background: 'rgba(15, 23, 42, 0.6)', backdropFilter: 'blur(4px)', zIndex: 200,
      display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '1rem'
    }} onClick={onClose} className="animate-fade-in">
      <div className="card" style={{ width: '100%', maxWidth: '440px', position: 'relative' }} onClick={e => e.stopPropagation()}>
        <h2 style={{ fontSize: '1.25rem', fontWeight: '800', color: 'var(--text-primary)', marginBottom: '1.5rem' }}>
          작성 중 저장 / 불러오기
        </h2>

        <div style={{ display: 'flex', gap: '0.5rem', marginBottom: '1.5rem', background: 'var(--bg-color)', padding: '0.25rem', borderRadius: 'var(--radius-lg)' }}>
          {['save','load'].map(m => (
            <button key={m} onClick={() => setMode(m)} style={{
              flex: 1, padding: '0.75rem', borderRadius: 'var(--radius-md)', fontFamily: 'inherit',
              border: 'none', fontWeight: '600', fontSize: '0.875rem', cursor: 'pointer',
              background: mode === m ? 'white' : 'transparent',
              color: mode === m ? 'var(--text-primary)' : 'var(--text-secondary)',
              boxShadow: mode === m ? 'var(--shadow-sm)' : 'none',
              transition: 'all 0.2s'
            }}>
              {m === 'save' ? '💾 저장하기' : '📂 불러오기'}
            </button>
          ))}
        </div>

        {mode === 'save' ? (
          <div className="animate-fade-in">
            {savedId ? (
              <>
                <p style={{ fontSize: '0.9375rem', color: 'var(--text-secondary)', lineHeight: '1.6', marginBottom: '1rem' }}>
                  현재 열린 서류에 덮어쓰기 저장합니다. 이전 저장본은 수정 이력으로 남습니다.
                </p>
              <div style={{ background: '#f0fdf4', border: '1px solid #bbf7d0', borderRadius: 'var(--radius-lg)', padding: '1.25rem', marginBottom: '1rem' }}>
                <div style={{ display: 'grid', gap: '0.5rem', fontSize: '0.875rem', color: '#166534' }}>
                  <div><strong>저장 ID:</strong> <span style={{ fontFamily: 'monospace', letterSpacing: '1px' }}>{savedId}</span></div>
                  <div><strong>서류 이름:</strong> {savedDocName || '서류 이름 미설정'}</div>
                </div>
              </div>
                {saveError && <p style={{ color: '#ef4444', fontSize: '0.8125rem', marginBottom: '1rem' }}>{saveError}</p>}
                <button onClick={handleSaveClick} className="btn btn-primary" style={{ width: '100%', marginTop: '0.5rem' }}>
                  임시저장
                </button>
              </>
            ) : (
              <>
                <p style={{ fontSize: '0.9375rem', color: 'var(--text-secondary)', lineHeight: '1.6', marginBottom: '1rem' }}>
                  먼저 저장 ID 또는 서류 이름과 PIN으로 서류를 불러온 뒤 임시저장할 수 있습니다.
                </p>
                {saveError && <p style={{ color: '#ef4444', fontSize: '0.8125rem', marginBottom: '1rem' }}>{saveError}</p>}
                <button onClick={() => setMode('load')} className="btn btn-primary" style={{ width: '100%', marginTop: '0.5rem' }}>
                  불러오기
                </button>
              </>
            )}
          </div>
        ) : (
          <div className="animate-fade-in">
            <div className="mb-4">
              <label className="form-label">저장 ID 또는 서류 이름</label>
              <input value={loadQuery} onChange={e => setLoadQuery(e.target.value)} placeholder="저장 ID 또는 서류 이름"
                className="form-control" />
            </div>
            <div className="mb-6">
              <label className="form-label">비밀번호/PIN</label>
              <input value={loadPin} onChange={e => setLoadPin(e.target.value)} placeholder="비밀번호 또는 PIN"
                className="form-control" />
            </div>
            {loadError && <p style={{ color: '#ef4444', fontSize: '0.8125rem', marginBottom: '1rem' }}>{loadError}</p>}
            <button onClick={handleLoad} className="btn btn-primary" style={{ width: '100%', background: '#0f172a' }}>
              불러오기
            </button>
          </div>
        )}
        <button onClick={onClose} style={{ width: '100%', marginTop: '1rem', padding: '0.75rem', background: 'none', border: 'none', color: 'var(--text-muted)', fontSize: '0.875rem', cursor: 'pointer', fontFamily: 'inherit', fontWeight: '500' }}>닫기</button>
      </div>
    </div>
  );
}

// ── Success Screen ─────────────────────────────────────────────
function SuccessScreen({ receiptId, onReset }) {
  return (
    <div className="card text-center animate-fade-in" style={{ padding: '4rem 2rem' }}>
      <div style={{ fontSize: '4rem', marginBottom: '1.5rem' }}>🎉</div>
      <h2 style={{ fontSize: '1.75rem', fontWeight: '800', color: 'var(--text-primary)', marginBottom: '1rem' }}>접수가 완료되었습니다</h2>
      <p style={{ fontSize: '1rem', color: 'var(--text-secondary)', marginBottom: '2rem' }}>
        서류 준비가 완료되면 입력하신 이메일로 안내드립니다.<br/>
        통상 <strong>1~2 영업일</strong> 내 확인 후 연락드립니다.
      </p>
      <div style={{ background: 'var(--primary-light)', border: '1px solid #bae6fd', borderRadius: 'var(--radius-lg)', padding: '1.5rem 2rem', display: 'inline-block', marginBottom: '2rem' }}>
        <div style={{ fontSize: '0.875rem', color: '#0369a1', marginBottom: '0.25rem', fontWeight: '600' }}>접수 번호</div>
        <div style={{ fontSize: '2rem', fontWeight: '800', color: '#0284c7', letterSpacing: '2px', fontFamily: 'monospace' }}>{receiptId}</div>
      </div>
      <div style={{ background: '#fffbeb', border: '1px solid #fcd34d', borderRadius: 'var(--radius-md)', padding: '1rem 1.5rem', fontSize: '0.875rem', color: '#92400e', marginBottom: '2.5rem', textAlign: 'left', maxWidth: '400px', margin: '0 auto 2.5rem' }}>
        <strong>안내사항</strong><br/>
        • 접수 번호를 문의 시 알려주시면 빠른 확인이 가능합니다.<br/>
        • 제출 서류 중 미비한 항목은 별도 연락드립니다.
      </div>
      <button onClick={onReset} className="btn" style={{ background: '#0f172a', color: 'white', padding: '1rem 2rem' }}>
        새 신청서 작성하기
      </button>
    </div>
  );
}

// ── Main FormApp ───────────────────────────────────────────────
function FormApp() {
  const [step, setStep] = React.useState(1);
  const [formData, setFormData] = React.useState(normalizeFormData());
  const [files, setFiles] = React.useState({});
  const [showSave, setShowSave] = React.useState(false);
  const [saveMode, setSaveMode] = React.useState('save');
  const [savedId, setSavedId] = React.useState('');
  const [savedPin, setSavedPin] = React.useState('');
  const [savedDocName, setSavedDocName] = React.useState('');
  const [saveNotice, setSaveNotice] = React.useState('');
  const [submitError, setSubmitError] = React.useState('');
  const [submitting, setSubmitting] = React.useState(false);
  const [submitted, setSubmitted] = React.useState(false);
  const [receiptId, setReceiptId] = React.useState('');
  const stepTabsRef = React.useRef(null);

  const setStepData = (key) => (val) => setFormData(p => ({ ...p, [key]: val }));

  React.useEffect(() => {
    const wrap = stepTabsRef.current;
    const active = wrap?.querySelector(`[data-step-id="${step}"]`);
    if (!wrap || !active) return;

    const wrapRect = wrap.getBoundingClientRect();
    const activeRect = active.getBoundingClientRect();
    const centeredLeft = wrap.scrollLeft + activeRect.left - wrapRect.left - ((wrap.clientWidth - activeRect.width) / 2);
    wrap.scrollTo({ left: Math.max(0, centeredLeft), behavior: 'smooth' });
  }, [step]);

  function handleSave() {
    if (!savedId) return '먼저 불러오기로 서류를 연 뒤 임시저장해 주세요.';
    const existing = readDraftRecord(savedId);
    if (!existing) return '저장본을 찾을 수 없습니다. 다시 불러온 뒤 저장해 주세요.';
    const revisions = [...(existing.revisions || []), makeDraftRevision(existing)];
    const record = {
      ...existing,
      id: savedId,
      data: formData,
      files: sanitizeFiles(files),
      createdAt: existing?.createdAt || nowIso(),
      updatedAt: nowIso(),
      revisions,
    };
    saveDraftRecord(record);
    setSavedPin(record.pin || '');
    setSavedDocName(record.docName || '');
    return '';
  }

  function handleLoad(data, filesMeta, id, pin, docName) {
    setFormData(normalizeFormData(data || {}));
    setFiles(filesMeta || {});
    setSavedId(id);
    setSavedPin(pin);
    setSavedDocName(docName || '');
    setSaveNotice(`${docName || id} 서류를 불러왔습니다.`);
    setStep(1);
  }

  function handleQuickSave() {
    const error = handleSave();
    if (error) {
      setSaveNotice(error);
      setSaveMode('load');
      setShowSave(true);
      return;
    }
    setSaveNotice('임시저장했습니다. 이전 저장본은 수정 이력으로 남겼습니다.');
  }

  async function handleSubmit() {
    const errors = validateBeforeSubmit(formData, files);
    if (errors.length) {
      setSubmitError(errors.slice(0, 8).join('\n') + (errors.length > 8 ? `\n외 ${errors.length - 8}건` : ''));
      return;
    }

    const body = new FormData();
    body.append('payload', JSON.stringify({ formData, files: sanitizeFiles(files) }));
    Object.entries(files).forEach(([key, item]) => {
      if (item?.file instanceof File) {
        body.append(`files[${key}]`, item.file, item.file.name);
      }
    });

    setSubmitting(true);
    setSubmitError('');
    try {
      const response = await fetch('submit.php', { method: 'POST', body });
      const result = await response.json();
      if (!response.ok || !result.ok) {
        const messages = result.errors || [result.error || '접수 저장에 실패했습니다.'];
        setSubmitError(messages.join('\n'));
        return;
      }
      setReceiptId(result.receiptId || result.requestId);
      setSubmitted(true);
      if (savedId) localStorage.removeItem(`ciq_draft_${savedId}`);
    } catch (error) {
      setSubmitError('서버에 접수 데이터를 저장할 수 없습니다. PHP 서버에서 열었는지 확인해 주세요.');
    } finally {
      setSubmitting(false);
    }
  }

  const summary = [
    { label: '신청자', value: formData.applicant?.name },
    { label: '연락처', value: formData.applicant?.phone },
    { label: '출항지', value: formData.voyage?.departPort },
    { label: '입항지(일본)', value: formData.voyage?.arrivePort },
    { label: '예정 출항일', value: formData.voyage?.departDate },
    { label: '선박명', value: [formData.vessel?.vesselNameKo, formData.vessel?.vesselNameEn].filter(Boolean).join(' / ') },
    { label: '선장', value: formData.captain?.captainNameKo },
    { label: '승선 인원', value: formData.crew?.crew?.length ? `${formData.crew.crew.length}명` : '' },
    { label: '한국→일본 승선', value: `${countCrewByLeg(formData.crew, 'koreaToJapan')}명` },
    { label: '일본→한국 승선', value: `${countCrewByLeg(formData.crew, 'japanToKorea')}명` },
    { label: '첨부파일', value: `${Object.keys(files).length}건 업로드` },
  ];

  if (submitted) return <SuccessScreen receiptId={receiptId} onReset={() => { setSubmitted(false); setFormData(normalizeFormData()); setFiles({}); setStep(1); setSavedId(''); setSavedPin(''); setSavedDocName(''); }} />;

  return (
    <div style={{ maxWidth: '800px', margin: '0 auto', padding: '0 1rem 4rem' }}>
      {/* Progress */}
      <div className="mb-8">
        <div className="step-tabs-shell">
          <div ref={stepTabsRef} className="step-tabs" aria-label="신청 단계">
          {STEPS.map(s => (
            <button key={s.id} data-step-id={s.id} aria-current={step === s.id ? 'step' : undefined} onClick={() => setStep(s.id)} style={{
              display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '0.25rem',
              flex: '0 0 auto', padding: '0.75rem 1rem', borderRadius: 'var(--radius-lg)', cursor: 'pointer',
              border: 'none', fontFamily: 'inherit',
              background: step === s.id ? '#0f172a' : step > s.id ? 'var(--primary-light)' : 'var(--bg-color)',
              color: step === s.id ? 'white' : step > s.id ? 'var(--primary)' : 'var(--text-muted)',
              transition: 'all 0.3s ease',
              boxShadow: step === s.id ? '0 4px 12px rgba(15,23,42,0.15)' : 'none'
            }}>
              <span style={{ fontSize: '1.25rem' }}>{step > s.id ? '✓' : s.icon}</span>
              <span style={{ fontSize: '0.75rem', fontWeight: '600', whiteSpace: 'nowrap' }}>{s.title}</span>
            </button>
          ))}
          </div>
        </div>
        {/* Progress bar */}
        <div style={{ height: '6px', background: 'var(--bg-color)', borderRadius: '3px', overflow: 'hidden' }}>
          <div style={{ height: '100%', background: 'linear-gradient(90deg, var(--primary), #3b82f6)', width: `${(step / STEPS.length) * 100}%`, transition: 'width 0.4s cubic-bezier(0.4, 0, 0.2, 1)' }} />
        </div>
      </div>

      {/* Step title */}
      <div className="mb-6">
        <div style={{ fontSize: '0.8125rem', color: 'var(--primary)', fontWeight: '700', letterSpacing: '1px', marginBottom: '0.5rem' }}>STEP {step} / {STEPS.length}</div>
        <h2 style={{ fontSize: '1.75rem', fontWeight: '800', color: 'var(--text-primary)' }}>{STEPS[step-1].icon} {STEPS[step-1].title}</h2>
      </div>

      {/* Step content */}
      <div className="card mb-8">
        {step === 1 && <Step1 data={formData.applicant} set={setStepData('applicant')} />}
        {step === 2 && <Step2 data={formData.voyage} set={setStepData('voyage')} />}
        {step === 3 && <Step3 data={formData.vessel} set={setStepData('vessel')} />}
        {step === 4 && <Step4 data={formData.captain} set={setStepData('captain')} />}
        {step === 5 && <Step5 data={formData.crew} set={setStepData('crew')} />}
        {step === 6 && <Step6 files={files} setFiles={setFiles} />}
        {step === 7 && <Step7 summary={summary} consent={formData.consent} setConsent={setStepData('consent')} />}
      </div>

      {/* Nav buttons */}
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', gap: '1rem' }}>
        <div style={{ display: 'flex', gap: '0.5rem' }}>
          {step > 1 && (
            <button onClick={() => setStep(s => s - 1)} className="btn btn-outline" style={{ padding: '0.75rem 1.25rem' }}>
              ← 이전
            </button>
          )}
          <button onClick={() => { setSaveMode('load'); setShowSave(true); }} className="btn" style={{ background: 'var(--bg-color)', color: 'var(--text-secondary)', padding: '0.75rem 1.25rem' }}>
            📂 불러오기
          </button>
          <button onClick={handleQuickSave} className="btn" style={{ background: 'var(--bg-color)', color: 'var(--text-secondary)', padding: '0.75rem 1.25rem' }}>
            💾 임시저장
          </button>
        </div>

        {step < STEPS.length ? (
          <button onClick={() => setStep(s => s + 1)} className="btn btn-primary" style={{ padding: '0.875rem 2rem' }}>
            다음 단계 →
          </button>
        ) : (
          <button onClick={handleSubmit} disabled={submitting} className="btn btn-primary" style={{ padding: '0.875rem 2rem', background: 'linear-gradient(135deg, #0f172a, #3b82f6)', boxShadow: '0 4px 15px rgba(59,130,246,0.4)', opacity: submitting ? 0.7 : 1 }}>
            {submitting ? '접수 저장 중...' : '📨 접수 제출하기'}
          </button>
        )}
      </div>
      {submitError && (
        <div role="alert" style={{ marginTop: '1rem', whiteSpace: 'pre-line', color: '#b91c1c', background: '#fef2f2', border: '1px solid #fecaca', borderRadius: 'var(--radius-md)', padding: '1rem', fontSize: '0.875rem', lineHeight: 1.6 }}>
          {submitError}
        </div>
      )}
      {saveNotice && (
        <p role="status" aria-live="polite" style={{ marginTop: '1rem', color: saveNotice.includes('먼저') || saveNotice.includes('찾을 수') ? '#ef4444' : 'var(--text-secondary)', fontSize: '0.875rem' }}>
          {saveNotice}
        </p>
      )}

      {showSave && (
        <SaveModal
          onClose={() => setShowSave(false)}
          onSave={handleSave}
          onLoad={handleLoad}
          savedId={savedId}
          savedPin={savedPin}
          savedDocName={savedDocName}
          initialMode={saveMode}
        />
      )}
    </div>
  );
}

Object.assign(window, { FormApp });
