     1→     1→'use client';
     2→     2→
     3→     3→import { useState, useCallback, useRef, useEffect } from 'react';
     4→     4→import { motion, AnimatePresence } from 'framer-motion';
     5→     5→import {
     6→     6→  Upload, Image as ImageIcon, Sparkles, Download, ArrowRight,
     7→     7→  Palette, Camera, Layers, SlidersHorizontal, Loader2, Check,
     8→     8→  Trash2, RotateCcw, Eye, Wand2, Sun, Paintbrush, Film,
     9→     9→  Pencil, History, ChevronLeft, X, GripVertical
    10→    10→} from 'lucide-react';
    11→    11→import { Button } from '@/components/ui/button';
    12→    12→import { Textarea } from '@/components/ui/textarea';
    13→    13→import { Progress } from '@/components/ui/progress';
    14→    14→import { Card, CardContent } from '@/components/ui/card';
    15→    15→import {
    16→    16→  Dialog,
    17→    17→  DialogContent,
    18→    18→  DialogHeader,
    19→    19→  DialogTitle,
    20→    20→  DialogTrigger,
    21→    21→} from '@/components/ui/dialog';
    22→    22→import { useAppStore, type PhotoProject } from '@/store/photo-store';
    23→    23→
    24→    24→/* ─── Edit Tool Definitions ─── */
    25→    25→const EDIT_TOOLS = [
    26→    26→  { id: 'oil-painting', label: 'لوحة زيتية', icon: Paintbrush, prompt: 'Transform this image into an oil painting style, with visible brushstrokes and rich, vibrant colors, maintain the composition and subject', color: 'from-amber-500/20 to-orange-600/20' },
    27→    27→  { id: 'cartoon', label: 'رسم كرتوني', icon: Pencil, prompt: 'Transform this image into a cartoon illustration style, with bold outlines, flat colors, and simplified shapes, keep the main subject recognizable', color: 'from-pink-500/20 to-rose-600/20' },
    28→    28→  { id: 'bw', label: 'أبيض وأسود', icon: Camera, prompt: 'Convert this image to a stunning black and white photograph with high contrast and dramatic lighting, professional photography style', color: 'from-gray-500/20 to-gray-700/20' },
    29→    29→  { id: 'golden-hour', label: 'إضاءة ذهبية', icon: Sun, prompt: 'Apply warm golden hour lighting to this image, with beautiful warm tones, soft shadows, and a magical sunset glow, maintain all subjects', color: 'from-yellow-500/20 to-amber-600/20' },
    30→    30→  { id: 'enhance', label: 'تحسين الجودة', icon: Sparkles, prompt: 'Enhance the quality and sharpness of this image, improve colors, add more detail and clarity, make it look professional and high-resolution', color: 'from-emerald-500/20 to-teal-600/20' },
    31→    31→  { id: 'bg-remove', label: 'خلفية احترافية', icon: Layers, prompt: 'Replace the background with a clean, modern, professional studio-like background, keep the main subject exactly the same with proper lighting', color: 'from-cyan-500/20 to-blue-600/20' },
    32→    32→  { id: 'cinematic', label: 'تأثير سينمائي', icon: Film, prompt: 'Apply a cinematic color grading to this image, with deep shadows, teal and orange tones, letterbox style, dramatic and moody atmosphere', color: 'from-violet-500/20 to-purple-600/20' },
    33→    33→  { id: 'illustration', label: 'أسلوب رسومي', icon: Palette, prompt: 'Transform this image into a digital illustration style, clean lines, artistic rendering, vibrant but harmonious colors, maintain the scene composition', color: 'from-fuchsia-500/20 to-pink-600/20' },
    34→    34→];
    35→    35→
    36→    36→/* ─── Header Component ─── */
    37→    37→function Header() {
    38→    38→  const { currentView, setView } = useAppStore();
    39→    39→  return (
    40→    40→    <header className="glass sticky top-0 z-50">
    41→    41→      <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-16 flex items-center justify-between">
    42→    42→        <button
    43→    43→          onClick={() => setView('home')}
    44→    44→          className="flex items-center gap-3 group"
    45→    45→        >
    46→    46→          <div className="w-9 h-9 rounded-lg bg-primary/20 flex items-center justify-center">
    47→    47→            <Wand2 className="w-5 h-5 text-primary" />
    48→    48→          </div>
    49→    49→          <span className="text-lg font-bold gradient-text">محرر الصور AI</span>
    50→    50→        </button>
    51→    51→        <nav className="flex items-center gap-1">
    52→    52→          <Button
    53→    53→            variant={currentView === 'home' ? 'default' : 'ghost'}
    54→    54→            size="sm"
    55→    55→            onClick={() => setView('home')}
    56→    56→            className="gap-2"
    57→    57→          >
    58→    58→            <ImageIcon className="w-4 h-4" />
    59→    59→            <span className="hidden sm:inline">الرئيسية</span>
    60→    60→          </Button>
    61→    61→          <Button
    62→    62→            variant={currentView === 'gallery' ? 'default' : 'ghost'}
    63→    63→            size="sm"
    64→    64→            onClick={() => setView('gallery')}
    65→    65→            className="gap-2"
    66→    66→          >
    67→    67→            <History className="w-4 h-4" />
    68→    68→            <span className="hidden sm:inline">المعرض</span>
    69→    69→          </Button>
    70→    70→        </nav>
    71→    71→      </div>
    72→    72→    </header>
    73→    73→  );
    74→    74→}
    75→    75→
    76→    76→/* ─── Footer Component ─── */
    77→    77→function Footer() {
    78→    78→  return (
    79→    79→    <footer className="glass mt-auto">
    80→    80→      <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4 flex flex-col sm:flex-row items-center justify-between gap-2 text-sm text-muted-foreground">
    81→    81→        <p>محرر الصور بالذكاء الاصطناعي — قوّة الذكاء الاصطناعي بين يديك</p>
    82→    82→        <p>© {new Date().getFullYear()} جميع الحقوق محفوظة</p>
    83→    83→      </div>
    84→    84→    </footer>
    85→    85→  );
    86→    86→}
    87→    87→
    88→    88→/* ─── Upload Area Component ─── */
    89→    89→function UploadArea() {
    90→    90→  const { setOriginalImage, setOriginalFileName, setView, setAnalysis, setEditedImage, setEditError } = useAppStore();
    91→    91→  const [isDragOver, setIsDragOver] = useState(false);
    92→    92→  const [isUploading, setIsUploading] = useState(false);
    93→    93→  const fileInputRef = useRef<HTMLInputElement>(null);
    94→    94→
    95→    95→  const handleFile = useCallback(async (file: File) => {
    96→    96→    if (!file.type.startsWith('image/')) return;
    97→    97→    setIsUploading(true);
    98→    98→    setEditError(null);
    99→    99→    setEditedImage(null);
   100→   100→    setAnalysis(null);
   101→   101→    try {
   102→   102→      const formData = new FormData();
   103→   103→      formData.append('image', file);
   104→   104→
   105→   105→      const res = await fetch('/api/upload', { method: 'POST', body: formData });
   106→   106→      const data = await res.json();
   107→   107→      if (!res.ok) throw new Error(data.error || 'فشل رفع الصورة');
   108→   108→
   109→   109→      setOriginalImage(data.imageUrl);
   110→   110→      setOriginalFileName(file.name);
   111→   111→      setView('editor');
   112→   112→    } catch (err: unknown) {
   113→   113→      const message = err instanceof Error ? err.message : 'حدث خطأ';
   114→   114→      setEditError(message);
   115→   115→    } finally {
   116→   116→      setIsUploading(false);
   117→   117→    }
   118→   118→  }, [setOriginalImage, setOriginalFileName, setView, setEditedImage, setAnalysis, setEditError]);
   119→   119→
   120→   120→  const onDrop = useCallback((e: React.DragEvent) => {
   121→   121→    e.preventDefault();
   122→   122→    setIsDragOver(false);
   123→   123→    const file = e.dataTransfer.files[0];
   124→   124→    if (file) handleFile(file);
   125→   125→  }, [handleFile]);
   126→   126→
   127→   127→  const onDragOver = useCallback((e: React.DragEvent) => {
   128→   128→    e.preventDefault();
   129→   129→    setIsDragOver(true);
   130→   130→  }, []);
   131→   131→
   132→   132→  const onDragLeave = useCallback(() => setIsDragOver(false), []);
   133→   133→
   134→   134→  return (
   135→   135→    <motion.div
   136→   136→      initial={{ opacity: 0, y: 30 }}
   137→   137→      animate={{ opacity: 1, y: 0 }}
   138→   138→      transition={{ duration: 0.6 }}
   139→   139→      className="w-full max-w-2xl mx-auto"
   140→   140→    >
   141→   141→      <div
   142→   142→        onDrop={onDrop}
   143→   143→        onDragOver={onDragOver}
   144→   144→        onDragLeave={onDragLeave}
   145→   145→        onClick={() => fileInputRef.current?.click()}
   146→   146→        className={`
   147→   147→          relative cursor-pointer rounded-2xl border-2 border-dashed p-12 sm:p-16
   148→   148→          transition-all duration-300 text-center
   149→   149→          ${isDragOver
   150→   150→            ? 'upload-area-active border-primary'
   151→   151→            : 'border-muted-foreground/30 hover:border-primary/50 hover:bg-primary/5'
   152→   152→          }
   153→   153→        `}
   154→   154→      >
   155→   155→        <input
   156→   156→          ref={fileInputRef}
   157→   157→          type="file"
   158→   158→          accept="image/*"
   159→   159→          className="hidden"
   160→   160→          onChange={(e) => {
   161→   161→            const file = e.target.files?.[0];
   162→   162→            if (file) handleFile(file);
   163→   163→            e.target.value = '';
   164→   164→          }}
   165→   165→        />
   166→   166→        {isUploading ? (
   167→   167→          <div className="flex flex-col items-center gap-4">
   168→   168→            <Loader2 className="w-12 h-12 text-primary animate-spin" />
   169→   169→            <p className="text-lg text-muted-foreground">جارٍ رفع الصورة...</p>
   170→   170→          </div>
   171→   171→        ) : (
   172→   172→          <div className="flex flex-col items-center gap-4">
   173→   173→            <div className="w-20 h-20 rounded-full bg-primary/10 flex items-center justify-center">
   174→   174→              <Upload className="w-10 h-10 text-primary" />
   175→   175→            </div>
   176→   176→            <div>
   177→   177→              <p className="text-xl font-semibold mb-2">اسحب الصورة هنا أو انقر للاختيار</p>
   178→   178→              <p className="text-muted-foreground text-sm">يدعم: PNG, JPG, WEBP — حتى 10 ميجا</p>
   179→   179→            </div>
   180→   180→          </div>
   181→   181→        )}
   182→   182→      </div>
   183→   183→    </motion.div>
   184→   184→  );
   185→   185→}
   186→   186→
   187→   187→/* ─── Feature Cards ─── */
   188→   188→function FeatureCards() {
   189→   189→  const features = [
   190→   190→    { icon: Sparkles, title: 'تحرير بالذكاء', desc: 'أدوات تعديل ذكية تفهم صورتك وتحسّنها' },
   191→   191→    { icon: Palette, title: 'أنماط فنية', desc: 'حوّل صورك إلى لوحات زيتية أو رسوم كرتونية' },
   192→   192→    { icon: SlidersHorizontal, title: 'مقارنة فورية', desc: 'قارن بين الأصل والنسخة المحرّرة بسهولة' },
   193→   193→    { icon: Download, title: 'تحميل مباشر', desc: 'حمّل الصور المحرّرة بجودة عالية' },
   194→   194→  ];
   195→   195→  return (
   196→   196→    <div className="grid grid-cols-2 lg:grid-cols-4 gap-4 max-w-5xl mx-auto mt-16">
   197→   197→      {features.map((f, i) => (
   198→   198→        <motion.div
   199→   199→          key={f.title}
   200→   200→          initial={{ opacity: 0, y: 20 }}
   201→   201→          animate={{ opacity: 1, y: 0 }}
   202→   202→          transition={{ duration: 0.5, delay: 0.2 + i * 0.1 }}
   203→   203→        >
   204→   204→          <Card className="glass h-full text-center p-4 sm:p-6">
   205→   205→            <CardContent className="p-0 flex flex-col items-center gap-3">
   206→   206→              <div className="w-12 h-12 rounded-xl bg-primary/15 flex items-center justify-center">
   207→   207→                <f.icon className="w-6 h-6 text-primary" />
   208→   208→              </div>
   209→   209→              <h3 className="font-semibold text-sm sm:text-base">{f.title}</h3>
   210→   210→              <p className="text-xs sm:text-sm text-muted-foreground">{f.desc}</p>
   211→   211→            </CardContent>
   212→   212→          </Card>
   213→   213→        </motion.div>
   214→   214→      ))}
   215→   215→    </div>
   216→   216→  );
   217→   217→}
   218→   218→
   219→   219→/* ─── Home View ─── */
   220→   220→function HomeView() {
   221→   221→  return (
   222→   222→    <main className="flex-1 flex flex-col items-center justify-center px-4 py-12">
   223→   223→      <motion.div
   224→   224→        initial={{ opacity: 0, y: -20 }}
   225→   225→        animate={{ opacity: 1, y: 0 }}
   226→   226→        transition={{ duration: 0.5 }}
   227→   227→        className="text-center mb-10"
   228→   228→      >
   229→   229→        <h1 className="text-4xl sm:text-5xl lg:text-6xl font-bold mb-4">
   230→   230→          <span className="gradient-text">محرر الصور</span> بالذكاء الاصطناعي
   231→   231→        </h1>
   232→   232→        <p className="text-lg sm:text-xl text-muted-foreground max-w-xl mx-auto">
   233→   233→          ارفع صورتك واختر التأثير المطلوب — وشاهد الذكاء الاصطناعي يُبدع
   234→   234→        </p>
   235→   235→      </motion.div>
   236→   236→      <UploadArea />
   237→   237→      <FeatureCards />
   238→   238→    </main>
   239→   239→  );
   240→   240→}
   241→   241→
   242→   242→/* ─── Before/After Comparison Slider ─── */
   243→   243→function ComparisonSlider({ original, edited }: { original: string; edited: string }) {
   244→   244→  const containerRef = useRef<HTMLDivElement>(null);
   245→   245→  const [position, setPosition] = useState(50);
   246→   246→  const [containerWidth, setContainerWidth] = useState(0);
   247→   247→  const isDragging = useRef(false);
   248→   248→
   249→   249→  useEffect(() => {
   250→   250→    const el = containerRef.current;
   251→   251→    if (!el) return;
   252→   252→    const observer = new ResizeObserver((entries) => {
   253→   253→      for (const entry of entries) {
   254→   254→        setContainerWidth(entry.contentRect.width);
   255→   255→      }
   256→   256→    });
   257→   257→    observer.observe(el);
   258→   258→    return () => observer.disconnect();
   259→   259→  }, []);
   260→   260→
   261→   261→  const updatePosition = useCallback((clientX: number) => {
   262→   262→    if (!containerRef.current) return;
   263→   263→    const rect = containerRef.current.getBoundingClientRect();
   264→   264→    // RTL: position is measured from the right edge
   265→   265→    const x = clientX - rect.left;
   266→   266→    const pct = Math.min(100, Math.max(0, (x / rect.width) * 100));
   267→   267→    setPosition(pct);
   268→   268→  }, []);
   269→   269→
   270→   270→  const handlePointerDown = useCallback((e: React.PointerEvent) => {
   271→   271→    isDragging.current = true;
   272→   272→    (e.target as HTMLElement).setPointerCapture(e.pointerId);
   273→   273→    updatePosition(e.clientX);
   274→   274→  }, [updatePosition]);
   275→   275→
   276→   276→  const handlePointerMove = useCallback((e: React.PointerEvent) => {
   277→   277→    if (!isDragging.current) return;
   278→   278→    updatePosition(e.clientX);
   279→   279→  }, [updatePosition]);
   280→   280→
   281→   281→  const handlePointerUp = useCallback(() => {
   282→   282→    isDragging.current = false;
   283→   283→  }, []);
   284→   284→
   285→   285→  return (
   286→   286→    <div
   287→   287→      ref={containerRef}
   288→   288→      className="comparison-container rounded-xl overflow-hidden bg-black/50 relative w-full"
   289→   289→      style={{ aspectRatio: 'auto' }}
   290→   290→      onPointerDown={handlePointerDown}
   291→   291→      onPointerMove={handlePointerMove}
   292→   292→      onPointerUp={handlePointerUp}
   293→   293→    >
   294→   294→      {/* Edited image (full width, behind) */}
   295→   295→      <img
   296→   296→        src={edited}
   297→   297→        alt="After"
   298→   298→        className="w-full h-auto block"
   299→   299→        draggable={false}
   300→   300→      />
   301→   301→
   302→   302→      {/* Original image (clipped from right in RTL) */}
   303→   303→      <div
   304→   304→        className="absolute inset-0 overflow-hidden"
   305→   305→        style={{ width: `${position}%` }}
   306→   306→      >
   307→   307→        <img
   308→   308→          src={original}
   309→   309→          alt="Before"
   310→   310→          className="w-full h-auto block"
   311→   311→          style={{ width: containerWidth > 0 ? `${containerWidth}px` : '100%' }}
   312→   312→          draggable={false}
   313→   313→        />
   314→   314→      </div>
   315→   315→
   316→   316→      {/* Slider line */}
   317→   317→      <div
   318→   318→        className="comparison-slider-line"
   319→   319→        style={{ left: `${position}%` }}
   320→   320→      >
   321→   321→        <div className="comparison-slider-handle">
   322→   322→          <GripVertical className="w-5 h-5 text-gray-700" />
   323→   323→        </div>
   324→   324→      </div>
   325→   325→
   326→   326→      {/* Labels */}
   327→   327→      <div className="absolute top-3 right-3 bg-black/60 text-white text-xs px-2 py-1 rounded-md">الأصلي</div>
   328→   328→      <div className="absolute top-3 left-3 bg-primary/80 text-white text-xs px-2 py-1 rounded-md">المحرّر</div>
   329→   329→    </div>
   330→   330→  );
   331→   331→}
   332→   332→
   333→   333→/* ─── Editor View ─── */
   334→   334→function EditorView() {
   335→   335→  const {
   336→   336→    originalImage, editedImage, isEditing, editProgress, editError,
   337→   337→    analysis, customPrompt, setCustomPrompt, setEditedImage,
   338→   338→    setEditProgress, setIsEditing, setEditError, setAnalysis,
   339→   339→    setView, resetEditor, projects, setProjects, originalFileName,
   340→   340→  } = useAppStore();
   341→   341→  const [selectedTool, setSelectedTool] = useState<string | null>(null);
   342→   342→  const [isAnalyzing, setIsAnalyzing] = useState(false);
   343→   343→  const fileInputRef = useRef<HTMLInputElement>(null);
   344→   344→
   345→   345→  const handleAnalyze = useCallback(async () => {
   346→   346→    if (!originalImage) return;
   347→   347→    setIsAnalyzing(true);
   348→   348→    try {
   349→   349→      const res = await fetch('/api/analyze', {
   350→   350→        method: 'POST',
   351→   351→        headers: { 'Content-Type': 'application/json' },
   352→   352→        body: JSON.stringify({ imageUrl: originalImage }),
   353→   353→      });
   354→   354→      const data = await res.json();
   355→   355→      if (!res.ok) throw new Error(data.error || 'فشل التحليل');
   356→   356→      setAnalysis(data.analysis);
   357→   357→    } catch (err: unknown) {
   358→   358→      const message = err instanceof Error ? err.message : 'حدث خطأ';
   359→   359→      setEditError(message);
   360→   360→    } finally {
   361→   361→      setIsAnalyzing(false);
   362→   362→    }
   363→   363→  }, [originalImage, setAnalysis, setEditError]);
   364→   364→
   365→   365→  const handleEdit = useCallback(async (prompt: string, label: string, toolType: string) => {
   366→   366→    if (!originalImage) return;
   367→   367→    setIsEditing(true);
   368→   368→    setEditError(null);
   369→   369→    setEditedImage(null);
   370→   370→    setEditProgress(0);
   371→   371→
   372→   372→    try {
   373→   373→      const res = await fetch('/api/edit', {
   374→   374→        method: 'POST',
   375→   375→        headers: { 'Content-Type': 'application/json' },
   376→   376→        body: JSON.stringify({
   377→   377→          imageUrl: originalImage,
   378→   378→          prompt,
   379→   379→          label,
   380→   380→          toolType,
   381→   381→        }),
   382→   382→      });
   383→   383→
   384→   384→      if (!res.ok) {
   385→   385→        const data = await res.json();
   386→   386→        throw new Error(data.error || 'فشل التعديل');
   387→   387→      }
   388→   388→
   389→   389→      const reader = res.body?.getReader();
   390→   390→      if (!reader) throw new Error('لا يمكن قراءة الاستجابة');
   391→   391→
   392→   392→      const decoder = new TextDecoder();
   393→   393→      let buffer = '';
   394→   394→
   395→   395→      while (true) {
   396→   396→        const { done, value } = await reader.read();
   397→   397→        if (done) break;
   398→   398→
   399→   399→        buffer += decoder.decode(value, { stream: true });
   400→   400→        const lines = buffer.split('\n');
   401→   401→        buffer = lines.pop() || '';
   402→   402→
   403→   403→        for (const line of lines) {
   404→   404→          if (line.startsWith('data: ')) {
   405→   405→            const data = line.slice(6);
   406→   406→            let parsed: Record<string, unknown>;
   407→   407→            try {
   408→   408→              parsed = JSON.parse(data);
   409→   409→            } catch {
   410→   410→              continue; // Skip malformed JSON lines
   411→   411→            }
   412→   412→
   413→   413→            if (parsed.type === 'progress') {
   414→   414→              setEditProgress(parsed.value as number);
   415→   415→            } else if (parsed.type === 'done') {
   416→   416→              setEditedImage(parsed.editedImageUrl as string);
   417→   417→              setEditProgress(100);
   418→   418→              // Refresh gallery
   419→   419→              try {
   420→   420→                const projectsRes = await fetch('/api/projects');
   421→   421→                if (projectsRes.ok) {
   422→   422→                  const projectsData = await projectsRes.json();
   423→   423→                  setProjects(projectsData);
   424→   424→                }
   425→   425→              } catch { /* ignore gallery refresh failure */ }
   426→   426→            } else if (parsed.type === 'error') {
   427→   427→              throw new Error(parsed.message as string);
   428→   428→            }
   429→   429→          }
   430→   430→        }
   431→   431→      }
   432→   432→    } catch (err: unknown) {
   433→   433→      const message = err instanceof Error ? err.message : 'حدث خطأ أثناء التعديل';
   434→   434→      setEditError(message);
   435→   435→    } finally {
   436→   436→      setIsEditing(false);
   437→   437→      setSelectedTool(null);
   438→   438→    }
   439→   439→  }, [originalImage, setIsEditing, setEditError, setEditedImage, setEditProgress, setProjects]);
   440→   440→
   441→   441→  const handleCustomEdit = useCallback(() => {
   442→   442→    if (!customPrompt.trim()) return;
   443→   443→    handleEdit(customPrompt.trim(), 'تعديل مخصص', 'custom');
   444→   444→  }, [customPrompt, handleEdit]);
   445→   445→
   446→   446→  const handleNewImage = useCallback(() => {
   447→   447→    resetEditor();
   448→   448→    setView('home');
   449→   449→  }, [resetEditor, setView]);
   450→   450→
   451→   451→  const handleReupload = useCallback(async (e: React.ChangeEvent<HTMLInputElement>) => {
   452→   452→    const file = e.target.files?.[0];
   453→   453→    if (!file || !file.type.startsWith('image/')) return;
   454→   454→    const formData = new FormData();
   455→   455→    formData.append('image', file);
   456→   456→    try {
   457→   457→      const res = await fetch('/api/upload', { method: 'POST', body: formData });
   458→   458→      const data = await res.json();
   459→   459→      if (!res.ok) throw new Error(data.error);
   460→   460→      useAppStore.getState().setOriginalImage(data.imageUrl);
   461→   461→      useAppStore.getState().setOriginalFileName(file.name);
   462→   462→      useAppStore.getState().setEditedImage(null);
   463→   463→      useAppStore.getState().setAnalysis(null);
   464→   464→    } catch {}
   465→   465→    e.target.value = '';
   466→   466→  }, []);
   467→   467→
   468→   468→  const handleDownload = useCallback(() => {
   469→   469→    if (!editedImage) return;
   470→   470→    const a = document.createElement('a');
   471→   471→    a.href = editedImage;
   472→   472→    a.download = `edited-${originalFileName || 'image.png'}`;
   473→   473→    a.click();
   474→   474→  }, [editedImage, originalFileName]);
   475→   475→
   476→   476→  return (
   477→   477→    <main className="flex-1 px-4 py-6 max-w-7xl mx-auto w-full">
   478→   478→      {/* Top bar */}
   479→   479→      <div className="flex items-center justify-between mb-6">
   480→   480→        <Button variant="ghost" onClick={handleNewImage} className="gap-2">
   481→   481→          <ChevronLeft className="w-4 h-4" />
   482→   482→          صورة جديدة
   483→   483→        </Button>
   484→   484→        {editedImage && (
   485→   485→          <Button onClick={handleDownload} className="gap-2">
   486→   486→            <Download className="w-4 h-4" />
   487→   487→            تحميل الصورة
   488→   488→          </Button>
   489→   489→        )}
   490→   490→      </div>
   491→   491→
   492→   492→      <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
   493→   493→        {/* Image Preview (2/3 width on desktop) */}
   494→   494→        <div className="lg:col-span-2">
   495→   495→          <Card className="glass overflow-hidden">
   496→   496→            <CardContent className="p-0 relative">
   497→   497→              {/* Image display */}
   498→   498→              <div className="relative min-h-[300px] sm:min-h-[400px] flex items-center justify-center bg-black/30">
   499→   499→                {isEditing && (
   500→   500→                  <div className="absolute inset-0 z-20 flex flex-col items-center justify-center bg-black/50 backdrop-blur-sm">
   501→   501→                    <Loader2 className="w-12 h-12 text-primary animate-spin mb-4" />
   502→   502→                    <p className="text-lg font-semibold mb-2">جارٍ التعديل بالذكاء الاصطناعي...</p>
   503→   503→                    <Progress value={editProgress} className="w-48 h-2" />
   504→   504→                    <p className="text-sm text-muted-foreground mt-2">{editProgress}%</p>
   505→   505→                  </div>
   506→   506→                )}
   507→   507→
   508→   508→                {editedImage ? (
   509→   509→                  <ComparisonSlider original={originalImage!} edited={editedImage} />
   510→   510→                ) : (
   511→   511→                  <img
   512→   512→                    src={originalImage!}
   513→   513→                    alt="Original"
   514→   514→                    className="max-w-full max-h-[70vh] object-contain mx-auto"
   515→   515→                  />
   516→   516→                )}
   517→   517→              </div>
   518→   518→
   519→   519→              {/* Image info bar */}
   520→   520→              <div className="p-3 border-t border-border/50 flex items-center justify-between text-sm text-muted-foreground">
   521→   521→                <span className="truncate max-w-[60%]">{originalFileName || 'صورة'}</span>
   522→   522→                <Button variant="ghost" size="sm" className="gap-1 text-xs h-8" onClick={() => fileInputRef.current?.click()}>
   523→   523→                  <RotateCcw className="w-3 h-3" />
   524→   524→                  تغيير الصورة
   525→   525→                </Button>
   526→   526→                <input ref={fileInputRef} type="file" accept="image/*" className="hidden" onChange={handleReupload} />
   527→   527→              </div>
   528→   528→            </CardContent>
   529→   529→          </Card>
   530→   530→
   531→   531→          {/* Analysis section */}
   532→   532→          <div className="mt-4">
   533→   533→            <Button
   534→   534→              variant="outline"
   535→   535→              onClick={handleAnalyze}
   536→   536→              disabled={isAnalyzing || !originalImage}
   537→   537→              className="w-full gap-2 mb-3"
   538→   538→            >
   539→   539→              {isAnalyzing ? (
   540→   540→                <Loader2 className="w-4 h-4 animate-spin" />
   541→   541→              ) : (
   542→   542→                <Eye className="w-4 h-4" />
   543→   543→              )}
   544→   544→              تحليل الصورة بالذكاء الاصطناعي
   545→   545→            </Button>
   546→   546→            <AnimatePresence>
   547→   547→              {analysis && (
   548→   548→                <motion.div
   549→   549→                  initial={{ opacity: 0, height: 0 }}
   550→   550→                  animate={{ opacity: 1, height: 'auto' }}
   551→   551→                  exit={{ opacity: 0, height: 0 }}
   552→   552→                >
   553→   553→                  <Card className="glass">
   554→   554→                    <CardContent className="p-4">
   555→   555→                      <h3 className="text-sm font-semibold mb-2 flex items-center gap-2">
   556→   556→                        <Eye className="w-4 h-4 text-primary" />
   557→   557→                        نتيجة التحليل
   558→   558→                      </h3>
   559→   559→                      <p className="text-sm text-muted-foreground leading-relaxed whitespace-pre-wrap">{analysis}</p>
   560→   560→                    </CardContent>
   561→   561→                  </Card>
   562→   562→                </motion.div>
   563→   563→              )}
   564→   564→            </AnimatePresence>
   565→   565→          </div>
   566→   566→        </div>
   567→   567→
   568→   568→        {/* Tools Panel (1/3 width on desktop) */}
   569→   569→        <div className="lg:col-span-1 space-y-4">
   570→   570→          {/* Quick Tools */}
   571→   571→          <Card className="glass">
   572→   572→            <CardContent className="p-4">
   573→   573→              <h3 className="font-semibold mb-3 flex items-center gap-2">
   574→   574→                <Wand2 className="w-4 h-4 text-primary" />
   575→   575→                أدوات التحرير السريعة
   576→   576→              </h3>
   577→   577→              <div className="grid grid-cols-2 gap-2">
   578→   578→                {EDIT_TOOLS.map((tool) => {
   579→   579→                  const Icon = tool.icon;
   580→   580→                  const isLoading = isEditing && selectedTool === tool.id;
   581→   581→                  return (
   582→   582→                    <button
   583→   583→                      key={tool.id}
   584→   584→                      onClick={() => {
   585→   585→                        if (isEditing) return;
   586→   586→                        setSelectedTool(tool.id);
   587→   587→                        handleEdit(tool.prompt, tool.label, 'quick-tool');
   588→   588→                      }}
   589→   589→                      disabled={isEditing}
   590→   590→                      className={`
   591→   591→                        tool-card relative flex flex-col items-center gap-2 p-3 rounded-xl
   592→   592→                        border border-border/50 text-center transition-all
   593→   593→                        ${isLoading ? 'ring-2 ring-primary' : 'hover:border-primary/40'}
   594→   594→                        ${isEditing ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}
   595→   595→                      `}
   596→   596→                    >
   597→   597→                      <div className={`w-10 h-10 rounded-lg bg-gradient-to-br ${tool.color} flex items-center justify-center`}>
   598→   598→                        {isLoading ? (
   599→   599→                          <Loader2 className="w-5 h-5 text-primary animate-spin" />
   600→   600→                        ) : (
   601→   601→                          <Icon className="w-5 h-5 text-foreground" />
   602→   602→                        )}
   603→   603→                      </div>
   604→   604→                      <span className="text-xs font-medium">{tool.label}</span>
   605→   605→                    </button>
   606→   606→                  );
   607→   607→                })}
   608→   608→              </div>
   609→   609→            </CardContent>
   610→   610→          </Card>
   611→   611→
   612→   612→          {/* Custom Prompt */}
   613→   613→          <Card className="glass">
   614→   614→            <CardContent className="p-4">
   615→   615→              <h3 className="font-semibold mb-3 flex items-center gap-2">
   616→   616→                <Pencil className="w-4 h-4 text-primary" />
   617→   617→                تعديل مخصص
   618→   618→              </h3>
   619→   619→              <Textarea
   620→   620→                value={customPrompt}
   621→   621→                onChange={(e) => setCustomPrompt(e.target.value)}
   622→   622→                placeholder="صِف التعديل الذي تريده... مثال: غيّر الخلفية إلى شاطئ عند الغروب"
   623→   623→                className="min-h-[100px] resize-none mb-3"
   624→   624→                disabled={isEditing}
   625→   625→              />
   626→   626→              <Button
   627→   627→                onClick={handleCustomEdit}
   628→   628→                disabled={isEditing || !customPrompt.trim()}
   629→   629→                className="w-full gap-2"
   630→   630→              >
   631→   631→                {isEditing ? (
   632→   632→                  <Loader2 className="w-4 h-4 animate-spin" />
   633→   633→                ) : (
   634→   634→                  <Sparkles className="w-4 h-4" />
   635→   635→                )}
   636→   636→                تطبيق التعديل
   637→   637→              </Button>
   638→   638→            </CardContent>
   639→   639→          </Card>
   640→   640→
   641→   641→          {/* Error display */}
   642→   642→          <AnimatePresence>
   643→   643→            {editError && (
   644→   644→              <motion.div
   645→   645→                initial={{ opacity: 0, y: 10 }}
   646→   646→                animate={{ opacity: 1, y: 0 }}
   647→   647→                exit={{ opacity: 0, y: -10 }}
   648→   648→              >
   649→   649→                <Card className="border-destructive/50 bg-destructive/10">
   650→   650→                  <CardContent className="p-4 flex items-start gap-3">
   651→   651→                    <X className="w-5 h-5 text-destructive mt-0.5 shrink-0" />
   652→   652→                    <div>
   653→   653→                      <p className="text-sm font-medium text-destructive">حدث خطأ</p>
   654→   654→                      <p className="text-xs text-muted-foreground mt-1">{editError}</p>
   655→   655→                    </div>
   656→   656→                  </CardContent>
   657→   657→                </Card>
   658→   658→              </motion.div>
   659→   659→            )}
   660→   660→          </AnimatePresence>
   661→   661→        </div>
   662→   662→      </div>
   663→   663→    </main>
   664→   664→  );
   665→   665→}
   666→   666→
   667→   667→/* ─── Gallery View ─── */
   668→   668→function GalleryView() {
   669→   669→  const { projects, setProjects, setView, setOriginalImage, setOriginalFileName, setEditedImage, setAnalysis } = useAppStore();
   670→   670→  const [isLoading, setIsLoading] = useState(true);
   671→   671→
   672→   672→  useEffect(() => {
   673→   673→    const loadProjects = async () => {
   674→   674→      try {
   675→   675→        const res = await fetch('/api/projects');
   676→   676→        if (res.ok) {
   677→   677→          const data = await res.json();
   678→   678→          setProjects(data);
   679→   679→        }
   680→   680→      } catch {}
   681→   681→      setIsLoading(false);
   682→   682→    };
   683→   683→    loadProjects();
   684→   684→  }, [setProjects]);
   685→   685→
   686→   686→  const handleDelete = useCallback(async (id: string) => {
   687→   687→    try {
   688→   688→      const res = await fetch(`/api/projects/${id}`, { method: 'DELETE' });
   689→   689→      if (res.ok) {
   690→   690→        setProjects(projects.filter((p) => p.id !== id));
   691→   691→      }
   692→   692→    } catch {}
   693→   693→  }, [projects, setProjects]);
   694→   694→
   695→   695→  const handleOpen = useCallback((project: PhotoProject) => {
   696→   696→    const lastEdit = project.edits?.[project.edits.length - 1];
   697→   697→    if (lastEdit?.editedPath) {
   698→   698→      setOriginalImage(lastEdit.originalPath);
   699→   699→      setEditedImage(lastEdit.editedPath);
   700→   700→      setOriginalFileName(project.title);
   701→   701→      setAnalysis(null);
   702→   702→      setView('editor');
   703→   703→    } else if (lastEdit) {
   704→   704→      setOriginalImage(lastEdit.originalPath);
   705→   705→      setEditedImage(null);
   706→   706→      setOriginalFileName(project.title);
   707→   707→      setAnalysis(null);
   708→   708→      setView('editor');
   709→   709→    }
   710→   710→  }, [setOriginalImage, setEditedImage, setOriginalFileName, setAnalysis, setView]);
   711→   711→
   712→   712→  if (isLoading) {
   713→   713→    return (
   714→   714→      <main className="flex-1 flex items-center justify-center">
   715→   715→        <Loader2 className="w-8 h-8 text-primary animate-spin" />
   716→   716→      </main>
   717→   717→    );
   718→   718→  }
   719→   719→
   720→   720→  return (
   721→   721→    <main className="flex-1 px-4 py-8 max-w-6xl mx-auto w-full">
   722→   722→      <motion.div
   723→   723→        initial={{ opacity: 0, y: -10 }}
   724→   724→        animate={{ opacity: 1, y: 0 }}
   725→   725→        className="text-center mb-8"
   726→   726→      >
   727→   727→        <h2 className="text-3xl font-bold mb-2">
   728→   728→          <span className="gradient-text">المعرض</span>
   729→   729→        </h2>
   730→   730→        <p className="text-muted-foreground">جميع مشاريع تعديل الصور السابقة</p>
   731→   731→      </motion.div>
   732→   732→
   733→   733→      {projects.length === 0 ? (
   734→   734→        <motion.div
   735→   735→          initial={{ opacity: 0 }}
   736→   736→          animate={{ opacity: 1 }}
   737→   737→          className="text-center py-20"
   738→   738→        >
   739→   739→          <div className="w-20 h-20 rounded-full bg-muted/30 flex items-center justify-center mx-auto mb-4">
   740→   740→            <ImageIcon className="w-10 h-10 text-muted-foreground" />
   741→   741→          </div>
   742→   742→          <p className="text-lg text-muted-foreground mb-4">لا توجد مشاريع بعد</p>
   743→   743→          <Button onClick={() => setView('home')} className="gap-2">
   744→   744→            <Upload className="w-4 h-4" />
   745→   745→            ابدأ بتعديل صورة
   746→   746→          </Button>
   747→   747→        </motion.div>
   748→   748→      ) : (
   749→   749→        <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
   750→   750→          {projects.map((project, i) => {
   751→   751→            const lastEdit = project.edits?.[project.edits.length - 1];
   752→   752→            const thumbnail = lastEdit?.editedPath || lastEdit?.originalPath || '';
   753→   753→            return (
   754→   754→              <motion.div
   755→   755→                key={project.id}
   756→   756→                initial={{ opacity: 0, y: 20 }}
   757→   757→                animate={{ opacity: 1, y: 0 }}
   758→   758→                transition={{ delay: i * 0.05 }}
   759→   759→              >
   760→   760→                <Card className="glass overflow-hidden group cursor-pointer hover:border-primary/40 transition-all" onClick={() => handleOpen(project)}>
   761→   761→                  <div className="aspect-video bg-black/30 relative overflow-hidden">
   762→   762→                    {thumbnail ? (
   763→   763→                      <img src={thumbnail} alt={project.title} className="w-full h-full object-cover" />
   764→   764→                    ) : (
   765→   765→                      <div className="w-full h-full flex items-center justify-center">
   766→   766→                        <ImageIcon className="w-8 h-8 text-muted-foreground" />
   767→   767→                      </div>
   768→   768→                    )}
   769→   769→                    <div className="absolute inset-0 bg-black/0 group-hover:bg-black/30 transition-colors flex items-center justify-center">
   770→   770→                      <span className="opacity-0 group-hover:opacity-100 transition-opacity bg-white/20 backdrop-blur-sm px-3 py-1.5 rounded-lg text-sm font-medium">
   771→   771→                        فتح المشروع
   772→   772→                      </span>
   773→   773→                    </div>
   774→   774→                  </div>
   775→   775→                  <CardContent className="p-3 flex items-center justify-between">
   776→   776→                    <div>
   777→   777→                      <p className="font-medium text-sm truncate">{project.title}</p>
   778→   778→                      <p className="text-xs text-muted-foreground">
   779→   779→                        {new Date(project.createdAt).toLocaleDateString('ar-EG')}
   780→   780→                        {project.edits?.length ? ` — ${project.edits.length} تعديل` : ''}
   781→   781→                      </p>
   782→   782→                    </div>
   783→   783→                    <Button
   784→   784→                      variant="ghost"
   785→   785→                      size="icon"
   786→   786→                      className="h-8 w-8 text-muted-foreground hover:text-destructive shrink-0"
   787→   787→                      onClick={(e) => {
   788→   788→                        e.stopPropagation();
   789→   789→                        handleDelete(project.id);
   790→   790→                      }}
   791→   791→                    >
   792→   792→                      <Trash2 className="w-4 h-4" />
   793→   793→                    </Button>
   794→   794→                  </CardContent>
   795→   795→                </Card>
   796→   796→              </motion.div>
   797→   797→            );
   798→   798→          })}
   799→   799→        </div>
   800→   800→      )}
   801→   801→    </main>
   802→   802→  );
   803→   803→}
   804→   804→
   805→   805→/* ─── Main Client Component ─── */
   806→   806→export default function HomeClient() {
   807→   807→  const { currentView, editError, setEditError } = useAppStore();
   808→   808→
   809→   809→  // Dismiss errors on click outside
   810→   810→  useEffect(() => {
   811→   811→    if (editError) {
   812→   812→      const timer = setTimeout(() => setEditError(null), 8000);
   813→   813→      return () => clearTimeout(timer);
   814→   814→    }
   815→   815→  }, [editError, setEditError]);
   816→   816→
   817→   817→  return (
   818→   818→    <div className="min-h-screen flex flex-col">
   819→   819→      <Header />
   820→   820→      <AnimatePresence mode="wait">
   821→   821→        {currentView === 'home' && (
   822→   822→          <motion.div key="home" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} className="flex-1">
   823→   823→            <HomeView />
   824→   824→          </motion.div>
   825→   825→        )}
   826→   826→        {currentView === 'editor' && (
   827→   827→          <motion.div key="editor" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} className="flex-1 flex flex-col">
   828→   828→            <EditorView />
   829→   829→          </motion.div>
   830→   830→        )}
   831→   831→        {currentView === 'gallery' && (
   832→   832→          <motion.div key="gallery" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} className="flex-1">
   833→   833→            <GalleryView />
   834→   834→          </motion.div>
   835→   835→        )}
   836→   836→      </AnimatePresence>
   837→   837→      <Footer />
   838→   838→    </div>
   839→   839→  );
   840→   840→}