     1→'use client';
     2→
     3→import { useState, useCallback, useRef, useEffect } from 'react';
     4→import { motion, AnimatePresence } from 'framer-motion';
     5→import {
     6→  Upload, Image as ImageIcon, Sparkles, Download, ArrowRight,
     7→  Palette, Camera, Layers, SlidersHorizontal, Loader2, Check,
     8→  Trash2, RotateCcw, Eye, Wand2, Sun, Paintbrush, Film,
     9→  Pencil, History, ChevronLeft, X, GripVertical, WandSparkles,
    10→  Square, RectangleVertical, Monitor, Settings, Megaphone, Code,
    11→  LogIn, LogOut, Shield
    12→} from 'lucide-react';
    13→import { Button } from '@/components/ui/button';
    14→import { Textarea } from '@/components/ui/textarea';
    15→import { Progress } from '@/components/ui/progress';
    16→import { Card, CardContent } from '@/components/ui/card';
    17→import {
    18→  Dialog,
    19→  DialogContent,
    20→  DialogHeader,
    21→  DialogTitle,
    22→  DialogTrigger,
    23→} from '@/components/ui/dialog';
    24→import { Input } from '@/components/ui/input';
    25→import { Switch } from '@/components/ui/switch';
    26→import { Label } from '@/components/ui/label';
    27→import { useAppStore, type PhotoProject } from '@/store/photo-store';
    28→import { signIn, signOut } from 'next-auth/react';
    29→
    30→/* ─── Session Types ─── */
    31→interface SessionUser {
    32→  id: string;
    33→  name?: string | null;
    34→  email?: string | null;
    35→  image?: string | null;
    36→  role?: string;
    37→}
    38→
    39→/* ─── useAdminSession Hook ─── */
    40→function useAdminSession() {
    41→  const [isAdmin, setIsAdmin] = useState(false);
    42→  const [isLoading, setIsLoading] = useState(true);
    43→  const [userName, setUserName] = useState<string | null>(null);
    44→
    45→  const checkSession = useCallback(async () => {
    46→    try {
    47→      const res = await fetch('/api/auth/session');
    48→      if (!res.ok) { setIsAdmin(false); setIsLoading(false); return; }
    49→      const session = await res.json();
    50→      const role = (session?.user as SessionUser | undefined)?.role;
    51→      setIsAdmin(role === 'admin');
    52→      setUserName(session?.user?.name || null);
    53→    } catch {
    54→      setIsAdmin(false);
    55→    } finally {
    56→      setIsLoading(false);
    57→    }
    58→  }, []);
    59→
    60→  useEffect(() => { checkSession(); }, [checkSession]);
    61→
    62→  return { isAdmin, isLoading, userName, refresh: checkSession };
    63→}
    64→
    65→/* ─── Types ─── */
    66→interface BannerData {
    67→  id: string;
    68→  adType: string;
    69→  imageUrl: string;
    70→  adCode: string;
    71→  linkUrl: string;
    72→  text: string;
    73→  active: boolean;
    74→  position: string;
    75→}
    76→
    77→/* ─── Banner Display Component ─── */
    78→function BannerDisplay({ position }: { position: 'top' | 'above-upload' | 'below-features' }) {
    79→  const [banner, setBanner] = useState<BannerData | null>(null);
    80→  const [dismissed, setDismissed] = useState(false);
    81→
    82→  useEffect(() => {
    83→    fetch('/api/banner')
    84→      .then((r) => r.json())
    85→      .then((data) => {
    86→        if (data.banner && data.banner.position === position) {
    87→          setBanner(data.banner);
    88→        }
    89→      })
    90→      .catch(() => {});
    91→  }, [position]);
    92→
    93→  if (!banner || !banner.active || dismissed) return null;
    94→
    95→  // External ad code (Google AdSense, etc.)
    96→  if (banner.adType === 'external' && banner.adCode) {
    97→    return (
    98→      <motion.div
    99→        initial={{ opacity: 0, y: -10 }}
   100→        animate={{ opacity: 1, y: 0 }}
   101→        className="relative w-full max-w-4xl mx-auto"
   102→      >
   103→        <div className="rounded-xl overflow-hidden bg-card/50 border border-border/30 p-1">
   104→          <div
   105→            className="w-full min-h-[60px] flex items-center justify-center"
   106→            dangerouslySetInnerHTML={{ __html: banner.adCode }}
   107→          />
   108→        </div>
   109→        <button
   110→          onClick={() => setDismissed(true)}
   111→          className="absolute -top-2 -left-2 w-6 h-6 rounded-full bg-muted text-muted-foreground flex items-center justify-center hover:bg-muted-foreground hover:text-background transition-colors border border-border/50"
   112→          aria-label="إغلاق الإعلان"
   113→        >
   114→          <X className="w-3 h-3" />
   115→        </button>
   116→      </motion.div>
   117→    );
   118→  }
   119→
   120→  // Image banner
   121→  if (!banner.imageUrl) return null;
   122→
   123→  const Wrapper = banner.linkUrl ? 'a' : 'div';
   124→  const wrapperProps = banner.linkUrl
   125→    ? { href: banner.linkUrl, target: '_blank' as const, rel: 'noopener noreferrer' }
   126→    : {};
   127→
   128→  return (
   129→    <motion.div
   130→      initial={{ opacity: 0, y: -10 }}
   131→      animate={{ opacity: 1, y: 0 }}
   132→      className="relative w-full max-w-4xl mx-auto"
   133→    >
   134→      <Wrapper
   135→        {...wrapperProps}
   136→        className="block relative rounded-xl overflow-hidden"
   137→      >
   138→        <img
   139→          src={banner.imageUrl}
   140→          alt={banner.text || 'إعلان'}
   141→          className="w-full h-auto object-cover max-h-48 rounded-xl"
   142→        />
   143→        {banner.text && (
   144→          <div className="absolute inset-0 bg-gradient-to-t from-black/60 via-transparent to-transparent flex items-end p-4">
   145→            <p className="text-white text-sm sm:text-base font-medium">{banner.text}</p>
   146→          </div>
   147→        )}
   148→      </Wrapper>
   149→      <button
   150→        onClick={() => setDismissed(true)}
   151→        className="absolute top-2 left-2 w-6 h-6 rounded-full bg-black/50 text-white flex items-center justify-center hover:bg-black/70 transition-colors"
   152→        aria-label="إغلاق الإعلان"
   153→      >
   154→        <X className="w-3 h-3" />
   155→      </button>
   156→    </motion.div>
   157→  );
   158→}
   159→
   160→/* ─── Login Dialog ─── */
   161→function LoginDialog({ open, onOpenChange, onLoginSuccess }: { open: boolean; onOpenChange: (v: boolean) => void; onLoginSuccess: () => void }) {
   162→  const [username, setUsername] = useState('');
   163→  const [password, setPassword] = useState('');
   164→  const [loading, setLoading] = useState(false);
   165→  const [error, setError] = useState<string | null>(null);
   166→
   167→  const handleSubmit = useCallback(async (e: React.FormEvent) => {
   168→    e.preventDefault();
   169→    if (!username.trim() || !password.trim()) return;
   170→    setLoading(true);
   171→    setError(null);
   172→    try {
   173→      const res = await signIn('credentials', {
   174→        username,
   175→        password,
   176→        redirect: false,
   177→      });
   178→      if (res?.error) {
   179→        setError('اسم المستخدم أو كلمة المرور غير صحيحة');
   180→      } else {
   181→        setUsername('');
   182→        setPassword('');
   183→        onOpenChange(false);
   184→        onLoginSuccess();
   185→      }
   186→    } catch {
   187→      setError('حدث خطأ أثناء تسجيل الدخول');
   188→    } finally {
   189→      setLoading(false);
   190→    }
   191→  }, [username, password, onOpenChange, onLoginSuccess]);
   192→
   193→  return (
   194→    <Dialog open={open} onOpenChange={(v) => { if (!v) setError(null); onOpenChange(v); }}>
   195→      <DialogContent className="max-w-sm" dir="rtl">
   196→        <DialogHeader>
   197→          <DialogTitle className="flex items-center gap-2">
   198→            <Shield className="w-5 h-5 text-primary" />
   199→            تسجيل دخول المدير
   200→          </DialogTitle>
   201→        </DialogHeader>
   202→        <form onSubmit={handleSubmit} className="space-y-4 mt-2">
   203→          <div className="space-y-2">
   204→            <Label htmlFor="admin-user">اسم المستخدم</Label>
   205→            <Input
   206→              id="admin-user"
   207→              value={username}
   208→              onChange={(e) => setUsername(e.target.value)}
   209→              placeholder="admin"
   210→              autoComplete="username"
   211→              autoFocus
   212→            />
   213→          </div>
   214→          <div className="space-y-2">
   215→            <Label htmlFor="admin-pass">كلمة المرور</Label>
   216→            <Input
   217→              id="admin-pass"
   218→              type="password"
   219→              value={password}
   220→              onChange={(e) => setPassword(e.target.value)}
   221→              placeholder="••••••••"
   222→              autoComplete="current-password"
   223→            />
   224→          </div>
   225→          {error && (
   226→            <p className="text-sm text-red-500 bg-red-500/10 p-2 rounded-lg text-center">{error}</p>
   227→          )}
   228→          <Button type="submit" disabled={loading || !username.trim() || !password.trim()} className="w-full gap-2">
   229→            {loading ? <Loader2 className="w-4 h-4 animate-spin" /> : <LogIn className="w-4 h-4" />}
   230→            {loading ? 'جارٍ التحقق...' : 'تسجيل الدخول'}
   231→          </Button>
   232→        </form>
   233→      </DialogContent>
   234→    </Dialog>
   235→  );
   236→}
   237→
   238→/* ─── Banner Admin Panel ─── */
   239→function BannerAdmin({ open, onOpenChange }: { open: boolean; onOpenChange: (v: boolean) => void }) {
   240→  const [adType, setAdType] = useState<'image' | 'external'>('image');
   241→  const [imageUrl, setImageUrl] = useState('');
   242→  const [adCode, setAdCode] = useState('');
   243→  const [linkUrl, setLinkUrl] = useState('');
   244→  const [text, setText] = useState('');
   245→  const [active, setActive] = useState(false);
   246→  const [position, setPosition] = useState('top');
   247→  const [saving, setSaving] = useState(false);
   248→  const [uploading, setUploading] = useState(false);
   249→  const [message, setMessage] = useState<{ type: 'success' | 'error'; text: string } | null>(null);
   250→  const fileInputRef = useRef<HTMLInputElement>(null);
   251→
   252→  // Load existing banner on open
   253→  useEffect(() => {
   254→    if (!open) return;
   255→    fetch('/api/banner')
   256→      .then((r) => r.json())
   257→      .then((data) => {
   258→        if (data.banner) {
   259→          setAdType((data.banner.adType as 'image' | 'external') || 'image');
   260→          setImageUrl(data.banner.imageUrl || '');
   261→          setAdCode(data.banner.adCode || '');
   262→          setLinkUrl(data.banner.linkUrl);
   263→          setText(data.banner.text);
   264→          setActive(data.banner.active);
   265→          setPosition(data.banner.position);
   266→        } else {
   267→          setAdType('image');
   268→          setImageUrl('');
   269→          setAdCode('');
   270→          setLinkUrl('');
   271→          setText('');
   272→          setActive(false);
   273→          setPosition('top');
   274→        }
   275→        setMessage(null);
   276→      })
   277→      .catch(() => {});
   278→  }, [open]);
   279→
   280→  const handleUpload = useCallback(async (file: File) => {
   281→    if (!file.type.startsWith('image/')) return;
   282→    setUploading(true);
   283→    setMessage(null);
   284→    try {
   285→      const formData = new FormData();
   286→      formData.append('image', file);
   287→      const res = await fetch('/api/banner', { method: 'POST', body: formData });
   288→      const data = await res.json();
   289→      if (!res.ok) throw new Error(data.error || 'فشل رفع الصورة');
   290→      setImageUrl(data.imageUrl);
   291→    } catch (err: unknown) {
   292→      setMessage({ type: 'error', text: err instanceof Error ? err.message : 'خطأ' });
   293→    } finally {
   294→      setUploading(false);
   295→    }
   296→  }, []);
   297→
   298→  const handleSave = useCallback(async () => {
   299→    if (adType === 'image' && !imageUrl) {
   300→      setMessage({ type: 'error', text: 'يرجى رفع صورة البانر أولاً' });
   301→      return;
   302→    }
   303→    if (adType === 'external' && !adCode.trim()) {
   304→      setMessage({ type: 'error', text: 'يرجى لصق كود الإعلان الخارجي' });
   305→      return;
   306→    }
   307→    setSaving(true);
   308→    setMessage(null);
   309→    try {
   310→      const res = await fetch('/api/banner', {
   311→        method: 'PUT',
   312→        headers: { 'Content-Type': 'application/json' },
   313→        body: JSON.stringify({ adType, imageUrl, adCode, linkUrl, text, active, position }),
   314→      });
   315→      const data = await res.json();
   316→      if (!res.ok) throw new Error(data.error || 'فشل الحفظ');
   317→      setMessage({ type: 'success', text: 'تم حفظ البانر بنجاح' });
   318→    } catch (err: unknown) {
   319→      setMessage({ type: 'error', text: err instanceof Error ? err.message : 'خطأ' });
   320→    } finally {
   321→      setSaving(false);
   322→    }
   323→  }, [adType, imageUrl, adCode, linkUrl, text, active, position]);
   324→
   325→  const POSITION_OPTIONS = [
   326→    { value: 'top', label: 'أعلى الصفحة' },
   327→    { value: 'above-upload', label: 'فوق منطقة الرفع' },
   328→    { value: 'below-features', label: 'أسفل المميزات' },
   329→  ];
   330→
   331→  return (
   332→    <Dialog open={open} onOpenChange={onOpenChange}>
   333→      <DialogContent className="max-w-md max-h-[90vh] overflow-y-auto" dir="rtl">
   334→        <DialogHeader>
   335→          <DialogTitle className="flex items-center gap-2">
   336→            <Megaphone className="w-5 h-5" />
   337→            إدارة البانر الإعلاني
   338→          </DialogTitle>
   339→        </DialogHeader>
   340→
   341→        <div className="space-y-4 mt-2">
   342→          {/* Ad Type Selector */}
   343→          <div className="space-y-2">
   344→            <Label>نوع الإعلان</Label>
   345→            <div className="grid grid-cols-2 gap-2">
   346→              <button
   347→                onClick={() => setAdType('image')}
   348→                className={`p-3 rounded-lg border text-sm font-medium transition-all flex flex-col items-center gap-1.5 ${
   349→                  adType === 'image'
   350→                    ? 'border-primary bg-primary/10 text-primary'
   351→                    : 'border-border/50 hover:border-primary/30 text-muted-foreground'
   352→                }`}
   353→              >
   354→                <ImageIcon className="w-5 h-5" />
   355→                صورة مرفوعة
   356→              </button>
   357→              <button
   358→                onClick={() => setAdType('external')}
   359→                className={`p-3 rounded-lg border text-sm font-medium transition-all flex flex-col items-center gap-1.5 ${
   360→                  adType === 'external'
   361→                    ? 'border-primary bg-primary/10 text-primary'
   362→                    : 'border-border/50 hover:border-primary/30 text-muted-foreground'
   363→                }`}
   364→              >
   365→                <Code className="w-5 h-5" />
   366→                كود خارجي
   367→              </button>
   368→            </div>
   369→          </div>
   370→
   371→          {/* Image Upload (only for image type) */}
   372→          {adType === 'image' && (
   373→            <div className="space-y-2">
   374→              <Label>صورة البانر</Label>
   375→              <div
   376→                onClick={() => !uploading && fileInputRef.current?.click()}
   377→                className={`relative rounded-lg border-2 border-dashed p-4 text-center cursor-pointer transition-all
   378→                  ${imageUrl ? 'border-primary/30' : 'border-muted-foreground/30 hover:border-primary/50'}`}
   379→              >
   380→                <input
   381→                  ref={fileInputRef}
   382→                  type="file"
   383→                  accept="image/*"
   384→                  className="hidden"
   385→                  onChange={(e) => {
   386→                    const f = e.target.files?.[0];
   387→                    if (f) handleUpload(f);
   388→                    e.target.value = '';
   389→                  }}
   390→                />
   391→                {uploading ? (
   392→                  <div className="flex items-center justify-center gap-2 py-2">
   393→                    <Loader2 className="w-5 h-5 animate-spin text-primary" />
   394→                    <span className="text-sm text-muted-foreground">جارٍ الرفع...</span>
   395→                  </div>
   396→                ) : imageUrl ? (
   397→                  <div className="space-y-2">
   398→                    <img src={imageUrl} alt="بانر" className="w-full h-24 object-cover rounded-md" />
   399→                    <p className="text-xs text-muted-foreground">انقر لتغيير الصورة</p>
   400→                  </div>
   401→                ) : (
   402→                  <div className="py-2">
   403→                    <Upload className="w-8 h-8 mx-auto text-muted-foreground/50 mb-2" />
   404→                    <p className="text-sm text-muted-foreground">انقر لاختيار صورة البانر</p>
   405→                    <p className="text-xs text-muted-foreground mt-1">PNG, JPG, WEBP — حتى 2 ميجا</p>
   406→                  </div>
   407→                )}
   408→              </div>
   409→            </div>
   410→          )}
   411→
   412→          {/* External Ad Code (only for external type) */}
   413→          {adType === 'external' && (
   414→            <div className="space-y-2">
   415→              <Label>كود الإعلان الخارجي</Label>
   416→              <p className="text-xs text-muted-foreground">
   417→                الصق كود الإعلان من جوجل أدسنس أو أي شبكة إعلانية أخرى
   418→              </p>
   419→              <Textarea
   420→                value={adCode}
   421→                onChange={(e) => setAdCode(e.target.value)}
   422→                placeholder={'<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-XXXXX"></script>\n<ins class="adsbygoogle" ...></ins>'}
   423→                className="min-h-[120px] font-mono text-xs"
   424→                dir="ltr"
   425→              />
   426→            </div>
   427→          )}
   428→
   429→          {/* Link URL (only for image type) */}
   430→          {adType === 'image' && (
   431→            <div className="space-y-2">
   432→              <Label>رابط الإعلان (اختياري)</Label>
   433→              <Input
   434→                value={linkUrl}
   435→                onChange={(e) => setLinkUrl(e.target.value)}
   436→                placeholder="https://example.com"
   437→                dir="ltr"
   438→              />
   439→            </div>
   440→          )}
   441→
   442→          {/* Text Overlay (only for image type) */}
   443→          {adType === 'image' && (
   444→            <div className="space-y-2">
   445→              <Label>نص على البانر (اختياري)</Label>
   446→              <Input
   447→                value={text}
   448→                onChange={(e) => setText(e.target.value)}
   449→                placeholder="عنوان الإعلان..."
   450→              />
   451→            </div>
   452→          )}
   453→
   454→          {/* Position */}
   455→          <div className="space-y-2">
   456→            <Label>موضع البانر</Label>
   457→            <div className="grid grid-cols-3 gap-2">
   458→              {POSITION_OPTIONS.map((opt) => (
   459→                <button
   460→                  key={opt.value}
   461→                  onClick={() => setPosition(opt.value)}
   462→                  className={`p-2 rounded-lg border text-xs font-medium transition-all
   463→                    ${position === opt.value
   464→                      ? 'border-primary bg-primary/10 text-primary'
   465→                      : 'border-border/50 hover:border-primary/30 text-muted-foreground'}`}
   466→                >
   467→                  {opt.label}
   468→                </button>
   469→              ))}
   470→            </div>
   471→          </div>
   472→
   473→          {/* Active Toggle */}
   474→          <div className="flex items-center justify-between p-3 rounded-lg border border-border/50">
   475→            <Label className="cursor-pointer">عرض البانر</Label>
   476→            <Switch checked={active} onCheckedChange={setActive} />
   477→          </div>
   478→
   479→          {/* Message */}
   480→          <AnimatePresence>
   481→            {message && (
   482→              <motion.div
   483→                initial={{ opacity: 0, y: -5 }}
   484→                animate={{ opacity: 1, y: 0 }}
   485→                exit={{ opacity: 0 }}
   486→                className={`text-sm p-3 rounded-lg ${message.type === 'success' ? 'bg-emerald-500/10 text-emerald-600' : 'bg-red-500/10 text-red-600'}`}
   487→              >
   488→                {message.text}
   489→              </motion.div>
   490→            )}
   491→          </AnimatePresence>
   492→
   493→          {/* Save Button */}
   494→          <Button
   495→            onClick={handleSave}
   496→            disabled={saving || (adType === 'image' ? !imageUrl : !adCode.trim())}
   497→            className="w-full gap-2"
   498→          >
   499→            {saving ? <Loader2 className="w-4 h-4 animate-spin" /> : <Check className="w-4 h-4" />}
   500→            {saving ? 'جارٍ الحفظ...' : 'حفظ البانر'}
   501→          </Button>
   502→        </div>
   503→      </DialogContent>
   504→    </Dialog>
   505→  );
   506→}
   507→
   508→/* ─── Edit Tool Definitions ─── */
   509→const EDIT_TOOLS = [
   510→  { 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' },
   511→  { 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' },
   512→  { 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' },
   513→  { 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' },
   514→  { 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' },
   515→  { id: 'bg-remove', label: 'خلفية احترافية', icon: Layers, prompt: 'Enhance this photo with a clean neutral studio background while preserving the main subject naturally', color: 'from-cyan-500/20 to-blue-600/20' },
   516→  { 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' },
   517→  { 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' },
   518→];
   519→
   520→/* ─── Header Component ─── */
   521→function Header({
   522→  isAdmin,
   523→  isLoading,
   524→  onOpenBannerAdmin,
   525→  onOpenLogin,
   526→  onLogout,
   527→}: {
   528→  isAdmin: boolean;
   529→  isLoading: boolean;
   530→  onOpenBannerAdmin: () => void;
   531→  onOpenLogin: () => void;
   532→  onLogout: () => void;
   533→}) {
   534→  const { currentView, setView } = useAppStore();
   535→  return (
   536→    <header className="glass sticky top-0 z-50">
   537→      <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-16 flex items-center justify-between">
   538→        <button
   539→          onClick={() => setView('home')}
   540→          className="flex items-center gap-3 group"
   541→        >
   542→          <div className="w-9 h-9 rounded-lg bg-primary/20 flex items-center justify-center">
   543→            <Wand2 className="w-5 h-5 text-primary" />
   544→          </div>
   545→          <span className="text-lg font-bold gradient-text">محرر الصور Fouad AI</span>
   546→        </button>
   547→        <nav className="flex items-center gap-1">
   548→          <Button
   549→            variant={currentView === 'home' ? 'default' : 'ghost'}
   550→            size="sm"
   551→            onClick={() => setView('home')}
   552→            className="gap-2"
   553→          >
   554→            <ImageIcon className="w-4 h-4" />
   555→            <span className="hidden sm:inline">الرئيسية</span>
   556→          </Button>
   557→          <Button
   558→            variant={currentView === 'gallery' ? 'default' : 'ghost'}
   559→            size="sm"
   560→            onClick={() => setView('gallery')}
   561→            className="gap-2"
   562→          >
   563→            <History className="w-4 h-4" />
   564→            <span className="hidden sm:inline">المعرض</span>
   565→          </Button>
   566→          <Button
   567→            variant={currentView === 'generate' ? 'default' : 'ghost'}
   568→            size="sm"
   569→            onClick={() => setView('generate')}
   570→            className="gap-2"
   571→          >
   572→            <WandSparkles className="w-4 h-4" />
   573→            <span className="hidden sm:inline">توليد الصور</span>
   574→          </Button>
   575→          {!isLoading && (
   576→            isAdmin ? (
   577→              <>
   578→                <Button
   579→                  variant="ghost"
   580→                  size="icon"
   581→                  className="mr-1"
   582→                  onClick={onOpenBannerAdmin}
   583→                  title="إدارة البانر"
   584→                >
   585→                  <Settings className="w-4 h-4" />
   586→                </Button>
   587→                <Button
   588→                  variant="ghost"
   589→                  size="icon"
   590→                  onClick={onLogout}
   591→                  title="تسجيل الخروج"
   592→                  className="text-red-400 hover:text-red-300 hover:bg-red-500/10"
   593→                >
   594→                  <LogOut className="w-4 h-4" />
   595→                </Button>
   596→              </>
   597→            ) : (
   598→              <Button
   599→                variant="ghost"
   600→                size="icon"
   601→                className="mr-1"
   602→                onClick={onOpenLogin}
   603→                title="دخول المدير"
   604→              >
   605→                <LogIn className="w-4 h-4" />
   606→              </Button>
   607→            )
   608→          )}
   609→        </nav>
   610→      </div>
   611→    </header>
   612→  );
   613→}
   614→
   615→/* ─── Footer Component ─── */
   616→function Footer() {
   617→  return (
   618→    <footer className="glass mt-auto">
   619→      <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">
   620→        <p>محرر الصور Fouad AI — قوّة الذكاء الاصطناعي بين يديك</p>
   621→        <p>© {new Date().getFullYear()} جميع الحقوق محفوظة</p>
   622→      </div>
   623→    </footer>
   624→  );
   625→}
   626→
   627→/* ─── Upload Area Component ─── */
   628→function UploadArea() {
   629→  const { setOriginalImage, setOriginalFileName, setView, setAnalysis, setEditedImage, setEditError } = useAppStore();
   630→  const [isDragOver, setIsDragOver] = useState(false);
   631→  const [isUploading, setIsUploading] = useState(false);
   632→  const fileInputRef = useRef<HTMLInputElement>(null);
   633→
   634→  const handleFile = useCallback(async (file: File) => {
   635→    if (!file.type.startsWith('image/')) return;
   636→    setIsUploading(true);
   637→    setEditError(null);
   638→    setEditedImage(null);
   639→    setAnalysis(null);
   640→    try {
   641→      const formData = new FormData();
   642→      formData.append('image', file);
   643→
   644→      const res = await fetch('/api/upload', { method: 'POST', body: formData });
   645→      const data = await res.json();
   646→      if (!res.ok) throw new Error(data.error || 'فشل رفع الصورة');
   647→
   648→      setOriginalImage(data.imageUrl);
   649→      setOriginalFileName(file.name);
   650→      setView('editor');
   651→    } catch (err: unknown) {
   652→      const message = err instanceof Error ? err.message : 'حدث خطأ';
   653→      setEditError(message);
   654→    } finally {
   655→      setIsUploading(false);
   656→    }
   657→  }, [setOriginalImage, setOriginalFileName, setView, setEditedImage, setAnalysis, setEditError]);
   658→
   659→  const onDrop = useCallback((e: React.DragEvent) => {
   660→    e.preventDefault();
   661→    setIsDragOver(false);
   662→    const file = e.dataTransfer.files[0];
   663→    if (file) handleFile(file);
   664→  }, [handleFile]);
   665→
   666→  const onDragOver = useCallback((e: React.DragEvent) => {
   667→    e.preventDefault();
   668→    setIsDragOver(true);
   669→  }, []);
   670→
   671→  const onDragLeave = useCallback(() => setIsDragOver(false), []);
   672→
   673→  return (
   674→    <motion.div
   675→      initial={{ opacity: 0, y: 30 }}
   676→      animate={{ opacity: 1, y: 0 }}
   677→      transition={{ duration: 0.6 }}
   678→      className="w-full max-w-2xl mx-auto"
   679→    >
   680→      <div
   681→        onDrop={onDrop}
   682→        onDragOver={onDragOver}
   683→        onDragLeave={onDragLeave}
   684→        onClick={() => fileInputRef.current?.click()}
   685→        className={`
   686→          relative cursor-pointer rounded-2xl border-2 border-dashed p-12 sm:p-16
   687→          transition-all duration-300 text-center
   688→          ${isDragOver
   689→            ? 'upload-area-active border-primary'
   690→            : 'border-muted-foreground/30 hover:border-primary/50 hover:bg-primary/5'
   691→          }
   692→        `}
   693→      >
   694→        <input
   695→          ref={fileInputRef}
   696→          type="file"
   697→          accept="image/*"
   698→          className="hidden"
   699→          onChange={(e) => {
   700→            const file = e.target.files?.[0];
   701→            if (file) handleFile(file);
   702→            e.target.value = '';
   703→          }}
   704→        />
   705→        {isUploading ? (
   706→          <div className="flex flex-col items-center gap-4">
   707→            <Loader2 className="w-12 h-12 text-primary animate-spin" />
   708→            <p className="text-lg text-muted-foreground">جارٍ رفع الصورة...</p>
   709→          </div>
   710→        ) : (
   711→          <div className="flex flex-col items-center gap-4">
   712→            <div className="w-20 h-20 rounded-full bg-primary/10 flex items-center justify-center">
   713→              <Upload className="w-10 h-10 text-primary" />
   714→            </div>
   715→            <div>
   716→              <p className="text-xl font-semibold mb-2">اسحب الصورة هنا أو انقر للاختيار</p>
   717→              <p className="text-muted-foreground text-sm">يدعم: PNG, JPG, WEBP — حتى 10 ميجا</p>
   718→            </div>
   719→          </div>
   720→        )}
   721→      </div>
   722→    </motion.div>
   723→  );
   724→}
   725→
   726→/* ─── Feature Cards ─── */
   727→function FeatureCards() {
   728→  const features = [
   729→    { icon: Sparkles, title: 'تحرير بالذكاء', desc: 'أدوات تعديل ذكية تفهم صورتك وتحسّنها' },
   730→    { icon: Palette, title: 'أنماط فنية', desc: 'حوّل صورك إلى لوحات زيتية أو رسوم كرتونية' },
   731→    { icon: SlidersHorizontal, title: 'مقارنة فورية', desc: 'قارن بين الأصل والنسخة المحرّرة بسهولة' },
   732→    { icon: Download, title: 'تحميل مباشر', desc: 'حمّل الصور المحرّرة بجودة عالية' },
   733→  ];
   734→  return (
   735→    <div className="grid grid-cols-2 lg:grid-cols-4 gap-4 max-w-5xl mx-auto mt-16">
   736→      {features.map((f, i) => (
   737→        <motion.div
   738→          key={f.title}
   739→          initial={{ opacity: 0, y: 20 }}
   740→          animate={{ opacity: 1, y: 0 }}
   741→          transition={{ duration: 0.5, delay: 0.2 + i * 0.1 }}
   742→        >
   743→          <Card className="glass h-full text-center p-4 sm:p-6">
   744→            <CardContent className="p-0 flex flex-col items-center gap-3">
   745→              <div className="w-12 h-12 rounded-xl bg-primary/15 flex items-center justify-center">
   746→                <f.icon className="w-6 h-6 text-primary" />
   747→              </div>
   748→              <h3 className="font-semibold text-sm sm:text-base">{f.title}</h3>
   749→              <p className="text-xs sm:text-sm text-muted-foreground">{f.desc}</p>
   750→            </CardContent>
   751→          </Card>
   752→        </motion.div>
   753→      ))}
   754→    </div>
   755→  );
   756→}
   757→
   758→/* ─── Home View ─── */
   759→function HomeView() {
   760→  return (
   761→    <main className="flex-1 flex flex-col items-center px-4 py-12">
   762→      <div className="my-6">
   763→        <BannerDisplay position="above-upload" />
   764→      </div>
   765→      <motion.div
   766→        initial={{ opacity: 0, y: -20 }}
   767→        animate={{ opacity: 1, y: 0 }}
   768→        transition={{ duration: 0.5 }}
   769→        className="text-center mb-10"
   770→      >
   771→        <h1 className="text-4xl sm:text-5xl lg:text-6xl font-bold mb-4">
   772→          <span className="gradient-text">محرر الصور Fouad AI</span>
   773→        </h1>
   774→        <p className="text-lg sm:text-xl text-muted-foreground max-w-xl mx-auto">
   775→          ارفع صورتك واختر التأثير المطلوب — وشاهد الذكاء الاصطناعي يُبدع
   776→        </p>
   777→      </motion.div>
   778→      <UploadArea />
   779→      <FeatureCards />
   780→      <div className="my-6">
   781→        <BannerDisplay position="below-features" />
   782→      </div>
   783→    </main>
   784→  );
   785→}
   786→
   787→/* ─── Before/After Comparison Slider ─── */
   788→function ComparisonSlider({ original, edited }: { original: string; edited: string }) {
   789→  const containerRef = useRef<HTMLDivElement>(null);
   790→  const [position, setPosition] = useState(50);
   791→  const [containerWidth, setContainerWidth] = useState(0);
   792→  const isDragging = useRef(false);
   793→
   794→  useEffect(() => {
   795→    const el = containerRef.current;
   796→    if (!el) return;
   797→    const observer = new ResizeObserver((entries) => {
   798→      for (const entry of entries) {
   799→        setContainerWidth(entry.contentRect.width);
   800→      }
   801→    });
   802→    observer.observe(el);
   803→    return () => observer.disconnect();
   804→  }, []);
   805→
   806→  const updatePosition = useCallback((clientX: number) => {
   807→    if (!containerRef.current) return;
   808→    const rect = containerRef.current.getBoundingClientRect();
   809→    // RTL: position is measured from the right edge
   810→    const x = clientX - rect.left;
   811→    const pct = Math.min(100, Math.max(0, (x / rect.width) * 100));
   812→    setPosition(pct);
   813→  }, []);
   814→
   815→  const handlePointerDown = useCallback((e: React.PointerEvent) => {
   816→    isDragging.current = true;
   817→    (e.target as HTMLElement).setPointerCapture(e.pointerId);
   818→    updatePosition(e.clientX);
   819→  }, [updatePosition]);
   820→
   821→  const handlePointerMove = useCallback((e: React.PointerEvent) => {
   822→    if (!isDragging.current) return;
   823→    updatePosition(e.clientX);
   824→  }, [updatePosition]);
   825→
   826→  const handlePointerUp = useCallback(() => {
   827→    isDragging.current = false;
   828→  }, []);
   829→
   830→  return (
   831→    <div
   832→      ref={containerRef}
   833→      className="comparison-container rounded-xl overflow-hidden bg-black/50 relative w-full"
   834→      style={{ aspectRatio: 'auto' }}
   835→      onPointerDown={handlePointerDown}
   836→      onPointerMove={handlePointerMove}
   837→      onPointerUp={handlePointerUp}
   838→    >
   839→      {/* Edited image (full width, behind) */}
   840→      <img
   841→        src={edited}
   842→        alt="After"
   843→        className="w-full h-auto block"
   844→        draggable={false}
   845→      />
   846→
   847→      {/* Original image (clipped from right in RTL) */}
   848→      <div
   849→        className="absolute inset-0 overflow-hidden"
   850→        style={{ width: `${position}%` }}
   851→      >
   852→        <img
   853→          src={original}
   854→          alt="Before"
   855→          className="w-full h-auto block"
   856→          style={{ width: containerWidth > 0 ? `${containerWidth}px` : '100%' }}
   857→          draggable={false}
   858→        />
   859→      </div>
   860→
   861→      {/* Slider line */}
   862→      <div
   863→        className="comparison-slider-line"
   864→        style={{ left: `${position}%` }}
   865→      >
   866→        <div className="comparison-slider-handle">
   867→          <GripVertical className="w-5 h-5 text-gray-700" />
   868→        </div>
   869→      </div>
   870→
   871→      {/* Labels */}
   872→      <div className="absolute top-3 right-3 bg-black/60 text-white text-xs px-2 py-1 rounded-md">الأصلي</div>
   873→      <div className="absolute top-3 left-3 bg-primary/80 text-white text-xs px-2 py-1 rounded-md">المحرّر</div>
   874→    </div>
   875→  );
   876→}
   877→
   878→/* ─── Editor View ─── */
   879→function EditorView() {
   880→  const {
   881→    originalImage, editedImage, isEditing, editProgress, editError,
   882→    analysis, customPrompt, setCustomPrompt, setEditedImage,
   883→    setEditProgress, setIsEditing, setEditError, setAnalysis,
   884→    setView, resetEditor, projects, setProjects, originalFileName,
   885→  } = useAppStore();
   886→  const [selectedTool, setSelectedTool] = useState<string | null>(null);
   887→  const [lastEditArgs, setLastEditArgs] = useState<{ prompt: string; label: string; toolType: string } | null>(null);
   888→  const [editCount, setEditCount] = useState(0);
   889→  const [isAnalyzing, setIsAnalyzing] = useState(false);
   890→  const fileInputRef = useRef<HTMLInputElement>(null);
   891→
   892→  const handleAnalyze = useCallback(async () => {
   893→    if (!originalImage) return;
   894→    setIsAnalyzing(true);
   895→    try {
   896→      const res = await fetch('/api/analyze', {
   897→        method: 'POST',
   898→        headers: { 'Content-Type': 'application/json' },
   899→        body: JSON.stringify({ imageUrl: originalImage }),
   900→      });
   901→      const data = await res.json();
   902→      if (!res.ok) throw new Error(data.error || 'فشل التحليل');
   903→      setAnalysis(data.analysis);
   904→    } catch (err: unknown) {
   905→      const message = err instanceof Error ? err.message : 'حدث خطأ';
   906→      setEditError(message);
   907→    } finally {
   908→      setIsAnalyzing(false);
   909→    }
   910→  }, [originalImage, setAnalysis, setEditError]);
   911→
   912→  const handleEdit = useCallback(async (prompt: string, label: string, toolType: string) => {
   913→    // Use the last edited image as base for stacking edits
   914→    const baseImage = editedImage || originalImage;
   915→    if (!baseImage) return;
   916→    setLastEditArgs({ prompt, label, toolType });
   917→    setIsEditing(true);
   918→    setEditError(null);
   919→    setEditedImage(null);
   920→    setEditProgress(0);
   921→
   922→    try {
   923→      const res = await fetch('/api/edit', {
   924→        method: 'POST',
   925→        headers: { 'Content-Type': 'application/json' },
   926→        body: JSON.stringify({
   927→          imageUrl: baseImage,
   928→          prompt,
   929→          label,
   930→          toolType,
   931→        }),
   932→      });
   933→
   934→      if (!res.ok) {
   935→        const data = await res.json();
   936→        throw new Error(data.error || 'فشل التعديل');
   937→      }
   938→
   939→      const reader = res.body?.getReader();
   940→      if (!reader) throw new Error('لا يمكن قراءة الاستجابة');
   941→
   942→      const decoder = new TextDecoder();
   943→      let buffer = '';
   944→
   945→      while (true) {
   946→        const { done, value } = await reader.read();
   947→        if (done) break;
   948→
   949→        buffer += decoder.decode(value, { stream: true });
   950→        const lines = buffer.split('\n');
   951→        buffer = lines.pop() || '';
   952→
   953→        for (const line of lines) {
   954→          if (line.startsWith('data: ')) {
   955→            const data = line.slice(6);
   956→            let parsed: Record<string, unknown>;
   957→            try {
   958→              parsed = JSON.parse(data);
   959→            } catch {
   960→              continue; // Skip malformed JSON lines
   961→            }
   962→
   963→            if (parsed.type === 'progress') {
   964→              setEditProgress(parsed.value as number);
   965→            } else if (parsed.type === 'done') {
   966→              setEditedImage(parsed.editedImageUrl as string);
   967→              setEditProgress(100);
   968→              setEditCount((c) => c + 1);
   969→              // Refresh gallery
   970→              try {
   971→                const projectsRes = await fetch('/api/projects');
   972→                if (projectsRes.ok) {
   973→                  const projectsData = await projectsRes.json();
   974→                  setProjects(projectsData);
   975→                }
   976→              } catch { /* ignore gallery refresh failure */ }
   977→            } else if (parsed.type === 'error') {
   978→              throw new Error(parsed.message as string);
   979→            }
   980→          }
   981→        }
   982→      }
   983→    } catch (err: unknown) {
   984→      const message = err instanceof Error ? err.message : 'حدث خطأ أثناء التعديل';
   985→      setEditError(message);
   986→    } finally {
   987→      setIsEditing(false);
   988→      setSelectedTool(null);
   989→    }
   990→  }, [originalImage, editedImage, setIsEditing, setEditError, setEditedImage, setEditProgress, setProjects]);
   991→
   992→  const handleCustomEdit = useCallback(() => {
   993→    if (!customPrompt.trim()) return;
   994→    handleEdit(customPrompt.trim(), 'تعديل مخصص', 'custom');
   995→  }, [customPrompt, handleEdit]);
   996→
   997→  const handleNewImage = useCallback(() => {
   998→    resetEditor();
   999→    setView('home');
  1000→  }, [resetEditor, setView]);
  1001→
  1002→  const handleResetToOriginal = useCallback(() => {
  1003→    setEditedImage(null);
  1004→    setEditCount(0);
  1005→    setEditError(null);
  1006→  }, [setEditedImage, setEditError]);
  1007→
  1008→  const handleReupload = useCallback(async (e: React.ChangeEvent<HTMLInputElement>) => {
  1009→    const file = e.target.files?.[0];
  1010→    if (!file || !file.type.startsWith('image/')) return;
  1011→    const formData = new FormData();
  1012→    formData.append('image', file);
  1013→    try {
  1014→      const res = await fetch('/api/upload', { method: 'POST', body: formData });
  1015→      const data = await res.json();
  1016→      if (!res.ok) throw new Error(data.error);
  1017→      useAppStore.getState().setOriginalImage(data.imageUrl);
  1018→      useAppStore.getState().setOriginalFileName(file.name);
  1019→      useAppStore.getState().setEditedImage(null);
  1020→      useAppStore.getState().setAnalysis(null);
  1021→    } catch {}
  1022→    e.target.value = '';
  1023→  }, []);
  1024→
  1025→  const handleDownload = useCallback(() => {
  1026→    if (!editedImage) return;
  1027→    const a = document.createElement('a');
  1028→    a.href = editedImage;
  1029→    const ext = originalFileName?.split('.').pop() || 'png';
  1030→    const baseName = originalFileName ? originalFileName.replace(/\.[^.]+$/, '') : 'image';
  1031→    a.download = `Fouad-AI-${baseName}.${ext}`;
  1032→    a.click();
  1033→  }, [editedImage, originalFileName]);
  1034→
  1035→  return (
  1036→    <main className="flex-1 px-4 py-6 max-w-7xl mx-auto w-full">
  1037→      {/* Top bar */}
  1038→      <div className="flex items-center justify-between mb-6">
  1039→        <div className="flex items-center gap-2">
  1040→          <Button variant="ghost" onClick={handleNewImage} className="gap-2">
  1041→            <ChevronLeft className="w-4 h-4" />
  1042→            صورة جديدة
  1043→          </Button>
  1044→          {editedImage && (
  1045→            <Button variant="outline" size="sm" onClick={handleResetToOriginal} className="gap-1.5 text-xs">
  1046→              <RotateCcw className="w-3.5 h-3.5" />
  1047→              العودة للأصل
  1048→            </Button>
  1049→          )}
  1050→          {editCount > 0 && (
  1051→            <span className="text-xs text-muted-foreground bg-muted/50 px-2 py-1 rounded-full">
  1052→              {editCount} تعديل{editCount > 1 ? 'ات' : ''}
  1053→            </span>
  1054→          )}
  1055→        </div>
  1056→        {editedImage && (
  1057→          <Button onClick={handleDownload} className="gap-2">
  1058→            <Download className="w-4 h-4" />
  1059→            تحميل الصورة
  1060→          </Button>
  1061→        )}
  1062→      </div>
  1063→
  1064→      <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
  1065→        {/* Image Preview (2/3 width on desktop) */}
  1066→        <div className="lg:col-span-2">
  1067→          <Card className="glass overflow-hidden">
  1068→            <CardContent className="p-0 relative">
  1069→              {/* Image display */}
  1070→              <div className="relative min-h-[300px] sm:min-h-[400px] flex items-center justify-center bg-black/30">
  1071→                {isEditing && (
  1072→                  <div className="absolute inset-0 z-20 flex flex-col items-center justify-center bg-black/50 backdrop-blur-sm">
  1073→                    <Loader2 className="w-12 h-12 text-primary animate-spin mb-4" />
  1074→                    <p className="text-lg font-semibold mb-2">جارٍ التعديل بالذكاء الاصطناعي...</p>
  1075→                    <Progress value={editProgress} className="w-48 h-2" />
  1076→                    <p className="text-sm text-muted-foreground mt-2">{editProgress}%</p>
  1077→                  </div>
  1078→                )}
  1079→
  1080→                {editedImage ? (
  1081→                  <ComparisonSlider original={originalImage!} edited={editedImage} />
  1082→                ) : (
  1083→                  <img
  1084→                    src={originalImage!}
  1085→                    alt="Original"
  1086→                    className="max-w-full max-h-[70vh] object-contain mx-auto"
  1087→                  />
  1088→                )}
  1089→              </div>
  1090→
  1091→              {/* Image info bar */}
  1092→              <div className="p-3 border-t border-border/50 flex items-center justify-between text-sm text-muted-foreground">
  1093→                <span className="truncate max-w-[60%]">{originalFileName || 'صورة'}</span>
  1094→                <Button variant="ghost" size="sm" className="gap-1 text-xs h-8" onClick={() => fileInputRef.current?.click()}>
  1095→                  <RotateCcw className="w-3 h-3" />
  1096→                  تغيير الصورة
  1097→                </Button>
  1098→                <input ref={fileInputRef} type="file" accept="image/*" className="hidden" onChange={handleReupload} />
  1099→              </div>
  1100→            </CardContent>
  1101→          </Card>
  1102→
  1103→          {/* Analysis section */}
  1104→          <div className="mt-4">
  1105→            <Button
  1106→              variant="outline"
  1107→              onClick={handleAnalyze}
  1108→              disabled={isAnalyzing || !originalImage}
  1109→              className="w-full gap-2 mb-3"
  1110→            >
  1111→              {isAnalyzing ? (
  1112→                <Loader2 className="w-4 h-4 animate-spin" />
  1113→              ) : (
  1114→                <Eye className="w-4 h-4" />
  1115→              )}
  1116→              تحليل الصورة بالذكاء الاصطناعي
  1117→            </Button>
  1118→            <AnimatePresence>
  1119→              {analysis && (
  1120→                <motion.div
  1121→                  initial={{ opacity: 0, height: 0 }}
  1122→                  animate={{ opacity: 1, height: 'auto' }}
  1123→                  exit={{ opacity: 0, height: 0 }}
  1124→                >
  1125→                  <Card className="glass">
  1126→                    <CardContent className="p-4">
  1127→                      <h3 className="text-sm font-semibold mb-2 flex items-center gap-2">
  1128→                        <Eye className="w-4 h-4 text-primary" />
  1129→                        نتيجة التحليل
  1130→                      </h3>
  1131→                      <p className="text-sm text-muted-foreground leading-relaxed whitespace-pre-wrap">{analysis}</p>
  1132→                    </CardContent>
  1133→                  </Card>
  1134→                </motion.div>
  1135→              )}
  1136→            </AnimatePresence>
  1137→          </div>
  1138→        </div>
  1139→
  1140→        {/* Tools Panel (1/3 width on desktop) */}
  1141→        <div className="lg:col-span-1 space-y-4">
  1142→          {/* Quick Tools */}
  1143→          <Card className="glass">
  1144→            <CardContent className="p-4">
  1145→              <h3 className="font-semibold mb-3 flex items-center gap-2">
  1146→                <Wand2 className="w-4 h-4 text-primary" />
  1147→                أدوات التحرير السريعة
  1148→              </h3>
  1149→              <div className="grid grid-cols-2 gap-2">
  1150→                {EDIT_TOOLS.map((tool) => {
  1151→                  const Icon = tool.icon;
  1152→                  const isLoading = isEditing && selectedTool === tool.id;
  1153→                  return (
  1154→                    <button
  1155→                      key={tool.id}
  1156→                      onClick={() => {
  1157→                        if (isEditing) return;
  1158→                        setSelectedTool(tool.id);
  1159→                        handleEdit(tool.prompt, tool.label, 'quick-tool');
  1160→                      }}
  1161→                      disabled={isEditing}
  1162→                      className={`
  1163→                        tool-card relative flex flex-col items-center gap-2 p-3 rounded-xl
  1164→                        border border-border/50 text-center transition-all
  1165→                        ${isLoading ? 'ring-2 ring-primary' : 'hover:border-primary/40'}
  1166→                        ${isEditing ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}
  1167→                      `}
  1168→                    >
  1169→                      <div className={`w-10 h-10 rounded-lg bg-gradient-to-br ${tool.color} flex items-center justify-center`}>
  1170→                        {isLoading ? (
  1171→                          <Loader2 className="w-5 h-5 text-primary animate-spin" />
  1172→                        ) : (
  1173→                          <Icon className="w-5 h-5 text-foreground" />
  1174→                        )}
  1175→                      </div>
  1176→                      <span className="text-xs font-medium">{tool.label}</span>
  1177→                    </button>
  1178→                  );
  1179→                })}
  1180→              </div>
  1181→            </CardContent>
  1182→          </Card>
  1183→
  1184→          {/* Custom Prompt */}
  1185→          <Card className="glass">
  1186→            <CardContent className="p-4">
  1187→              <h3 className="font-semibold mb-3 flex items-center gap-2">
  1188→                <Pencil className="w-4 h-4 text-primary" />
  1189→                تعديل مخصص
  1190→              </h3>
  1191→              <Textarea
  1192→                value={customPrompt}
  1193→                onChange={(e) => setCustomPrompt(e.target.value)}
  1194→                placeholder="صِف التعديل الذي تريده... مثال: غيّر الخلفية إلى شاطئ عند الغروب"
  1195→                className="min-h-[100px] resize-none mb-3"
  1196→                disabled={isEditing}
  1197→              />
  1198→              <Button
  1199→                onClick={handleCustomEdit}
  1200→                disabled={isEditing || !customPrompt.trim()}
  1201→                className="w-full gap-2"
  1202→              >
  1203→                {isEditing ? (
  1204→                  <Loader2 className="w-4 h-4 animate-spin" />
  1205→                ) : (
  1206→                  <Sparkles className="w-4 h-4" />
  1207→                )}
  1208→                تطبيق التعديل
  1209→              </Button>
  1210→            </CardContent>
  1211→          </Card>
  1212→
  1213→          {/* Error display */}
  1214→          <AnimatePresence>
  1215→            {editError && (
  1216→              <motion.div
  1217→                initial={{ opacity: 0, y: 10 }}
  1218→                animate={{ opacity: 1, y: 0 }}
  1219→                exit={{ opacity: 0, y: -10 }}
  1220→              >
  1221→                <Card className="border-destructive/50 bg-destructive/10">
  1222→                  <CardContent className="p-4 flex items-start gap-3">
  1223→                    <X className="w-5 h-5 text-destructive mt-0.5 shrink-0" />
  1224→                    <div className="flex-1">
  1225→                      <p className="text-sm font-medium text-destructive">حدث خطأ</p>
  1226→                      <p className="text-xs text-muted-foreground mt-1">{editError}</p>
  1227→                    </div>
  1228→                    {lastEditArgs && (
  1229→                      <Button
  1230→                        variant="outline"
  1231→                        size="sm"
  1232→                        className="shrink-0 gap-1 text-xs h-8"
  1233→                        onClick={() => {
  1234→                          setEditError(null);
  1235→                          handleEdit(lastEditArgs.prompt, lastEditArgs.label, lastEditArgs.toolType);
  1236→                        }}
  1237→                      >
  1238→                        <RotateCcw className="w-3 h-3" />
  1239→                        إعادة المحاولة
  1240→                      </Button>
  1241→                    )}
  1242→                  </CardContent>
  1243→                </Card>
  1244→              </motion.div>
  1245→            )}
  1246→          </AnimatePresence>
  1247→        </div>
  1248→      </div>
  1249→    </main>
  1250→  );
  1251→}
  1252→
  1253→/* ─── Gallery View ─── */
  1254→function GalleryView() {
  1255→  const { projects, setProjects, setView, setOriginalImage, setOriginalFileName, setEditedImage, setAnalysis } = useAppStore();
  1256→  const [isLoading, setIsLoading] = useState(true);
  1257→
  1258→  useEffect(() => {
  1259→    const loadProjects = async () => {
  1260→      try {
  1261→        const res = await fetch('/api/projects');
  1262→        if (res.ok) {
  1263→          const data = await res.json();
  1264→          setProjects(data);
  1265→        }
  1266→      } catch {}
  1267→      setIsLoading(false);
  1268→    };
  1269→    loadProjects();
  1270→  }, [setProjects]);
  1271→
  1272→  const handleDelete = useCallback(async (id: string) => {
  1273→    try {
  1274→      const res = await fetch(`/api/projects/${id}`, { method: 'DELETE' });
  1275→      if (res.ok) {
  1276→        setProjects(projects.filter((p) => p.id !== id));
  1277→      }
  1278→    } catch {}
  1279→  }, [projects, setProjects]);
  1280→
  1281→  const handleOpen = useCallback((project: PhotoProject) => {
  1282→    const lastEdit = project.edits?.[project.edits.length - 1];
  1283→    if (lastEdit?.editedPath) {
  1284→      setOriginalImage(lastEdit.originalPath);
  1285→      setEditedImage(lastEdit.editedPath);
  1286→      setOriginalFileName(project.title);
  1287→      setAnalysis(null);
  1288→      setView('editor');
  1289→    } else if (lastEdit) {
  1290→      setOriginalImage(lastEdit.originalPath);
  1291→      setEditedImage(null);
  1292→      setOriginalFileName(project.title);
  1293→      setAnalysis(null);
  1294→      setView('editor');
  1295→    }
  1296→  }, [setOriginalImage, setEditedImage, setOriginalFileName, setAnalysis, setView]);
  1297→
  1298→  if (isLoading) {
  1299→    return (
  1300→      <main className="flex-1 flex items-center justify-center">
  1301→        <Loader2 className="w-8 h-8 text-primary animate-spin" />
  1302→      </main>
  1303→    );
  1304→  }
  1305→
  1306→  return (
  1307→    <main className="flex-1 px-4 py-8 max-w-6xl mx-auto w-full">
  1308→      <motion.div
  1309→        initial={{ opacity: 0, y: -10 }}
  1310→        animate={{ opacity: 1, y: 0 }}
  1311→        className="text-center mb-8"
  1312→      >
  1313→        <h2 className="text-3xl font-bold mb-2">
  1314→          <span className="gradient-text">المعرض</span>
  1315→        </h2>
  1316→        <p className="text-muted-foreground">جميع مشاريع تعديل الصور السابقة</p>
  1317→      </motion.div>
  1318→
  1319→      {projects.length === 0 ? (
  1320→        <motion.div
  1321→          initial={{ opacity: 0 }}
  1322→          animate={{ opacity: 1 }}
  1323→          className="text-center py-20"
  1324→        >
  1325→          <div className="w-20 h-20 rounded-full bg-muted/30 flex items-center justify-center mx-auto mb-4">
  1326→            <ImageIcon className="w-10 h-10 text-muted-foreground" />
  1327→          </div>
  1328→          <p className="text-lg text-muted-foreground mb-4">لا توجد مشاريع بعد</p>
  1329→          <Button onClick={() => setView('home')} className="gap-2">
  1330→            <Upload className="w-4 h-4" />
  1331→            ابدأ بتعديل صورة
  1332→          </Button>
  1333→        </motion.div>
  1334→      ) : (
  1335→        <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
  1336→          {projects.map((project, i) => {
  1337→            const lastEdit = project.edits?.[project.edits.length - 1];
  1338→            const thumbnail = lastEdit?.editedPath || lastEdit?.originalPath || '';
  1339→            return (
  1340→              <motion.div
  1341→                key={project.id}
  1342→                initial={{ opacity: 0, y: 20 }}
  1343→                animate={{ opacity: 1, y: 0 }}
  1344→                transition={{ delay: i * 0.05 }}
  1345→              >
  1346→                <Card className="glass overflow-hidden group cursor-pointer hover:border-primary/40 transition-all" onClick={() => handleOpen(project)}>
  1347→                  <div className="aspect-video bg-black/30 relative overflow-hidden">
  1348→                    {thumbnail ? (
  1349→                      <img src={thumbnail} alt={project.title} className="w-full h-full object-cover" />
  1350→                    ) : (
  1351→                      <div className="w-full h-full flex items-center justify-center">
  1352→                        <ImageIcon className="w-8 h-8 text-muted-foreground" />
  1353→                      </div>
  1354→                    )}
  1355→                    <div className="absolute inset-0 bg-black/0 group-hover:bg-black/30 transition-colors flex items-center justify-center">
  1356→                      <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">
  1357→                        فتح المشروع
  1358→                      </span>
  1359→                    </div>
  1360→                  </div>
  1361→                  <CardContent className="p-3 flex items-center justify-between">
  1362→                    <div>
  1363→                      <p className="font-medium text-sm truncate">{project.title}</p>
  1364→                      <p className="text-xs text-muted-foreground">
  1365→                        {new Date(project.createdAt).toLocaleDateString('ar-EG')}
  1366→                        {project.edits?.length ? ` — ${project.edits.length} تعديل` : ''}
  1367→                      </p>
  1368→                    </div>
  1369→                    <Button
  1370→                      variant="ghost"
  1371→                      size="icon"
  1372→                      className="h-8 w-8 text-muted-foreground hover:text-destructive shrink-0"
  1373→                      onClick={(e) => {
  1374→                        e.stopPropagation();
  1375→                        handleDelete(project.id);
  1376→                      }}
  1377→                    >
  1378→                      <Trash2 className="w-4 h-4" />
  1379→                    </Button>
  1380→                  </CardContent>
  1381→                </Card>
  1382→              </motion.div>
  1383→            );
  1384→          })}
  1385→        </div>
  1386→      )}
  1387→    </main>
  1388→  );
  1389→}
  1390→
  1391→/* ─── Generate View ─── */
  1392→const SIZE_OPTIONS = [
  1393→  { id: 'square', label: 'مربع', icon: Square, desc: '1024×1024', color: 'from-primary/20 to-primary/5' },
  1394→  { id: 'portrait', label: 'عمودي', icon: RectangleVertical, desc: '864×1152', color: 'from-amber-500/20 to-amber-600/5' },
  1395→  { id: 'landscape', label: 'أفقي', icon: Monitor, desc: '1344×768', color: 'from-emerald-500/20 to-emerald-600/5' },
  1396→  { id: 'wide', label: 'عريض', icon: Monitor, desc: '1440×720', color: 'from-violet-500/20 to-violet-600/5' },
  1397→];
  1398→
  1399→function GenerateView() {
  1400→  const { setOriginalImage, setOriginalFileName, setView, setEditedImage, setAnalysis } = useAppStore();
  1401→  const [prompt, setPrompt] = useState('');
  1402→  const [selectedSize, setSelectedSize] = useState('square');
  1403→  const [isGenerating, setIsGenerating] = useState(false);
  1404→  const [generatedImage, setGeneratedImage] = useState<string | null>(null);
  1405→  const [error, setError] = useState<string | null>(null);
  1406→  const [progress, setProgress] = useState(0);
  1407→  const [progressMsg, setProgressMsg] = useState('');
  1408→
  1409→  const pollIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
  1410→
  1411→  const handleGenerate = useCallback(async () => {
  1412→    if (!prompt.trim() || isGenerating) return;
  1413→    setIsGenerating(true);
  1414→    setError(null);
  1415→    setGeneratedImage(null);
  1416→    setProgress(0);
  1417→    setProgressMsg('جارٍ البدء...');
  1418→
  1419→    try {
  1420→      // Step 1: Start the job (returns immediately)
  1421→      const startRes = await fetch('/api/generate', {
  1422→        method: 'POST',
  1423→        headers: { 'Content-Type': 'application/json' },
  1424→        body: JSON.stringify({ prompt: prompt.trim(), sizeId: selectedSize }),
  1425→      });
  1426→
  1427→      const startData = await startRes.json();
  1428→
  1429→      if (!startRes.ok || startData.error) {
  1430→        throw new Error(startData.error || 'حدث خطأ غير متوقع');
  1431→      }
  1432→
  1433→      const { jobId } = startData;
  1434→      if (!jobId) {
  1435→        throw new Error('لم يتم إنشاء العملية');
  1436→      }
  1437→
  1438→      // Step 2: Poll every 3 seconds until done or error
  1439→      const result = await new Promise<{ imageUrl: string }>((resolve, reject) => {
  1440→        let attempts = 0;
  1441→        const maxAttempts = 120; // 6 minutes max
  1442→
  1443→        pollIntervalRef.current = setInterval(async () => {
  1444→          attempts++;
  1445→
  1446→          if (attempts > maxAttempts) {
  1447→            if (pollIntervalRef.current) clearInterval(pollIntervalRef.current);
  1448→            pollIntervalRef.current = null;
  1449→            reject(new Error('انتهت المهلة. حاول مرة أخرى.'));
  1450→            return;
  1451→          }
  1452→
  1453→          try {
  1454→            const pollRes = await fetch(`/api/generate?jobId=${jobId}`);
  1455→            const pollData = await pollRes.json();
  1456→
  1457→            if (pollData.error && !pollData.status) {
  1458→              if (pollIntervalRef.current) clearInterval(pollIntervalRef.current);
  1459→              pollIntervalRef.current = null;
  1460→              reject(new Error(pollData.error));
  1461→              return;
  1462→            }
  1463→
  1464→            // Update progress
  1465→            if (pollData.progress !== undefined) {
  1466→              setProgress((prev) => Math.max(prev, pollData.progress));
  1467→            }
  1468→            if (pollData.message) {
  1469→              setProgressMsg(pollData.message);
  1470→            }
  1471→
  1472→            // Check terminal states
  1473→            if (pollData.status === 'done' && pollData.imageUrl) {
  1474→              if (pollIntervalRef.current) clearInterval(pollIntervalRef.current);
  1475→              pollIntervalRef.current = null;
  1476→              resolve({ imageUrl: pollData.imageUrl });
  1477→            } else if (pollData.status === 'error') {
  1478→              if (pollIntervalRef.current) clearInterval(pollIntervalRef.current);
  1479→              pollIntervalRef.current = null;
  1480→              reject(new Error(pollData.error || 'فشل توليد الصورة'));
  1481→            }
  1482→          } catch (pollErr: unknown) {
  1483→            // Network error on a single poll — don't abort, just retry
  1484→            console.error('[GEN] Poll error, retrying...', pollErr);
  1485→          }
  1486→        }, 3000);
  1487→      });
  1488→
  1489→      setGeneratedImage(result.imageUrl);
  1490→    } catch (err: unknown) {
  1491→      setError(err instanceof Error ? err.message : 'حدث خطأ');
  1492→    } finally {
  1493→      if (pollIntervalRef.current) {
  1494→        clearInterval(pollIntervalRef.current);
  1495→        pollIntervalRef.current = null;
  1496→      }
  1497→      setIsGenerating(false);
  1498→    }
  1499→  }, [prompt, selectedSize, isGenerating]);
  1500→
  1501→  // Cleanup polling on unmount
  1502→  useEffect(() => {
  1503→    return () => {
  1504→      if (pollIntervalRef.current) {
  1505→        clearInterval(pollIntervalRef.current);
  1506→        pollIntervalRef.current = null;
  1507→      }
  1508→    };
  1509→  }, []);
  1510→
  1511→  const handleSendToEditor = useCallback(() => {
  1512→    if (!generatedImage) return;
  1513→    setOriginalImage(generatedImage);
  1514→    setOriginalFileName('Fouad-AI-generated.png');
  1515→    setEditedImage(null);
  1516→    setAnalysis(null);
  1517→    setView('editor');
  1518→  }, [generatedImage, setOriginalImage, setOriginalFileName, setEditedImage, setAnalysis, setView]);
  1519→
  1520→  const handleDownload = useCallback(() => {
  1521→    if (!generatedImage) return;
  1522→    const a = document.createElement('a');
  1523→    a.href = generatedImage;
  1524→    a.download = 'Fouad-AI-generated.png';
  1525→    a.click();
  1526→  }, [generatedImage]);
  1527→
  1528→  return (
  1529→    <main className="flex-1 px-4 py-6 max-w-5xl mx-auto w-full">
  1530→      <motion.div
  1531→        initial={{ opacity: 0, y: -10 }}
  1532→        animate={{ opacity: 1, y: 0 }}
  1533→        className="text-center mb-8"
  1534→      >
  1535→        <h2 className="text-3xl font-bold mb-2">
  1536→          <span className="gradient-text">رسم الصور بالذكاء</span>
  1537→        </h2>
  1538→        <p className="text-muted-foreground">صِف الصورة التي تريدها وسنرسمها لك</p>
  1539→      </motion.div>
  1540→
  1541→      <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
  1542→        {/* Left: Input */}
  1543→        <div className="space-y-4">
  1544→          {/* Prompt */}
  1545→          <Card className="glass">
  1546→            <CardContent className="p-4">
  1547→              <h3 className="font-semibold mb-3 flex items-center gap-2">
  1548→                <Pencil className="w-4 h-4 text-primary" />
  1549→                وصف الصورة
  1550→              </h3>
  1551→              <Textarea
  1552→                value={prompt}
  1553→                onChange={(e) => setPrompt(e.target.value)}
  1554→                placeholder="مثال: قطة جميلة تجلس في حديقة مليئة بالزهور عند الغروب..."
  1555→                className="min-h-[120px] resize-none mb-3"
  1556→                disabled={isGenerating}
  1557→              />
  1558→              <p className="text-xs text-muted-foreground mb-3">
  1559→                يمكنك الكتابة بالعربية أو الإنجليزية
  1560→              </p>
  1561→
  1562→              {/* Size selector */}
  1563→              <h4 className="text-sm font-medium mb-2">حجم الصورة</h4>
  1564→              <div className="grid grid-cols-4 gap-2">
  1565→                {SIZE_OPTIONS.map((s) => {
  1566→                  const Icon = s.icon;
  1567→                  return (
  1568→                    <button
  1569→                      key={s.id}
  1570→                      onClick={() => setSelectedSize(s.id)}
  1571→                      disabled={isGenerating}
  1572→                      className={`
  1573→                        flex flex-col items-center gap-1.5 p-2.5 rounded-xl border text-center transition-all
  1574→                        ${selectedSize === s.id
  1575→                          ? 'border-primary bg-primary/10 ring-1 ring-primary/30'
  1576→                          : 'border-border/50 hover:border-primary/30'}
  1577→                        ${isGenerating ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}
  1578→                      `}
  1579→                    >
  1580→                      <Icon className="w-4 h-4 text-foreground" />
  1581→                      <span className="text-xs font-medium">{s.label}</span>
  1582→                      <span className="text-[10px] text-muted-foreground">{s.desc}</span>
  1583→                    </button>
  1584→                  );
  1585→                })}
  1586→              </div>
  1587→
  1588→              {/* Generate button */}
  1589→              <Button
  1590→                onClick={handleGenerate}
  1591→                disabled={isGenerating || !prompt.trim()}
  1592→                className="w-full gap-2 mt-4"
  1593→                size="lg"
  1594→              >
  1595→                {isGenerating ? (
  1596→                  <Loader2 className="w-5 h-5 animate-spin" />
  1597→                ) : (
  1598→                  <WandSparkles className="w-5 h-5" />
  1599→                )}
  1600→                {isGenerating ? 'جارٍ الرسم...' : 'ارسم الصورة'}
  1601→              </Button>
  1602→            </CardContent>
  1603→          </Card>
  1604→
  1605→          {/* Error */}
  1606→          <AnimatePresence>
  1607→            {error && (
  1608→              <motion.div initial={{ opacity: 0, y: 10 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: -10 }}>
  1609→                <Card className="border-destructive/50 bg-destructive/10">
  1610→                  <CardContent className="p-4 flex items-start gap-3">
  1611→                    <X className="w-5 h-5 text-destructive mt-0.5 shrink-0" />
  1612→                    <div className="flex-1">
  1613→                      <p className="text-sm font-medium text-destructive">خطأ</p>
  1614→                      <p className="text-xs text-muted-foreground mt-1">{error}</p>
  1615→                    </div>
  1616→                    <Button
  1617→                      variant="outline"
  1618→                      size="sm"
  1619→                      className="shrink-0 gap-1 text-xs"
  1620→                      onClick={() => handleGenerate()}
  1621→                    >
  1622→                      <RotateCcw className="w-3 h-3" />
  1623→                      إعادة المحاولة
  1624→                    </Button>
  1625→                  </CardContent>
  1626→                </Card>
  1627→              </motion.div>
  1628→            )}
  1629→          </AnimatePresence>
  1630→        </div>
  1631→
  1632→        {/* Right: Result */}
  1633→        <div>
  1634→          <Card className="glass overflow-hidden">
  1635→            <CardContent className="p-0">
  1636→              <div className="relative min-h-[400px] flex items-center justify-center bg-black/30">
  1637→                {isGenerating && (
  1638→                  <div className="absolute inset-0 z-10 flex flex-col items-center justify-center bg-black/50 backdrop-blur-sm gap-4 px-8">
  1639→                    <Loader2 className="w-16 h-16 text-primary animate-spin" />
  1640→                    <p className="text-sm font-medium animate-pulse">{progressMsg || 'جارٍ رسم الصورة بالذكاء الاصطناعي...'}</p>
  1641→                    <Progress value={progress} className="w-64 h-2" />
  1642→                    <p className="text-xs text-muted-foreground">{progress}%</p>
  1643→                  </div>
  1644→                )}
  1645→
  1646→                {generatedImage ? (
  1647→                  <img
  1648→                    src={generatedImage}
  1649→                    alt="Generated"
  1650→                    className="w-full h-auto block"
  1651→                  />
  1652→                ) : !isGenerating ? (
  1653→                  <div className="flex flex-col items-center gap-4 py-16">
  1654→                    <div className="w-20 h-20 rounded-full bg-muted/20 flex items-center justify-center">
  1655→                      <WandSparkles className="w-10 h-10 text-muted-foreground/50" />
  1656→                    </div>
  1657→                    <p className="text-muted-foreground text-center px-4">
  1658→                      الصورة المرسومة ستظهر هنا
  1659→                    </p>
  1660→                  </div>
  1661→                ) : null}
  1662→              </div>
  1663→
  1664→              {/* Action buttons */}
  1665→              {generatedImage && (
  1666→                <div className="p-3 border-t border-border/50 flex items-center gap-2">
  1667→                  <Button onClick={handleSendToEditor} className="flex-1 gap-2" size="sm">
  1668→                    <ArrowRight className="w-4 h-4" />
  1669→                    تعديل الصورة
  1670→                  </Button>
  1671→                  <Button onClick={handleDownload} variant="outline" className="gap-2" size="sm">
  1672→                    <Download className="w-4 h-4" />
  1673→                    تحميل
  1674→                  </Button>
  1675→                </div>
  1676→              )}
  1677→            </CardContent>
  1678→          </Card>
  1679→
  1680→          {/* Example prompts */}
  1681→          {!generatedImage && !isGenerating && (
  1682→            <Card className="glass mt-4">
  1683→              <CardContent className="p-4">
  1684→                <h4 className="text-sm font-medium mb-3 flex items-center gap-2">
  1685→                  <Sparkles className="w-4 h-4 text-primary" />
  1686→                  أفكار للتجربة
  1687→                </h4>
  1688→                <div className="flex flex-wrap gap-2">
  1689→                  {[
  1690→                    'غروب على شاطئ بصخور ملساء',
  1691→                    'مدينة مستقبلية بالليل',
  1692→                    'طائر فيلمنق زاهي الألوان',
  1693→                    'قرية جبلية وسط الضباب',
  1694→                  ].map((example) => (
  1695→                    <button
  1696→                      key={example}
  1697→                      onClick={() => setPrompt(example)}
  1698→                      className="text-xs px-3 py-1.5 rounded-full border border-border/50 hover:border-primary/40 hover:bg-primary/5 transition-all cursor-pointer"
  1699→                    >
  1700→                      {example}
  1701→                    </button>
  1702→                  ))}
  1703→                </div>
  1704→              </CardContent>
  1705→            </Card>
  1706→          )}
  1707→        </div>
  1708→      </div>
  1709→    </main>
  1710→  );
  1711→}
  1712→
  1713→/* ─── Main Client Component ─── */
  1714→export default function HomeClient() {
  1715→  const { currentView, editError, setEditError } = useAppStore();
  1716→  const [bannerAdminOpen, setBannerAdminOpen] = useState(false);
  1717→  const [loginOpen, setLoginOpen] = useState(false);
  1718→  const { isAdmin, isLoading, refresh: refreshSession } = useAdminSession();
  1719→
  1720→  const handleLoginSuccess = useCallback(() => {
  1721→    refreshSession().then(() => {
  1722→      setBannerAdminOpen(true);
  1723→    });
  1724→  }, [refreshSession]);
  1725→
  1726→  const handleLogout = useCallback(async () => {
  1727→    await signOut({ redirect: false });
  1728→    refreshSession();
  1729→  }, [refreshSession]);
  1730→
  1731→  const handleSettingsClick = useCallback(() => {
  1732→    if (isAdmin) {
  1733→      setBannerAdminOpen(true);
  1734→    } else {
  1735→      setLoginOpen(true);
  1736→    }
  1737→  }, [isAdmin]);
  1738→
  1739→  // Dismiss errors on click outside
  1740→  useEffect(() => {
  1741→    if (editError) {
  1742→      const timer = setTimeout(() => setEditError(null), 8000);
  1743→      return () => clearTimeout(timer);
  1744→    }
  1745→  }, [editError, setEditError]);
  1746→
  1747→  return (
  1748→    <div className="min-h-screen flex flex-col">
  1749→      <Header
  1750→        isAdmin={isAdmin}
  1751→        isLoading={isLoading}
  1752→        onOpenBannerAdmin={handleSettingsClick}
  1753→        onOpenLogin={() => setLoginOpen(true)}
  1754→        onLogout={handleLogout}
  1755→      />
  1756→      <div className="w-full">
  1757→        <BannerDisplay position="top" />
  1758→      </div>
  1759→      <LoginDialog open={loginOpen} onOpenChange={setLoginOpen} onLoginSuccess={handleLoginSuccess} />
  1760→      <BannerAdmin open={bannerAdminOpen} onOpenChange={setBannerAdminOpen} />
  1761→      <AnimatePresence mode="wait">
  1762→        {currentView === 'home' && (
  1763→          <motion.div key="home" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} className="flex-1">
  1764→            <HomeView />
  1765→          </motion.div>
  1766→        )}
  1767→        {currentView === 'editor' && (
  1768→          <motion.div key="editor" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} className="flex-1 flex flex-col">
  1769→            <EditorView />
  1770→          </motion.div>
  1771→        )}
  1772→        {currentView === 'gallery' && (
  1773→          <motion.div key="gallery" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} className="flex-1">
  1774→            <GalleryView />
  1775→          </motion.div>
  1776→        )}
  1777→        {currentView === 'generate' && (
  1778→          <motion.div key="generate" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} className="flex-1 flex flex-col">
  1779→            <GenerateView />
  1780→          </motion.div>
  1781→        )}
  1782→      </AnimatePresence>
  1783→      <Footer />
  1784→    </div>
  1785→  );
  1786→}