// ─── Clip Proxy Helper ──────────────────────────────────
function proxyClipUrl(url) {
  if (!url) return url;
  if (url.startsWith('https://clip.cafe/')) return '/api/clips/proxy?url=' + encodeURIComponent(url);
  return url;
}

// ─── Storage Cleanup Helpers ─────────────────────────────
function deleteStorageFromUrl(url) {
  if (!url || !url.includes('firebasestorage.googleapis.com')) return;
  try {
    var path = decodeURIComponent(url.split('/o/')[1].split('?')[0]);
    firebase.storage().ref(path).delete().catch(function(err) {
      console.warn('[cleanup] storage delete failed:', err.message);
    });
  } catch(e) {
    console.warn('[cleanup] could not parse storage path from URL');
  }
}

function deleteDropStorage(dropId) {
  firebase.storage().ref('media/' + dropId).listAll().then(function(result) {
    result.items.forEach(function(item) { item.delete(); });
  }).catch(function(err) {
    console.warn('[cleanup] drop storage cleanup failed:', err.message);
  });
}

// ─── Drops Module ────────────────────────────────────────
function DropsModule(props) {
  var db = props.db, showToast = props.showToast;
  var drops = props.drops;
  var cards = props.cards;
  var library = props.library, crowdScores = props.crowdScores;
  var generateCode = props.generateCode, generateId = props.generateId;
  var tasteProfile = props.tasteProfile;
  var SCORE_FIELDS = props.SCORE_FIELDS;

  var [search, setSearch] = useState('');
  var [selected, setSelected] = useState({});
  var [editDrop, setEditDrop] = useState(null);
  var [saving, setSaving] = useState(false);
  var [deleteConfirm, setDeleteConfirm] = useState(false);
  var [bulkStartDate, setBulkStartDate] = useState('');

  // Render state
  var [renderFormat, setRenderFormat] = useState('PORTRAIT (4:5)');
  var [renderTheme, setRenderTheme] = useState('DARK');
  var [rendering, setRendering] = useState(false);
  var [renderPreview, setRenderPreview] = useState(null);
  var [batchRendering, setBatchRendering] = useState(false);
  var [batchProgress, setBatchProgress] = useState(null);

  // Clip search state
  var [clipSearching, setClipSearching] = useState(false);
  var [clipResults, setClipResults] = useState(null);
  var [clipSearchQuery, setClipSearchQuery] = useState('');
  var [mediaUploading, setMediaUploading] = useState(false);
  var [mediaUploadProgress, setMediaUploadProgress] = useState(0);

  function getToken() { return firebase.auth().currentUser.getIdToken(); }

  function handleMediaUpload(e) {
    var file = e.target.files && e.target.files[0];
    if (!file || !editDrop) return;
    e.target.value = '';
    setMediaUploading(true); setMediaUploadProgress(0);
    var ref = firebase.storage().ref('media/' + editDrop.id + '/' + file.name);
    var task = ref.put(file);
    task.on('state_changed', function(snap) {
      setMediaUploadProgress(Math.round((snap.bytesTransferred / snap.totalBytes) * 100));
    }, function(err) {
      setMediaUploading(false); showToast('UPLOAD FAILED: ' + err.message);
    }, function() {
      task.snapshot.ref.getDownloadURL().then(function(url) {
        var isImage = file.type.startsWith('image/');
        updateDropField('clip_url', url);
        updateDropField('clip_thumbnail', isImage ? url : null);
        updateDropField('clip_title', file.name);
        setMediaUploading(false);
        showToast('UPLOADED');
      });
    });
  }

  var dropsArray = useMemo(function() {
    if (!drops) return [];
    return Object.values(drops);
  }, [drops]);

  var drafts = useMemo(function() {
    var arr = dropsArray.filter(function(d) { return d.status === 'draft'; });
    if (search) {
      var q = search.toLowerCase();
      arr = arr.filter(function(d) {
        return (d.line || '').toLowerCase().includes(q) ||
          (d.source || '').toLowerCase().includes(q) ||
          (d.situation || '').toLowerCase().includes(q);
      });
    }
    arr.sort(function(a, b) { return (a.created_at || '').localeCompare(b.created_at || ''); });
    return arr;
  }, [dropsArray, search]);

  function toggleSelect(id) { setSelected(function(p) { var n = Object.assign({}, p); if (n[id]) delete n[id]; else n[id] = true; return n; }); }
  function selectAllDrafts() { var n = {}; drafts.forEach(function(d) { n[d.id] = true; }); setSelected(n); }
  function clearSelection() { setSelected({}); }
  var selCount = Object.keys(selected).length;

  function newDrop() {
    var id = 'drop-' + Date.now() + '-' + Math.random().toString(36).substr(2, 6);
    setEditDrop({
      id: id, line: '', source: '', situation: '', signoff: '', acronym: '', medium: 'movie',
      scheduled_date: null, status: 'draft', created_at: new Date().toISOString(), reference_id: '', performance: null
    });
    setDeleteConfirm(false);
    setRenderPreview(null);
  }

  function openDrop(drop) {
    setEditDrop(JSON.parse(JSON.stringify(drop)));
    setDeleteConfirm(false);
    setRenderPreview(null);
  }

  function updateDropField(field, value) {
    setEditDrop(function(prev) {
      var next = Object.assign({}, prev);
      next[field] = value;
      return next;
    });
  }

  function saveDrop() {
    if (!editDrop || !editDrop.id) return;
    setSaving(true);
    var d = Object.assign({}, editDrop);
    if (d.scheduled_date && d.status === 'draft') d.status = 'scheduled';
    if (!d.scheduled_date && d.status === 'scheduled') d.status = 'draft';
    db.ref('drops/' + d.id).set(d).then(function() {
      setSaving(false);
      showToast('DROP SAVED');
      setEditDrop(null);
    }).catch(function(e) { setSaving(false); showToast('SAVE FAILED: ' + e.message); });
  }

  function deleteDrop() {
    if (!editDrop || !editDrop.id) return;
    deleteDropStorage(editDrop.id);
    db.ref('drops/' + editDrop.id).remove().then(function() {
      showToast('DROP DELETED');
      setEditDrop(null); setDeleteConfirm(false);
    }).catch(function(e) { showToast('DELETE FAILED: ' + e.message); });
  }

  function copyToClipboard() {
    if (!editDrop) return;
    var text = '';
    if (editDrop.situation) text += editDrop.situation + '\n\n';
    if (editDrop.line) text += '"' + editDrop.line + '"';
    if (editDrop.source) text += ' — ' + editDrop.source;
    text += '\n';
    if (editDrop.signoff) text += '\n' + editDrop.signoff;
    navigator.clipboard.writeText(text).then(function() { showToast('COPIED'); }).catch(function() { showToast('COPY FAILED'); });
  }

  function searchClips() {
    if (!editDrop) return;
    setClipSearching(true); setClipResults(null);
    getToken().then(function(token) {
      return fetch('/api/clips/search', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token },
        body: JSON.stringify({ line: editDrop.line || '', source: editDrop.source || '' })
      });
    }).then(function(res) {
      if (!res.ok) throw new Error('HTTP ' + res.status);
      return res.json();
    }).then(function(data) {
      setClipResults(data.results || []);
      setClipSearching(false);
    }).catch(function(e) { setClipSearching(false); showToast('CLIP SEARCH FAILED: ' + e.message); });
  }

  function searchClipsCustom() {
    if (!clipSearchQuery.trim()) return;
    setClipSearching(true); setClipResults(null);
    getToken().then(function(token) {
      return fetch('/api/clips/search', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token },
        body: JSON.stringify({ query: clipSearchQuery.trim() })
      });
    }).then(function(res) {
      if (!res.ok) throw new Error('HTTP ' + res.status);
      return res.json();
    }).then(function(data) {
      setClipResults(data.results || []);
      setClipSearching(false);
    }).catch(function(e) { setClipSearching(false); showToast('CLIP SEARCH FAILED: ' + e.message); });
  }

  function selectClip(clip) {
    updateDropField('clip_url', clip.videoUrl);
    updateDropField('clip_thumbnail', clip.thumbnailUrl);
    updateDropField('clip_title', (clip.title || '') + (clip.year ? ' (' + clip.year + ')' : ''));
    setClipResults(null);
    setClipSearchQuery('');
  }

  function removeClip() {
    deleteStorageFromUrl(editDrop.clip_url);
    updateDropField('clip_url', null);
    updateDropField('clip_thumbnail', null);
    updateDropField('clip_title', null);
  }

  function bulkSchedule() {
    if (!bulkStartDate || selCount === 0) return;
    var ids = Object.keys(selected).filter(function(id) { return drops && drops[id] && drops[id].status === 'draft'; });
    if (ids.length === 0) { showToast('NO DRAFTS SELECTED'); return; }
    var updates = {};
    var start = new Date(bulkStartDate + 'T00:00:00');
    ids.forEach(function(id, i) {
      var d = new Date(start);
      d.setDate(d.getDate() + i);
      var ds = d.getFullYear() + '-' + String(d.getMonth() + 1).padStart(2, '0') + '-' + String(d.getDate()).padStart(2, '0');
      updates['drops/' + id + '/scheduled_date'] = ds;
      updates['drops/' + id + '/status'] = 'scheduled';
    });
    db.ref().update(updates).then(function() {
      showToast(ids.length + ' DROPS SCHEDULED');
      clearSelection(); setBulkStartDate('');
    }).catch(function(e) { showToast('SCHEDULE FAILED: ' + e.message); });
  }

  // Render functions — browser-side via ffmpeg.wasm
  function renderDrop() {
    if (!editDrop) return;
    setRendering(true); setRenderPreview(null);
    var renderData = {
      situation: editDrop.situation || '',
      puzzle: editDrop.signoff || '',
      media_url: proxyClipUrl(editDrop.clip_url) || undefined,
    };
    var renderOpts = {
      format: renderFormat, theme: renderTheme,
      name: props.brandSettings && props.brandSettings.display_name || 'lineconic',
      handle: props.brandSettings && props.brandSettings.handle || '@lineconic',
      bar_color: props.brandSettings && props.brandSettings.line_color || '#FF007F',
      bar_height: props.brandSettings && props.brandSettings.line_weight || 25,
    };
    window.FFmpegRenderer.renderToMP4(renderData, renderOpts, function(pct) {
      // progress — could show percentage but keeping simple indeterminate for calendar view
    }).then(function(blob) {
      var url = URL.createObjectURL(blob);
      setRenderPreview(url);
      if (editDrop.status === 'scheduled') {
        var updated = Object.assign({}, editDrop, { status: 'rendered', rendered_at: new Date().toISOString() });
        db.ref('drops/' + editDrop.id).set(updated).then(function() {
          setEditDrop(updated);
          showToast('RENDERED');
        });
      } else {
        showToast('RENDERED');
      }
      setRendering(false);
    }).catch(function(e) { setRendering(false); showToast('RENDER FAILED: ' + e.message); });
  }

  function downloadRender() {
    if (!renderPreview) return;
    var link = document.createElement('a');
    link.href = renderPreview;
    link.download = (editDrop ? editDrop.id : 'render') + '.mp4';
    link.click();
  }

  function batchRender() {
    var ids = Object.keys(selected).filter(function(id) {
      return drops && drops[id] && (drops[id].status === 'scheduled' || drops[id].status === 'rendered');
    });
    if (ids.length === 0) { showToast('NO SCHEDULED DROPS SELECTED'); return; }
    setBatchRendering(true); setBatchProgress('0 / ' + ids.length);

    var renderOpts = {
      format: renderFormat, theme: renderTheme,
      name: props.brandSettings && props.brandSettings.display_name || 'lineconic',
      handle: props.brandSettings && props.brandSettings.handle || '@lineconic',
      bar_color: props.brandSettings && props.brandSettings.line_color || '#FF007F',
      bar_height: props.brandSettings && props.brandSettings.line_weight || 25,
    };

    // Render sequentially to avoid memory pressure
    var done = 0;
    function renderNext() {
      if (done >= ids.length) {
        var updates = {};
        var now = new Date().toISOString();
        ids.forEach(function(id) {
          if (drops[id].status === 'scheduled') {
            updates['drops/' + id + '/status'] = 'rendered';
            updates['drops/' + id + '/rendered_at'] = now;
          }
        });
        if (Object.keys(updates).length > 0) {
          db.ref().update(updates).then(function() {
            showToast(ids.length + ' DROPS RENDERED');
          });
        } else {
          showToast(ids.length + ' DROPS RENDERED');
        }
        setBatchRendering(false); setBatchProgress(null); clearSelection();
        return;
      }
      var id = ids[done];
      var d = drops[id];
      var renderData = {
        situation: d.situation || '',
        puzzle: d.signoff || '',
        media_url: proxyClipUrl(d.clip_url) || undefined,
      };
      setBatchProgress((done + 1) + ' / ' + ids.length);
      window.FFmpegRenderer.renderToMP4(renderData, renderOpts).then(function() {
        done++;
        renderNext();
      }).catch(function(e) {
        done++;
        console.warn('Batch render failed for ' + id + ':', e.message);
        renderNext();
      });
    }
    renderNext();
  }

  // Performance pill color helper
  function getPillStyle(drop) {
    if (drop.status === 'published') {
      if (drop.performance === 'fire') return { bg: 'rgba(74,222,128,.12)', color: '#4ade80', border: '#4ade80' };
      if (drop.performance === 'flop') return { bg: 'rgba(239,68,68,.12)', color: '#ef4444', border: '#ef4444' };
      if (drop.performance === 'mid') return { bg: 'rgba(156,163,175,.12)', color: '#9ca3af', border: '#9ca3af' };
      return { bg: 'rgba(74,222,128,.12)', color: '#4ade80', border: '#4ade80' };
    }
    if (drop.status === 'rendered') return { bg: 'rgba(0,255,255,.12)', color: 'var(--cyan)', border: 'var(--cyan)' };
    return { bg: 'rgba(255,215,0,.12)', color: 'var(--gold)', border: 'var(--gold)' };
  }

  if (drops === null) return React.createElement('div', {className: 'A-empty'}, React.createElement('div', {className: 'icon'}, 'L'), React.createElement('div', {className: 'msg'}, 'LOADING DROPS...'));

  return (
    <div style={{height:'100%',overflow:'hidden'}}>
      <StudioView db={db} drops={drops} showToast={showToast} getToken={getToken} cards={cards} dropsArray={dropsArray} getPillStyle={getPillStyle} library={library} crowdScores={crowdScores} generateCode={generateCode} generateId={generateId} tasteProfile={tasteProfile} SCORE_FIELDS={SCORE_FIELDS} brandSettings={props.brandSettings} creators={props.creators} />
    </div>
  );
}


// ─── Studio View Component ──────────────────────────────
function StudioView(props) {
  var db = props.db, drops = props.drops, showToast = props.showToast, getToken = props.getToken, cards = props.cards, dropsArray = props.dropsArray, getPillStyle = props.getPillStyle;
  var library = props.library, crowdScores = props.crowdScores;
  var generateCode = props.generateCode, generateId = props.generateId;
  var tasteProfile = props.tasteProfile;
  var SCORE_FIELDS = props.SCORE_FIELDS;
  var brandSettings = props.brandSettings;
  var creators = props.creators;

  var [isMobile, setIsMobile] = useState(window.innerWidth < 768);
  useEffect(function(){
    function onResize(){setIsMobile(window.innerWidth < 768)}
    window.addEventListener('resize', onResize);
    return function(){window.removeEventListener('resize', onResize)};
  },[]);
  var [mobileShowSettings, setMobileShowSettings] = useState(false);

  var [activeDrop, setActiveDrop] = useState(null);
  var [dropPickerSearch, setDropPickerSearch] = useState('');
  var [clipSearching, setClipSearching] = useState(false);
  var [clipResults, setClipResults] = useState(null);
  var [clipSearchQuery, setClipSearchQuery] = useState('');
  var [clipPreviewUrl, setClipPreviewUrl] = useState(null);
  var [mediaUploading, setMediaUploading] = useState(false);
  var [mediaUploadProgress, setMediaUploadProgress] = useState(0);
  // Load saved preferences from localStorage
  var savedPrefs = useMemo(function() {
    try { return JSON.parse(localStorage.getItem('drops_studio_prefs') || '{}'); } catch(e) { return {}; }
  }, []);

  var [renderFormat, setRenderFormat] = useState(savedPrefs.renderFormat || 'PORTRAIT (4:5)');
  var [renderTheme, setRenderTheme] = useState(savedPrefs.renderTheme || 'DARK');
  var [rendering, setRendering] = useState(false);
  var [renderPreview, setRenderPreview] = useState(null);
  var [saving, setSaving] = useState(false);
  var [deleteConfirm, setDeleteConfirm] = useState(false);
  var [clipPlaying, setClipPlaying] = useState(false);

  // Advanced render settings
  var [showBar, setShowBar] = useState(savedPrefs.showBar !== undefined ? savedPrefs.showBar : false);
  var [showFooter, setShowFooter] = useState(savedPrefs.showFooter !== undefined ? savedPrefs.showFooter : false);
  var [showBadge, setShowBadge] = useState(savedPrefs.showBadge !== undefined ? savedPrefs.showBadge : false);
  var [showProfile, setShowProfile] = useState(savedPrefs.showProfile !== undefined ? savedPrefs.showProfile : true);
  var [showLine, setShowLine] = useState(savedPrefs.showLine !== undefined ? savedPrefs.showLine : false);
  var [showSignoff, setShowSignoff] = useState(savedPrefs.showSignoff !== undefined ? savedPrefs.showSignoff : false);
  var [previewTab, setPreviewTab] = useState('live');
  var [mediaRadius, setMediaRadius] = useState(savedPrefs.mediaRadius !== undefined ? savedPrefs.mediaRadius : 45);
  var [videoScale, setVideoScale] = useState(savedPrefs.videoScale !== undefined ? savedPrefs.videoScale : 1.0);
  var [clipStartTime, setClipStartTime] = useState(savedPrefs.clipStartTime !== undefined ? savedPrefs.clipStartTime : 0);
  var [clipEndTime, setClipEndTime] = useState(savedPrefs.clipEndTime !== undefined ? savedPrefs.clipEndTime : 15);
  var [useFullClip, setUseFullClip] = useState(savedPrefs.useFullClip !== undefined ? savedPrefs.useFullClip : true);

  // Persist preferences to localStorage on change
  useEffect(function() {
    localStorage.setItem('drops_studio_prefs', JSON.stringify({
      renderFormat: renderFormat, renderTheme: renderTheme,
      showBar: showBar, showFooter: showFooter, showBadge: showBadge,
      showProfile: showProfile, showLine: showLine, showSignoff: showSignoff,
      mediaRadius: mediaRadius, videoScale: videoScale,
      clipStartTime: clipStartTime, clipEndTime: clipEndTime, useFullClip: useFullClip
    }));
  }, [renderFormat, renderTheme, showBar, showFooter, showBadge, showProfile, showLine, showSignoff, mediaRadius, videoScale, clipStartTime, clipEndTime, useFullClip]);

  // AI Generate Situation state
  var [aiGenerating, setAiGenerating] = useState(false);

  // AI Score state
  var [aiScoring, setAiScoring] = useState(false);
  var [aiScoreResult, setAiScoreResult] = useState(null);

  // Batch selection state
  var [selected, setSelected] = useState({});
  var [bulkStartDate, setBulkStartDate] = useState('');
  var [batchRendering, setBatchRendering] = useState(false);
  var [batchProgress, setBatchProgress] = useState(null);

  // Bulk Plan state
  var [bulkBrief, setBulkBrief] = useState('');
  var [bulkCount, setBulkCount] = useState(15);
  var [bulkLoading, setBulkLoading] = useState(false);
  var [bulkPlan, setBulkPlan] = useState(null);
  var [bulkError, setBulkError] = useState(null);
  var [bulkRefineText, setBulkRefineText] = useState('');
  var [bulkRefining, setBulkRefining] = useState(false);
  var [bulkCreatorId, setBulkCreatorId] = useState('');
  var [bulkAutoSchedule, setBulkAutoSchedule] = useState(true);

  var sortedDrops = useMemo(function() {
    var arr = dropsArray.slice();
    if (dropPickerSearch) {
      var q = dropPickerSearch.toLowerCase();
      arr = arr.filter(function(d) {
        return (d.line || '').toLowerCase().includes(q) ||
          (d.source || '').toLowerCase().includes(q) ||
          (d.situation || '').toLowerCase().includes(q);
      });
    }
    arr.sort(function(a, b) { return (b.created_at || '').localeCompare(a.created_at || ''); });
    return arr;
  }, [dropsArray, dropPickerSearch]);

  function newDrop() {
    var id = 'drop-' + Date.now() + '-' + Math.random().toString(36).substr(2, 6);
    setActiveDrop({
      id: id, line: '', source: '', situation: '', signoff: '', acronym: '', medium: 'movie',
      scheduled_date: null, status: 'draft', created_at: new Date().toISOString(), reference_id: '', performance: null
    });
    setDeleteConfirm(false); setRenderPreview(null);
    setClipResults(null); setClipPreviewUrl(null); setClipPlaying(false); setAiScoreResult(null);
  }

  function loadDrop(drop) {
    setActiveDrop(JSON.parse(JSON.stringify(drop)));
    setDeleteConfirm(false); setRenderPreview(null);
    setClipResults(null); setClipPreviewUrl(null); setClipPlaying(false); setAiScoreResult(null);
  }

  function updateField(field, value) {
    setActiveDrop(function(prev) {
      if (!prev) return prev;
      var next = Object.assign({}, prev);
      next[field] = value;
      if (field === 'acronym' && !prev.signoff) {
        next.signoff = value;
      }
      return next;
    });
  }

  function saveDrop() {
    if (!activeDrop || !activeDrop.id) return;
    setSaving(true);
    var d = Object.assign({}, activeDrop);
    if (d.scheduled_date && d.status === 'draft') d.status = 'scheduled';
    if (!d.scheduled_date && d.status === 'scheduled') d.status = 'draft';
    db.ref('drops/' + d.id).set(d).then(function() {
      setSaving(false);
      showToast('DROP SAVED');
      setActiveDrop(d);
    }).catch(function(e) { setSaving(false); showToast('SAVE FAILED: ' + e.message); });
  }

  function deleteDrop() {
    if (!activeDrop || !activeDrop.id) return;
    deleteDropStorage(activeDrop.id);
    db.ref('drops/' + activeDrop.id).remove().then(function() {
      showToast('DROP DELETED');
      setActiveDrop(null);
      setDeleteConfirm(false);
    }).catch(function(e) { showToast('DELETE FAILED: ' + e.message); });
  }

  function copyToClipboard() {
    if (!activeDrop) return;
    var text = '';
    if (activeDrop.situation) text += activeDrop.situation + '\n\n';
    if (activeDrop.line) text += '"' + activeDrop.line + '"';
    if (activeDrop.source) text += ' — ' + activeDrop.source;
    text += '\n';
    if (activeDrop.signoff) text += '\n' + activeDrop.signoff;
    navigator.clipboard.writeText(text).then(function() { showToast('COPIED'); }).catch(function() { showToast('COPY FAILED'); });
  }

  function searchClips() {
    if (!activeDrop) return;
    setClipSearching(true); setClipResults(null); setClipPreviewUrl(null);
    getToken().then(function(token) {
      return fetch('/api/clips/search', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token },
        body: JSON.stringify({ line: activeDrop.line || '', source: activeDrop.source || '' })
      });
    }).then(function(res) {
      if (!res.ok) throw new Error('HTTP ' + res.status);
      return res.json();
    }).then(function(data) {
      setClipResults(data.results || []);
      setClipSearching(false);
    }).catch(function(e) { setClipSearching(false); showToast('CLIP SEARCH FAILED: ' + e.message); });
  }

  function searchClipsCustom() {
    if (!clipSearchQuery.trim()) return;
    setClipSearching(true); setClipResults(null); setClipPreviewUrl(null);
    getToken().then(function(token) {
      return fetch('/api/clips/search', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token },
        body: JSON.stringify({ query: clipSearchQuery.trim() })
      });
    }).then(function(res) {
      if (!res.ok) throw new Error('HTTP ' + res.status);
      return res.json();
    }).then(function(data) {
      setClipResults(data.results || []);
      setClipSearching(false);
    }).catch(function(e) { setClipSearching(false); showToast('CLIP SEARCH FAILED: ' + e.message); });
  }

  function selectClip(clip) {
    updateField('clip_url', clip.videoUrl);
    updateField('clip_thumbnail', clip.thumbnailUrl);
    updateField('clip_title', (clip.title || '') + (clip.year ? ' (' + clip.year + ')' : ''));
    setClipResults(null);
    setClipSearchQuery('');
    setClipPreviewUrl(null);
  }

  function removeClip() {
    deleteStorageFromUrl(activeDrop.clip_url);
    updateField('clip_url', null);
    updateField('clip_thumbnail', null);
    updateField('clip_title', null);
    setClipPlaying(false);
  }

  function handleMediaUpload(e) {
    var file = e.target.files && e.target.files[0];
    if (!file || !activeDrop) return;
    e.target.value = '';
    setMediaUploading(true); setMediaUploadProgress(0);
    var ref = firebase.storage().ref('media/' + activeDrop.id + '/' + file.name);
    var task = ref.put(file);
    task.on('state_changed', function(snap) {
      setMediaUploadProgress(Math.round((snap.bytesTransferred / snap.totalBytes) * 100));
    }, function(err) {
      setMediaUploading(false); showToast('UPLOAD FAILED: ' + err.message);
    }, function() {
      task.snapshot.ref.getDownloadURL().then(function(url) {
        var isImage = file.type.startsWith('image/');
        updateField('clip_url', url);
        updateField('clip_thumbnail', isImage ? url : null);
        updateField('clip_title', file.name);
        setMediaUploading(false);
        showToast('UPLOADED');
      });
    });
  }

  function buildRenderSettings(outputs) {
    return {
      format: renderFormat,
      theme: renderTheme,
      outputs: outputs,
      name: brandSettings && brandSettings.display_name || 'lineconic',
      handle: brandSettings && brandSettings.handle || '@lineconic',
      bar_color: brandSettings && brandSettings.line_color || '#FF007F',
      bar_height: brandSettings && brandSettings.line_weight || 25,
      show_bar: showBar,
      show_footer: showFooter,
      show_badge: showBadge,
      show_profile: showProfile,
      show_line: showLine,
      show_signoff: showSignoff,
      radius: mediaRadius,
      video_scale: videoScale,
      start_time: useFullClip ? 0 : clipStartTime,
      end_time: useFullClip ? null : clipEndTime
    };
  }

  function renderDrop() {
    if (!activeDrop) return;
    setRendering(true); setRenderPreview(null);

    var renderData = {
      situation: activeDrop.situation || '',
      puzzle: activeDrop.signoff || '',
      media_url: proxyClipUrl(activeDrop.clip_url) || undefined,
    };
    var renderOpts = buildRenderSettings(['mp4']);

    window.FFmpegRenderer.renderToMP4(renderData, renderOpts, function(pct) {
      // Could display pct in UI — for now the indeterminate bar covers it
    }).then(function(blob) {
      var url = URL.createObjectURL(blob);
      setRenderPreview(url);
      setPreviewTab('render');
      // Auto-download
      var link = document.createElement('a');
      link.href = url;
      link.download = (activeDrop ? activeDrop.id : 'render') + '.mp4';
      link.click();
      if (activeDrop.status === 'scheduled') {
        var updated = Object.assign({}, activeDrop, { status: 'rendered', rendered_at: new Date().toISOString() });
        db.ref('drops/' + activeDrop.id).set(updated).then(function() {
          setActiveDrop(updated);
          showToast('RENDERED');
        });
      } else {
        showToast('RENDERED');
      }
      setRendering(false);
    }).catch(function(e) { setRendering(false); showToast('RENDER FAILED: ' + e.message); });
  }

  function downloadRender() {
    if (!renderPreview) return;
    var link = document.createElement('a');
    link.href = renderPreview;
    link.download = (activeDrop ? activeDrop.id : 'render') + '.mp4';
    link.click();
  }

  // --- AI Generate Situation ---
  function aiGenerateSituation() {
    if (!activeDrop || aiGenerating) return;
    setAiGenerating(true);
    var prompt = (activeDrop.line || '') + ' — ' + (activeDrop.source || '');
    var tp = tasteProfile && tasteProfile.content ? tasteProfile.content : undefined;
    getToken().then(function(token) {
      return aiFetch('/api/ai/generate-cards', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token },
        body: JSON.stringify({ prompt: prompt, count: 1, media_type: activeDrop.medium || undefined, tasteProfile: tp })
      });
    }).then(function(res) {
      return res.json();
    }).then(function(data) {
      var card = data.cards && data.cards[0];
      if (card) {
        if (card._situation || card.situation) updateField('situation', card._situation || card.situation || '');
        if (card._signoff || card.signoff) updateField('signoff', card._signoff || card.signoff || '');
      }
      setAiGenerating(false);
      showToast('AI SITUATION GENERATED');
    }).catch(function(e) { setAiGenerating(false); showToast('AI GENERATE FAILED: ' + formatAiError(e)); });
  }

  // --- AI Quick Score ---
  function aiScoreDrop() {
    if (!activeDrop || aiScoring) return;
    setAiScoring(true); setAiScoreResult(null);
    var card = {
      id: activeDrop.reference_id || activeDrop.id,
      content: { answer: activeDrop.line || '' },
      source: activeDrop.source || '',
      media_type: activeDrop.medium || 'movie'
    };
    getToken().then(function(token) {
      return aiFetch('/api/ai/score-cards', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token },
        body: JSON.stringify({ cards: [card] })
      });
    }).then(function(res) {
      return res.json();
    }).then(function(data) {
      var scores = data.scores && data.scores[0];
      if (scores) setAiScoreResult(scores);
      setAiScoring(false);
    }).catch(function(e) { setAiScoring(false); showToast('AI SCORE FAILED: ' + formatAiError(e)); });
  }

  function applyAiScore() {
    if (!aiScoreResult || !activeDrop) return;
    var refId = activeDrop.reference_id;
    if (!refId) { showToast('NO REFERENCE ID'); return; }
    var updated = cards && cards[refId] ? JSON.parse(JSON.stringify(cards[refId])) : {};
    updated.scores = aiScoreResult.scores;
    db.ref('cards/cards/' + refId).update({ scores: aiScoreResult.scores }).then(function() {
      showToast('SCORES APPLIED TO ' + refId);
    }).catch(function(e) { showToast('APPLY FAILED: ' + e.message); });
  }

  // --- Batch Selection ---
  function toggleSelect(id) { setSelected(function(p) { var n = Object.assign({}, p); if (n[id]) delete n[id]; else n[id] = true; return n; }); }
  function selectAllDrops() { var n = {}; sortedDrops.forEach(function(d) { n[d.id] = true; }); setSelected(n); }
  function clearSelection() { setSelected({}); }
  var selCount = Object.keys(selected).length;

  function bulkSchedule() {
    if (!bulkStartDate || selCount === 0) return;
    var ids = Object.keys(selected).filter(function(id) { return drops && drops[id] && drops[id].status === 'draft'; });
    if (ids.length === 0) { showToast('NO DRAFTS SELECTED'); return; }
    var updates = {};
    var start = new Date(bulkStartDate + 'T00:00:00');
    ids.forEach(function(id, i) {
      var d = new Date(start);
      d.setDate(d.getDate() + i);
      var ds = d.getFullYear() + '-' + String(d.getMonth() + 1).padStart(2, '0') + '-' + String(d.getDate()).padStart(2, '0');
      updates['drops/' + id + '/scheduled_date'] = ds;
      updates['drops/' + id + '/status'] = 'scheduled';
    });
    db.ref().update(updates).then(function() {
      showToast(ids.length + ' DROPS SCHEDULED');
      clearSelection(); setBulkStartDate('');
    }).catch(function(e) { showToast('SCHEDULE FAILED: ' + e.message); });
  }

  function batchRender() {
    var ids = Object.keys(selected).filter(function(id) {
      return drops && drops[id] && (drops[id].status === 'scheduled' || drops[id].status === 'rendered');
    });
    if (ids.length === 0) { showToast('NO SCHEDULED DROPS SELECTED'); return; }
    batchRenderIds(ids);
  }

  function batchRenderIds(ids) {
    setBatchRendering(true); setBatchProgress('0 / ' + ids.length);

    var renderOpts = buildRenderSettings(['mp4']);

    // Pipelined rendering: pre-load next drop's canvas/media while FFmpeg encodes current
    var done = 0;
    var preloadedData = null;

    function preloadDrop(id) {
      var d = drops && drops[id];
      if (!d) return Promise.resolve(null);
      var data = {
        situation: d.situation || '',
        puzzle: d.signoff || '',
        media_url: proxyClipUrl(d.clip_url) || undefined,
      };
      // Pre-fetch media to warm browser cache
      if (data.media_url) {
        return fetch(data.media_url, { mode: 'cors' }).then(function() { return data; }).catch(function() { return data; });
      }
      return Promise.resolve(data);
    }

    function renderNext() {
      if (done >= ids.length) {
        var updates = {};
        var now = new Date().toISOString();
        ids.forEach(function(id) {
          if (drops[id] && drops[id].status === 'scheduled') {
            updates['drops/' + id + '/status'] = 'rendered';
            updates['drops/' + id + '/rendered_at'] = now;
          }
        });
        if (Object.keys(updates).length > 0) {
          db.ref().update(updates).then(function() {
            showToast(ids.length + ' DROPS RENDERED');
          });
        } else {
          showToast(ids.length + ' DROPS RENDERED');
        }
        setBatchRendering(false); setBatchProgress(null); clearSelection();
        return;
      }

      var currentId = ids[done];
      var renderDataPromise = preloadedData ? Promise.resolve(preloadedData) : preloadDrop(currentId);
      preloadedData = null;

      renderDataPromise.then(function(renderData) {
        if (!renderData) {
          renderData = { situation: '', puzzle: '', media_url: undefined };
        }
        setBatchProgress((done + 1) + ' / ' + ids.length);

        // Start preloading next drop while this one renders
        var nextIdx = done + 1;
        if (nextIdx < ids.length) {
          preloadDrop(ids[nextIdx]).then(function(data) { preloadedData = data; });
        }

        return window.FFmpegRenderer.renderToMP4(renderData, renderOpts);
      }).then(function() {
        done++;
        renderNext();
      }).catch(function(e) {
        done++;
        console.warn('Batch render failed for ' + currentId + ':', e.message);
        renderNext();
      });
    }

    // Kick off by preloading first drop, then start rendering
    preloadDrop(ids[0]).then(function(data) {
      preloadedData = data;
      renderNext();
    });
  }

  // --- Bulk Plan (ported from AIBulkPlan) ---
  function selectReferences(allRefs, briefText) {
    var briefLower = briefText.toLowerCase();
    var scored = allRefs.map(function(r) {
      var score = r.lineconic_score || r.scores && r.scores.lineconic_score || 5;
      if (r.category && briefLower.includes(r.category.toLowerCase())) score += 2;
      if (r.source && briefLower.includes(r.source.toLowerCase().split(' ')[0].toLowerCase())) score += 3;
      var tags = r.themes || r.tags || [];
      for (var i = 0; i < tags.length; i++) {
        if (briefLower.includes(tags[i].toLowerCase())) score += 1.5;
      }
      var pp = r.scores && r.scores.performance_potential || 5;
      score += pp * 0.15;
      var cs = crowdScores && crowdScores[r.id];
      if (cs && cs.lastPlayed) {
        var daysSince = (Date.now() - new Date(cs.lastPlayed).getTime()) / 86400000;
        if (daysSince < 30) score -= 4;
      }
      score += Math.random() * 1.5;
      return { ref: r, score: score };
    });
    scored.sort(function(a, b) { return b.score - a.score; });
    return scored.slice(0, 200).map(function(s) { return s.ref; });
  }

  function buildDigest(refs) {
    return refs.map(function(r) {
      var id = r.id || '';
      var answer = r.content && r.content.answer || r.line || '';
      var source = r.source || '';
      var mediaType = r.media_type || '';
      var category = r.category || '';
      var ls = r.lineconic_score || r.scores && r.scores.lineconic_score || '';
      var tags = r.themes || r.tags || [];
      var cs = crowdScores && crowdScores[id];
      var recentTag = cs && cs.lastPlayed && (Date.now() - new Date(cs.lastPlayed).getTime()) / 86400000 < 30 ? ' [RECENTLY USED — avoid]' : '';
      var scoreTag = ls ? ' LS:' + ls : '';
      return '[' + id + '] "' + answer + '" — ' + source + ' (' + mediaType + ') [' + category + ']' + scoreTag + ' tags: ' + tags.join(', ') + recentTag;
    }).join('\n');
  }

  function buildCreatorProfile() {
    if (!bulkCreatorId || !creators || !creators[bulkCreatorId]) return null;
    var cr = creators[bulkCreatorId];
    var cp = 'Creator: ' + cr.name;
    if (cr.handle) cp += ' (' + cr.handle + ')';
    if (cr.platform) cp += ' on ' + cr.platform;
    if (cr.audience_size) cp += '. Audience size: ' + cr.audience_size;
    if (cr.audience_demo) cp += '. Audience demo: ' + cr.audience_demo;
    if (cr.content_style) cp += '. Content style: ' + cr.content_style;
    if (cr.notes) cp += '. Notes: ' + cr.notes;
    // Enrich with performance data
    if (drops) {
      var crDrops = Object.values(drops).filter(function(d) { return d.creator_id === bulkCreatorId; });
      var crRated = crDrops.filter(function(d) { return d.performance; });
      var crFire = crRated.filter(function(d) { return d.performance === 'fire'; });
      var crFlop = crRated.filter(function(d) { return d.performance === 'flop'; });
      if (crRated.length > 0) {
        var crFireRate = Math.round(crFire.length / crRated.length * 100);
        cp += '\nPerformance history: ' + crFire.length + ' fire / ' + crRated.length + ' rated (' + crFireRate + '%).';
        var mediumCounts = {};
        crFire.forEach(function(d) { if (d.medium) mediumCounts[d.medium] = (mediumCounts[d.medium] || 0) + 1; });
        var bestMediums = Object.keys(mediumCounts).sort(function(a, b) { return mediumCounts[b] - mediumCounts[a]; });
        if (bestMediums.length > 0) cp += '\nBest mediums: ' + bestMediums.slice(0, 3).join(', ') + '.';
        var sourceCounts = {};
        crFire.forEach(function(d) { if (d.source) sourceCounts[d.source] = (sourceCounts[d.source] || 0) + 1; });
        var bestSources = Object.keys(sourceCounts).sort(function(a, b) { return sourceCounts[b] - sourceCounts[a]; });
        if (bestSources.length > 0) cp += '\nBest sources: ' + bestSources.slice(0, 3).join(', ') + '.';
        var fireSits = crFire.map(function(d) { return d.situation; }).filter(Boolean).slice(0, 5);
        if (fireSits.length > 0) cp += '\nFire situations: ' + fireSits.map(function(s) { return '"' + s + '"'; }).join(', ') + '.';
        var avoidMediums = {};
        crFlop.forEach(function(d) { if (d.medium) avoidMediums[d.medium] = (avoidMediums[d.medium] || 0) + 1; });
        var avoid = Object.keys(avoidMediums).filter(function(m) { return !mediumCounts[m]; });
        if (avoid.length > 0) cp += '\nAvoid: ' + avoid.join(', ') + ' (low engagement).';
      }
    }
    return cp;
  }

  function bulkGenerate() {
    if (!bulkBrief.trim() || !library) return;
    setBulkLoading(true); setBulkError(null); setBulkPlan(null); setBulkRefineText('');

    var refs = selectReferences(library, bulkBrief);
    var digest = buildDigest(refs);

    var topPerformers = null;
    if (drops) {
      var fireDrops = Object.values(drops).filter(function(d) { return d.performance === 'fire'; });
      if (fireDrops.length > 0) {
        var fireSituations = [];
        var fireSignoffs = [];
        fireDrops.forEach(function(d) {
          if (d.situation && fireSituations.indexOf(d.situation) === -1) fireSituations.push(d.situation);
          if (d.signoff && fireSignoffs.indexOf(d.signoff) === -1) fireSignoffs.push(d.signoff);
        });
        topPerformers = { situations: fireSituations.slice(0, 10), signoffs: fireSignoffs.slice(0, 10) };
      }
    }

    var tp = tasteProfile && tasteProfile.content ? tasteProfile.content : null;
    var creatorProfile = buildCreatorProfile();

    getToken().then(function(token) {
      return aiFetch('/api/ai/bulk-plan', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token },
        body: JSON.stringify({ brief: bulkBrief, count: bulkCount, libraryDigest: digest, totalLibrarySize: library.length, tasteProfile: tp, topPerformers: topPerformers, creatorProfile: creatorProfile })
      }, 60000);
    }).then(function(res) {
      return res.json();
    }).then(function(data) {
      setBulkPlan(data.plan || []);
      setBulkLoading(false);
    }).catch(function(e) { setBulkError(formatAiError(e)); setBulkLoading(false); });
  }

  function bulkRefine() {
    if (!bulkRefineText.trim() || !bulkPlan || !library) return;
    setBulkRefining(true); setBulkError(null);

    var refs = selectReferences(library, bulkRefineText);
    var digest = buildDigest(refs);

    getToken().then(function(token) {
      return aiFetch('/api/ai/bulk-plan', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token },
        body: JSON.stringify({ brief: bulkBrief, count: bulkCount, libraryDigest: digest, totalLibrarySize: library.length, currentPlan: bulkPlan, instruction: bulkRefineText, tasteProfile: tasteProfile && tasteProfile.content ? tasteProfile.content : null, creatorProfile: buildCreatorProfile() })
      }, 60000);
    }).then(function(res) {
      return res.json();
    }).then(function(data) {
      setBulkPlan(data.plan || []);
      setBulkRefineText('');
      setBulkRefining(false);
    }).catch(function(e) { setBulkError(formatAiError(e)); setBulkRefining(false); });
  }

  function bulkPlanItemToCard(item) {
    var answer = item.line || '';
    var id = generateId(answer);
    var code = generateCode(answer);
    return {
      id: id, code: code,
      content: { primary: code.split('.').join('.  ').trim(), secondary: '', answer: answer },
      source: item.source || '', media_type: item.medium || 'movie',
      difficulty: 3, category: 'Evergreen Canon', themes: [], scores: {}, staged: true,
      _situation: item.situation || '', _signoff: item.signoff || ''
    };
  }

  function bulkAcceptItem(item) {
    var card = bulkPlanItemToCard(item);
    db.ref('cards/cards/' + card.id).set(card).then(function() {
      showToast('ACCEPTED: ' + card.id);
      setBulkPlan(function(prev) { return prev.filter(function(p) { return p.line !== item.line; }); });
    }).catch(function(e) { showToast('SAVE FAILED: ' + e.message); });
  }

  function bulkAcceptAll() {
    if (!bulkPlan || bulkPlan.length === 0) return;
    var promises = bulkPlan.map(function(item) {
      var card = bulkPlanItemToCard(item);
      return db.ref('cards/cards/' + card.id).set(card);
    });
    Promise.all(promises).then(function() {
      showToast(bulkPlan.length + ' CARDS STAGED');
      setBulkPlan([]);
    }).catch(function(e) { showToast('BULK SAVE FAILED: ' + e.message); });
  }

  function bulkSendToDrops(andRender) {
    if (!bulkPlan || bulkPlan.length === 0) return;
    var updates = {};
    var createdIds = [];
    var startDate = new Date();
    startDate.setDate(startDate.getDate() + 1);
    bulkPlan.forEach(function(item, idx) {
      var id = 'drop-' + Date.now() + '-' + Math.random().toString(36).substr(2, 6);
      createdIds.push(id);
      var scheduledDate = null;
      var status = 'draft';
      if (bulkAutoSchedule) {
        var d = new Date(startDate);
        d.setDate(d.getDate() + idx);
        scheduledDate = d.toISOString().split('T')[0];
        status = 'scheduled';
      }
      updates['drops/' + id] = {
        id: id, line: item.line || '', source: item.source || '',
        situation: item.situation || '', signoff: item.signoff || '',
        acronym: item.acronym || '', medium: item.medium || 'movie',
        scheduled_date: scheduledDate, status: status,
        created_at: new Date().toISOString(),
        reference_id: generateId(item.line),
        creator_id: bulkCreatorId || null
      };
    });
    var count = bulkPlan.length;
    db.ref().update(updates).then(function() {
      showToast(count + ' DROPS ' + (bulkAutoSchedule ? 'QUEUED' : 'CREATED'));
      setBulkPlan([]);
      if (andRender && bulkAutoSchedule) {
        // Auto-select created drops and trigger batch render
        var sel = {};
        createdIds.forEach(function(id) { sel[id] = true; });
        setSelected(sel);
        // Defer to next tick so drops state has updated from Firebase
        setTimeout(function() { batchRenderIds(createdIds); }, 1500);
      }
    }).catch(function(e) { showToast('SEND TO DROPS FAILED: ' + e.message); });
  }

  function bulkEditItem(item) {
    var id = 'drop-' + Date.now() + '-' + Math.random().toString(36).substr(2, 6);
    setActiveDrop({
      id: id, line: item.line || '', source: item.source || '',
      situation: item.situation || '', signoff: item.signoff || '',
      acronym: item.acronym || '', medium: item.medium || 'movie',
      scheduled_date: null, status: 'draft',
      created_at: new Date().toISOString(),
      reference_id: generateId(item.line), performance: null
    });
    setDeleteConfirm(false);
    setRenderPreview(null);
    setClipResults(null);
    setClipPreviewUrl(null);
    setClipPlaying(false);
    setAiScoreResult(null);
  }

  // Theme backgrounds
  var themeBgs = { 'DARK': '#15202b', 'LIGHT': '#ffffff', 'CINEMA': '#000', 'GLASS': '#000' };
  var themeBg = themeBgs[renderTheme] || '#15202b';
  var themeTextColor = renderTheme === 'LIGHT' ? '#000' : '#fff';
  var themeBarColor = renderTheme === 'LIGHT' ? '#222' : renderTheme === 'CINEMA' ? '#c9a227' : renderTheme === 'GLASS' ? 'rgba(255,255,255,.3)' : 'var(--cyan)';

  // Format aspect ratios
  var formatAspect = renderFormat.includes('4:5') ? '1 / 1.25' : renderFormat.includes('1:1') ? '1 / 1' : '1 / 1.778';

  return (
    <div style={{display:'flex',flexDirection:isMobile?'column':'row',height:'100%',overflow:'hidden'}}>
      {/* LEFT PANEL — Render Settings + Drop Picker */}
      <div style={{width:isMobile?'100%':260,flexShrink:0,borderRight:isMobile?'none':'1px solid var(--border)',display:isMobile&&activeDrop?'none':'flex',flexDirection:'column',overflow:'hidden'}}>
        {/* Render Settings */}
        <div style={{padding:12,borderBottom:'1px solid var(--border)'}}>
          <div style={{fontSize:10,letterSpacing:2,color:'var(--signal)',marginBottom:8,cursor:isMobile?'pointer':'default',display:'flex',justifyContent:'space-between',alignItems:'center'}} onClick={isMobile?function(){setMobileShowSettings(!mobileShowSettings)}:undefined}>
            <span>RENDER SETTINGS</span>
            {isMobile && <span style={{fontSize:12,color:'var(--text-dim)'}}>{mobileShowSettings?'▲':'▼'}</span>}
          </div>
          {(!isMobile || mobileShowSettings) && <div>
          <div style={{marginBottom:8}}>
            <div style={{fontSize:9,color:'var(--text-dim)',marginBottom:4}}>FORMAT</div>
            <select className="A-select" value={renderFormat} onChange={function(e){setRenderFormat(e.target.value)}} style={{fontSize:10,width:'100%'}}>
              <option value="PORTRAIT (4:5)">Portrait (4:5)</option>
              <option value="SQUARE (1:1)">Square (1:1)</option>
              <option value="STORY (9:16)">Story (9:16)</option>
            </select>
          </div>
          <div style={{marginBottom:8}}>
            <div style={{fontSize:9,color:'var(--text-dim)',marginBottom:4}}>THEME</div>
            <select className="A-select" value={renderTheme} onChange={function(e){setRenderTheme(e.target.value)}} style={{fontSize:10,width:'100%'}}>
              <option value="DARK">Dark</option>
              <option value="LIGHT">Light</option>
              <option value="CINEMA">Cinema</option>
              <option value="GLASS">Glass</option>
            </select>
          </div>
          {/* Toggles */}
          <div style={{fontSize:9,color:'var(--text-dim)',marginBottom:4,marginTop:4}}>TOGGLES</div>
          <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:'2px 8px',marginBottom:8}}>
            <label style={{display:'flex',alignItems:'center',gap:4,fontSize:10,color:'var(--text-sec)',cursor:'pointer'}}>
              <input type="checkbox" checked={showProfile} onChange={function(e){setShowProfile(e.target.checked)}} /> Profile
            </label>
            <label style={{display:'flex',alignItems:'center',gap:4,fontSize:10,color:'var(--text-sec)',cursor:'pointer'}}>
              <input type="checkbox" checked={showBadge} onChange={function(e){setShowBadge(e.target.checked)}} /> Badge
            </label>
            <label style={{display:'flex',alignItems:'center',gap:4,fontSize:10,color:'var(--text-sec)',cursor:'pointer'}}>
              <input type="checkbox" checked={showFooter} onChange={function(e){setShowFooter(e.target.checked)}} /> Footer
            </label>
            <label style={{display:'flex',alignItems:'center',gap:4,fontSize:10,color:'var(--text-sec)',cursor:'pointer'}}>
              <input type="checkbox" checked={showBar} onChange={function(e){setShowBar(e.target.checked)}} /> Bar
            </label>
            <label style={{display:'flex',alignItems:'center',gap:4,fontSize:10,color:'var(--text-sec)',cursor:'pointer'}}>
              <input type="checkbox" checked={showLine} onChange={function(e){setShowLine(e.target.checked)}} /> Line
            </label>
            <label style={{display:'flex',alignItems:'center',gap:4,fontSize:10,color:'var(--text-sec)',cursor:'pointer'}}>
              <input type="checkbox" checked={showSignoff} onChange={function(e){setShowSignoff(e.target.checked)}} /> Signoff
            </label>
          </div>

          {/* Media */}
          <div style={{fontSize:9,color:'var(--text-dim)',marginBottom:4}}>MEDIA</div>
          <div style={{marginBottom:4}}>
            <div style={{display:'flex',justifyContent:'space-between',fontSize:9,color:'var(--text-sec)',marginBottom:2}}>
              <span>Radius</span><span>{mediaRadius}</span>
            </div>
            <input type="range" min="0" max="90" value={mediaRadius} onChange={function(e){setMediaRadius(parseInt(e.target.value))}} style={{width:'100%'}} />
          </div>
          <div style={{marginBottom:8}}>
            <div style={{display:'flex',justifyContent:'space-between',fontSize:9,color:'var(--text-sec)',marginBottom:2}}>
              <span>Scale</span><span>{videoScale.toFixed(1)}</span>
            </div>
            <input type="range" min="0.5" max="2.0" step="0.1" value={videoScale} onChange={function(e){setVideoScale(parseFloat(e.target.value))}} style={{width:'100%'}} />
          </div>

          {/* Video timing */}
          {activeDrop && activeDrop.clip_url && (
            <div style={{marginBottom:8}}>
              <div style={{fontSize:9,color:'var(--text-dim)',marginBottom:4}}>VIDEO TIMING</div>
              <label style={{display:'flex',alignItems:'center',gap:6,fontSize:9,color:'var(--text-sec)',marginBottom:4,cursor:'pointer'}}>
                <input type="checkbox" checked={useFullClip} onChange={function(e){setUseFullClip(e.target.checked)}} />
                USE FULL CLIP
              </label>
              {!useFullClip && (
                <div style={{display:'flex',gap:8}}>
                  <div style={{flex:1}}>
                    <div style={{fontSize:8,color:'var(--text-dim)',marginBottom:2}}>START (s)</div>
                    <input className="A-input" type="number" min="0" value={clipStartTime} onChange={function(e){setClipStartTime(parseInt(e.target.value)||0)}} style={{fontSize:10,padding:'4px 6px'}} />
                  </div>
                  <div style={{flex:1}}>
                    <div style={{fontSize:8,color:'var(--text-dim)',marginBottom:2}}>END (s)</div>
                    <input className="A-input" type="number" min="1" value={clipEndTime} onChange={function(e){setClipEndTime(parseInt(e.target.value)||15)}} style={{fontSize:10,padding:'4px 6px'}} />
                  </div>
                </div>
              )}
            </div>
          )}

          {rendering ? (
            <div style={{width:'100%',marginBottom:4}}>
              <div style={{fontSize:9,color:'var(--signal)',marginBottom:4,textAlign:'center'}}>RENDERING...</div>
              <div style={{width:'100%',height:4,background:'var(--border)',borderRadius:2,overflow:'hidden'}}>
                <div style={{width:'40%',height:'100%',background:'var(--signal)',borderRadius:2,animation:'render-progress 1.2s ease-in-out infinite'}}></div>
              </div>
            </div>
          ) : (
            <button className="A-btn signal" style={{width:'100%',marginBottom:4}} onClick={renderDrop} disabled={!activeDrop}>RENDER</button>
          )}
          {renderPreview && (
            <button className="A-btn cyan" style={{width:'100%'}} onClick={downloadRender}>DOWNLOAD</button>
          )}
          </div>}
        </div>

        {/* Drop Picker */}
        <div style={{padding:'8px 12px',borderBottom:'1px solid var(--border)'}}>
          <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:6}}>
            <span style={{fontSize:10,letterSpacing:2,color:'var(--signal)'}}>DROPS ({sortedDrops.length})</span>
            <button className="A-btn cyan" style={{fontSize:9,padding:'3px 8px'}} onClick={newDrop}>+ NEW</button>
          </div>
          <input className="A-input" placeholder="Search drops..." value={dropPickerSearch} onChange={function(e){setDropPickerSearch(e.target.value)}} style={{fontSize:11,marginBottom:6}} />
          <div style={{display:'flex',gap:6,fontSize:9}}>
            <span style={{cursor:'pointer',color:'var(--cyan)',letterSpacing:1}} onClick={selectAllDrops}>SELECT ALL</span>
            <span style={{cursor:'pointer',color:'var(--text-dim)',letterSpacing:1}} onClick={clearSelection}>CLEAR</span>
          </div>
        </div>

        {/* Bulk actions bar */}
        {selCount > 0 && (
          <div style={{padding:'8px 12px',borderBottom:'1px solid var(--border)',background:'rgba(255,0,127,.05)'}}>
            <div style={{fontSize:9,color:'var(--signal)',letterSpacing:1,marginBottom:6}}>{selCount} SELECTED</div>
            <div style={{display:'flex',gap:6,alignItems:'center',marginBottom:6}}>
              <input type="date" className="A-input" style={{fontSize:10,padding:'4px 6px',flex:1}} value={bulkStartDate} onChange={function(e){setBulkStartDate(e.target.value)}} />
              <button className="A-btn gold" style={{fontSize:9,padding:'4px 8px',whiteSpace:'nowrap'}} onClick={bulkSchedule} disabled={!bulkStartDate}>SCHEDULE</button>
            </div>
            <button className="A-btn signal" style={{fontSize:9,padding:'4px 8px',width:'100%'}} onClick={batchRender} disabled={batchRendering}>
              {batchRendering ? 'RENDERING ' + (batchProgress || '...') : 'BATCH RENDER'}
            </button>
          </div>
        )}

        <div style={{flex:1,overflow:'auto'}}>
          {sortedDrops.map(function(d) {
            var isActive = activeDrop && activeDrop.id === d.id;
            var sel = selected[d.id];
            var ps = getPillStyle(d);
            return (
              <div key={d.id} style={{
                display:'flex',alignItems:'center',gap:8,padding:'8px 12px',borderBottom:'1px solid #1a1a1a',cursor:'pointer',
                background:isActive ? 'rgba(0,255,255,.05)' : sel ? 'rgba(255,0,127,.03)' : 'transparent'
              }}>
                <div onClick={function(e){e.stopPropagation();toggleSelect(d.id)}} style={{width:16,height:16,border:'1px solid '+(sel?'var(--signal)':'var(--border)'),background:sel?'var(--signal)':'transparent',flexShrink:0,cursor:'pointer'}}></div>
                <div onClick={function(){loadDrop(d)}} style={{flex:1,minWidth:0}}>
                  <div style={{fontSize:11,color:'#e0e0e0',whiteSpace:'nowrap',overflow:'hidden',textOverflow:'ellipsis'}}>"{d.line || '—'}"</div>
                  <div style={{fontSize:9,color:'#888',whiteSpace:'nowrap',overflow:'hidden',textOverflow:'ellipsis'}}>{d.source || ''} {d.medium ? '· ' + d.medium : ''}</div>
                </div>
                <div style={{display:'flex',alignItems:'center',gap:4,flexShrink:0}}>
                  {d.clip_url && <div style={{width:5,height:5,borderRadius:'50%',background:'var(--cyan)'}} title="Has clip"></div>}
                  <span style={{fontSize:8,padding:'2px 6px',background:ps.bg,color:ps.color,border:'1px solid '+ps.border,letterSpacing:'.5px'}}>{d.status}</span>
                </div>
              </div>
            );
          })}
          {sortedDrops.length === 0 && <div style={{padding:24,textAlign:'center',color:'var(--text-dim)',fontSize:11}}>No drops found</div>}
        </div>
      </div>

      {/* CENTER PANEL — Drop Editor + Clip Search */}
      <div style={isMobile ? (activeDrop ? {position:'fixed',inset:0,zIndex:200,background:'#000',display:'flex',flexDirection:'column',overflow:'hidden'} : {display:'none'}) : {flex:1,display:'flex',flexDirection:'column',overflow:'hidden',minWidth:0}}>
        {activeDrop ? (
          <React.Fragment>
            <div style={{flex:1,overflow:'auto',padding:16}}>
              {isMobile && <button className="A-btn" style={{marginBottom:12}} onClick={function(){setActiveDrop(null)}}>← BACK</button>}
              <div style={{maxWidth:600}}>
                <div style={{marginBottom:12}}><label className="A-label">Line</label><input className="A-input" value={activeDrop.line||''} onChange={function(e){updateField('line',e.target.value)}} /></div>
                <div style={{marginBottom:12}}><label className="A-label">Source</label><input className="A-input" value={activeDrop.source||''} onChange={function(e){updateField('source',e.target.value)}} /></div>
                <div style={{marginBottom:12}}>
                  <div style={{display:'flex',justifyContent:'space-between',alignItems:'center'}}><label className="A-label">Situation</label>
                    <button className="A-btn gold" style={{fontSize:9,padding:'3px 8px'}} onClick={aiGenerateSituation} disabled={aiGenerating || !activeDrop.line}>{aiGenerating ? 'GENERATING...' : 'GENERATE'}</button>
                  </div>
                  <textarea className="A-textarea" rows="3" value={activeDrop.situation||''} onChange={function(e){updateField('situation',e.target.value)}} />
                </div>
                <div style={{marginBottom:12}}><label className="A-label">Signoff</label><input className="A-input" value={activeDrop.signoff||''} onChange={function(e){updateField('signoff',e.target.value)}} /></div>
                <div style={{marginBottom:12}}><label className="A-label">Acronym</label><input className="A-input" value={activeDrop.acronym||''} onChange={function(e){updateField('acronym',e.target.value)}} /></div>
                <div style={{marginBottom:12}}><label className="A-label">Medium</label>
                  <select className="A-select" value={activeDrop.medium||'movie'} onChange={function(e){updateField('medium',e.target.value)}}>
                    {['movie','music','tv','internet','ad','meme','cliche'].map(function(mt){return <option key={mt} value={mt}>{mt}</option>})}
                  </select>
                </div>

                {/* Creator assignment */}
                {props.creators && (
                  <div style={{marginBottom:12}}><label className="A-label">Creator</label>
                    <select className="A-select" value={activeDrop.creator_id||''} onChange={function(e){updateField('creator_id',e.target.value||null)}}>
                      <option value="">None</option>
                      {Object.values(props.creators).map(function(c){return <option key={c.id} value={c.id}>{c.name}{c.handle ? ' ('+c.handle+')' : ''}</option>})}
                    </select>
                  </div>
                )}

                {/* Media attachment */}
                <div style={{marginBottom:12}}>
                  <label className="A-label">Media</label>
                  {activeDrop.clip_url ? (
                    <div>
                      <div style={{display:'flex',gap:8,alignItems:'center',padding:8,border:'1px solid var(--border)',background:'var(--surface-2)',marginBottom:8}}>
                        {activeDrop.clip_thumbnail ? (
                          <img src={activeDrop.clip_thumbnail} onError={function(e){e.target.style.display='none'}} style={{width:60,height:40,objectFit:'cover',border:'1px solid var(--border)'}} />
                        ) : (
                          <div style={{width:60,height:40,display:'flex',alignItems:'center',justifyContent:'center',border:'1px solid var(--border)',background:'var(--surface)',fontSize:16,color:'var(--text-dim)'}}>&#9654;</div>
                        )}
                        <div style={{flex:1,minWidth:0}}>
                          <div style={{fontSize:10,color:'#fff',whiteSpace:'nowrap',overflow:'hidden',textOverflow:'ellipsis'}}>{activeDrop.clip_title || 'Media attached'}</div>
                          <div style={{fontSize:9,color:'var(--text-dim)',whiteSpace:'nowrap',overflow:'hidden',textOverflow:'ellipsis'}}>{activeDrop.clip_url}</div>
                        </div>
                        <div style={{display:'flex',gap:4,flexShrink:0}}>
                          <button className="A-btn" style={{fontSize:9,padding:'3px 8px'}} onClick={function(){setClipPlaying(!clipPlaying)}}>{clipPlaying ? 'HIDE' : 'PLAY'}</button>
                          {['movie','tv','music'].includes(activeDrop.medium) && (
                            <button className="A-btn gold" style={{fontSize:9,padding:'3px 8px'}} onClick={function(){removeClip();searchClips()}}>REPLACE</button>
                          )}
                          <button className="A-btn danger" style={{fontSize:9,padding:'3px 8px'}} onClick={removeClip}>REMOVE</button>
                        </div>
                      </div>
                      {clipPlaying && (
                        <div style={{marginBottom:8}}>
                          <video src={proxyClipUrl(activeDrop.clip_url)} crossOrigin="anonymous" controls style={{width:'100%',maxHeight:300,background:'#000',border:'1px solid var(--border)'}} />
                        </div>
                      )}
                    </div>
                  ) : (
                    <div>
                      <div style={{display:'flex',gap:6,marginBottom:6}}>
                        {['movie','tv','music'].includes(activeDrop.medium) && (
                          <button className="A-btn gold" style={{fontSize:9,padding:'4px 10px'}} onClick={searchClips} disabled={clipSearching}>
                            {clipSearching ? 'SEARCHING...' : 'FIND CLIP'}
                          </button>
                        )}
                        <input type="file" id="media-upload-studio" accept="image/*,video/*" style={{display:'none'}} onChange={handleMediaUpload} />
                        <button className="A-btn" style={{fontSize:9,padding:'4px 10px'}} onClick={function(){document.getElementById('media-upload-studio').click()}} disabled={mediaUploading}>
                          {mediaUploading ? 'UPLOADING ' + mediaUploadProgress + '%' : 'UPLOAD'}
                        </button>
                      </div>
                      {['movie','tv','music'].includes(activeDrop.medium) && (
                        <div style={{display:'flex',gap:4,marginBottom:6}}>
                          <input className="A-input" placeholder="Custom search..." value={clipSearchQuery} onChange={function(e){setClipSearchQuery(e.target.value)}} style={{fontSize:10,flex:1}} onKeyDown={function(e){if(e.key==='Enter')searchClipsCustom()}} />
                          <button className="A-btn" style={{fontSize:9,padding:'4px 8px'}} onClick={searchClipsCustom} disabled={clipSearching || !clipSearchQuery.trim()}>GO</button>
                        </div>
                      )}
                      {clipResults && clipResults.length === 0 && (
                        <div style={{fontSize:10,color:'var(--text-dim)',padding:'8px 0'}}>No clips found</div>
                      )}
                      {clipResults && clipResults.length > 0 && (
                        <div>
                          <div style={{display:'flex',gap:8,overflowX:'auto',paddingTop:8,paddingBottom:4}}>
                            {clipResults.map(function(clip, idx) {
                              return (
                                <div key={idx} onClick={function(){setClipPreviewUrl(clip.videoUrl)}} style={{
                                  flexShrink:0,width:100,cursor:'pointer',border:'1px solid ' + (clipPreviewUrl === clip.videoUrl ? 'var(--cyan)' : 'var(--border)'),background:'var(--surface-2)',padding:4
                                }}>
                                  <img src={clip.thumbnailUrl} onError={function(e){e.target.style.display='none'}} style={{width:'100%',height:56,objectFit:'cover',marginBottom:4}} />
                                  <div style={{fontSize:8,color:'#fff',whiteSpace:'nowrap',overflow:'hidden',textOverflow:'ellipsis'}}>{clip.title}</div>
                                  <div style={{fontSize:8,color:'var(--text-dim)'}}>{clip.year} {clip.duration ? '· ' + clip.duration : ''}</div>
                                </div>
                              );
                            })}
                          </div>
                          {clipPreviewUrl && (
                            <div style={{marginTop:8}}>
                              <video src={clipPreviewUrl} crossOrigin="anonymous" controls autoPlay style={{width:'100%',maxHeight:300,background:'#000',border:'1px solid var(--border)'}} />
                              <button className="A-btn signal" style={{width:'100%',marginTop:4}} onClick={function(){
                                var clip = clipResults.find(function(c){return c.videoUrl === clipPreviewUrl});
                                if (clip) selectClip(clip);
                              }}>SELECT</button>
                            </div>
                          )}
                        </div>
                      )}
                    </div>
                  )}
                </div>

                <div style={{display:'flex',gap:12,marginBottom:12}}>
                  <div style={{flex:1}}><label className="A-label">Scheduled Date</label><input className="A-input" type="date" value={activeDrop.scheduled_date||''} onChange={function(e){updateField('scheduled_date',e.target.value||null)}} /></div>
                  <div style={{flex:1}}><label className="A-label">Status</label>
                    <select className="A-select" value={activeDrop.status||'draft'} onChange={function(e){updateField('status',e.target.value)}}>
                      <option value="draft">Draft</option>
                      <option value="scheduled">Scheduled</option>
                      <option value="rendered">Rendered</option>
                      <option value="published">Published</option>
                    </select>
                  </div>
                </div>

                {/* Performance tags — only for published */}
                {activeDrop.status === 'published' && (
                  <div style={{marginBottom:12}}>
                    <label className="A-label">Performance</label>
                    <div style={{display:'flex',gap:8}}>
                      {[
                        {val:'fire',label:'FIRE',color:'#4ade80'},
                        {val:'mid',label:'MID',color:'#9ca3af'},
                        {val:'flop',label:'FLOP',color:'#ef4444'}
                      ].map(function(p) {
                        var active = activeDrop.performance === p.val;
                        return (
                          <button key={p.val} style={{
                            padding:'6px 16px',fontSize:10,letterSpacing:1,cursor:'pointer',
                            background:active ? p.color : 'transparent',
                            color:active ? '#000' : p.color,
                            border:'1px solid ' + p.color,
                            fontWeight:active ? 700 : 400
                          }} onClick={function(){updateField('performance', active ? null : p.val)}}>
                            {p.label}
                          </button>
                        );
                      })}
                    </div>
                  </div>
                )}

                {/* AI Quick Score */}
                {(activeDrop.reference_id || activeDrop.line) && (
                  <div style={{marginBottom:12,padding:12,border:'1px solid var(--border)',background:'var(--surface-2)'}}>
                    <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:8}}>
                      <span style={{fontSize:10,letterSpacing:1,color:'var(--text-dim)'}}>AI SCORE</span>
                      <button className="A-btn signal" style={{fontSize:9,padding:'3px 8px'}} onClick={aiScoreDrop} disabled={aiScoring}>{aiScoring ? 'SCORING...' : 'AI SCORE'}</button>
                    </div>
                    {aiScoreResult && (
                      <div>
                        {SCORE_FIELDS && SCORE_FIELDS.map(function(sf) {
                          var val = aiScoreResult.scores && aiScoreResult.scores[sf] || 0;
                          return <div key={sf} style={{display:'flex',justifyContent:'space-between',padding:'2px 0',fontSize:10}}>
                            <span style={{color:'var(--text-dim)',textTransform:'uppercase',fontSize:9}}>{sf.replace(/_/g,' ')}</span>
                            <span style={{color:'var(--cyan)'}}>{val}</span>
                          </div>;
                        })}
                        <div style={{display:'flex',justifyContent:'space-between',padding:'4px 0',borderTop:'1px solid var(--border)',marginTop:4}}>
                          <span style={{fontSize:10,fontWeight:700}}>LINECONIC SCORE</span>
                          <span style={{fontWeight:700,color:'var(--gold)'}}>{aiScoreResult.scores && aiScoreResult.scores.lineconic_score || 0}</span>
                        </div>
                        {activeDrop.reference_id && (
                          <button className="A-btn gold" style={{width:'100%',marginTop:8,fontSize:9}} onClick={applyAiScore}>APPLY TO {activeDrop.reference_id}</button>
                        )}
                      </div>
                    )}
                  </div>
                )}

                {/* Inline preview on mobile */}
                {isMobile && activeDrop && (
                  <div style={{marginTop:16}}>
                    <div style={{fontSize:10,letterSpacing:2,color:'var(--signal)',marginBottom:8}}>PREVIEW</div>
                    <div style={{
                      width:'100%',maxWidth:340,aspectRatio:formatAspect,background:brandSettings && brandSettings.card_bg || themeBg,border:'1px solid var(--border)',
                      display:'flex',flexDirection:'column',overflow:'hidden',position:'relative'
                    }}>
                      {showProfile && (
                        <div style={{padding:'10px 12px',display:'flex',alignItems:'center',gap:8}}>
                          {brandSettings && brandSettings.profile_pic_url
                            ? <img src={brandSettings.profile_pic_url} style={{width:28,height:28,borderRadius:'50%',objectFit:'cover',border:'1px solid #555'}} />
                            : <div style={{width:28,height:28,borderRadius:'50%',background:'#333',border:'1px solid #555'}}></div>
                          }
                          <div>
                            <div style={{fontSize:10,fontWeight:700,color:themeTextColor,lineHeight:1.2}}>
                              {brandSettings && brandSettings.display_name || 'lineconic'}
                              {showBadge && <span style={{marginLeft:4,color:'#1DA1F2',fontSize:8}}>&#10003;</span>}
                            </div>
                            <div style={{fontSize:8,color:renderTheme==='LIGHT'?'#666':'#888'}}>{brandSettings && brandSettings.handle || '@lineconic'}</div>
                          </div>
                        </div>
                      )}
                      <div style={{padding:'4px 12px',fontSize:10,color:themeTextColor,lineHeight:1.5,flex:'0 0 auto'}}>
                        {activeDrop.situation ? activeDrop.situation : <span style={{color:renderTheme==='LIGHT'?'#ccc':'#444'}}>Situation text...</span>}
                      </div>
                      <div style={{flex:1,display:'flex',alignItems:'center',justifyContent:'center',overflow:'hidden',minHeight:0,margin:'0 12px',borderRadius:mediaRadius * (340/1080)}}>
                        {activeDrop.clip_url ? (
                          <video src={proxyClipUrl(activeDrop.clip_url)} crossOrigin="anonymous" muted autoPlay loop playsInline style={{width:'100%',height:'100%',objectFit:'cover'}} />
                        ) : (
                          <div style={{fontSize:11,color:renderTheme==='LIGHT'?'#ccc':'#444',textTransform:'uppercase',letterSpacing:2}}>
                            {activeDrop.medium ? activeDrop.medium : 'MEDIA'}
                          </div>
                        )}
                      </div>
                      {showBar && (
                        <div style={{height:brandSettings && brandSettings.line_weight || 4,background:brandSettings && brandSettings.line_color || themeBarColor,flexShrink:0,marginTop:4}}></div>
                      )}
                      {showFooter && (
                        <div style={{padding:'8px 12px',textAlign:'center'}}>
                          <div style={{fontSize:9,letterSpacing:2,color:themeTextColor,opacity:.7}}>
                            {showSignoff ? (activeDrop.signoff || 'signoff...') : ''}
                          </div>
                        </div>
                      )}
                    </div>
                    {renderPreview && (
                      <div style={{marginTop:12}}>
                        <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:4}}>
                          <div style={{fontSize:9,letterSpacing:1,color:'var(--text-dim)'}}>RENDER OUTPUT</div>
                          <button onClick={function(){setRenderPreview(null);}} style={{background:'none',border:'none',color:'var(--text-dim)',cursor:'pointer',fontSize:14,lineHeight:1,padding:'0 2px'}} title="Close">&times;</button>
                        </div>
                        <video src={renderPreview} controls muted style={{width:'100%',border:'1px solid var(--border)'}} />
                      </div>
                    )}
                  </div>
                )}
              </div>
            </div>

            {/* Action bar */}
            <div style={{display:'flex',gap:8,padding:'12px 16px',borderTop:'1px solid var(--border)',flexShrink:0,background:'var(--surface)',flexWrap:isMobile?'wrap':'nowrap'}}>
              <button className="A-btn cyan" style={{flex:1}} onClick={saveDrop} disabled={saving}>{saving ? 'SAVING...' : 'SAVE'}</button>
              {rendering ? (
                <div style={{flex:1,maxWidth:120}}>
                  <div style={{width:'100%',height:4,background:'var(--border)',borderRadius:2,overflow:'hidden'}}>
                    <div style={{width:'40%',height:'100%',background:'var(--signal)',borderRadius:2,animation:'render-progress 1.2s ease-in-out infinite'}}></div>
                  </div>
                </div>
              ) : (
                <button className="A-btn signal" onClick={renderDrop} style={{fontSize:10}}>RENDER</button>
              )}
              {renderPreview && <button className="A-btn gold" onClick={downloadRender} style={{fontSize:10}}>EXPORT</button>}
              <button className="A-btn" onClick={copyToClipboard} style={{fontSize:10}}>COPY</button>
              {deleteConfirm
                ? <React.Fragment><button className="A-btn danger" onClick={deleteDrop}>CONFIRM</button><button className="A-btn" onClick={function(){setDeleteConfirm(false)}}>CANCEL</button></React.Fragment>
                : <button className="A-btn danger" onClick={function(){setDeleteConfirm(true)}}>DELETE</button>
              }
            </div>
          </React.Fragment>
        ) : (
          <div style={{flex:1,overflow:'auto',padding:16}}>
            <div style={{maxWidth:700}}>
              <div className="A-section-head">BULK PLAN</div>
              <div style={{fontSize:10,color:'var(--text-dim)',marginBottom:16,letterSpacing:.5}}>Library-aware generation — contentlab engine</div>

              <div style={{marginBottom:16}}>
                <label className="A-label">Creative Brief</label>
                <textarea className="A-textarea" rows="3" value={bulkBrief} onChange={function(e){setBulkBrief(e.target.value)}} placeholder="e.g., '90s film nostalgia — iconic movie quotes millennials quote daily'" />
              </div>
              <div style={{display:'flex',gap:12,marginBottom:16,alignItems:'end',flexWrap:'wrap'}}>
                <div><label className="A-label">Count</label><input className="A-input" type="number" min="5" max="30" value={bulkCount} onChange={function(e){setBulkCount(parseInt(e.target.value)||15)}} style={{width:60}} /></div>
                {creators && Object.keys(creators).length > 0 && (
                  <div><label className="A-label">Creator</label>
                    <select className="A-select" value={bulkCreatorId} onChange={function(e){setBulkCreatorId(e.target.value)}} style={{width:160,fontSize:10}}>
                      <option value="">None</option>
                      {Object.values(creators).map(function(c){return <option key={c.id} value={c.id}>{c.name}{c.handle ? ' ('+c.handle+')' : ''}</option>})}
                    </select>
                  </div>
                )}
                <button className="A-btn signal" onClick={bulkGenerate} disabled={bulkLoading || !bulkBrief.trim() || !library}>{bulkLoading ? 'GENERATING...' : 'GENERATE'}</button>
                {!library && <span style={{fontSize:10,color:'var(--text-dim)'}}>Loading library...</span>}
              </div>

              {bulkError && <div style={{color:'var(--signal)',fontSize:11,marginBottom:16}}>Error: {bulkError}</div>}

              {bulkPlan && bulkPlan.length === 0 && <div style={{color:'var(--text-dim)',padding:24}}>No items generated. Try a different brief.</div>}

              {bulkPlan && bulkPlan.length > 0 && (
                <div>
                  <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:12,flexWrap:'wrap',gap:8}}>
                    <div style={{display:'flex',alignItems:'center',gap:12}}>
                      <span style={{fontSize:11,color:'var(--text-sec)'}}>{bulkPlan.length} items</span>
                      <label style={{display:'flex',alignItems:'center',gap:4,fontSize:10,color:'var(--text-sec)',cursor:'pointer'}}>
                        <input type="checkbox" checked={bulkAutoSchedule} onChange={function(e){setBulkAutoSchedule(e.target.checked)}} /> AUTO-SCHEDULE
                      </label>
                    </div>
                    <div style={{display:'flex',gap:8}}>
                      <button className="A-btn gold" onClick={bulkAcceptAll}>ACCEPT ALL</button>
                      <button className="A-btn cyan" onClick={function(){bulkSendToDrops(false)}}>SEND TO DROPS</button>
                      <button className="A-btn signal" onClick={function(){bulkSendToDrops(true)}} disabled={batchRendering}>QUEUE ALL + RENDER</button>
                    </div>
                  </div>

                  {bulkPlan.map(function(item, idx) {
                    var exists = cards && generateId && cards[generateId(item.line)];
                    return (
                      <div key={idx} className="AI-card-preview">
                        <div style={{display:'flex',justifyContent:'space-between',alignItems:'flex-start',marginBottom:8}}>
                          <div style={{flex:1}}>
                            <div style={{fontSize:13,color:'#fff',marginBottom:4}}>"{item.line}"</div>
                            <div style={{fontSize:11,color:'var(--text-sec)',marginBottom:4}}>{item.source} — {item.medium}</div>
                          </div>
                          <div style={{display:'flex',gap:8,flexShrink:0}}>
                            {exists && <span style={{fontSize:9,color:'var(--gold)',letterSpacing:1}}>EXISTS</span>}
                            <button className="A-btn" onClick={function(){bulkEditItem(item)}} style={{fontSize:10,padding:'4px 10px'}}>EDIT</button>
                            <button className="A-btn cyan" onClick={function(){bulkAcceptItem(item)}} disabled={exists} style={{fontSize:10,padding:'4px 10px'}}>ACCEPT</button>
                          </div>
                        </div>
                        <div style={{fontSize:11,color:'var(--cyan)',marginBottom:4}}>{item.situation}</div>
                        <div style={{display:'flex',gap:16,fontSize:10,color:'var(--text-dim)'}}>
                          <span>signoff: "{item.signoff}"</span>
                          <span>acronym: {item.acronym}</span>
                        </div>
                      </div>
                    );
                  })}

                  {/* Refinement */}
                  <div style={{marginTop:24,padding:16,border:'1px solid var(--border)',background:'var(--surface-2)'}}>
                    <label className="A-label">Refine Plan</label>
                    <textarea className="A-textarea" rows="2" value={bulkRefineText} onChange={function(e){setBulkRefineText(e.target.value)}} placeholder="e.g., 'swap out rom-com references for action movies'" />
                    <button className="A-btn signal" onClick={bulkRefine} disabled={bulkRefining || !bulkRefineText.trim()} style={{marginTop:8}}>{bulkRefining ? 'REFINING...' : 'REFINE'}</button>
                  </div>
                </div>
              )}
            </div>
          </div>
        )}
      </div>

      {/* RIGHT PANEL — Live Preview Card */}
      <div style={{width:380,flexShrink:0,borderLeft:'1px solid var(--border)',overflow:'auto',padding:16,display:isMobile?'none':'flex',flexDirection:'column',alignItems:'center'}}>
        {/* Tab bar */}
        <div style={{display:'flex',gap:16,alignSelf:'flex-start',marginBottom:12}}>
          <div
            onClick={function(){setPreviewTab('live')}}
            style={{fontSize:10,letterSpacing:2,cursor:'pointer',paddingBottom:4,
              color:previewTab==='live'?'var(--signal)':'var(--text-dim)',
              borderBottom:previewTab==='live'?'2px solid var(--signal)':'2px solid transparent'
            }}
          >LIVE PREVIEW</div>
          {renderPreview && (
            <div style={{display:'flex',alignItems:'center',gap:4}}>
              <div
                onClick={function(){setPreviewTab('render')}}
                style={{fontSize:10,letterSpacing:2,cursor:'pointer',paddingBottom:4,
                  color:previewTab==='render'?'var(--signal)':'var(--text-dim)',
                  borderBottom:previewTab==='render'?'2px solid var(--signal)':'2px solid transparent'
                }}
              >RENDER OUTPUT</div>
              <div
                onClick={function(){setRenderPreview(null);setPreviewTab('live')}}
                style={{fontSize:10,cursor:'pointer',color:'var(--text-dim)',marginLeft:2,lineHeight:1}}
                title="Close render output"
              >×</div>
            </div>
          )}
        </div>

        {/* Tab content */}
        {previewTab === 'live' && (<>
          {/* Card mockup */}
          <div style={{
            width:'100%',maxWidth:340,aspectRatio:formatAspect,background:brandSettings && brandSettings.card_bg || themeBg,border:'1px solid var(--border)',
            display:'flex',flexDirection:'column',overflow:'hidden',position:'relative'
          }}>
            {/* Profile row */}
            {showProfile && (
              <div style={{padding:'10px 12px',display:'flex',alignItems:'center',gap:8}}>
                {brandSettings && brandSettings.profile_pic_url
                  ? <img src={brandSettings.profile_pic_url} style={{width:28,height:28,borderRadius:'50%',objectFit:'cover',border:'1px solid #555'}} />
                  : <div style={{width:28,height:28,borderRadius:'50%',background:'#333',border:'1px solid #555'}}></div>
                }
                <div>
                  <div style={{fontSize:10,fontWeight:700,color:themeTextColor,lineHeight:1.2}}>
                    {brandSettings && brandSettings.display_name || 'lineconic'}
                    {showBadge && <span style={{marginLeft:4,color:'#1DA1F2',fontSize:8}}>&#10003;</span>}
                  </div>
                  <div style={{fontSize:8,color:renderTheme==='LIGHT'?'#666':'#888'}}>{brandSettings && brandSettings.handle || '@lineconic'}</div>
                </div>
              </div>
            )}

            {/* Situation text */}
            <div style={{padding:'4px 12px',fontSize:10,color:themeTextColor,lineHeight:1.5,flex:'0 0 auto'}}>
              {activeDrop && activeDrop.situation ? activeDrop.situation : <span style={{color:renderTheme==='LIGHT'?'#ccc':'#444'}}>Situation text...</span>}
            </div>

            {/* Media area */}
            <div style={{flex:1,display:'flex',alignItems:'center',justifyContent:'center',overflow:'hidden',minHeight:0,margin:'0 12px',borderRadius:mediaRadius * (340/1080)}}>
              {activeDrop && activeDrop.clip_url ? (
                <video src={proxyClipUrl(activeDrop.clip_url)} crossOrigin="anonymous" muted autoPlay loop playsInline style={{width:'100%',height:'100%',objectFit:'cover'}} />
              ) : (
                <div style={{fontSize:11,color:renderTheme==='LIGHT'?'#ccc':'#444',textTransform:'uppercase',letterSpacing:2}}>
                  {activeDrop && activeDrop.medium ? activeDrop.medium : 'MEDIA'}
                </div>
              )}
            </div>

            {/* Line separator */}
            {showLine && (
              <div style={{height:1,background:'#30363d',flexShrink:0,marginTop:4}}></div>
            )}

            {/* Colored bar */}
            {showBar && (
              <div style={{height:brandSettings && brandSettings.line_weight || 4,background:brandSettings && brandSettings.line_color || themeBarColor,flexShrink:0,marginTop:showLine ? 0 : 4}}></div>
            )}

            {/* Footer */}
            {showFooter && (
              <div style={{padding:'8px 12px',textAlign:'center'}}>
                <div style={{fontSize:9,letterSpacing:2,color:themeTextColor,opacity:.7}}>
{showSignoff ? (activeDrop ? (activeDrop.signoff || 'signoff...') : 'signoff...') : ''}
                </div>
              </div>
            )}

            {/* Bottom padding when no footer and no bar */}
            {!showFooter && !showBar && (
              <div style={{height:8}}></div>
            )}
          </div>

          {/* Caption below card */}
          <div style={{marginTop:8,fontSize:10,color:'var(--text-dim)',textAlign:'center'}}>
            {activeDrop ? (
              <span>"{activeDrop.line || '...'}" — {activeDrop.source || '...'}</span>
            ) : (
              <span>No drop selected</span>
            )}
          </div>
          {activeDrop && (
            <div style={{marginTop:4,fontSize:9,color:'var(--text-dim)',textAlign:'center'}}>
              <span>{activeDrop.status}</span>
              {activeDrop.created_at && <span> · {new Date(activeDrop.created_at).toLocaleDateString()}</span>}
              {activeDrop.rendered_at && <span> · rendered {new Date(activeDrop.rendered_at).toLocaleDateString()}</span>}
            </div>
          )}
        </>)}

        {previewTab === 'render' && renderPreview && (
          <div style={{width:'100%'}}>
            <video src={renderPreview} controls muted autoPlay loop style={{width:'100%',border:'1px solid var(--border)'}} />
          </div>
        )}
      </div>
    </div>
  );
}

// QuickRateView and DropsInsights extracted to insights.jsx
