/* panels.jsx — LeftPanel, RightPanel, Toolbar */
const { useState, useCallback, useEffect } = React;

const SHAPES = [
  { key:'sphere',label:'Сфера' },{ key:'box',label:'Куб' },{ key:'cylinder',label:'Цилиндр' },
  { key:'cone',label:'Конус' },{ key:'torus',label:'Тор' },{ key:'torusknot',label:'Узел' },
  { key:'icosahedron',label:'Икосаэдр' },{ key:'octahedron',label:'Октаэдр' },{ key:'capsule',label:'Капсула' },
];

const MAT_PRESETS = [
  { label:'Глянец',   v:{ metalness:0, roughness:0.05, transmission:0, clearcoat:1 } },
  { label:'Матовый',  v:{ metalness:0, roughness:0.85, transmission:0, clearcoat:0 } },
  { label:'Металл',   v:{ metalness:1, roughness:0.08, transmission:0, clearcoat:0 } },
  { label:'Стекло',   v:{ metalness:0, roughness:0.0,  transmission:0.97, ior:1.5, clearcoat:1 } },
  { label:'Пластик',  v:{ metalness:0, roughness:0.4,  transmission:0, clearcoat:0.5 } },
  { label:'Золото',   v:{ metalness:1, roughness:0.12, transmission:0, color:'#d4a017' } },
  { label:'Хром',     v:{ metalness:1, roughness:0,    transmission:0, envMapIntensity:2 } },
  { label:'Матовый металл', v:{ metalness:0.8, roughness:0.5, transmission:0 } },
];

// ─── Left Panel ───────────────────────────────────────────────────
function LeftPanel({ objects, selectedId, onSelect, onAddSVG, onAddGLTF, onAddPrimitive, onDelete, onDuplicate, onToggleVisible, onRename }) {
  const [menu, setMenu] = useState(false);
  const [editingId, setEditingId] = useState(null);
  const [editName, setEditName] = useState('');

  const startRename = (id, name, e) => { e.stopPropagation(); setEditingId(id); setEditName(name); };
  const commitRename = (id) => { if (editName.trim()) onRename(id, editName.trim()); setEditingId(null); };

  const typeIcon = t => t === 'svg' ? IC.layers : t === 'gltf' ? IC.cube : IC.sparkle;

  return (
    <div style={{ width:224,background:'var(--bg1)',borderRight:'1px solid var(--border)',display:'flex',flexDirection:'column',overflow:'hidden',flexShrink:0 }}>
      {/* Header */}
      <div style={{ padding:'10px 12px 8px',borderBottom:'1px solid var(--border)' }}>
        <div style={{ display:'flex',alignItems:'center',justifyContent:'space-between' }}>
          <span style={{ fontSize:11,fontWeight:600,color:'var(--t1)',letterSpacing:'.02em' }}>Объекты сцены</span>
          <div style={{ position:'relative' }}>
            <Btn variant="ghost" size="xs" onClick={() => setMenu(m=>!m)} title="Добавить">
              <Svg d={IC.plus} size={13} /> Добавить
            </Btn>
            {menu && (
              <div style={{ position:'absolute',top:26,right:0,background:'var(--bg2)',border:'1px solid var(--border)',
                borderRadius:9,width:180,zIndex:200,boxShadow:'0 10px 30px rgba(0,0,0,.6)',overflow:'hidden' }}>
                <div style={{ padding:'6px 0' }}>
                  <MI onClick={() => { onAddSVG(); setMenu(false); }}><Svg d={IC.upload} size={12}/>Загрузить SVG</MI>
                  <MI onClick={() => { onAddGLTF(); setMenu(false); }}><Svg d={IC.cube} size={12}/>Загрузить GLB / GLTF</MI>
                  <div style={{ height:1,background:'var(--border)',margin:'5px 0' }} />
                  <div style={{ padding:'3px 12px 2px',fontSize:9.5,color:'var(--t3)',fontWeight:600,letterSpacing:'.08em',textTransform:'uppercase' }}>Фигуры</div>
                  {SHAPES.map(s => (
                    <MI key={s.key} onClick={() => { onAddPrimitive(s.key); setMenu(false); }}>
                      <Svg d={IC.sparkle} size={12}/>{s.label}
                    </MI>
                  ))}
                </div>
              </div>
            )}
          </div>
        </div>
      </div>

      {/* List */}
      <div style={{ flex:1,overflowY:'auto',padding:'4px 0' }} onClick={() => setMenu(false)}>
        {objects.length === 0 ? (
          <div style={{ padding:'30px 16px',textAlign:'center',color:'var(--t3)',fontSize:11,lineHeight:1.8 }}>
            Перетащите SVG-файл<br/>на вьюпорт или нажмите<br/>«Добавить»
          </div>
        ) : objects.map(obj => (
          <div key={obj.id} onClick={() => onSelect(obj.id)} style={{
            display:'flex',alignItems:'center',gap:7,padding:'5px 8px 5px 12px',cursor:'pointer',
            borderRadius:6,margin:'1px 4px',
            background: selectedId===obj.id ? 'rgba(94,92,230,.18)' : 'transparent',
            border: `1px solid ${selectedId===obj.id ? 'rgba(94,92,230,.35)' : 'transparent'}`,
          }}
            onMouseEnter={e => { if(selectedId!==obj.id) e.currentTarget.style.background='var(--bg3)'; }}
            onMouseLeave={e => { if(selectedId!==obj.id) e.currentTarget.style.background='transparent'; }}>
            <span style={{ color: selectedId===obj.id?'var(--accent2)':'var(--t3)',flexShrink:0 }}>
              <Svg d={typeIcon(obj.type)} size={12} />
            </span>
            {editingId === obj.id ? (
              <input autoFocus value={editName} onChange={e=>setEditName(e.target.value)}
                onBlur={() => commitRename(obj.id)} onKeyDown={e=>{ if(e.key==='Enter') commitRename(obj.id); if(e.key==='Escape') setEditingId(null); }}
                onClick={e=>e.stopPropagation()}
                style={{ flex:1,background:'var(--bg3)',border:'1px solid var(--accent)',borderRadius:4,color:'var(--t1)',fontSize:11,padding:'1px 5px',outline:'none' }}
              />
            ) : (
              <span onDoubleClick={e=>startRename(obj.id,obj.name,e)} style={{ flex:1,fontSize:11,color:selectedId===obj.id?'var(--t1)':'var(--t2)',overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap' }}>
                {obj.name}
              </span>
            )}
            <button onClick={e=>{e.stopPropagation();onToggleVisible(obj.id,!obj.visible);}} style={{
              background:'none',border:'none',padding:2,cursor:'pointer',display:'flex',
              color:'var(--t3)',opacity:obj.visible!==false?0.45:0.18,
            }}>
              <Svg d={obj.visible!==false?IC.eye:IC.eyeOff} size={11}/>
            </button>
          </div>
        ))}
      </div>

      {/* Actions */}
      {selectedId && (
        <div style={{ padding:'8px 10px',borderTop:'1px solid var(--border)',display:'flex',gap:4 }}>
          <Btn variant="outline" size="xs" onClick={()=>onDuplicate(selectedId)} title="Дублировать (Ctrl+D)"><Svg d={IC.copy} size={11}/>Копия</Btn>
          <Btn variant="danger" size="xs" onClick={()=>onDelete(selectedId)} title="Удалить (Delete)"><Svg d={IC.trash} size={11}/>Удалить</Btn>
        </div>
      )}
    </div>
  );
}

const MI = ({ children, onClick }) => (
  <div onClick={onClick} style={{ padding:'6px 12px',display:'flex',alignItems:'center',gap:8,fontSize:11,color:'var(--t1)',cursor:'pointer' }}
    onMouseEnter={e=>e.currentTarget.style.background='var(--bg3)'}
    onMouseLeave={e=>e.currentTarget.style.background=''}>
    {children}
  </div>
);

// ─── Toolbar ──────────────────────────────────────────────────────
function Toolbar({ transformMode, setTransformMode, onReset, onAddSVG, engineRef }) {
  return (
    <div style={{ height:46,background:'var(--bg1)',borderBottom:'1px solid var(--border)',display:'flex',alignItems:'center',padding:'0 14px',gap:10,flexShrink:0,zIndex:10 }}>
      {/* Logo */}
      <div style={{ display:'flex',alignItems:'center',gap:8,marginRight:4 }}>
        <div style={{ width:24,height:24,background:'linear-gradient(135deg,#5e5ce6,#a855f7)',borderRadius:7,display:'flex',alignItems:'center',justifyContent:'center',flexShrink:0 }}>
          <Svg d={IC.cube} size={13} stroke="#fff" />
        </div>
        <span style={{ fontSize:12.5,fontWeight:600,color:'var(--t1)',letterSpacing:'.01em' }}>3D Студия</span>
      </div>
      <div style={{ width:1,height:24,background:'var(--border)',flexShrink:0 }} />

      {/* Transform modes */}
      <div style={{ display:'flex',background:'var(--bg0)',borderRadius:8,padding:2,gap:2 }}>
        {[
          { mode:'translate', icon:IC.move,   label:'Переместить', key:'T' },
          { mode:'rotate',    icon:IC.rotate,  label:'Повернуть',   key:'R' },
          { mode:'scale',     icon:IC.scale,   label:'Масштаб',     key:'S' },
        ].map(({ mode, icon, label, key }) => (
          <button key={mode} onClick={() => setTransformMode(mode)} title={`${label} (${key})`} style={{
            width:32,height:28,background:transformMode===mode?'var(--bg3)':'transparent',
            border:'none',borderRadius:6,cursor:'pointer',display:'flex',alignItems:'center',justifyContent:'center',
            color:transformMode===mode?'var(--t1)':'var(--t2)',transition:'all .15s',
          }}>
            <Svg d={icon} size={14}/>
          </button>
        ))}
      </div>
      <div style={{ flex:1 }} />

      <Btn variant="outline" size="sm" onClick={onReset} title="Сбросить камеру">
        <Svg d={IC.reset} size={13}/>Камера
      </Btn>
    </div>
  );
}

// ─── Right Panel ──────────────────────────────────────────────────
const TABS = ['Материал','Текстуры','Геометрия','Позиция','Сцена','Экспорт'];

function RightPanel({ selectedId, objectType, engineRef }) {
  const [tab, setTab] = useState('Материал');
  const [mat, setMat] = useState({ color:'#5e5ce6',metalness:0,roughness:0.35,transmission:0,opacity:1,ior:1.5,thickness:0.5,clearcoat:0,envMapIntensity:1.2,emissive:'#000000',emissiveIntensity:0,wireframe:false,flatShading:false });
  const [geo, setGeo] = useState({ depth:0.45,bevelEnabled:true,bevelSize:0.05,bevelSegments:8 });
  const [pos, setPos] = useState({ x:0,y:0,z:0,rx:0,ry:0,rz:0,scale:1 });
  const [light, setLight] = useState({ ambientIntensity:0.6,ambientColor:'#ffffff',dirIntensity:1.8,dirColor:'#ffffff',dirX:5,dirY:10,dirZ:7.5,fillIntensity:0.4,fillColor:'#4488ff',shadows:true,exposure:1.2 });
  const [bg, setBg] = useState({ type:'solid',color1:'#0f0f1a',color2:'#1a1a3e' });
  const [bloom, setBloom] = useState({ enabled:false,strength:0.4,radius:0.5,threshold:0.8 });
  const [grid, setGrid] = useState(false);
  const [exp, setExp] = useState({ format:'png',width:2048,height:2048,transparent:true });
  const [exporting, setExporting] = useState(false);

  // Sync from engine when selection changes
  useEffect(() => {
    if (!selectedId || !engineRef.current) return;
    const p = engineRef.current.getObjectProps(selectedId);
    if (!p) return;
    setMat(prev => {
      const k = Object.keys(prev); const n={...prev}; k.forEach(key=>{ if(key in p) n[key]=p[key]; }); return n;
    });
    setGeo(prev => { const n={...prev}; Object.keys(prev).forEach(k=>{ if(k in p) n[k]=p[k]; }); return n; });
    setPos(prev => { const n={...prev}; Object.keys(prev).forEach(k=>{ if(k in p) n[k]=p[k]; }); return n; });
  }, [selectedId]);

  // Sync transform from gizmo drags
  useEffect(() => {
    if (!engineRef.current) return;
    engineRef.current.onTransformChange = (id, props) => {
      if (id === selectedId) setPos(prev => ({ ...prev, x:props.x,y:props.y,z:props.z,rx:props.rx,ry:props.ry,rz:props.rz,scale:props.scale }));
    };
  }, [selectedId, engineRef.current]);

  const updMat = useCallback((k,v) => {
    setMat(p=>{const n={...p,[k]:v}; return n;});
    if (selectedId && engineRef.current) engineRef.current.updateMaterial(selectedId,{[k]:v});
  },[selectedId]);

  const applyPreset = useCallback(v => {
    setMat(p=>({...p,...v}));
    if (selectedId && engineRef.current) engineRef.current.updateMaterial(selectedId,v);
  },[selectedId]);

  const updPos = useCallback(upd => {
    setPos(p=>({...p,...upd}));
    if (selectedId && engineRef.current) engineRef.current.updateTransform(selectedId,upd);
  },[selectedId]);

  const updLight = useCallback(upd => {
    setLight(p=>({...p,...upd}));
    if (engineRef.current) engineRef.current.updateLighting(upd);
  },[]);

  const updBg = useCallback(upd => {
    setBg(p=>{const n={...p,...upd}; engineRef.current?.setBackground(n.type,n.color1,n.color2); return n;});
  },[]);

  const updBloom = useCallback(upd => {
    setBloom(p=>{const n={...p,...upd}; engineRef.current?.setBloom(n); return n;});
  },[]);

  const updGrid = v => { setGrid(v); engineRef.current?.toggleGrid(v); };

  const applyGeo = useCallback(newGeo => {
    if (selectedId && engineRef.current && objectType === 'svg') engineRef.current.reextrudeSVG(selectedId, newGeo);
  },[selectedId, objectType]);

  const doExport = () => {
    if (!engineRef.current) return;
    setExporting(true);
    setTimeout(() => {
      const url = engineRef.current.exportImage(exp.format,exp.width,exp.height,exp.transparent);
      const a = document.createElement('a'); a.href=url; a.download=`render.${exp.format}`; a.click();
      setExporting(false);
    }, 80);
  };

  const noSel = !selectedId;

  return (
    <div style={{ width:272,background:'var(--bg1)',borderLeft:'1px solid var(--border)',display:'flex',flexDirection:'column',overflow:'hidden',flexShrink:0 }}>
      {/* Tab strip */}
      <div style={{ display:'flex',borderBottom:'1px solid var(--border)',overflowX:'auto' }}>
        {TABS.map(t => (
          <button key={t} onClick={()=>setTab(t)} style={{
            padding:'8px 10px',fontSize:10.5,fontFamily:'inherit',cursor:'pointer',background:'none',border:'none',
            borderBottom:`2px solid ${tab===t?'var(--accent)':'transparent'}`,
            color:tab===t?'var(--t1)':'var(--t2)',flexShrink:0,transition:'color .15s',whiteSpace:'nowrap',
          }}>{t}</button>
        ))}
      </div>

      <div style={{ flex:1,overflowY:'auto',padding:'14px 14px' }}>

        {/* ── МАТЕРИАЛ ── */}
        {tab==='Материал' && (noSel ? <EmptyState label="Выберите объект"/> : <>
          <SectionHead>Пресеты материала</SectionHead>
          <div style={{ display:'flex',flexWrap:'wrap',gap:4,marginBottom:12 }}>
            {MAT_PRESETS.map(p=>(
              <button key={p.label} onClick={()=>applyPreset(p.v)} style={{
                padding:'4px 8px',fontSize:10,fontFamily:'inherit',cursor:'pointer',
                background:'var(--bg3)',color:'var(--t2)',border:'1px solid var(--border)',borderRadius:6,
                transition:'all .15s',
              }}
                onMouseEnter={e=>{e.currentTarget.style.background='var(--accent)';e.currentTarget.style.color='#fff';}}
                onMouseLeave={e=>{e.currentTarget.style.background='var(--bg3)';e.currentTarget.style.color='var(--t2)';}}>
                {p.label}
              </button>
            ))}
          </div>
          <Divider/>
          <SectionHead>Цвет и поверхность</SectionHead>
          <ColorRow label="Цвет" value={mat.color} onChange={v=>updMat('color',v)}/>
          <Slider label="Металлик" value={mat.metalness} onChange={v=>updMat('metalness',v)}/>
          <Slider label="Шероховатость" value={mat.roughness} onChange={v=>updMat('roughness',v)}/>
          <Slider label="Глянец (clearcoat)" value={mat.clearcoat} onChange={v=>updMat('clearcoat',v)}/>
          <Slider label="Env отражение" value={mat.envMapIntensity} min={0} max={3} step={0.05} onChange={v=>updMat('envMapIntensity',v)}/>
          <Divider/>
          <SectionHead>Стекло и прозрачность</SectionHead>
          <Slider label="Пропускание" value={mat.transmission} onChange={v=>updMat('transmission',v)}/>
          <Slider label="IOR (преломление)" value={mat.ior} min={1} max={3} step={0.01} onChange={v=>updMat('ior',v)}/>
          <Slider label="Толщина стекла" value={mat.thickness} min={0} max={4} step={0.05} onChange={v=>updMat('thickness',v)}/>
          <Slider label="Непрозрачность" value={mat.opacity} onChange={v=>updMat('opacity',v)}/>
          <Divider/>
          <SectionHead>Свечение и эффекты</SectionHead>
          <ColorRow label="Emissive" value={mat.emissive} onChange={v=>updMat('emissive',v)}/>
          <Slider label="Интенс. свечения" value={mat.emissiveIntensity} min={0} max={4} step={0.05} onChange={v=>updMat('emissiveIntensity',v)}/>
          <Toggle label="Wireframe" value={mat.wireframe} onChange={v=>updMat('wireframe',v)}/>
          <Toggle label="Flat shading" value={mat.flatShading} onChange={v=>updMat('flatShading',v)}/>
        </>)}

        {/* ── ТЕКСТУРЫ ── */}
        {tab==='Текстуры' && (noSel ? <EmptyState label="Выберите объект"/> : <>
          <SectionHead>Карты текстур</SectionHead>
          <div style={{ fontSize:11,color:'var(--t3)',marginBottom:10,lineHeight:1.6 }}>
            Загружайте PNG/JPG изображения как текстуры для объекта.
          </div>
          <TextureSlot label="Albedo (цвет)" type="map" objectId={selectedId} engineRef={engineRef}/>
          <TextureSlot label="Normal map" type="normalMap" objectId={selectedId} engineRef={engineRef}/>
          <TextureSlot label="Roughness map" type="roughnessMap" objectId={selectedId} engineRef={engineRef}/>
          <TextureSlot label="Metalness map" type="metalnessMap" objectId={selectedId} engineRef={engineRef}/>
          <TextureSlot label="Emissive map" type="emissiveMap" objectId={selectedId} engineRef={engineRef}/>
          <Divider/>
          <div style={{ fontSize:11,color:'var(--t3)',lineHeight:1.6 }}>
            После загрузки Normal map включите соответствующую интенсивность в настройках материала.
          </div>
        </>)}

        {/* ── ГЕОМЕТРИЯ ── */}
        {tab==='Геометрия' && (noSel ? <EmptyState label="Выберите объект"/> : <>
          {objectType==='svg' ? <>
            <SectionHead>Экструзия SVG</SectionHead>
            <Slider label="Глубина (толщина)" value={geo.depth} min={0.01} max={5} step={0.02} onChange={v=>setGeo(p=>({...p,depth:v}))}/>
            <Toggle label="Скос краёв (bevel)" value={geo.bevelEnabled} onChange={v=>setGeo(p=>({...p,bevelEnabled:v}))}/>
            <Slider label="Размер скоса" value={geo.bevelSize} min={0} max={0.5} step={0.005} onChange={v=>setGeo(p=>({...p,bevelSize:v}))}/>
            <Slider label="Сегменты скоса" value={geo.bevelSegments} min={1} max={16} step={1} onChange={v=>setGeo(p=>({...p,bevelSegments:v}))}/>
            <Btn variant="solid" size="md" onClick={()=>applyGeo(geo)} style={{width:'100%',justifyContent:'center',marginTop:6}}>
              <Svg d={IC.check} size={13}/>Применить геометрию
            </Btn>
            <div style={{ marginTop:8,padding:'8px 10px',background:'var(--bg3)',borderRadius:7,fontSize:10.5,color:'var(--t3)',lineHeight:1.5 }}>
              Изменение формы требует пересчёта — нажмите «Применить» чтобы обновить 3D-геометрию SVG.
            </div>
          </> : <>
            <SectionHead>Масштаб объекта</SectionHead>
            <Slider label="Масштаб" value={pos.scale} min={0.05} max={6} step={0.05} onChange={v=>updPos({scale:v})}/>
          </>}
        </>)}

        {/* ── ПОЗИЦИЯ ── */}
        {tab==='Позиция' && (noSel ? <EmptyState label="Выберите объект"/> : <>
          <SectionHead>Перемещение</SectionHead>
          <XYZRow vx={pos.x} vy={pos.y} vz={pos.z} onChange={upd=>updPos(upd)} step={0.1}/>
          <Divider/>
          <SectionHead>Вращение (°)</SectionHead>
          <XYZRow vx={pos.rx} vy={pos.ry} vz={pos.rz} onChange={upd=>updPos({rx:upd.x??pos.rx,ry:upd.y??pos.ry,rz:upd.z??pos.rz})} step={1}/>
          <Divider/>
          <SectionHead>Масштаб</SectionHead>
          <Slider label="Масштаб" value={pos.scale} min={0.05} max={6} step={0.05} onChange={v=>updPos({scale:v})}/>
          <Divider/>
          <Btn variant="outline" size="sm" onClick={()=>updPos({x:0,y:0,z:0,rx:0,ry:0,rz:0,scale:1})}>
            Сбросить трансформации
          </Btn>
        </>)}

        {/* ── СЦЕНА ── */}
        {tab==='Сцена' && <>
          <SectionHead>Фон</SectionHead>
          <div style={{ display:'flex',gap:4,marginBottom:10 }}>
            {[['solid','Цвет'],['gradient','Градиент'],['transparent','Прозрачный']].map(([k,l])=>(
              <button key={k} onClick={()=>updBg({type:k})} style={{
                flex:1,padding:'5px 4px',fontSize:10.5,fontFamily:'inherit',cursor:'pointer',
                background:bg.type===k?'var(--accent)':'var(--bg3)',
                color:bg.type===k?'#fff':'var(--t2)',
                border:`1px solid ${bg.type===k?'var(--accent)':'var(--border)'}`,
                borderRadius:6,transition:'all .15s',
              }}>{l}</button>
            ))}
          </div>
          {bg.type!=='transparent'&&<ColorRow label={bg.type==='gradient'?'Цвет 1':'Цвет'} value={bg.color1} onChange={v=>updBg({color1:v})}/>}
          {bg.type==='gradient'&&<ColorRow label="Цвет 2" value={bg.color2} onChange={v=>updBg({color2:v})}/>}
          <Toggle label="Сетка (grid)" value={grid} onChange={updGrid}/>
          <Divider/>
          <SectionHead>Освещение</SectionHead>
          <Slider label="Ambient" value={light.ambientIntensity} min={0} max={3} step={0.05} onChange={v=>updLight({ambientIntensity:v})}/>
          <ColorRow label="Цвет ambient" value={light.ambientColor} onChange={v=>updLight({ambientColor:v})}/>
          <Slider label="Основной свет" value={light.dirIntensity} min={0} max={5} step={0.1} onChange={v=>updLight({dirIntensity:v})}/>
          <ColorRow label="Цвет осн. света" value={light.dirColor} onChange={v=>updLight({dirColor:v})}/>
          <XYZRow label="Позиция света" vx={light.dirX} vy={light.dirY} vz={light.dirZ}
            onChange={upd=>updLight({dirX:upd.x??light.dirX,dirY:upd.y??light.dirY,dirZ:upd.z??light.dirZ})} step={0.5}/>
          <Slider label="Заполн. свет" value={light.fillIntensity} min={0} max={2} step={0.05} onChange={v=>updLight({fillIntensity:v})}/>
          <ColorRow label="Цвет заполн." value={light.fillColor} onChange={v=>updLight({fillColor:v})}/>
          <Toggle label="Тени" value={light.shadows} onChange={v=>updLight({shadows:v})}/>
          <Slider label="Экспозиция" value={light.exposure} min={0.1} max={4} step={0.05} onChange={v=>updLight({exposure:v})}/>
          <Divider/>
          <SectionHead>Bloom (свечение)</SectionHead>
          <Toggle label="Включить bloom" value={bloom.enabled} onChange={v=>updBloom({enabled:v})}/>
          <Slider label="Сила" value={bloom.strength} min={0} max={3} step={0.05} onChange={v=>updBloom({strength:v})}/>
          <Slider label="Радиус" value={bloom.radius} min={0} max={1} step={0.01} onChange={v=>updBloom({radius:v})}/>
          <Slider label="Порог" value={bloom.threshold} min={0} max={1} step={0.01} onChange={v=>updBloom({threshold:v})}/>
        </>}

        {/* ── ЭКСПОРТ ── */}
        {tab==='Экспорт' && <>
          <SectionHead>Формат</SectionHead>
          <Row label="Файл">
            <select value={exp.format} onChange={e=>setExp(p=>({...p,format:e.target.value}))} style={{flex:1}}>
              <option value="png">PNG</option>
              <option value="jpg">JPEG</option>
              <option value="webp">WebP</option>
            </select>
          </Row>
          <Divider/>
          <SectionHead>Разрешение</SectionHead>
          <div style={{ display:'grid',gridTemplateColumns:'1fr 1fr',gap:5,marginBottom:10 }}>
            {[[512,'512'],[1024,'1K'],[2048,'2K'],[4096,'4K']].map(([v,l])=>(
              <button key={v} onClick={()=>setExp(p=>({...p,width:v,height:v}))} style={{
                padding:'5px',fontSize:10.5,fontFamily:'inherit',cursor:'pointer',
                background:exp.width===v?'var(--accent)':'var(--bg3)',
                color:exp.width===v?'#fff':'var(--t2)',
                border:`1px solid ${exp.width===v?'var(--accent)':'var(--border)'}`,
                borderRadius:6,transition:'all .15s',
              }}>{l}</button>
            ))}
          </div>
          <Row label="Ширина px"><NumInput value={exp.width} min={64} max={8192} step={64} onChange={v=>setExp(p=>({...p,width:v}))}/></Row>
          <Row label="Высота px"><NumInput value={exp.height} min={64} max={8192} step={64} onChange={v=>setExp(p=>({...p,height:v}))}/></Row>
          <Divider/>
          <Toggle label="Прозрачный фон" value={exp.transparent} onChange={v=>setExp(p=>({...p,transparent:v}))}/>
          <button onClick={doExport} disabled={exporting} style={{
            width:'100%',padding:'10px',background:'var(--accent)',color:'#fff',border:'none',
            borderRadius:8,fontSize:12,fontFamily:'inherit',cursor:exporting?'wait':'pointer',
            display:'flex',alignItems:'center',justifyContent:'center',gap:8,fontWeight:500,
            marginTop:14,transition:'background .15s',opacity:exporting?0.7:1,
          }}
            onMouseEnter={e=>{if(!exporting)e.currentTarget.style.background='var(--accent2)';}}
            onMouseLeave={e=>e.currentTarget.style.background='var(--accent)'}>
            <Svg d={IC.download} size={14}/>
            {exporting?'Рендеринг…':`Скачать ${exp.format.toUpperCase()}`}
          </button>
        </>}

      </div>
    </div>
  );
}

Object.assign(window, { LeftPanel, RightPanel, Toolbar });
