// mmv-pages.jsx — Dashboard, SongsPage, SplitsPage, CollaboratorsPage, SyncPage, ReleasesPage

const { useState: useState2, useMemo: useMemo2, useRef: useRef2, useEffect: useEffect2 } = React;

// ─── GenreDropdown ────────────────────────────────────────────────────────────

function GenreDropdown({ allGenres, selectedGenres, setSelectedGenres, genreMode, setGenreMode }) {
  const [open, setOpen] = useState2(false);
  const ref = useRef2(null);

  useEffect2(() => {
    if (!open) return;
    const handler = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener("mousedown", handler);
    return () => document.removeEventListener("mousedown", handler);
  }, [open]);

  const toggle = (g) => setSelectedGenres(prev => prev.includes(g) ? prev.filter(x => x !== g) : [...prev, g]);
  const active = selectedGenres.length > 0;
  const label  = active ? `Genre (${selectedGenres.length})` : "Genre";

  return (
    <div ref={ref} style={{ position:"relative" }}>
      <button
        onClick={() => setOpen(o => !o)}
        style={{ fontSize:12, padding:"4px 10px", borderRadius:5, border: active ? "1px solid var(--accent)" : "1px solid var(--border)", background: active ? "var(--accent-dim)" : "var(--bg-2)", color: active ? "var(--accent-text)" : "var(--text-2)", cursor:"pointer", fontWeight: active ? 600 : 400, display:"flex", alignItems:"center", gap:4, whiteSpace:"nowrap" }}
      >
        {label} <span style={{ fontSize:9 }}>▾</span>
      </button>
      {open && (
        <div style={{ position:"absolute", top:"calc(100% + 4px)", left:0, zIndex:200, background:"var(--card)", border:"1px solid var(--border)", borderRadius:"var(--r-lg)", boxShadow:"var(--shadow)", minWidth:180, padding:"6px 0" }}>
          {active && (
            <button onClick={() => setSelectedGenres([])} style={{ display:"block", width:"100%", textAlign:"left", padding:"5px 12px", fontSize:11, color:"var(--accent)", background:"none", border:"none", cursor:"pointer", borderBottom:"1px solid var(--border-sub)", marginBottom:4, fontWeight:500 }}>
              Clear
            </button>
          )}
          {allGenres.map(g => (
            <label key={g} style={{ display:"flex", alignItems:"center", gap:8, padding:"5px 12px", cursor:"pointer", fontSize:13, color:"var(--text)" }}
              onMouseEnter={e => e.currentTarget.style.background = "var(--bg-2)"}
              onMouseLeave={e => e.currentTarget.style.background = ""}
            >
              <input type="checkbox" checked={selectedGenres.includes(g)} onChange={() => toggle(g)} style={{ accentColor:"var(--accent)", cursor:"pointer" }} />
              {g}
            </label>
          ))}
          {selectedGenres.length >= 2 && (
            <div style={{ borderTop:"1px solid var(--border-sub)", marginTop:4, padding:"6px 12px", display:"flex", alignItems:"center", justifyContent:"space-between" }}>
              <span style={{ fontSize:11, color:"var(--text-3)" }}>Match</span>
              <button onClick={() => setGenreMode(m => m==="OR"?"AND":"OR")} style={{ fontSize:11, padding:"2px 8px", borderRadius:4, border:"1px solid var(--accent)", background:"var(--accent-dim)", color:"var(--accent-text)", cursor:"pointer", fontWeight:600 }}>
                {genreMode}
              </button>
            </div>
          )}
        </div>
      )}
    </div>
  );
}

// ─── Dashboard ────────────────────────────────────────────────────────────────

function Dashboard({ songs, briefs, showAnalytics, onSelectSong }) {
  const syncReady = songs.filter(s => s.syncReady).length;
  const pending   = songs.filter(s => s.splitConflict).length;
  const released  = songs.filter(s => s.status === "Released").length;

  const stats = [
    { num:songs.length, label:"Total Songs",      sub:`${released} released`,       accent:"var(--accent)" },
    { num:syncReady,    label:"Sync Ready",        sub:"cleared for licensing",       accent:"#059669" },
    { num:pending,      label:"Pending Splits",    sub:"awaiting signatures",         accent:"#d97706" },
    { num:2,            label:"Upcoming Releases", sub:"next 90 days",                accent:"#2563eb" },
  ];

  return (
    <div className="page-content page-fade">
      {showAnalytics && (
        <div className="stat-grid">
          {stats.map((s,i) => (
            <div key={i} className="stat-card">
              <div style={{ fontSize:36, fontWeight:700, lineHeight:1, color:s.accent, letterSpacing:"-0.03em" }}>{s.num}</div>
              <div style={{ fontSize:13.5, fontWeight:600, marginTop:8, color:"var(--text)" }}>{s.label}</div>
              <div style={{ fontSize:12, color:"var(--text-3)", marginTop:2 }}>{s.sub}</div>
              <div style={{ position:"absolute", top:0, left:0, width:3, height:"100%", background:s.accent, borderRadius:"6px 0 0 6px", opacity:0.7 }}></div>
            </div>
          ))}
        </div>
      )}

      <div className="dash-grid">
        {/* Recent songs */}
        <div className="dash-panel">
          <div className="panel-header"><span>Recent Songs</span><span style={{ fontSize:11, color:"var(--text-3)" }}>Updated recently</span></div>
          <table className="mini-table">
            <thead><tr><th>Title</th><th>BPM</th><th>Status</th><th>Sync</th></tr></thead>
            <tbody>
              {[...songs].reverse().slice(0,5).map(s => (
                <tr key={s.id} onClick={() => onSelectSong(s)} style={{ cursor:"pointer" }}>
                  <td>
                    <div style={{ fontWeight:500, fontSize:13 }}>{s.title}</div>
                    <div style={{ fontSize:11, color:"var(--text-3)" }}>{s.genre}</div>
                  </td>
                  <td><span className="mono" style={{ fontSize:12 }}>{s.bpm}</span></td>
                  <td><StatusBadge status={s.status} /></td>
                  <td>{s.syncReady ? <span style={{ color:"#059669", fontWeight:600 }}>✓</span> : <span style={{ color:"var(--text-3)" }}>—</span>}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>

        {/* Sync-ready */}
        <div className="dash-panel">
          <div className="panel-header"><span>Sync-Ready Catalog</span><span style={{ fontSize:11, color:"#059669" }}>{syncReady} tracks</span></div>
          {songs.filter(s=>s.syncReady).map(s => (
            <div key={s.id} className="sync-item" onClick={() => onSelectSong(s)}>
              <div style={{ width:38, height:38, borderRadius:8, flexShrink:0, background:`hsl(${s.artworkHue||240},40%,92%)`, display:"flex", alignItems:"center", justifyContent:"center" }}>
                <span style={{ fontSize:9, fontFamily:"var(--mono)", color:`hsl(${s.artworkHue||240},40%,40%)` }}>{s.bpm}</span>
              </div>
              <div style={{ flex:1, minWidth:0 }}>
                <div style={{ fontWeight:500, fontSize:13, overflow:"hidden", textOverflow:"ellipsis", whiteSpace:"nowrap" }}>{s.title}</div>
                <div style={{ fontSize:11, color:"var(--text-3)", marginTop:1 }}>{s.key} · {s.genre}</div>
              </div>
              {s.stemsAvailable && <Badge color="var(--accent)" bg="#ede9fe" style={{ fontSize:9 }}>Stems</Badge>}
            </div>
          ))}
        </div>

        {/* Active briefs */}
        <div className="dash-panel">
          <div className="panel-header"><span>Active Sync Briefs</span><span style={{ fontSize:11, color:"var(--text-3)" }}>{briefs.filter(b=>!["Landed","Passed","Expired"].includes(b.status)).length} active</span></div>
          {briefs.filter(b=>!["Landed","Passed","Expired"].includes(b.status)).slice(0,5).map(b => (
            <div key={b.id} className="brief-row">
              <div style={{ flex:1, minWidth:0 }}>
                <div style={{ fontWeight:500, fontSize:13, overflow:"hidden", textOverflow:"ellipsis", whiteSpace:"nowrap" }}>{b.title}</div>
                <div style={{ fontSize:11, color:"var(--text-3)", marginTop:2 }}>{b.client} · {b.deadline}</div>
              </div>
              <StatusBadge status={b.status} />
            </div>
          ))}
          {briefs.filter(b=>!["Landed","Passed","Expired"].includes(b.status)).length===0 && (
            <div style={{ padding:"20px 0", textAlign:"center", color:"var(--text-3)", fontSize:12 }}>No active briefs</div>
          )}
        </div>
      </div>
    </div>
  );
}

// ─── Songs Page ───────────────────────────────────────────────────────────────

function SongsPage({ songs, collabs: collabsProp, setSongs, search, onSelect, density }) {
  const allCollabs = collabsProp || COLLABS;
  const [filter,         setFilter]         = useState2("All");
  const [sortBy,         setSortBy]         = useState2("date-desc");
  const [selectedGenres, setSelectedGenres] = useState2([]);
  const [genreMode,      setGenreMode]      = useState2("OR");
  const ROW_PAD = { compact:"7px 14px", comfortable:"11px 14px", spacious:"16px 14px" };
  const pad = ROW_PAD[density] || ROW_PAD.comfortable;

  const allGenres = useMemo2(() => {
    const gs = songs.flatMap(s => s.genre.split(" / ").map(g => g.trim()));
    return [...new Set(gs)].sort();
  }, [songs]);

  const toggleGenre = (g) => setSelectedGenres(prev => prev.includes(g) ? prev.filter(x => x !== g) : [...prev, g]);

  const filtered = useMemo2(() => {
    let list = songs;
    if      (filter==="Sync Ready")  list = list.filter(s => s.syncReady);
    else if (filter==="Released")    list = list.filter(s => s.status==="Released");
    else if (filter==="In Progress") list = list.filter(s => ["In Progress","Mixing"].includes(s.status));
    else if (filter==="Demo")        list = list.filter(s => s.status==="Demo");
    if (search) {
      const q = search.toLowerCase();
      list = list.filter(s =>
        s.title.toLowerCase().includes(q) || s.genre.toLowerCase().includes(q) ||
        s.key.toLowerCase().includes(q)   || s.isrc.toLowerCase().includes(q) ||
        s.moods.some(m => m.toLowerCase().includes(q))
      );
    }
    if (selectedGenres.length > 0) {
      list = list.filter(s => {
        const sg = s.genre.split(" / ").map(g => g.trim());
        return genreMode === "OR"
          ? selectedGenres.some(g => sg.includes(g))
          : selectedGenres.every(g => sg.includes(g));
      });
    }
    list = [...list].sort((a,b) => {
      if (sortBy==="title-asc"  || sortBy==="title")   return a.title.localeCompare(b.title);
      if (sortBy==="title-desc")                        return b.title.localeCompare(a.title);
      if (sortBy==="bpm-desc"   || sortBy==="bpm")     return b.bpm - a.bpm;
      if (sortBy==="bpm-asc")                          return a.bpm - b.bpm;
      if (sortBy==="status-asc" || sortBy==="status")  return a.status.localeCompare(b.status);
      if (sortBy==="status-desc")                       return b.status.localeCompare(a.status);
      if (sortBy==="date-asc")                         return (a.createdAt||0) - (b.createdAt||0);
      return (b.createdAt||0) - (a.createdAt||0);
    });
    return list;
  }, [songs, filter, search, sortBy, selectedGenres, genreMode]);

  const selStyle = { fontSize:12, padding:"4px 8px", borderRadius:5, border:"1px solid var(--border)", background:"var(--bg-2)", color:"var(--text-2)", outline:"none", cursor:"pointer" };

  const handleColSort = (col) => {
    if (col === "title") {
      if (sortBy === "title-asc" || sortBy === "title") setSortBy("title-desc");
      else setSortBy("title-asc");
    } else if (col === "bpm") {
      if (sortBy === "bpm-desc" || sortBy === "bpm") setSortBy("bpm-asc");
      else setSortBy("bpm-desc");
    } else if (col === "status") {
      if (sortBy === "status-asc" || sortBy === "status") setSortBy("status-desc");
      else setSortBy("status-asc");
    }
  };

  const colSortIcon = (col) => {
    if (col === "title") {
      if (sortBy === "title-asc" || sortBy === "title") return " ↑";
      if (sortBy === "title-desc") return " ↓";
    } else if (col === "bpm") {
      if (sortBy === "bpm-desc" || sortBy === "bpm") return " ↓";
      if (sortBy === "bpm-asc") return " ↑";
    } else if (col === "status") {
      if (sortBy === "status-asc" || sortBy === "status") return " ↑";
      if (sortBy === "status-desc") return " ↓";
    }
    return " ↕";
  };

  const thSort = (col, label) => (
    <th onClick={() => handleColSort(col)} style={{ cursor:"pointer", userSelect:"none", whiteSpace:"nowrap" }}>
      {label}<span style={{ color:"var(--text-3)", fontSize:10 }}>{colSortIcon(col)}</span>
    </th>
  );

  return (
    <div className="page-content page-fade">
      <div className="filter-bar">
        {["All","Released","Sync Ready","In Progress","Demo"].map(f => (
          <button key={f} className={"filter-chip"+(filter===f?" active":"")} onClick={() => setFilter(f)}>{f}</button>
        ))}
        <div style={{ marginLeft:"auto", display:"flex", alignItems:"center", gap:8 }}>
          {allGenres.length > 0 && <GenreDropdown allGenres={allGenres} selectedGenres={selectedGenres} setSelectedGenres={setSelectedGenres} genreMode={genreMode} setGenreMode={setGenreMode} />}
          <select style={selStyle} value={sortBy} onChange={e => setSortBy(e.target.value)}>
            <option value="date-desc">Newest first</option>
            <option value="date-asc">Oldest first</option>
            <option value="title-asc">Title A–Z</option>
            <option value="title-desc">Title Z–A</option>
            <option value="status-asc">Status A–Z</option>
            <option value="bpm-desc">BPM ↓</option>
            <option value="bpm-asc">BPM ↑</option>
          </select>
          <span style={{ fontSize:12, color:"var(--text-3)" }}>{filtered.length} songs</span>
        </div>
      </div>

      <div className="table-wrap">
        <table className="data-table">
          <thead>
            <tr>
              {thSort("title", "Title")}<th>Key / BPM</th><th>Genre</th><th>Moods</th>
              {thSort("status", "Status")}<th>Sync</th><th>Own%</th><th>Collaborators</th>
            </tr>
          </thead>
          <tbody>
            {filtered.map(song => (
              <tr key={song.id} onClick={() => onSelect(song)} style={{ cursor:"pointer" }}>
                <td style={{ padding:pad, minWidth:160 }}>
                  <div style={{ fontWeight:500, fontSize:13 }}>{song.title}</div>
                  <div style={{ fontSize:11, color:"var(--text-3)", marginTop:1 }}>{song.version}</div>
                  {song.splitConflict && <div style={{ fontSize:10, color:"#d97706", marginTop:2 }}>⚠ Split pending</div>}
                </td>
                <td style={{ padding:pad }}>
                  <div style={{ fontSize:12 }}>{song.key}</div>
                  <div className="mono" style={{ fontSize:11, color:"var(--text-3)" }}>{song.bpm} bpm</div>
                </td>
                <td style={{ padding:pad, fontSize:12, color:"var(--text-2)", maxWidth:130 }}>{song.genre}</td>
                <td style={{ padding:pad }}>
                  <div style={{ display:"flex", gap:3, flexWrap:"wrap" }}>
                    {song.moods.slice(0,2).map(m => <Badge key={m} style={{ fontSize:9.5 }}>{m}</Badge>)}
                  </div>
                </td>
                <td style={{ padding:pad }}><StatusBadge status={song.status} /></td>
                <td style={{ padding:pad }}>
                  {song.syncReady
                    ? <span style={{ color:"#059669", fontWeight:600, fontSize:12 }}>✓ Ready</span>
                    : <span style={{ color:"var(--text-3)", fontSize:12 }}>—</span>}
                </td>
                <td style={{ padding:pad, textAlign:"center" }}>
                  <span className="mono" style={{ fontSize:12 }}>
                    {+parseFloat(song.ownershipPct).toFixed(2)}%<span style={{ color:"var(--text-3)" }}> / </span>{+parseFloat(song.splits.find(s => getSplitName(s, allCollabs) === song.masterOwner)?.publisher ?? song.ownershipPct).toFixed(2)}%
                  </span>
                  <div style={{ fontSize:9.5, color:"var(--text-3)", marginTop:1 }}>M / P</div>
                </td>
                <td style={{ padding:pad }}>
                  <div style={{ display:"flex", gap:3 }}>
                    {song.splits.map((sp,i) => {
                      const spName = getSplitName(sp, allCollabs);
                      return (
                        <div key={i} title={`${spName}: ${sp.writer}%`} style={{
                          width:24, height:24, borderRadius:"50%", background:SPLIT_COLORS[i%SPLIT_COLORS.length],
                          display:"flex", alignItems:"center", justifyContent:"center",
                          fontSize:9, fontWeight:700, color:"#fff", flexShrink:0,
                        }}>{spName.charAt(0)}</div>
                      );
                    })}
                  </div>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
        {filtered.length===0 && (
          <div style={{ padding:40, textAlign:"center", color:"var(--text-3)", fontSize:13 }}>
            No songs match your filters.
          </div>
        )}
      </div>
    </div>
  );
}

// ─── Splits Page ──────────────────────────────────────────────────────────────

function SplitsPage({ songs, collabs: collabsProp, onSaveSplits }) {
  const collabs = collabsProp || COLLABS;
  const [selId, setSelId]         = useState2(songs[0]?.id);
  const [editSplits, setEditSplits] = useState2(null);
  const [saved, setSaved]          = useState2(false);

  const song = songs.find(s => s.id===selId) || songs[0];

  useEffect2(() => {
    if (song) setEditSplits(song.splits.map(s => ({...s})));
    setSaved(false);
  }, [selId]);

  const total = (editSplits||[]).reduce((a,s) => a + Number(s.writer||0), 0);
  const valid = Math.abs(total - 100) < 0.01;
  const dirty = editSplits && JSON.stringify(editSplits) !== JSON.stringify(song?.splits);

  const update = (idx, field, val) => {
    setSaved(false);
    setEditSplits(prev => prev.map((s,i) => i===idx ? {...s, [field]: field==="writer"||field==="publisher" ? Number(val) : val} : s));
  };

  const save = () => {
    if (!valid) return;
    onSaveSplits(selId, editSplits);
    setSaved(true);
    setTimeout(() => setSaved(false), 2000);
  };

  const distribute = () => {
    if (!editSplits) return;
    const each = Math.floor(100 / editSplits.length);
    const rem  = 100 - each * editSplits.length;
    setEditSplits(editSplits.map((s,i) => ({...s, writer:each+(i===0?rem:0), publisher:each+(i===0?rem:0)})));
    setSaved(false);
  };

  if (!song || !editSplits) return null;

  return (
    <div className="page-content page-fade">
      <div className="splits-layout">
        {/* Song list */}
        <div className="splits-songlist">
          <div className="panel-header" style={{ fontSize:12 }}>Songs</div>
          {songs.map(s => {
            const t = s.splits.reduce((a,sp) => a+sp.writer, 0);
            return (
              <div key={s.id} className={"split-song-item"+(s.id===selId?" active":"")} onClick={() => setSelId(s.id)}>
                <div style={{ flex:1, minWidth:0 }}>
                  <div style={{ fontWeight:500, fontSize:12.5, overflow:"hidden", textOverflow:"ellipsis", whiteSpace:"nowrap" }}>{s.title}</div>
                  <div style={{ fontSize:10, marginTop:1, color: t===100?"#059669":"#d97706" }}>
                    {t===100 ? "✓ Balanced" : `⚠ ${t}%`}
                  </div>
                </div>
                <span style={{ fontSize:10, color:"var(--text-3)" }}>{s.splits.length}p</span>
              </div>
            );
          })}
        </div>

        {/* Detail */}
        <div className="splits-detail">
          <div className="panel-header" style={{ padding:"14px 20px" }}>
            <span style={{ fontWeight:600 }}>{song.title}</span>
            <div style={{ display:"flex", gap:8, alignItems:"center" }}>
              {valid
                ? <Badge color="#166534" bg="#dcfce7">✓ Balanced</Badge>
                : <Badge color="#92400e" bg="#fef3c7">⚠ {+parseFloat(total).toFixed(2)}%</Badge>
              }
              {dirty && !saved && (
                <>
                  <button onClick={distribute} className="btn-ghost" style={{ fontSize:11 }}>Distribute evenly</button>
                  <button onClick={save} disabled={!valid} className="btn-accent" style={{ fontSize:12, opacity:valid?1:0.5 }}>Save</button>
                </>
              )}
              {saved && <span style={{ fontSize:12, color:"#059669", fontWeight:500 }}>✓ Saved</span>}
            </div>
          </div>

          <div style={{ padding:"20px" }}>
            {/* Live visual bar */}
            <div style={{ marginBottom:20 }}>
              <div style={{ fontSize:10.5, color:"var(--text-3)", textTransform:"uppercase", letterSpacing:"0.06em", marginBottom:8 }}>Writer Split Distribution</div>
              <div style={{ display:"flex", height:10, borderRadius:5, overflow:"hidden", gap:2 }}>
                {editSplits.map((s,i) => (
                  <div key={i} style={{ width:`${s.writer}%`, background:SPLIT_COLORS[i], transition:"width 0.15s ease", minWidth: s.writer>0?2:0 }}></div>
                ))}
                {total < 100 && <div style={{ flex:1, background:"var(--border)" }}></div>}
              </div>
              <div style={{ display:"flex", gap:14, marginTop:8, flexWrap:"wrap" }}>
                {editSplits.map((s,i) => (
                  <div key={i} style={{ display:"flex", alignItems:"center", gap:5, fontSize:12 }}>
                    <div style={{ width:9, height:9, borderRadius:2, background:SPLIT_COLORS[i] }}></div>
                    <span style={{ color:"var(--text-2)" }}>{getSplitName(s, collabs).split(" ")[0]}: <strong style={{ color:"var(--text)", fontFamily:"var(--mono)" }}>{s.writer}%</strong></span>
                  </div>
                ))}
              </div>
            </div>

            {/* Editable table */}
            <table className="data-table">
              <thead><tr>
                <th>Collaborator</th><th>Role</th><th>Writer %</th><th>Publisher %</th><th>PRO</th><th>Status</th>
              </tr></thead>
              <tbody>
                {editSplits.map((s,i) => (
                  <tr key={i}>
                    <td>
                      <div style={{ display:"flex", alignItems:"center", gap:8 }}>
                        <div style={{ width:28, height:28, borderRadius:"50%", background:SPLIT_COLORS[i], display:"flex", alignItems:"center", justifyContent:"center", fontSize:11, fontWeight:700, color:"#fff", flexShrink:0 }}>{getSplitName(s, collabs).charAt(0)}</div>
                        <span style={{ fontWeight:500, fontSize:13 }}>{getSplitName(s, collabs)}</span>
                      </div>
                    </td>
                    <td style={{ fontSize:12, color:"var(--text-3)" }}>{s.role}</td>
                    <td>
                      <div style={{ display:"flex", alignItems:"center", gap:6 }}>
                        <input
                          type="number" min="0" max="100" step="0.01"
                          value={s.writer}
                          onChange={e => update(i,"writer",e.target.value)}
                          className="split-input"
                          style={{ borderColor: valid?"var(--border)":"#fcd34d" }}
                        />
                        <span style={{ fontSize:12, color:"var(--text-3)" }}>%</span>
                      </div>
                    </td>
                    <td>
                      <div style={{ display:"flex", alignItems:"center", gap:6 }}>
                        <input
                          type="number" min="0" max="100" step="0.01"
                          value={s.publisher}
                          onChange={e => update(i,"publisher",e.target.value)}
                          className="split-input"
                        />
                        <span style={{ fontSize:12, color:"var(--text-3)" }}>%</span>
                      </div>
                    </td>
                    <td style={{ fontSize:12, color:"var(--text-3)" }}>
                      {(() => {
                        const c = s.collabId ? collabs.find(x => x.id === s.collabId) : collabs.find(x => x.name === s.name);
                        return c ? (c.pro || "—") : "—";
                      })()}
                    </td>
                    <td>
                      {(song.splitConflict && i > 0)
                        ? <Badge color="#92400e" bg="#fef3c7">Pending</Badge>
                        : <Badge color="#166534" bg="#dcfce7">Signed</Badge>}
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>

            {/* Total row */}
            <div style={{ marginTop:16, padding:"12px 16px", background:"var(--bg-2)", border:`1px solid ${valid?"var(--border)":"#fcd34d"}`, borderRadius:8, display:"flex", justifyContent:"space-between", alignItems:"center" }}>
              <span style={{ fontSize:13, color:"var(--text-2)" }}>Writer Total</span>
              <span className="mono" style={{ fontWeight:700, fontSize:16, color: valid?"#059669":"#d97706" }}>{+parseFloat(total).toFixed(2)}%</span>
            </div>
            {!valid && (
              <div style={{ marginTop:8, fontSize:12, color:"#d97706" }}>
                ⚠ {total < 100 ? `${+parseFloat(100-total).toFixed(2)}% unassigned` : `${+parseFloat(total-100).toFixed(2)}% over-allocated`} — adjust splits before saving.
              </div>
            )}
          </div>
        </div>
      </div>
    </div>
  );
}

// ─── Collaborators Page ───────────────────────────────────────────────────────

function CollaboratorsPage({ search, collabs: collabsProp, songs: songsProp, onSelectCollab }) {
  const collabs = collabsProp || COLLABS;
  const songs   = songsProp   || SONGS;
  const [filter,         setFilter]         = useState2("All");
  const [selectedGenres, setSelectedGenres] = useState2([]);
  const [genreMode,      setGenreMode]      = useState2("OR");
  const [sortAZ,         setSortAZ]         = useState2(null);
  const [viewMode,       setViewMode]       = useState2("cards");
  const [listSort,       setListSort]       = useState2({ col: "name", dir: "asc" });

  const allGenres = useMemo2(() => {
    const tags = collabs.flatMap(c => c.tags || []);
    return [...new Set(tags)].sort();
  }, [collabs]);

  const filtered = useMemo2(() => {
    let list = collabs;
    if (filter === "Incomplete") list = list.filter(c => !isCollabComplete(c));
    if (search) {
      const q = search.toLowerCase();
      list = list.filter(c =>
        c.name.toLowerCase().includes(q) || c.role.toLowerCase().includes(q) ||
        (c.location||"").toLowerCase().includes(q) || (c.tags||[]).some(t=>t.toLowerCase().includes(q))
      );
    }
    if (selectedGenres.length > 0) {
      list = list.filter(c => {
        const tags = c.tags || [];
        return genreMode === "OR"
          ? selectedGenres.some(g => tags.includes(g))
          : selectedGenres.every(g => tags.includes(g));
      });
    }
    return list;
  }, [collabs, search, filter, selectedGenres, genreMode]);

  const sorted = useMemo2(() => {
    let list = [...filtered];
    if (viewMode === "cards") {
      if (sortAZ === "asc")  list.sort((a,b) => a.name.localeCompare(b.name));
      if (sortAZ === "desc") list.sort((a,b) => b.name.localeCompare(a.name));
    } else {
      list.sort((a,b) => {
        const av = (a[listSort.col] || "").toString();
        const bv = (b[listSort.col] || "").toString();
        return listSort.dir === "asc" ? av.localeCompare(bv) : bv.localeCompare(av);
      });
    }
    return list;
  }, [filtered, viewMode, sortAZ, listSort]);

  const songCountByCollab = useMemo2(() => {
    const map = {};
    for (const c of collabs) {
      map[c.id] = songs.filter(s => s.splits.some(sp => sp.collabId === c.id || sp.name === c.name)).length;
    }
    return map;
  }, [collabs, songs]);

  const incompleteCount = collabs.filter(c => !isCollabComplete(c)).length;

  const toggleListSort = (col) => setListSort(prev =>
    prev.col === col ? { col, dir: prev.dir === "asc" ? "desc" : "asc" } : { col, dir: "asc" }
  );

  const thSort = (col, label) => (
    <th onClick={() => toggleListSort(col)} style={{ cursor:"pointer", userSelect:"none" }}>
      {label}{listSort.col === col ? (listSort.dir === "asc" ? " ▲" : " ▼") : ""}
    </th>
  );

  return (
    <div className="page-content page-fade">
      <div className="filter-bar" style={{ marginBottom:16 }}>
        {["All","Incomplete"].map(f => (
          <button key={f} className={"filter-chip"+(filter===f?" active":"")} onClick={() => setFilter(f)}>
            {f}
            {f === "Incomplete" && incompleteCount > 0 && (
              <span style={{ marginLeft:4, background:"#d97706", color:"#fff", borderRadius:8, padding:"0 5px", fontSize:9 }}>{incompleteCount}</span>
            )}
          </button>
        ))}
        <div style={{ marginLeft:"auto", display:"flex", alignItems:"center", gap:6 }}>
          {allGenres.length > 0 && <GenreDropdown allGenres={allGenres} selectedGenres={selectedGenres} setSelectedGenres={setSelectedGenres} genreMode={genreMode} setGenreMode={setGenreMode} />}
          {viewMode === "cards" && (
            <button
              onClick={() => setSortAZ(s => s === "asc" ? "desc" : s === "desc" ? null : "asc")}
              style={{ fontSize:11, padding:"3px 9px", borderRadius:5, border:"1px solid var(--border)", background: sortAZ ? "var(--accent-dim)" : "var(--bg-2)", color: sortAZ ? "var(--accent-text)" : "var(--text-2)", cursor:"pointer", fontWeight: sortAZ ? 600 : 400 }}
            >
              {sortAZ === "asc" ? "A → Z" : sortAZ === "desc" ? "Z → A" : "A–Z"}
            </button>
          )}
          <div style={{ display:"flex", gap:2 }}>
            {[["cards","Cards"],["list","List"]].map(([mode, label]) => (
              <button
                key={mode}
                onClick={() => setViewMode(mode)}
                style={{
                  padding:"4px 10px", borderRadius:5, fontSize:12, fontWeight: viewMode === mode ? 600 : 400,
                  border: viewMode === mode ? "1px solid var(--accent)" : "1px solid var(--border)",
                  background: viewMode === mode ? "var(--accent-dim)" : "var(--bg-2)",
                  color: viewMode === mode ? "var(--accent-text)" : "var(--text-2)",
                  cursor:"pointer", fontFamily:"var(--font)",
                }}
              >{label}</button>
            ))}
          </div>
        </div>
      </div>

      {viewMode === "cards" ? (
        <div className="collab-grid">
          {sorted.map((c,idx) => {
            const pal = COLLAB_PALETTE[idx % COLLAB_PALETTE.length];
            const songCount = songCountByCollab[c.id] ?? 0;
            return (
              <div key={c.id} className="collab-card" onClick={() => onSelectCollab(c)}>
                <div style={{ display:"flex", justifyContent:"space-between", alignItems:"flex-start" }}>
                  <div style={{ width:44, height:44, borderRadius:11, background:pal.bg, color:pal.color, display:"flex", alignItems:"center", justifyContent:"center", fontWeight:700, fontSize:15 }}>
                    {c.name.split(" ").map(n=>n[0]).join("")}
                  </div>
                  <div style={{ display:"flex", gap:4, alignItems:"center" }}>
                    {!isCollabComplete(c) && (
                      <span style={{ fontSize:9.5, color:"#d97706", background:"#fef3c7", border:"1px solid #fcd34d", borderRadius:4, padding:"1px 6px", fontWeight:500 }}>⚠ Incomplete</span>
                    )}
                    <StatusBadge status={c.status} />
                  </div>
                </div>
                <div style={{ marginTop:13 }}>
                  <div style={{ fontWeight:700, fontSize:15 }}>{c.name}</div>
                  <div style={{ fontSize:12.5, color:"var(--text-3)", marginTop:2 }}>{c.role}</div>
                  <div style={{ fontSize:11.5, color:"var(--text-3)", marginTop:2 }}>{c.location}</div>
                </div>
                <div style={{ display:"flex", gap:4, marginTop:10, flexWrap:"wrap" }}>
                  {c.tags.map(t => <Badge key={t} style={{ fontSize:9.5 }}>{t}</Badge>)}
                </div>
                <div style={{ marginTop:13, paddingTop:12, borderTop:"1px solid var(--border)", display:"flex", justifyContent:"space-between", fontSize:12, color:"var(--text-3)" }}>
                  <span>{songCount} song{songCount!==1?"s":""}</span>
                  <span>{c.pro}</span>
                </div>
              </div>
            );
          })}
        </div>
      ) : (
        <div className="table-wrap">
          <table className="data-table">
            <thead>
              <tr>
                {thSort("name", "Name")}
                {thSort("role", "Role")}
                <th>Location</th>
                <th>Songs</th>
                {thSort("status", "Status")}
              </tr>
            </thead>
            <tbody>
              {sorted.map(c => {
                const songCount = songCountByCollab[c.id] ?? 0;
                return (
                  <tr key={c.id} onClick={() => onSelectCollab(c)} style={{ cursor:"pointer" }}>
                    <td>
                      <span style={{ fontWeight:600 }}>{c.name}</span>
                      {!isCollabComplete(c) && <span style={{ marginLeft:6, fontSize:11, color:"#d97706" }} title="Missing PRO or IPI">⚠</span>}
                    </td>
                    <td style={{ color:"var(--text-3)", fontSize:13 }}>{c.role || "—"}</td>
                    <td style={{ color:"var(--text-3)", fontSize:13 }}>{c.location || "—"}</td>
                    <td style={{ fontSize:13 }}>{songCount}</td>
                    <td><StatusBadge status={c.status} /></td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      )}
    </div>
  );
}

// ─── Sync Page ────────────────────────────────────────────────────────────────

function SyncPage({ briefs, songs, onUpdateBrief, onSelectBrief, onNewBrief }) {
  const [tab,           setTab]           = useState2("active");
  const [historyFilter, setHistoryFilter] = useState2("All");
  const { dragOverCol, handleDragStart, handleDrop, handleDragOver, handleDragLeave, handleDragEnd } = useKanban(onUpdateBrief);

  const ARCHIVE = ["Landed","Passed","Expired"];
  const COLS    = ["Active","Submitted","In Review","Shortlisted"];

  const pipeline = briefs.filter(b => !ARCHIVE.includes(b.status));
  const history  = briefs.filter(b =>  ARCHIVE.includes(b.status));

  const overdueFU     = pipeline.filter(b => b.followUpDate && !b.followUpDone && new Date(b.followUpDate) < new Date()).length;
  const pipelineValue = pipeline.reduce((a, b) => a + (b.budgetEstimate || 0), 0);
  const landedDeals   = history.filter(b => b.status === "Landed");
  const landedRevenue = landedDeals.reduce((a, b) => a + (b.confirmedFee || 0), 0);

  const filteredHistory = historyFilter === "All" ? history : history.filter(b => b.status === historyFilter);

  return (
    <div className="page-content page-fade">

      {/* Stats bar */}
      <div style={{ display:"grid", gridTemplateColumns:"repeat(4,1fr)", gap:12, marginBottom:20 }}>
        {[
          { label:"Active Briefs",      value:pipeline.length,                                                                      accent:"var(--accent)" },
          { label:"Overdue Follow-ups", value:overdueFU,                                                                            accent:overdueFU>0?"#dc2626":"#9ca3af" },
          { label:"Pipeline Value",     value:pipelineValue>0?"$"+pipelineValue.toLocaleString():"—",                               accent:"#059669" },
          { label:"Landed",             value:landedRevenue>0?"$"+landedRevenue.toLocaleString():landedDeals.length+" deal"+(landedDeals.length!==1?"s":""), accent:"#2563eb" },
        ].map((s, i) => (
          <div key={i} className="stat-card">
            <div style={{ position:"absolute", top:0, left:0, width:3, height:"100%", background:s.accent, borderRadius:"6px 0 0 6px", opacity:0.7 }}></div>
            <div style={{ fontSize:26, fontWeight:700, color:s.accent, letterSpacing:"-0.02em" }}>{s.value}</div>
            <div style={{ fontSize:11.5, color:"var(--text-3)", marginTop:4 }}>{s.label}</div>
          </div>
        ))}
      </div>

      {/* Tab bar + New Brief */}
      <div style={{ display:"flex", justifyContent:"space-between", alignItems:"center", marginBottom:16 }}>
        <div style={{ display:"flex", gap:4 }}>
          {[["active","Active Pipeline"],["history","History"]].map(([t,l]) => (
            <button key={t} className={"filter-chip"+(tab===t?" active":"")} onClick={()=>setTab(t)}>{l}</button>
          ))}
        </div>
        <button className="btn-accent" onClick={onNewBrief} style={{ fontSize:12 }}>+ New Brief</button>
      </div>

      {/* Kanban */}
      {tab==="active" && (
        <div className="kanban">
          {COLS.map(col => {
            const colBriefs = pipeline.filter(b => b.status === col);
            return (
              <div
                key={col}
                className={"kanban-col"+(dragOverCol===col?" drag-over":"")}
                onDragOver={e=>handleDragOver(e,col)}
                onDragLeave={handleDragLeave}
                onDrop={e=>handleDrop(e,col)}
              >
                <div className="kanban-col-header">
                  <span>{col}</span>
                  <span style={{fontSize:11,background:"var(--bg-2)",padding:"1px 8px",borderRadius:10,color:"var(--text-3)"}}>{colBriefs.length}</span>
                </div>

                {colBriefs.map(b => {
                  const overdue = b.followUpDate && !b.followUpDone && new Date(b.followUpDate) < new Date();
                  const songCt  = (b.submittedSongs||[]).length;
                  return (
                    <div
                      key={b.id}
                      className="brief-card brief-card-draggable"
                      draggable
                      onDragStart={e=>handleDragStart(e,b.id)}
                      onDragEnd={handleDragEnd}
                      onClick={()=>onSelectBrief(b)}
                    >
                      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",gap:6}}>
                        <div style={{fontWeight:600,fontSize:13.5,flex:1,minWidth:0,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}>{b.title}</div>
                        {overdue && <span className="followup-badge">Follow-up</span>}
                      </div>
                      <div style={{fontSize:12,color:"var(--text-3)",marginTop:3}}>{b.client||"—"}</div>
                      {b.placement && <div style={{fontSize:11,color:"var(--text-3)",marginTop:1}}>{b.placement}</div>}
                      {(b.mood||[]).length>0 && (
                        <div style={{display:"flex",gap:4,flexWrap:"wrap",marginTop:8}}>
                          {(b.mood||[]).slice(0,2).map((m,i)=><Badge key={i} style={{fontSize:9.5}}>{m}</Badge>)}
                        </div>
                      )}
                      <div style={{marginTop:10,paddingTop:9,borderTop:"1px solid var(--border)",display:"flex",justifyContent:"space-between",alignItems:"center"}}>
                        <div style={{display:"flex",gap:8,alignItems:"center"}}>
                          {b.deadline && <span style={{fontSize:11,color:"var(--text-3)"}}>Due {b.deadline}</span>}
                          {songCt>0 && <span style={{fontSize:11,color:"var(--accent)"}}>{songCt} song{songCt!==1?"s":""}</span>}
                        </div>
                        {b.budget && <span style={{fontSize:11,fontWeight:600,color:"#059669"}}>{b.budget}</span>}
                      </div>
                    </div>
                  );
                })}

                {colBriefs.length===0 && (
                  <div style={{margin:12,padding:"24px 12px",textAlign:"center",color:"var(--text-3)",fontSize:12,border:"1px dashed var(--border)",borderRadius:7}}>
                    {dragOverCol===col?"Drop here":"Empty"}
                  </div>
                )}
              </div>
            );
          })}
        </div>
      )}

      {/* History */}
      {tab==="history" && (
        <div>
          <div className="filter-bar" style={{marginBottom:12}}>
            {["All","Landed","Passed","Expired"].map(f=>(
              <button key={f} className={"filter-chip"+(historyFilter===f?" active":"")} onClick={()=>setHistoryFilter(f)}>{f}</button>
            ))}
            <span style={{marginLeft:"auto",fontSize:12,color:"var(--text-3)"}}>{filteredHistory.length} brief{filteredHistory.length!==1?"s":""}</span>
          </div>

          {filteredHistory.length>0 ? (
            <div className="table-wrap">
              <table className="data-table">
                <thead><tr>
                  <th>Brief</th><th>Client</th><th>Deadline</th><th>Outcome</th><th>Songs</th><th>Fee</th><th>Notes</th>
                </tr></thead>
                <tbody>
                  {filteredHistory.map(b => {
                    const songCt = (b.submittedSongs||[]).length;
                    return (
                      <tr key={b.id} onClick={()=>onSelectBrief(b)} style={{cursor:"pointer"}}>
                        <td style={{padding:"11px 14px",minWidth:160}}>
                          <div style={{fontWeight:500,fontSize:13}}>{b.title}</div>
                          {b.placement && <div style={{fontSize:11,color:"var(--text-3)",marginTop:1}}>{b.placement}</div>}
                        </td>
                        <td style={{padding:"11px 14px",fontSize:12,color:"var(--text-2)"}}>{b.client||"—"}</td>
                        <td style={{padding:"11px 14px",fontSize:12,color:"var(--text-3)"}}>{b.deadline||"—"}</td>
                        <td style={{padding:"11px 14px"}}><StatusBadge status={b.status}/></td>
                        <td style={{padding:"11px 14px",fontSize:12,color:songCt>0?"var(--accent)":"var(--text-3)"}}>
                          {songCt>0?`${songCt} song${songCt!==1?"s":""}` : "—"}
                        </td>
                        <td style={{padding:"11px 14px",fontSize:12,fontWeight:b.confirmedFee?600:400,color:b.confirmedFee?"#059669":"var(--text-3)"}}>
                          {b.confirmedFee?"$"+b.confirmedFee.toLocaleString():"—"}
                        </td>
                        <td style={{padding:"11px 14px",fontSize:12,color:"var(--text-3)",maxWidth:240}}>
                          <div style={{overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}>{b.outcomeNotes||"—"}</div>
                        </td>
                      </tr>
                    );
                  })}
                </tbody>
              </table>
            </div>
          ) : (
            <div style={{padding:48,textAlign:"center",color:"var(--text-3)",fontSize:13,border:"1px dashed var(--border)",borderRadius:10}}>
              No {historyFilter!=="All"?historyFilter.toLowerCase()+" ":""}briefs yet.
            </div>
          )}
        </div>
      )}

    </div>
  );
}

// ─── Releases Page ────────────────────────────────────────────────────────────

function ReleasesPage() {
  const labels = { metadata:"Metadata Complete", artwork:"Artwork Delivered", audio:"Audio Mastered", isrc:"ISRC Registered", upc:"UPC Assigned", pitchSubmitted:"DSP Pitch Submitted" };
  return (
    <div className="page-content page-fade">
      <div style={{ display:"flex", flexDirection:"column", gap:16 }}>
        {RELEASES.map(r => {
          const items = Object.entries(r.checklist);
          const done  = items.filter(([,v])=>v).length;
          const pct   = Math.round(done/items.length*100);
          return (
            <div key={r.id} className="release-card">
              <div style={{ display:"flex", justifyContent:"space-between", alignItems:"flex-start", marginBottom:16 }}>
                <div>
                  <div style={{ fontWeight:700, fontSize:18, letterSpacing:"-0.02em" }}>{r.title}</div>
                  <div style={{ fontSize:13, color:"var(--text-3)", marginTop:3 }}>{r.type} · {r.distributor} · {r.date}</div>
                </div>
                <StatusBadge status={r.status} />
              </div>
              <div style={{ display:"flex", alignItems:"center", gap:12, marginBottom:18 }}>
                <div style={{ flex:1, height:6, borderRadius:3, background:"var(--border)", overflow:"hidden" }}>
                  <div style={{ width:`${pct}%`, height:"100%", background: pct===100?"#059669":"var(--accent)", borderRadius:3, transition:"width 0.3s" }}></div>
                </div>
                <span className="mono" style={{ fontSize:13, fontWeight:700, color: pct===100?"#059669":"var(--accent)", minWidth:36 }}>{pct}%</span>
              </div>
              <div style={{ display:"grid", gridTemplateColumns:"repeat(auto-fill,minmax(196px,1fr))", gap:8 }}>
                {items.map(([key,val]) => (
                  <div key={key} style={{ display:"flex", alignItems:"center", gap:8, fontSize:13 }}>
                    <span style={{ color: val?"#059669":"var(--border)", fontSize:15 }}>{val?"●":"○"}</span>
                    <span style={{ color: val?"var(--text)":"var(--text-3)" }}>{labels[key]}</span>
                  </div>
                ))}
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

// ─── Publishers Page ──────────────────────────────────────────────────────────

function PublishersPage({ search, publishers: publishersProp, collabs: collabsProp, songs: songsProp, onSelectPublisher, onSelectSong }) {
  const publishers = publishersProp || PUBLISHERS;
  const collabs    = collabsProp    || COLLABS;
  const songs      = songsProp      || SONGS;
  const [filter, setFilter] = useState2("All");
  const [selId,  setSelId]  = useState2(publishers[0]?.id);
  const [sortAZ, setSortAZ] = useState2(null);

  const incompleteCount = publishers.filter(p => !isPublisherComplete(p)).length;

  const filtered = useMemo2(() => {
    let list = publishers;
    if (filter === "Incomplete") list = list.filter(p => !isPublisherComplete(p));
    if (search) {
      const q = search.toLowerCase();
      list = list.filter(p =>
        p.name.toLowerCase().includes(q) || (p.type||"").toLowerCase().includes(q) ||
        (p.pro||"").toLowerCase().includes(q) || (p.address||"").toLowerCase().includes(q)
      );
    }
    if (sortAZ === "asc")  list = [...list].sort((a,b) => a.name.localeCompare(b.name));
    if (sortAZ === "desc") list = [...list].sort((a,b) => b.name.localeCompare(a.name));
    return list;
  }, [search, publishers, filter, sortAZ]);

  const pub = publishers.find(p => p.id === selId) || filtered[0];

  const rosterCollabs = useMemo2(() =>
    pub ? collabs.filter(c => (pub.roster||[]).includes(c.id)) : [],
    [pub, collabs]
  );

  const pubSongs = useMemo2(() =>
    pub ? songs.filter(s =>
      s.publishingOwner === pub.name ||
      s.splits.some(sp => rosterCollabs.some(c => c.id === sp.collabId || c.name === sp.name))
    ) : [],
    [pub, rosterCollabs, songs]
  );

  return (
    <div className="page-content page-fade">
      <div className="filter-bar" style={{ marginBottom:16 }}>
        {["All","Incomplete"].map(f => (
          <button key={f} className={"filter-chip"+(filter===f?" active":"")} onClick={() => setFilter(f)}>
            {f}
            {f === "Incomplete" && incompleteCount > 0 && (
              <span style={{ marginLeft:4, background:"#d97706", color:"#fff", borderRadius:8, padding:"0 5px", fontSize:9 }}>{incompleteCount}</span>
            )}
          </button>
        ))}
        <div style={{ marginLeft:"auto" }}>
          <button
            onClick={() => setSortAZ(s => s === "asc" ? "desc" : s === "desc" ? null : "asc")}
            style={{ fontSize:11, padding:"3px 9px", borderRadius:5, border:"1px solid var(--border)", background: sortAZ ? "var(--accent-dim)" : "var(--bg-2)", color: sortAZ ? "var(--accent-text)" : "var(--text-2)", cursor:"pointer", fontWeight: sortAZ ? 600 : 400 }}
          >
            {sortAZ === "asc" ? "A → Z" : sortAZ === "desc" ? "Z → A" : "A–Z"}
          </button>
        </div>
      </div>

      <div className="splits-layout">
        {/* Left: publisher list */}
        <div className="splits-songlist">
          <div className="panel-header" style={{ fontSize:12 }}>Publishers ({filtered.length})</div>
          {filtered.map(p => {
            const tc = PUB_TYPE_COLORS[p.type] || { bg:"#f3f4f6", color:"#6b7280" };
            const rc = collabs.filter(c => (p.roster||[]).includes(c.id));
            return (
              <div key={p.id} className={"split-song-item"+(p.id===selId?" active":"")} onClick={() => setSelId(p.id)}>
                <div style={{ flex:1, minWidth:0 }}>
                  <div style={{ fontWeight:500, fontSize:12.5, overflow:"hidden", textOverflow:"ellipsis", whiteSpace:"nowrap" }}>{p.name}</div>
                  <div style={{ fontSize:10, marginTop:1, color:"var(--text-3)" }}>{rc.length} collab{rc.length!==1?"s":""}</div>
                </div>
                <span style={{ fontSize:9.5, padding:"1px 6px", borderRadius:4, background:tc.bg, color:tc.color, fontWeight:500, flexShrink:0 }}>{p.type}</span>
              </div>
            );
          })}
        </div>

        {/* Right: publisher detail */}
        {pub && (
          <div className="splits-detail">
            <div className="panel-header" style={{ padding:"14px 20px" }}>
              <div>
                <span style={{ fontWeight:600, fontSize:15 }}>{pub.name}</span>
                {(pub.pro || pub.ipi) && (
                  <span style={{ marginLeft:8, fontSize:11, color:"var(--text-3)" }}>
                    {pub.pro}{pub.ipi ? ` · IPI ${pub.ipi}` : ""}
                  </span>
                )}
              </div>
              <button onClick={() => onSelectPublisher(pub)} className="btn-ghost" style={{ fontSize:12 }}>Edit →</button>
            </div>

            <div style={{ padding:"20px" }}>
              {/* Collaborators */}
              <div style={{ fontSize:11, fontWeight:600, color:"var(--text-3)", textTransform:"uppercase", letterSpacing:"0.06em", marginBottom:10 }}>
                Collaborators ({rosterCollabs.length})
              </div>
              {rosterCollabs.length > 0 ? (
                <table className="data-table" style={{ marginBottom:28 }}>
                  <thead><tr><th>Name</th><th>Role</th><th>PRO</th><th>IPI</th></tr></thead>
                  <tbody>
                    {rosterCollabs.map(c => (
                      <tr key={c.id}>
                        <td style={{ fontWeight:500 }}>{c.name}</td>
                        <td style={{ color:"var(--text-3)", fontSize:12 }}>{c.role || "—"}</td>
                        <td style={{ fontSize:12 }}>{c.pro || "—"}</td>
                        <td className="mono" style={{ fontSize:11.5, color:"var(--text-3)" }}>{c.ipi || "—"}</td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              ) : (
                <div style={{ fontSize:12.5, color:"var(--text-3)", marginBottom:28 }}>No collaborators linked.</div>
              )}

              {/* Songs */}
              <div style={{ fontSize:11, fontWeight:600, color:"var(--text-3)", textTransform:"uppercase", letterSpacing:"0.06em", marginBottom:10 }}>
                Songs ({pubSongs.length})
              </div>
              {pubSongs.length > 0 ? (
                <table className="data-table">
                  <thead><tr><th>Title</th><th>Artist</th><th>Writer</th><th>Writer %</th><th>Publisher %</th></tr></thead>
                  <tbody>
                    {pubSongs.flatMap(s => {
                      const rosterSplits = s.splits.filter(sp => rosterCollabs.some(c => c.id === sp.collabId || c.name === sp.name));
                      return rosterSplits.map((sp, i) => {
                        const collab = rosterCollabs.find(c => c.id === sp.collabId || c.name === sp.name);
                        return (
                          <tr key={`${s.id}-${i}`} onClick={() => onSelectSong && onSelectSong(s)} style={{ cursor: onSelectSong ? "pointer" : "default" }}>
                            <td style={{ fontWeight:500 }}>{i === 0 ? s.title : ""}</td>
                            <td style={{ color:"var(--text-3)", fontSize:12 }}>{i === 0 ? (s.artist || "—") : ""}</td>
                            <td style={{ fontSize:12 }}>{collab ? collab.name : sp.name || "—"}</td>
                            <td className="mono" style={{ fontSize:12 }}>{Number(sp.writer||0)}%</td>
                            <td className="mono" style={{ fontSize:12 }}>{Number(sp.publisher||0)}%</td>
                          </tr>
                        );
                      });
                    })}
                  </tbody>
                </table>
              ) : (
                <div style={{ fontSize:12.5, color:"var(--text-3)" }}>No songs linked.</div>
              )}
            </div>
          </div>
        )}
      </div>

    </div>
  );
}

// ─── Analytics Page ───────────────────────────────────────────────────────────

function AnalyticsPage({ songs, briefs }) {
  const statusGroups = [
    {label:"Released",    color:"#059669"}, {label:"Mastered", color:"#2563eb"},
    {label:"In Progress", color:"#d97706"}, {label:"Mixing",   color:"#d97706"},
    {label:"Demo",        color:"#9ca3af"},
  ].map(s => ({...s, count:songs.filter(x=>x.status===s.label).length}));
  const maxStatus = Math.max(...statusGroups.map(s=>s.count), 1);

  const genreMap = {};
  songs.forEach(s => { const g=s.genre.split("/")[0].trim(); genreMap[g]=(genreMap[g]||0)+1; });
  const genres = Object.entries(genreMap).map(([l,c])=>({label:l,count:c})).sort((a,b)=>b.count-a.count);
  const GCOLS = ["#7c6fff","#f472b6","#22c55e","#60a5fa","#f59e0b","#e879f9","#2dd4bf"];
  let donutPos=0;
  const donutSlices = genres.map((g,i)=>{
    const pct=(g.count/songs.length)*100; const start=donutPos; donutPos+=pct;
    return {...g,pct,start,color:GCOLS[i%GCOLS.length]};
  });

  const collabShares = {};
  songs.forEach(s=>s.splits.forEach(sp=>{
    const n = getSplitName(sp, COLLABS);
    collabShares[n]=(collabShares[n]||0)+sp.writer/100*s.ownershipPct;
  }));
  const topCollabs = Object.entries(collabShares).map(([n,s])=>({name:n,share:Math.round(s)})).sort((a,b)=>b.share-a.share).slice(0,5);
  const maxShare = Math.max(...topCollabs.map(c=>c.share),1);

  const bpmBuckets = [
    {label:"<80",  count:songs.filter(s=>s.bpm<80).length},
    {label:"80–100",count:songs.filter(s=>s.bpm>=80&&s.bpm<100).length},
    {label:"100–120",count:songs.filter(s=>s.bpm>=100&&s.bpm<120).length},
    {label:"120–140",count:songs.filter(s=>s.bpm>=120&&s.bpm<140).length},
    {label:"140+", count:songs.filter(s=>s.bpm>=140).length},
  ];
  const maxBPM = Math.max(...bpmBuckets.map(b=>b.count),1);

  const syncTotal   = briefs.filter(b=>!["Landed","Passed","Expired"].includes(b.status)).reduce((a,b)=>a+(b.budgetEstimate||0),0);
  const syncCleared = briefs.filter(b=>b.status==="Landed").reduce((a,b)=>a+(b.confirmedFee||b.budgetEstimate||0),0);
  const avgOwn = Math.round(songs.reduce((a,s)=>a+s.ownershipPct,0)/songs.length);

  return (
    <div className="page-content page-fade">
      {/* KPIs */}
      <div className="stat-grid" style={{marginBottom:22}}>
        {[
          {label:"Sync Pipeline",  value:"$"+syncTotal.toLocaleString(), sub:"total potential value",      accent:"var(--accent)"},
          {label:"Landed Revenue",  value:"$"+syncCleared.toLocaleString(),sub:"confirmed sync licensing",   accent:"#059669"},
          {label:"Sync Ready",     value:`${songs.filter(s=>s.syncReady).length}/${songs.length}`, sub:"tracks cleared for licensing", accent:"#2563eb"},
          {label:"Avg Ownership",  value:avgOwn+"%",                      sub:"per track across catalog",   accent:"#d97706"},
        ].map((k,i)=>(
          <div key={i} className="stat-card">
            <div style={{position:"absolute",top:0,left:0,width:3,height:"100%",background:k.accent,borderRadius:"6px 0 0 6px",opacity:0.7}}></div>
            <div style={{fontSize:28,fontWeight:700,color:k.accent,letterSpacing:"-0.02em"}}>{k.value}</div>
            <div style={{fontSize:13,fontWeight:600,marginTop:6}}>{k.label}</div>
            <div style={{fontSize:11,color:"var(--text-3)",marginTop:2}}>{k.sub}</div>
          </div>
        ))}
      </div>

      <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:14,marginBottom:14}}>
        {/* Status breakdown */}
        <div className="dash-panel">
          <div className="panel-header"><span>Catalog by Status</span><span style={{fontSize:11,color:"var(--text-3)"}}>{songs.length} total</span></div>
          <div style={{padding:"16px 20px",display:"flex",flexDirection:"column",gap:12}}>
            {statusGroups.filter(s=>s.count>0).map(s=>(
              <div key={s.label}>
                <div style={{display:"flex",justifyContent:"space-between",fontSize:12,marginBottom:5}}>
                  <span style={{color:"var(--text-2)"}}>{s.label}</span>
                  <span className="mono" style={{fontWeight:600}}>{s.count}</span>
                </div>
                <div style={{height:8,borderRadius:4,background:"var(--border)",overflow:"hidden"}}>
                  <div style={{width:`${(s.count/maxStatus)*100}%`,height:"100%",background:s.color,borderRadius:4,transition:"width 0.4s ease"}}></div>
                </div>
              </div>
            ))}
          </div>
        </div>

        {/* Genre donut */}
        <div className="dash-panel">
          <div className="panel-header"><span>Genre Breakdown</span></div>
          <div style={{padding:"16px 20px",display:"flex",gap:20,alignItems:"center"}}>
            <div style={{position:"relative",width:110,height:110,flexShrink:0}}>
              <div style={{width:110,height:110,borderRadius:"50%",background:`conic-gradient(${donutSlices.map(s=>`${s.color} ${s.start}% ${s.start+s.pct}%`).join(",")})`}}></div>
              <div style={{position:"absolute",inset:"27%",borderRadius:"50%",background:"var(--card)",display:"flex",alignItems:"center",justifyContent:"center",fontSize:13,fontWeight:700,color:"var(--text)"}}>{songs.length}</div>
            </div>
            <div style={{flex:1,display:"flex",flexDirection:"column",gap:7}}>
              {donutSlices.map((s,i)=>(
                <div key={i} style={{display:"flex",alignItems:"center",gap:7,fontSize:12}}>
                  <div style={{width:9,height:9,borderRadius:2,background:s.color,flexShrink:0}}></div>
                  <span style={{flex:1,color:"var(--text-2)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}>{s.label}</span>
                  <span className="mono" style={{fontWeight:600}}>{s.count}</span>
                </div>
              ))}
            </div>
          </div>
        </div>
      </div>

      <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:14,marginBottom:14}}>
        {/* Collaborator shares */}
        <div className="dash-panel">
          <div className="panel-header"><span>Collaborator Catalog Share</span></div>
          <div style={{padding:"16px 20px",display:"flex",flexDirection:"column",gap:12}}>
            {topCollabs.map((c,i)=>(
              <div key={i}>
                <div style={{display:"flex",justifyContent:"space-between",fontSize:12,marginBottom:5,alignItems:"center"}}>
                  <div style={{display:"flex",alignItems:"center",gap:7}}>
                    <div style={{width:20,height:20,borderRadius:"50%",background:SPLIT_COLORS[i%SPLIT_COLORS.length],display:"flex",alignItems:"center",justifyContent:"center",fontSize:9,fontWeight:700,color:"#fff"}}>{c.name.charAt(0)}</div>
                    <span style={{color:"var(--text-2)"}}>{c.name.split(" ")[0]}</span>
                  </div>
                  <span className="mono" style={{fontWeight:600}}>{c.share}%</span>
                </div>
                <div style={{height:8,borderRadius:4,background:"var(--border)",overflow:"hidden"}}>
                  <div style={{width:`${(c.share/maxShare)*100}%`,height:"100%",background:SPLIT_COLORS[i%SPLIT_COLORS.length],borderRadius:4}}></div>
                </div>
              </div>
            ))}
          </div>
        </div>

        {/* BPM histogram */}
        <div className="dash-panel">
          <div className="panel-header"><span>BPM Distribution</span></div>
          <div style={{padding:"16px 20px 12px",display:"flex",alignItems:"flex-end",gap:10,height:152}}>
            {bpmBuckets.map((b,i)=>(
              <div key={i} style={{flex:1,display:"flex",flexDirection:"column",alignItems:"center",gap:4,height:"100%"}}>
                <div style={{flex:1,display:"flex",alignItems:"flex-end",width:"100%"}}>
                  <div style={{width:"100%",height:b.count>0?`${(b.count/maxBPM)*88}%`:"4px",background:b.count>0?"var(--accent)":"var(--border)",borderRadius:"4px 4px 0 0",opacity:0.85,minHeight:b.count>0?6:0,transition:"height 0.3s"}}></div>
                </div>
                <div style={{fontSize:9.5,color:"var(--text-3)",textAlign:"center",whiteSpace:"nowrap"}}>{b.label}</div>
                {b.count>0&&<div className="mono" style={{fontSize:11,fontWeight:600,color:"var(--text-2)"}}>{b.count}</div>}
              </div>
            ))}
          </div>
        </div>
      </div>

      {/* Sync pipeline */}
      <div className="dash-panel">
        <div className="panel-header">
          <span>Sync Licensing Pipeline</span>
          <span style={{fontSize:12,color:"var(--text-3)"}}>Potential: {syncTotal>0?"$"+syncTotal.toLocaleString():"—"}</span>
        </div>
        <div style={{padding:"16px 20px"}}>
          {briefs.filter(b=>!["Landed","Passed","Expired"].includes(b.status)).length>0 ? (
            <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(180px,1fr))",gap:12}}>
              {briefs.filter(b=>!["Landed","Passed","Expired"].includes(b.status)).map(b=>{
                const pct=syncTotal>0?((b.budgetEstimate||0)/syncTotal)*100:0;
                const sc={"Active":"#7c3aed","Submitted":"#2563eb","In Review":"#9d174d","Shortlisted":"#d97706"};
                return(
                  <div key={b.id} style={{padding:14,background:"var(--bg-2)",borderRadius:8,border:"1px solid var(--border)"}}>
                    <div style={{fontWeight:600,fontSize:13,marginBottom:2,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}>{b.client||b.title}</div>
                    <div style={{fontSize:11,color:"var(--text-3)",marginBottom:10,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}>{b.title}</div>
                    <div style={{height:6,borderRadius:3,background:"var(--border)",overflow:"hidden",marginBottom:8}}>
                      <div style={{width:`${pct}%`,height:"100%",background:sc[b.status]||"var(--accent)",borderRadius:3}}></div>
                    </div>
                    <div style={{display:"flex",justifyContent:"space-between",alignItems:"center"}}>
                      <StatusBadge status={b.status}/>
                      <span style={{fontSize:12,fontWeight:600,color:"#059669"}}>{b.budget||"—"}</span>
                    </div>
                  </div>
                );
              })}
            </div>
          ):(
            <div style={{padding:"20px 0",textAlign:"center",color:"var(--text-3)",fontSize:13}}>No active briefs in pipeline</div>
          )}
        </div>
      </div>
    </div>
  );
}

// ─── Import / Export Page ─────────────────────────────────────────────────────

function ImportExportPage({ songs, setSongs, campaigns, pitchEntries, contacts, onAddPitchEntry, onUpdateContact, collabs, publishers, profile, onUpdateSong }) {
  const [importFile,    setImportFile]    = useState2(null);
  const [importHeaders, setImportHeaders] = useState2([]);
  const [importAllRows, setImportAllRows] = useState2([]);
  const [columnMap,     setColumnMap]     = useState2({});
  const [importStep,    setImportStep]    = useState2("idle");
  const [importCount,   setImportCount]   = useState2(0);
  const fileInputRef = useRef2(null);

  const [pitchImportFile,    setPitchImportFile]    = useState2(null);
  const [pitchImportStep,    setPitchImportStep]    = useState2("idle");
  const [pitchImportRows,    setPitchImportRows]    = useState2([]);
  const [pitchImportResults, setPitchImportResults] = useState2(null);
  const pitchFileInputRef = useRef2(null);

  const [cwrStep,     setCwrStep]     = useState2("idle");
  const [cwrResult,   setCwrResult]   = useState2(null);
  const [cwrSociety,  setCwrSociety]  = useState2("008"); // APRA AMCOS default
  const [cwrVersion,  setCwrVersion]  = useState2("2.1"); // driven by society selection
  const [cwrSeqNum,   setCwrSeqNum]   = useState2(1);

  const cwrValidation = useMemo2(() => {
    if (typeof cwrValidateAll === "undefined") return { valid:true, errors:[], profileErrors:[], groupedSongErrors:[], songsWithErrors:[], eligibleSongs:songs };
    const result         = cwrValidateAll(songs, collabs || [], profile || {});
    const profileErrors  = result.errors.filter(e => !e.song);
    const songErrors     = result.errors.filter(e =>  e.song);
    const songsWithErrors = [...new Set(songErrors.map(e => e.song.id))];
    const eligibleSongs  = songs.filter(s => !songsWithErrors.includes(s.id));
    const songErrorMap   = {};
    songErrors.forEach(({ song, error }) => {
      if (!songErrorMap[song.id]) songErrorMap[song.id] = { song, errors: [] };
      songErrorMap[song.id].errors.push(error);
    });
    return { ...result, profileErrors, groupedSongErrors: Object.values(songErrorMap), songsWithErrors, eligibleSongs };
  }, [songs, collabs, profile]);

  const handleCwrExport = () => {
    const { eligibleSongs } = cwrValidation;
    const result = cwrExportSongs(eligibleSongs, collabs || [], publishers || [], profile || {}, {
      version: cwrVersion,
      receiverCode: cwrSociety,
      seqNum: cwrSeqNum,
    });
    const blob = new Blob([result.content], { type: "text/plain;charset=us-ascii" });
    const url  = URL.createObjectURL(blob);
    const a    = document.createElement("a");
    a.href     = url;
    a.download = result.filename;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
    if (onUpdateSong) {
      eligibleSongs.forEach(song => onUpdateSong(song.id, { cwrExportedAt: Date.now(), cwrFileRef: result.filename }));
    }
    setCwrResult(result);
    setCwrStep("done");
  };

  const CAMPAIGN_NAME_MAP = {
    "cameron taylor library": "cameron-library",
    "cameron taylor music":   "cameron-library",
    "cameron library":        "cameron-library",
    "kyte publishing":        "kyte-publishing",
    "kyte":                   "kyte-publishing",
  };

  const PITCH_STATUS_MAP = {
    "not contacted":  "Not Contacted",
    "email sent":     "Pitched",
    "pitched":        "Pitched",
    "awaiting reply": "Following Up",
    "following up":   "Following Up",
    "in discussion":  "In Discussion",
    "deal":           "Signed",
    "signed":         "Signed",
    "no response":    "No Response",
    "passed":         "Passed",
  };

  const handlePitchFile = (e) => {
    const f = e.target.files[0]; if (!f) return;
    const reader = new FileReader();
    reader.onload = (ev) => {
      const lines = ev.target.result.trim().split("\n");
      if (lines.length < 2) return;
      const headers = parseLine(lines[0]).map(h => h.toLowerCase().trim());
      const col = (name) => headers.indexOf(name);
      const rows = lines.slice(1).map(parseLine).filter(r => r.some(v => v)).map(row => {
        const agency      = (row[col("agency")] || "").trim();
        const campaignRaw = (row[col("campaign")] || "").trim();
        const statusRaw   = (row[col("status")] || "").trim();
        const notes       = (row[col("notes")] || "").trim();
        const subWindow   = (row[col("submission window")] || "").trim();
        const warmIntro   = (row[col("requires warm intro")] || "").trim();
        const dateStr     = (row[col("date contacted")] || "").trim();
        const campaignId  = CAMPAIGN_NAME_MAP[campaignRaw.toLowerCase()] || null;
        const contact     = agency ? (contacts || []).find(c => c.name?.toLowerCase() === agency.toLowerCase()) : null;
        const status      = PITCH_STATUS_MAP[statusRaw.toLowerCase()] || "Not Contacted";
        const alreadyExists = contact && campaignId && (pitchEntries || []).some(e => e.contactId === contact.id && e.campaignId === campaignId);
        const skip = !agency || !campaignId || !contact || alreadyExists;
        const skipReason = !agency ? "No agency name" : !campaignId ? `Unknown campaign: "${campaignRaw}"` : !contact ? "No matching contact" : "Already in campaign";
        return { agency, campaignId, campaignRaw, status, notes, subWindow, dateStr,
          requiresWarmIntro: ["yes","true","1"].includes(warmIntro.toLowerCase()),
          contact, alreadyExists, skip, skipReason };
      }).filter(r => r.agency);
      setPitchImportRows(rows);
      setPitchImportFile({ name: f.name, count: rows.length });
      setPitchImportStep("preview");
    };
    reader.readAsText(f);
    e.target.value = "";
  };

  const runPitchImport = async () => {
    let created = 0, updated = 0, skipped = 0;
    for (let i = 0; i < pitchImportRows.length; i++) {
      const row = pitchImportRows[i];
      if (row.skip) { skipped++; continue; }
      const entry = {
        id: String(Date.now() + i),
        contactId: row.contact.id,
        campaignId: row.campaignId,
        status: row.status,
        customNote: row.notes,
        followUpDate: null,
        followUpDone: false,
        pitchHistory: row.status !== "Not Contacted"
          ? [{ type: "pitched", date: row.dateStr || new Date().toISOString().split("T")[0], note: "Imported from outreach tracker", sentVia: "email" }]
          : [],
        createdAt: Date.now(),
        updatedAt: Date.now(),
      };
      await onAddPitchEntry(row.campaignId, entry);
      created++;
      if (row.subWindow || row.requiresWarmIntro) {
        const contactUpdates = {};
        if (row.subWindow) contactUpdates.submissionWindow = row.subWindow;
        if (row.requiresWarmIntro) contactUpdates.requiresWarmIntro = true;
        onUpdateContact(row.contact.id, contactUpdates);
        updated++;
      }
    }
    setPitchImportResults({ created, updated, skipped });
    setPitchImportStep("done");
  };

  const EXPORT_PRESETS = [
    {
      id:"full", name:"Full Catalog", accent:"var(--accent)",
      description:"All song metadata including new fields. Use for backups or migrating data between systems.",
      fields:"Title, Version, Artist, Album, ISRC, ISWC, BPM, Key, Genre, Duration, Status, Sync Ready, Stems, Instrumental, Release Date, International Title, Master, Publisher, Own%, PRO, Moods, Splits, Notes",
      action: () => exportSongsCSV(songs),
      count: `${songs.length} songs`,
    },
    {
      id:"sync", name:"Sync Brief", accent:"#059669",
      description:"Curated fields for sync supervisors and music libraries. Sync-ready tracks only.",
      fields:"Title, Artist, Key, BPM, Genre, Moods, Duration, Sync Ready, Stems, Instrumental, ISRC, Status, Notes",
      action: () => exportSyncBriefCSV(songs),
      count: `${songs.filter(s=>s.syncReady).length} sync-ready`,
    },
    {
      id:"kyte", name:"KYTE Sub-Pub Registration", accent:"#2563eb",
      description:"Multi-row format for KYTE sub-publisher registration. One row per writer per song, with CISAC codes.",
      fields:"n°, Title, International Title, Artist, IPI, Role, Composer Name, PRO CISAC, PR%, MRO CISAC, MR%, Control, Publisher, ISWC, Album, ISRC, Release Date",
      action: () => exportKYTECSV(songs),
      count: `${songs.length} songs`,
    },
  ];

  const APP_FIELDS = [
    {value:"",label:"— Ignore —"},
    {value:"title",label:"Title"},{value:"version",label:"Version"},
    {value:"artist",label:"Artist"},{value:"album",label:"Album"},
    {value:"isrc",label:"ISRC"},{value:"iswc",label:"ISWC"},
    {value:"bpm",label:"BPM"},{value:"key",label:"Key"},
    {value:"genre",label:"Genre"},{value:"duration",label:"Duration"},
    {value:"status",label:"Status"},{value:"syncReady",label:"Sync Ready (Yes/No)"},
    {value:"stemsAvailable",label:"Stems Available (Yes/No)"},{value:"instrumental",label:"Instrumental (Yes/No)"},
    {value:"releaseDate",label:"Release Date"},{value:"masterOwner",label:"Master Owner"},
    {value:"publishingOwner",label:"Publishing Owner"},{value:"ownershipPct",label:"Ownership %"},
    {value:"pro",label:"PRO"},{value:"moods",label:"Moods (semicolon-separated)"},
    {value:"notes",label:"Notes"},{value:"internationalTitle",label:"International Title"},
  ];

  const parseLine = (line) => {
    const vals=[]; let cur=""; let inQ=false;
    for (let c=0;c<line.length;c++){
      const ch=line[c];
      if(ch==='"'){inQ=!inQ;}
      else if(ch===','&&!inQ){vals.push(cur);cur="";}
      else{cur+=ch;}
    }
    vals.push(cur);
    return vals.map(v=>v.replace(/^"|"$/g,"").trim());
  };

  const autoMatch = (headers) => {
    const map={};
    const norm = s => s.toLowerCase().replace(/[^a-z0-9]/g,"");
    const lookup = {
      title:"title",version:"version",artist:"artist",album:"album",
      isrc:"isrc",iswc:"iswc",bpm:"bpm",key:"key",genre:"genre",
      duration:"duration",status:"status",syncready:"syncReady",
      stemsavailable:"stemsAvailable",instrumental:"instrumental",
      releasedate:"releaseDate",masterowner:"masterOwner",
      publishingowner:"publishingOwner",ownership:"ownershipPct",
      ownershipPct:"ownershipPct",pro:"pro",moods:"moods",notes:"notes",
      internationaltitle:"internationalTitle",
    };
    headers.forEach((h,i)=>{ map[i]=lookup[norm(h)]||""; });
    return map;
  };

  const handleFile = (e) => {
    const f=e.target.files[0]; if(!f) return;
    const reader=new FileReader();
    reader.onload=(ev)=>{
      const lines=ev.target.result.trim().split("\n");
      if(lines.length<2) return;
      const headers=parseLine(lines[0]);
      const allRows=lines.slice(1).map(parseLine).filter(r=>r.some(v=>v));
      setImportHeaders(headers);
      setImportAllRows(allRows);
      setColumnMap(autoMatch(headers));
      setImportFile({name:f.name,count:allRows.length});
      setImportStep("mapping");
    };
    reader.readAsText(f);
    e.target.value="";
  };

  const runImport = () => {
    const boolVal = v => v.toLowerCase()==="yes"||v==="true"||v==="1";
    const imported = importAllRows.map((row,idx)=>{
      const song={
        id:Date.now()+idx, title:"Untitled", version:"Original", isrc:"", iswc:"",
        bpm:120, key:"C Major", genre:"", duration:"", status:"Demo",
        syncReady:false, stemsAvailable:false, instrumental:false,
        releaseDate:null, masterOwner:"", publishingOwner:"", ownershipPct:100,
        pro:"", moods:[], notes:"", artist:"", album:"", internationalTitle:"",
        artworkHue:Math.floor(Math.random()*360),
        splits:[{name:"",role:"Writer",writer:100,publisher:100}],
      };
      Object.entries(columnMap).forEach(([ci,field])=>{
        if(!field) return;
        const val=(row[parseInt(ci)]||"").trim();
        if(field==="bpm") song[field]=parseInt(val)||0;
        else if(field==="ownershipPct") song[field]=parseFloat(val)||0;
        else if(["syncReady","stemsAvailable","instrumental"].includes(field)) song[field]=boolVal(val);
        else if(field==="moods") song[field]=val?val.split(";").map(m=>m.trim()).filter(Boolean):[];
        else if(field==="releaseDate") song[field]=val||null;
        else song[field]=val;
      });
      return song;
    }).filter(s=>s.title&&s.title!=="Untitled");
    setSongs(prev=>[...prev,...imported]);
    setImportCount(imported.length);
    setImportStep("done");
  };

  const sel = {width:"100%",padding:"5px 8px",border:"1px solid var(--border)",borderRadius:5,background:"var(--bg-2)",color:"var(--text)",fontSize:12,fontFamily:"var(--font)",outline:"none"};

  return (
    <div className="page-content page-fade">

      {/* Export */}
      <div style={{marginBottom:36}}>
        <div style={{fontSize:16,fontWeight:700,letterSpacing:"-0.01em",marginBottom:3}}>Export</div>
        <div style={{fontSize:13,color:"var(--text-3)",marginBottom:18}}>Download your catalog in different formats.</div>
        <div style={{display:"grid",gridTemplateColumns:"repeat(3,1fr)",gap:14}}>
          {EXPORT_PRESETS.map(p=>(
            <div key={p.id} className="dash-panel" style={{display:"flex",flexDirection:"column"}}>
              <div style={{padding:"16px 18px",flex:1}}>
                <div style={{display:"flex",alignItems:"center",gap:8,marginBottom:10}}>
                  <div style={{width:8,height:8,borderRadius:"50%",background:p.accent,flexShrink:0}}></div>
                  <div style={{fontWeight:700,fontSize:14}}>{p.name}</div>
                </div>
                <div style={{fontSize:12,color:"var(--text-3)",lineHeight:1.55,marginBottom:12}}>{p.description}</div>
                <div style={{fontSize:10.5,color:"var(--text-3)",background:"var(--bg-2)",border:"1px solid var(--border)",borderRadius:5,padding:"7px 9px",lineHeight:1.65}}>
                  {p.fields}
                </div>
              </div>
              <div style={{padding:"10px 18px 14px",borderTop:"1px solid var(--border-sub)",display:"flex",justifyContent:"space-between",alignItems:"center"}}>
                <span style={{fontSize:11,color:"var(--text-3)"}}>{p.count}</span>
                <button className="btn-accent" onClick={p.action} style={{fontSize:12}}>↓ Download</button>
              </div>
            </div>
          ))}
        </div>
      </div>

      {/* CWR Export [PUBLISHER] */}
      <div style={{marginBottom:36}}>
        <div style={{display:"flex",alignItems:"center",gap:8,marginBottom:3}}>
          <div style={{fontSize:16,fontWeight:700,letterSpacing:"-0.01em"}}>CWR Export</div>
          <span style={{fontSize:9.5,fontWeight:700,background:"#7c3aed",color:"#fff",padding:"1px 6px",borderRadius:4,letterSpacing:"0.04em"}}>PUBLISHER</span>
        </div>
        <div style={{fontSize:13,color:"var(--text-3)",marginBottom:18}}>
          Generate a CWR file for PRO registration with APRA AMCOS, ASCAP, BMI, PRS, and other CISAC members.
        </div>

        {/* Profile config warning */}
        {cwrValidation.profileErrors.length > 0 && (
          <div style={{background:"#fef3c7",border:"1px solid #fbbf24",borderRadius:8,padding:"12px 16px",marginBottom:16,fontSize:12,color:"#92400e",display:"flex",alignItems:"center",gap:8}}>
            <span>⚠</span>
            <span>{cwrValidation.profileErrors[0].error}</span>
          </div>
        )}

        {/* Per-song validation issues */}
        {cwrValidation.groupedSongErrors.length > 0 && (
          <div style={{background:"var(--bg-2)",border:"1px solid var(--border)",borderRadius:8,marginBottom:16}}>
            <div style={{padding:"9px 16px",borderBottom:"1px solid var(--border-sub)",fontSize:12,fontWeight:600,color:"var(--text-2)",display:"flex",gap:6,alignItems:"center"}}>
              <span style={{color:"#dc2626"}}>⚠</span>
              {cwrValidation.groupedSongErrors.length} song{cwrValidation.groupedSongErrors.length!==1?"s":""} with issues — will be skipped on export
            </div>
            <div style={{maxHeight:180,overflowY:"auto"}}>
              {cwrValidation.groupedSongErrors.map(({song,errors},i) => (
                <div key={i} style={{padding:"8px 16px",borderBottom:"1px solid var(--border-sub)",fontSize:12,display:"flex",gap:8,flexWrap:"wrap"}}>
                  <span style={{fontWeight:600,color:"var(--text)",flexShrink:0}}>{song.title}</span>
                  <span style={{color:"#dc2626"}}>{errors.join(" · ")}</span>
                </div>
              ))}
            </div>
          </div>
        )}

        {/* Society + version + seq controls */}
        <div className="dash-panel" style={{padding:"16px 18px",marginBottom:12}}>
          <div style={{display:"grid",gridTemplateColumns:"1fr auto auto",gap:12,alignItems:"end"}}>
            <div>
              <div style={{fontSize:11,fontWeight:600,color:"var(--text-3)",marginBottom:5,textTransform:"uppercase",letterSpacing:"0.04em"}}>Target Society</div>
              <select
                value={cwrSociety}
                onChange={e => {
                  const soc = (typeof CWR_SOCIETIES !== "undefined" ? CWR_SOCIETIES : []).find(s => s.code === e.target.value);
                  setCwrSociety(e.target.value);
                  if (soc) setCwrVersion(soc.defaultVersion);
                }}
                style={{width:"100%",padding:"6px 10px",borderRadius:7,border:"1px solid var(--border)",background:"var(--bg-2)",color:"var(--text)",fontSize:12.5,fontFamily:"var(--font)"}}
              >
                {(typeof CWR_SOCIETIES !== "undefined" ? CWR_SOCIETIES : []).map(s => (
                  <option key={s.code} value={s.code}>{s.name} — {s.territory}</option>
                ))}
              </select>
            </div>
            <div>
              <div style={{fontSize:11,fontWeight:600,color:"var(--text-3)",marginBottom:5,textTransform:"uppercase",letterSpacing:"0.04em"}}>Version</div>
              <select
                value={cwrVersion}
                onChange={e => setCwrVersion(e.target.value)}
                style={{padding:"6px 10px",borderRadius:7,border:"1px solid var(--border)",background:"var(--bg-2)",color:"var(--text)",fontSize:12.5,fontFamily:"var(--font)"}}
              >
                <option value="2.1">v2.1</option>
                <option value="2.2">v2.2</option>
              </select>
            </div>
            <div>
              <div style={{fontSize:11,fontWeight:600,color:"var(--text-3)",marginBottom:5,textTransform:"uppercase",letterSpacing:"0.04em"}}>Seq #</div>
              <input
                type="number"
                min={1}
                max={9999}
                value={cwrSeqNum}
                onChange={e => setCwrSeqNum(Math.max(1, parseInt(e.target.value)||1))}
                style={{width:70,padding:"6px 8px",borderRadius:7,border:"1px solid var(--border)",background:"var(--bg-2)",color:"var(--text)",fontSize:12.5,fontFamily:"monospace",textAlign:"center"}}
              />
            </div>
          </div>
          <div style={{marginTop:10,paddingTop:10,borderTop:"1px solid var(--border-sub)",display:"flex",alignItems:"center",justifyContent:"space-between",gap:12}}>
            <div>
              <div style={{fontWeight:600,fontSize:13}}>
                CWR {cwrVersion} — {(typeof CWR_SOCIETIES !== "undefined" ? CWR_SOCIETIES : []).find(s=>s.code===cwrSociety)?.name || cwrSociety}
              </div>
              <div style={{fontSize:12,color:"var(--text-3)",marginTop:2}}>
                {cwrValidation.eligibleSongs.length} song{cwrValidation.eligibleSongs.length!==1?"s":""} eligible
                {cwrValidation.songsWithErrors.length > 0 && ` · ${cwrValidation.songsWithErrors.length} skipped`}
                {" · "}filename: <span style={{fontFamily:"monospace",fontSize:11}}>{typeof cwrFilename!=="undefined" && cwrFilename((profile&&profile.cwrSenderId)||"MMV", cwrSeqNum, cwrSociety, cwrVersion)}</span>
              </div>
            </div>
            <button
              className="btn-accent"
              onClick={handleCwrExport}
              disabled={cwrValidation.profileErrors.length > 0 || cwrValidation.eligibleSongs.length === 0}
              style={{fontSize:12,flexShrink:0}}
            >
              ↓ Export CWR File
            </button>
          </div>
        </div>

        {/* Success banner */}
        {cwrStep === "done" && cwrResult && (
          <div style={{background:"#dcfce7",border:"1px solid #86efac",borderRadius:8,padding:"14px 18px",display:"flex",justifyContent:"space-between",alignItems:"center"}}>
            <div>
              <div style={{fontWeight:600,fontSize:13,color:"#166534"}}>✓ CWR file downloaded</div>
              <div style={{fontSize:12,color:"#166534",marginTop:2,fontFamily:"var(--mono)"}}>
                {cwrResult.filename} · {cwrResult.songCount} song{cwrResult.songCount!==1?"s":""} · {cwrResult.recordCount} records
              </div>
            </div>
            <button className="btn-ghost" onClick={() => setCwrStep("idle")} style={{fontSize:12}}>✕</button>
          </div>
        )}
      </div>

      {/* Import */}
      <div>
        <div style={{fontSize:16,fontWeight:700,letterSpacing:"-0.01em",marginBottom:3}}>Import</div>
        <div style={{fontSize:13,color:"var(--text-3)",marginBottom:18}}>Import songs from a CSV. Map columns to app fields before importing.</div>

        {importStep==="idle" && (
          <div
            onClick={()=>fileInputRef.current?.click()}
            style={{border:"2px dashed var(--border)",borderRadius:10,padding:"44px 24px",textAlign:"center",cursor:"pointer",background:"var(--bg-2)",transition:"all 0.15s"}}
            onMouseEnter={e=>{e.currentTarget.style.borderColor="var(--accent)";e.currentTarget.style.background="var(--accent-dim)";}}
            onMouseLeave={e=>{e.currentTarget.style.borderColor="var(--border)";e.currentTarget.style.background="var(--bg-2)";}}
          >
            <div style={{fontSize:26,marginBottom:10,color:"var(--text-3)"}}>↑</div>
            <div style={{fontWeight:600,fontSize:14,marginBottom:4}}>Upload CSV file</div>
            <div style={{fontSize:12,color:"var(--text-3)"}}>Click to browse · Columns are mapped before import</div>
          </div>
        )}

        {importStep==="mapping" && importFile && (
          <div className="table-wrap">
            <div style={{padding:"13px 18px",borderBottom:"1px solid var(--border)",display:"flex",justifyContent:"space-between",alignItems:"center"}}>
              <div>
                <div style={{fontWeight:600,fontSize:14}}>{importFile.name}</div>
                <div style={{fontSize:12,color:"var(--text-3)",marginTop:2}}>{importFile.count} rows · Map each column to an app field, or ignore it</div>
              </div>
              <button className="btn-ghost" style={{fontSize:11}} onClick={()=>{setImportStep("idle");setImportFile(null);}}>✕ Cancel</button>
            </div>
            <div style={{maxHeight:400,overflowY:"auto"}}>
              <table className="data-table">
                <thead><tr><th>CSV Column</th><th>Map to App Field</th><th>Preview (row 1)</th></tr></thead>
                <tbody>
                  {importHeaders.map((h,i)=>(
                    <tr key={i}>
                      <td style={{fontWeight:500,fontSize:13}}>{h}</td>
                      <td style={{width:220}}>
                        <select value={columnMap[i]||""} onChange={e=>setColumnMap(prev=>({...prev,[i]:e.target.value}))} style={sel}>
                          {APP_FIELDS.map(f=><option key={f.value} value={f.value}>{f.label}</option>)}
                        </select>
                      </td>
                      <td style={{fontSize:11,color:"var(--text-3)",fontFamily:"var(--mono)",maxWidth:180,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}>
                        {importAllRows[0]?.[i]||"—"}
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
            <div style={{padding:"12px 18px",borderTop:"1px solid var(--border)",display:"flex",justifyContent:"space-between",alignItems:"center"}}>
              <span style={{fontSize:12,color:"var(--text-3)"}}>Songs missing a Title will be skipped.</span>
              <div style={{display:"flex",gap:8}}>
                <button className="btn-ghost" onClick={()=>{setImportStep("idle");setImportFile(null);}}>Cancel</button>
                <button className="btn-accent" onClick={runImport}>Import {importFile.count} rows →</button>
              </div>
            </div>
          </div>
        )}

        {importStep==="done" && (
          <div style={{background:"#dcfce7",border:"1px solid #86efac",borderRadius:10,padding:"20px 24px",display:"flex",justifyContent:"space-between",alignItems:"center"}}>
            <div>
              <div style={{fontWeight:600,fontSize:14,color:"#166534"}}>✓ Import complete</div>
              <div style={{fontSize:12,color:"#166534",marginTop:3}}>{importCount} song{importCount!==1?"s":""} added to your catalog.</div>
            </div>
            <button className="btn-ghost" onClick={()=>{setImportStep("idle");setImportFile(null);}} style={{fontSize:12}}>Import another</button>
          </div>
        )}

        <input ref={fileInputRef} type="file" accept=".csv,text/csv" style={{display:"none"}} onChange={handleFile}/>
      </div>

      {/* Pitching Import */}
      <div style={{marginTop:36}}>
        <div style={{fontSize:16,fontWeight:700,letterSpacing:"-0.01em",marginBottom:3}}>Import Outreach Tracker</div>
        <div style={{fontSize:13,color:"var(--text-3)",marginBottom:6}}>
          Import your sync pitching contacts from a Google Sheets CSV export into the Pitching page.
        </div>
        <div style={{fontSize:12,color:"var(--text-3)",background:"var(--bg-2)",border:"1px solid var(--border)",borderRadius:6,padding:"8px 12px",marginBottom:18,fontFamily:"var(--mono)"}}>
          Expected columns: Agency, Campaign, Status, Date Contacted, Notes, Submission Window, Requires Warm Intro
        </div>

        {pitchImportStep==="idle" && (
          <div
            onClick={()=>pitchFileInputRef.current?.click()}
            style={{border:"2px dashed var(--border)",borderRadius:10,padding:"44px 24px",textAlign:"center",cursor:"pointer",background:"var(--bg-2)",transition:"all 0.15s"}}
            onMouseEnter={e=>{e.currentTarget.style.borderColor="var(--accent)";e.currentTarget.style.background="var(--accent-dim)";}}
            onMouseLeave={e=>{e.currentTarget.style.borderColor="var(--border)";e.currentTarget.style.background="var(--bg-2)";}}
          >
            <div style={{fontSize:26,marginBottom:10,color:"var(--text-3)"}}>↑</div>
            <div style={{fontWeight:600,fontSize:14,marginBottom:4}}>Upload outreach tracker CSV</div>
            <div style={{fontSize:12,color:"var(--text-3)"}}>Contacts matched by agency name · Duplicates skipped automatically</div>
          </div>
        )}

        {pitchImportStep==="preview" && pitchImportFile && (()=>{
          const willCreate = pitchImportRows.filter(r=>!r.skip).length;
          const willSkip   = pitchImportRows.filter(r=>r.skip).length;
          return (
            <div className="table-wrap">
              <div style={{padding:"13px 18px",borderBottom:"1px solid var(--border)",display:"flex",justifyContent:"space-between",alignItems:"center"}}>
                <div>
                  <div style={{fontWeight:600,fontSize:14}}>{pitchImportFile.name}</div>
                  <div style={{fontSize:12,color:"var(--text-3)",marginTop:2}}>{willCreate} entr{willCreate===1?"y":"ies"} will be created · {willSkip} row{willSkip!==1?"s":""} skipped</div>
                </div>
                <button className="btn-ghost" style={{fontSize:11}} onClick={()=>{setPitchImportStep("idle");setPitchImportFile(null);}}>✕ Cancel</button>
              </div>
              <div style={{maxHeight:400,overflowY:"auto"}}>
                <table className="data-table">
                  <thead><tr><th>Agency</th><th>Campaign</th><th>Status</th><th>Result</th></tr></thead>
                  <tbody>
                    {pitchImportRows.map((r,i)=>(
                      <tr key={i} style={{opacity:r.skip?0.5:1}}>
                        <td style={{fontWeight:500,fontSize:13}}>{r.agency}</td>
                        <td style={{fontSize:12,color:"var(--text-3)"}}>{r.campaignRaw||"—"}</td>
                        <td><span style={{fontSize:11,background:"var(--bg-2)",border:"1px solid var(--border)",borderRadius:4,padding:"2px 7px"}}>{r.status}</span></td>
                        <td style={{fontSize:12}}>
                          {r.skip
                            ? <span style={{color:"#dc2626"}}>⚠ {r.skipReason}</span>
                            : <span style={{color:"#059669"}}>✓ Will create</span>
                          }
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
              <div style={{padding:"12px 18px",borderTop:"1px solid var(--border)",display:"flex",justifyContent:"space-between",alignItems:"center"}}>
                <span style={{fontSize:12,color:"var(--text-3)"}}>Contacts matched by agency name (case-insensitive).</span>
                <div style={{display:"flex",gap:8}}>
                  <button className="btn-ghost" onClick={()=>{setPitchImportStep("idle");setPitchImportFile(null);}}>Cancel</button>
                  <button className="btn-accent" onClick={runPitchImport} disabled={willCreate===0}>
                    Import {willCreate} entr{willCreate===1?"y":"ies"} →
                  </button>
                </div>
              </div>
            </div>
          );
        })()}

        {pitchImportStep==="done" && pitchImportResults && (
          <div style={{background:"#dcfce7",border:"1px solid #86efac",borderRadius:10,padding:"20px 24px",display:"flex",justifyContent:"space-between",alignItems:"center"}}>
            <div>
              <div style={{fontWeight:600,fontSize:14,color:"#166534"}}>✓ Pitching import complete</div>
              <div style={{fontSize:12,color:"#166534",marginTop:3}}>
                {pitchImportResults.created} {pitchImportResults.created===1?"entry":"entries"} created · {pitchImportResults.updated} contact{pitchImportResults.updated!==1?"s":""} updated · {pitchImportResults.skipped} row{pitchImportResults.skipped!==1?"s":""} skipped.
              </div>
            </div>
            <button className="btn-ghost" onClick={()=>{setPitchImportStep("idle");setPitchImportFile(null);setPitchImportResults(null);}} style={{fontSize:12}}>Import another</button>
          </div>
        )}

        <input ref={pitchFileInputRef} type="file" accept=".csv,text/csv" style={{display:"none"}} onChange={handlePitchFile}/>
      </div>
    </div>
  );
}

// ─── Artists Page ─────────────────────────────────────────────────────────────

function ArtistsPage({ songs, search, onSelectArtist }) {
  const unassigned = songs.filter(s => !s.artist).length;
  const [selectedGenres, setSelectedGenres] = useState2([]);
  const [genreMode,      setGenreMode]      = useState2("OR");

  const allGenres = useMemo2(() => {
    const gs = ARTISTS.flatMap(a => a.genre.split(" / ").map(g => g.trim()));
    return [...new Set(gs)].sort();
  }, []);

  const toggleGenre = (g) => setSelectedGenres(prev => prev.includes(g) ? prev.filter(x => x !== g) : [...prev, g]);

  const filtered = useMemo2(() => {
    let list = ARTISTS;
    if (search) {
      const q = search.toLowerCase();
      list = list.filter(a =>
        a.name.toLowerCase().includes(q) ||
        a.genre.toLowerCase().includes(q) ||
        (a.description||"").toLowerCase().includes(q)
      );
    }
    if (selectedGenres.length > 0) {
      list = list.filter(a => {
        const ag = a.genre.split(" / ").map(g => g.trim());
        return genreMode === "OR"
          ? selectedGenres.some(g => ag.includes(g))
          : selectedGenres.every(g => ag.includes(g));
      });
    }
    return list;
  }, [search, selectedGenres, genreMode]);

  return (
    <div className="page-content page-fade">

      <div className="stat-grid" style={{ gridTemplateColumns:"repeat(3,1fr)", marginBottom:20 }}>
        {[
          { label:"Artist Projects", value:ARTISTS.length,                    accent:"var(--accent)" },
          { label:"Songs Assigned",  value:songs.filter(s=>s.artist).length,  accent:"#059669" },
          { label:"Unassigned",      value:unassigned,                        accent:unassigned>0?"#d97706":"#9ca3af" },
        ].map((s,i) => (
          <div key={i} className="stat-card">
            <div style={{ position:"absolute", top:0, left:0, width:3, height:"100%", background:s.accent, borderRadius:"6px 0 0 6px", opacity:0.7 }}></div>
            <div style={{ fontSize:32, fontWeight:700, color:s.accent, letterSpacing:"-0.03em" }}>{s.value}</div>
            <div style={{ fontSize:13, fontWeight:600, marginTop:6 }}>{s.label}</div>
          </div>
        ))}
      </div>

      {allGenres.length > 0 && (
        <div className="filter-bar" style={{ marginBottom:16 }}>
          <GenreDropdown allGenres={allGenres} selectedGenres={selectedGenres} setSelectedGenres={setSelectedGenres} genreMode={genreMode} setGenreMode={setGenreMode} />
        </div>
      )}

      <div className="collab-grid">
        {filtered.map(artist => {
          const artistSongs = songs.filter(s => s.artist === artist.name);
          const released    = artistSongs.filter(s => s.status === "Released").length;
          const syncReady   = artistSongs.filter(s => s.syncReady).length;
          const inProgress  = artistSongs.filter(s => ["In Progress","Mixing","Demo","Mastered"].includes(s.status)).length;
          const genres      = [...new Set(artistSongs.map(s => s.genre.split("/")[0].trim()))].slice(0,3);

          return (
            <div key={artist.id} className="collab-card" onClick={() => onSelectArtist(artist)}>
              <div style={{ display:"flex", justifyContent:"space-between", alignItems:"flex-start" }}>
                <div style={{ width:48, height:48, borderRadius:12, background:`hsl(${artist.artworkHue},45%,90%)`, color:`hsl(${artist.artworkHue},45%,32%)`, display:"flex", alignItems:"center", justifyContent:"center", fontWeight:700, fontSize:16, flexShrink:0 }}>
                  {artist.name.split(" ").map(n=>n[0]).join("").slice(0,2)}
                </div>
                <Badge color={artist.active?"#166534":"#6b7280"} bg={artist.active?"#dcfce7":"#f3f4f6"}>
                  {artist.active ? "Active" : "Inactive"}
                </Badge>
              </div>

              <div style={{ marginTop:14 }}>
                <div style={{ fontWeight:700, fontSize:15 }}>{artist.name}</div>
                <div style={{ fontSize:12.5, color:"var(--text-3)", marginTop:2 }}>{artist.genre}</div>
                {artist.description && (
                  <div style={{ fontSize:11.5, color:"var(--text-3)", marginTop:5, lineHeight:1.45,
                    overflow:"hidden", display:"-webkit-box", WebkitLineClamp:2, WebkitBoxOrient:"vertical" }}>
                    {artist.description}
                  </div>
                )}
              </div>

              {genres.length > 0 && (
                <div style={{ display:"flex", gap:4, marginTop:10, flexWrap:"wrap" }}>
                  {genres.map(g => <Badge key={g} style={{ fontSize:9.5 }}>{g}</Badge>)}
                </div>
              )}

              {artistSongs.length > 0 && (
                <div style={{ marginTop:12 }}>
                  <div style={{ height:4, borderRadius:2, background:"var(--border)", overflow:"hidden", display:"flex", gap:1 }}>
                    <div style={{ width:`${(released/artistSongs.length)*100}%`, background:"#059669", height:"100%" }}></div>
                    <div style={{ width:`${(inProgress/artistSongs.length)*100}%`, background:"#d97706", height:"100%" }}></div>
                  </div>
                </div>
              )}

              <div style={{ marginTop:12, paddingTop:11, borderTop:"1px solid var(--border)", display:"flex", justifyContent:"space-between", fontSize:12, color:"var(--text-3)" }}>
                <span>{artistSongs.length} song{artistSongs.length!==1?"s":""}</span>
                <span style={{ color:syncReady>0?"#059669":"var(--text-3)" }}>{syncReady} sync ready</span>
              </div>
            </div>
          );
        })}

        <div
          className="collab-card"
          style={{ display:"flex", flexDirection:"column", alignItems:"center", justifyContent:"center", gap:8, minHeight:200, background:"var(--bg-2)", border:"1.5px dashed var(--border)", cursor:"pointer" }}
          onMouseEnter={e => e.currentTarget.style.borderColor = "var(--accent)"}
          onMouseLeave={e => e.currentTarget.style.borderColor = "var(--border)"}
        >
          <div style={{ width:40, height:40, borderRadius:10, background:"var(--border)", display:"flex", alignItems:"center", justifyContent:"center", fontSize:22, color:"var(--text-3)", lineHeight:1 }}>+</div>
          <div style={{ fontSize:13, fontWeight:500, color:"var(--text-3)" }}>Add Artist</div>
          <div style={{ fontSize:11, color:"var(--text-3)" }}>New project or alias</div>
        </div>

        {unassigned > 0 && (
          <div className="collab-card" style={{ background:"var(--bg-2)", cursor:"default" }}>
            <div style={{ width:48, height:48, borderRadius:12, background:"var(--border)", display:"flex", alignItems:"center", justifyContent:"center", fontSize:20, color:"var(--text-3)", flexShrink:0 }}>?</div>
            <div style={{ marginTop:14 }}>
              <div style={{ fontWeight:700, fontSize:15, color:"var(--text-2)" }}>Unassigned</div>
              <div style={{ fontSize:12, color:"var(--text-3)", marginTop:2 }}>No artist set</div>
              <div style={{ fontSize:11.5, color:"var(--text-3)", marginTop:5, lineHeight:1.45 }}>
                {unassigned} song{unassigned!==1?"s":""} without an artist. Edit each song to assign.
              </div>
            </div>
            <div style={{ marginTop:12, paddingTop:11, borderTop:"1px solid var(--border)", fontSize:12, color:"#d97706" }}>
              ⚠ {unassigned} unassigned
            </div>
          </div>
        )}
      </div>
    </div>
  );
}

// ─── Contacts Page ────────────────────────────────────────────────────────────

const CONTACT_TYPE_COLORS2 = { "Agency":"#7c6fff", "Sub-Publisher":"#22c55e", "Supervisor":"#f59e0b", "Label":"#f472b6" };

function ContactsPage({ contacts, songs, onSelectContact }) {
  const [filter, setFilter] = useState2("All");
  const totalLinked = songs.filter(s => (s.agencyIds||[]).length > 0).length;

  const filtered = useMemo2(() => {
    if (filter === "All") return contacts;
    return contacts.filter(c => c.type === filter);
  }, [contacts, filter]);

  const types = ["All", "Agency", "Sub-Publisher", "Supervisor", "Label"];

  return (
    <div className="page-content page-fade">
      <div style={{ display:"flex", gap:10, marginBottom:20 }}>
        {[
          ["Contacts", contacts.length],
          ["Songs Pitched", totalLinked],
          ["Agencies", contacts.filter(c=>c.type==="Agency").length],
          ["Sub-Publishers", contacts.filter(c=>c.type==="Sub-Publisher").length],
        ].map(([l,v]) => (
          <div key={l} style={{ background:"var(--card)", border:"1px solid var(--border)", borderRadius:8, padding:"10px 16px", minWidth:110 }}>
            <div style={{ fontSize:20, fontWeight:700 }}>{v}</div>
            <div style={{ fontSize:11, color:"var(--text-3)", marginTop:2 }}>{l}</div>
          </div>
        ))}
      </div>

      <div className="filter-bar">
        {types.map(t => (
          <button key={t} className={"filter-chip"+(filter===t?" active":"")} onClick={() => setFilter(t)}>{t}</button>
        ))}
        <div style={{ marginLeft:"auto" }}>
          <span style={{ fontSize:12, color:"var(--text-3)" }}>{filtered.length} contacts</span>
        </div>
      </div>

      <div className="table-wrap">
        <table className="data-table">
          <thead>
            <tr>
              <th>Name</th>
              <th>Type</th>
              <th>Email</th>
              <th>Website</th>
              <th>Songs Linked</th>
              <th>Notes</th>
            </tr>
          </thead>
          <tbody>
            {filtered.map(c => {
              const typeColor = CONTACT_TYPE_COLORS2[c.type] || "var(--text-3)";
              const linked = songs.filter(s => (s.agencyIds||[]).includes(c.id)).length;
              const initials = c.name.split(" ").map(w=>w[0]).join("").slice(0,2).toUpperCase();
              return (
                <tr key={c.id} onClick={() => onSelectContact(c)} style={{ cursor:"pointer" }}>
                  <td style={{ padding:"11px 14px", minWidth:180 }}>
                    <div style={{ display:"flex", alignItems:"center", gap:10 }}>
                      <div style={{ width:30, height:30, borderRadius:7, background:typeColor+"22", color:typeColor, display:"flex", alignItems:"center", justifyContent:"center", fontWeight:700, fontSize:11, flexShrink:0 }}>{initials}</div>
                      <div style={{ fontWeight:500, fontSize:13 }}>{c.name}</div>
                    </div>
                  </td>
                  <td style={{ padding:"11px 14px" }}>
                    <span style={{ fontSize:11, fontWeight:500, background:typeColor+"22", color:typeColor, borderRadius:4, padding:"2px 8px" }}>{c.type}</span>
                  </td>
                  <td style={{ padding:"11px 14px", fontSize:12, color:"var(--text-2)" }}>
                    {c.email ? <a href={"mailto:"+c.email} onClick={e=>e.stopPropagation()} style={{ color:"var(--accent)", textDecoration:"none" }}>{c.email}</a> : <span style={{ color:"var(--text-3)" }}>—</span>}
                  </td>
                  <td style={{ padding:"11px 14px", fontSize:12 }}>
                    {c.website ? <a href={"https://"+c.website.replace(/^https?:\/\//,"")} target="_blank" rel="noopener noreferrer" onClick={e=>e.stopPropagation()} style={{ color:"var(--accent)", textDecoration:"none" }}>{c.website}</a> : <span style={{ color:"var(--text-3)" }}>—</span>}
                  </td>
                  <td style={{ padding:"11px 14px", fontSize:12, color: linked > 0 ? "var(--text)" : "var(--text-3)" }}>
                    {linked > 0 ? <span style={{ fontWeight:500 }}>{linked} song{linked!==1?"s":""}</span> : "—"}
                  </td>
                  <td style={{ padding:"11px 14px", fontSize:12, color:"var(--text-3)", maxWidth:260 }}>
                    <div style={{ overflow:"hidden", textOverflow:"ellipsis", whiteSpace:"nowrap" }}>{c.notes||"—"}</div>
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
    </div>
  );
}

// ─── Profile Page ─────────────────────────────────────────────────────────────

function ProfilePage({ user, songs, contacts, darkMode, onToggleDark, drawerCentered, onToggleDrawerCentered, onLogout, onDeleteAllData, profile, onUpdateProfile }) {
  const { useState, useEffect } = React;
  const [showDeleteModal,   setShowDeleteModal]   = useState(false);
  const [deleteConfirmText, setDeleteConfirmText] = useState('');
  const [deleteLoading,     setDeleteLoading]     = useState(false);
  const [cwrSenderIdInput,  setCwrSenderIdInput]  = useState('');
  const [cwrSaved,          setCwrSaved]          = useState(false);

  useEffect(() => { setCwrSenderIdInput(profile?.cwrSenderId || ''); }, [profile?.cwrSenderId]);

  const handleDeleteAllData = async () => {
    setDeleteLoading(true);
    await onDeleteAllData();
  };

  const handleSaveCwrSenderId = () => {
    if (onUpdateProfile) onUpdateProfile({ cwrSenderId: cwrSenderIdInput.trim() });
    setCwrSaved(true);
    setTimeout(() => setCwrSaved(false), 2000);
  };

  const displayName = user?.displayName || user?.email?.split("@")[0] || "User";
  const initials    = displayName.split(" ").filter(Boolean).map(w => w[0]).join("").toUpperCase().slice(0, 2) || "U";
  const joinDate    = user?.metadata?.creationTime
    ? new Date(user.metadata.creationTime).toLocaleDateString("en-AU", { day:"numeric", month:"long", year:"numeric" })
    : "—";
  const provider    = user?.providerData?.[0]?.providerId === "google.com" ? "Google OAuth" : "Email & Password";

  const statsData = [
    { label:"Total Songs",   value:songs.length,                                  accent:"var(--accent)" },
    { label:"Sync Ready",    value:songs.filter(s => s.syncReady).length,          accent:"#059669"       },
    { label:"Released",      value:songs.filter(s => s.status === "Released").length, accent:"#2563eb"   },
    { label:"Contacts",      value:contacts.length,                               accent:"#d97706"       },
  ];

  return (
    <div className="page-content page-fade" style={{ maxWidth:680 }}>

      {/* ── Profile header ── */}
      <div style={{ display:"flex", alignItems:"center", gap:20, marginBottom:20, padding:"22px 24px", background:"var(--card)", border:"1px solid var(--border)", borderRadius:"var(--r-lg)", boxShadow:"var(--shadow-sm)" }}>
        <div style={{ width:64, height:64, borderRadius:14, background:"var(--accent-dim)", color:"var(--accent-text)", display:"flex", alignItems:"center", justifyContent:"center", flexShrink:0, overflow:"hidden" }}>
          {user?.photoURL
            ? <img src={user.photoURL} alt="" style={{ width:64, height:64, objectFit:"cover" }} />
            : <span style={{ fontSize:22, fontWeight:700 }}>{initials}</span>
          }
        </div>
        <div style={{ flex:1, minWidth:0 }}>
          <div style={{ fontSize:21, fontWeight:700, letterSpacing:"-0.02em", color:"var(--text)" }}>{displayName}</div>
          <div style={{ fontSize:13, color:"var(--text-3)", marginTop:3 }}>{user?.email}</div>
          <div style={{ fontSize:11.5, color:"var(--text-3)", marginTop:3 }}>Member since {joinDate}</div>
        </div>
        <span style={{ fontSize:11, fontWeight:600, background:"var(--accent-dim)", color:"var(--accent-text)", padding:"4px 10px", borderRadius:6, flexShrink:0 }}>Beta</span>
      </div>

      {/* ── Stats ── */}
      <div style={{ display:"grid", gridTemplateColumns:"repeat(4,1fr)", gap:10, marginBottom:20 }}>
        {statsData.map((s, i) => (
          <div key={i} style={{ background:"var(--card)", border:"1px solid var(--border)", borderRadius:"var(--r)", padding:"14px 16px", position:"relative", overflow:"hidden", boxShadow:"var(--shadow-sm)" }}>
            <div style={{ position:"absolute", top:0, left:0, width:3, height:"100%", background:s.accent, opacity:0.7, borderRadius:"var(--r) 0 0 var(--r)" }}></div>
            <div style={{ fontSize:26, fontWeight:700, color:s.accent, letterSpacing:"-0.02em" }}>{s.value}</div>
            <div style={{ fontSize:11, color:"var(--text-3)", marginTop:4 }}>{s.label}</div>
          </div>
        ))}
      </div>

      {/* ── Account details ── */}
      <div className="profile-section">
        <div className="profile-section-header">Account</div>
        <div className="profile-row">
          <span style={{ color:"var(--text-3)" }}>Email address</span>
          <span style={{ fontWeight:500 }}>{user?.email}</span>
        </div>
        <div className="profile-row">
          <span style={{ color:"var(--text-3)" }}>Sign-in method</span>
          <span style={{ fontWeight:500 }}>{provider}</span>
        </div>
        <div className="profile-row">
          <span style={{ color:"var(--text-3)" }}>Member since</span>
          <span style={{ fontWeight:500 }}>{joinDate}</span>
        </div>
        <div className="profile-row">
          <span style={{ color:"var(--text-3)" }}>User ID</span>
          <span className="mono" style={{ fontSize:10.5, color:"var(--text-3)" }}>{user?.uid}</span>
        </div>
      </div>

      {/* ── Subscription ── */}
      <div className="profile-section">
        <div className="profile-section-header">Subscription</div>
        <div className="profile-row">
          <div>
            <div style={{ fontWeight:600 }}>Free — Beta Access</div>
            <div style={{ fontSize:12, color:"var(--text-3)", marginTop:3 }}>Full access during beta period</div>
          </div>
          <button className="btn-accent" style={{ fontSize:12, opacity:0.45, cursor:"not-allowed" }} disabled>
            Upgrade · $15 AUD/mo
          </button>
        </div>
        <div className="profile-row" style={{ fontSize:12, color:"var(--text-3)" }}>
          Paid plans coming soon — $15 AUD/month · 14-day free trial · card required at signup.
        </div>
      </div>

      {/* ── Preferences ── */}
      <div className="profile-section">
        <div className="profile-section-header">Preferences</div>
        <div className="profile-row">
          <div>
            <div style={{ fontWeight:500 }}>Appearance</div>
            <div style={{ fontSize:12, color:"var(--text-3)", marginTop:2 }}>Currently: {darkMode ? "Dark mode" : "Light mode"}</div>
          </div>
          <button
            onClick={onToggleDark}
            style={{ display:"flex", alignItems:"center", gap:8, background:"var(--bg-2)", border:"1px solid var(--border)", borderRadius:"var(--r)", padding:"7px 13px", cursor:"pointer", fontSize:13, fontFamily:"var(--font)", color:"var(--text)", transition:"background 0.1s" }}
            onMouseEnter={e => e.currentTarget.style.background = "var(--border)"}
            onMouseLeave={e => e.currentTarget.style.background = "var(--bg-2)"}
          >
            {darkMode ? "☀ Switch to Light" : "◑ Switch to Dark"}
          </button>
        </div>
        <div className="profile-row">
          <div>
            <div style={{ fontWeight:500 }}>Edit panel layout</div>
            <div style={{ fontSize:12, color:"var(--text-3)", marginTop:2 }}>Default: {drawerCentered ? "Centered (float)" : "Side panel (right)"}</div>
          </div>
          <button
            onClick={onToggleDrawerCentered}
            style={{ display:"flex", alignItems:"center", gap:8, background:"var(--bg-2)", border:"1px solid var(--border)", borderRadius:"var(--r)", padding:"7px 13px", cursor:"pointer", fontSize:13, fontFamily:"var(--font)", color:"var(--text)", transition:"background 0.1s" }}
            onMouseEnter={e => e.currentTarget.style.background = "var(--border)"}
            onMouseLeave={e => e.currentTarget.style.background = "var(--bg-2)"}
          >
            {drawerCentered ? "⊡ Float center" : "⊟ Side panel"}
          </button>
        </div>
      </div>

      {/* ── CWR Settings [PUBLISHER] ── */}
      <div className="profile-section">
        <div className="profile-section-header" style={{ display:"flex", alignItems:"center", gap:8 }}>
          CWR Settings
          <span style={{ fontSize:10, fontWeight:700, background:"#7c3aed", color:"#fff", padding:"2px 7px", borderRadius:4, letterSpacing:"0.04em" }}>PUBLISHER</span>
        </div>
        <div className="profile-row" style={{ flexDirection:"column", alignItems:"flex-start", gap:10 }}>
          <div>
            <div style={{ fontWeight:500 }}>CWR Sender ID</div>
            <div style={{ fontSize:12, color:"var(--text-3)", marginTop:2 }}>Your unique sender identifier issued by your PRO or CISAC-registered society. Used in the CWR file header (HDR record).</div>
          </div>
          <div style={{ display:"flex", gap:8, width:"100%", alignItems:"center" }}>
            <input
              type="text"
              value={cwrSenderIdInput}
              onChange={e => setCwrSenderIdInput(e.target.value.toUpperCase())}
              placeholder="e.g. APRA001"
              maxLength={9}
              style={{ flex:1, maxWidth:220, padding:"7px 11px", border:"1px solid var(--border)", borderRadius:"var(--r)", fontSize:13, fontFamily:"monospace", background:"var(--bg-2)", color:"var(--text)", outline:"none" }}
            />
            <button
              onClick={handleSaveCwrSenderId}
              disabled={cwrSenderIdInput.trim() === (profile?.cwrSenderId || '')}
              style={{ background:"var(--accent)", border:"none", borderRadius:"var(--r)", padding:"7px 14px", cursor:"pointer", fontSize:13, fontWeight:600, color:"#fff", fontFamily:"var(--font)", opacity: cwrSenderIdInput.trim() === (profile?.cwrSenderId || '') ? 0.45 : 1, transition:"opacity 0.1s" }}
            >
              {cwrSaved ? "Saved ✓" : "Save"}
            </button>
          </div>
        </div>
      </div>

      {/* ── Session ── */}
      <div className="profile-section">
        <div className="profile-section-header">Session</div>
        <div className="profile-row">
          <div>
            <div style={{ fontWeight:500 }}>Sign out</div>
            <div style={{ fontSize:12, color:"var(--text-3)", marginTop:2 }}>Sign out of MMV on this device</div>
          </div>
          <button
            onClick={onLogout}
            style={{ background:"#fef2f2", border:"1px solid #fecaca", borderRadius:"var(--r)", padding:"7px 14px", cursor:"pointer", fontSize:13, fontWeight:500, color:"#dc2626", fontFamily:"var(--font)", transition:"background 0.1s" }}
            onMouseEnter={e => e.currentTarget.style.background = "#fee2e2"}
            onMouseLeave={e => e.currentTarget.style.background = "#fef2f2"}
          >
            Sign Out
          </button>
        </div>
      </div>

      {/* ── Danger Zone ── */}
      <div className="profile-section" style={{ borderColor:"#fecaca" }}>
        <div className="profile-section-header" style={{ color:"#dc2626" }}>Danger Zone</div>
        <div className="profile-row">
          <div>
            <div style={{ fontWeight:500 }}>Delete all data</div>
            <div style={{ fontSize:12, color:"var(--text-3)", marginTop:2 }}>Permanently remove all songs, artists, collaborators, publishers, contacts, and sync briefs. Cannot be undone.</div>
          </div>
          <button
            onClick={() => { setShowDeleteModal(true); setDeleteConfirmText(''); }}
            style={{ background:"#fef2f2", border:"1px solid #fecaca", borderRadius:"var(--r)", padding:"7px 14px", cursor:"pointer", fontSize:13, fontWeight:500, color:"#dc2626", fontFamily:"var(--font)", transition:"background 0.1s", whiteSpace:"nowrap" }}
            onMouseEnter={e => e.currentTarget.style.background = "#fee2e2"}
            onMouseLeave={e => e.currentTarget.style.background = "#fef2f2"}
          >
            Delete All Data
          </button>
        </div>
      </div>

      {/* ── Delete confirmation modal ── */}
      {showDeleteModal && (
        <div style={{ position:"fixed", inset:0, background:"rgba(0,0,0,0.5)", zIndex:1000, display:"flex", alignItems:"center", justifyContent:"center", padding:20 }}>
          <div style={{ background:"var(--card)", border:"1px solid #fecaca", borderRadius:"var(--r-lg)", padding:"28px 28px 24px", maxWidth:440, width:"100%", boxShadow:"0 20px 60px rgba(0,0,0,0.3)" }}>
            <div style={{ fontSize:16, fontWeight:700, color:"#dc2626", marginBottom:8 }}>Delete all data</div>
            <div style={{ fontSize:13, color:"var(--text-2)", lineHeight:1.55, marginBottom:16 }}>
              This will permanently delete all your songs, artists, collaborators, publishers, contacts, and sync briefs. Your account will remain active with zero data. <strong>This cannot be undone.</strong>
            </div>
            <div style={{ fontSize:12, color:"var(--text-3)", marginBottom:8 }}>Type <span style={{ fontFamily:"monospace", fontWeight:700, color:"var(--text)" }}>DELETE</span> to confirm:</div>
            <input
              type="text"
              value={deleteConfirmText}
              onChange={e => setDeleteConfirmText(e.target.value)}
              placeholder="DELETE"
              disabled={deleteLoading}
              style={{ width:"100%", boxSizing:"border-box", padding:"8px 11px", border:"1px solid var(--border)", borderRadius:"var(--r)", fontSize:13, fontFamily:"var(--font)", background:"var(--bg-2)", color:"var(--text)", marginBottom:16, outline:"none" }}
              autoFocus
            />
            <div style={{ display:"flex", gap:10, justifyContent:"flex-end" }}>
              <button
                onClick={() => setShowDeleteModal(false)}
                disabled={deleteLoading}
                style={{ background:"var(--bg-2)", border:"1px solid var(--border)", borderRadius:"var(--r)", padding:"7px 14px", cursor:"pointer", fontSize:13, fontFamily:"var(--font)", color:"var(--text)" }}
              >
                Cancel
              </button>
              <button
                onClick={handleDeleteAllData}
                disabled={deleteConfirmText !== 'DELETE' || deleteLoading}
                style={{ background: deleteConfirmText === 'DELETE' && !deleteLoading ? "#dc2626" : "#fca5a5", border:"none", borderRadius:"var(--r)", padding:"7px 16px", cursor: deleteConfirmText === 'DELETE' && !deleteLoading ? "pointer" : "not-allowed", fontSize:13, fontWeight:600, color:"#fff", fontFamily:"var(--font)", display:"flex", alignItems:"center", gap:6, transition:"background 0.1s" }}
              >
                {deleteLoading
                  ? <><span style={{ display:"inline-block", width:12, height:12, border:"2px solid rgba(255,255,255,0.4)", borderTopColor:"#fff", borderRadius:"50%", animation:"spin 0.7s linear infinite" }} /> Deleting…</>
                  : "Delete All Data"
                }
              </button>
            </div>
          </div>
        </div>
      )}

    </div>
  );
}

// ─── PitchingPage ─────────────────────────────────────────────────────────────

const PITCH_STAGES = ["Not Contacted", "Pitched", "Following Up", "In Discussion", "Signed", "Passed", "No Response"];
const PITCH_TERMINAL = ["Signed", "Passed", "No Response"];

function PitchingPage({ campaigns, pitchEntries, contacts, onAddCampaign, onUpdateCampaign, onSelectEntry, onUpdateEntry, onAddEntry }) {
  const [activeCampaignId, setActiveCampaignId] = useState2(campaigns[0]?.id || null);
  const [showNewCampaign,  setShowNewCampaign]  = useState2(false);
  const [newCampaignName,  setNewCampaignName]  = useState2("");
  const [statusFilter,     setStatusFilter]     = useState2("All");
  const [search,           setSearch]           = useState2("");
  const [openStatusDropId, setOpenStatusDropId] = useState2(null);
  const [addContactOpen,   setAddContactOpen]   = useState2(false);
  const [viewMode,         setViewMode]         = useState2("table");
  const statusDropRef = useRef2(null);

  // Kanban drag-and-drop for pitch entries
  const handleKanbanMove = (entryId, { status: newStage }) => {
    const entry = pitchEntries.find(e => e.id === entryId);
    if (entry) onUpdateEntry(entry.campaignId, entry.id, { status: newStage });
  };
  const { dragOverCol: pitchDragOverCol, handleDragStart: pitchDragStart, handleDrop: pitchDrop, handleDragOver: pitchDragOver, handleDragLeave: pitchDragLeave, handleDragEnd: pitchDragEnd } = useKanban(handleKanbanMove);

  useEffect2(() => {
    const handler = (e) => {
      if (statusDropRef.current && !statusDropRef.current.contains(e.target)) {
        setOpenStatusDropId(null);
      }
    };
    document.addEventListener("mousedown", handler);
    return () => document.removeEventListener("mousedown", handler);
  }, []);

  // Keep activeCampaignId in sync if campaigns load asynchronously
  useEffect2(() => {
    if (!activeCampaignId && campaigns.length > 0) setActiveCampaignId(campaigns[0].id);
  }, [campaigns, activeCampaignId]);

  const activeCampaign = campaigns.find(c => c.id === activeCampaignId) || null;

  const campaignEntries = useMemo2(() =>
    pitchEntries.filter(e => e.campaignId === activeCampaignId)
  , [pitchEntries, activeCampaignId]);

  const isOverdue = (e) => {
    if (!e.followUpDate || e.followUpDone || PITCH_TERMINAL.includes(e.status)) return false;
    const d = new Date(e.followUpDate);
    d.setHours(0, 0, 0, 0);
    const t = new Date();
    t.setHours(0, 0, 0, 0);
    return d < t;
  };

  // Stats for active campaign
  const stats = useMemo2(() => ({
    total:        campaignEntries.length,
    pitched:      campaignEntries.filter(e => e.status === "Pitched" || e.status === "Following Up").length,
    inDiscussion: campaignEntries.filter(e => e.status === "In Discussion").length,
    signed:       campaignEntries.filter(e => e.status === "Signed").length,
    overdue:      campaignEntries.filter(isOverdue).length,
  }), [campaignEntries]);

  // Filtered entries
  const filtered = useMemo2(() => {
    let list = campaignEntries;
    if (statusFilter !== "All") list = list.filter(e => e.status === statusFilter);
    if (search) {
      const q = search.toLowerCase();
      list = list.filter(e => {
        const name = contacts.find(c => c.id === e.contactId)?.name || "";
        return name.toLowerCase().includes(q);
      });
    }
    return list;
  }, [campaignEntries, statusFilter, search, contacts]);

  const handleSaveCampaign = () => {
    if (!newCampaignName.trim()) return;
    const newCampaign = {
      id: String(Date.now()),
      name: newCampaignName.trim(),
      pitchTemplate:    { subject: "", body: "" },
      followUpTemplate: { subject: "", body: "" },
      createdAt: Date.now(),
    };
    onAddCampaign(newCampaign);
    setActiveCampaignId(newCampaign.id);
    setNewCampaignName("");
    setShowNewCampaign(false);
  };

  const handleStatusChange = (entry, newStatus) => {
    onUpdateEntry(entry.campaignId, entry.id, { status: newStatus });
    setOpenStatusDropId(null);
  };

  const selStyle = {
    fontSize: 12, padding: "4px 8px", borderRadius: 5,
    border: "1px solid var(--border)", background: "var(--bg-2)",
    color: "var(--text-2)", outline: "none", cursor: "pointer",
    fontFamily: "var(--font)",
  };

  return (
    <div className="page-content page-fade">

      {/* ── Campaign tabs ── */}
      <div style={{ display:"flex", alignItems:"center", gap:6, marginBottom:16, flexWrap:"wrap" }}>
        {campaigns.map(c => (
          <button
            key={c.id}
            onClick={() => { setActiveCampaignId(c.id); setStatusFilter("All"); setSearch(""); setOpenStatusDropId(null); }}
            style={{
              padding: "6px 14px", borderRadius: 6, fontSize: 13,
              fontWeight: activeCampaignId === c.id ? 600 : 450,
              border: activeCampaignId === c.id ? "1px solid var(--accent)" : "1px solid var(--border)",
              background: activeCampaignId === c.id ? "var(--accent-dim)" : "var(--bg-2)",
              color: activeCampaignId === c.id ? "var(--accent-text)" : "var(--text-2)",
              cursor: "pointer", transition: "background 0.1s, color 0.1s",
            }}
          >
            {c.name}
          </button>
        ))}
        <button
          onClick={() => setShowNewCampaign(true)}
          style={{ padding:"6px 12px", borderRadius:6, fontSize:13, fontWeight:450, border:"1px dashed var(--border)", background:"none", color:"var(--text-3)", cursor:"pointer" }}
        >
          + New Campaign
        </button>
      </div>

      {/* ── Stats bar ── */}
      {activeCampaign && (
        <div style={{ display:"flex", gap:8, marginBottom:16, flexWrap:"wrap" }}>
          {[
            { label:"Total",        value:stats.total,        color:"var(--text-2)",    bg:"var(--bg-2)",    border:"var(--border)" },
            { label:"Pitched",      value:stats.pitched,      color:"var(--text-2)",    bg:"var(--bg-2)",    border:"var(--border)" },
            { label:"In Discussion",value:stats.inDiscussion, color:"var(--text-2)",    bg:"var(--bg-2)",    border:"var(--border)" },
            { label:"Signed",       value:stats.signed,       color:"var(--accent-text)",bg:"var(--accent-dim)",border:"var(--accent)" },
            { label:"Overdue",      value:stats.overdue,      color:"#92400e",          bg:"#fef3c7",        border:"#fcd34d" },
          ].map(s => (
            <div key={s.label} style={{ background:s.bg, border:"1px solid "+s.border, borderRadius:20, padding:"4px 14px", display:"flex", alignItems:"center", gap:6 }}>
              <span style={{ fontSize:14, fontWeight:700, color:s.color }}>{s.value}</span>
              <span style={{ fontSize:11, color:"var(--text-3)" }}>{s.label}</span>
            </div>
          ))}
        </div>
      )}

      {/* ── Filter row ── */}
      {activeCampaign && (
        <div style={{ display:"flex", alignItems:"center", gap:8, marginBottom:14, flexWrap:"wrap" }}>
          {viewMode === "table" && (
            <select style={selStyle} value={statusFilter} onChange={e => setStatusFilter(e.target.value)}>
              <option value="All">All Statuses</option>
              {PITCH_STAGES.map(s => <option key={s} value={s}>{s}</option>)}
            </select>
          )}
          <input
            type="text"
            placeholder="Search by contact name…"
            value={search}
            onChange={e => setSearch(e.target.value)}
            style={{ ...selStyle, padding:"5px 10px", width:220 }}
          />
          <span style={{ fontSize:12, color:"var(--text-3)", marginLeft:"auto" }}>
            {filtered.length} contact{filtered.length !== 1 ? "s" : ""}
          </span>
          {/* View mode toggle */}
          <div style={{ display:"flex", gap:2 }}>
            {[["table","Table"],["kanban","Kanban"]].map(([mode, label]) => (
              <button
                key={mode}
                onClick={() => { setViewMode(mode); setOpenStatusDropId(null); }}
                style={{
                  padding:"4px 10px", borderRadius:5, fontSize:12, fontWeight: viewMode === mode ? 600 : 400,
                  border: viewMode === mode ? "1px solid var(--accent)" : "1px solid var(--border)",
                  background: viewMode === mode ? "var(--accent-dim)" : "var(--bg-2)",
                  color: viewMode === mode ? "var(--accent-text)" : "var(--text-2)",
                  cursor:"pointer", fontFamily:"var(--font)",
                }}
              >{label}</button>
            ))}
          </div>
          <button
            onClick={() => setAddContactOpen(true)}
            style={{ padding:"5px 12px", borderRadius:6, fontSize:12, fontWeight:500, border:"1px solid var(--accent)", background:"var(--accent-dim)", color:"var(--accent-text)", cursor:"pointer", fontFamily:"var(--font)" }}
          >+ Add Contact</button>
        </div>
      )}

      {/* ── Contact table ── */}
      {activeCampaign && viewMode === "table" ? (
        <div className="table-wrap">
          <table className="data-table">
            <thead>
              <tr>
                <th>Agency / Contact</th>
                <th>Status</th>
                <th>Last Pitched</th>
                <th>Follow-Up Date</th>
                <th>Notes</th>
              </tr>
            </thead>
            <tbody>
              {filtered.length === 0 ? (
                <tr>
                  <td colSpan={5} style={{ padding:"32px 14px", textAlign:"center", color:"var(--text-3)", fontSize:13 }}>
                    {campaignEntries.length === 0
                      ? "No contacts in this campaign yet. Add contacts to get started."
                      : "No contacts match the current filter."}
                  </td>
                </tr>
              ) : filtered.map(entry => {
                const contact    = contacts.find(c => c.id === entry.contactId);
                const name       = contact?.name || "Unknown";
                const overdueEntry = isOverdue(entry);
                const initials   = name.split(" ").filter(Boolean).map(w => w[0]).join("").slice(0, 2).toUpperCase();

                return (
                  <tr key={entry.id} onClick={() => onSelectEntry(entry)} style={{ cursor:"pointer" }}>

                    {/* Agency / Contact */}
                    <td style={{ padding:"11px 14px", minWidth:180 }}>
                      <div style={{ display:"flex", alignItems:"center", gap:9 }}>
                        <div style={{ width:28, height:28, borderRadius:6, background:"var(--accent-dim)", color:"var(--accent-text)", display:"flex", alignItems:"center", justifyContent:"center", fontWeight:700, fontSize:10, flexShrink:0 }}>
                          {initials}
                        </div>
                        <div style={{ fontWeight:500, fontSize:13 }}>{name}</div>
                      </div>
                    </td>

                    {/* Inline status dropdown */}
                    <td style={{ padding:"11px 14px" }} onClick={e => e.stopPropagation()}>
                      <div ref={openStatusDropId === entry.id ? statusDropRef : null} style={{ position:"relative", display:"inline-block" }}>
                        <button
                          onClick={() => setOpenStatusDropId(openStatusDropId === entry.id ? null : entry.id)}
                          style={{
                            fontSize:11, fontWeight:500,
                            background: entry.status === "Signed" ? "var(--accent-dim)" : "var(--bg-2)",
                            color: entry.status === "Signed" ? "var(--accent-text)" : "var(--text-2)",
                            border: entry.status === "Signed" ? "1px solid var(--accent)" : "1px solid var(--border)",
                            borderRadius:4, padding:"3px 9px", cursor:"pointer", display:"flex", alignItems:"center", gap:4,
                            fontFamily:"var(--font)",
                          }}
                        >
                          {entry.status || "Not Contacted"} <span style={{ fontSize:9 }}>▾</span>
                        </button>
                        {openStatusDropId === entry.id && (
                          <div style={{ position:"absolute", top:"calc(100% + 3px)", left:0, zIndex:300, background:"var(--card)", border:"1px solid var(--border)", borderRadius:"var(--r)", boxShadow:"var(--shadow)", minWidth:150, padding:"4px 0" }}>
                            {PITCH_STAGES.map(stage => (
                              <button
                                key={stage}
                                onClick={() => handleStatusChange(entry, stage)}
                                style={{
                                  display:"block", width:"100%", textAlign:"left",
                                  padding:"6px 12px", fontSize:12,
                                  color: stage === entry.status ? "var(--accent-text)" : "var(--text)",
                                  background: stage === entry.status ? "var(--accent-dim)" : "none",
                                  border:"none", cursor:"pointer", fontFamily:"var(--font)", transition:"background 0.08s",
                                }}
                                onMouseEnter={e => { if (stage !== entry.status) e.currentTarget.style.background = "var(--bg-2)"; }}
                                onMouseLeave={e => { if (stage !== entry.status) e.currentTarget.style.background = "none"; }}
                              >
                                {stage}
                              </button>
                            ))}
                          </div>
                        )}
                      </div>
                    </td>

                    {/* Last Pitched */}
                    <td style={{ padding:"11px 14px", fontSize:12, color:"var(--text-2)" }}>
                      {entry.lastPitchedDate
                        ? new Date(entry.lastPitchedDate).toLocaleDateString("en-AU", { day:"numeric", month:"short", year:"numeric" })
                        : <span style={{ color:"var(--text-3)" }}>—</span>}
                    </td>

                    {/* Follow-Up Date */}
                    <td style={{ padding:"11px 14px", fontSize:12 }}>
                      {entry.followUpDate ? (
                        <span style={{ color: overdueEntry ? "#dc2626" : "var(--text-2)", fontWeight: overdueEntry ? 600 : 400, display:"flex", alignItems:"center", gap:4 }}>
                          {overdueEntry && <span title="Overdue">⚠</span>}
                          {new Date(entry.followUpDate).toLocaleDateString("en-AU", { day:"numeric", month:"short", year:"numeric" })}
                        </span>
                      ) : <span style={{ color:"var(--text-3)" }}>—</span>}
                    </td>

                    {/* Notes snippet */}
                    <td style={{ padding:"11px 14px", fontSize:12, color:"var(--text-3)", maxWidth:240 }}>
                      <div style={{ overflow:"hidden", textOverflow:"ellipsis", whiteSpace:"nowrap" }}>
                        {entry.customNote || "—"}
                      </div>
                    </td>

                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      ) : activeCampaign && viewMode === "kanban" ? (
        /* ── Kanban board ── */
        <div className="kanban">
          {PITCH_STAGES.map(stage => {
            const colEntries = filtered.filter(e => e.status === stage);
            return (
              <div
                key={stage}
                className={"kanban-col"+(pitchDragOverCol===stage?" drag-over":"")}
                onDragOver={e => pitchDragOver(e, stage)}
                onDragLeave={pitchDragLeave}
                onDrop={e => pitchDrop(e, stage)}
              >
                <div className="kanban-col-header">
                  <span>{stage}</span>
                  <span style={{ fontSize:11, background:"var(--bg-2)", padding:"1px 8px", borderRadius:10, color:"var(--text-3)" }}>{colEntries.length}</span>
                </div>

                {colEntries.map(entry => {
                  const contact = contacts.find(c => c.id === entry.contactId);
                  const name    = contact?.name || "Unknown";
                  const overdueEntry = isOverdue(entry);
                  return (
                    <div
                      key={entry.id}
                      className="brief-card brief-card-draggable"
                      draggable
                      onDragStart={e => pitchDragStart(e, entry.id)}
                      onDragEnd={pitchDragEnd}
                      onClick={() => onSelectEntry(entry)}
                    >
                      <div style={{ fontWeight:600, fontSize:13.5, overflow:"hidden", textOverflow:"ellipsis", whiteSpace:"nowrap" }}>{name}</div>
                      <div style={{ display:"flex", alignItems:"center", gap:4, marginTop:4 }}>
                        <span style={{
                          fontSize:10, fontWeight:500, borderRadius:4, padding:"2px 7px",
                          background: entry.status === "Signed" ? "var(--accent-dim)" : "var(--bg-2)",
                          color: entry.status === "Signed" ? "var(--accent-text)" : "var(--text-3)",
                          border: entry.status === "Signed" ? "1px solid var(--accent)" : "1px solid var(--border)",
                        }}>{entry.status || "Not Contacted"}</span>
                      </div>
                      {entry.customNote && (
                        <div style={{ fontSize:12, color:"var(--text-3)", marginTop:6, overflow:"hidden", textOverflow:"ellipsis", whiteSpace:"nowrap" }}>
                          {entry.customNote}
                        </div>
                      )}
                      {entry.followUpDate && (
                        <div style={{ marginTop:8, paddingTop:7, borderTop:"1px solid var(--border)", fontSize:11, color: overdueEntry ? "#dc2626" : "var(--text-3)", fontWeight: overdueEntry ? 600 : 400, display:"flex", alignItems:"center", gap:3 }}>
                          {overdueEntry && <span title="Overdue">⚠</span>}
                          {new Date(entry.followUpDate).toLocaleDateString("en-AU", { day:"numeric", month:"short", year:"numeric" })}
                        </div>
                      )}
                    </div>
                  );
                })}

                {colEntries.length === 0 && (
                  <div style={{ margin:12, padding:"24px 12px", textAlign:"center", color:"var(--text-3)", fontSize:12, border:"1px dashed var(--border)", borderRadius:7 }}>
                    {pitchDragOverCol === stage ? "Drop here" : "Empty"}
                  </div>
                )}
              </div>
            );
          })}
        </div>
      ) : (
        <div style={{ padding:"40px 0", textAlign:"center", color:"var(--text-3)", fontSize:13 }}>
          No campaigns yet. Create one to get started.
        </div>
      )}

      {/* ── Add Contact modal ── */}
      {addContactOpen && activeCampaign && (
        <AddContactModal
          contacts={contacts}
          pitchEntries={(pitchEntries || []).filter(e => e.campaignId === activeCampaignId)}
          campaignId={activeCampaignId}
          onAdd={onAddEntry}
          onClose={() => setAddContactOpen(false)}
        />
      )}

      {/* ── New Campaign modal ── */}
      {showNewCampaign && (
        <>
          <div className="overlay" onClick={() => setShowNewCampaign(false)} />
          <div className="drawer centered" style={{ width:400, padding:0 }}>
            <div className="drawer-header">
              <div className="drawer-title">New Campaign</div>
              <button className="icon-btn" onClick={() => setShowNewCampaign(false)}>✕</button>
            </div>
            <div style={{ padding:"20px 20px 24px" }}>
              <div style={{ fontSize:11, color:"var(--text-3)", textTransform:"uppercase", letterSpacing:"0.07em", fontWeight:500, marginBottom:6 }}>Campaign Name</div>
              <input
                type="text"
                value={newCampaignName}
                onChange={e => setNewCampaignName(e.target.value)}
                onKeyDown={e => { if (e.key === "Enter") handleSaveCampaign(); if (e.key === "Escape") setShowNewCampaign(false); }}
                placeholder="e.g. Summer 2026 Pitch"
                autoFocus
                style={{ width:"100%", padding:"8px 11px", border:"1px solid var(--border)", borderRadius:"var(--r)", background:"var(--bg-2)", color:"var(--text)", fontSize:13, outline:"none", fontFamily:"var(--font)", marginBottom:20, boxSizing:"border-box" }}
              />
              <div style={{ display:"flex", gap:8, justifyContent:"flex-end" }}>
                <button
                  onClick={() => setShowNewCampaign(false)}
                  style={{ padding:"7px 14px", borderRadius:"var(--r)", background:"var(--bg-2)", border:"1px solid var(--border)", color:"var(--text-2)", fontSize:13, cursor:"pointer", fontFamily:"var(--font)" }}
                >
                  Cancel
                </button>
                <button
                  onClick={handleSaveCampaign}
                  disabled={!newCampaignName.trim()}
                  className="btn-accent"
                  style={{ padding:"7px 16px" }}
                >
                  Create Campaign
                </button>
              </div>
            </div>
          </div>
        </>
      )}

    </div>
  );
}

Object.assign(window, { Dashboard, SongsPage, SplitsPage, CollaboratorsPage, PublishersPage, AnalyticsPage, SyncPage, PitchingPage, ReleasesPage, ArtistsPage, ImportExportPage, ContactsPage, ProfilePage });
