// ─── Cards Module (migrated from editor.html) ──────────
function CardsModule(props) {
  var cards = props.cards, meta = props.meta, db = props.db, showToast = props.showToast;
  var MEDIA_TYPES = props.MEDIA_TYPES, SCORE_FIELDS = props.SCORE_FIELDS;
  var crowdScores = props.crowdScores;

  var [search, setSearch] = useState('');
  var [filterMedia, setFilterMedia] = useState(null);
  var [filterDifficulty, setFilterDifficulty] = useState(null);
  var [filterStaged, setFilterStaged] = useState(false);
  var [filterReview, setFilterReview] = useState(false);
  var [sortBy, setSortBy] = useState('lineconic_score_desc');
  var [selectedId, setSelectedId] = useState(null);
  var [editCard, setEditCard] = useState(null);
  var [isNew, setIsNew] = useState(false);
  var [saving, setSaving] = useState(false);
  var [publishing, setPublishing] = useState(false);
  var [deleteConfirm, setDeleteConfirm] = useState(false);
  var [seeding, setSeeding] = useState(false);
  var [bulkMode, setBulkMode] = useState(false);
  var [selected, setSelected] = useState({});
  var [bulkDifficulty, setBulkDifficulty] = useState(3);
  var [bulkTheme, setBulkTheme] = useState('');
  var [bulkDeleteConfirm, setBulkDeleteConfirm] = useState(false);

  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 cardArray = useMemo(function() {
    if (!cards) return [];
    return Object.values(cards);
  }, [cards]);

  var filtered = useMemo(function() {
    var arr = cardArray.slice();
    if (search) {
      var q = search.toLowerCase();
      arr = arr.filter(function(c) {
        return (c.content&&c.content.answer||'').toLowerCase().includes(q) ||
          (c.source||'').toLowerCase().includes(q) ||
          (c.id||'').toLowerCase().includes(q) ||
          (c.code||'').toLowerCase().includes(q);
      });
    }
    if (filterMedia) arr = arr.filter(function(c){return c.media_type===filterMedia});
    if (filterDifficulty) arr = arr.filter(function(c){return c.difficulty===filterDifficulty});
    if (filterStaged) arr = arr.filter(function(c){return c.staged === true});
    if (filterReview) arr = arr.filter(function(c){return c.status === 'review'});
    arr.sort(function(a,b) {
      switch(sortBy) {
        case 'lineconic_score_desc': return (b.scores&&b.scores.lineconic_score||0) - (a.scores&&a.scores.lineconic_score||0);
        case 'lineconic_score_asc': return (a.scores&&a.scores.lineconic_score||0) - (b.scores&&b.scores.lineconic_score||0);
        case 'alpha': return (a.content&&a.content.answer||'').localeCompare(b.content&&b.content.answer||'');
        case 'difficulty': return (a.difficulty||0) - (b.difficulty||0);
        case 'crowd_score_desc':
          var csA = crowdScores && crowdScores[a.id] ? crowdScores[a.id].crowd_score : 0;
          var csB = crowdScores && crowdScores[b.id] ? crowdScores[b.id].crowd_score : 0;
          return csB - csA;
        default: return 0;
      }
    });
    return arr;
  }, [cardArray, search, filterMedia, filterDifficulty, filterStaged, filterReview, sortBy]);

  var stats = useMemo(function() {
    var byMedia = {};
    var totalScore = 0, scored = 0, unscored = 0;
    cardArray.forEach(function(c) {
      byMedia[c.media_type] = (byMedia[c.media_type]||0) + 1;
      var ls = c.scores && c.scores.lineconic_score || 0;
      if (ls > 0) { totalScore += ls; scored++; } else { unscored++; }
    });
    var reviewCount = cardArray.filter(function(c){return c.status === 'review'}).length;
    return { total: cardArray.length, byMedia: byMedia, avgScore: scored > 0 ? (totalScore/scored).toFixed(1) : '0', unscored: unscored, reviewCount: reviewCount };
  }, [cardArray]);

  function selectCard(id) {
    setSelectedId(id); setDeleteConfirm(false);
    var c = cards[id];
    if (c) { setEditCard(JSON.parse(JSON.stringify(c))); setIsNew(false); }
  }

  function newCard() {
    setEditCard({
      id:'', code:'', content:{primary:'',secondary:'',answer:''},
      source:'', difficulty:1, category:'', themes:[], media_type:'movie',
      scores:{iconic_status:0,quotability:0,emotional_impact:0,performance_potential:0,visual_cue_power:0,lineconic_score:0}
    });
    setSelectedId(null); setIsNew(true); setDeleteConfirm(false);
  }

  function updateField(path, value) {
    setEditCard(function(prev) {
      var next = JSON.parse(JSON.stringify(prev));
      var parts = path.split('.');
      var obj = next;
      for (var i=0; i<parts.length-1; i++) obj = obj[parts[i]];
      obj[parts[parts.length-1]] = value;
      if (path === 'content.answer') {
        next.code = generateCode(value);
        next.content.primary = generateCode(value).split('.').join('.  ') + '.';
        if (isNew) next.id = generateId(value);
      }
      if (path.startsWith('scores.')) {
        next.scores.lineconic_score = calcLineconicScore(next.scores);
      }
      return next;
    });
  }

  function saveCard() {
    if (!editCard || !editCard.id) return;
    setSaving(true);
    editCard.scores.lineconic_score = calcLineconicScore(editCard.scores);
    if (typeof editCard.themes === 'string') {
      editCard.themes = editCard.themes.split(',').map(function(t){return t.trim()}).filter(Boolean);
    }
    db.ref('cards/cards/' + editCard.id).set(editCard).then(function() {
      return db.ref('cards/cards').once('value');
    }).then(function(snap) {
      return db.ref('cards/meta/total_cards').set(snap.numChildren());
    }).then(function() {
      setSelectedId(editCard.id); setIsNew(false); setSaving(false);
      showToast('CARD SAVED');
    }).catch(function(e) { showToast('SAVE FAILED: ' + e.message); setSaving(false); });
  }

  function deleteCard() {
    if (!editCard || !editCard.id) return;
    db.ref('cards/cards/' + editCard.id).remove().then(function() {
      return db.ref('cards/cards').once('value');
    }).then(function(snap) {
      return db.ref('cards/meta/total_cards').set(snap.numChildren());
    }).then(function() {
      setEditCard(null); setSelectedId(null); setDeleteConfirm(false);
      showToast('CARD DELETED');
    }).catch(function(e) { showToast('DELETE FAILED: ' + e.message); });
  }

  function seedFromJson() {
    setSeeding(true);
    fetch('/card-library.json').then(function(r){return r.json()}).then(function(data) {
      var cardsObj = {};
      (data.cards || []).forEach(function(c){cardsObj[c.id] = c});
      return db.ref('cards').set({meta: data.meta, cards: cardsObj});
    }).then(function() { setSeeding(false); showToast('SEEDED FROM JSON'); })
    .catch(function(e) { showToast('SEED FAILED: ' + e.message); setSeeding(false); });
  }

  function toggleSelect(id) { setSelected(function(p) { var n = Object.assign({}, p); if (n[id]) delete n[id]; else n[id] = true; return n; }); }
  function selectAllFiltered() { var n = {}; filtered.forEach(function(c) { n[c.id] = true; }); setSelected(n); }
  function clearSelection() { setSelected({}); setBulkDeleteConfirm(false); }
  var selCount = Object.keys(selected).length;

  function bulkApproveStaged() {
    var ids = Object.keys(selected).filter(function(id) { return cards[id] && cards[id].staged === true; });
    if (ids.length === 0) { showToast('NO STAGED CARDS SELECTED'); return; }
    var updates = {};
    ids.forEach(function(id) { updates['cards/cards/' + id + '/staged'] = null; });
    db.ref().update(updates).then(function() {
      showToast(ids.length + ' CARDS APPROVED');
      clearSelection();
    }).catch(function(e) { showToast('APPROVE FAILED: ' + e.message); });
  }

  function bulkSetDifficulty() {
    var ids = Object.keys(selected).filter(function(id) { return cards[id]; });
    if (ids.length === 0) return;
    var updates = {};
    ids.forEach(function(id) { updates['cards/cards/' + id + '/difficulty'] = bulkDifficulty; });
    db.ref().update(updates).then(function() {
      showToast(ids.length + ' CARDS → DIFFICULTY ' + bulkDifficulty);
      clearSelection();
    }).catch(function(e) { showToast('UPDATE FAILED: ' + e.message); });
  }

  function bulkSetTheme() {
    if (!bulkTheme.trim()) return;
    var theme = bulkTheme.trim();
    var ids = Object.keys(selected).filter(function(id) { return cards[id]; });
    if (ids.length === 0) return;
    var updates = {};
    ids.forEach(function(id) {
      var existing = cards[id].themes || [];
      if (!Array.isArray(existing)) existing = [];
      if (existing.indexOf(theme) < 0) {
        updates['cards/cards/' + id + '/themes'] = existing.concat([theme]);
      }
    });
    if (Object.keys(updates).length === 0) { showToast('THEME ALREADY SET ON ALL'); return; }
    db.ref().update(updates).then(function() {
      showToast('THEME "' + theme + '" ADDED');
      clearSelection(); setBulkTheme('');
    }).catch(function(e) { showToast('UPDATE FAILED: ' + e.message); });
  }

  function bulkDelete() {
    if (!bulkDeleteConfirm) { setBulkDeleteConfirm(true); return; }
    var ids = Object.keys(selected).filter(function(id) { return cards[id]; });
    if (ids.length === 0) return;
    var updates = {};
    ids.forEach(function(id) { updates['cards/cards/' + id] = null; });
    db.ref().update(updates).then(function() {
      return db.ref('cards/cards').once('value');
    }).then(function(snap) {
      return db.ref('cards/meta/total_cards').set(snap.numChildren());
    }).then(function() {
      showToast(ids.length + ' CARDS DELETED');
      clearSelection();
      setEditCard(null); setSelectedId(null);
    }).catch(function(e) { showToast('DELETE FAILED: ' + e.message); });
  }

  function publishCards() {
    setPublishing(true);
    var cardsArr = Object.values(cards);
    var payload = { meta: Object.assign({}, meta), cards: cardsArr };
    firebase.auth().currentUser.getIdToken().then(function(token) {
      return aiFetch('/api/publish-cards', {
        method:'POST',
        headers:{'Content-Type':'application/json','Authorization':'Bearer ' + token},
        body: JSON.stringify(payload)
      });
    }).then(function(res) {
      return db.ref('cards/meta/last_published').set(new Date().toISOString());
    }).then(function() {
      setPublishing(false); showToast('PUBLISHED TO REPO');
    }).catch(function(e) {
      setPublishing(false); showToast('PUBLISH FAILED: ' + formatAiError(e));
    });
  }

  if (cards === null) return <div className="A-empty"><div className="icon">L</div><div className="msg">LOADING CARDS...</div></div>;

  var isEmpty = Object.keys(cards).length === 0;
  var diffColors = ['','#4ade80','#a3e635','#fbbf24','#f97316','#ef4444'];
  var mediaColors = {movie:'#fbbf24',music:'#a78bfa',tv:'#60a5fa',internet:'#34d399',ad:'#f472b6',meme:'#fb923c',cliche:'#94a3b8'};

  return (
    <div style={{display:'flex',height:'100%',overflow:'hidden'}}>
      {/* Seed overlay */}
      {isEmpty && (
        <div style={{position:'fixed',inset:0,background:'rgba(0,0,0,.85)',display:'flex',alignItems:'center',justifyContent:'center',zIndex:999}}>
          <div style={{background:'#141414',border:'1px solid var(--border)',padding:32,maxWidth:400,textAlign:'center'}}>
            <div style={{fontSize:14,letterSpacing:2,color:'#fff',marginBottom:12}}>DATABASE EMPTY</div>
            <div style={{fontSize:12,color:'#888',marginBottom:20}}>No cards found. Seed from card-library.json?</div>
            <button className="A-btn cyan" onClick={seedFromJson} disabled={seeding}>{seeding ? 'SEEDING...' : 'SEED FROM JSON'}</button>
          </div>
        </div>
      )}

      {/* Left: card list */}
      <div style={{flex:1,display:'flex',flexDirection:'column',overflow:'hidden',minWidth:0}}>
        {/* Toolbar */}
        <div style={{padding:'12px 16px',borderBottom:'1px solid var(--border)',background:'var(--surface)',flexShrink:0}}>
          <div style={{display:'flex',gap:8,marginBottom:8}}>
            <input className="A-input" placeholder="Search cards..." value={search} onChange={function(e){setSearch(e.target.value)}} style={{flex:1,fontSize:12}} />
            <select className="A-select" style={{width:'auto',fontSize:10,letterSpacing:1}} value={sortBy} onChange={function(e){setSortBy(e.target.value)}}>
              <option value="lineconic_score_desc">Score ↓</option>
              <option value="lineconic_score_asc">Score ↑</option>
              <option value="crowd_score_desc">Crowd ↓</option>
              <option value="alpha">A → Z</option>
              <option value="difficulty">Difficulty</option>
            </select>
            <button className="A-btn cyan" onClick={newCard} style={{whiteSpace:'nowrap'}}>+ NEW</button>
            <button className={'A-btn' + (bulkMode ? ' signal' : '')} onClick={function(){setBulkMode(!bulkMode);clearSelection()}} style={{whiteSpace:'nowrap'}}>BULK</button>
          </div>
          <div style={{display:'flex',gap:6,flexWrap:'wrap',alignItems:'center',maxHeight:isMobile?'80px':'none',overflowY:isMobile?'auto':'visible'}}>
            <span style={{fontSize:9,color:'var(--text-dim)',letterSpacing:1,marginRight:4}}>TYPE</span>
            {MEDIA_TYPES.map(function(mt) {
              return <div key={mt} className={'A-chip' + (filterMedia===mt?' on':'')} onClick={function(){setFilterMedia(filterMedia===mt?null:mt)}}>{mt}</div>;
            })}
            <span style={{fontSize:9,color:'var(--text-dim)',letterSpacing:1,marginLeft:8,marginRight:4}}>DIFF</span>
            {[1,2,3,4,5].map(function(d) {
              return <div key={d} className={'A-chip' + (filterDifficulty===d?' on':'')} onClick={function(){setFilterDifficulty(filterDifficulty===d?null:d)}}>{d}</div>;
            })}
            <span style={{fontSize:9,color:'var(--text-dim)',letterSpacing:1,marginLeft:8,marginRight:4}}>STATUS</span>
            <div className={'A-chip' + (filterStaged?' on':'')} onClick={function(){setFilterStaged(!filterStaged)}} style={filterStaged?{borderColor:'var(--gold)',color:'var(--gold)'}:{}}>STAGED</div>
            <div className={'A-chip' + (filterReview?' on':'')} onClick={function(){setFilterReview(!filterReview)}} style={filterReview?{borderColor:'var(--signal)',color:'var(--signal)'}:{}}>REVIEW</div>
            {(filterMedia || filterDifficulty || filterStaged || filterReview) && <div className="A-chip" style={{color:'#ff3333',borderColor:'#ff3333'}} onClick={function(){setFilterMedia(null);setFilterDifficulty(null);setFilterStaged(false);setFilterReview(false)}}>CLEAR</div>}
          </div>
        </div>

        {bulkMode && selCount > 0 && (
          <div style={{padding:'8px 16px',borderBottom:'1px solid var(--border)',background:'rgba(255,0,127,.05)',display:'flex',gap:8,alignItems:'center',flexWrap:'wrap'}}>
            <span style={{fontSize:10,color:'var(--signal)',letterSpacing:1,fontWeight:700}}>{selCount} SELECTED</span>
            <button className="A-btn gold" style={{fontSize:9,padding:'4px 10px'}} onClick={bulkApproveStaged}>APPROVE STAGED</button>
            <select className="A-select" style={{width:60,fontSize:10,padding:'4px 6px'}} value={bulkDifficulty} onChange={function(e){setBulkDifficulty(parseInt(e.target.value))}}>
              {[1,2,3,4,5].map(function(d){return <option key={d} value={d}>{d}</option>})}
            </select>
            <button className="A-btn" style={{fontSize:9,padding:'4px 10px'}} onClick={bulkSetDifficulty}>SET DIFF</button>
            <input className="A-input" style={{width:120,fontSize:10,padding:'4px 8px'}} value={bulkTheme} onChange={function(e){setBulkTheme(e.target.value)}} placeholder="theme..." />
            <button className="A-btn" style={{fontSize:9,padding:'4px 10px'}} onClick={bulkSetTheme} disabled={!bulkTheme.trim()}>SET THEME</button>
            <button className={'A-btn danger'} style={{fontSize:9,padding:'4px 10px'}} onClick={bulkDelete}>{bulkDeleteConfirm ? 'CONFIRM DELETE' : 'DELETE'}</button>
            {bulkDeleteConfirm && <button className="A-btn" style={{fontSize:9,padding:'4px 10px'}} onClick={function(){setBulkDeleteConfirm(false)}}>CANCEL</button>}
            <button className="A-btn" style={{fontSize:9,padding:'4px 10px',marginLeft:'auto'}} onClick={clearSelection}>CLEAR</button>
          </div>
        )}
        {bulkMode && (
          <div style={{padding:'4px 16px',borderBottom:'1px solid #1a1a1a',fontSize:9,color:'var(--text-dim)',letterSpacing:1,display:'flex',gap:8}}>
            <span style={{cursor:'pointer',color:'var(--cyan)'}} onClick={selectAllFiltered}>SELECT ALL ({filtered.length})</span>
            <span style={{cursor:'pointer'}} onClick={clearSelection}>DESELECT ALL</span>
          </div>
        )}

        {/* Count bar */}
        <div style={{padding:'6px 16px',borderBottom:'1px solid #1a1a1a',fontSize:10,color:'var(--text-dim)',letterSpacing:1,display:'flex',justifyContent:'space-between'}}>
          <span>{filtered.length} / {cardArray.length} cards</span>
          <div style={{display:'flex',gap:8}}>
            <button className="A-btn signal" onClick={publishCards} disabled={publishing} style={{fontSize:9,padding:'2px 10px'}}>
              {publishing ? 'PUBLISHING...' : 'PUBLISH TO REPO'}
            </button>
            {meta && meta.last_published && <span style={{fontSize:9,color:'var(--text-dim)'}}>Last: {new Date(meta.last_published).toLocaleDateString()}</span>}
          </div>
        </div>

        {/* Card list */}
        <div style={{flex:1,overflow:'auto'}}>
          {filtered.map(function(c) {
            var sel = selectedId === c.id;
            var cs = crowdScores && crowdScores[c.id];
            var csVal = cs ? cs.crowd_score : null;
            var csColor = csVal === null ? 'var(--text-dim)' : csVal >= 7 ? '#4ade80' : csVal >= 4 ? 'var(--gold)' : 'var(--signal)';
            var isReview = c.status === 'review';
            return (
              <div key={c.id} onClick={function(){selectCard(c.id)}} style={{
                display:'grid',gridTemplateColumns:isMobile ? (bulkMode ? '28px 1fr' : '1fr') : (bulkMode ? '28px 36px 1fr 140px 70px 50px 50px' : '36px 1fr 140px 70px 50px 50px'),alignItems:'center',gap:isMobile?6:8,padding:isMobile?'8px 12px':'8px 16px',
                borderBottom:'1px solid #1a1a1a',cursor:'pointer',
                background:isReview?'rgba(255,0,127,.04)':sel?'rgba(0,255,255,.05)':'transparent',
                borderLeft:isReview?'2px solid var(--signal)':sel?'2px solid var(--cyan)':'2px solid transparent'
              }}>
                {bulkMode && <div onClick={function(e){e.stopPropagation();toggleSelect(c.id)}} style={{width:16,height:16,border:'1px solid '+(selected[c.id]?'var(--cyan)':'var(--border)'),background:selected[c.id]?'var(--cyan)':'transparent',cursor:'pointer',margin:'auto'}}></div>}
                {!isMobile && <div style={{width:24,height:24,display:'flex',alignItems:'center',justifyContent:'center',fontSize:11,fontWeight:700,border:'1px solid '+(diffColors[c.difficulty]||'#333'),color:diffColors[c.difficulty]||'#333'}}>{c.difficulty}</div>}
                <div style={{minWidth:0}}>
                  <div style={{fontSize:13,color:'#e0e0e0',whiteSpace:'nowrap',overflow:'hidden',textOverflow:'ellipsis'}}>
                    {c.content&&c.content.answer||'—'}
                    {c.staged && <span style={{fontSize:8,marginLeft:6,padding:'1px 5px',background:'rgba(251,191,36,.15)',color:'var(--gold)',border:'1px solid var(--gold)',letterSpacing:1,verticalAlign:'middle'}}>STAGED</span>}
                    {isReview && <span style={{fontSize:8,marginLeft:6,padding:'1px 5px',background:'rgba(255,0,127,.15)',color:'var(--signal)',border:'1px solid var(--signal)',letterSpacing:1,verticalAlign:'middle'}}>REVIEW</span>}
                  </div>
                  <div style={{fontSize:11,color:'#888',whiteSpace:'nowrap',overflow:'hidden',textOverflow:'ellipsis'}}>
                    {c.source||''}
                    {isMobile && <React.Fragment>
                      {c.category && <span style={{marginLeft:8,fontSize:9,color:'var(--text-dim)'}}>{c.category}</span>}
                      <span style={{marginLeft:8,fontSize:9,letterSpacing:1,textTransform:'uppercase',padding:'1px 4px',border:'1px solid '+(mediaColors[c.media_type]||'#555'),color:mediaColors[c.media_type]||'#555'}}>{c.media_type||'—'}</span>
                      <span style={{marginLeft:8,fontSize:10,color:'var(--gold)'}}>{c.scores&&c.scores.lineconic_score||'—'}</span>
                      {csVal !== null && <span style={{marginLeft:6,fontSize:9,color:csColor}}>{csVal}</span>}
                    </React.Fragment>}
                  </div>
                </div>
                {!isMobile && <div style={{fontSize:11,color:'#888',whiteSpace:'nowrap',overflow:'hidden',textOverflow:'ellipsis'}}>{c.category||''}</div>}
                {!isMobile && <div style={{fontSize:9,letterSpacing:1,textTransform:'uppercase',padding:'2px 6px',border:'1px solid '+(mediaColors[c.media_type]||'#555'),color:mediaColors[c.media_type]||'#555'}}>{c.media_type||'—'}</div>}
                {!isMobile && <div style={{fontSize:12,color:'var(--gold)',textAlign:'right'}}>{c.scores&&c.scores.lineconic_score||'—'}</div>}
                {!isMobile && <div style={{fontSize:10,color:csColor,textAlign:'right'}}>{csVal !== null ? csVal : '—'}<div style={{fontSize:7,color:'var(--text-dim)',letterSpacing:.5}}>{cs ? cs.showCount+'x' : ''}</div></div>}
              </div>
            );
          })}
          {filtered.length === 0 && !isEmpty && <div style={{padding:40,textAlign:'center',color:'var(--text-dim)',fontSize:12}}>No cards match filters</div>}
        </div>

        {/* Stats bar */}
        <div style={{display:'flex',gap:16,padding:'8px 20px',borderTop:'1px solid var(--border)',fontSize:10,color:'var(--text-dim)',letterSpacing:1,flexShrink:0,flexWrap:'wrap',background:'#000'}}>
          <span>TOTAL: <b style={{color:'#fff'}}>{stats.total}</b></span>
          <span>AVG: <b style={{color:'var(--gold)'}}>{stats.avgScore}</b></span>
          <span>UNSCORED: <b style={{color:stats.unscored>0?'#ff3333':'#4ade80'}}>{stats.unscored}</b></span>
          {stats.reviewCount > 0 && <span>REVIEW: <b style={{color:'var(--signal)'}}>{stats.reviewCount}</b></span>}
          {Object.entries(stats.byMedia).sort(function(a,b){return b[1]-a[1]}).map(function(e) {
            return <span key={e[0]}>{e[0].toUpperCase()}: <b style={{color:'#fff'}}>{e[1]}</b></span>;
          })}
        </div>
      </div>

      {/* Right: editor panel */}
      <div style={isMobile ? (editCard ? {position:'fixed',inset:0,zIndex:200,background:'#000',display:'flex',flexDirection:'column',overflow:'hidden'} : {display:'none'}) : {width:editCard?420:0,flexShrink:0,borderLeft:'1px solid var(--border)',background:'var(--surface)',overflow:'hidden',transition:'width .2s ease',display:'flex',flexDirection:'column'}}>
        {editCard && (
          <React.Fragment>
            <div style={{width:isMobile?'100%':420,padding:16,overflow:'auto',flex:1}}>
              <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:16}}>
                <span style={{fontSize:12,letterSpacing:2,textTransform:'uppercase',color:'var(--cyan)'}}>{isNew?'NEW CARD':'EDIT CARD'}</span>
                <button className="A-btn" style={{fontSize:10,padding:'4px 10px'}} onClick={function(){setEditCard(null);setSelectedId(null)}}>✕</button>
              </div>

              {/* Lineconic score + crowd score */}
              <div style={{display:'flex',justifyContent:'center',gap:24,padding:'8px 0'}}>
                <div style={{textAlign:'center'}}>
                  <div style={{fontSize:24,fontWeight:700,color:'var(--gold)',letterSpacing:2}}>{editCard.scores&&editCard.scores.lineconic_score||0}</div>
                  <div style={{fontSize:9,color:'var(--text-dim)',letterSpacing:1}}>LINECONIC</div>
                </div>
                {(function(){var cs=crowdScores&&crowdScores[editCard.id];if(!cs)return null;var color=cs.crowd_score>=7?'#4ade80':cs.crowd_score>=4?'var(--gold)':'var(--signal)';return React.createElement('div',{style:{textAlign:'center'}},React.createElement('div',{style:{fontSize:24,fontWeight:700,color:color,letterSpacing:2}},cs.crowd_score),React.createElement('div',{style:{fontSize:9,color:'var(--text-dim)',letterSpacing:1}},cs.showCount+'x CROWD'))})()}
              </div>
              {editCard.status === 'review' && <div style={{textAlign:'center',marginBottom:8}}><span style={{fontSize:9,padding:'2px 8px',background:'rgba(255,0,127,.15)',color:'var(--signal)',border:'1px solid var(--signal)',letterSpacing:1}}>FLAGGED FOR REVIEW — LOW CROWD SCORE</span></div>}

              {/* Fields */}
              <div style={{marginBottom:12}}><label className="A-label">ID</label><input className="A-input" value={editCard.id} readOnly={!isNew} onChange={function(e){isNew&&updateField('id',e.target.value)}} style={isNew?{}:{background:'#0a0a0a',borderColor:'#1a1a1a',color:'#555'}} /></div>
              <div style={{marginBottom:12}}><label className="A-label">Code</label><input className="A-input" value={editCard.code} readOnly style={{background:'#0a0a0a',borderColor:'#1a1a1a',color:'#555'}} /></div>
              <div style={{marginBottom:12}}><label className="A-label">Answer (the line)</label><input className="A-input" value={editCard.content&&editCard.content.answer||''} onChange={function(e){updateField('content.answer',e.target.value)}} /></div>
              <div style={{marginBottom:12}}><label className="A-label">Primary (code display)</label><input className="A-input" value={editCard.content&&editCard.content.primary||''} onChange={function(e){updateField('content.primary',e.target.value)}} /></div>
              <div style={{marginBottom:12}}><label className="A-label">Secondary</label><input className="A-input" value={editCard.content&&editCard.content.secondary||''} onChange={function(e){updateField('content.secondary',e.target.value)}} /></div>
              <div style={{marginBottom:12}}><label className="A-label">Source</label><input className="A-input" value={editCard.source||''} onChange={function(e){updateField('source',e.target.value)}} /></div>
              <div style={{marginBottom:12}}><label className="A-label">Media Type</label>
                <select className="A-select" value={editCard.media_type||'movie'} onChange={function(e){updateField('media_type',e.target.value)}}>
                  {MEDIA_TYPES.map(function(mt){return <option key={mt} value={mt}>{mt}</option>})}
                </select>
              </div>
              <div style={{marginBottom:12}}><label className="A-label">Difficulty</label>
                <div style={{display:'flex',gap:4}}>
                  {[1,2,3,4,5].map(function(d) {
                    var active = editCard.difficulty===d;
                    return <div key={d} onClick={function(){updateField('difficulty',d)}} style={{
                      width:28,height:28,display:'flex',alignItems:'center',justifyContent:'center',fontSize:12,fontWeight:700,cursor:'pointer',
                      border:'1px solid '+diffColors[d],color:active?'#000':diffColors[d],background:active?diffColors[d]:'transparent'
                    }}>{d}</div>;
                  })}
                </div>
              </div>
              <div style={{marginBottom:12}}><label className="A-label">Category</label><input className="A-input" value={editCard.category||''} onChange={function(e){updateField('category',e.target.value)}} /></div>
              <div style={{marginBottom:12}}><label className="A-label">Themes (comma-separated)</label><input className="A-input" value={Array.isArray(editCard.themes)?editCard.themes.join(', '):(editCard.themes||'')} onChange={function(e){updateField('themes',e.target.value.split(',').map(function(t){return t.trim()}).filter(Boolean))}} /></div>

              {/* Scores */}
              <div style={{marginTop:16,marginBottom:12}}><label className="A-label" style={{marginBottom:8}}>Scores (0–10)</label>
                <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:8}}>
                  {SCORE_FIELDS.map(function(sf) {
                    return <div key={sf}><label className="A-label" style={{fontSize:9}}>{sf.replace(/_/g,' ')}</label>
                      <input className="A-input" type="number" min="0" max="10" step="1" style={{textAlign:'center',width:'100%'}}
                        value={editCard.scores&&editCard.scores[sf]!=null?editCard.scores[sf]:0}
                        onChange={function(e){updateField('scores.'+sf,Math.min(10,Math.max(0,Number(e.target.value)||0)))}} />
                    </div>;
                  })}
                </div>
              </div>
            </div>

            {/* Actions */}
            <div style={{display:'flex',gap:8,padding:'12px 16px',borderTop:'1px solid var(--border)',flexShrink:0}}>
              <button className="A-btn cyan" style={{flex:1}} onClick={saveCard} disabled={saving||!editCard.id}>{saving?'SAVING...':'SAVE'}</button>
              {!isNew && editCard.staged && <button className="A-btn" style={{background:'rgba(251,191,36,.15)',color:'var(--gold)',borderColor:'var(--gold)'}} onClick={function(){db.ref('cards/cards/'+editCard.id+'/staged').remove().then(function(){showToast('CARD APPROVED');setEditCard(function(p){var n=JSON.parse(JSON.stringify(p));delete n.staged;return n})}).catch(function(e){showToast('APPROVE FAILED: '+e.message)})}}>APPROVE</button>}
              {!isNew && editCard.status === 'review' && <button className="A-btn" style={{background:'rgba(0,255,136,.1)',color:'#4ade80',borderColor:'#4ade80'}} onClick={function(){db.ref('cards/cards/'+editCard.id+'/status').remove().then(function(){showToast('REVIEW CLEARED');setEditCard(function(p){var n=JSON.parse(JSON.stringify(p));delete n.status;return n})}).catch(function(e){showToast('CLEAR FAILED: '+e.message)})}}>CLEAR REVIEW</button>}
              {!isNew && (deleteConfirm
                ? <React.Fragment><button className="A-btn danger" onClick={deleteCard}>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>
    </div>
  );
}
