import React, { useState, useEffect, useRef } from 'react';
import { createRoot } from 'react-dom/client';
import JSZip from 'jszip';
import { PDFDocument } from 'pdf-lib';
import { 
  FileText, 
  Image as ImageIcon, 
  Download, 
  Sparkles, 
  Scale, 
  RefreshCw, 
  UploadCloud, 
  FileCheck, 
  Layers, 
  Sliders, 
  ImageDown, 
  FileDown, 
  Info, 
  Check, 
  ArrowRightLeft,
  X,
  Lock,
  Unlock,
  Maximize,
  Grid,
  Split,
  Columns
} from 'lucide-react';

// Declare pdfjsLib global variable
declare const pdfjsLib: any;

interface HistoryItem {
  id: string;
  fileName: string;
  type: 'pdf' | 'image';
  originalSize: number;
  optimizedSize: number;
  timestamp: string;
  dataUrl: string;
  format: string;
}

// App entry point
function App() {
  const [activeTab, setActiveTab] = useState<'pdf' | 'image' | 'split'>('pdf');
  const [history, setHistory] = useState<HistoryItem[]>([]);

  // Load history from localStorage on mount if exists
  useEffect(() => {
    try {
      const saved = localStorage.getItem('formatflow_history');
      if (saved) {
        setHistory(JSON.parse(saved));
      }
    } catch (e) {
      console.error('Failed to load history:', e);
    }
  }, []);

  const addToHistory = (item: Omit<HistoryItem, 'id' | 'timestamp'>) => {
    const newItem: HistoryItem = {
      ...item,
      id: Math.random().toString(36).substring(2, 9),
      timestamp: new Date().toLocaleTimeString('ko-KR', { hour: '2-digit', minute: '2-digit' })
    };
    setHistory(prev => {
      const updated = [newItem, ...prev].slice(0, 12); // Keep last 12 items
      try {
        localStorage.setItem('formatflow_history', JSON.stringify(updated));
      } catch (e) {
        console.error('Failed to save history:', e);
      }
      return updated;
    });
  };

  const clearHistory = () => {
    setHistory([]);
    try {
      localStorage.removeItem('formatflow_history');
    } catch (e) {}
  };

  // Cumulative savings calculations
  const totalOriginalSize = history.reduce((acc, item) => acc + item.originalSize, 0);
  const totalOptimizedSize = history.reduce((acc, item) => acc + item.optimizedSize, 0);
  const totalSavedSize = Math.max(0, totalOriginalSize - totalOptimizedSize);
  const averageCompression = totalOriginalSize > 0 
    ? ((totalSavedSize / totalOriginalSize) * 100).toFixed(1) 
    : '0.0';

  return (
    <div className="min-h-screen bg-slate-50 text-slate-800 flex flex-col font-sans selection:bg-rose-500 selection:text-white">
      {/* Background soft glow accents */}
      <div className="absolute top-0 left-0 right-0 h-[400px] bg-gradient-to-b from-rose-50/40 to-slate-50/10 pointer-events-none"></div>

      {/* Header */}
      <header className="relative border-b border-slate-200 bg-white/90 backdrop-blur-md z-10 shadow-sm">
        <div className="max-w-7xl mx-auto px-4 py-4 flex flex-col md:flex-row md:items-center md:justify-between gap-4">
          <div className="flex items-center gap-3">
            <div className="p-2 bg-rose-600 rounded-xl shadow-md shadow-rose-600/10">
              <Sparkles className="w-5 h-5 text-white animate-pulse" />
            </div>
            <div>
              <div className="flex items-center gap-2">
                <h1 className="text-lg font-black tracking-tight text-slate-900">
                  FormatFlow <span className="text-[10px] bg-rose-100 text-rose-700 font-bold px-2 py-0.5 rounded-full border border-rose-200">PRO</span>
                </h1>
                <span className="text-[9px] font-bold bg-slate-100 text-slate-600 border border-slate-200 px-1.5 py-0.2 rounded-md">
                  v3.5 Premium
                </span>
              </div>
              <p className="text-[11px] text-slate-500 mt-0.5 font-medium">
                서버 전송 없이 안전한 브라우저 가속 PDF 변환 및 이미지 최적화 솔루션
              </p>
            </div>
          </div>

          {/* Tab Navigation (SaaS pill-style) */}
          <div className="flex flex-wrap gap-1 bg-slate-100 p-1.5 rounded-xl border border-slate-200/60 max-w-max">
            <button
              id="tab-btn-pdf"
              onClick={() => setActiveTab('pdf')}
              className={`flex items-center gap-2 px-4 py-2 text-xs font-bold rounded-lg transition-all duration-200 cursor-pointer ${
                activeTab === 'pdf'
                  ? 'bg-white text-rose-600 shadow-sm border border-slate-200/50 font-extrabold'
                  : 'text-slate-600 hover:text-slate-900 hover:bg-white/40'
              }`}
            >
              <FileText className="w-3.5 h-3.5" />
              PDF JPG 변환
            </button>
            <button
              id="tab-btn-split"
              onClick={() => setActiveTab('split')}
              className={`flex items-center gap-2 px-4 py-2 text-xs font-bold rounded-lg transition-all duration-200 cursor-pointer ${
                activeTab === 'split'
                  ? 'bg-white text-rose-600 shadow-sm border border-slate-200/50 font-extrabold'
                  : 'text-slate-600 hover:text-slate-900 hover:bg-white/40'
              }`}
            >
              <Split className="w-3.5 h-3.5" />
              PDF 페이지 분할 (Split)
            </button>
            <button
              id="tab-btn-image"
              onClick={() => setActiveTab('image')}
              className={`flex items-center gap-2 px-4 py-2 text-xs font-bold rounded-lg transition-all duration-200 cursor-pointer ${
                activeTab === 'image'
                  ? 'bg-white text-rose-600 shadow-sm border border-slate-200/50 font-extrabold'
                  : 'text-slate-600 hover:text-slate-900 hover:bg-white/40'
              }`}
            >
              <ImageIcon className="w-3.5 h-3.5" />
              이미지 압축 & 포맷 최적화
            </button>
          </div>
        </div>
      </header>

      {/* Modern SaaS Features Highlights Grid */}
      <section className="relative z-10 max-w-7xl w-full mx-auto px-4 pt-6">
        <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
          <div className="bg-white border border-slate-200/60 rounded-xl p-3.5 flex items-start gap-3 shadow-[0_2px_8px_rgba(0,0,0,0.01)]">
            <div className="p-2 bg-emerald-50 text-emerald-600 rounded-lg shrink-0">
              <Lock className="w-4 h-4" />
            </div>
            <div>
              <h4 className="text-xs font-bold text-slate-800">100% 완전 로컬 프라이버시 보장</h4>
              <p className="text-[10px] text-slate-500 mt-0.5 leading-relaxed">서버 업로드 및 클라우드 전송 과정이 전혀 없습니다. 모든 기밀 문서가 브라우저 내부에서만 완벽히 안전하게 처리됩니다.</p>
            </div>
          </div>
          <div className="bg-white border border-slate-200/60 rounded-xl p-3.5 flex items-start gap-3 shadow-[0_2px_8px_rgba(0,0,0,0.01)]">
            <div className="p-2 bg-rose-50 text-rose-600 rounded-lg shrink-0">
              <Sparkles className="w-4 h-4" />
            </div>
            <div>
              <h4 className="text-xs font-bold text-slate-800">GPU 하드웨어 가속 연산</h4>
              <p className="text-[10px] text-slate-500 mt-0.5 leading-relaxed">대용량 다면 PDF 문서나 수십 장의 무손실 이미지도 병렬 연산 코어를 통해 수 초 내에 최적 변환을 구현합니다.</p>
            </div>
          </div>
          <div className="bg-white border border-slate-200/60 rounded-xl p-3.5 flex items-start gap-3 shadow-[0_2px_8px_rgba(0,0,0,0.01)]">
            <div className="p-2 bg-amber-50 text-amber-600 rounded-lg shrink-0">
              <Scale className="w-4 h-4" />
            </div>
            <div>
              <h4 className="text-xs font-bold text-slate-800">선명도 극대화 래스터라이저</h4>
              <p className="text-[10px] text-slate-500 mt-0.5 leading-relaxed">디지털 서명, 서브픽셀 폰트 비트맵 힌팅 기술 및 하이파이 컬러 매핑 알고리즘이 탑재되어 무손실 수준의 명료함을 전달합니다.</p>
            </div>
          </div>
        </div>
      </section>

      {/* Main Content */}
      <main className="flex-grow max-w-7xl w-full mx-auto px-4 py-6 relative z-10">
        {activeTab === 'pdf' && <PdfConverter onAddToHistory={addToHistory} />}
        {activeTab === 'split' && <PdfSplitter onAddToHistory={addToHistory} />}
        {activeTab === 'image' && <ImageOptimizer onAddToHistory={addToHistory} />}

        {/* 3. Workspace History & Savings Dashboard */}
        <section className="mt-12 bg-white border border-slate-200 rounded-2xl p-6 shadow-sm relative overflow-hidden" id="workspace-dashboard">
          <div className="flex flex-col md:flex-row items-start md:items-center justify-between border-b border-slate-100 pb-5 mb-6 gap-4">
            <div>
              <h3 className="text-base font-bold text-slate-900 flex items-center gap-2">
                <Layers className="w-5 h-5 text-rose-500" />
                로컬 작업 히스토리 및 대역폭 통계 리포트
              </h3>
              <p className="text-xs text-slate-500 mt-1">
                현재 브라우저 가상 샌드박스에서 처리 완료된 파일 조각들과 디스크 절약 현황입니다.
              </p>
            </div>
            {history.length > 0 && (
              <button
                id="btn-clear-history"
                onClick={clearHistory}
                className="text-xs text-slate-500 hover:text-slate-800 font-semibold px-3 py-1.5 bg-white border border-slate-200 hover:border-slate-300 rounded-lg transition-all cursor-pointer"
              >
                히스토리 초기화
              </button>
            )}
          </div>

          <div className="grid grid-cols-1 lg:grid-cols-12 gap-8">
            {/* Cumulative Statistics Widget */}
            <div className="lg:col-span-4 bg-slate-950 border border-slate-850 rounded-xl p-5 flex flex-col justify-between relative overflow-hidden" id="analytics-statistics-card">
              <div className="space-y-4">
                <span className="text-[10px] text-indigo-400 font-bold uppercase tracking-wider block">대역폭 및 저장소 절약 수치</span>
                
                <div className="grid grid-cols-2 gap-4">
                  <div className="bg-slate-900/50 p-3 rounded-lg border border-slate-850">
                    <span className="text-[9px] text-slate-500 font-bold block">총 최적화 횟수</span>
                    <span className="text-2xl font-black text-white">{history.length} <span className="text-xs text-slate-400">건</span></span>
                  </div>
                  <div className="bg-slate-900/50 p-3 rounded-lg border border-slate-850">
                    <span className="text-[9px] text-slate-500 font-bold block">평균 압축 효율</span>
                    <span className="text-2xl font-black text-emerald-400">-{averageCompression}%</span>
                  </div>
                </div>

                <div className="bg-slate-900/50 p-4 rounded-lg border border-slate-850 space-y-1.5">
                  <div className="flex justify-between text-xs">
                    <span className="text-slate-400 font-semibold">총 절감 용량</span>
                    <span className="text-indigo-400 font-bold">{(totalSavedSize / 1024).toFixed(1)} KB 절약됨</span>
                  </div>
                  <div className="w-full bg-slate-950 rounded-full h-1.5 overflow-hidden">
                    <div 
                      className="bg-gradient-to-r from-emerald-400 to-indigo-500 h-full rounded-full transition-all duration-300"
                      style={{ width: `${Math.min(100, history.length * 15)}%` }}
                    ></div>
                  </div>
                </div>
              </div>

              <div className="text-[10px] text-slate-500 mt-4 leading-relaxed">
                로컬 샌드박스 보안 프로토콜에 따라, 모든 파일 캐시는 사용자가 탭을 닫거나 새로고침할 때 브라우저 임시 메모리에서 완벽히 소거됩니다.
              </div>
            </div>

            {/* List of Recent Conversion items */}
            <div className="lg:col-span-8 flex flex-col">
              {history.length === 0 ? (
                <div className="flex-grow flex flex-col items-center justify-center text-slate-600 py-12 border border-dashed border-slate-850 rounded-xl bg-slate-950/20" id="history-empty-state">
                  <RefreshCw className="w-8 h-8 text-slate-800 mb-2.5 animate-pulse" />
                  <p className="text-xs font-semibold text-slate-400">기록된 최근 변환 내역이 없습니다</p>
                  <p className="text-[10px] text-slate-500 mt-1">상단 도구를 이용하여 PDF 변환이나 이미지 압축을 실행해 보세요.</p>
                </div>
              ) : (
                <div className="space-y-2 max-h-[280px] overflow-y-auto pr-1.5 scrollbar-thin scrollbar-thumb-slate-800 scrollbar-track-transparent" id="history-list">
                  {history.map((item) => {
                    const savedPct = item.originalSize > item.optimizedSize 
                      ? ((1 - item.optimizedSize / item.originalSize) * 100).toFixed(0)
                      : '0';

                    return (
                      <div 
                        key={item.id} 
                        className="bg-slate-950 border border-slate-850 hover:border-slate-750 p-3 rounded-xl flex items-center justify-between gap-4 transition-all duration-200 group"
                      >
                        <div className="flex items-center gap-3 overflow-hidden">
                          {/* Mini visual image preview */}
                          <div className="w-10 h-10 rounded-lg bg-slate-900 border border-slate-800 shrink-0 overflow-hidden flex items-center justify-center">
                            {item.dataUrl ? (
                              <img src={item.dataUrl} alt="thumbnail" className="w-full h-full object-cover" />
                            ) : (
                              <FileText className="w-5 h-5 text-slate-500" />
                            )}
                          </div>
                          
                          <div className="overflow-hidden">
                            <h5 className="text-xs font-semibold text-slate-200 truncate max-w-[200px] sm:max-w-[320px]">
                              {item.fileName}
                            </h5>
                            <div className="flex items-center gap-2 mt-1">
                              <span className="text-[9px] bg-slate-900 border border-slate-800 text-slate-400 px-1.5 py-0.2 rounded font-mono uppercase">
                                {item.format}
                              </span>
                              <span className="text-[10px] text-slate-500 font-mono">
                                {(item.originalSize / 1024).toFixed(1)}KB → <span className="text-slate-300 font-bold">{(item.optimizedSize / 1024).toFixed(1)}KB</span>
                              </span>
                              <span className="text-[10px] text-slate-400 font-semibold">
                                {item.timestamp}
                              </span>
                            </div>
                          </div>
                        </div>

                        <div className="flex items-center gap-2 shrink-0">
                          {Number(savedPct) > 0 && (
                            <span className="text-[10px] bg-emerald-500/10 text-emerald-400 border border-emerald-500/20 font-extrabold px-2 py-0.5 rounded-full">
                              -{savedPct}%
                            </span>
                          )}
                          <a
                            href={item.dataUrl}
                            download={item.fileName.includes('page') ? item.fileName : `${item.fileName.replace(/\.[^/.]+$/, "")}_optimized.${item.format.toLowerCase()}`}
                            className="p-1.5 bg-slate-900 hover:bg-indigo-600 border border-slate-800 hover:border-indigo-500 text-slate-400 hover:text-white rounded-lg transition-all"
                            title="다시 다운로드"
                          >
                            <Download className="w-3.5 h-3.5" />
                          </a>
                        </div>
                      </div>
                    );
                  })}
                </div>
              )}
            </div>
          </div>
        </section>
      </main>

      {/* Footer */}
      <footer className="border-t border-slate-900 bg-slate-950/80 py-6 text-center text-xs text-slate-500 relative z-10">
        <p>© 2026 FormatFlow Studio Pro. 브라우저 로컬 가속 샌드박스로 모든 파일 데이터가 안전하게 보호됩니다.</p>
      </footer>
    </div>
  );
}


// ==========================================
// 1. PDF TO JPG CONVERTER COMPONENT
// ==========================================
interface PdfPageItem {
  pageNumber: number;
  dataUrl: string;
}

function PdfConverter({ onAddToHistory }: { onAddToHistory: (item: Omit<HistoryItem, 'id' | 'timestamp'>) => void }) {
  const [file, setFile] = useState<File | null>(null);
  const [totalPages, setTotalPages] = useState<number>(0);
  const [scale, setScale] = useState<number>(1.5); // Resolution multiplier
  const [convertedPages, setConvertedPages] = useState<PdfPageItem[]>([]);
  const [isProcessing, setIsProcessing] = useState<boolean>(false);
  const [progress, setProgress] = useState<{ current: number; total: number }>({ current: 0, total: 0 });
  const [dragActive, setDragActive] = useState<boolean>(false);
  const [pageRangeMode, setPageRangeMode] = useState<'all' | 'custom'>('all');
  const [startPage, setStartPage] = useState<number>(1);
  const [endPage, setEndPage] = useState<number>(1);
  
  // Real-time page previews of the PDF file
  const [pdfPreviewPages, setPdfPreviewPages] = useState<string[]>([]);
  const [isPreviewLoading, setIsPreviewLoading] = useState<boolean>(false);
  
  const fileInputRef = useRef<HTMLInputElement>(null);

  // Set pdf.js worker URL on mount
  useEffect(() => {
    if (typeof window !== 'undefined' && pdfjsLib) {
      pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js';
    }
  }, []);

  const handleDrag = (e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    if (e.type === "dragenter" || e.type === "dragover") {
      setDragActive(true);
    } else if (e.type === "dragleave") {
      setDragActive(false);
    }
  };

  const handleDrop = (e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setDragActive(false);

    if (e.dataTransfer.files && e.dataTransfer.files[0]) {
      const droppedFile = e.dataTransfer.files[0];
      if (droppedFile.type === 'application/pdf' || droppedFile.name.endsWith('.pdf')) {
        handlePdfSelection(droppedFile);
      } else {
        alert('PDF 파일만 업로드할 수 있습니다.');
      }
    }
  };

  const handleFileInput = (e: React.ChangeEvent<HTMLInputElement>) => {
    if (e.target.files && e.target.files[0]) {
      handlePdfSelection(e.target.files[0]);
    }
  };

  const handlePdfSelection = async (selectedFile: File) => {
    setFile(selectedFile);
    setConvertedPages([]);
    setPdfPreviewPages([]);
    setProgress({ current: 0, total: 0 });
    setIsPreviewLoading(true);

    try {
      const fileReader = new FileReader();
      fileReader.onload = async function () {
        try {
          const typedarray = new Uint8Array(this.result as ArrayBuffer);
          const loadingTask = pdfjsLib.getDocument({ data: typedarray });
          const pdf = await loadingTask.promise;
          const total = pdf.numPages;
          setTotalPages(total);
          setEndPage(total);
          setStartPage(1);

          // Generate preview for first 5 pages (or total if less than 5)
          const previewsCount = Math.min(5, total);
          const previewUrls: string[] = [];
          for (let i = 1; i <= previewsCount; i++) {
            const page = await pdf.getPage(i);
            const viewport = page.getViewport({ scale: 0.6 }); // Fast preview scale
            const canvas = document.createElement('canvas');
            const context = canvas.getContext('2d');
            if (context) {
              canvas.height = viewport.height;
              canvas.width = viewport.width;
              await page.render({ canvasContext: context, viewport }).promise;
              previewUrls.push(canvas.toDataURL('image/jpeg', 0.82));
            }
          }
          setPdfPreviewPages(previewUrls);
        } catch (err) {
          console.error('Error generating PDF live previews:', err);
        } finally {
          setIsPreviewLoading(false);
        }
      };
      fileReader.readAsArrayBuffer(selectedFile);
    } catch (err) {
      console.error(err);
      alert('PDF 파일을 분석하는 중 오류가 발생했습니다.');
      setIsPreviewLoading(false);
    }
  };

  const startConversion = async () => {
    if (!file) return;
    setIsProcessing(true);
    setConvertedPages([]);

    const actualStart = pageRangeMode === 'all' ? 1 : Math.max(1, startPage);
    const actualEnd = pageRangeMode === 'all' ? totalPages : Math.min(totalPages, endPage);
    const targetPages: number[] = [];
    for (let i = actualStart; i <= actualEnd; i++) {
      targetPages.push(i);
    }

    setProgress({ current: 0, total: targetPages.length });

    try {
      const fileReader = new FileReader();
      fileReader.onload = async function () {
        try {
          const typedarray = new Uint8Array(this.result as ArrayBuffer);
          const loadingTask = pdfjsLib.getDocument({ data: typedarray });
          const pdf = await loadingTask.promise;

          const renderedList: PdfPageItem[] = [];

          for (let index = 0; index < targetPages.length; index++) {
            const pageNum = targetPages[index];
            const page = await pdf.getPage(pageNum);
            const viewport = page.getViewport({ scale: scale });
            
            const canvas = document.createElement('canvas');
            const context = canvas.getContext('2d');
            if (context) {
              canvas.height = viewport.height;
              canvas.width = viewport.width;

              const renderContext = {
                canvasContext: context,
                viewport: viewport,
              };

              await page.render(renderContext).promise;
              const dataUrl = canvas.toDataURL('image/jpeg', 0.94);
              renderedList.push({
                pageNumber: pageNum,
                dataUrl: dataUrl
              });
            }
            setProgress(prev => ({ ...prev, current: index + 1 }));
          }

          setConvertedPages(renderedList);

          if (renderedList.length > 0) {
            // Log conversion complete inside local history context
            const base64Str = renderedList[0].dataUrl.split(',')[1];
            const sampleSize = window.atob(base64Str).length;
            const estimatedTotalSize = sampleSize * renderedList.length;

            onAddToHistory({
              fileName: `${file.name} (총 ${renderedList.length}개 페이지)`,
              type: 'pdf',
              originalSize: file.size,
              optimizedSize: estimatedTotalSize,
              dataUrl: renderedList[0].dataUrl,
              format: 'JPEG'
            });
          }
        } catch (innerErr) {
          console.error(innerErr);
          alert('변환 중 오류가 발생했습니다. 파일 형식을 다시 확인해 주세요.');
        } finally {
          setIsProcessing(false);
        }
      };
      fileReader.readAsArrayBuffer(file);
    } catch (err) {
      console.error(err);
      alert('파일을 읽는 중 에러가 발생했습니다.');
      setIsProcessing(false);
    }
  };

  const downloadAllAsZip = async () => {
    if (convertedPages.length === 0 || !file) return;

    const zip = new JSZip();
    const folderName = file.name.replace(/\.[^/.]+$/, "");

    convertedPages.forEach((page) => {
      const base64Data = page.dataUrl.split(',')[1];
      zip.file(`${folderName}_page_${page.pageNumber}.jpg`, base64Data, { base64: true });
    });

    const content = await zip.generateAsync({ type: 'blob' });
    const link = document.createElement('a');
    link.href = URL.createObjectURL(content);
    link.download = `${folderName}_jpg_images.zip`;
    link.click();
  };

  const removeFile = () => {
    setFile(null);
    setTotalPages(0);
    setConvertedPages([]);
    setPdfPreviewPages([]);
    setProgress({ current: 0, total: 0 });
    if (fileInputRef.current) fileInputRef.current.value = '';
  };

  return (
    <div className="space-y-8 animate-fade-in" id="pdf-converter-container">
      {/* Introduction text */}
      <div className="text-center max-w-2xl mx-auto space-y-3">
        <span className="px-3 py-1 bg-indigo-500/10 text-indigo-400 rounded-full text-xs font-semibold border border-indigo-500/20 tracking-wide uppercase inline-block">
          Interactive PDF Engine
        </span>
        <h2 className="text-3xl font-extrabold tracking-tight text-white sm:text-4xl" id="pdf-title">
          PDF 고화질 JPG 일괄 변환기
        </h2>
        <p className="text-slate-400 text-sm leading-relaxed">
          브라우저 내부 가속 렌더링 기술을 통해 개인 정보 누출 걱정 없이 안전하게 PDF를 완벽한 JPG 파일로 개별 변환합니다.
        </p>
      </div>

      <div className="grid grid-cols-1 lg:grid-cols-12 gap-8 items-start">
        {/* Upload & Controls */}
        <div className="lg:col-span-5 space-y-6">
          <div className="bg-slate-900 border border-slate-800 rounded-2xl p-6 shadow-xl relative overflow-hidden" id="pdf-upload-card">
            {/* Background decor glow */}
            <div className="absolute top-0 right-0 w-32 h-32 bg-indigo-500/10 rounded-full blur-3xl pointer-events-none"></div>

            <h3 className="text-sm font-semibold tracking-wide text-indigo-400 uppercase mb-4 flex items-center gap-2">
              <UploadCloud className="w-4 h-4" /> 1. PDF 파일 업로드
            </h3>

            {/* Drag & Drop Zone */}
            {!file ? (
              <div
                id="pdf-drop-zone"
                onDragEnter={handleDrag}
                onDragOver={handleDrag}
                onDragLeave={handleDrag}
                onDrop={handleDrop}
                onClick={() => fileInputRef.current?.click()}
                className={`border-2 border-dashed rounded-xl p-8 text-center cursor-pointer transition-all duration-300 flex flex-col items-center justify-center min-h-[220px] ${
                  dragActive 
                    ? 'border-indigo-500 bg-indigo-500/10 scale-[1.02]' 
                    : 'border-slate-800 bg-slate-950/60 hover:border-slate-700 hover:bg-slate-900/40'
                }`}
              >
                <div className="p-4 bg-slate-900 rounded-2xl border border-slate-800 shadow-md group-hover:scale-110 transition-transform duration-300">
                  <FileText className="w-8 h-8 text-indigo-400" />
                </div>
                <p className="mt-4 text-sm font-medium text-slate-200">
                  PDF 파일을 여기에 드래그하거나 클릭하여 업로드하세요
                </p>
                <p className="mt-1.5 text-xs text-slate-500">
                  파일은 외부 서버로 절대 유출되지 않으며 완벽하게 내부 메모리에서 변환됩니다
                </p>
                <input
                  type="file"
                  ref={fileInputRef}
                  onChange={handleFileInput}
                  accept=".pdf,application/pdf"
                  className="hidden"
                  id="pdf-file-input"
                />
              </div>
            ) : (
              <div className="space-y-4">
                <div className="bg-slate-950 border border-slate-800 rounded-xl p-4 flex items-center justify-between shadow-inner" id="pdf-file-info-badge">
                  <div className="flex items-center gap-3 overflow-hidden">
                    <div className="p-2.5 bg-indigo-500/15 rounded-lg shrink-0 border border-indigo-500/10">
                      <FileCheck className="w-5 h-5 text-indigo-400" />
                    </div>
                    <div className="overflow-hidden">
                      <p className="text-sm font-medium text-slate-200 truncate" title={file.name}>
                        {file.name}
                      </p>
                      <p className="text-xs text-slate-500 mt-0.5">
                        {(file.size / (1024 * 1024)).toFixed(2)} MB • 총 {totalPages}페이지
                      </p>
                    </div>
                  </div>
                  <button
                    id="btn-remove-pdf"
                    onClick={removeFile}
                    className="p-1.5 text-slate-400 hover:text-slate-100 hover:bg-slate-800 rounded-md transition-colors border border-transparent hover:border-slate-700"
                    title="파일 제거"
                  >
                    <X className="w-4 h-4" />
                  </button>
                </div>

                {/* PDF Live Page Preview */}
                {isPreviewLoading && (
                  <div className="bg-slate-950 border border-slate-800 rounded-xl p-6 flex flex-col items-center justify-center space-y-2">
                    <RefreshCw className="w-5 h-5 text-indigo-400 animate-spin" />
                    <span className="text-xs text-slate-400">PDF 페이지 실시간 미리보기 생성 중...</span>
                  </div>
                )}

                {!isPreviewLoading && pdfPreviewPages.length > 0 && (
                  <div className="bg-slate-950/60 border border-slate-800/80 rounded-xl p-4 space-y-3" id="pdf-preview-box">
                    <div className="flex justify-between items-center">
                      <span className="text-xs text-indigo-300 font-semibold flex items-center gap-1.5">
                        <span className="w-1.5 h-1.5 rounded-full bg-indigo-500 animate-pulse"></span>
                        업로드된 PDF 실시간 미리보기
                      </span>
                      <span className="text-[10px] text-slate-500 font-mono">
                        처음 {pdfPreviewPages.length}개 페이지 자동 로드됨
                      </span>
                    </div>
                    <div className="flex gap-3 overflow-x-auto pb-2.5 scrollbar-thin scrollbar-thumb-slate-800 scrollbar-track-transparent">
                      {pdfPreviewPages.map((url, idx) => (
                        <div key={idx} className="relative shrink-0 w-24 aspect-[3/4] bg-slate-900 border border-slate-800 rounded-lg overflow-hidden group shadow-md hover:border-indigo-500/50 transition-all duration-300">
                          <img src={url} alt={`Preview page ${idx + 1}`} className="w-full h-full object-contain p-1" />
                          <div className="absolute inset-0 bg-slate-950/40 opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center">
                            <span className="text-[9px] font-bold bg-indigo-600 px-1.5 py-0.5 rounded text-white shadow">
                              Page {idx + 1}
                            </span>
                          </div>
                          <div className="absolute bottom-1 right-1 bg-slate-950/90 backdrop-blur px-1.5 py-0.5 rounded text-[8px] font-semibold text-slate-400 border border-slate-800/60">
                            P. {idx + 1}
                          </div>
                        </div>
                      ))}
                    </div>
                  </div>
                )}
              </div>
            )}
          </div>

          {/* Settings Section */}
          {file && (
            <div className="bg-slate-900 border border-slate-800 rounded-2xl p-6 shadow-xl relative overflow-hidden animate-slide-up" id="pdf-settings-card">
              <h3 className="text-sm font-semibold tracking-wide text-indigo-400 uppercase mb-4 flex items-center gap-2">
                <Sliders className="w-4 h-4" /> 2. 변환 정밀 설정
              </h3>

              <div className="space-y-5">
                {/* Resolution / Scale Slider */}
                <div className="space-y-3">
                  <div className="flex justify-between items-center text-xs">
                    <span className="text-slate-400 font-medium flex items-center gap-1">
                      <Maximize className="w-3.5 h-3.5 text-indigo-400" />
                      스마트 변환 프로필 프리셋 (Smart Presets)
                    </span>
                    <span className="text-[11px] font-extrabold text-indigo-400 bg-indigo-500/10 px-2 py-0.5 rounded border border-indigo-500/10">
                      Scale: {scale}x
                    </span>
                  </div>
                  
                  <div className="grid grid-cols-2 gap-2.5">
                    {[
                      { val: 1, label: '📱 모바일 최적화', desc: '가볍고 빠른 로딩 (1.0x)' },
                      { val: 1.5, label: '💻 웹 표준 HD', desc: '권장 표준 균형 (1.5x)' },
                      { val: 2, label: '🖥️ 프레젠테이션', desc: '텍스트 선명화 (2.0x)' },
                      { val: 3, label: '🖨️ 전문 인쇄용', desc: '출판용 최고화질 (3.0x)' }
                    ].map((preset) => (
                      <button
                        key={preset.val}
                        id={`btn-scale-${preset.val.toString().replace('.', '-')}`}
                        onClick={() => setScale(preset.val)}
                        type="button"
                        className={`text-left p-2.5 rounded-xl border transition-all duration-200 cursor-pointer ${
                          scale === preset.val 
                            ? 'bg-indigo-600/15 border-indigo-500 text-white shadow-md shadow-indigo-500/10' 
                            : 'bg-slate-950/60 border-slate-800 hover:border-slate-750 text-slate-300'
                        }`}
                      >
                        <p className="text-[11px] font-bold">{preset.label}</p>
                        <p className="text-[9px] text-slate-500 mt-0.5">{preset.desc}</p>
                      </button>
                    ))}
                  </div>
                </div>

                {/* Page Range Selection */}
                <div className="space-y-3">
                  <span className="text-xs text-slate-400 font-medium block">변환할 페이지 범위</span>
                  <div className="flex bg-slate-950 p-1 rounded-lg border border-slate-800">
                    <button
                      id="btn-range-all"
                      onClick={() => setPageRangeMode('all')}
                      className={`flex-1 text-xs py-2 font-medium rounded-md transition-all duration-200 ${
                        pageRangeMode === 'all'
                          ? 'bg-slate-800 text-white font-semibold shadow-sm'
                          : 'text-slate-400 hover:text-slate-200'
                      }`}
                    >
                      전체 페이지 ({totalPages})
                    </button>
                    <button
                      id="btn-range-custom"
                      onClick={() => setPageRangeMode('custom')}
                      className={`flex-1 text-xs py-2 font-medium rounded-md transition-all duration-200 ${
                        pageRangeMode === 'custom'
                          ? 'bg-slate-800 text-white font-semibold shadow-sm'
                          : 'text-slate-400 hover:text-slate-200'
                      }`}
                    >
                      직접 입력
                    </button>
                  </div>

                  {pageRangeMode === 'custom' && (
                    <div className="flex items-center gap-2 animate-slide-down bg-slate-950 p-3 rounded-xl border border-slate-800" id="custom-range-inputs">
                      <div className="flex-1 space-y-1">
                        <label className="text-[10px] text-slate-500 font-semibold block">시작 페이지</label>
                        <input
                          id="input-start-page"
                          type="number"
                          min={1}
                          max={totalPages}
                          value={startPage}
                          onChange={(e) => setStartPage(Math.max(1, Math.min(totalPages, parseInt(e.target.value) || 1)))}
                          className="w-full bg-slate-900 border border-slate-800 rounded-lg px-2.5 py-1.5 text-xs text-slate-200 focus:outline-none focus:border-indigo-500"
                        />
                      </div>
                      <span className="text-slate-600 mt-4 text-xs font-semibold">~</span>
                      <div className="flex-1 space-y-1">
                        <label className="text-[10px] text-slate-500 font-semibold block">종료 페이지</label>
                        <input
                          id="input-end-page"
                          type="number"
                          min={1}
                          max={totalPages}
                          value={endPage}
                          onChange={(e) => setEndPage(Math.max(1, Math.min(totalPages, parseInt(e.target.value) || 1)))}
                          className="w-full bg-slate-900 border border-slate-800 rounded-lg px-2.5 py-1.5 text-xs text-slate-200 focus:outline-none focus:border-indigo-500"
                        />
                      </div>
                    </div>
                  )}
                </div>

                {/* Submit Action */}
                <button
                  id="btn-convert-pdf"
                  onClick={startConversion}
                  disabled={isProcessing}
                  className="w-full mt-2 py-3 bg-gradient-to-r from-indigo-500 to-purple-600 hover:from-indigo-600 hover:to-purple-700 disabled:from-slate-800 disabled:to-slate-800 text-sm font-semibold rounded-xl text-white shadow-lg hover:shadow-indigo-500/20 transition-all duration-200 flex items-center justify-center gap-2"
                >
                  {isProcessing ? (
                    <>
                      <RefreshCw className="w-4 h-4 animate-spin" />
                      JPG 파일로 변환 중 ({progress.current}/{progress.total})
                    </>
                  ) : (
                    <>
                      <Sparkles className="w-4 h-4" />
                      JPG 이미지로 변환하기
                    </>
                  )}
                </button>
              </div>
            </div>
          )}

          {/* Progress Tracker bar */}
          {isProcessing && (
            <div className="bg-slate-900 border border-slate-800 rounded-2xl p-5 shadow-xl space-y-3" id="pdf-progress-card">
              <div className="flex justify-between items-center text-xs">
                <span className="text-slate-400 font-medium">변환 처리율</span>
                <span className="text-indigo-400 font-bold">{Math.round((progress.current / progress.total) * 100)}% 완료</span>
              </div>
              <div className="w-full bg-slate-950 rounded-full h-2 overflow-hidden border border-slate-800">
                <div 
                  className="bg-gradient-to-r from-indigo-500 to-purple-500 h-full rounded-full transition-all duration-300"
                  style={{ width: `${(progress.current / progress.total) * 100}%` }}
                ></div>
              </div>
              <p className="text-[10px] text-slate-500 text-center">페이지 {progress.current} / {progress.total}를 변환하는 중입니다...</p>
            </div>
          )}
        </div>

        {/* Output Grid */}
        <div className="lg:col-span-7">
          <div className="bg-slate-900 border border-slate-800 rounded-2xl p-6 shadow-xl min-h-[500px] flex flex-col" id="pdf-output-card">
            <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between pb-4 border-b border-slate-800 mb-6 gap-3">
              <div className="flex items-center gap-2">
                <h3 className="font-semibold text-slate-200">변환된 이미지 결과 목록</h3>
                {convertedPages.length > 0 && (
                  <span className="text-xs bg-emerald-500/10 text-emerald-400 font-semibold px-2 py-0.5 rounded-full border border-emerald-500/20">
                    {convertedPages.length}개 완료
                  </span>
                )}
              </div>

              {/* Bulk Actions */}
              {convertedPages.length > 0 && (
                <button
                  id="btn-download-all-zip"
                  onClick={downloadAllAsZip}
                  className="px-4 py-2 bg-emerald-600 hover:bg-emerald-700 text-xs font-semibold rounded-lg text-white shadow-md hover:shadow-emerald-500/15 transition-all duration-200 flex items-center gap-1.5 self-start sm:self-auto animate-pulse"
                >
                  <FileDown className="w-3.5 h-3.5" />
                  ZIP 압축파일로 일괄 다운로드
                </button>
              )}
            </div>

            {/* Displaying images */}
            {convertedPages.length === 0 ? (
              <div className="flex-grow flex flex-col items-center justify-center text-slate-500 py-16" id="pdf-empty-state">
                <div className="p-4 bg-slate-950 border border-slate-800 rounded-full shadow-inner mb-4">
                  <Grid className="w-10 h-10 text-slate-700" />
                </div>
                <p className="text-sm font-medium text-slate-300">변환 완료된 이미지가 여기에 표시됩니다.</p>
                <p className="text-xs text-slate-500 mt-1">왼쪽에서 PDF 파일을 선택하고 변환 버튼을 눌러주세요.</p>
              </div>
            ) : (
              <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-2 gap-5" id="pdf-results-grid">
                {convertedPages.map((page) => (
                  <div 
                    key={page.pageNumber} 
                    className="group bg-slate-950 border border-slate-800/80 rounded-xl overflow-hidden shadow-lg flex flex-col transition-all duration-300 hover:border-slate-700"
                    id={`page-card-${page.pageNumber}`}
                  >
                    <div className="relative aspect-[3/4] bg-slate-900 flex items-center justify-center overflow-hidden">
                      <img 
                        src={page.dataUrl} 
                        alt={`Page ${page.pageNumber}`} 
                        className="max-h-full max-w-full object-contain p-1 group-hover:scale-[1.03] transition-transform duration-300"
                      />
                      <div className="absolute top-2.5 left-2.5 bg-slate-950/90 backdrop-blur border border-slate-800 text-[10px] font-semibold text-indigo-300 px-2.5 py-1 rounded-md shadow-md">
                        PAGE {page.pageNumber}
                      </div>
                    </div>
                    <div className="p-3 border-t border-slate-900 flex items-center justify-between bg-slate-900/30">
                      <div className="space-y-0.5">
                        <span className="text-xs text-slate-300 font-semibold block">JPEG 이미지</span>
                        <span className="text-[10px] text-slate-500 block">해상도 {scale}x 가속</span>
                      </div>
                      <a
                        id={`btn-download-page-${page.pageNumber}`}
                        href={page.dataUrl}
                        download={`${file?.name.replace(/\.[^/.]+$/, "")}_page_${page.pageNumber}.jpg`}
                        className="p-2 bg-indigo-600 hover:bg-indigo-700 text-white rounded-lg transition-colors shadow-sm"
                        title={`Page ${page.pageNumber} 다운로드`}
                      >
                        <Download className="w-4 h-4" />
                      </a>
                    </div>
                  </div>
                ))}
              </div>
            )}
          </div>
        </div>
      </div>
    </div>
  );
}

// ==========================================
// 1.5. PDF PAGES SPLITTER COMPONENT
// ==========================================
interface SplitResultItem {
  id: string;
  name: string;
  pageRangeText: string;
  pageCount: number;
  blob: Blob;
  downloadUrl: string;
  size: number;
}

interface SplitRange {
  id: string;
  start: number;
  end: number;
}

function PdfSplitter({ onAddToHistory }: { onAddToHistory: (item: Omit<HistoryItem, 'id' | 'timestamp'>) => void }) {
  const [file, setFile] = useState<File | null>(null);
  const [totalPages, setTotalPages] = useState<number>(0);
  const [isProcessing, setIsProcessing] = useState<boolean>(false);
  const [dragActive, setDragActive] = useState<boolean>(false);
  
  // Splitting control (iLovePDF Style)
  const [splitMode, setSplitMode] = useState<'range' | 'fixed'>('range');
  const [fixedInterval, setFixedInterval] = useState<number>(1);
  
  // Interactive Range list
  const [rangesList, setRangesList] = useState<SplitRange[]>([
    { id: '1', start: 1, end: 1 }
  ]);
  
  const [splitResults, setSplitResults] = useState<SplitResultItem[]>([]);
  const [progress, setProgress] = useState<{ current: number; total: number }>({ current: 0, total: 0 });
  const fileInputRef = useRef<HTMLInputElement>(null);

  // Real-time page thumbnails
  const [pdfPreviewPages, setPdfPreviewPages] = useState<string[]>([]);
  const [isPreviewLoading, setIsPreviewLoading] = useState<boolean>(false);

  // Helper to load file and get page count
  const loadPdfInfo = async (selectedFile: File) => {
    if (!selectedFile || selectedFile.type !== 'application/pdf') {
      alert('올바른 PDF 파일을 업로드해 주세요.');
      return;
    }
    setFile(selectedFile);
    setSplitResults([]);
    setPdfPreviewPages([]);
    setIsProcessing(true);
    setIsPreviewLoading(true);
    
    try {
      const arrayBuffer = await selectedFile.arrayBuffer();
      const pdfDoc = await PDFDocument.load(arrayBuffer);
      const count = pdfDoc.getPageCount();
      setTotalPages(count);
      
      // Initialize with first range spanning the entire PDF
      setRangesList([{ id: Math.random().toString(36).substring(2, 9), start: 1, end: count }]);

      // Generate thumbnails using pdfjsLib
      if (typeof window !== 'undefined' && pdfjsLib) {
        const fileReader = new FileReader();
        fileReader.onload = async function () {
          try {
            const typedarray = new Uint8Array(this.result as ArrayBuffer);
            const loadingTask = pdfjsLib.getDocument({ data: typedarray });
            const pdf = await loadingTask.promise;
            const previewsCount = Math.min(24, count); // Limit to 24 for excellent performance
            const previewUrls: string[] = [];
            
            for (let i = 1; i <= previewsCount; i++) {
              const page = await pdf.getPage(i);
              const viewport = page.getViewport({ scale: 0.35 });
              const canvas = document.createElement('canvas');
              const context = canvas.getContext('2d');
              if (context) {
                canvas.height = viewport.height;
                canvas.width = viewport.width;
                await page.render({ canvasContext: context, viewport }).promise;
                previewUrls.push(canvas.toDataURL('image/jpeg', 0.8));
              }
            }
            setPdfPreviewPages(previewUrls);
          } catch (err) {
            console.error('Error generating PDF splitter previews:', err);
          } finally {
            setIsPreviewLoading(false);
          }
        };
        fileReader.readAsArrayBuffer(selectedFile);
      } else {
        setIsPreviewLoading(false);
      }
    } catch (err) {
      console.error(err);
      alert('PDF 정보를 가져오는 데 실패했습니다. 파일이 암호화되어 있거나 손상되었을 수 있습니다.');
      setFile(null);
      setIsPreviewLoading(false);
    } finally {
      setIsProcessing(false);
    }
  };

  const handleDrag = (e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    if (e.type === 'dragenter' || e.type === 'dragover') {
      setDragActive(true);
    } else if (e.type === 'dragleave') {
      setDragActive(false);
    }
  };

  const handleDrop = (e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setDragActive(false);
    if (e.dataTransfer.files && e.dataTransfer.files[0]) {
      loadPdfInfo(e.dataTransfer.files[0]);
    }
  };

  const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    if (e.target.files && e.target.files[0]) {
      loadPdfInfo(e.target.files[0]);
    }
  };

  const triggerFileInput = () => {
    fileInputRef.current?.click();
  };

  const resetState = () => {
    setFile(null);
    setTotalPages(0);
    setSplitResults([]);
    setPdfPreviewPages([]);
    setProgress({ current: 0, total: 0 });
    setRangesList([{ id: '1', start: 1, end: 1 }]);
    if (fileInputRef.current) {
      fileInputRef.current.value = '';
    }
  };

  // Add a new split range
  const addRange = () => {
    const lastRange = rangesList[rangesList.length - 1];
    let nextStart = 1;
    if (lastRange) {
      nextStart = Math.min(lastRange.end + 1, totalPages);
    }
    const nextEnd = Math.min(nextStart + 2, totalPages);
    setRangesList([
      ...rangesList,
      {
        id: Math.random().toString(36).substring(2, 9),
        start: nextStart,
        end: nextEnd
      }
    ]);
  };

  // Remove a split range
  const removeRange = (id: string) => {
    if (rangesList.length <= 1) return;
    setRangesList(prev => prev.filter(r => r.id !== id));
  };

  // Update specific range start/end page
  const updateRangeValue = (id: string, field: 'start' | 'end', value: number) => {
    setRangesList(prev => prev.map(r => {
      if (r.id === id) {
        const parsedVal = Math.max(1, Math.min(totalPages, value));
        const updated = { ...r, [field]: parsedVal };
        // Validation boundary checks
        if (field === 'start' && updated.start > updated.end) {
          updated.end = updated.start;
        } else if (field === 'end' && updated.end < updated.start) {
          updated.start = updated.end;
        }
        return updated;
      }
      return r;
    }));
  };

  // Compile active ranges based on the current mode
  const activeRanges = splitMode === 'fixed'
    ? (() => {
        const interval = Math.max(1, fixedInterval);
        const list: { start: number; end: number }[] = [];
        for (let i = 1; i <= totalPages; i += interval) {
          list.push({
            start: i,
            end: Math.min(i + interval - 1, totalPages)
          });
        }
        return list;
      })()
    : rangesList.map(r => ({ start: r.start, end: r.end }));

  // Execute PDF division algorithms on-device
  const executeSplit = async () => {
    if (!file || activeRanges.length === 0) return;
    setIsProcessing(true);
    setProgress({ current: 0, total: activeRanges.length });
    
    try {
      const arrayBuffer = await file.arrayBuffer();
      const originalPdf = await PDFDocument.load(arrayBuffer);
      const results: SplitResultItem[] = [];

      for (let i = 0; i < activeRanges.length; i++) {
        const { start, end } = activeRanges[i];
        const indices: number[] = [];
        for (let p = start; p <= end; p++) {
          indices.push(p - 1);
        }

        const newPdf = await PDFDocument.create();
        const copiedPages = await newPdf.copyPages(originalPdf, indices);
        copiedPages.forEach(page => newPdf.addPage(page));
        
        const newPdfBytes = await newPdf.save();
        const blob = new Blob([newPdfBytes], { type: 'application/pdf' });
        const url = URL.createObjectURL(blob);
        const fileNameWithoutExt = file.name.replace(/\.[^/.]+$/, "");
        
        results.push({
          id: Math.random().toString(36).substring(2, 9),
          name: `${fileNameWithoutExt}_split_p${start}_to_p${end}.pdf`,
          pageRangeText: start === end ? `${start}페이지` : `${start} ~ ${end}페이지`,
          pageCount: indices.length,
          blob: blob,
          downloadUrl: url,
          size: newPdfBytes.length
        });

        setProgress(prev => ({ ...prev, current: i + 1 }));
      }

      setSplitResults(results);

      const totalSplitsSize = results.reduce((acc, r) => acc + r.size, 0);
      onAddToHistory({
        fileName: `${file.name} (분할 완료: ${results.length}개 파일)`,
        type: 'pdf',
        originalSize: file.size,
        optimizedSize: totalSplitsSize,
        dataUrl: '',
        format: 'PDF (Split)'
      });

    } catch (err) {
      console.error(err);
      alert('PDF 분할 도중 에러가 발생했습니다. 파일 무결성을 재확인바랍니다.');
    } finally {
      setIsProcessing(false);
    }
  };

  const downloadAllAsZip = async () => {
    if (splitResults.length === 0) return;
    setIsProcessing(true);
    try {
      const zip = new JSZip();
      const baseFolderName = file ? file.name.replace(/\.[^/.]+$/, "") : "split_pdfs";
      const folder = zip.folder(baseFolderName);
      
      splitResults.forEach(item => {
        folder?.file(item.name, item.blob);
      });

      const zipBlob = await zip.generateAsync({ type: 'blob' });
      const url = URL.createObjectURL(zipBlob);
      
      const link = document.createElement('a');
      link.href = url;
      link.download = `${baseFolderName}_split_files.zip`;
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
    } catch (err) {
      console.error(err);
      alert('ZIP 압축 파일 생성 중 실패하였습니다.');
    } finally {
      setIsProcessing(false);
    }
  };

  // Determine colors of different range groups to visualize pages beautifully
  const getRangeColorClasses = (pageIndex: number) => {
    // Find first range this page belongs to
    const rIdx = activeRanges.findIndex(r => pageIndex >= r.start && pageIndex <= r.end);
    if (rIdx === -1) return { border: 'border-slate-200', bg: 'bg-slate-100 text-slate-500', name: null };
    
    // Aesthetic theme colors matched for ranges
    const colors = [
      { border: 'border-rose-500 ring-2 ring-rose-500/20', bg: 'bg-rose-500 text-white', name: `범위 ${rIdx + 1}` },
      { border: 'border-indigo-500 ring-2 ring-indigo-500/20', bg: 'bg-indigo-500 text-white', name: `범위 ${rIdx + 1}` },
      { border: 'border-emerald-500 ring-2 ring-emerald-500/20', bg: 'bg-emerald-500 text-white', name: `범위 ${rIdx + 1}` },
      { border: 'border-amber-500 ring-2 ring-amber-500/20', bg: 'bg-amber-500 text-white', name: `범위 ${rIdx + 1}` },
      { border: 'border-cyan-500 ring-2 ring-cyan-500/20', bg: 'bg-cyan-500 text-white', name: `범위 ${rIdx + 1}` },
      { border: 'border-violet-500 ring-2 ring-violet-500/20', bg: 'bg-violet-500 text-white', name: `범위 ${rIdx + 1}` }
    ];
    return colors[rIdx % colors.length];
  };

  return (
    <div className="w-full">
      {/* 1. File Upload Selector Stage (iLovePDF Style) */}
      {!file && (
        <div 
          onDragEnter={handleDrag}
          onDragOver={handleDrag}
          onDragLeave={handleDrag}
          onDrop={handleDrop}
          onClick={triggerFileInput}
          className={`relative max-w-4xl mx-auto border-2 border-dashed rounded-3xl p-16 text-center flex flex-col items-center justify-center transition-all cursor-pointer ${
            dragActive 
              ? 'border-red-500 bg-red-50/40' 
              : 'border-slate-300 hover:border-red-400 bg-white shadow-sm hover:shadow-md'
          }`}
          style={{ minHeight: '440px' }}
        >
          <input 
            ref={fileInputRef}
            type="file"
            accept=".pdf"
            onChange={handleFileChange}
            className="hidden"
          />
          <div className="w-24 h-24 bg-red-50 text-[#ff3a44] rounded-3xl flex items-center justify-center mb-6 shadow-sm transition-transform hover:scale-105">
            <UploadCloud className="w-12 h-12" />
          </div>
          <h2 className="text-2xl font-black text-slate-900 tracking-tight mb-2">
            PDF 페이지 분할 (Split)
          </h2>
          <p className="text-sm text-slate-500 max-w-lg mb-8 leading-relaxed">
            PDF의 특정 범위를 선택하여 별도의 파일로 내보내거나, 고정된 장수 간격으로 모든 페이지를 한 번에 자동 해체합니다.
          </p>
          <button 
            type="button"
            className="px-8 py-4 bg-[#ff3a44] hover:bg-[#e52230] text-white text-base font-extrabold rounded-2xl shadow-lg hover:shadow-red-500/20 transition-all duration-200 transform hover:-translate-y-0.5 cursor-pointer flex items-center gap-2"
          >
            PDF 파일 선택
          </button>
          <p className="text-xs text-slate-400 mt-5 font-medium">
            또는 여기에 PDF 파일을 드래그하여 놓으세요 (100% 로컬 연산 안전 보장)
          </p>
        </div>
      )}

      {/* 2. Dual Column Interactive Division Layout (iLovePDF Style) */}
      {file && splitResults.length === 0 && (
        <div className="grid grid-cols-1 lg:grid-cols-12 gap-8 items-start">
          
          {/* LEFT: Live PDF Storyboard Workspace (iLovePDF aesthetic page grid) */}
          <div className="lg:col-span-8 space-y-4">
            <div className="bg-slate-100 border border-slate-200 rounded-2xl p-6 min-h-[500px] shadow-inner relative">
              <div className="flex items-center justify-between border-b border-slate-200/80 pb-4 mb-6">
                <div>
                  <h3 className="text-sm font-bold text-slate-800 flex items-center gap-2">
                    <Grid className="w-4 h-4 text-[#ff3a44]" />
                    PDF 페이지 스토리보드
                  </h3>
                  <p className="text-[11px] text-slate-500 mt-0.5">
                    현재 적용된 범위 분할 구획이 각 페이지 카드에 실시간 적용되어 강조됩니다.
                  </p>
                </div>
                <div className="bg-white/80 backdrop-blur border border-slate-200/60 px-3 py-1 rounded-full text-xs font-semibold text-slate-600">
                  총 <span className="text-[#ff3a44] font-bold">{totalPages}</span> 페이지
                </div>
              </div>

              {isPreviewLoading && (
                <div className="absolute inset-0 bg-slate-100/70 backdrop-blur-sm flex flex-col items-center justify-center z-10 rounded-2xl">
                  <RefreshCw className="w-8 h-8 text-[#ff3a44] animate-spin mb-3" />
                  <p className="text-xs font-bold text-slate-600">PDF 원본의 실제 썸네일 이미지를 가속 렌더링 중입니다...</p>
                </div>
              )}

              {/* Grid of Interactive Pages */}
              <div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-4 max-h-[560px] overflow-y-auto pr-1">
                {Array.from({ length: totalPages }).map((_, idx) => {
                  const pageNum = idx + 1;
                  const rangeConfig = getRangeColorClasses(pageNum);
                  const hasThumbnail = pdfPreviewPages[idx];

                  return (
                    <div 
                      key={idx} 
                      className={`bg-white rounded-xl p-2.5 border transition-all relative flex flex-col justify-between ${rangeConfig.border} shadow-sm group`}
                    >
                      {/* Range Badge overlay */}
                      {rangeConfig.name && (
                        <div className={`absolute top-2.5 left-2.5 z-10 text-[9px] font-black px-2 py-0.5 rounded shadow-sm ${rangeConfig.bg}`}>
                          {rangeConfig.name}
                        </div>
                      )}

                      {/* Thumbnail frame */}
                      <div className="w-full aspect-[3/4] bg-slate-50 rounded-lg border border-slate-100 flex items-center justify-center overflow-hidden mb-2 relative">
                        {hasThumbnail ? (
                          <img 
                            src={pdfPreviewPages[idx]} 
                            alt={`page-${pageNum}`} 
                            className="w-full h-full object-contain"
                            referrerPolicy="no-referrer"
                          />
                        ) : (
                          <div className="flex flex-col items-center justify-center text-slate-300">
                            <FileText className="w-8 h-8 stroke-[1.2]" />
                            <span className="text-[9px] text-slate-400 font-bold mt-1">Page {pageNum}</span>
                          </div>
                        )}
                        <div className="absolute inset-0 bg-black/0 group-hover:bg-black/5 transition-colors pointer-events-none"></div>
                      </div>

                      {/* Footer page identifier */}
                      <div className="flex items-center justify-between px-1">
                        <span className="text-[10px] font-black text-slate-700">페이지 {pageNum}</span>
                        <span className="text-[9px] font-medium text-slate-400 font-mono">#{pageNum}</span>
                      </div>
                    </div>
                  );
                })}
              </div>
            </div>
            
            {/* loaded file info panel */}
            <div className="bg-white border border-slate-200 rounded-xl p-4 flex items-center justify-between">
              <div className="flex items-center gap-3 overflow-hidden">
                <div className="p-2 bg-red-50 text-[#ff3a44] rounded-lg">
                  <FileText className="w-5 h-5" />
                </div>
                <div className="overflow-hidden">
                  <h4 className="text-xs font-bold text-slate-800 truncate max-w-[280px] sm:max-w-[400px]">{file.name}</h4>
                  <p className="text-[10px] text-slate-400 mt-0.5">{(file.size / 1024 / 1024).toFixed(2)} MB • 총 {totalPages}페이지</p>
                </div>
              </div>
              <button 
                onClick={resetState}
                className="text-xs font-bold text-slate-400 hover:text-rose-500 px-3 py-1.5 hover:bg-rose-50 rounded-lg transition-all"
              >
                파일 제거
              </button>
            </div>
          </div>

          {/* RIGHT: Settings Sidebar panel (Exactly iLovePDF structural match) */}
          <div className="lg:col-span-4 sticky top-6">
            <div className="bg-white border border-slate-200 rounded-2xl shadow-md overflow-hidden flex flex-col">
              {/* Header Info */}
              <div className="bg-slate-50 border-b border-slate-200 p-5">
                <h3 className="text-sm font-extrabold text-slate-900 uppercase tracking-wider flex items-center gap-2">
                  <Sliders className="w-4 h-4 text-[#ff3a44]" />
                  분할 설정 (Split settings)
                </h3>
              </div>

              {/* Setting Mode Tabs */}
              <div className="grid grid-cols-2 border-b border-slate-200">
                <button
                  type="button"
                  onClick={() => setSplitMode('range')}
                  className={`text-xs font-bold py-3.5 transition-all flex items-center justify-center gap-2 cursor-pointer ${
                    splitMode === 'range'
                      ? 'border-b-2 border-red-500 text-slate-900 bg-white font-extrabold'
                      : 'text-slate-500 hover:text-slate-800 bg-slate-50/50 hover:bg-slate-50'
                  }`}
                >
                  <Columns className="w-3.5 h-3.5" />
                  범위 지정 분할
                </button>
                <button
                  type="button"
                  onClick={() => setSplitMode('fixed')}
                  className={`text-xs font-bold py-3.5 transition-all flex items-center justify-center gap-2 cursor-pointer ${
                    splitMode === 'fixed'
                      ? 'border-b-2 border-red-500 text-slate-900 bg-white font-extrabold'
                      : 'text-slate-500 hover:text-slate-800 bg-slate-50/50 hover:bg-slate-50'
                  }`}
                >
                  <Split className="w-3.5 h-3.5" />
                  고정 간격 분할
                </button>
              </div>

              {/* Mode-specific configuration blocks */}
              <div className="p-5 space-y-4">
                {splitMode === 'range' ? (
                  <div className="space-y-4">
                    <div className="flex justify-between items-center">
                      <span className="text-xs font-extrabold text-slate-800">범위 목록 (Ranges)</span>
                      <span className="text-[10px] text-slate-400 font-semibold">동적 세그먼트 추출</span>
                    </div>

                    {/* Scrollable range segments list */}
                    <div className="space-y-3.5 max-h-[280px] overflow-y-auto pr-1">
                      {rangesList.map((range, index) => (
                        <div 
                          key={range.id}
                          className="bg-slate-50 border border-slate-200 rounded-xl p-3.5 relative shadow-sm"
                        >
                          <div className="flex items-center justify-between mb-2">
                            <span className="text-xs font-bold text-slate-700 flex items-center gap-1.5">
                              <span className="w-2.5 h-2.5 rounded-full bg-rose-500 inline-block"></span>
                              범위 {index + 1}
                            </span>
                            {rangesList.length > 1 && (
                              <button
                                type="button"
                                onClick={() => removeRange(range.id)}
                                className="text-[10px] text-slate-400 hover:text-rose-500 font-bold"
                              >
                                삭제
                              </button>
                            )}
                          </div>

                          <div className="grid grid-cols-2 gap-3">
                            <div className="space-y-1">
                              <label className="text-[10px] text-slate-400 font-medium block">시작 페이지</label>
                              <input
                                type="number"
                                min="1"
                                max={totalPages}
                                value={range.start}
                                onChange={(e) => updateRangeValue(range.id, 'start', parseInt(e.target.value) || 1)}
                                className="w-full bg-white border border-slate-200 rounded-lg py-1 px-2.5 text-xs font-bold text-slate-800 focus:border-[#ff3a44] focus:outline-none text-center"
                              />
                            </div>
                            <div className="space-y-1">
                              <label className="text-[10px] text-slate-400 font-medium block">종료 페이지</label>
                              <input
                                type="number"
                                min="1"
                                max={totalPages}
                                value={range.end}
                                onChange={(e) => updateRangeValue(range.id, 'end', parseInt(e.target.value) || 1)}
                                className="w-full bg-white border border-slate-200 rounded-lg py-1 px-2.5 text-xs font-bold text-slate-800 focus:border-[#ff3a44] focus:outline-none text-center"
                              />
                            </div>
                          </div>
                        </div>
                      ))}
                    </div>

                    {/* Add Range helper */}
                    <button
                      type="button"
                      onClick={addRange}
                      disabled={rangesList[rangesList.length - 1]?.end >= totalPages}
                      className="w-full py-2 bg-white hover:bg-slate-50 border border-slate-200 border-dashed rounded-xl text-xs font-bold text-slate-600 hover:text-slate-800 transition-all cursor-pointer flex items-center justify-center gap-1 disabled:opacity-40 disabled:pointer-events-none"
                    >
                      + 새 범위 추가
                    </button>
                  </div>
                ) : (
                  <div className="space-y-3.5 bg-slate-50 border border-slate-200 p-4 rounded-xl">
                    <div className="flex justify-between items-center">
                      <label className="text-xs text-slate-700 font-bold">장수 간격 설정 (Interval)</label>
                      <span className="text-xs font-black text-[#ff3a44]">{fixedInterval}장 단위</span>
                    </div>

                    <div className="flex items-center gap-2">
                      <button
                        type="button"
                        onClick={() => setFixedInterval(prev => Math.max(1, prev - 1))}
                        className="p-2 bg-white hover:bg-slate-100 border border-slate-200 rounded-lg text-slate-600 text-xs font-bold cursor-pointer transition-colors"
                      >
                        -1장
                      </button>
                      <input
                        type="number"
                        min="1"
                        max={totalPages}
                        value={fixedInterval}
                        onChange={(e) => setFixedInterval(Math.max(1, Math.min(totalPages, parseInt(e.target.value) || 1)))}
                        className="flex-grow bg-white border border-slate-200 rounded-lg text-center text-xs font-black text-slate-800 py-1.5 focus:border-[#ff3a44] focus:outline-none"
                      />
                      <button
                        type="button"
                        onClick={() => setFixedInterval(prev => Math.min(totalPages, prev + 1))}
                        className="p-2 bg-white hover:bg-slate-100 border border-slate-200 rounded-lg text-slate-600 text-xs font-bold cursor-pointer transition-colors"
                      >
                        +1장
                      </button>
                    </div>

                    {/* Quick presets */}
                    <div className="grid grid-cols-4 gap-1 pt-2">
                      {[1, 2, 5, 10].map(val => (
                        <button
                          key={val}
                          type="button"
                          onClick={() => setFixedInterval(Math.min(totalPages, val))}
                          disabled={val > totalPages}
                          className={`text-[10px] py-1.5 rounded-lg border font-bold transition-all cursor-pointer ${
                            fixedInterval === val 
                              ? 'bg-red-500 border-red-500 text-white shadow-sm' 
                              : 'bg-white border-slate-200 text-slate-500 hover:bg-slate-50 hover:text-slate-700'
                          } disabled:opacity-30 disabled:pointer-events-none`}
                        >
                          {val}장씩
                        </button>
                      ))}
                    </div>
                  </div>
                )}

                {/* Info summary card */}
                <div className="p-3 bg-red-50/40 border border-red-100 rounded-xl text-[11px] text-slate-600 leading-relaxed space-y-1">
                  <p className="font-bold text-[#ff3a44]">💡 이 알고리즘의 동작 요약:</p>
                  <p>총 <span className="font-bold text-slate-800">{activeRanges.length}</span>개의 분할 문서 조각이 브라우저 내부에서 즉각 샌드박스로 가공 분배됩니다.</p>
                </div>

                {/* Big execution CTA action button */}
                <button
                  type="button"
                  onClick={executeSplit}
                  disabled={isProcessing || activeRanges.length === 0}
                  className="w-full py-4 bg-[#ff3a44] hover:bg-[#e52230] disabled:bg-slate-200 text-white font-extrabold rounded-2xl text-sm transition-all shadow-md hover:shadow-red-500/10 cursor-pointer disabled:cursor-not-allowed flex items-center justify-center gap-2"
                >
                  {isProcessing ? (
                    <>
                      <RefreshCw className="w-4 h-4 animate-spin shrink-0" />
                      연산 중 ({progress.current}/{progress.total})
                    </>
                  ) : (
                    <>
                      <Split className="w-4 h-4" />
                      PDF 분할 실행하기 →
                    </>
                  )}
                </button>
              </div>
            </div>
          </div>
        </div>
      )}

      {/* 3. Division Results Success Display Page (iLovePDF Style) */}
      {file && splitResults.length > 0 && (
        <div className="max-w-3xl mx-auto space-y-6">
          <div className="bg-white border border-slate-200 rounded-3xl p-8 text-center shadow-sm">
            <div className="w-16 h-16 bg-emerald-50 text-emerald-500 rounded-full flex items-center justify-center mx-auto mb-4">
              <FileCheck className="w-8 h-8" />
            </div>
            <h2 className="text-xl font-extrabold text-slate-900 tracking-tight">PDF 분할이 완료되었습니다!</h2>
            <p className="text-xs text-slate-500 mt-1 max-w-md mx-auto">
              성공적으로 {splitResults.length}개의 조각 파일이 로컬 캐시에 준비되었습니다. ZIP으로 내려받거나 개별로 직접 내려받으세요.
            </p>

            <div className="mt-8 flex flex-col sm:flex-row items-center justify-center gap-3">
              <button
                onClick={downloadAllAsZip}
                className="w-full sm:w-auto px-8 py-3.5 bg-[#ff3a44] hover:bg-[#e52230] text-white text-sm font-extrabold rounded-xl shadow-md hover:shadow-red-500/15 transition-all cursor-pointer flex items-center justify-center gap-2"
              >
                <FileDown className="w-4 h-4" />
                분할 파일들 한 번에 다운로드 (ZIP)
              </button>
              <button
                onClick={resetState}
                className="w-full sm:w-auto px-6 py-3.5 bg-slate-100 hover:bg-slate-200 text-slate-700 text-sm font-bold rounded-xl transition-all cursor-pointer"
              >
                다른 파일 분할하기
              </button>
            </div>
          </div>

          {/* Table list of individual divided range outputs */}
          <div className="bg-white border border-slate-200 rounded-3xl p-6 shadow-sm">
            <h3 className="text-xs font-bold text-slate-800 uppercase tracking-wider mb-4">
              조각 파일 리스트 ({splitResults.length}개)
            </h3>
            
            <div className="divide-y divide-slate-100 max-h-[380px] overflow-y-auto pr-1">
              {splitResults.map((item, index) => (
                <div key={item.id} className="py-3 flex items-center justify-between gap-4">
                  <div className="flex items-center gap-3 overflow-hidden">
                    <span className="w-6 h-6 rounded-full bg-slate-100 text-slate-600 font-mono text-[10px] font-black flex items-center justify-center">
                      {index + 1}
                    </span>
                    <div className="overflow-hidden">
                      <h4 className="text-xs font-bold text-slate-800 truncate max-w-[200px] sm:max-w-[400px]">
                        {item.name}
                      </h4>
                      <p className="text-[10px] text-slate-400 mt-0.5">
                        {item.pageRangeText} • {item.pageCount}개 페이지 • {(item.size / 1024).toFixed(1)} KB
                      </p>
                    </div>
                  </div>
                  <a
                    href={item.downloadUrl}
                    download={item.name}
                    className="p-2 bg-slate-50 hover:bg-red-50 text-slate-500 hover:text-[#ff3a44] border border-slate-200 hover:border-red-200 rounded-lg transition-all cursor-pointer shrink-0"
                    title="다운로드"
                  >
                    <Download className="w-3.5 h-3.5" />
                  </a>
                </div>
              ))}
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

// ==========================================
// 2. IMAGE FORMAT & RESIZE OPTIMIZER COMPONENT
// ==========================================
function ImageOptimizer({ onAddToHistory }: { onAddToHistory: (item: Omit<HistoryItem, 'id' | 'timestamp'>) => void }) {
  const [originalSrc, setOriginalSrc] = useState<string>('');
  const [originalName, setOriginalName] = useState<string>('');
  const [originalSize, setOriginalSize] = useState<number>(0);
  const [originalDimensions, setOriginalDimensions] = useState<{ w: number; h: number }>({ w: 0, h: 0 });

  const [outputFormat, setOutputFormat] = useState<string>('image/jpeg');
  const [resizeMode, setResizeMode] = useState<'custom' | 'scale'>('scale');
  const [scalePercentage, setScalePercentage] = useState<number>(100);
  const [customWidth, setCustomWidth] = useState<number>(0);
  const [customHeight, setCustomHeight] = useState<number>(0);
  const [aspectRatioLocked, setAspectRatioLocked] = useState<boolean>(true);
  const [quality, setQuality] = useState<number>(85); // 0-100

  const [optimizedSrc, setOptimizedSrc] = useState<string>('');
  const [optimizedSize, setOptimizedSize] = useState<number>(0);
  const [optimizedDimensions, setOptimizedDimensions] = useState<{ w: number; h: number }>({ w: 0, h: 0 });
  const [isProcessing, setIsProcessing] = useState<boolean>(false);
  const [dragActive, setDragActive] = useState<boolean>(false);

  // Fancy design states
  const [previewMode, setPreviewMode] = useState<'slider' | 'side-by-side'>('slider');
  const [sliderPosition, setSliderPosition] = useState<number>(50);
  const [isDragging, setIsDragging] = useState<boolean>(false);
  const [dominantColors, setDominantColors] = useState<string[]>([]);

  const fileInputRef = useRef<HTMLInputElement>(null);
  const sliderContainerRef = useRef<HTMLDivElement>(null);

  // Premium interactive compression presets
  const presets = [
    { id: 'web-lite', label: '🚀 초고압축 웹 최적화', format: 'image/webp', quality: 55, scale: 80, desc: 'WebP • 55%화질 • 80%비율' },
    { id: 'blog-sns', label: '📸 블로그/SNS 표준', format: 'image/jpeg', quality: 80, scale: 100, desc: 'JPEG • 80%화질 • 100%비율' },
    { id: 'hd-backup', label: '🎨 고선명 WebP 백업', format: 'image/webp', quality: 90, scale: 100, desc: 'WebP • 90%화질 • 100%비율' },
    { id: 'lossless', label: '💾 무손실 PNG 변환', format: 'image/png', quality: 100, scale: 100, desc: 'PNG • 무손실 변환 • 100%비율' }
  ];

  const applyPreset = (p: typeof presets[0]) => {
    setOutputFormat(p.format);
    setResizeMode('scale');
    setScalePercentage(p.scale);
    setQuality(p.quality);
  };

  const handleDownloadOptimized = () => {
    if (!optimizedSrc) return;
    onAddToHistory({
      fileName: `${originalName.replace(/\.[^/.]+$/, "")}_optimized.${extensionMap[outputFormat]}`,
      type: 'image',
      originalSize: originalSize,
      optimizedSize: optimizedSize,
      dataUrl: optimizedSrc,
      format: getFormatLabel(outputFormat)
    });
  };

  const handleDrag = (e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    if (e.type === "dragenter" || e.type === "dragover") {
      setDragActive(true);
    } else if (e.type === "dragleave") {
      setDragActive(false);
    }
  };

  const handleDrop = (e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setDragActive(false);

    if (e.dataTransfer.files && e.dataTransfer.files[0]) {
      const droppedFile = e.dataTransfer.files[0];
      if (droppedFile.type.startsWith('image/')) {
        handleImageSelection(droppedFile);
      } else {
        alert('이미지 파일만 업로드할 수 있습니다.');
      }
    }
  };

  const handleFileInput = (e: React.ChangeEvent<HTMLInputElement>) => {
    if (e.target.files && e.target.files[0]) {
      handleImageSelection(e.target.files[0]);
    }
  };

  const handleImageSelection = (file: File) => {
    setOriginalName(file.name);
    setOriginalSize(file.size);
    setOptimizedSrc('');
    setOptimizedSize(0);
    setDominantColors([]);

    const reader = new FileReader();
    reader.onload = (event) => {
      if (event.target?.result) {
        const src = event.target.result as string;
        setOriginalSrc(src);

        // Load image to get dimensions and sample dominant colors
        const img = new Image();
        img.onload = () => {
          setOriginalDimensions({ w: img.width, h: img.height });
          setCustomWidth(img.width);
          setCustomHeight(img.height);

          // Fast dominant color sampling in canvas
          try {
            const canvas = document.createElement('canvas');
            canvas.width = 50;
            canvas.height = 50;
            const ctx = canvas.getContext('2d');
            if (ctx) {
              ctx.drawImage(img, 0, 0, 50, 50);
              const data = ctx.getImageData(0, 0, 50, 50).data;
              const sampleCoords = [
                { x: 10, y: 10 },
                { x: 35, y: 10 },
                { x: 25, y: 25 },
                { x: 15, y: 35 },
                { x: 35, y: 35 }
              ];
              const sampled = sampleCoords.map(c => {
                const i = (c.y * 50 + c.x) * 4;
                return `rgb(${data[i]}, ${data[i+1]}, ${data[i+2]})`;
              });
              setDominantColors(sampled);
            }
          } catch (err) {
            console.error("Sampling dominant colors failed:", err);
          }
        };
        img.src = src;
      }
    };
    reader.readAsDataURL(file);
  };

  // Calculate new height or width if aspect ratio locked
  const handleWidthChange = (w: number) => {
    setCustomWidth(w);
    if (aspectRatioLocked && originalDimensions.w > 0) {
      const ratio = originalDimensions.h / originalDimensions.w;
      setCustomHeight(Math.round(w * ratio));
    }
  };

  const handleHeightChange = (h: number) => {
    setCustomHeight(h);
    if (aspectRatioLocked && originalDimensions.h > 0) {
      const ratio = originalDimensions.w / originalDimensions.h;
      setCustomWidth(Math.round(h * ratio));
    }
  };

  const startOptimization = () => {
    if (!originalSrc) return;
    setIsProcessing(true);

    setTimeout(() => {
      const img = new Image();
      img.onload = () => {
        let targetWidth = originalDimensions.w;
        let targetHeight = originalDimensions.h;

        if (resizeMode === 'scale') {
          const factor = scalePercentage / 100;
          targetWidth = Math.round(originalDimensions.w * factor);
          targetHeight = Math.round(originalDimensions.h * factor);
        } else {
          targetWidth = customWidth || originalDimensions.w;
          targetHeight = customHeight || originalDimensions.h;
        }

        const canvas = document.createElement('canvas');
        canvas.width = targetWidth;
        canvas.height = targetHeight;
        const ctx = canvas.getContext('2d');

        if (ctx) {
          ctx.drawImage(img, 0, 0, targetWidth, targetHeight);
          
          const formatQuality = quality / 100;
          const dataUrl = canvas.toDataURL(outputFormat, formatQuality);
          setOptimizedSrc(dataUrl);
          setOptimizedDimensions({ w: targetWidth, h: targetHeight });

          // Calculate size from DataURL (approximation)
          const base64Str = dataUrl.split(',')[1];
          const decodedSize = window.atob(base64Str).length;
          setOptimizedSize(decodedSize);
        }
        setIsProcessing(false);
      };
      img.src = originalSrc;
    }, 400); // Small timeout to ensure visual spinner trigger
  };

  // Run automatically when settings change and there's a loaded image
  useEffect(() => {
    if (originalSrc) {
      startOptimization();
    }
  }, [outputFormat, resizeMode, scalePercentage, aspectRatioLocked, quality]);

  // Keep width/height updated if aspect ratio locked and resizeMode toggled
  useEffect(() => {
    if (originalDimensions.w > 0) {
      if (resizeMode === 'custom' && customWidth === originalDimensions.w) {
        handleWidthChange(originalDimensions.w);
      }
    }
  }, [resizeMode]);

  const removeImage = () => {
    setOriginalSrc('');
    setOriginalName('');
    setOriginalSize(0);
    setOriginalDimensions({ w: 0, h: 0 });
    setOptimizedSrc('');
    setOptimizedSize(0);
    setOptimizedDimensions({ w: 0, h: 0 });
    setDominantColors([]);
    if (fileInputRef.current) fileInputRef.current.value = '';
  };

  const getFormatLabel = (mime: string) => {
    switch (mime) {
      case 'image/jpeg': return 'JPG';
      case 'image/png': return 'PNG';
      case 'image/webp': return 'WebP';
      default: return 'JPG';
    }
  };

  const extensionMap: Record<string, string> = {
    'image/jpeg': 'jpg',
    'image/png': 'png',
    'image/webp': 'webp'
  };

  // Drag to compare handlers
  const handleSliderMove = (clientX: number) => {
    if (!sliderContainerRef.current) return;
    const rect = sliderContainerRef.current.getBoundingClientRect();
    const x = clientX - rect.left;
    const position = Math.max(0, Math.min(100, (x / rect.width) * 100));
    setSliderPosition(position);
  };

  const onMouseMove = (e: React.MouseEvent) => {
    if (isDragging || e.buttons === 1) {
      handleSliderMove(e.clientX);
    }
  };

  const onTouchMove = (e: React.TouchEvent) => {
    if (e.touches && e.touches[0]) {
      handleSliderMove(e.touches[0].clientX);
    }
  };

  return (
    <div className="space-y-8 animate-fade-in" id="image-optimizer-container">
      {/* Introduction */}
      <div className="text-center max-w-2xl mx-auto space-y-3">
        <span className="px-3 py-1 bg-indigo-500/10 text-indigo-400 rounded-full text-xs font-semibold border border-indigo-500/20 tracking-wide uppercase inline-block">
          Interactive Image Lab
        </span>
        <h2 className="text-3xl font-extrabold tracking-tight text-white sm:text-4xl" id="image-title">
          이미지 규격 & 포맷 조절 스튜디오
        </h2>
        <p className="text-slate-400 text-sm leading-relaxed">
          실시간 분할 슬라이더를 통해 화질 손상 정도를 눈으로 대조하며, 용량 압축 및 규격 변환을 즉시 수행합니다.
        </p>
      </div>

      <div className="grid grid-cols-1 lg:grid-cols-12 gap-8 items-start">
        {/* Settings Panel */}
        <div className="lg:col-span-5 space-y-6">
          <div className="bg-slate-900 border border-slate-800 rounded-2xl p-6 shadow-xl relative overflow-hidden" id="img-upload-card">
            <div className="absolute top-0 right-0 w-32 h-32 bg-indigo-500/10 rounded-full blur-3xl pointer-events-none"></div>

            <h3 className="text-sm font-semibold tracking-wide text-indigo-400 uppercase mb-4 flex items-center gap-2">
              <UploadCloud className="w-4 h-4" /> 1. 사진 파일 업로드
            </h3>

            {!originalSrc ? (
              <div
                id="image-drop-zone"
                onDragEnter={handleDrag}
                onDragOver={handleDrag}
                onDragLeave={handleDrag}
                onDrop={handleDrop}
                onClick={() => fileInputRef.current?.click()}
                className={`border-2 border-dashed rounded-xl p-8 text-center cursor-pointer transition-all duration-300 flex flex-col items-center justify-center min-h-[220px] ${
                  dragActive 
                    ? 'border-indigo-500 bg-indigo-500/10 scale-[1.02]' 
                    : 'border-slate-800 bg-slate-950/60 hover:border-slate-700 hover:bg-slate-900/40'
                }`}
              >
                <div className="p-4 bg-slate-900 rounded-2xl border border-slate-800 shadow-md">
                  <ImageIcon className="w-8 h-8 text-indigo-400" />
                </div>
                <p className="mt-4 text-sm font-medium text-slate-200">
                  이미지 파일을 드래그하거나 클릭하세요
                </p>
                <p className="mt-1.5 text-xs text-slate-500">
                  PNG, JPG, WebP, GIF 등 모든 표준 규격을 로컬에서 가속 처리합니다
                </p>
                <input
                  type="file"
                  ref={fileInputRef}
                  onChange={handleFileInput}
                  accept="image/*"
                  className="hidden"
                  id="image-file-input"
                />
              </div>
            ) : (
              <div className="bg-slate-950 border border-slate-800 rounded-xl p-4 flex items-center justify-between shadow-inner" id="img-info-badge">
                <div className="flex items-center gap-3 overflow-hidden">
                  <div className="p-2.5 bg-indigo-500/15 rounded-lg shrink-0 border border-indigo-500/10">
                    <ImageIcon className="w-5 h-5 text-indigo-400" />
                  </div>
                  <div className="overflow-hidden">
                    <p className="text-sm font-medium text-slate-200 truncate" title={originalName}>
                      {originalName}
                    </p>
                    <p className="text-xs text-slate-500 mt-0.5">
                      {(originalSize / 1024).toFixed(1)} KB • {originalDimensions.w} × {originalDimensions.h}px
                    </p>
                  </div>
                </div>
                <button
                  id="btn-remove-image"
                  onClick={removeImage}
                  className="p-1.5 text-slate-400 hover:text-slate-100 hover:bg-slate-800 rounded-md transition-colors border border-transparent hover:border-slate-700"
                  title="사진 제거"
                >
                  <X className="w-4 h-4" />
                </button>
              </div>
            )}
          </div>

          {originalSrc && (
            <div className="bg-slate-900 border border-slate-800 rounded-2xl p-6 shadow-xl space-y-6 animate-slide-up" id="img-controls-card">
              <h3 className="text-sm font-semibold tracking-wide text-indigo-400 uppercase flex items-center gap-2">
                <Sliders className="w-4 h-4" /> 2. 변환 및 압축 제어
              </h3>

              {/* Premium Compression Presets bento */}
              <div className="space-y-2">
                <label className="text-xs text-slate-400 font-medium block flex items-center gap-1.5">
                  <Sparkles className="w-3.5 h-3.5 text-indigo-400" />
                  원클릭 스마트 프로필 (Smart Profiles)
                </label>
                <div className="grid grid-cols-2 gap-2">
                  {presets.map((p) => {
                    const isMimeMatch = outputFormat === p.format;
                    const isScaleMatch = resizeMode === 'scale' && scalePercentage === p.scale;
                    const isQualityMatch = outputFormat === 'image/png' || quality === p.quality;
                    const isActive = isMimeMatch && isScaleMatch && isQualityMatch;
                    return (
                      <button
                        key={p.id}
                        type="button"
                        onClick={() => applyPreset(p)}
                        className={`text-left p-2.5 rounded-xl border transition-all duration-200 cursor-pointer ${
                          isActive
                            ? 'bg-indigo-600/15 border-indigo-500 text-white shadow-md shadow-indigo-500/10'
                            : 'bg-slate-950/60 border-slate-800 hover:border-slate-750 text-slate-300'
                        }`}
                      >
                        <p className="text-[10px] font-bold">{p.label}</p>
                        <p className="text-[8px] text-slate-500 mt-0.5">{p.desc}</p>
                      </button>
                    );
                  })}
                </div>
              </div>

              {/* Format selection */}
              <div className="space-y-2">
                <label className="text-xs text-slate-400 font-medium block">출력 포맷 (Format)</label>
                <div className="grid grid-cols-3 gap-2 bg-slate-950 p-1 rounded-lg border border-slate-800">
                  {['image/jpeg', 'image/png', 'image/webp'].map((mime) => (
                    <button
                      key={mime}
                      id={`btn-format-${mime.split('/')[1]}`}
                      onClick={() => setOutputFormat(mime)}
                      className={`text-xs py-2 font-semibold rounded-md transition-all duration-200 ${
                        outputFormat === mime
                          ? 'bg-indigo-600 text-white shadow-sm'
                          : 'text-slate-400 hover:text-slate-200 hover:bg-slate-900'
                      }`}
                    >
                      {getFormatLabel(mime)}
                    </button>
                  ))}
                </div>
              </div>

              {/* Resize settings */}
              <div className="space-y-3">
                <div className="flex justify-between items-center">
                  <label className="text-xs text-slate-400 font-medium">크기 조절 (Resize)</label>
                  <div className="flex bg-slate-950 p-0.5 rounded-md border border-slate-800">
                    <button
                      id="btn-resize-scale"
                      onClick={() => setResizeMode('scale')}
                      className={`text-[10px] px-2.5 py-1 font-medium rounded-md transition-colors ${
                        resizeMode === 'scale' ? 'bg-slate-800 text-white shadow-sm' : 'text-slate-400 hover:text-slate-200'
                      }`}
                    >
                      비율 수축
                    </button>
                    <button
                      id="btn-resize-custom"
                      onClick={() => setResizeMode('custom')}
                      className={`text-[10px] px-2.5 py-1 font-medium rounded-md transition-colors ${
                        resizeMode === 'custom' ? 'bg-slate-800 text-white shadow-sm' : 'text-slate-400 hover:text-slate-200'
                      }`}
                    >
                      직접 크기
                    </button>
                  </div>
                </div>

                {resizeMode === 'scale' ? (
                  <div className="space-y-2 bg-slate-950 p-3 rounded-xl border border-slate-800" id="resize-scale-panel">
                    <div className="flex justify-between text-xs">
                      <span className="text-slate-400 font-medium">조절 배율</span>
                      <span className="text-indigo-400 font-bold">{scalePercentage}%</span>
                    </div>
                    <input
                      id="range-scale-percentage"
                      type="range"
                      min={10}
                      max={100}
                      step={5}
                      value={scalePercentage}
                      onChange={(e) => setScalePercentage(parseInt(e.target.value))}
                      className="w-full accent-indigo-500 bg-slate-800 h-1 rounded-lg appearance-none cursor-pointer"
                    />
                    <div className="flex justify-between text-[10px] text-slate-500">
                      <span>10% (최소)</span>
                      <span>원본 ({originalDimensions.w}x{originalDimensions.h}px)</span>
                    </div>
                  </div>
                ) : (
                  <div className="space-y-3 bg-slate-950 p-4 rounded-xl border border-slate-800" id="resize-custom-panel">
                    <div className="grid grid-cols-2 gap-3">
                      <div className="space-y-1">
                        <label className="text-[10px] text-slate-500 font-semibold block">너비 (Width, px)</label>
                        <input
                          id="input-custom-width"
                          type="number"
                          value={customWidth || ''}
                          onChange={(e) => handleWidthChange(parseInt(e.target.value) || 0)}
                          className="w-full bg-slate-900 border border-slate-800 rounded-lg px-3 py-1.5 text-xs text-slate-200 focus:outline-none focus:border-indigo-500"
                        />
                      </div>
                      <div className="space-y-1">
                        <label className="text-[10px] text-slate-500 font-semibold block">높이 (Height, px)</label>
                        <input
                          id="input-custom-height"
                          type="number"
                          value={customHeight || ''}
                          onChange={(e) => handleHeightChange(parseInt(e.target.value) || 0)}
                          className="w-full bg-slate-900 border border-slate-800 rounded-lg px-3 py-1.5 text-xs text-slate-200 focus:outline-none focus:border-indigo-500"
                        />
                      </div>
                    </div>

                    <button
                      id="btn-toggle-aspect-ratio"
                      onClick={() => setAspectRatioLocked(!aspectRatioLocked)}
                      className="flex items-center gap-1.5 text-[10px] text-indigo-400 hover:text-indigo-300 font-semibold transition-colors mt-1"
                    >
                      {aspectRatioLocked ? (
                        <>
                          <Lock className="w-3.5 h-3.5" /> 종횡비 유지 잠금 활성화됨
                        </>
                      ) : (
                        <>
                          <Unlock className="w-3.5 h-3.5" /> 종횡비 유지 잠금 해제됨
                        </>
                      )}
                    </button>
                  </div>
                )}
              </div>

              {/* Quality control for JPEG/WebP */}
              {outputFormat !== 'image/png' && (
                <div className="space-y-2">
                  <div className="flex justify-between items-center text-xs">
                    <span className="text-slate-400 font-medium">인코딩 화질 (Quality)</span>
                    <span className="text-indigo-400 font-bold bg-indigo-500/10 px-2.5 py-0.5 rounded-md border border-indigo-500/10">
                      {quality}%
                    </span>
                  </div>
                  <input
                    id="range-quality"
                    type="range"
                    min={10}
                    max={100}
                    value={quality}
                    onChange={(e) => setQuality(parseInt(e.target.value))}
                    className="w-full accent-indigo-500 bg-slate-800 h-1 rounded-lg appearance-none cursor-pointer"
                  />
                  <p className="text-[10px] text-slate-500 mt-0.5 leading-relaxed">
                    화질을 낮추면 파일 용량(KB)이 급격히 줄어들며, 웹 환경 최적화에 탁월합니다.
                  </p>
                </div>
              )}

              {/* Manual Trigger */}
              <button
                id="btn-manual-recalculate"
                onClick={startOptimization}
                disabled={isProcessing}
                className="w-full py-2.5 bg-slate-800 hover:bg-slate-700 disabled:bg-slate-900 text-xs text-slate-300 font-semibold rounded-xl border border-slate-700/85 transition-colors flex items-center justify-center gap-1.5"
              >
                <RefreshCw className={`w-3.5 h-3.5 ${isProcessing ? 'animate-spin' : ''}`} />
                설정 적용하여 수동 재연산
              </button>
            </div>
          )}
        </div>

        {/* Display Panel */}
        <div className="lg:col-span-7">
          <div className="bg-slate-900 border border-slate-800 rounded-2xl p-6 shadow-xl min-h-[460px] flex flex-col space-y-5" id="img-display-card">
            {!originalSrc ? (
              <div className="flex-grow flex flex-col items-center justify-center text-slate-500 py-24" id="img-empty-state">
                <div className="p-4 bg-slate-950 border border-slate-800 rounded-full shadow-inner mb-4">
                  <ImageIcon className="w-10 h-10 text-slate-700" />
                </div>
                <p className="text-sm font-medium text-slate-300">편집할 이미지를 업로드해 주세요.</p>
                <p className="text-xs text-slate-500 mt-1">사이즈, 해상도, 포맷이 완벽히 변환되어 즉시 최적화됩니다.</p>
              </div>
            ) : (
              <div className="flex-grow flex flex-col h-full space-y-6" id="img-results-panel">
                
                {/* Tab selector for preview layout */}
                <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 bg-slate-950 p-2.5 rounded-xl border border-slate-850">
                  <span className="text-xs text-slate-300 font-bold px-1.5">실시간 비교 미리보기</span>
                  <div className="flex gap-1 bg-slate-900 p-0.5 rounded-lg border border-slate-800">
                    <button
                      onClick={() => setPreviewMode('slider')}
                      className={`text-xs px-3 py-1.5 font-medium rounded-md transition-all duration-200 flex items-center gap-1.5 ${
                        previewMode === 'slider' 
                          ? 'bg-indigo-600 text-white font-semibold' 
                          : 'text-slate-400 hover:text-slate-200'
                      }`}
                    >
                      <Split className="w-3.5 h-3.5" />
                      슬라이더 비교
                    </button>
                    <button
                      onClick={() => setPreviewMode('side-by-side')}
                      className={`text-xs px-3 py-1.5 font-medium rounded-md transition-all duration-200 flex items-center gap-1.5 ${
                        previewMode === 'side-by-side' 
                          ? 'bg-indigo-600 text-white font-semibold' 
                          : 'text-slate-400 hover:text-slate-200'
                      }`}
                    >
                      <Columns className="w-3.5 h-3.5" />
                      나란히 보기
                    </button>
                  </div>
                </div>

                {/* Statistics Box */}
                {optimizedSrc && (
                  <div className="bg-slate-950 border border-slate-800 rounded-xl p-4 grid grid-cols-1 sm:grid-cols-3 gap-4 shadow-inner" id="img-statistics-grid">
                    <div className="space-y-1 border-b sm:border-b-0 sm:border-r border-slate-800 pb-3 sm:pb-0 sm:pr-4">
                      <span className="text-[10px] text-slate-500 font-bold tracking-wider uppercase">용량 압축률</span>
                      <div className="flex items-baseline gap-1.5">
                        <span className="text-lg font-extrabold text-emerald-400">
                          {originalSize > optimizedSize 
                            ? `${((1 - optimizedSize / originalSize) * 100).toFixed(1)}%` 
                            : '0%'
                          }
                        </span>
                        <span className="text-xs text-slate-400">절감 완료</span>
                      </div>
                    </div>

                    <div className="space-y-1 border-b sm:border-b-0 sm:border-r border-slate-800 pb-3 sm:pb-0 sm:pr-4">
                      <span className="text-[10px] text-slate-500 font-bold tracking-wider uppercase">최종 파일 크기</span>
                      <div className="flex items-baseline gap-1.5">
                        <span className="text-lg font-bold text-slate-100">
                          {(optimizedSize / 1024).toFixed(1)} KB
                        </span>
                        <span className="text-xs text-slate-500 line-through">
                          {(originalSize / 1024).toFixed(1)} KB
                        </span>
                      </div>
                    </div>

                    <div className="space-y-1">
                      <span className="text-[10px] text-slate-500 font-bold tracking-wider uppercase">최종 이미지 해상도</span>
                      <div className="flex items-baseline gap-1.5">
                        <span className="text-base font-semibold text-slate-200">
                          {optimizedDimensions.w} × {optimizedDimensions.h}px
                        </span>
                      </div>
                    </div>
                  </div>
                )}

                {/* Dominant Colors Analysis */}
                {dominantColors.length > 0 && (
                  <div className="bg-slate-950/40 border border-slate-850 rounded-xl p-3.5 space-y-2">
                    <div className="flex items-center gap-1.5 text-xs text-slate-400 font-medium">
                      <Sparkles className="w-3.5 h-3.5 text-indigo-400 animate-pulse" />
                      <span>이미지 주요 색상 팔레트 분석</span>
                    </div>
                    <div className="flex items-center gap-2">
                      {dominantColors.map((color, idx) => (
                        <div key={idx} className="flex-1 h-6 rounded-md relative group transition-transform duration-200 hover:scale-[1.05] shadow border border-slate-800" style={{ backgroundColor: color }}>
                          <div className="absolute inset-0 opacity-0 group-hover:opacity-100 bg-slate-950/90 rounded-md flex items-center justify-center transition-opacity text-[8px] font-mono text-slate-300">
                            {color}
                          </div>
                        </div>
                      ))}
                    </div>
                  </div>
                )}

                {/* Main Preview Block */}
                {previewMode === 'slider' ? (
                  <div className="flex flex-col space-y-2">
                    <span className="text-xs text-slate-400 font-semibold flex items-center gap-1">
                      <span className="w-1.5 h-1.5 rounded-full bg-indigo-500 animate-pulse"></span>
                      분할 슬라이더 (드래그하여 대조 비교)
                    </span>
                    <div 
                      ref={sliderContainerRef}
                      onMouseMove={onMouseMove}
                      onTouchMove={onTouchMove}
                      onMouseDown={() => setIsDragging(true)}
                      onMouseUp={() => setIsDragging(false)}
                      onMouseLeave={() => setIsDragging(false)}
                      className="relative w-full bg-slate-950 border border-slate-800 rounded-xl aspect-[4/3] sm:aspect-video overflow-hidden cursor-ew-resize select-none shadow-xl"
                      id="image-slider-comparison"
                    >
                      {/* Original (Underneath / Right side) */}
                      <div className="absolute inset-0 flex items-center justify-center p-4">
                        <img 
                          src={originalSrc} 
                          alt="Original" 
                          className="max-h-full max-w-full object-contain pointer-events-none"
                        />
                        <div className="absolute top-3 left-3 bg-slate-950/90 backdrop-blur border border-slate-800 px-2 py-0.5 rounded text-[10px] text-slate-400 font-mono shadow-md">
                          원본 (Before)
                        </div>
                      </div>

                      {/* Optimized (Foreground Layer / Left side with Clip) */}
                      <div 
                        className="absolute inset-y-0 left-0 overflow-hidden bg-slate-950 flex items-center justify-center p-4 border-r-2 border-indigo-500"
                        style={{ width: `${sliderPosition}%` }}
                      >
                        {/* We use a wrapper with fixed size equal to the parent container's actual size 
                            so the sliding mask scales the exact same centered image perfectly without shift */}
                        <div 
                          className="absolute inset-0 flex items-center justify-center p-4"
                          style={{ width: sliderContainerRef.current?.getBoundingClientRect().width || '100%' }}
                        >
                          {isProcessing ? (
                            <div className="flex flex-col items-center gap-2">
                              <RefreshCw className="w-6 h-6 text-indigo-500 animate-spin" />
                            </div>
                          ) : optimizedSrc ? (
                            <img 
                              src={optimizedSrc} 
                              alt="Optimized" 
                              className="max-h-full max-w-full object-contain pointer-events-none"
                            />
                          ) : null}
                        </div>
                        <div className="absolute top-3 right-3 bg-indigo-950/95 backdrop-blur border border-indigo-900/60 px-2 py-0.5 rounded text-[10px] text-indigo-300 font-mono shadow-md whitespace-nowrap">
                          {getFormatLabel(outputFormat)} ({quality}%) (After)
                        </div>
                      </div>

                      {/* Slider Bar Handle */}
                      <div 
                        className="absolute inset-y-0 pointer-events-none z-10"
                        style={{ left: `${sliderPosition}%` }}
                      >
                        <div className="absolute top-1/2 -translate-y-1/2 -translate-x-1/2 w-8 h-8 bg-indigo-600 text-white rounded-full flex items-center justify-center shadow-lg border border-indigo-400 active:scale-110 transition-transform">
                          <Sliders className="w-4 h-4 rotate-90" />
                        </div>
                      </div>
                    </div>
                  </div>
                ) : (
                  <div className="grid grid-cols-1 md:grid-cols-2 gap-6 flex-grow">
                    
                    {/* Original image block */}
                    <div className="flex flex-col border border-slate-800 rounded-xl bg-slate-950/40 p-4" id="img-preview-original">
                      <span className="text-xs text-slate-400 font-semibold mb-2 flex items-center gap-1.5">
                        <span className="w-1.5 h-1.5 rounded-full bg-slate-500"></span> 원본 이미지
                      </span>
                      <div className="flex-grow flex items-center justify-center bg-slate-950 border border-slate-800/60 rounded-lg aspect-square overflow-hidden relative">
                        <img 
                          src={originalSrc} 
                          alt="Original" 
                          className="max-h-full max-w-full object-contain p-2"
                        />
                        <div className="absolute bottom-2.5 right-2.5 bg-slate-950/80 backdrop-blur border border-slate-800 px-2 py-0.5 rounded text-[10px] text-slate-400 font-mono">
                          {originalDimensions.w} × {originalDimensions.h}px • {(originalSize / 1024).toFixed(1)} KB
                        </div>
                      </div>
                    </div>

                    {/* Optimized image block */}
                    <div className="flex flex-col border border-slate-800 rounded-xl bg-slate-950/40 p-4" id="img-preview-optimized">
                      <span className="text-xs text-indigo-400 font-semibold mb-2 flex items-center gap-1.5">
                        <span className="w-1.5 h-1.5 rounded-full bg-indigo-500 animate-pulse"></span> 변환 및 최적화 이미지
                      </span>
                      <div className="flex-grow flex items-center justify-center bg-slate-950 border border-slate-800/60 rounded-lg aspect-square overflow-hidden relative">
                        {isProcessing ? (
                          <div className="flex flex-col items-center gap-2">
                            <RefreshCw className="w-8 h-8 text-indigo-500 animate-spin" />
                            <span className="text-xs text-slate-500">재연산 중...</span>
                          </div>
                        ) : optimizedSrc ? (
                          <>
                            <img 
                              src={optimizedSrc} 
                              alt="Optimized" 
                              className="max-h-full max-w-full object-contain p-2"
                            />
                            <div className="absolute bottom-2.5 right-2.5 bg-indigo-950/80 backdrop-blur border border-indigo-900/60 px-2 py-0.5 rounded text-[10px] text-indigo-300 font-mono">
                              {optimizedDimensions.w} × {optimizedDimensions.h}px • {(optimizedSize / 1024).toFixed(1)} KB
                            </div>
                          </>
                        ) : (
                          <span className="text-xs text-slate-600">처리 중...</span>
                        )}
                      </div>
                    </div>

                  </div>
                )}

                {/* Final Action Button */}
                {optimizedSrc && !isProcessing && (
                  <div className="pt-4 border-t border-slate-800 flex justify-end" id="img-download-container">
                    <a
                      id="btn-download-optimized"
                      href={optimizedSrc}
                      download={`${originalName.replace(/\.[^/.]+$/, "")}_optimized.${extensionMap[outputFormat]}`}
                      onClick={handleDownloadOptimized}
                      className="px-6 py-3 bg-gradient-to-r from-emerald-500 to-teal-600 hover:from-emerald-600 hover:to-teal-700 text-sm font-semibold rounded-xl text-white shadow-lg hover:shadow-emerald-500/10 transition-all duration-200 flex items-center gap-2"
                    >
                      <ImageDown className="w-4 h-4" />
                      최적화된 이미지 다운로드하기
                    </a>
                  </div>
                )}

              </div>
            )}
          </div>
        </div>
      </div>
    </div>
  );
}

// Mount the React Application
const container = document.getElementById('root');
if (container) {
  const root = createRoot(container);
  root.render(
    <React.StrictMode>
      <App />
    </React.StrictMode>
  );
}
