import React, { useState, useRef, useEffect, Suspense, useMemo, useCallback } from 'react';
import { X, Upload, Trash2, RotateCw, Eye, EyeOff } from 'lucide-react';
import { Canvas } from '@react-three/fiber';
import { OrbitControls, Environment } from '@react-three/drei';
import * as THREE from 'three';
import { ModelViewer } from './ModelViewer';

interface Layer {
  id: string;
  url: string;
  img?: HTMLImageElement;
  x: number; y: number;
  scaleX: number; scaleY: number;
  rotation: number;
  cropL: number; cropT: number; cropR: number; cropB: number;
  visible: boolean;
}

type Handle = 'move' | 'rotate' | 'scaleNW' | 'scaleNE' | 'scaleSW' | 'scaleSE' | 'scaleN' | 'scaleS' | 'scaleE' | 'scaleW';

interface UVEditorProps {
  onClose: () => void;
  onSave: (dataUrl: string, mappingType: string, layers: any[], bgColor: string, bgTransparent: boolean) => void;
  targetObject?: any;
  loadedModel?: THREE.Group | null;
  sceneObjects?: any[];
}

function deg2rad(d: number) { return d * Math.PI / 180; }

export function UVEditor({ onClose, onSave, targetObject, loadedModel, sceneObjects }: UVEditorProps) {
  const initBg = targetObject?.materialProps?.uvBackground ?? '#1a1a2e';
  const initTrans = targetObject?.materialProps?.uvTransparent ?? false;

  const [layers, setLayers] = useState<Layer[]>([]);
  const [selectedId, setSelectedId] = useState<string | null>(null);
  const [previewUrl, setPreviewUrl] = useState<string | null>(null);
  const [mappingType, setMappingType] = useState<string>(targetObject?.materialProps?.mappingType || 'uv');
  const [bgColor, setBgColor] = useState(initBg);
  const [bgTransparent, setBgTransparent] = useState(initTrans);
  const [canvasW, setCanvasW] = useState(1024);
  const [canvasH, setCanvasH] = useState(1024);

  const containerRef = useRef<HTMLDivElement>(null);
  const fileInputRef = useRef<HTMLInputElement>(null);
  const dragRef = useRef<{ handle: Handle; startX: number; startY: number; layer: Layer } | null>(null);

  useEffect(() => {
    const saved = targetObject?.materialProps?.uvLayers;
    if (saved?.length) {
      setCanvasW(1024);
      setCanvasH(1024);
      let n = 0;
      const init: Layer[] = saved.map((l: any) => ({ ...l }));
      init.forEach(layer => {
        const img = new Image();
        img.crossOrigin = "anonymous";
        img.onload = () => { layer.img = img; n++; if (n === init.length) setLayers([...init]); };
        img.src = layer.url;
      });
    } else if (targetObject?.materialProps?.map) {
      // If no saved layers but there's a base map texture, load it as the initial layer
      const url = targetObject.materialProps.map;
      const img = new Image();
      img.crossOrigin = "anonymous";
      img.onload = () => {
        // Reduced MAX size from 2048 to 1024 to prevent huge base64 strings
        // that trigger the 1MB Nginx reverse proxy 413 Payload Too Large limit.
        const MAX = 1024;
        let scale = 1;
        if (img.width > MAX || img.height > MAX) {
          scale = MAX / Math.max(img.width, img.height);
        }
        const cw = Math.round(img.width * scale);
        const ch = Math.round(img.height * scale);
        setCanvasW(cw);
        setCanvasH(ch);
        
        const scaleX = cw / img.width;
        const scaleY = ch / img.height;

        const layer: Layer = {
          id: `l-base`,
          url,
          img,
          x: cw / 2,
          y: ch / 2,
          scaleX,
          scaleY,
          rotation: 0,
          cropL: 0,
          cropT: 0,
          cropR: 0,
          cropB: 0,
          visible: true
        };
        setLayers([layer]);
        setSelectedId(layer.id);
      };
      img.src = url;
    }
  }, [targetObject]);

  const renderCanvas = useCallback((lrs: Layer[], transparent: boolean, bg: string): string => {
    const c = document.createElement('canvas');
    c.width = canvasW; c.height = canvasH;
    const ctx = c.getContext('2d')!;
    if (!transparent) { ctx.fillStyle = bg; ctx.fillRect(0, 0, canvasW, canvasH); }
    lrs.forEach(layer => {
      if (!layer.img || layer.visible === false) return;
      const iw = layer.img.width, ih = layer.img.height;
      const sx = layer.cropL * iw, sy = layer.cropT * ih;
      const sw = (1 - layer.cropL - layer.cropR) * iw;
      const sh = (1 - layer.cropT - layer.cropB) * ih;
      ctx.save();
      ctx.translate(layer.x, layer.y);
      ctx.rotate(deg2rad(layer.rotation));
      ctx.scale(layer.scaleX, layer.scaleY);
      ctx.drawImage(layer.img, sx, sy, sw, sh, -sw / 2, -sh / 2, sw, sh);
      ctx.restore();
    });
    try {
      // Use JPEG with 0.75 quality to heavily compress the image size
      // to avoid hitting the 1MB Nginx reverse proxy limit.
      return c.toDataURL(transparent ? 'image/png' : 'image/jpeg', 0.75);
    } catch (e) {
      console.error("Canvas render error (likely CORS taint):", e);
      return "";
    }
  }, [canvasW, canvasH]);

  useEffect(() => {
    setPreviewUrl(renderCanvas(layers, bgTransparent, bgColor));
  }, [layers, bgTransparent, bgColor]);

  const handleFileUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0]; if (!file) return;
    const reader = new FileReader();
    reader.onload = ev => {
      const url = ev.target?.result as string;
      const img = new Image();
      img.onload = () => {
        const nl: Layer = { id: `l-${Date.now()}`, url, img, x: canvasW / 2, y: canvasH / 2, scaleX: 1, scaleY: 1, rotation: 0, cropL: 0, cropT: 0, cropR: 0, cropB: 0, visible: true };
        setLayers(p => [...p, nl]);
        setSelectedId(nl.id);
      };
      img.src = url;
    };
    reader.readAsDataURL(file);
    e.target.value = '';
  };

  const updateLayer = (id: string, u: Partial<Layer>) => setLayers(p => p.map(l => l.id === id ? { ...l, ...u } : l));
  const selectedLayer = layers.find(l => l.id === selectedId) ?? null;

  const getSF = () => {
    const r = containerRef.current?.getBoundingClientRect();
    return r ? canvasW / r.width : 1;
  };

  const onHandleDown = (e: React.MouseEvent, handle: Handle, layer: Layer) => {
    e.stopPropagation();
    setSelectedId(layer.id);
    dragRef.current = { handle, startX: e.clientX, startY: e.clientY, layer: { ...layer } };
    e.preventDefault();
  };

  // Snap helper: snap value to nearest multiple of snapSize
  const snap = (v: number, snapSize: number) => Math.round(v / snapSize) * snapSize;

  const onMouseMove = (e: React.MouseEvent) => {
    const d = dragRef.current;
    if (!d) return;
    const sf = getSF();
    const dx = (e.clientX - d.startX) * sf;
    const dy = (e.clientY - d.startY) * sf;
    const isShift = e.shiftKey;
    const SNAP_PX = 16; // grid snap in canvas units

    if (d.handle === 'move') {
      let nx = d.layer.x + dx;
      let ny = d.layer.y + dy;
      // Clamp to canvas bounds with soft margin
      nx = Math.max(0, Math.min(canvasW, nx));
      ny = Math.max(0, Math.min(canvasH, ny));
      // Hold Shift to snap to grid
      if (isShift) { nx = snap(nx, SNAP_PX); ny = snap(ny, SNAP_PX); }
      // Center snapping: snap near canvas center
      if (Math.abs(nx - canvasW / 2) < SNAP_PX) nx = canvasW / 2;
      if (Math.abs(ny - canvasH / 2) < SNAP_PX) ny = canvasH / 2;
      updateLayer(d.layer.id, { x: nx, y: ny });
    } else if (d.handle === 'rotate') {
      let rot = d.layer.rotation + dx / 2;
      // Snap rotation to 15° increments when Shift held
      if (isShift) rot = snap(rot, 15);
      updateLayer(d.layer.id, { rotation: rot });
    } else if (d.handle.startsWith('scale')) {
      if (isShift) {
        // Shift held: stretch X and Y independently
        const sx = Math.max(0.05, d.layer.scaleX + dx / 200);
        const sy = Math.max(0.05, d.layer.scaleY + dy / 200);
        updateLayer(d.layer.id, { scaleX: sx, scaleY: sy });
      } else {
        // No shift: uniform scale driven by the larger axis
        const delta = (Math.abs(dx) > Math.abs(dy) ? dx : dy) / 200;
        const sx = Math.max(0.05, d.layer.scaleX + delta);
        const sy = Math.max(0.05, d.layer.scaleY + delta);
        updateLayer(d.layer.id, { scaleX: sx, scaleY: sy });
      }
    }
  };

  const onMouseUp = () => { dragRef.current = null; };

  const handleSave = () => {
    if (previewUrl) {
      const serialized = layers.map(({ img, ...rest }) => rest);
      onSave(previewUrl, mappingType, serialized, bgColor, bgTransparent);
    }
    onClose();
  };

  const PreviewModel = () => {
    const mockObjs = useMemo(() => {
      if (!sceneObjects) return [];
      return sceneObjects.map(obj => obj.id === targetObject?.id
        ? { ...obj, materialProps: { ...obj.materialProps, map: previewUrl, mappingType } }
        : obj
      );
    }, [sceneObjects, previewUrl, mappingType]);
    const cloned = useMemo(() => loadedModel?.clone() ?? null, [loadedModel]);
    if (!targetObject) return <mesh><boxGeometry /><meshStandardMaterial /></mesh>;
    if (targetObject.type === 'cube') {
      const tex = previewUrl ? (() => { const t = new THREE.TextureLoader().load(previewUrl); t.colorSpace = THREE.SRGBColorSpace; t.flipY = false; return t; })() : null;
      return <mesh><boxGeometry args={[1, 1, 1]} /><meshStandardMaterial map={tex ?? undefined} /></mesh>;
    }
    return <ModelViewer object={cloned} sceneObjects={mockObjs} />;
  };

  // Bounding box overlay rendered on canvas div
  const BoundingBox = ({ layer }: { layer: Layer }) => {
    const iw = (layer.img?.width ?? 200) * (1 - layer.cropL - layer.cropR);
    const ih = (layer.img?.height ?? 200) * (1 - layer.cropT - layer.cropB);
    const rect = containerRef.current?.getBoundingClientRect();
    if (!rect) return null;
    
    const w = (iw * layer.scaleX / canvasW) * 100;
    const h = (ih * layer.scaleY / canvasH) * 100;
    const lx = (layer.x / canvasW) * 100;
    const ly = (layer.y / canvasH) * 100;

    const cornerStyle = (cx: string, cy: string, cursor: string): React.CSSProperties => ({
      position: 'absolute', left: cx, top: cy, width: 10, height: 10,
      background: '#ffffff', border: '2px solid #3b82f6', borderRadius: 2,
      transform: 'translate(-50%,-50%)', cursor, zIndex: 10, touchAction: 'none'
    });
    const edgeStyle = (cx: string, cy: string, cursor: string): React.CSSProperties => ({
      position: 'absolute', left: cx, top: cy, width: 8, height: 8,
      background: '#3b82f6', borderRadius: '50%',
      transform: 'translate(-50%,-50%)', cursor, zIndex: 10
    });

    return (
      <div style={{
        position: 'absolute',
        left: `${lx}%`, top: `${ly}%`,
        width: `${w}%`, height: `${h}%`,
        transform: `translate(-50%,-50%) rotate(${layer.rotation}deg)`,
        border: '1.5px solid #3b82f6',
        pointerEvents: 'none',
        zIndex: 5,
      }}>
        {/* Corners - scale */}
        {(['NW','NE','SW','SE'] as const).map(c => (
          <div key={c}
            style={{
              ...cornerStyle(
                c.includes('W') ? '0%' : '100%',
                c.includes('N') ? '0%' : '100%',
                c === 'NW' || c === 'SE' ? 'nwse-resize' : 'nesw-resize'
              ), pointerEvents: 'all'
            }}
            onMouseDown={e => onHandleDown(e, `scale${c}` as Handle, layer)}
          />
        ))}
        {/* Edge midpoints - scale */}
        {[
          { id: 'N', cx: '50%', cy: '0%', cur: 'ns-resize' },
          { id: 'S', cx: '50%', cy: '100%', cur: 'ns-resize' },
          { id: 'E', cx: '100%', cy: '50%', cur: 'ew-resize' },
          { id: 'W', cx: '0%', cy: '50%', cur: 'ew-resize' },
        ].map(({ id, cx, cy, cur }) => (
          <div key={id} style={{ ...edgeStyle(cx, cy, cur), pointerEvents: 'all' }}
            onMouseDown={e => onHandleDown(e, `scale${id}` as Handle, layer)} />
        ))}
        {/* Rotate handle - top center above box */}
        <div style={{
          position: 'absolute', left: '50%', top: -28,
          transform: 'translateX(-50%)',
          width: 14, height: 14,
          background: '#f59e0b', border: '2px solid #fff', borderRadius: '50%',
          cursor: 'grab', zIndex: 10, pointerEvents: 'all',
        }} onMouseDown={e => onHandleDown(e, 'rotate', layer)} title="Rotate" />
        {/* Line from box to rotate handle */}
        <div style={{ position: 'absolute', left: '50%', top: -20, width: 2, height: 20, background: '#3b82f6', transform: 'translateX(-50%)', pointerEvents: 'none' }} />
      </div>
    );
  };

  return (
    <div className="fixed inset-0 z-[200] flex flex-col text-zinc-100" style={{ fontFamily: 'Inter,sans-serif', background: '#0f0f13' }}>
      {/* Top Bar */}
      <div className="h-11 border-b border-zinc-800 bg-zinc-900/95 flex items-center justify-between px-4 flex-shrink-0 backdrop-blur">
        <div className="flex items-center gap-3">
          <button onClick={onClose} className="p-1.5 hover:bg-zinc-800 rounded-lg text-zinc-400 hover:text-white transition-colors">
            <X size={16} />
          </button>
          <div className="w-px h-4 bg-zinc-700" />
          <span className="text-sm font-semibold">UV Map</span>
        </div>
        <div className="flex items-center gap-3">
          <label className="flex items-center gap-1.5 text-xs text-zinc-400 cursor-pointer select-none">
            <input type="checkbox" checked={bgTransparent} onChange={e => setBgTransparent(e.target.checked)} className="accent-blue-500 w-3 h-3" />
            Transparent
          </label>
          {!bgTransparent && (
            <label className="relative flex items-center gap-1.5 cursor-pointer">
              <div className="w-5 h-5 rounded border border-zinc-600 overflow-hidden relative">
                <div className="absolute inset-0" style={{ background: bgColor }} />
                <input type="color" value={bgColor} onChange={e => setBgColor(e.target.value)} className="opacity-0 absolute inset-0 w-full h-full cursor-pointer" />
              </div>
              <span className="text-[10px] font-mono text-zinc-400">{bgColor}</span>
            </label>
          )}
          <button onClick={handleSave} className="px-4 py-1.5 bg-blue-500 hover:bg-blue-600 rounded-lg text-sm font-semibold transition-colors">
            Apply to Model
          </button>
        </div>
      </div>

      <div className="flex-1 flex overflow-hidden">
        {/* Left sidebar */}
        <div className="w-60 bg-zinc-900 border-r border-zinc-800 flex flex-col overflow-y-auto flex-shrink-0">
          <div className="p-4 flex flex-col gap-3">
            <input type="file" ref={fileInputRef} className="hidden" accept=".jpg,.jpeg,.png,.webp,.svg" onChange={handleFileUpload} />
            <button onClick={() => fileInputRef.current?.click()}
              className="w-full py-2 bg-zinc-800 hover:bg-zinc-700 rounded-lg text-sm font-semibold flex items-center justify-center gap-2 border border-zinc-700 transition-colors">
              <Upload size={14} /> Add Image
            </button>
            <div className="h-px bg-zinc-800" />
            <p className="text-[10px] font-bold text-zinc-500 uppercase tracking-widest">Layers</p>
            {layers.length === 0 && (
              <div className="p-5 text-center text-zinc-600 text-xs border-2 border-dashed border-zinc-800 rounded-xl">Upload an image to start</div>
            )}
            {[...layers].reverse().map((layer, i) => (
              <div key={layer.id} onClick={() => setSelectedId(layer.id)}
                className={`flex items-center gap-2 p-2 rounded-lg border cursor-pointer transition-all ${selectedId === layer.id ? 'border-blue-500 bg-blue-500/10' : 'border-zinc-800 hover:border-zinc-600 bg-zinc-800/20'} ${!layer.visible ? 'opacity-40' : ''}`}>
                <img src={layer.url} alt="" className="w-8 h-8 object-contain rounded bg-zinc-900 border border-zinc-700 flex-shrink-0" />
                <span className="text-xs text-zinc-300 flex-1 truncate">Layer {layers.length - i}</span>
                <button onClick={e => { e.stopPropagation(); updateLayer(layer.id, { visible: !layer.visible }); }}
                  className="p-1 text-zinc-600 hover:text-blue-400 rounded" title={layer.visible ? 'Hide layer' : 'Show layer'}>
                  {layer.visible !== false ? <Eye size={11} /> : <EyeOff size={11} />}
                </button>
                <button onClick={e => { e.stopPropagation(); setLayers(ls => ls.filter(l => l.id !== layer.id)); if (selectedId === layer.id) setSelectedId(null); }}
                  className="p-1 text-zinc-600 hover:text-red-400 rounded">
                  <Trash2 size={11} />
                </button>
              </div>
            ))}

            {/* Layer props */}
            {selectedLayer && (
              <div className="mt-1 flex flex-col gap-2 p-3 rounded-xl border border-zinc-800 bg-zinc-800/20">
                <p className="text-[10px] font-bold text-zinc-500 uppercase tracking-widest">Transform</p>
                <div className="grid grid-cols-2 gap-2">
                  {(['x', 'y'] as const).map(ax => (
                    <div key={ax}>
                      <p className="text-[9px] text-zinc-500 uppercase mb-0.5">{ax}</p>
                      <input type="number" step="1" value={Math.round(selectedLayer[ax])}
                        onChange={e => updateLayer(selectedLayer.id, { [ax]: +e.target.value })}
                        className="w-full bg-zinc-900 border border-zinc-700 rounded px-2 py-1 text-[11px] text-blue-400 font-mono outline-none focus:border-blue-500" />
                    </div>
                  ))}
                </div>
                <div className="grid grid-cols-2 gap-2">
                  {(['scaleX', 'scaleY'] as const).map(ax => (
                    <div key={ax}>
                      <p className="text-[9px] text-zinc-500 uppercase mb-0.5">{ax === 'scaleX' ? 'Scl X' : 'Scl Y'}</p>
                      <input type="number" step="0.01" min="0.01" value={selectedLayer[ax].toFixed(2)}
                        onChange={e => updateLayer(selectedLayer.id, { [ax]: Math.max(0.01, +e.target.value) })}
                        className="w-full bg-zinc-900 border border-zinc-700 rounded px-2 py-1 text-[11px] text-blue-400 font-mono outline-none focus:border-blue-500" />
                    </div>
                  ))}
                </div>
                <div>
                  <div className="flex justify-between text-[9px] text-zinc-500 uppercase mb-1">
                    <span>Rotation</span><span className="text-blue-400 font-mono">{Math.round(selectedLayer.rotation)}°</span>
                  </div>
                  <input type="range" min="-180" max="180" step="1" value={selectedLayer.rotation}
                    onChange={e => updateLayer(selectedLayer.id, { rotation: +e.target.value })}
                    className="w-full h-1 bg-zinc-700 rounded appearance-none cursor-pointer accent-blue-500" />
                </div>

                <div className="h-px bg-zinc-700 my-1" />
                <p className="text-[10px] font-bold text-zinc-500 uppercase tracking-widest">Crop</p>
                {(['cropL', 'cropT', 'cropR', 'cropB'] as const).map(s => (
                  <div key={s} className="flex items-center gap-2">
                    <span className="text-[9px] text-zinc-500 w-6 uppercase">{s.slice(4)}</span>
                    <input type="range" min="0" max="0.49" step="0.01" value={selectedLayer[s]}
                      onChange={e => updateLayer(selectedLayer.id, { [s]: +e.target.value })}
                      className="flex-1 h-1 bg-zinc-700 rounded appearance-none cursor-pointer accent-orange-500" />
                    <span className="text-[9px] font-mono text-orange-400 w-6 text-right">{Math.round(selectedLayer[s] * 100)}%</span>
                  </div>
                ))}
              </div>
            )}
          </div>
        </div>

        {/* Canvas area */}
        <div className="flex-1 flex items-center justify-center overflow-hidden relative"
          style={{ background: 'radial-gradient(ellipse at center, #1a1a2e 0%, #0f0f13 100%)' }}
          onMouseMove={onMouseMove}
          onMouseUp={onMouseUp}
          onMouseLeave={onMouseUp}
          onClick={() => setSelectedId(null)}>
          <div ref={containerRef} className="relative shadow-2xl border border-zinc-700/50"
            style={{
              width: 'min(68vh, 90%)', aspectRatio: `${canvasW}/${canvasH}`,
              background: bgTransparent
                ? 'repeating-conic-gradient(#27272a 0% 25%, #18181b 0% 50%) 0 0 / 16px 16px'
                : bgColor
            }}>

            {/* Layers */}
            {layers.map(layer => {
              if (layer.visible === false) return null;
              const iw = (layer.img?.width ?? 200) * (1 - layer.cropL - layer.cropR);
              const ih = (layer.img?.height ?? 200) * (1 - layer.cropT - layer.cropB);
              const isSelected = selectedId === layer.id;
              return (
                <div key={layer.id}
                  onMouseDown={e => { e.stopPropagation(); onHandleDown(e, 'move', layer); }}
                  className="absolute cursor-move"
                  style={{
                    left: `${(layer.x / canvasW) * 100}%`,
                    top: `${(layer.y / canvasH) * 100}%`,
                    width: `${(iw / canvasW) * 100}%`,
                    height: `${(ih / canvasH) * 100}%`,
                    transform: `translate(-50%,-50%) rotate(${layer.rotation}deg) scale(${layer.scaleX},${layer.scaleY})`,
                    zIndex: isSelected ? 4 : 2,
                    transition: 'transform 0.04s linear',
                  }}>
                  {layer.img && (
                    <div style={{ width: '100%', height: '100%', overflow: 'hidden' }}>
                      <img src={layer.url} alt=""
                        style={{ 
                          position: 'relative', 
                          left: `${-layer.cropL * 100}%`, 
                          top: `${-layer.cropT * 100}%`, 
                          width: `${(1 / (1 - layer.cropL - layer.cropR)) * 100}%`, 
                          height: `${(1 / (1 - layer.cropT - layer.cropB)) * 100}%`, 
                          display: 'block', 
                          pointerEvents: 'none', 
                          imageRendering: 'auto' 
                        }} />
                    </div>
                  )}
                </div>
              );
            })}

            {/* Bounding box overlays - only for visible selected layer */}
            {layers.map(layer => selectedId === layer.id && layer.visible !== false && <BoundingBox key={`bb-${layer.id}`} layer={layer} />)}

            <div className="absolute bottom-2 left-2 bg-black/50 text-[10px] text-zinc-400 px-2 py-0.5 rounded font-mono select-none">
              {canvasW}x{canvasH}
            </div>
          </div>
        </div>

        {/* Right panel - preview */}
        <div className="w-72 bg-zinc-900 border-l border-zinc-800 flex flex-col p-4 gap-4 flex-shrink-0 overflow-y-auto">
          <div>
            <div className="flex items-center gap-2 mb-2">
              <RotateCw size={11} className="text-zinc-500" />
              <span className="text-[10px] font-bold text-zinc-500 uppercase tracking-widest">3D Preview</span>
            </div>
            <div className="w-full aspect-square bg-zinc-950 rounded-xl overflow-hidden border border-zinc-800">
              <Canvas shadows camera={{ position: [2, 2, 2], fov: 45 }}>
                <ambientLight intensity={0.5} />
                <directionalLight position={[5, 5, 5]} intensity={1} castShadow />
                <Environment preset="studio" />
                <Suspense fallback={null}><PreviewModel /></Suspense>
                <OrbitControls autoRotate autoRotateSpeed={1.5} />
              </Canvas>
            </div>
          </div>



          <div className="p-3 bg-zinc-800/30 rounded-xl border border-zinc-800 text-zinc-500">
            <p className="text-[10px] font-bold uppercase tracking-widest mb-2">Legend</p>
            <div className="flex flex-col gap-1.5 text-[10px]">
              <div className="flex items-center gap-2"><div className="w-3 h-3 rounded-sm bg-white border-2 border-blue-500" /><span>Drag corner/edge — uniform scale</span></div>
              <div className="flex items-center gap-2"><div className="w-3 h-3 rounded-sm bg-blue-400 border-2 border-blue-500 flex items-center justify-center text-[7px] font-bold text-white">⇧</div><span>Shift + drag — free X/Y stretch</span></div>
              <div className="flex items-center gap-2"><div className="w-3 h-3 rounded-full bg-amber-400" /><span>Drag top handle — rotate</span></div>
              <div className="flex items-center gap-2"><div className="w-3 h-3 rounded-sm bg-zinc-600 border border-zinc-500 cursor-move" /><span>Drag layer — move (Shift snaps)</span></div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}
