// Editorial Studio — TUEPAC-original drafting. Topic brief -> AI draft -> edit -> publish.
// Uses window.claude.complete when available; deterministic scripted fallback otherwise.

const DESKS = ['Civic','Business','Politics','Sports','Education','Culture','Health','Housing','Legal'];
const STUDIO_CITIES = ['Charlotte','Raleigh','Durham','Greensboro','Winston-Salem','Fayetteville','Wilmington','Statewide'];

const SEED_PIECES = [
  { id:'OR-211', stage:'published', desk:'Business', city:'Statewide', tone:'Analysis', headline:'Inside the broadband gap: who owns the dark fiber under rural Black NC counties', dek:'A three-month review of right-of-way filings shows ownership concentrated among four entities.', editor:'RO', updated:'May 19', words:1180, source:'ai' },
  { id:'OR-210', stage:'published', desk:'Politics', city:'Raleigh', tone:'Reported', headline:'Bill to expand minority contracting transparency clears committee', dek:'The measure would require quarterly disclosure of prime-contractor subcontracting data.', editor:'CR', updated:'May 19', words:740, source:'staff' },
  { id:'OR-209', stage:'draft', desk:'Sports', city:'Greensboro', tone:'Analysis', headline:'A&T\u2019s 2027 schedule is the most aggressive HBCU football move of the decade', dek:'Three Power-Four guarantees reset what an MEAC program can demand at the negotiating table.', editor:'ME', updated:'May 18', words:610, source:'ai' },
  { id:'OR-208', stage:'review', desk:'Health', city:'Charlotte', tone:'Explainer', headline:'What Atrium\u2019s second mobile maternal clinic actually changes in District 3', dek:'A plain-language look at access, hours, and who qualifies.', editor:'AL', updated:'May 18', words:520, source:'ai' },
];

function stageMeta(s){
  if(s==='published') return ['live','LIVE'];
  if(s==='review')    return ['warn','IN REVIEW'];
  if(s==='scheduled') return ['info','SCHEDULED'];
  return ['muted','DRAFT'];
}

function studioInp(h){
  const base = {width:'100%',padding:'8px 10px',border:'1px solid var(--rule-line)',background:'var(--bg)',fontSize:13,outline:'none',resize:'vertical',display:'block',fontFamily:'var(--sans)'};
  if(h) base.minHeight = h;
  return base;
}

function EditorialStudio({setRoute}){
  const [pieces, setPieces] = React.useState(SEED_PIECES);
  const [view, setView]     = React.useState('brief');
  const [llmOn, setLlmOn]   = React.useState(typeof window!=='undefined' && window.claude && typeof window.claude.complete==='function');

  const [topic, setTopic]   = React.useState('');
  const [desk, setDesk]     = React.useState('Business');
  const [city, setCity]     = React.useState('Charlotte');
  const [tone, setTone]     = React.useState('Reported');
  const [length, setLength] = React.useState('Standard');
  const [notes, setNotes]   = React.useState('');
  const [outlineFirst, setOutlineFirst] = React.useState(true);

  const [headline, setHeadline] = React.useState('');
  const [dek, setDek]           = React.useState('');
  const [outline, setOutline]   = React.useState([]);
  const [body, setBody]         = React.useState('');
  const [slug, setSlug]         = React.useState('');
  const [meta, setMeta]         = React.useState('');
  const [rights, setRights]     = React.useState('Original');
  const [sponsor, setSponsor]   = React.useState('');
  const [cites, setCites]       = React.useState([]);
  const [genNote, setGenNote]   = React.useState('');
  const [genErr, setGenErr]     = React.useState('');

  const [when, setWhen]   = React.useState('now');
  const [toNL, setToNL]   = React.useState(true);
  const [nlPick, setNlPick] = React.useState('TUEPAC Daily · Network');

  const words = body.trim() ? body.trim().split(/\s+/).length : 0;

  function reset(){
    setTopic(''); setNotes(''); setHeadline(''); setDek(''); setOutline([]); setBody('');
    setSlug(''); setMeta(''); setRights('Original'); setSponsor(''); setCites([]);
    setGenNote(''); setGenErr(''); setView('brief');
  }

  function suggestCites(){
    const all = window.PUBLISHERS || [];
    const local = all.filter(p=>p.city===city);
    const rest  = all.filter(p=>p.city!==city);
    return [...local, ...rest].slice(0,3).map(p=>p.id);
  }

  async function generate(){
    if(!topic.trim()) return;
    setView('generating'); setGenErr('');
    const paras = length==='Brief' ? '3-4' : length==='Feature' ? '7-9' : '5-6';
    const prompt = `You are a senior editor at TUEPAC, a network of Black-owned and Black-led North Carolina news publishers. Voice: institutional, factual, community-grounded, not promotional.
Write a ${tone.toLowerCase()} ${length.toLowerCase()} piece for the ${desk} desk.
TOPIC / ANGLE: ${topic}
CITY FOCUS: ${city}
${notes.trim()?'EDITOR NOTES: '+notes.trim():''}
Return ONLY valid minified JSON, no markdown, with keys:
"headline" (<=14 words, specific, no clickbait),
"dek" (one sentence summary),
"outline" (array of ${outlineFirst?'4-6':'3-4'} short section labels),
"body" (array of ${paras} paragraph strings, plain text),
"slug" (lowercase-hyphenated),
"meta" (<=155 char SEO description).`;

    let parsed = null;
    if(llmOn){
      try{
        const raw = await window.claude.complete(prompt);
        const clean = String(raw).replace(/```json|```/g,'').trim();
        const s = clean.indexOf('{'), e = clean.lastIndexOf('}');
        parsed = JSON.parse(clean.slice(s, e+1));
        if(!parsed.headline || !parsed.body) throw new Error('thin');
        setGenNote('Drafted with Claude · review required before publish');
      }catch(err){
        parsed = null;
        setGenErr('Live model unavailable — used scripted draft. '+(err.message||''));
      }
    }
    if(!parsed) parsed = scriptedDraft({topic,desk,city,tone,length,notes});

    setHeadline(parsed.headline||'');
    setDek(parsed.dek||'');
    setOutline(Array.isArray(parsed.outline)?parsed.outline:[]);
    setBody((Array.isArray(parsed.body)?parsed.body:[String(parsed.body||'')]).join('\n\n'));
    setSlug(parsed.slug || (parsed.headline||'untitled').toLowerCase().replace(/[^a-z0-9]+/g,'-').replace(/^-|-$/g,'').slice(0,60));
    setMeta(parsed.meta || parsed.dek || '');
    setCites(suggestCites());
    if(!llmOn) setGenNote('Scripted draft · live model not detected in this environment');
    setView('draft');
  }

  function finalize(){
    const id = 'OR-' + (212 + pieces.filter(p=>p.id.startsWith('OR-2')).length);
    const stage = when==='now' ? 'published' : 'scheduled';
    const piece = { id, stage, desk, city, tone, headline, dek, editor: (window.OPERATOR?window.OPERATOR.initials:'MW'), updated:'now', words, source: llmOn?'ai':'staff' };
    setPieces([piece, ...pieces]);
    setView('done');
  }

  return (
    <AdminShell route="studio" setRoute={setRoute} title="Editorial studio" breadcrumb="CONTENT · TUEPAC ORIGINALS"
      actions={<>
        <span className="pill muted" style={{marginRight:2}}>
          <span className="d" style={{background:llmOn?'#1f8a5b':'var(--gold-2)'}}></span>{llmOn?'AI ASSIST ON':'SCRIPTED MODE'}
        </span>
        <button className="btn gh" onClick={()=>setLlmOn(v=>!v)}>{llmOn?'Use scripted':'Use AI'}</button>
        <button className="btn g" onClick={()=>{reset();}}>+ New original</button>
      </>}>

      <div className="split-4" style={{marginBottom:18}}>
        <Stat n={String(pieces.length)} l="Pieces in studio" d="originals only"/>
        <Stat n={String(pieces.filter(p=>p.source==='ai').length)} l="AI-assisted drafts" d="this cycle" up={true}/>
        <Stat n={String(pieces.filter(p=>p.stage==='review'||p.stage==='draft').length)} l="Awaiting edit/review" d="needs an editor" up={false}/>
        <Stat n={String(pieces.filter(p=>p.stage==='published').length)} l="Originals live" d="published"/>
      </div>

      <div style={{display:'grid',gridTemplateColumns:'300px 1fr',gap:18,alignItems:'flex-start'}}>
        <Card title="Originals" meta={`${pieces.length}`}>
          <div style={{display:'flex',flexDirection:'column'}}>
            {pieces.map(p=>{
              const [k,lbl] = stageMeta(p.stage);
              return (
                <div key={p.id} style={{padding:'10px 0',borderBottom:'1px solid var(--rule-line)',display:'flex',flexDirection:'column',gap:5}}>
                  <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',gap:8}}>
                    <span className="mono" style={{fontSize:9.5,color:'var(--mute)',letterSpacing:'.06em'}}>{p.id} · {p.desk.toUpperCase()}</span>
                    <Pill k={k}>{lbl}</Pill>
                  </div>
                  <div className="serif" style={{fontSize:14.5,fontWeight:700,lineHeight:1.18,letterSpacing:'-.005em',textWrap:'pretty'}}>{p.headline}</div>
                  <div className="mono" style={{fontSize:9.5,color:'var(--mute)',letterSpacing:'.04em'}}>
                    {p.source==='ai'?'\u2726 AI ':'\u270e '}{p.editor} · {p.words}w · {p.updated}
                  </div>
                </div>
              );
            })}
          </div>
        </Card>

        <div>
          <StudioRail view={view}/>
          {view==='brief' && (
            <Card title="Story brief" meta="define the assignment"
              actions={<button className="btn k" onClick={generate} disabled={!topic.trim()} style={{opacity:topic.trim()?1:.4}}>{outlineFirst?'Generate outline + draft →':'Generate draft →'}</button>}>
              <div className="eyebrow" style={{marginBottom:6}}>TOPIC / ANGLE</div>
              <textarea value={topic} onChange={e=>setTopic(e.target.value)} placeholder="e.g. How the West End façade-grant fund will actually reach small Black-owned businesses — eligibility, timeline, and who decides"
                style={studioInp(64)}/>
              <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:14,marginTop:14}}>
                <div>
                  <div className="eyebrow" style={{marginBottom:6}}>DESK</div>
                  <select value={desk} onChange={e=>setDesk(e.target.value)} style={studioInp()}>{DESKS.map(d=><option key={d}>{d}</option>)}</select>
                </div>
                <div>
                  <div className="eyebrow" style={{marginBottom:6}}>CITY FOCUS</div>
                  <select value={city} onChange={e=>setCity(e.target.value)} style={studioInp()}>{STUDIO_CITIES.map(c=><option key={c}>{c}</option>)}</select>
                </div>
              </div>
              <div style={{display:'flex',gap:24,marginTop:14,flexWrap:'wrap'}}>
                <div>
                  <div className="eyebrow" style={{marginBottom:6}}>TREATMENT</div>
                  <Seg value={tone} onChange={setTone} options={['Reported','Analysis','Opinion','Explainer']}/>
                </div>
                <div>
                  <div className="eyebrow" style={{marginBottom:6}}>LENGTH</div>
                  <Seg value={length} onChange={setLength} options={['Brief','Standard','Feature']}/>
                </div>
              </div>
              <div className="eyebrow" style={{margin:'14px 0 6px'}}>SOURCE NOTES / FACTS TO INCLUDE <span style={{color:'var(--mute)',letterSpacing:'.04em',textTransform:'none'}}>· optional</span></div>
              <textarea value={notes} onChange={e=>setNotes(e.target.value)} placeholder="Paste figures, quotes, links, or publisher reports the writer should ground the piece in."
                style={studioInp(56)}/>
              <label style={{display:'flex',alignItems:'center',gap:8,marginTop:14,cursor:'default',fontSize:12}}>
                <input type="checkbox" checked={outlineFirst} onChange={e=>setOutlineFirst(e.target.checked)}/>
                Build a section outline before the full draft
              </label>
              <div style={{marginTop:14,padding:'10px 12px',background:'var(--paper)',border:'1px solid var(--rule-line)',fontSize:11.5,color:'var(--ink-2)',lineHeight:1.5}}>
                <span className="mono" style={{fontSize:9,letterSpacing:'.14em',color:'var(--mute)'}}>EDITORIAL POLICY</span><br/>
                AI drafts are <b>internal assists only</b>. Nothing publishes without an editor's review — every original carries a human byline, disclosure, and the TUEPAC standards check.
              </div>
            </Card>
          )}

          {view==='generating' && (
            <Card title="Drafting" meta={llmOn?'claude-haiku':'scripted'}>
              <div style={{padding:'30px 0',textAlign:'center'}}>
                <div className="mono" style={{fontSize:10.5,letterSpacing:'.18em',color:'var(--mute)',textTransform:'uppercase'}}>{llmOn?'Generating draft from your brief…':'Composing scripted draft…'}</div>
                <div style={{marginTop:18,display:'flex',flexDirection:'column',gap:8,maxWidth:520,marginInline:'auto'}}>
                  {[88,72,94,64,80].map((w,i)=><div key={i} style={{height:9,width:w+'%',background:'linear-gradient(90deg,var(--rule-line),var(--canvas))',animation:`stpulse 1.1s ${i*0.12}s ease-in-out infinite`}}/>) }
                </div>
              </div>
            </Card>
          )}

          {view==='draft' && (
            <DraftEditor {...{headline,setHeadline,dek,setDek,outline,setOutline,body,setBody,slug,setSlug,meta,setMeta,
              rights,setRights,sponsor,setSponsor,cites,setCites,desk,city,tone,words,genNote,genErr,llmOn,
              onRegen:generate,onBack:()=>setView('brief'),onNext:()=>setView('publish')}}/>
          )}

          {view==='publish' && (
            <PublishPanel {...{headline,dek,desk,city,rights,sponsor,slug,words,cites,when,setWhen,toNL,setToNL,nlPick,setNlPick,
              onBack:()=>setView('draft'),onPublish:finalize}}/>
          )}

          {view==='done' && (
            <Card title="Published" meta={when==='now'?'live now':'scheduled'}>
              <div style={{padding:'18px 0 8px',display:'flex',gap:16,alignItems:'flex-start'}}>
                <div style={{width:44,height:44,flex:'0 0 auto',background:'var(--green)',color:'var(--ivory)',display:'flex',alignItems:'center',justifyContent:'center',fontSize:22,fontWeight:700}}>✓</div>
                <div>
                  <div className="serif" style={{fontSize:22,fontWeight:700,letterSpacing:'-.01em',lineHeight:1.12,textWrap:'pretty'}}>{headline}</div>
                  <div className="mono" style={{fontSize:10.5,color:'var(--mute)',letterSpacing:'.06em',marginTop:8}}>
                    {when==='now'?'PUBLISHED · LIVE NOW':'SCHEDULED'} · {desk.toUpperCase()} · {city.toUpperCase()} · TUEPAC ORIGINAL · {rights.toUpperCase()}
                  </div>
                  {toNL && <div className="mono" style={{fontSize:10.5,color:'var(--green)',letterSpacing:'.06em',marginTop:5}}>✓ QUEUED FOR “{nlPick}”</div>}
                  <div style={{display:'flex',gap:8,marginTop:16}}>
                    <button className="btn g" onClick={reset}>+ Draft another</button>
                    <button className="btn gh" onClick={()=>setRoute('desk')}>Open content desk →</button>
                  </div>
                </div>
              </div>
            </Card>
          )}
        </div>
      </div>

      <style>{`@keyframes stpulse{0%,100%{opacity:.45}50%{opacity:1}}`}</style>
    </AdminShell>
  );
}

function StudioRail({view}){
  const steps = [['brief','Brief'],['generating','Generate'],['draft','Draft & edit'],['publish','Publish']];
  const order = ['brief','generating','draft','publish','done'];
  const cur = order.indexOf(view);
  return (
    <div style={{display:'flex',alignItems:'center',gap:0,marginBottom:14}}>
      {steps.map(([k,lbl],i)=>{
        const idx = order.indexOf(k);
        const active = view===k || (view==='done'&&k==='publish');
        const done = idx < cur;
        return (
          <React.Fragment key={k}>
            <div style={{display:'flex',alignItems:'center',gap:7}}>
              <span style={{width:20,height:20,display:'flex',alignItems:'center',justifyContent:'center',fontFamily:'var(--mono)',fontSize:10,fontWeight:600,
                background:active?'var(--black)':done?'var(--green)':'var(--bg)',color:active||done?'var(--ivory)':'var(--mute)',border:'1px solid '+(active?'var(--black)':done?'var(--green)':'var(--rule-line)')}}>{done?'✓':i+1}</span>
              <span className="mono" style={{fontSize:10,letterSpacing:'.1em',textTransform:'uppercase',color:active?'var(--ink)':'var(--mute)',fontWeight:active?600:400}}>{lbl}</span>
            </div>
            {i<steps.length-1 && <div style={{flex:'0 0 28px',height:1,background:'var(--rule-line)',margin:'0 10px'}}/>}
          </React.Fragment>
        );
      })}
    </div>
  );
}

function DraftEditor(p){
  const all = window.PUBLISHERS || [];
  function toggleCite(id){ p.setCites(p.cites.includes(id)?p.cites.filter(x=>x!==id):[...p.cites,id]); }
  return (
    <div style={{display:'grid',gridTemplateColumns:'1fr 280px',gap:18,alignItems:'flex-start'}}>
      <Card title="Draft" meta={`${p.words} words · editable`}
        actions={<>
          <button className="btn gh" onClick={p.onRegen}>↻ Regenerate</button>
          <button className="btn k" onClick={p.onNext}>Review & publish →</button>
        </>}>
        {(p.genNote||p.genErr) && (
          <div style={{padding:'7px 10px',marginBottom:12,fontSize:10.5,lineHeight:1.45,
            background:p.genErr?'rgba(214,161,58,.1)':'rgba(31,46,79,.05)',border:'1px solid '+(p.genErr?'rgba(185,134,32,.32)':'rgba(31,46,79,.16)'),color:p.genErr?'var(--gold-2)':'var(--navy)'}}>
            <span className="mono" style={{fontSize:9,letterSpacing:'.12em'}}>{p.genErr?'⚠ FALLBACK':'✦ AI DRAFT'}</span> · {p.genErr||p.genNote}
          </div>
        )}

        {p.outline.length>0 && (
          <details style={{marginBottom:14}}>
            <summary className="mono" style={{fontSize:9.5,letterSpacing:'.14em',color:'var(--mute)',textTransform:'uppercase',cursor:'default'}}>SECTION OUTLINE · {p.outline.length}</summary>
            <ol style={{margin:'8px 0 0',paddingLeft:18,fontSize:12,color:'var(--ink-2)',lineHeight:1.7}}>
              {p.outline.map((o,i)=><li key={i}>{o}</li>)}
            </ol>
          </details>
        )}

        <div className="eyebrow" style={{marginBottom:5}}>HEADLINE</div>
        <textarea value={p.headline} onChange={e=>p.setHeadline(e.target.value)} className="serif"
          style={{...studioInp(54),fontSize:24,fontWeight:700,lineHeight:1.1,letterSpacing:'-.01em'}}/>

        <div className="eyebrow" style={{margin:'12px 0 5px'}}>DEK</div>
        <textarea value={p.dek} onChange={e=>p.setDek(e.target.value)} style={{...studioInp(50),fontFamily:'var(--serif)',fontSize:15}}/>

        <div className="eyebrow" style={{margin:'12px 0 5px'}}>BODY</div>
        <textarea value={p.body} onChange={e=>p.setBody(e.target.value)}
          style={{...studioInp(360),fontFamily:'IBM Plex Serif, Georgia, serif',fontSize:14.5,lineHeight:1.65}}/>
      </Card>

      <div style={{display:'flex',flexDirection:'column',gap:14}}>
        <Card title="Rights & disclosure">
          <Seg value={p.rights} onChange={p.setRights} options={['Original','Sponsored']}/>
          {p.rights==='Sponsored' && (
            <input value={p.sponsor} onChange={e=>p.setSponsor(e.target.value)} placeholder="Sponsor name" style={{...studioInp(),marginTop:10}}/>
          )}
          <div style={{marginTop:10,fontSize:11,color:'var(--ink-2)',lineHeight:1.5}}>
            {p.rights==='Sponsored'
              ? 'Runs with a clear sponsored-content disclosure label.'
              : 'TUEPAC-commissioned. Carries a staff byline and canonical on tuepac.com.'}
          </div>
        </Card>

        <Card title="Cite publishers" meta={`${p.cites.length} added`}>
          <div style={{fontSize:11,color:'var(--mute)',marginBottom:8,lineHeight:1.4}}>Credit network reporting this piece draws on.</div>
          {all.map(pub=>{
            const on = p.cites.includes(pub.id);
            return (
              <div key={pub.id} onClick={()=>toggleCite(pub.id)} style={{display:'flex',alignItems:'center',gap:8,padding:'6px 0',borderBottom:'1px solid var(--rule-line)',cursor:'default'}}>
                <span style={{width:18,height:18,flex:'0 0 auto',background:`var(--${pub.color})`,color:pub.color==='gold'?'var(--black)':'var(--ivory)',fontFamily:'var(--serif)',fontWeight:800,fontSize:9.5,display:'flex',alignItems:'center',justifyContent:'center'}}>{pub.short[0]}</span>
                <span style={{flex:1,fontSize:11.5,whiteSpace:'nowrap',overflow:'hidden',textOverflow:'ellipsis'}}>{pub.name}</span>
                <span className="mono" style={{fontSize:13,color:on?'var(--green)':'var(--rule-line)',fontWeight:700}}>{on?'✓':'+'}</span>
              </div>
            );
          })}
        </Card>

        <Card title="SEO">
          <div className="eyebrow" style={{marginBottom:5}}>SLUG</div>
          <div style={{display:'flex',alignItems:'center',border:'1px solid var(--rule-line)',background:'var(--canvas)'}}>
            <span className="mono" style={{fontSize:10,color:'var(--mute)',padding:'0 0 0 8px'}}>/{p.desk.toLowerCase()}/</span>
            <input value={p.slug} onChange={e=>p.setSlug(e.target.value)} style={{...studioInp(),border:0,background:'transparent',padding:'7px 8px'}}/>
          </div>
          <div className="eyebrow" style={{margin:'12px 0 5px'}}>META DESCRIPTION</div>
          <textarea value={p.meta} onChange={e=>p.setMeta(e.target.value)} maxLength={180} style={studioInp(56)}/>
          <div className="mono" style={{fontSize:9,color:'var(--mute)',textAlign:'right',marginTop:3}}>{p.meta.length}/155</div>
          <div style={{marginTop:10,padding:'9px 11px',background:'var(--bg)',border:'1px solid var(--rule-line)'}}>
            <div className="mono" style={{fontSize:9,letterSpacing:'.1em',color:'var(--mute)',marginBottom:4}}>OG PREVIEW</div>
            <div style={{fontSize:12.5,color:'#1a4b8c',fontWeight:600,lineHeight:1.2,textWrap:'pretty'}}>{p.headline||'Headline preview'}</div>
            <div style={{fontSize:10.5,color:'var(--green)',fontFamily:'var(--mono)',marginTop:2}}>tuepac.com › {p.desk.toLowerCase()} › {p.slug||'slug'}</div>
            <div style={{fontSize:11,color:'var(--mute)',marginTop:3,lineHeight:1.4}}>{p.meta||p.dek}</div>
          </div>
        </Card>
      </div>
    </div>
  );
}

function PublishPanel(p){
  const nls = (window.NEWSLETTERS||[]).map(n=>n.name);
  return (
    <Card title="Review & publish" meta="final check"
      actions={<>
        <button className="btn gh" onClick={p.onBack}>← Back to draft</button>
        <button className="btn g" onClick={p.onPublish}>{p.when==='now'?'Publish now':'Schedule'} →</button>
      </>}>
      <div style={{display:'grid',gridTemplateColumns:'1fr 240px',gap:20,alignItems:'flex-start'}}>
        <div>
          <div className="mono" style={{fontSize:9.5,letterSpacing:'.14em',color:'var(--mute)'}}>TUEPAC ORIGINAL · {p.desk.toUpperCase()} · {p.city.toUpperCase()}</div>
          <div className="serif" style={{fontSize:28,fontWeight:700,letterSpacing:'-.012em',lineHeight:1.05,margin:'8px 0 8px',textWrap:'pretty'}}>{p.headline}</div>
          <div className="serif" style={{fontSize:15,fontStyle:'italic',color:'var(--ink-2)',lineHeight:1.4,textWrap:'pretty'}}>{p.dek}</div>
          <div style={{display:'flex',gap:8,marginTop:14,flexWrap:'wrap'}}>
            <Pill k="k">{p.rights==='Sponsored'?'SPONSORED · '+(p.sponsor||'sponsor'):'ORIGINAL'}</Pill>
            <Pill k="muted">{p.words} WORDS</Pill>
            <Pill k="muted">/{p.desk.toLowerCase()}/{p.slug}</Pill>
            {p.cites.map(id=>{const pub=window.PUB_BY_ID[id];return <Pill key={id} k="info">CITES {pub.short}</Pill>;})}
          </div>
          <div style={{marginTop:16,paddingTop:14,borderTop:'1px solid var(--rule-line)'}}>
            <div className="eyebrow" style={{marginBottom:8}}>STANDARDS CHECK</div>
            {[['Human editor assigned','ok'],['Byline + disclosure set','ok'],['Citations credited to publishers', p.cites.length?'ok':'warn'],['No unverified claims flagged','ok'],['Canonical + slug set','ok']].map(([k,c])=>(
              <div key={k} style={{display:'grid',gridTemplateColumns:'auto 1fr',gap:8,padding:'3px 0',alignItems:'center'}}>
                <span style={{width:14,textAlign:'center',color:c==='ok'?'var(--green)':'var(--gold-2)',fontSize:12}}>{c==='ok'?'✓':'!'}</span>
                <span style={{fontSize:12}}>{k}</span>
              </div>
            ))}
          </div>
        </div>
        <div style={{display:'flex',flexDirection:'column',gap:12}}>
          <div>
            <div className="eyebrow" style={{marginBottom:6}}>TIMING</div>
            <Seg value={p.when} onChange={p.setWhen} options={['now','schedule']}/>
          </div>
          <label style={{display:'flex',alignItems:'center',gap:8,fontSize:12,cursor:'default'}}>
            <input type="checkbox" checked={p.toNL} onChange={e=>p.setToNL(e.target.checked)}/>
            Add to a newsletter
          </label>
          {p.toNL && (
            <select value={p.nlPick} onChange={e=>p.setNlPick(e.target.value)} style={studioInp()}>{nls.map(n=><option key={n}>{n}</option>)}</select>
          )}
          <div style={{padding:'10px 12px',background:'var(--paper)',border:'1px solid var(--rule-line)',fontSize:11,color:'var(--ink-2)',lineHeight:1.5}}>
            Publishing posts this original to the public site under <b>TUEPAC Originals</b> and the {p.desk} desk{p.city!=='Statewide'?`, surfaced on the ${p.city} city page`:''}.
          </div>
        </div>
      </div>
    </Card>
  );
}

function scriptedDraft({topic,desk,city,tone,length,notes}){
  const t = topic.trim().replace(/\.$/,'');
  const cityTag = city==='Statewide'?'across North Carolina':`in ${city}`;
  const lead = tone==='Opinion'
    ? `The debate over ${stLc(t)} ${cityTag} is really a debate about who gets counted when the money moves.`
    : tone==='Explainer'
    ? `Here is a plain-language look at ${stLc(t)} — what it is, who it touches ${cityTag}, and what happens next.`
    : `A closer look at ${stLc(t)} shows a story that is bigger ${cityTag} than the headline numbers suggest.`;
  const paras = [
    lead,
    `${city==='Statewide'?'Statewide':city} organizers and Black-owned outlets have tracked this for months, and the through-line is access: who is at the table, who sees the filing first, and who is left to read about it after the vote.`,
    notes.trim()? `Records and reporting provided to TUEPAC — ${stTrim(notes,180)} — sharpen the picture and point to the next decision point.` : `TUEPAC's network of ${desk.toLowerCase()} reporters is requesting the underlying records to confirm the figures before they harden into conventional wisdom.`,
    `For readers, the practical question is simple: does this change what a family, a small business, or a congregation can actually do this year? Early signs suggest the answer depends on follow-through, not announcements.`,
    `What to watch: the timeline, the eligibility rules, and whether the institutions involved report results in public — the kind of accountability the Black press ${cityTag} has always supplied.`,
  ];
  if(length==='Feature'){
    paras.splice(3,0,`Context matters here. The pattern ${cityTag} echoes earlier rounds, when promises outpaced delivery and community outlets were the ones that kept the receipts.`);
    paras.push(`TUEPAC will update this original as publishers in the network file their own reporting and as the named institutions respond.`);
  }
  if(length==='Brief') paras.length = 3;
  return {
    headline: stCap(tone==='Opinion'?`${stCap(stLc(t))}: the question NC keeps dodging`:`${stCap(stLc(t))}, explained for ${city==='Statewide'?'NC':city}`),
    dek: `${stCap(tone.toLowerCase())} from the TUEPAC ${desk} desk on ${stLc(t)} ${cityTag}.`,
    outline: ['The lede','Why it matters','What the records show','Who it touches','What to watch'].slice(0,length==='Brief'?3:5),
    body: paras,
    slug: t.toLowerCase().replace(/[^a-z0-9]+/g,'-').replace(/^-|-$/g,'').slice(0,60),
    meta: `TUEPAC ${desk} desk: ${stTrim(t,110)} — reported ${cityTag} with credit to the Black-owned publishers covering it.`,
  };
}
function stLc(s){ return s.charAt(0).toLowerCase()+s.slice(1); }
function stCap(s){ return s.charAt(0).toUpperCase()+s.slice(1); }
function stTrim(s,n){ s=s.replace(/\s+/g,' ').trim(); return s.length>n?s.slice(0,n)+'…':s; }

window.EditorialStudio = EditorialStudio;
