// v-overview.jsx — Profit-ops command center: pacing vs target & vs last week,
// delivery focus, reviews & reputation, performance scorecard, next action.

// ─── Small shared bits ───────────────────────────────────────────────
function CompareChip({ label, delta, dir }) {
  const c = dir==='up' ? '#247a41' : dir==='down' ? '#b0341a' : '#7C675B';
  return (
    <div style={{ display:'flex', alignItems:'center', gap:6, padding:'5px 9px', background:'var(--bg-app)', border:'1px solid var(--soft-line)', borderRadius:9 }}>
      <span style={{ fontFamily:'var(--font-body)', fontSize:11, color:'var(--warm-stone)', whiteSpace:'nowrap' }}>{label}</span>
      <span style={{ display:'inline-flex', alignItems:'center', gap:2, fontFamily:'var(--font-display)', fontWeight:800, fontSize:12, color:c }}>
        {dir==='up'&&<I.trendUp c={c} s={13}/>}{dir==='down'&&<I.trendDown c={c} s={13}/>}{delta}
      </span>
    </div>
  );
}

// ─── Profit pacing hero ──────────────────────────────────────────────
function ProfitHero({ app }) {
  const p = PROFIT;
  const expectedByNow = p.revenue.target * p.pace;
  const projected = Math.round(p.revenue.now / p.pace);
  const ahead = projected >= p.revenue.target;
  const projDelta = Math.round((projected/p.revenue.target - 1)*100);
  const vsLastWeek = Math.round((p.revenue.now/p.revenue.lastWeekToDate - 1)*100);
  const vsYesterday = Math.round((p.revenue.now/p.revenue.yesterdayToDate - 1)*100);
  const pacePct = Math.min(100, Math.round(p.revenue.now/p.revenue.target*100));
  const expectedPct = Math.round(p.pace*100);
  const wfMax = Math.max(...p.waterfall.map(w=>Math.abs(w.value)));

  return (
    <Card pad={0} style={{ overflow:'hidden', marginBottom:16 }}>
      <div style={{ display:'grid', gridTemplateColumns:'1.5fr 1fr' }}>
        {/* pacing */}
        <div style={{ padding:'20px 24px', borderRight:'1px solid var(--soft-line)' }}>
          <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', gap:12 }}>
            <Eyebrow><I.pound c="var(--brand-orange)" s={13}/> &nbsp;Profit today · live</Eyebrow>
            <Pill tone={ahead?'green':'amber'} dot>{ahead?`On track to beat target`:'Behind pace'}</Pill>
          </div>
          <div style={{ display:'flex', alignItems:'flex-end', gap:18, marginTop:14, flexWrap:'wrap' }}>
            <div>
              <div style={{ fontFamily:'var(--font-display)', fontWeight:900, fontSize:40, letterSpacing:'-0.025em', color:'var(--fg-primary)', lineHeight:0.95 }}>£{p.net.now.toLocaleString()}</div>
              <div style={{ marginTop:5, fontFamily:'var(--font-body)', fontSize:12.5, color:'var(--warm-stone)' }}>Net profit · {p.net.marginPct}% margin</div>
            </div>
            <div style={{ paddingBottom:2 }}>
              <div style={{ fontFamily:'var(--font-display)', fontWeight:900, fontSize:20, color:'var(--fg-primary)', lineHeight:1 }}>£{p.revenue.now.toLocaleString()}</div>
              <div style={{ fontFamily:'var(--font-body)', fontSize:11.5, color:'var(--warm-stone)', marginTop:3 }}>Gross sales</div>
            </div>
          </div>

          {/* pace-to-target bar */}
          <div style={{ marginTop:18 }}>
            <div style={{ display:'flex', justifyContent:'space-between', alignItems:'baseline', marginBottom:6 }}>
              <span style={{ fontFamily:'var(--font-body)', fontSize:12, color:'var(--warm-stone)' }}>Gross vs daily target</span>
              <span style={{ fontFamily:'var(--font-display)', fontWeight:800, fontSize:12.5, color:'var(--fg-primary)' }}>£{p.revenue.now.toLocaleString()} <span style={{ color:'var(--warm-stone)', fontWeight:600 }}>/ £{p.revenue.target.toLocaleString()}</span></span>
            </div>
            <div style={{ position:'relative', height:12, background:'rgba(27,18,13,0.07)', borderRadius:999, overflow:'visible' }}>
              <div style={{ width:`${pacePct}%`, height:'100%', background: ahead?'linear-gradient(90deg,#2E8B4E,#3aa861)':'linear-gradient(90deg,#E0992A,#caa24e)', borderRadius:999, transition:'width 600ms var(--ease-out)' }}/>
              {/* "where you should be by now" marker */}
              <div style={{ position:'absolute', left:`${expectedPct}%`, top:-3, bottom:-3, width:2, background:'var(--dark-chocolate)', borderRadius:2 }}/>
              <div style={{ position:'absolute', left:`${expectedPct}%`, top:-17, transform:'translateX(-50%)', fontFamily:'var(--font-mono)', fontSize:9, color:'var(--horse-brown)', whiteSpace:'nowrap' }}>pace</div>
            </div>
            <div style={{ marginTop:9, fontFamily:'var(--font-body)', fontSize:12.5, color:'var(--warm-stone)' }}>
              Projected close <strong style={{ color:'var(--fg-primary)', fontFamily:'var(--font-display)' }}>£{projected.toLocaleString()}</strong> — {ahead?<span style={{ color:'#247a41', fontFamily:'var(--font-display)', fontWeight:700 }}>{projDelta>=0?'+':''}{projDelta}% over target</span>:<span style={{ color:'#b0341a', fontFamily:'var(--font-display)', fontWeight:700 }}>{projDelta}% under target</span>}
            </div>
          </div>

          {/* comparisons */}
          <div style={{ display:'flex', gap:9, marginTop:16, flexWrap:'wrap' }}>
            <CompareChip label="vs same time last week" delta={`${vsLastWeek>=0?'+':''}${vsLastWeek}%`} dir={vsLastWeek>=0?'up':'down'}/>
            <CompareChip label="vs yesterday" delta={`${vsYesterday>=0?'+':''}${vsYesterday}%`} dir={vsYesterday>=0?'up':'down'}/>
            <CompareChip label="Orders" delta={`${p.orders.now}/${p.orders.target}`} dir="flat"/>
          </div>
        </div>

        {/* profit waterfall */}
        <div style={{ padding:'20px 22px', background:'var(--bg-app)' }}>
          <Eyebrow style={{ marginBottom:14 }}>Where today's £ goes</Eyebrow>
          <div style={{ display:'flex', flexDirection:'column', gap:11 }}>
            {p.waterfall.map(w=>{
              const isNeg = w.value<0;
              const col = w.kind==='end'?'#2E8B4E': w.kind==='start'?'var(--horse-brown)':'#C13B1F';
              return (
                <div key={w.label}>
                  <div style={{ display:'flex', justifyContent:'space-between', marginBottom:4 }}>
                    <span style={{ fontFamily:'var(--font-body)', fontSize:11.5, color:'var(--warm-stone)', whiteSpace:'nowrap' }}>{w.label}</span>
                    <span style={{ fontFamily:'var(--font-display)', fontWeight:800, fontSize:12.5, color: isNeg?'#b0341a':'var(--fg-primary)' }}>{isNeg?'−':''}£{Math.abs(w.value).toLocaleString()}</span>
                  </div>
                  <Bar pct={Math.abs(w.value)/wfMax*100} color={col} h={ w.kind==='end'||w.kind==='start'?9:6 }/>
                </div>
              );
            })}
          </div>
        </div>
      </div>
    </Card>
  );
}

// ─── KPI comparison tile (target + vs last week) ─────────────────────
function KpiTile({ k }) {
  const Icon = I[k.icon] || I.grid;
  const dirColor = k.dir==='up' ? '#247a41' : k.dir==='down' ? '#b0341a' : '#7C675B';
  const hitTarget = k.targetMet;
  return (
    <Card pad={16} hover>
      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between' }}>
        <div style={{ width:34, height:34, borderRadius:10, background:'var(--bg-warm)', display:'flex', alignItems:'center', justifyContent:'center' }}><Icon c="var(--brand-orange)" s={18}/></div>
        <span style={{ display:'inline-flex', alignItems:'center', gap:3, fontFamily:'var(--font-display)', fontWeight:800, fontSize:11.5, color:dirColor }}>
          {k.dir==='up'&&<I.trendUp c={dirColor} s={14}/>}{k.dir==='down'&&<I.trendDown c={dirColor} s={14}/>}{k.delta}
        </span>
      </div>
      <div style={{ marginTop:13, fontFamily:'var(--font-display)', fontWeight:900, fontSize:26, letterSpacing:'-0.02em', color:'var(--fg-primary)', lineHeight:1 }}>{k.value}</div>
      <div style={{ marginTop:6, fontFamily:'var(--font-display)', fontWeight:700, fontSize:12.5, color:'var(--fg-primary)' }}>{k.label}</div>
      <div style={{ marginTop:6, display:'flex', alignItems:'center', gap:6 }}>
        <span style={{ display:'inline-flex', alignItems:'center', gap:3, fontFamily:'var(--font-display)', fontWeight:700, fontSize:10.5, color: hitTarget?'#247a41':'#a86d12' }}>
          {hitTarget?<I.check c="#247a41" s={12}/>:<I.target c="#a86d12" s={11}/>}{k.target}
        </span>
        <span style={{ fontFamily:'var(--font-body)', fontSize:10.5, color:'var(--warm-stone)' }}>· {k.sub}</span>
      </div>
    </Card>
  );
}

// ─── Performance scorecard row ───────────────────────────────────────
function ScoreRow({ m, last }) {
  const good = m.good==='high' ? m.value>=m.target : m.value<=m.target;
  const fmt = (v)=> m.id==='cancel' ? v.toFixed(1)+m.unit : v+m.unit;
  return (
    <div style={{ display:'grid', gridTemplateColumns:'1.5fr 0.9fr 1fr 0.8fr', gap:12, alignItems:'center', padding:'13px 0', borderBottom: last?'none':'1px solid var(--soft-line)' }}>
      <div style={{ display:'flex', alignItems:'center', gap:8 }}>
        <span style={{ width:8, height:8, borderRadius:'50%', background: good?'#2E8B4E':'#E0992A', flexShrink:0 }}/>
        <span style={{ fontFamily:'var(--font-display)', fontWeight:700, fontSize:13, color:'var(--fg-primary)', whiteSpace:'nowrap' }}>{m.label}</span>
      </div>
      <div style={{ fontFamily:'var(--font-display)', fontWeight:900, fontSize:18, color:'var(--fg-primary)' }}>{fmt(m.value)}</div>
      <div style={{ display:'flex', alignItems:'center', gap:8 }}>
        <Spark data={m.spark} color={good?'#2E8B4E':'#E0992A'} h={20} w={52} bars={false}/>
        <span style={{ fontFamily:'var(--font-body)', fontSize:10.5, color:'var(--warm-stone)' }}>{m.vsLastWeek}</span>
      </div>
      <div style={{ textAlign:'right' }}>
        <span style={{ display:'inline-flex', alignItems:'center', gap:3, fontFamily:'var(--font-display)', fontWeight:700, fontSize:11, color: good?'#247a41':'#a86d12', whiteSpace:'nowrap' }}>
          {good?<I.check c="#247a41" s={12}/>:<I.alert c="#a86d12" s={12}/>}{fmt(m.target)}
        </span>
      </div>
    </div>
  );
}

// ─── Delivery focus ──────────────────────────────────────────────────
function DeliveryCard() {
  const d = DELIVERY;
  const distMax = Math.max(...d.dist.map(x=>x.pct));
  return (
    <Card>
      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:15 }}>
        <Eyebrow><I.truck c="var(--brand-orange)" s={13}/> &nbsp;Delivery focus</Eyebrow>
        <Pill tone={d.avgTime<=d.target?'green':'amber'} dot>{d.avgTime<=d.target?'Within target':'Over target'}</Pill>
      </div>
      <div style={{ display:'flex', alignItems:'center', gap:18 }}>
        <Ring pct={d.onTime} size={88} stroke={10} color="#D85A14">
          <div style={{ textAlign:'center' }}>
            <div style={{ fontFamily:'var(--font-display)', fontWeight:900, fontSize:21, color:'var(--fg-primary)', lineHeight:1 }}>{d.onTime}%</div>
            <div style={{ fontFamily:'var(--font-body)', fontSize:9, color:'var(--warm-stone)' }}>on-time</div>
          </div>
        </Ring>
        <div style={{ flex:1, display:'grid', gridTemplateColumns:'1fr 1fr', gap:'12px 14px' }}>
          {[['Avg delivery',`${d.avgTime} min`,`target ${d.target}`],['vs last week',`${d.lastWeekTime} min`,'was slower'],['Drivers out',d.driversOut,`${d.driversIdle} idle`],['Late orders',`${d.late}%`,'of today']].map(([l,v,s])=>(
            <div key={l}>
              <div style={{ fontFamily:'var(--font-display)', fontWeight:900, fontSize:17, color:'var(--fg-primary)' }}>{v}</div>
              <div style={{ fontFamily:'var(--font-body)', fontSize:10.5, color:'var(--warm-stone)', marginTop:1 }}>{l} · {s}</div>
            </div>
          ))}
        </div>
      </div>
      <div style={{ marginTop:16, paddingTop:14, borderTop:'1px solid var(--soft-line)' }}>
        <div style={{ fontFamily:'var(--font-body)', fontSize:11, color:'var(--warm-stone)', marginBottom:9 }}>Delivery time distribution</div>
        <div style={{ display:'flex', alignItems:'flex-end', gap:8, height:54 }}>
          {d.dist.map(x=>(
            <div key={x.b} style={{ flex:1, display:'flex', flexDirection:'column', alignItems:'center', gap:5 }}>
              <span style={{ fontFamily:'var(--font-display)', fontWeight:700, fontSize:10, color:'var(--warm-stone)' }}>{x.pct}%</span>
              <div style={{ width:'100%', maxWidth:34, height:`${x.pct/distMax*36}px`, background: x.b==='35+'?'#C13B1F':'rgba(216,90,20,0.55)', borderRadius:'4px 4px 0 0' }}/>
              <span style={{ fontFamily:'var(--font-mono)', fontSize:9, color:'var(--warm-stone)' }}>{x.b}</span>
            </div>
          ))}
        </div>
      </div>
      <div style={{ marginTop:13, display:'flex', alignItems:'center', gap:8, padding:'9px 12px', background:'rgba(224,153,42,0.10)', borderRadius:10 }}>
        <I.alert c="#a86d12" s={15}/>
        <span style={{ fontFamily:'var(--font-body)', fontSize:11.5, color:'var(--horse-brown)' }}>Longest wait: <strong style={{ fontFamily:'var(--font-display)' }}>{d.longestWait}</strong></span>
      </div>
    </Card>
  );
}

// ─── Reviews & reputation ────────────────────────────────────────────
function Stars({ n, s=12 }) {
  return <span style={{ display:'inline-flex', gap:1 }}>{[1,2,3,4,5].map(i=>(
    <I.star key={i} c={i<=n?'#E0992A':'rgba(27,18,13,0.14)'} s={s}/>
  ))}</span>;
}
function ReviewsCard({ app }) {
  const r = REVIEWS;
  const [replied, setReplied] = React.useState(()=>{ const m={}; r.recent.forEach(rv=>{ if(rv.replied) m[rv.id]='__seed'; }); return m; });
  const [composer, setComposer] = React.useState(null);   // review being replied to
  const [showAll, setShowAll] = React.useState(false);
  const [filter, setFilter] = React.useState('all');
  const isReplied = (rv)=> !!replied[rv.id];
  const shown = r.recent.slice(0,4);
  const openCount = r.recent.filter(rv=>!isReplied(rv)).length;

  const send = (rv, text)=>{ setReplied(m=>({ ...m, [rv.id]:text })); setComposer(null); app.toast(`Reply sent to ${rv.name}`); };

  const ReviewRow = ({ rv, last })=>(
    <div style={{ padding:'12px 0', borderBottom: last?'none':'1px solid var(--soft-line)' }}>
      <div style={{ display:'flex', alignItems:'center', gap:9, marginBottom:5 }}>
        <Stars n={rv.stars} s={11}/>
        <span style={{ fontFamily:'var(--font-display)', fontWeight:700, fontSize:12, color:'var(--fg-primary)' }}>{rv.name}</span>
        <span style={{ fontFamily:'var(--font-body)', fontSize:10.5, color:'var(--warm-stone)' }}>· {rv.estate} · {rv.when}</span>
        {!isReplied(rv) && <Pill tone="amber" style={{ marginLeft:'auto', fontSize:9.5, padding:'2px 7px' }}>Needs reply</Pill>}
      </div>
      <p style={{ margin:'0 0 7px', fontFamily:'var(--font-body)', fontSize:12.5, color:'var(--horse-brown)', lineHeight:1.45 }}>{rv.text}</p>
      {isReplied(rv) && replied[rv.id]!=='__seed' && (
        <div style={{ margin:'0 0 8px', padding:'8px 11px', background:'var(--bg-app)', borderLeft:'2px solid var(--brand-orange)', borderRadius:'0 8px 8px 0' }}>
          <div style={{ fontFamily:'var(--font-display)', fontWeight:700, fontSize:10, letterSpacing:'0.04em', textTransform:'uppercase', color:'var(--warm-stone)', marginBottom:2 }}>Your reply</div>
          <div style={{ fontFamily:'var(--font-body)', fontSize:12, color:'var(--horse-brown)', lineHeight:1.4 }}>{replied[rv.id]}</div>
        </div>
      )}
      <div style={{ display:'flex', alignItems:'center', gap:10 }}>
        <span style={{ fontFamily:'var(--font-body)', fontSize:10.5, color:'var(--warm-stone)' }}><I.utensils c="var(--warm-stone)" s={11}/> {rv.item}</span>
        {isReplied(rv)
          ? <span style={{ marginLeft:'auto', fontFamily:'var(--font-body)', fontSize:10.5, color:'#247a41', display:'inline-flex', alignItems:'center', gap:4 }}><I.check c="#247a41" s={12}/>Replied</span>
          : <button onClick={()=>setComposer(rv)} style={{ marginLeft:'auto', fontFamily:'var(--font-display)', fontWeight:700, fontSize:11, color:'var(--brand-orange)', background:'none', border:'none', cursor:'pointer', display:'inline-flex', alignItems:'center', gap:4 }}>Reply <I.arrow c="var(--brand-orange)" s={12}/></button>}
      </div>
    </div>
  );

  const filtered = filter==='all' ? r.recent : filter==='unanswered' ? r.recent.filter(rv=>!isReplied(rv)) : r.recent.filter(rv=>String(rv.stars)===filter);

  return (
    <Card pad={0} style={{ overflow:'hidden' }}>
      <div style={{ padding:'16px 20px 14px', borderBottom:'1px solid var(--soft-line)', display:'flex', alignItems:'center', justifyContent:'space-between' }}>
        <Eyebrow><I.star c="#E0992A" s={13}/> &nbsp;Reviews &amp; reputation</Eyebrow>
        <span style={{ fontFamily:'var(--font-display)', fontWeight:800, fontSize:12, color:'var(--brand-orange)', cursor:'pointer' }} onClick={()=>setShowAll(true)}>All reviews →</span>
      </div>
      <div style={{ display:'flex', gap:18, padding:'16px 20px', borderBottom:'1px solid var(--soft-line)' }}>
        <div style={{ textAlign:'center', flexShrink:0 }}>
          <div style={{ fontFamily:'var(--font-display)', fontWeight:900, fontSize:36, color:'var(--fg-primary)', lineHeight:1 }}>{r.rating}</div>
          <div style={{ marginTop:4 }}><Stars n={Math.round(r.rating)} s={13}/></div>
          <div style={{ fontFamily:'var(--font-body)', fontSize:10.5, color:'var(--warm-stone)', marginTop:4 }}>{r.count.toLocaleString()} reviews</div>
          <span style={{ display:'inline-flex', alignItems:'center', gap:3, marginTop:5, fontFamily:'var(--font-display)', fontWeight:800, fontSize:10.5, color:'#247a41' }}><I.trendUp c="#247a41" s={12}/>{r.ratingDelta} · 30d</span>
        </div>
        <div style={{ flex:1, display:'flex', flexDirection:'column', justifyContent:'center', gap:5 }}>
          {r.dist.map(d=>(
            <div key={d.s} style={{ display:'flex', alignItems:'center', gap:8 }}>
              <span style={{ fontFamily:'var(--font-mono)', fontSize:10, color:'var(--warm-stone)', width:8 }}>{d.s}</span>
              <I.star c="#E0992A" s={10}/>
              <div style={{ flex:1 }}><Bar pct={d.pct} color={d.s>=4?'#2E8B4E':d.s===3?'#E0992A':'#C13B1F'} h={6}/></div>
              <span style={{ fontFamily:'var(--font-body)', fontSize:10, color:'var(--warm-stone)', width:26, textAlign:'right' }}>{d.pct}%</span>
            </div>
          ))}
        </div>
      </div>
      <div style={{ padding:'4px 20px 8px' }}>
        {shown.map((rv,i)=> <ReviewRow key={rv.id} rv={rv} last={i===shown.length-1}/>)}
      </div>
      <div style={{ padding:'12px 20px', borderTop:'1px solid var(--soft-line)', background:'var(--bg-app)', display:'flex', alignItems:'center', justifyContent:'space-between' }}>
        <span style={{ fontFamily:'var(--font-body)', fontSize:11.5, color:'var(--warm-stone)' }}>{openCount} review{openCount!==1?'s':''} awaiting a reply</span>
        <Btn kind="white" size="sm" onClick={()=>setShowAll(true)} icon={<I.bell c="var(--fg-primary)" s={14}/>}>Reply to reviews</Btn>
      </div>

      {composer && <ReplyComposer rv={composer} onClose={()=>setComposer(null)} onSend={send}/>}
      {showAll && <AllReviewsModal r={r} filter={filter} setFilter={setFilter} filtered={filtered} isReplied={isReplied} repliedText={replied} onReply={(rv)=>setComposer(rv)} onClose={()=>setShowAll(false)}/>}
    </Card>
  );
}

// quick-reply templates
const REPLY_TEMPLATES = [
  { tag:'Thank', text:'Thanks so much for the kind words — we love making it and can\u2019t wait to feed you again soon!' },
  { tag:'Apologise', text:'We\u2019re really sorry this one missed the mark. That\u2019s not our standard — please reach out and we\u2019ll make it right.' },
  { tag:'Missing item', text:'Apologies the order wasn\u2019t complete — we\u2019ve flagged it with the kitchen and would love to make it up to you on your next order.' },
];

function ReplyComposer({ rv, onClose, onSend }) {
  const [text, setText] = React.useState('');
  return (
    <div onClick={onClose} style={{ position:'fixed', inset:0, zIndex:360, background:'rgba(27,18,13,0.5)', backdropFilter:'blur(3px)', display:'flex', justifyContent:'center', alignItems:'flex-start', padding:'52px 22px', overflowY:'auto', animation:'v-fade 180ms' }}>
      <div onClick={(e)=>e.stopPropagation()} style={{ width:'100%', maxWidth:500, background:'var(--bg-surface)', borderRadius:20, boxShadow:'var(--shadow-lg)', overflow:'hidden', animation:'v-pop 240ms var(--ease-out)' }}>
        <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', padding:'16px 22px', borderBottom:'1px solid var(--soft-line)' }}>
          <h2 style={{ margin:0, fontFamily:'var(--font-display)', fontWeight:900, fontSize:17, color:'var(--fg-primary)' }}>Reply to {rv.name}</h2>
          <button onClick={onClose} style={{ width:34, height:34, borderRadius:10, border:'1px solid var(--soft-line)', background:'var(--bg-app)', display:'flex', alignItems:'center', justifyContent:'center', cursor:'pointer' }}><I.x c="var(--warm-stone)" s={17}/></button>
        </div>
        <div style={{ padding:'18px 22px', display:'flex', flexDirection:'column', gap:14 }}>
          <div style={{ padding:'12px 14px', background:'var(--bg-app)', borderRadius:12, border:'1px solid var(--soft-line)' }}>
            <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:5 }}><Stars n={rv.stars} s={12}/><span style={{ fontFamily:'var(--font-body)', fontSize:10.5, color:'var(--warm-stone)' }}>{rv.estate} · {rv.item}</span></div>
            <p style={{ margin:0, fontFamily:'var(--font-body)', fontSize:12.5, color:'var(--horse-brown)', lineHeight:1.45 }}>{rv.text}</p>
          </div>
          <div>
            <div style={{ fontFamily:'var(--font-display)', fontWeight:700, fontSize:10.5, letterSpacing:'0.06em', textTransform:'uppercase', color:'var(--warm-stone)', marginBottom:8 }}>Quick start</div>
            <div style={{ display:'flex', gap:7, flexWrap:'wrap' }}>
              {REPLY_TEMPLATES.map(t=>(
                <button key={t.tag} onClick={()=>setText(t.text)} style={{ padding:'6px 11px', borderRadius:9, cursor:'pointer', background:'var(--bg-app)', border:'1px solid var(--soft-line)', fontFamily:'var(--font-display)', fontWeight:700, fontSize:11.5, color:'var(--fg-primary)' }}>{t.tag}</button>
              ))}
            </div>
          </div>
          <textarea autoFocus value={text} onChange={(e)=>setText(e.target.value)} rows={4} maxLength={400} placeholder="Write a warm, personal reply…"
            style={{ width:'100%', boxSizing:'border-box', background:'var(--bg-app)', border:'1px solid var(--soft-line)', borderRadius:11, padding:'12px 13px', fontFamily:'var(--font-body)', fontSize:13, color:'var(--fg-primary)', outline:'none', resize:'vertical', lineHeight:1.5 }}/>
        </div>
        <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', gap:10, padding:'14px 22px', borderTop:'1px solid var(--soft-line)', background:'var(--bg-app)' }}>
          <span style={{ fontFamily:'var(--font-body)', fontSize:11, color:'var(--warm-stone)' }}>Public reply · shown on your Lasso page</span>
          <div style={{ display:'flex', gap:10 }}>
            <Btn kind="white" onClick={onClose}>Cancel</Btn>
            <Btn kind="accent" disabled={!text.trim()} icon={<I.arrow c="#fff" s={15}/>} onClick={()=>onSend(rv, text.trim())}>Send reply</Btn>
          </div>
        </div>
      </div>
    </div>
  );
}

function AllReviewsModal({ r, filter, setFilter, filtered, isReplied, repliedText, onReply, onClose }) {
  const filters = [['all','All'],['unanswered','Unanswered'],['5','5★'],['4','4★'],['3','3★'],['2','2★']];
  return (
    <div onClick={onClose} style={{ position:'fixed', inset:0, zIndex:350, background:'rgba(27,18,13,0.5)', backdropFilter:'blur(3px)', display:'flex', justifyContent:'center', alignItems:'flex-start', padding:'40px 22px', overflowY:'auto', animation:'v-fade 180ms' }}>
      <div onClick={(e)=>e.stopPropagation()} style={{ width:'100%', maxWidth:580, maxHeight:'calc(100vh - 80px)', background:'var(--bg-surface)', borderRadius:20, boxShadow:'var(--shadow-lg)', overflow:'hidden', display:'flex', flexDirection:'column', animation:'v-pop 240ms var(--ease-out)' }}>
        <div style={{ padding:'16px 22px', borderBottom:'1px solid var(--soft-line)' }}>
          <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:13 }}>
            <div style={{ display:'flex', alignItems:'center', gap:11 }}>
              <div style={{ display:'flex', alignItems:'baseline', gap:7 }}>
                <span style={{ fontFamily:'var(--font-display)', fontWeight:900, fontSize:22, color:'var(--fg-primary)' }}>{r.rating}</span>
                <Stars n={Math.round(r.rating)} s={13}/>
              </div>
              <span style={{ fontFamily:'var(--font-body)', fontSize:12, color:'var(--warm-stone)' }}>{r.count.toLocaleString()} reviews</span>
            </div>
            <button onClick={onClose} style={{ width:34, height:34, borderRadius:10, border:'1px solid var(--soft-line)', background:'var(--bg-app)', display:'flex', alignItems:'center', justifyContent:'center', cursor:'pointer' }}><I.x c="var(--warm-stone)" s={17}/></button>
          </div>
          <div style={{ display:'flex', gap:7, flexWrap:'wrap' }}>
            {filters.map(([v,l])=>{
              const on=filter===v;
              return <button key={v} onClick={()=>setFilter(v)} style={{ padding:'6px 12px', borderRadius:9, cursor:'pointer', background: on?'var(--dark-chocolate)':'var(--bg-app)', color: on?'var(--dust-cream)':'var(--fg-primary)', border:'1px solid', borderColor: on?'var(--dark-chocolate)':'var(--soft-line)', fontFamily:'var(--font-display)', fontWeight:700, fontSize:12 }}>{l}</button>;
            })}
          </div>
        </div>
        <div style={{ flex:1, minHeight:0, overflowY:'auto', padding:'4px 22px 12px' }}>
          {filtered.length===0 ? (
            <div style={{ padding:'40px 0', textAlign:'center', fontFamily:'var(--font-body)', fontSize:13, color:'var(--warm-stone)' }}>No reviews match this filter.</div>
          ) : filtered.map((rv,i)=>(
            <div key={rv.id} style={{ padding:'13px 0', borderBottom: i<filtered.length-1?'1px solid var(--soft-line)':'none' }}>
              <div style={{ display:'flex', alignItems:'center', gap:9, marginBottom:5 }}>
                <Stars n={rv.stars} s={11}/>
                <span style={{ fontFamily:'var(--font-display)', fontWeight:700, fontSize:12.5, color:'var(--fg-primary)' }}>{rv.name}</span>
                <span style={{ fontFamily:'var(--font-body)', fontSize:10.5, color:'var(--warm-stone)' }}>· {rv.estate} · {rv.when}</span>
                {!isReplied(rv) && <Pill tone="amber" style={{ marginLeft:'auto', fontSize:9.5, padding:'2px 7px' }}>Needs reply</Pill>}
              </div>
              <p style={{ margin:'0 0 7px', fontFamily:'var(--font-body)', fontSize:12.5, color:'var(--horse-brown)', lineHeight:1.45 }}>{rv.text}</p>
              {isReplied(rv) && repliedText[rv.id]!=='__seed' && (
                <div style={{ margin:'0 0 8px', padding:'8px 11px', background:'var(--bg-app)', borderLeft:'2px solid var(--brand-orange)', borderRadius:'0 8px 8px 0' }}>
                  <div style={{ fontFamily:'var(--font-display)', fontWeight:700, fontSize:10, letterSpacing:'0.04em', textTransform:'uppercase', color:'var(--warm-stone)', marginBottom:2 }}>Your reply</div>
                  <div style={{ fontFamily:'var(--font-body)', fontSize:12, color:'var(--horse-brown)', lineHeight:1.4 }}>{repliedText[rv.id]}</div>
                </div>
              )}
              <div style={{ display:'flex', alignItems:'center', gap:10 }}>
                <span style={{ fontFamily:'var(--font-body)', fontSize:10.5, color:'var(--warm-stone)' }}><I.utensils c="var(--warm-stone)" s={11}/> {rv.item}</span>
                {isReplied(rv)
                  ? <span style={{ marginLeft:'auto', fontFamily:'var(--font-body)', fontSize:10.5, color:'#247a41', display:'inline-flex', alignItems:'center', gap:4 }}><I.check c="#247a41" s={12}/>Replied</span>
                  : <button onClick={()=>onReply(rv)} style={{ marginLeft:'auto', fontFamily:'var(--font-display)', fontWeight:700, fontSize:11, color:'var(--brand-orange)', background:'none', border:'none', cursor:'pointer', display:'inline-flex', alignItems:'center', gap:4 }}>Reply <I.arrow c="var(--brand-orange)" s={12}/></button>}
              </div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

// ─── Recommended action (kept, lightly trimmed) ──────────────────────
function RecommendedAction({ app }) {
  const oppEstate = ESTATES.find(e=>e.id==='bletchley');
  const oppState = NODE_STATE[oppEstate.state];
  return (
    <Card pad={0} style={{ overflow:'hidden', display:'flex', flexDirection:'column' }}>
      <div style={{ padding:'18px 22px 0', display:'flex', alignItems:'center', justifyContent:'space-between' }}>
        <Eyebrow><I.zap c="var(--brand-orange)" s={13} f/> &nbsp;Recommended next action</Eyebrow>
        <Pill tone="orange">Highest ROI</Pill>
      </div>
      <div style={{ padding:'14px 22px 20px', display:'flex', gap:20, alignItems:'center', flex:1 }}>
        <div style={{ flex:1 }}>
          <h3 style={{ margin:'0 0 7px', fontFamily:'var(--font-display)', fontWeight:900, fontSize:20, color:'var(--fg-primary)', lineHeight:1.15 }}>Launch a first-order discount in {oppEstate.name}</h3>
          <p style={{ margin:'0 0 14px', fontFamily:'var(--font-body)', fontSize:13, color:'var(--warm-stone)', lineHeight:1.55 }}>
            {oppEstate.interest} customers want pizza &amp; wings but haven't ordered from you. Demand up {oppEstate.trendPct}% with only {oppEstate.influence}% influence held.
          </p>
          <div style={{ display:'flex', gap:22, marginBottom:16 }}>
            {[['Est. new orders','+22–31'],['Est. revenue','£480–690'],['Expected ROI','4.2–6.1×']].map(([l,v])=>(
              <div key={l}><div style={{ fontFamily:'var(--font-display)', fontWeight:900, fontSize:18, color:'var(--fg-primary)' }}>{v}</div><div style={{ fontFamily:'var(--font-body)', fontSize:11, color:'var(--warm-stone)', marginTop:2 }}>{l}</div></div>
            ))}
          </div>
          <div style={{ display:'flex', gap:10 }}>
            <Btn kind="accent" icon={<I.rocket c="#fff" s={16}/>} onClick={()=>app.openBuilder(oppEstate.id)}>Build this campaign</Btn>
            <Btn kind="white" onClick={()=>{ app.setSelected(oppEstate.id); app.nav('map'); }}>View on map</Btn>
          </div>
        </div>
        <div style={{ width:140, flexShrink:0, alignSelf:'stretch', borderRadius:14, background:oppState.soft, border:`1px solid ${oppState.ring}33`, display:'flex', flexDirection:'column', alignItems:'center', justifyContent:'center', gap:8, padding:16 }}>
          <Ring pct={oppEstate.opportunity} size={82} stroke={9} color={oppState.fill}>
            <div style={{ textAlign:'center' }}>
              <div style={{ fontFamily:'var(--font-display)', fontWeight:900, fontSize:21, color:'var(--fg-primary)', lineHeight:1 }}>{oppEstate.opportunity}</div>
              <div style={{ fontFamily:'var(--font-body)', fontSize:9, color:'var(--warm-stone)' }}>opp. score</div>
            </div>
          </Ring>
          <div style={{ fontFamily:'var(--font-display)', fontWeight:800, fontSize:12.5, color:'var(--fg-primary)' }}>{oppEstate.name}</div>
          <Pill tone="green" dot>Top opportunity</Pill>
        </div>
      </div>
    </Card>
  );
}

// ─── Screen ──────────────────────────────────────────────────────────
// ─── Growth systems row — surfaces the newer management panels ──────
function SystemsRow({ app }) {
  const tc = window.TRAIL_CHALLENGES || [];
  const active = tc.filter(c=>c.status==='active').length;
  const completions = tc.reduce((s,c)=>s+(c.completions||0),0);
  const media = window.MEDIA_ASSETS || [];
  const mLive = media.filter(a=>a.status==='live').length;
  const mProc = media.filter(a=>a.status==='processing'||a.status==='uploading').length;
  const liveCamps = ACTIVE_CAMPAIGNS.filter(c=>c.status==='live'||c.status==='ending').length;
  const invites = (window.STAFF_INVITES||[]).filter(i=>i.status==='pending').length;
  const cards = [
    { id:'trail',   icon:I.target,    title:'Trail challenges', main:`${active} active`, sub:`${completions} completions · ${tc.length} total`, pill:{tone:'green',label:'Running'}, nav:'trail' },
    { id:'lucky',   icon:I.sparkle,   title:'Lucky Strike',     main:'Not live',         sub:'Draw engine contract pending',                 pill:{tone:'amber',label:'Pending'}, nav:'trail' },
    { id:'topc',    icon:I.crown,     title:'Top customers',    main:'Awaiting view',     sub:'Needs privacy-safe top_customers RPC',          pill:{tone:'amber',label:'Pending'}, nav:'trail' },
    { id:'camps',   icon:I.megaphone, title:'Campaigns & rewards', main:`${liveCamps} live`, sub:`${ACTIVE_CAMPAIGNS.length} campaigns this month`, pill:{tone:'purple',label:'Active'}, nav:'campaigns' },
    { id:'media',   icon:I.image,     title:'Media & assets',   main:`${mLive} live`,     sub: mProc?`${mProc} processing`:'All processed',    pill: mProc?{tone:'blue',label:'Processing'}:{tone:'green',label:'Healthy'}, nav:'team' },
    { id:'actions', icon:I.bell,      title:'Action items',     main:`${3+invites} open`, sub:`${invites} invites · 2 items off · docs in review`, pill:{tone:'orange',label:'Review'}, nav:'team' },
  ];
  return (
    <div style={{ marginBottom:16 }}>
      <div style={{ display:'flex', alignItems:'center', gap:9, marginBottom:11 }}>
        <Eyebrow><I.grid c="var(--brand-orange)" s={13}/> &nbsp;Your growth systems</Eyebrow>
      </div>
      <div data-overview-growth-row="" style={{ display:'grid', gridTemplateColumns:'repeat(6,1fr)', gap:12 }}>
        {cards.map(c=>(
          <Card key={c.id} data-overview-card={c.id} pad={14} hover onClick={()=>app.nav(c.nav)}>
            <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:10 }}>
              <span style={{ width:30, height:30, borderRadius:9, background:'var(--bg-warm)', display:'flex', alignItems:'center', justifyContent:'center' }}><c.icon c="var(--brand-orange)" s={15}/></span>
              <Pill tone={c.pill.tone} style={{ fontSize:9 }}>{c.pill.label}</Pill>
            </div>
            <div style={{ fontFamily:'var(--font-display)', fontWeight:700, fontSize:11, color:'var(--warm-stone)' }}>{c.title}</div>
            <div style={{ fontFamily:'var(--font-display)', fontWeight:900, fontSize:16, color:'var(--fg-primary)', marginTop:3, lineHeight:1.1 }}>{c.main}</div>
            <div style={{ fontFamily:'var(--font-body)', fontSize:10, color:'var(--warm-stone)', marginTop:4, lineHeight:1.35 }}>{c.sub}</div>
          </Card>
        ))}
      </div>
    </div>
  );
}

function OverviewScreen({ app }) {
  const pr = PERFORMANCE_RANK;
  // KPI tiles, all profit/comparison-flavoured
  const kpis = [
    { id:'orders',  label:"Orders today",   value:String(PROFIT.orders.now), delta:'+8%',   dir:'up',   target:`Target ${PROFIT.orders.target}`, targetMet:false, sub:'vs last Tue', icon:'receipt' },
    { id:'aov',     label:'Avg order value', value:`£${PROFIT.aov.now.toFixed(2)}`, delta:'+3%', dir:'up', target:`Target £${PROFIT.aov.target.toFixed(2)}`, targetMet:true, sub:'vs last wk', icon:'tag' },
    { id:'repeat',  label:'Repeat rate',     value:'47%',   delta:'+5pts', dir:'up', target:'Target 45%', targetMet:true, sub:'30 days', icon:'refresh' },
    { id:'roi',     label:'Marketing ROI',   value:'3.8×',  delta:'+0.4×', dir:'up', target:'Target 3.5×', targetMet:true, sub:'30-day', icon:'trendUp' },
  ];
  return (
    <div>
      <PageHead eyebrow={`${new Date().toLocaleDateString('en-GB',{weekday:'long', day:'numeric', month:'long'})} · Milton Keynes`}
        title={`Evening, ${VENDOR.name}`}
        sub="Your profit, delivery, reviews and performance — pacing live against target."
        right={<Segmented options={[{value:'today',label:'Today'},{value:'week',label:'7 days'},{value:'month',label:'30 days'}]} value={app.range} onChange={app.setRange}/>}/>

      <ProfitHero app={app}/>

      {/* KPI comparison row */}
      <div style={{ display:'grid', gridTemplateColumns:'repeat(4, 1fr)', gap:14, marginBottom:16 }}>
        {kpis.map(k=> <KpiTile key={k.id} k={k}/>)}
      </div>

      {/* growth systems */}
      <SystemsRow app={app}/>

      {/* performance scorecard + delivery focus */}
      <div style={{ display:'grid', gridTemplateColumns:'1.4fr 1fr', gap:16, marginBottom:16 }}>
        <Card>
          <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:6 }}>
            <Eyebrow><I.target c="var(--brand-orange)" s={13}/> &nbsp;Performance scorecard</Eyebrow>
            <div style={{ display:'flex', alignItems:'center', gap:8, padding:'5px 11px', background:'var(--bg-warm)', borderRadius:9 }}>
              <I.trophy c="var(--brand-orange)" s={15}/>
              <span style={{ fontFamily:'var(--font-display)', fontWeight:800, fontSize:12.5, color:'var(--fg-primary)' }}>#{pr.rank} of {pr.of}</span>
              <span style={{ fontFamily:'var(--font-body)', fontSize:11, color:'var(--warm-stone)' }}>local vendors · ↑{pr.up}</span>
            </div>
          </div>
          <div style={{ display:'grid', gridTemplateColumns:'1.5fr 0.9fr 1fr 0.8fr', gap:12, padding:'8px 0 4px' }}>
            {['Metric','Now','Trend · vs wk','Target'].map((h,i)=>(
              <span key={h} style={{ fontFamily:'var(--font-display)', fontWeight:700, fontSize:10, letterSpacing:'0.06em', textTransform:'uppercase', color:'var(--warm-stone)', textAlign:i===3?'right':'left' }}>{h}</span>
            ))}
          </div>
          {OPS_METRICS.map((m,i)=> <ScoreRow key={m.id} m={m} last={i===OPS_METRICS.length-1}/>)}
          <div style={{ marginTop:12, display:'flex', alignItems:'center', gap:8, padding:'9px 12px', background:'rgba(46,139,78,0.09)', borderRadius:10 }}>
            <I.shield c="#247a41" s={15}/>
            <span style={{ fontFamily:'var(--font-body)', fontSize:11.5, color:'var(--horse-brown)' }}>All four metrics within target — you're in the top <strong style={{ fontFamily:'var(--font-display)' }}>{100-pr.percentile}%</strong> of MK vendors this month.</span>
          </div>
        </Card>
        <DeliveryCard/>
      </div>

      {/* reviews + recommended action / campaigns */}
      <div style={{ display:'grid', gridTemplateColumns:'1fr 1.35fr', gap:16 }}>
        <ReviewsCard app={app}/>
        <div style={{ display:'flex', flexDirection:'column', gap:16 }}>
          <RecommendedAction app={app}/>
          <Card pad={0} style={{ overflow:'hidden' }}>
            <div style={{ padding:'16px 20px 12px', display:'flex', alignItems:'center', justifyContent:'space-between', borderBottom:'1px solid var(--soft-line)' }}>
              <Eyebrow><I.megaphone c="var(--brand-orange)" s={13}/> &nbsp;Active campaigns</Eyebrow>
              <span onClick={()=>app.nav('campaigns')} style={{ fontFamily:'var(--font-display)', fontWeight:800, fontSize:12, color:'var(--brand-orange)', cursor:'pointer' }}>Manage all →</span>
            </div>
            <div>
              {ACTIVE_CAMPAIGNS.map((c,i)=>{
                const ct = CAMPAIGN_TYPES.find(t=>t.id===c.type);
                const CIcon = (ct && I[ct.icon]) || I.megaphone;
                return (
                  <div key={c.id} style={{ display:'flex', alignItems:'center', gap:14, padding:'12px 20px', borderBottom: i<ACTIVE_CAMPAIGNS.length-1?'1px solid var(--soft-line)':'none' }}>
                    <div style={{ width:34, height:34, borderRadius:10, background:'var(--bg-warm)', display:'flex', alignItems:'center', justifyContent:'center', flexShrink:0 }}><CIcon c="var(--horse-brown)" s={16}/></div>
                    <div style={{ minWidth:0, flex:1 }}>
                      <div style={{ fontFamily:'var(--font-display)', fontWeight:800, fontSize:13, color:'var(--fg-primary)' }}>{c.name}</div>
                      <div style={{ fontFamily:'var(--font-body)', fontSize:11, color:'var(--warm-stone)', marginTop:1 }}><I.pin c="var(--warm-stone)" s={11}/> {c.area} · {c.ends}</div>
                    </div>
                    <div style={{ textAlign:'right' }}>
                      <div style={{ fontFamily:'var(--font-display)', fontWeight:900, fontSize:13.5, color:'var(--fg-primary)' }}>£{c.revenue.toLocaleString()}</div>
                      <div style={{ fontFamily:'var(--font-body)', fontSize:10.5, color:'var(--warm-stone)' }}>{c.orders} orders</div>
                    </div>
                    <Pill tone={c.roi>=5?'green':c.roi>=3.5?'amber':'red'} style={{ width:60, justifyContent:'center' }}>{c.roi}× ROI</Pill>
                  </div>
                );
              })}
            </div>
          </Card>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { OverviewScreen });
