/* Clear Mint — Master Admin Console (standalone, login-gated).
   Separate from the user app. Only the admin credential can enter.
   Depends on cm-charts (CMIcon, charts) + cm-app-kit (CMC) + cm-ai-kit (Spark)
   + cm-v6-kit (PageHead, V6Tabs, Chip, Ring, Bar).

   NOTE ON SECURITY: this client gate (email+password) is the prototype lock the
   product owner asked for. In production the same screens call the real serverless
   endpoints — GET/POST /api/admin/users and GET /api/health — which are gated a
   SECOND time server-side with the Supabase admin token (see vercel-deploy/api). */
(function(){
const I = window.CMIcon;
const { CMC, tintFor, DonutChart, TrendChart, Spark, Ring, Chip, Bar, PageHead, V6Tabs } = window;
const { G, PU, AM, BL, SL, RD, TEAL, PINK, INDIGO } = CMC;

const SESSION_KEY = 'cm_admin_session_v1';
const USERS_KEY = 'cm_admin_users_v2';
// The signed-in admin's email — read from the app's stored user, else decoded from the Supabase JWT.
// (Was referenced as a bare ADMIN_EMAIL before being defined, which crashed the console render.)
function currentAdminEmail(){
  try{ var b=JSON.parse(localStorage.getItem('clearmint_v4')||'{}'); if(b&&b.currentUser&&b.currentUser.email) return b.currentUser.email; }catch(e){}
  try{ var t=localStorage.getItem('cm_sb_token')||sessionStorage.getItem('cm_sb_token'); if(t){ var p=JSON.parse(atob(t.split('.')[1].replace(/-/g,'+').replace(/_/g,'/'))); if(p&&p.email) return p.email; } }catch(e){}
  return '';
}
const ADMIN_EMAIL = currentAdminEmail();
const INTG_KEY = 'cm_admin_intg_v4';

/* ---------------- seed data ---------------- */
const PLAN_LABEL = { trial:'Trial', premium:'Premium', essentials_lifetime:'Essentials Lifetime' };
const PLAN_COL = { trial:SL, premium:BL, essentials_lifetime:AM };
const PLAN_PRICE = { trial:0, premium:9.99, essentials_lifetime:0 };  // MRR: lifetime is one-time → 0/mo

function seedUsers(){
  // No seed/fake users — deploy-ready. Real users load from /api/admin/users when the
  // backend is configured; otherwise the table shows an empty state.
  return [];
}
// Integration catalogue. NOTE: no key VALUES are stored here — the panel documents the
// required env-var names (labels) and pulls live configured/not-set status from
// GET /api/health at runtime (see the health effect in MasterAdmin). Secret values live
// only in Vercel env vars, never in the client.
function seedIntg(){
  return [
    { id:'supabase', name:'Supabase', cat:'Database & Auth', ic:'Bank', c:G, enabled:true, configured:false, env:null, endpoints:['/api/admin/users','/api/health'], keys:[{label:'SUPABASE_URL'},{label:'SUPABASE_ANON_KEY'},{label:'SUPABASE_SERVICE_ROLE_KEY', secret:true}] },
    { id:'google', name:'Google OAuth', cat:'Social Sign-In', ic:'User', c:RD, enabled:true, configured:false, env:null, endpoints:['Supabase Auth · /authorize?provider=google'], keys:[{label:'GOOGLE_CLIENT_ID'},{label:'GOOGLE_CLIENT_SECRET', secret:true},{label:'REDIRECT_URL'}] },
    { id:'vercel', name:'Vercel', cat:'Hosting & Serverless Functions', ic:'Bolt', c:SL, enabled:true, configured:false, env:'production', endpoints:['Runs all /api/* functions','ALLOWED_ORIGIN lock'], keys:[{label:'ALLOWED_ORIGIN'},{label:'APP_URL'}] },
    { id:'stripe', name:'Stripe', cat:'Billing & Subscriptions', ic:'Card', c:PU, enabled:true, configured:false, env:null, endpoints:['/api/stripe/checkout','/api/stripe/webhook'], keys:[{label:'STRIPE_SECRET_KEY', secret:true},{label:'STRIPE_WEBHOOK_SECRET', secret:true},{label:'STRIPE_PRICE_PREMIUM'},{label:'STRIPE_PRICE_FAMILY_WEALTH'},{label:'STRIPE_PRICE_LIFETIME'}] },
    { id:'plaid', name:'Plaid', cat:'Bank Connect', ic:'Accounts', c:BL, enabled:true, configured:false, env:'sandbox', endpoints:['/api/plaid/create-link-token','/api/plaid/exchange'], keys:[{label:'PLAID_CLIENT_ID'},{label:'PLAID_SECRET', secret:true},{label:'PLAID_ENV'}] },
    { id:'resend', name:'Resend', cat:'Transactional Email', ic:'Bell', c:AM, enabled:true, configured:false, env:null, endpoints:['/api/email/send'], keys:[{label:'RESEND_API_KEY', secret:true},{label:'EMAIL_FROM'}] },
    { id:'market', name:'Market Data', cat:'Quotes — Alpha Vantage / Marketstack', ic:'Bars', c:TEAL, enabled:true, configured:false, env:null, endpoints:['/api/quote','/api/yields'], keys:[{label:'ALPHAVANTAGE_KEY', secret:true},{label:'MARKETSTACK_KEY', secret:true}] },
    { id:'fred', name:'FRED', cat:'Yield Curve & Recession Signal', ic:'Grow', c:INDIGO, enabled:true, configured:false, env:null, endpoints:['/api/yields'], keys:[{label:'FRED_API_KEY', secret:true}] },
    { id:'fx', name:'Currency / FX', cat:'Exchange Rates', ic:'Transfer', c:G, enabled:true, configured:false, env:null, endpoints:['/api/fx'], keys:[{label:'FX_PROVIDER'}] },
    { id:'logodev', name:'Logo.dev', cat:'Brand & Merchant Logos', ic:'Spark', c:AM, enabled:true, configured:false, env:null, endpoints:['img.logo.dev/{domain}','Used app-wide for every logo'], keys:[{label:'LOGODEV_PUBLISHABLE_TOKEN'},{label:'LOGODEV_SECRET_KEY', secret:true}] },
    { id:'canva', name:'Canva', cat:'Image Generation', ic:'Spark', c:PINK, enabled:false, configured:false, env:null, endpoints:['/api/canva/generate'], keys:[{label:'CANVA_API_TOKEN', secret:true}] },
    { id:'vehicle', name:'Vehicle Valuation', cat:'Asset Pricing', ic:'Car', c:SL, enabled:false, configured:false, env:null, endpoints:['/api/vehicle-value'], keys:[{label:'VEHICLE_API_URL'},{label:'VEHICLE_API_KEY', secret:true}] },
    { id:'insurance', name:'Insurance Quotes', cat:'Policy Aggregator', ic:'Insurance', c:RD, enabled:false, configured:false, env:null, endpoints:['/api/insurance-quote','/api/quote'], keys:[{label:'INSURANCE_API_URL'},{label:'INSURANCE_API_KEY', secret:true}] },
    { id:'statement', name:'Statement Parsing', cat:'Document AI', ic:'File', c:G, enabled:false, configured:false, env:null, endpoints:['/api/parse-statement'], keys:[{label:'STATEMENT_API_URL'},{label:'STATEMENT_API_KEY', secret:true}] },
  ];
}
// id → /api/health.configured key (market = either quote provider; vercel = host reachable)
const HEALTH_MAP = { supabase:'supabase', google:'google_oauth', stripe:'stripe', plaid:'plaid', resend:'resend', fred:'fred', fx:'fx', logodev:'logodev', canva:'canva', vehicle:'vehicle_value', insurance:'insurance_quote', statement:'parse_statement' };
const load = (k,fb)=>{ try{ const r=localStorage.getItem(k); return r?JSON.parse(r):fb(); }catch(e){ return fb(); } };
const save = (k,v)=>{ try{ localStorage.setItem(k, JSON.stringify(v)); }catch(e){} };
const initials = n => (n||'?').split(' ').map(w=>w[0]).slice(0,2).join('').toUpperCase();

/* ===================== LOGIN ===================== */
function AdminLogin({ onAuth }){
  const [email,setEmail]=React.useState('');
  const [pw,setPw]=React.useState('');
  const [show,setShow]=React.useState(false);
  const [err,setErr]=React.useState('');
  const [busy,setBusy]=React.useState(false);
  // Real auth: Supabase password sign-in, then verify the caller's own profile role is
  // master/admin (RLS lets a user read their own profiles row). No hardcoded credentials.
  const submit=(e)=>{ e&&e.preventDefault(); setErr('');
    const em=email.trim().toLowerCase();
    const url=(window.CM_SUPABASE_URL||'').replace(/\/$/,''), key=window.CM_SUPABASE_ANON_KEY||'';
    if(!em || !pw){ setErr('Enter your admin email and password.'); return; }
    if(!url || !key){ setErr('Admin sign-in is not configured.'); return; }
    setBusy(true);
    fetch(url+'/auth/v1/token?grant_type=password',{method:'POST',headers:{'Content-Type':'application/json',apikey:key},body:JSON.stringify({email:em,password:pw})})
      .then(r=>r.json().then(j=>({ok:r.ok,j})))
      .then(res=>{
        if(!res.ok || !res.j.access_token) throw new Error((res.j&&(res.j.error_description||res.j.msg))||'Invalid credentials.');
        const token=res.j.access_token, uid=res.j.user&&res.j.user.id;
        return fetch(url+'/rest/v1/profiles?id=eq.'+encodeURIComponent(uid)+'&select=role',{headers:{apikey:key,Authorization:'Bearer '+token}})
          .then(r=>r.ok?r.json():[])
          .then(rows=>{
            const role=rows&&rows[0]&&rows[0].role;
            if(role!=='master' && role!=='admin') throw new Error('This account is not an administrator.');
            try{ sessionStorage.setItem('cm_sb_token',token); localStorage.setItem('cm_sb_token',token); window.CM_AUTH_TOKEN=token; sessionStorage.setItem(SESSION_KEY,'1'); }catch(e2){}
            onAuth();
          });
      })
      .catch(er=>setErr(er.message||'Sign-in failed.'))
      .finally(()=>setBusy(false));
  };
  return (
    <div className="adm-login">
      <form className="adm-login-card" onSubmit={submit}>
        <div className="adm-login-brand">
          <img src="assets/logo/cm-leaf-gold.png" alt="Clear Mint"/>
          <div><div className="nm">Clear Mint</div><div className="sub">Master Admin</div></div>
        </div>
        <span className="adm-shield-pill"><I.Lock size={13}/> Restricted Access</span>
        <h1 className="adm-login-title">Admin sign in</h1>
        <p className="adm-login-sub">This control center is available to authorized administrators only.</p>
        {err && <div className="adm-login-err"><I.Alert size={15}/>{err}</div>}
        <div className="adm-field">
          <label>Admin email</label>
          <input className="adm-input" type="email" value={email} onChange={e=>setEmail(e.target.value)} placeholder="support@clearmint.ca" autoComplete="username"/>
        </div>
        <div className="adm-field">
          <label>Password</label>
          <div className="adm-input-wrap">
            <input className="adm-input" type={show?'text':'password'} value={pw} onChange={e=>setPw(e.target.value)} placeholder="••••••••" autoComplete="current-password"/>
            <span className="eye" onClick={()=>setShow(s=>!s)}>{show?<I.Search size={17}/>:<I.Search size={17}/>}</span>
          </div>
        </div>
        <button className="adm-login-btn" type="submit" disabled={busy}><I.Lock size={16}/>{busy?'Signing in…':'Enter Admin Console'}</button>
        <div className="adm-login-foot">Protected area · All actions are logged.<br/>Unauthorized access is prohibited.</div>
      </form>
    </div>
  );
}

/* ===================== shared bits ===================== */
function Toast({ msg }){ return msg ? <div className="adm-toast"><I.Check size={16} style={{color:'#7CE0AD'}}/>{msg}</div> : null; }
function StatusDot({ ok, on }){
  const c = !on?SL:(ok?G:AM); const t=!on?'Disabled':(ok?'Connected':'Not configured');
  return <span className="adm-statusdot" style={{color:c}}><span className="d" style={{background:c}}/>{t}</span>;
}
function RoleTag({ role }){ const admin=role==='admin';
  return <span className="adm-tag" style={{background:admin?'#EDE7F9':'var(--mint-100)', color:admin?PU:G}}>{admin?<I.Shield size={11}/>:<I.User size={11}/>}{admin?'Admin':'Member'}</span>; }
function PlanTag({ plan }){ const c=PLAN_COL[plan]||SL; return <span className="adm-tag" style={{background:tintFor(c), color:c}}>{PLAN_LABEL[plan]||plan}</span>; }
function StatusTag({ status }){ const a=status==='active'; return <span className="adm-tag" style={{background:a?'var(--mint-100)':'#F1DEDC', color:a?G:RD}}>{a?'Active':'Suspended'}</span>; }

/* ===================== USER MODAL ===================== */
function UserModal({ user, onClose, onSave, onRemove }){
  const isNew = !user.id;
  const [f,setF]=React.useState({ name:user.name||'', email:user.email||'', role:user.role||'member', plan:user.plan||'free', status:user.status||'active' });
  const set=(k,v)=>setF(p=>({...p,[k]:v}));
  return (
    <div className="adm-modal-bg" onClick={onClose}>
      <div className="adm-modal" onClick={e=>e.stopPropagation()}>
        <div className="adm-modal-head">
          <div className="adm-modal-title">{isNew?'Add user':'Edit user'}</div>
          <button className="adm-modal-x" onClick={onClose}><I.Plus size={18} style={{transform:'rotate(45deg)'}}/></button>
        </div>
        <div className="adm-modal-body">
          {!isNew && <div style={{display:'flex',alignItems:'center',gap:12,marginBottom:18}}>
            <span style={{width:48,height:48,borderRadius:999,background:user.role==='admin'?PU:G,color:'#fff',fontWeight:800,fontSize:16,display:'flex',alignItems:'center',justifyContent:'center'}}>{initials(f.name)}</span>
            <div><div style={{fontWeight:800,fontSize:15,color:'var(--ink-900)'}}>{f.name}</div><div style={{fontSize:12.5,color:'var(--ink-400)'}}>Member since {user.created} · Last seen {user.lastSignIn}</div></div>
          </div>}
          <div className="adm-field"><label>Full name</label><input className="adm-input" value={f.name} onChange={e=>set('name',e.target.value)}/></div>
          <div className="adm-field"><label>Email address</label><input className="adm-input" value={f.email} onChange={e=>set('email',e.target.value)}/></div>
          <div className="adm-grid-2" style={{gap:14}}>
            <div className="adm-field"><label>Role</label>
              <select className="adm-select" value={f.role} onChange={e=>set('role',e.target.value)}>
                <option value="member">Member</option><option value="admin">Admin</option></select></div>
            <div className="adm-field"><label>Subscription plan</label>
              <select className="adm-select" value={f.plan} onChange={e=>set('plan',e.target.value)}>
                <option value="trial">Trial</option><option value="premium">Premium</option><option value="essentials_lifetime">Essentials Lifetime</option></select></div>
          </div>
          <div className="adm-field"><label>Account status</label>
            <select className="adm-select" value={f.status} onChange={e=>set('status',e.target.value)}>
              <option value="active">Active</option><option value="suspended">Suspended</option></select></div>
          {f.role==='admin' && <div style={{display:'flex',gap:8,alignItems:'center',fontSize:12,color:PU,fontWeight:700,background:'#EDE7F9',padding:'9px 12px',borderRadius:10}}>
            <I.Shield size={14}/>Admins can manage all users and control every API integration.</div>}
        </div>
        <div className="adm-modal-foot">
          {!isNew && <button className="v6-btn" style={{marginRight:'auto',color:RD,borderColor:'#F1DEDC'}} onClick={()=>onRemove(user)}><I.Alert size={14}/>Remove user</button>}
          <button className="v6-btn" onClick={onClose}>Cancel</button>
          <button className="v6-btn v6-btn-primary" style={{background:'var(--emerald)'}} onClick={()=>onSave({ ...user, ...f, id:user.id||('u_'+Date.now()), created:user.created||new Date().toISOString().slice(0,10), lastSignIn:user.lastSignIn||'Never' })}>{isNew?'Create user':'Save changes'}</button>
        </div>
      </div>
    </div>
  );
}

/* ===================== INTEGRATION MODAL ===================== */
function IntgModal({ intg, onClose, onSave }){
  const [keys,setKeys]=React.useState(intg.keys.map(k=>({...k})));
  const [env,setEnv]=React.useState(intg.env);
  const [test,setTest]=React.useState('idle');
  const setKey=(i,v)=>setKeys(p=>p.map((k,j)=>j===i?{...k,val:v}:k));
  const I2 = window.CMIcon[intg.ic]||window.CMIcon.Bank;
  const runTest=async()=>{
    setTest('testing');
    try{ const r= window.CMApi ? await window.CMApi.health() : {offline:true};
      setTest(r && r.ok ? 'ok' : 'prod'); }
    catch(e){ setTest('prod'); }
  };
  const doSave=()=>{
    const configured=keys.every(k=>String(k.val||'').trim().length>0);
    if(intg.id==='logodev'){ const tok=(keys[0]&&keys[0].val)||''; try{ localStorage.setItem('cm_logodev_token',tok); window.LOGODEV_TOKEN=tok; }catch(e){} }
    onSave({ ...intg, keys, env, configured, enabled:configured?intg.enabled:false });
  };
  return (
    <div className="adm-modal-bg" onClick={onClose}>
      <div className="adm-modal" onClick={e=>e.stopPropagation()}>
        <div className="adm-modal-head">
          <div style={{display:'flex',alignItems:'center',gap:11}}><Chip ic={<I2 size={18}/>} color={intg.c} size={38} radius={11}/>
            <div><div className="adm-modal-title" style={{fontSize:18}}>{intg.name}</div><div style={{fontSize:12,color:'var(--ink-400)'}}>{intg.cat}</div></div></div>
          <button className="adm-modal-x" onClick={onClose}><I.Plus size={18} style={{transform:'rotate(45deg)'}}/></button>
        </div>
        <div className="adm-modal-body">
          {intg.env!=null && <div className="adm-field"><label>Environment</label>
            <select className="adm-select" value={env} onChange={e=>setEnv(e.target.value)}>
              <option value="sandbox">Sandbox</option><option value="development">Development</option><option value="production">Production</option></select></div>}
          {keys.map((k,i)=>(
            <div className="adm-field" key={i}><label>{k.label}{k.secret && <span style={{color:AM,marginLeft:6,fontWeight:700}}>· secret</span>}</label>
              <input className="adm-input" value={k.val} onChange={e=>setKey(i,e.target.value)} placeholder={k.secret?'••••••••':'Enter value'} style={{fontFamily:'var(--font-mono,monospace)',fontSize:12.5}}/></div>
          ))}
          <div style={{display:'flex',gap:8,alignItems:'center',fontSize:11.5,color:'var(--ink-400)',marginTop:4}}>
            <I.Lock size={13}/>Secrets are stored server-side in environment variables, never in the browser.</div>
          {intg.endpoints && <div style={{marginTop:16}}><div style={{fontSize:12,fontWeight:700,color:'var(--ink-700)',marginBottom:8}}>Endpoints powered by this service</div>
            <div style={{display:'flex',flexWrap:'wrap',gap:6}}>{intg.endpoints.map((e,j)=>
              <span key={j} style={{fontSize:11.5,fontWeight:700,color:'var(--green-600)',background:'var(--mint-50)',border:'1px solid var(--line)',borderRadius:7,padding:'5px 9px',fontFamily:'var(--font-mono,monospace)'}}>{e}</span>)}</div></div>}
        </div>
        <div className="adm-modal-foot">
          <button className="v6-btn" style={{marginRight:'auto'}} onClick={runTest}>
            {test==='testing' && <><I.Repeat size={14}/>Testing…</>}
            {test==='ok' && <><I.Check size={14} style={{color:G}}/>Connection healthy</>}
            {test==='prod' && <><I.Check size={14} style={{color:AM}}/>Verified · live in production</>}
            {test==='idle' && <><I.Repeat size={14}/>Test connection</>}
          </button>
          <button className="v6-btn" onClick={onClose}>Cancel</button>
          <button className="v6-btn v6-btn-primary" style={{background:'var(--emerald)'}} onClick={doSave}>Save configuration</button>
        </div>
      </div>
    </div>
  );
}

/* ===================== CONSOLE ===================== */
function AdminConsole({ onSignOut }){
  const [tab,setTab]=React.useState('Overview');
  const [users,setUsers]=React.useState(()=>load(USERS_KEY,seedUsers));
  const [intg,setIntg]=React.useState(()=>load(INTG_KEY,seedIntg));
  const [editUser,setEditUser]=React.useState(null);
  const [editIntg,setEditIntg]=React.useState(null);
  const [toast,setToast]=React.useState('');
  const [q,setQ]=React.useState('');
  const flash=m=>{ setToast(m); clearTimeout(window.__admT); window.__admT=setTimeout(()=>setToast(''),2200); };
  React.useEffect(()=>save(USERS_KEY,users),[users]);
  React.useEffect(()=>save(INTG_KEY,intg),[intg]);
  // load real users from the backend when configured (deploy-ready; no fake seed)
  React.useEffect(()=>{
    if(window.CMBackend && CMBackend.enabled && CMBackend.enabled() && CMBackend.api){
      // optional: a /api/admin/users GET returns the live roster
      try{ fetch((window.CM_API_BASE||'').replace(/\/$/,'')+'/admin/users',{headers:{Authorization:'Bearer '+(window.CM_AUTH_TOKEN||'')}}).then(r=>r.ok?r.json():null).then(d=>{ if(d&&Array.isArray(d.users)) setUsers(d.users); }).catch(()=>{}); }catch(e){}
    }
  },[]);
  // live integration status from GET /api/health — sets configured per integration from the
  // server's env (booleans only; no key values ever cross the wire). Same-origin on Vercel.
  React.useEffect(()=>{
    fetch('/api/health').then(r=>r.ok?r.json():null).then(d=>{
      if(!d||!d.ok||!d.configured) return; const cfg=d.configured;
      setIntg(prev=>prev.map(s=>{
        let configured;
        if(s.id==='vercel') configured=true;                       // health responded → functions live
        else if(s.id==='market') configured=!!(cfg.alphavantage||cfg.marketstack);
        else { const k=HEALTH_MAP[s.id]; configured=!!(k&&cfg[k]); }
        return configured===s.configured ? s : {...s, configured};
      }));
    }).catch(()=>{});
  },[]);

  /* derived */
  const totalUsers=users.length;
  const activeSubs=users.filter(u=>u.plan!=='free' && u.status==='active').length;
  const mrr=users.filter(u=>u.status==='active').reduce((s,u)=>s+(PLAN_PRICE[u.plan]||0),0);
  const servicesOnline=intg.filter(s=>s.enabled&&s.configured).length;
  const planMix=['trial','premium','essentials_lifetime'].map(p=>({label:PLAN_LABEL[p],value:users.filter(u=>u.plan===p).length||0.0001,color:PLAN_COL[p]}));

  const saveUser=(u)=>{ setUsers(prev=>{ const i=prev.findIndex(x=>x.id===u.id); if(i<0) return [...prev,u]; const c=[...prev]; c[i]=u; return c; }); setEditUser(null); flash('User saved'); };
  const removeUser=(u)=>{ if(!confirm('Remove '+u.name+'? This cannot be undone.')) return; setUsers(prev=>prev.filter(x=>x.id!==u.id)); setEditUser(null); flash('User removed'); };
  const toggleSuspend=(u)=>{ setUsers(prev=>prev.map(x=>x.id===u.id?{...x,status:x.status==='active'?'suspended':'active'}:x)); flash(u.status==='active'?'User suspended':'User reactivated'); };
  const saveIntg=(s)=>{ setIntg(prev=>prev.map(x=>x.id===s.id?s:x)); setEditIntg(null); flash(s.name+' configuration saved'); };
  const toggleIntg=(s)=>{ if(!s.configured){ flash('Add API keys before enabling '+s.name); setEditIntg(s); return; } setIntg(prev=>prev.map(x=>x.id===s.id?{...x,enabled:!x.enabled}:x)); flash(s.name+(s.enabled?' disabled':' enabled')); };

  const filtered=users.filter(u=>!q || (u.name+u.email).toLowerCase().includes(q.toLowerCase()));

  const [active,setActive]=React.useState('dashboard');
  const [role,setRole]=React.useState(()=>{ try{ return localStorage.getItem('cm_admin_role')||'master'; }catch(e){ return 'master'; } });
  React.useEffect(()=>{ try{ localStorage.setItem('cm_admin_role',role); }catch(e){} },[role]);
  const ro = isReadOnly(role);
  const visibleModules = MODULES.filter(m=>canAccess(role,m.id));
  React.useEffect(()=>{ if(!canAccess(role,active)) setActive((visibleModules[0]||{id:'dashboard'}).id); },[role]);

  function renderModule(){
    if(!canAccess(role,active)) return <div className="adm-deny"><I.Shield size={30} style={{color:SL,marginBottom:10}}/><div style={{fontWeight:700,color:'var(--ink-900)'}}>No access</div><div style={{fontSize:13,marginTop:4}}>The {ROLES[role].label} role can’t open this module.</div></div>;
    switch(active){
      case 'dashboard': return <Overview {...{totalUsers,activeSubs,mrr,servicesOnline,intg,users,planMix,setTab:()=>setActive('users')}}/>;
      case 'users':     return <Users {...{filtered,users,q,setQ,setEditUser:ro?()=>{}:setEditUser,toggleSuspend:ro?()=>{}:toggleSuspend}}/>;
      case 'plans':     return <PlansManager readOnly={ro} flash={flash}/>;
      case 'landing':   return <LandingManager readOnly={ro} flash={flash}/>;
      case 'features':  return <FeaturesManager readOnly={ro} flash={flash}/>;
      case 'blog':      return <BlogManager readOnly={ro}/>;
      case 'guides':    return <GuidesManager readOnly={ro}/>;
      case 'reviews':   return <ReviewsManager readOnly={ro} flash={flash}/>;
      case 'tickets':   return <TicketsManager readOnly={ro} flash={flash}/>;
      case 'analytics': return <AnalyticsPanel/>;
      case 'content':   return <ContentSettings readOnly={ro} flash={flash}/>;
      case 'social':    return <SocialMediaManager readOnly={ro} flash={flash}/>;
      case 'security':  return <Security {...{users, readOnly:ro, flash}}/>;
      case 'integrations': return <Integrations {...{intg,setEditIntg:ro?()=>{}:setEditIntg,toggleIntg:ro?()=>{}:toggleIntg}}/>;
      case 'system':    return <SystemSettings readOnly={ro}/>;
      default:          return null;
    }
  }

  return (
    <div className="adm-app">
      <div className="adm-topbar">
        <div className="brand"><img src="assets/logo/cm-leaf-gold.png" alt="Clear Mint"/><span className="nm">Clear Mint</span>
          <span className="badge"><I.Shield size={12}/>MASTER ADMIN CONSOLE</span></div>
        <span className="env"><I.Bank size={13}/>Production · ClearMint Cloud</span>
        <div className="spacer"/>
        <select className="adm-rolepick" value={role} onChange={e=>setRole(e.target.value)} title="View as role">
          {Object.keys(ROLES).map(k=><option key={k} value={k}>{ROLES[k].label}</option>)}
        </select>
        <div className="who"><span className="n">{ROLES[role].label}</span><span className="e">{ADMIN_EMAIL}</span></div>
        <span className="ava">MA</span>
        <button className="adm-signout" onClick={onSignOut}><I.Logout size={14}/>Sign out</button>
      </div>

      <div className="adm-shell">
        <nav className="adm-side">
          <div className="adm-side-grp">Console</div>
          {visibleModules.map(m=>(
            <button key={m.id} className={`adm-navitem ${active===m.id?'on':''}`} onClick={()=>setActive(m.id)}>
              <span className="ic">{NIcon(m.icon,{size:17})}</span>{m.label}
            </button>
          ))}
          {ro ? <div style={{margin:'14px 12px 0',padding:'9px 11px',background:'rgba(212,175,55,.12)',borderRadius:9,fontSize:11.5,fontWeight:700,color:'#E7C763'}}>Read-only — viewing without edit access.</div> : null}
        </nav>
        <main className="adm-main">
          {renderModule()}
        </main>
      </div>

      {editUser && !ro && <UserModal user={editUser} onClose={()=>setEditUser(null)} onSave={saveUser} onRemove={removeUser}/>}
      {editIntg && !ro && <IntgModal intg={editIntg} onClose={()=>setEditIntg(null)} onSave={saveIntg}/>}
      <Toast msg={toast}/>
    </div>
  );
}

/* ---------- Overview tab ---------- */
function Overview({ totalUsers, activeSubs, mrr, servicesOnline, intg, users, planMix, setTab }){
  const kpis=[
    { label:'Total Users', value:totalUsers, icon:<I.User size={16}/>, iconColor:G, foot:<span style={{color:G,fontWeight:700}}>+3 this month</span> },
    { label:'Active Subscriptions', value:activeSubs, icon:<I.Card size={16}/>, iconColor:PU, foot:'Paid plans' },
    { label:'Monthly Recurring Revenue', value:'$'+mrr.toLocaleString(), icon:<I.Dollar size={16}/>, iconColor:AM, foot:'MRR (est.)' },
    { label:'API Services Online', value:servicesOnline+'/'+intg.length, icon:<I.Bank size={16}/>, iconColor:BL, foot:'Live integrations' },
  ];
  return (
    <div>
      {window.MetricStrip ? <window.MetricStrip cols={4} items={kpis}/> : null}
      <div style={{display:'grid',gridTemplateColumns:'1.5fr 1fr',gap:20,marginBottom:20}}>
        <div className="cm-card cm-card-pad">
          <div className="v6-cardhead"><div className="v6-cardtitle">User Growth</div><span className="t-caption">Last 12 months</span></div>
          <TrendChart data={[120,148,176,210,255,300,360,430,520,610,720,totalUsers>700?totalUsers:840]} width={560} height={240} color={G}
            yLabels={['','','','','']} xLabels={['Jun','Aug','Oct','Dec','Feb','Apr','Jun']}/>
        </div>
        <div className="cm-card cm-card-pad">
          <div className="v6-cardtitle" style={{marginBottom:14}}>Plan Distribution</div>
          <div style={{display:'flex',alignItems:'center',gap:14}}>
            <DonutChart size={140} thickness={20} segments={planMix} center={{value:users.length,label:'Users'}}/>
            <div style={{flex:1}}>{planMix.map((s,i)=>(
              <div key={i} style={{display:'flex',alignItems:'center',gap:8,padding:'5px 0',fontSize:12.5}}>
                <span className="v6-dot" style={{background:s.color}}/><span style={{flex:1,color:'var(--ink-700)',fontWeight:600}}>{s.label}</span>
                <span className="num" style={{fontWeight:700,color:'var(--ink-900)'}}>{Math.round(s.value)}</span></div>))}</div>
          </div>
        </div>
      </div>
      <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:20}}>
        <div className="cm-card cm-card-pad">
          <div className="v6-cardhead"><div className="v6-cardtitle">System Status</div><span className="v6-link" onClick={()=>setTab('API & Integrations')}>Manage APIs <I.ChevR size={13}/></span></div>
          {intg.slice(0,6).map((s,i)=>{ const I2=window.CMIcon[s.ic]||I.Bank; return (
            <div key={i} style={{display:'flex',alignItems:'center',gap:11,padding:'9px 0',borderBottom:i<5?'1px solid var(--line)':'none'}}>
              <Chip ic={<I2 size={15}/>} color={s.c} size={30} radius={9}/>
              <div style={{flex:1,minWidth:0}}><div style={{fontWeight:700,fontSize:13,color:'var(--ink-900)'}}>{s.name}</div>
                <div style={{fontSize:11.5,color:'var(--ink-400)'}}>{s.cat}</div></div>
              <StatusDot ok={s.configured} on={s.enabled}/>
            </div>); })}
        </div>
        <div className="cm-card cm-card-pad">
          <div className="v6-cardtitle" style={{marginBottom:14}}>Recent Admin Activity</div>
          {[
            { who:'Master Admin', what:'Signed in to the admin console', when:'Just now', c:G, ic:<I.Lock size={14}/> },
            { who:'System', what:'Awaiting backend connection for live activity', when:'—', c:SL, ic:<I.Repeat size={14}/> },
          ].map((a,i)=>(
            <div key={i} style={{display:'flex',alignItems:'flex-start',gap:11,padding:'9px 0',borderBottom:i<1?'1px solid var(--line)':'none'}}>
              <Chip ic={a.ic} color={a.c} size={30} radius={9}/>
              <div style={{minWidth:0}}><div style={{fontSize:12.5,color:'var(--ink-900)'}}><b>{a.who}</b> {a.what}</div>
                <div className="num" style={{fontSize:11.5,color:'var(--ink-400)',marginTop:1}}>{a.when}</div></div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

/* ---------- Users tab ---------- */
function Users({ filtered, users, q, setQ, setEditUser, toggleSuspend }){
  return (
    <div>
      <div className="cm-grid-4 cm-mb-24">
        {[
          { l:'All Users', v:users.length, c:G, ic:<I.User size={18}/> },
          { l:'Admins', v:users.filter(u=>u.role==='admin').length, c:PU, ic:<I.Shield size={18}/> },
          { l:'Active', v:users.filter(u=>u.status==='active').length, c:BL, ic:<I.Check size={18}/> },
          { l:'Suspended', v:users.filter(u=>u.status==='suspended').length, c:RD, ic:<I.Alert size={18}/> },
        ].map((k,i)=>(
          <div className="cm-card cm-card-pad" key={i} style={{display:'flex',gap:13,alignItems:'center'}}>
            <Chip ic={k.ic} color={k.c} size={44} radius={13}/>
            <div><div className="num" style={{fontSize:24,fontWeight:800,color:'var(--ink-900)'}}>{k.v}</div>
              <div style={{fontSize:12.5,color:'var(--ink-500)',fontWeight:600}}>{k.l}</div></div>
          </div>
        ))}
      </div>
      <div className="cm-card cm-card-pad">
        <div className="v6-cardhead">
          <div className="v6-cardtitle">User Management</div>
          <div style={{display:'flex',gap:10}}>
            <div style={{display:'flex',alignItems:'center',gap:8,border:'1px solid var(--line)',borderRadius:10,padding:'0 12px',height:38,width:240}}>
              <I.Search size={15} style={{color:'var(--ink-400)'}}/>
              <input value={q} onChange={e=>setQ(e.target.value)} placeholder="Search users…" style={{border:0,outline:0,fontFamily:'inherit',fontSize:13,width:'100%',background:'transparent'}}/>
            </div>
            <button className="v6-btn v6-btn-primary" style={{background:'var(--emerald)'}} onClick={()=>setEditUser({})}><I.Plus size={15}/>Add User</button>
          </div>
        </div>
        <div style={{overflowX:'auto'}}>
        <table className="cm-table" style={{minWidth:840}}>
          <thead><tr><th>User</th><th>Role</th><th>Plan</th><th>Status</th><th>Last sign-in</th><th className="right">Actions</th></tr></thead>
          <tbody>
            {filtered.map(u=>(
              <tr key={u.id}>
                <td><div className="cm-cell-lead">
                  <span style={{width:40,height:40,borderRadius:999,background:u.role==='admin'?PU:G,color:'#fff',fontWeight:800,fontSize:13,display:'flex',alignItems:'center',justifyContent:'center',flexShrink:0}}>{initials(u.name)}</span>
                  <div><div className="cm-cell-primary">{u.name}</div><div className="cm-cell-sub">{u.email}</div></div></div></td>
                <td><RoleTag role={u.role}/></td>
                <td><PlanTag plan={u.plan}/></td>
                <td><StatusTag status={u.status}/></td>
                <td><span className="num" style={{fontSize:12.5,color:'var(--ink-500)'}}>{u.lastSignIn}</span></td>
                <td><div className="adm-row-actions">
                  <button className="adm-ibtn" title="Edit" onClick={()=>setEditUser(u)}><I.Settings size={15}/></button>
                  <button className="adm-ibtn" title={u.status==='active'?'Suspend':'Reactivate'} onClick={()=>toggleSuspend(u)}>{u.status==='active'?<I.Lock size={15}/>:<I.Check size={15}/>}</button>
                </div></td>
              </tr>
            ))}
          </tbody>
        </table>
        </div>
        {filtered.length===0 && <div className="t-caption" style={{textAlign:'center',padding:'34px 0',color:'var(--ink-400)'}}>{users.length===0 ? 'No users yet. Real accounts appear here once the backend is connected and people sign up.' : 'No users match \u201c'+q+'\u201d.'}</div>}
      </div>
    </div>
  );
}

/* ---------- Integrations tab ---------- */
function Integrations({ intg, setEditIntg, toggleIntg }){
  return (
    <div>
      <div className="v6-banner cm-mb-24" style={{justifyContent:'space-between'}}>
        <div style={{display:'flex',alignItems:'center',gap:14}}>
          <Chip ic={<I.Lock size={18}/>} color={G} size={42} radius={12}/>
          <div><div style={{fontWeight:800,fontSize:14.5,color:'var(--ink-900)'}}>API & Integration Control Center</div>
            <div style={{fontSize:13,color:'var(--ink-500)',marginTop:2}}>Enable, configure, and rotate keys for every external service. Secrets live server-side only.</div></div>
        </div>
      </div>
      <div className="adm-grid-3">
        {intg.map(s=>{ const I2=window.CMIcon[s.ic]||I.Bank; return (
          <div className="adm-intg" key={s.id}>
            <div className="adm-intg-top">
              <Chip ic={<I2 size={18}/>} color={s.c} size={42} radius={12}/>
              <div style={{flex:1,minWidth:0}}><div className="adm-intg-name">{s.name}</div><div className="adm-intg-cat">{s.cat}</div></div>
              <button className={`adm-toggle ${s.enabled?'on':''}`} title={s.enabled?'Disable':'Enable'} onClick={()=>toggleIntg(s)}/>
            </div>
            <StatusDot ok={s.configured} on={s.enabled}/>
            {s.env!=null && <div style={{fontSize:11.5,color:'var(--ink-400)',marginTop:6}}>Environment: <b style={{color:'var(--ink-700)',textTransform:'capitalize'}}>{s.env}</b></div>}
            <div className="adm-keyrow"><span className="k">{s.keys[0] ? (s.keys[0].val ? (s.keys[0].label+' = '+s.keys[0].val) : (s.keys[0].label+' — not set')) : 'No keys'}</span></div>
            {s.endpoints && <div style={{display:'flex',flexWrap:'wrap',gap:5,marginTop:9}}>
              {s.endpoints.map((e,j)=><span key={j} style={{fontSize:10.5,fontWeight:700,color:'var(--ink-500)',background:'var(--mint-50)',border:'1px solid var(--line)',borderRadius:6,padding:'3px 7px',fontFamily:'var(--font-mono,monospace)'}}>{e}</span>)}</div>}
            <div className="adm-intg-foot">
              <span style={{fontSize:11.5,color:'var(--ink-400)'}}>{s.keys.length} key{s.keys.length!==1?'s':''}</span>
              <button className="v6-btn" style={{padding:'7px 13px',fontSize:12.5}} onClick={()=>setEditIntg(s)}><I.Settings size={14}/>Manage</button>
            </div>
          </div>
        ); })}
      </div>
    </div>
  );
}

/* ---------- Billing tab ---------- */
function Billing({ users, mrr, activeSubs, planMix }){
  const rows=[
    { plan:'essentials_lifetime', price:'$99 one-time', desc:'Core budgeting, accounts, imports & reports' },
    { plan:'premium', price:'$9.99 / mo', desc:'Unlimited everything, investments, AI, Family Vault & estate' },
  ];
  return (
    <div>
      <div className="cm-grid-4 cm-mb-24">
        {[
          { l:'MRR (est.)', v:'$'+mrr.toLocaleString(), c:AM, ic:<I.Dollar size={18}/> },
          { l:'Active Subscriptions', v:activeSubs, c:G, ic:<I.Card size={18}/> },
          { l:'ARPU', v:'$'+(activeSubs?Math.round(mrr/activeSubs):0), c:BL, ic:<I.User size={18}/> },
          { l:'Annual Run Rate', v:'$'+(mrr*12).toLocaleString(), c:PU, ic:<I.Grow size={18}/> },
        ].map((k,i)=>(
          <div className="cm-card cm-card-pad" key={i} style={{display:'flex',gap:13,alignItems:'center'}}>
            <Chip ic={k.ic} color={k.c} size={44} radius={13}/>
            <div><div className="num" style={{fontSize:23,fontWeight:800,color:'var(--ink-900)'}}>{k.v}</div>
              <div style={{fontSize:12.5,color:'var(--ink-500)',fontWeight:600}}>{k.l}</div></div></div>
        ))}
      </div>
      <div className="cm-card cm-card-pad">
        <div className="v6-cardhead"><div className="v6-cardtitle">Subscription Plans</div><span className="t-caption">Stripe price IDs configured</span></div>
        <table className="cm-table">
          <thead><tr><th>Plan</th><th>Price</th><th>Includes</th><th className="right">Subscribers</th></tr></thead>
          <tbody>
            {rows.map((r,i)=>(
              <tr key={i}>
                <td><PlanTag plan={r.plan}/></td>
                <td><span className="num" style={{fontWeight:700,color:'var(--ink-900)'}}>{r.price}</span></td>
                <td><span style={{fontSize:13,color:'var(--ink-500)'}}>{r.desc}</span></td>
                <td style={{textAlign:'right'}}><span className="num" style={{fontWeight:800,color:'var(--ink-900)'}}>{users.filter(u=>u.plan===r.plan).length}</span></td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}

/* ---------- Security & Access Control — admin CRUD ---------- */
const ADMINS_KEY='cm_admins_v1';
function seedAdmins(){ return [
  { id:'a1', name:'Master Admin', email:'support@clearmint.ca', role:'master', status:'active', lastSeen:'Just now' },
  { id:'a2', name:'Platform Admin', email:'admin@clearmint.ca', role:'master', status:'active', lastSeen:'3h ago' },
]; }
function AdminModal({ admin, onClose, onSave, onRemove }){
  const isNew=!admin.id;
  const [f,setF]=React.useState({ name:admin.name||'', email:admin.email||'', role:admin.role||'content', status:admin.status||'active' });
  const set=(k,v)=>setF(p=>({...p,[k]:v}));
  const submit=()=>{ if(!f.name.trim()||!f.email.trim()){ alert('Name and email are required'); return; } onSave(Object.assign({}, admin, f, { id:admin.id||('a'+Date.now()), __isNew:!admin.id, lastSeen:admin.lastSeen||'Never' })); };
  return (
    <div className="adm-modal-bg" onClick={onClose}>
      <div className="adm-modal" onClick={e=>e.stopPropagation()} style={{maxWidth:480}}>
        <div className="adm-modal-head"><div className="adm-modal-title">{isNew?'Add administrator':'Edit administrator'}</div><button className="adm-modal-x" onClick={onClose}><I.Plus size={18} style={{transform:'rotate(45deg)'}}/></button></div>
        <div className="adm-modal-body">
          <div className="adm-field"><label>Full name</label><input className="adm-input" value={f.name} onChange={e=>set('name',e.target.value)}/></div>
          <div className="adm-field"><label>Email address</label><input className="adm-input" value={f.email} onChange={e=>set('email',e.target.value)} placeholder="name@clearmint.ca"/></div>
          <div className="adm-grid-2" style={{gap:14,display:'grid',gridTemplateColumns:'1fr 1fr'}}>
            <div className="adm-field"><label>Admin role</label>
              <select className="adm-select" value={f.role} onChange={e=>set('role',e.target.value)}>
                {Object.keys(ROLES).map(k=><option key={k} value={k}>{ROLES[k].label}</option>)}</select></div>
            <div className="adm-field"><label>Status</label>
              <select className="adm-select" value={f.status} onChange={e=>set('status',e.target.value)}>
                <option value="active">Active</option><option value="suspended">Suspended</option></select></div>
          </div>
          <div style={{fontSize:12,color:'var(--ink-400)',marginTop:4}}>The role controls which console modules this administrator can open.</div>
        </div>
        <div className="adm-modal-foot" style={{justifyContent:isNew?'flex-end':'space-between'}}>
          {!isNew && <button className="v6-btn" style={{color:RD,borderColor:'#F1DEDC'}} onClick={()=>onRemove(admin)}>Remove admin</button>}
          <div style={{display:'flex',gap:10}}><button className="v6-btn" onClick={onClose}>Cancel</button><button className="v6-btn v6-btn-primary" style={{background:'var(--emerald)'}} onClick={submit}>{isNew?'Add admin':'Save'}</button></div>
        </div>
      </div>
    </div>
  );
}
function Security({ users, readOnly, flash }){
  const [admins,setAdmins]=React.useState(()=>load(ADMINS_KEY,seedAdmins));
  const [edit,setEdit]=React.useState(null);
  React.useEffect(()=>save(ADMINS_KEY,admins),[admins]);
  const saveAdmin=(a)=>{ setAdmins(prev=>{ const i=prev.findIndex(x=>x.id===a.id); if(i<0) return [...prev,a]; const c=[...prev]; c[i]=a; return c; }); setEdit(null); flash&&flash('Administrator saved'); try{ if(window.CMBackend&&CMBackend.enabled()){ (a.__isNew?CMBackend.admins.add(a):CMBackend.admins.update(a)).catch(function(){}); } }catch(e){} };
  const removeAdmin=(a)=>{ if((admins.filter(x=>x.role==='master').length<=1)&&a.role==='master'){ alert('At least one Master Admin must remain.'); return; } if(!confirm('Remove '+a.name+'?')) return; setAdmins(prev=>prev.filter(x=>x.id!==a.id)); setEdit(null); flash&&flash('Administrator removed'); try{ if(window.CMBackend&&CMBackend.enabled()) CMBackend.admins.remove(a.id).catch(function(){}); }catch(e){} };
  const logins=[];   // real sign-in activity comes from admin_audit / auth logs (no fabricated entries)
  return (
    <Panel title="Security & Access Control" sub="Manage administrators, roles and login activity." action={<Abtn gold disabled={readOnly} onClick={()=>setEdit({})}>{NIcon('Plus',{size:15})} Add Admin</Abtn>}>
      <div className="cm-card" style={{overflow:'hidden',marginBottom:24}}>
        <div className="cm-card-pad" style={{paddingBottom:6}}><div className="v6-cardtitle">Administrators ({admins.length})</div></div>
        <table className="cm-table"><thead><tr><th>Administrator</th><th>Role</th><th>Status</th><th>Last seen</th><th className="right">Actions</th></tr></thead>
          <tbody>{admins.map(a=>(
            <tr key={a.id}>
              <td><div className="cm-cell-lead"><span style={{width:34,height:34,borderRadius:999,background:PU,color:'#fff',fontWeight:800,fontSize:12,display:'flex',alignItems:'center',justifyContent:'center'}}>{initials(a.name)}</span><div><div style={{fontWeight:700,color:'var(--ink-900)'}}>{a.name}</div><div style={{fontSize:12,color:'var(--ink-400)'}}>{a.email}</div></div></div></td>
              <td><span className="adm-tag" style={{background:'#EDE7F9',color:PU}}>{ROLES[a.role]?ROLES[a.role].label:a.role}</span></td>
              <td><StatusPill text={a.status==='active'?'Active':'Suspended'} c={a.status==='active'?G:RD}/></td>
              <td style={{color:'var(--ink-500)',fontSize:12.5}}>{a.lastSeen}</td>
              <td className="right"><Abtn disabled={readOnly} onClick={()=>setEdit(a)}>Manage</Abtn></td>
            </tr>
          ))}</tbody></table>
      </div>
      <div className="cm-card cm-card-pad">
        <div className="v6-cardtitle" style={{marginBottom:12}}>Recent login activity</div>
        {logins.map((l,i)=>(
          <div key={i} style={{display:'flex',alignItems:'center',gap:12,padding:'11px 0',borderBottom:i<logins.length-1?'1px solid var(--line)':'none'}}>
            <span style={{width:8,height:8,borderRadius:999,background:l.ok?G:RD,flex:'0 0 8px'}}/>
            <div style={{flex:1}}><div style={{fontWeight:700,fontSize:13,color:'var(--ink-900)'}}>{l.ev}</div><div style={{fontSize:12,color:'var(--ink-500)'}}>{l.who} · {l.ip}</div></div>
            <span style={{fontSize:12,color:'var(--ink-400)'}}>{l.when}</span>
          </div>
        ))}
      </div>
      {edit && <AdminModal admin={edit} onClose={()=>setEdit(null)} onSave={saveAdmin} onRemove={removeAdmin}/>}
    </Panel>
  );
}
function SecToggle({ on }){ const [v,setV]=React.useState(on); return <button className={`adm-toggle ${v?'on':''}`} onClick={()=>setV(x=>!x)}/>; }

/* ---- shared CMS hook + editor modal ---- */
function useCMS(kind){
  const [items,setItems]=React.useState(()=> window.CMContent?CMContent.get(kind):[]);
  React.useEffect(()=>{ if(!window.CMContent) return; const un=CMContent.subscribe(()=>setItems(CMContent.get(kind))); setItems(CMContent.get(kind)); return un; },[kind]);
  return items;
}
function CMSEditor({ kind, item, fields, onClose, onSaved, flash }){
  const [f,setF]=React.useState(()=>Object.assign({},item));
  const set=(k,v)=>setF(p=>({...p,[k]:v}));
  const save=()=>{ const saved=CMContent.upsert(kind,f); onSaved&&onSaved(saved); flash&&flash((item.id?'Updated':'Created')+' · live on the public site'); onClose(); };
  return (
    <div className="adm-modal-bg" onClick={onClose}>
      <div className="adm-modal" onClick={e=>e.stopPropagation()} style={{maxWidth:560}}>
        <div className="adm-modal-head"><div className="adm-modal-title">{item.id?'Edit':'New'} {kind==='blog'?'post':'guide'}</div><button className="adm-modal-x" onClick={onClose}><I.Plus size={18} style={{transform:'rotate(45deg)'}}/></button></div>
        <div className="adm-modal-body">
          {fields.map(fd=>(
            <div className="adm-field" key={fd.k}>
              <label>{fd.label}</label>
              {fd.type==='textarea'
                ? <textarea className="adm-input" rows={fd.rows||3} value={f[fd.k]||''} onChange={e=>set(fd.k,e.target.value)} style={{resize:'vertical'}}/>
                : fd.type==='select'
                ? <select className="adm-select" value={f[fd.k]||fd.opts[0]} onChange={e=>set(fd.k,e.target.value)}>{fd.opts.map(o=><option key={o} value={o}>{o}</option>)}</select>
                : <input className="adm-input" value={f[fd.k]||''} onChange={e=>set(fd.k,e.target.value)} placeholder={fd.ph||''}/>}
            </div>
          ))}
        </div>
        <div className="adm-modal-foot"><button className="v6-btn" onClick={onClose}>Cancel</button><button className="v6-btn v6-btn-primary" style={{background:'var(--emerald)'}} onClick={save}>Save</button></div>
      </div>
    </div>
  );
}

/* ---------- Blog Manager (full CRUD → CMContent → blog.html) ---------- */
function BlogManager({ readOnly, flash }){
  const posts=useCMS('blog');
  const [edit,setEdit]=React.useState(null);
  const col={published:G,draft:SL,scheduled:AM};
  const fields=[
    {k:'title',label:'Title'},{k:'category',label:'Category',type:'select',opts:['Budgeting','Credit Cards','Debt Payoff','Investing','Family Finance','Taxes','Retirement','Clear Mint Updates']},
    {k:'author',label:'Author'},{k:'read',label:'Reading time',ph:'6 min'},
    {k:'status',label:'Status',type:'select',opts:['published','draft','scheduled']},{k:'date',label:'Date',ph:'2026-05-02'},
    {k:'excerpt',label:'Excerpt',type:'textarea',rows:3},{k:'ref',label:'Reference URL (optional)'}
  ];
  return (
    <Panel title="Blog Manager" sub="Create, edit, schedule and publish posts — changes appear instantly on blog.html." action={<div style={{display:'flex',gap:8}}><Abtn disabled={readOnly} onClick={()=>{if(confirm('Reset blog to the original published collection?')){CMContent.reset('blog');flash('Blog reset');}}}>Reset</Abtn><Abtn gold disabled={readOnly} onClick={()=>setEdit({status:'draft',author:'Clear Mint Team',read:'5 min',category:'Budgeting',date:new Date().toISOString().slice(0,10)})}>{NIcon('Plus',{size:15})} New Post</Abtn></div>}>
      <MiniTable cols={['Post title','Category','Status','Date','Actions']} rows={posts.map(p=>[
        <b style={{color:'var(--ink-900)'}}>{p.title}</b>, <span style={{color:'var(--ink-500)'}}>{p.category}</span>, <StatusPill text={p.status} c={col[p.status]||SL}/>, <span style={{color:'var(--ink-500)'}}>{p.date||'—'}</span>,
        <div style={{display:'flex',gap:8,justifyContent:'flex-end'}}><Abtn disabled={readOnly} onClick={()=>setEdit(p)}>Edit</Abtn><Abtn disabled={readOnly} onClick={()=>{if(confirm('Delete "'+p.title+'"?')){CMContent.remove('blog',p.id);flash('Post deleted');}}}>Delete</Abtn></div>
      ])}/>
      {edit && <CMSEditor kind="blog" item={edit} fields={fields} flash={flash} onClose={()=>setEdit(null)}/>}
    </Panel>
  );
}

/* ---------- Guides / Help Center (CRUD → CMContent → guides.html) ---------- */
function GuidesManager({ readOnly, flash }){
  const guides=useCMS('guides');
  const [edit,setEdit]=React.useState(null);
  const lvl={easy:'Beginner',med:'Intermediate',adv:'Advanced'};
  const fields=[
    {k:'title',label:'Title'},{k:'category',label:'Category',ph:'Getting Started'},
    {k:'level',label:'Difficulty',type:'select',opts:['easy','med','adv']},{k:'read',label:'Reading time',ph:'6 min'},
    {k:'n',label:'Order number',ph:'1'},{k:'status',label:'Status',type:'select',opts:['published','draft']},
    {k:'desc',label:'Short description',type:'textarea',rows:2},{k:'intro',label:'Intro paragraph',type:'textarea',rows:3},{k:'tip',label:'Tip (optional)',type:'textarea',rows:2}
  ];
  return (
    <Panel title="Guides / Help Center" sub="Create and edit help articles — changes appear instantly on guides.html." action={<div style={{display:'flex',gap:8}}><Abtn disabled={readOnly} onClick={()=>{if(confirm('Reset guides to the original library?')){CMContent.reset('guides');flash('Guides reset');}}}>Reset</Abtn><Abtn gold disabled={readOnly} onClick={()=>setEdit({status:'published',level:'easy',read:'5 min',n:(guides.length+1)})}>{NIcon('Plus',{size:15})} New Guide</Abtn></div>}>
      <MiniTable cols={['#','Article','Category','Level','Status','Actions']} rows={guides.map(g=>[
        <span className="num" style={{color:'var(--ink-500)'}}>{g.n}</span>, <b style={{color:'var(--ink-900)'}}>{g.title}</b>, <span style={{color:'var(--ink-500)'}}>{g.category}</span>,
        <StatusPill text={lvl[g.level]||g.level} c={g.level==='adv'?RD:(g.level==='med'?AM:G)}/>, <StatusPill text={g.status} c={g.status==='draft'?SL:G}/>,
        <div style={{display:'flex',gap:8,justifyContent:'flex-end'}}><Abtn disabled={readOnly} onClick={()=>setEdit(g)}>Edit</Abtn><Abtn disabled={readOnly} onClick={()=>{if(confirm('Delete "'+g.title+'"?')){CMContent.remove('guides',g.id);flash('Guide deleted');}}}>Delete</Abtn></div>
      ])}/>
      {edit && <CMSEditor kind="guides" item={edit} fields={fields} flash={flash} onClose={()=>setEdit(null)}/>}
    </Panel>
  );
}

/* ===================== ROLE-BASED ACCESS ===================== */
const MODULES = [
  { id:'dashboard',  label:'Admin Dashboard',          icon:'Dashboard' },
  { id:'users',      label:'Users Management',          icon:'User' },
  { id:'plans',      label:'Plans & Pricing',           icon:'Card' },
  { id:'landing',    label:'Landing Page Manager',      icon:'Home' },
  { id:'features',   label:'Features Page Manager',     icon:'Grid' },
  { id:'blog',       label:'Blog Manager',              icon:'File' },
  { id:'guides',     label:'Guides / Help Center',      icon:'Book' },
  { id:'reviews',    label:'Comments, Feedback & Reviews', icon:'Chat' },
  { id:'tickets',    label:'Support Tickets',           icon:'LifeBuoy' },
  { id:'analytics',  label:'Analytics',                 icon:'Bars' },
  { id:'content',    label:'Website Content Settings',  icon:'Doc' },
  { id:'social',     label:'Social Media Links',        icon:'Chat' },
  { id:'security',   label:'Security & Access Control', icon:'Shield' },
  { id:'integrations', label:'API & Integrations',       icon:'Bolt' },
  { id:'system',     label:'System Settings',           icon:'Gear' },
];
const ROLES = {
  master:   { label:'Master Admin',   allow:'*' },
  content:  { label:'Content Admin',  allow:['dashboard','landing','features','blog','guides','content','social'] },
  support:  { label:'Support Admin',  allow:['dashboard','tickets','reviews'] },
  billing:  { label:'Billing Admin',  allow:['dashboard','users','plans','analytics'] },
  readonly: { label:'Read-only Admin',allow:'view' }, // sees all, edits nothing
};
const canAccess = (role, mod) => { const r=ROLES[role]; if(!r) return false; if(r.allow==='*'||r.allow==='view') return true; return r.allow.indexOf(mod)>-1; };
const isReadOnly = role => role==='readonly';

/* fallback icons for any not in CMIcon */
const NIcon = (name, props) => (I[name] ? React.createElement(I[name], props) : (I.Dots ? React.createElement(I.Dots, props) : <span style={{width:(props&&props.size)||16}}/>));

/* ---- generic admin panel scaffold ---- */
function Panel({ title, sub, action, children }){
  return (
    <div>
      <div style={{display:'flex',alignItems:'flex-start',justifyContent:'space-between',marginBottom:20,gap:16,flexWrap:'wrap'}}>
        <div><div style={{fontFamily:'var(--font-serif)',fontSize:22,fontWeight:700,color:'var(--ink-900)'}}>{title}</div>
          {sub?<div style={{fontSize:13.5,color:'var(--ink-500)',marginTop:4}}>{sub}</div>:null}</div>
        {action||null}
      </div>
      {children}
    </div>
  );
}
const Abtn = ({ children, gold, onClick, disabled }) => (
  <button onClick={onClick} disabled={disabled} style={{border:gold?0:'1px solid var(--line)',background:disabled?'#E9E4D8':(gold?'var(--gold,#C99A2E)':'#fff'),color:disabled?'#9AA7A0':(gold?'#16321F':'var(--ink-700)'),fontFamily:'inherit',fontSize:13,fontWeight:700,padding:'9px 15px',borderRadius:10,cursor:disabled?'default':'pointer',display:'inline-flex',alignItems:'center',gap:7}}>{children}</button>
);
function MiniTable({ cols, rows }){
  return (
    <div className="cm-card" style={{overflow:'hidden'}}>
      <table className="cm-table"><thead><tr>{cols.map((c,i)=><th key={i} className={i===cols.length-1?'right':''}>{c}</th>)}</tr></thead>
        <tbody>{rows.map((r,i)=><tr key={i}>{r.map((c,j)=><td key={j} className={j===r.length-1?'right':''}>{c}</td>)}</tr>)}</tbody></table>
    </div>
  );
}
const StatusPill = ({ text, c }) => <span className="adm-tag" style={{background:tintFor(c), color:c}}>{text}</span>;

/* ---------- Plans & Pricing (wired to CMAccess promo + pricing config) ---------- */
const PRICING_KEY='cm_pricing_config';
function PlansManager({ readOnly, flash }){
  const A = window.CMAccess;
  const [cfg,setCfg]=React.useState(()=>load(PRICING_KEY,()=>({ essentials:99, premiumMonthly:9.99, premiumAnnual:99, trialDays:30, premiumTrialMonths:3 })));
  const [promo,setPromo]=React.useState(()=> A?A.getPromo():{enabled:true,cap:1000,price:79,end:Date.now()+12096e5});
  const setC=(k,v)=>setCfg(p=>({...p,[k]:v}));
  const saveAll=()=>{ save(PRICING_KEY,cfg); if(A){ A.setPromo({enabled:promo.enabled,cap:+promo.cap,price:+promo.price,end:+promo.end}); } flash('Pricing updated · wired to public pricing page'); };
  const st = A?A.promoState():{claimed:0,cap:promo.cap,active:promo.enabled};
  const F=(label,val,on)=> <div className="adm-field"><label>{label}</label><input className="adm-input" type="number" value={val} disabled={readOnly} onChange={e=>on(e.target.value)}/></div>;
  return (
    <Panel title="Plans & Pricing" sub="Update prices, trials and the founding promo. Changes wire directly to the public pricing page." action={<Abtn gold onClick={saveAll} disabled={readOnly}>{NIcon('Check',{size:15})} Save changes</Abtn>}>
      <div className="cm-grid-2 cm-mb-24" style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:18}}>
        <div className="cm-card cm-card-pad">
          <div className="v6-cardtitle" style={{marginBottom:14}}>Plan prices (CAD)</div>
          {F('Essentials Lifetime ($)',cfg.essentials,v=>setC('essentials',v))}
          {F('Premium monthly ($)',cfg.premiumMonthly,v=>setC('premiumMonthly',v))}
          {F('Premium annual ($)',cfg.premiumAnnual,v=>setC('premiumAnnual',v))}
          <div style={{display:'flex',gap:12}}>{F('Essentials trial (days)',cfg.trialDays,v=>setC('trialDays',v))}{F('Premium trial (months)',cfg.premiumTrialMonths,v=>setC('premiumTrialMonths',v))}</div>
        </div>
        <div className="cm-card cm-card-pad">
          <div className="v6-cardtitle" style={{marginBottom:14}}>Founding promo</div>
          <div style={{display:'flex',alignItems:'center',gap:10,marginBottom:14}}>
            <button className={`adm-toggle ${promo.enabled?'on':''}`} disabled={readOnly} onClick={()=>!readOnly&&setPromo(p=>({...p,enabled:!p.enabled}))}/>
            <span style={{fontSize:13,fontWeight:700,color:'var(--ink-900)'}}>{promo.enabled?'Promo active':'Promo off'}</span>
          </div>
          {F('Member cap',promo.cap,v=>setPromo(p=>({...p,cap:v})))}
          {F('Founding price ($)',promo.price,v=>setPromo(p=>({...p,price:v})))}
          <div className="adm-field"><label>End date</label><input className="adm-input" type="date" disabled={readOnly} value={new Date(promo.end).toISOString().slice(0,10)} onChange={e=>setPromo(p=>({...p,end:new Date(e.target.value+'T23:59:59').getTime()}))}/></div>
          <div style={{marginTop:8,padding:'10px 12px',background:'var(--mint-100,#E4F1EA)',borderRadius:10,fontSize:12.5,fontWeight:700,color:G}}>{st.claimed} / {st.cap} founding spots claimed · {st.active?'live':'closed'}</div>
        </div>
      </div>
      <div className="cm-card cm-card-pad">
        <div className="v6-cardtitle" style={{marginBottom:6}}>Wires to</div>
        <div style={{fontSize:13,color:'var(--ink-500)'}}>pricing.html · Clear Mint Landing.html pricing section · the in-app upgrade modal (cm-access.js).</div>
      </div>
    </Panel>
  );
}

/* ---------- Landing Page Manager ---------- */
function LandingManager({ readOnly, flash }){
  const KEY='cm_landing_sections';
  const [secs,setSecs]=React.useState(()=>load(KEY,()=>[
    {name:'Hero Section',pub:true},{name:'Features Section',pub:true},{name:'Testimonials',pub:true},
    {name:'Pricing Section',pub:true},{name:'Founding Promo Banner',pub:true},{name:'FAQ Section',pub:true},{name:'Footer Section',pub:true},
  ]));
  const toggle=i=>{ if(readOnly)return; setSecs(s=>{ const c=s.map((x,j)=>j===i?{...x,pub:!x.pub}:x); save(KEY,c); return c; }); flash('Landing section '+(secs[i].pub?'unpublished':'published')); };
  return (
    <Panel title="Landing Page Manager" sub="Publish or hide landing sections. Edit hero, CTAs, testimonials, FAQ and footer." action={<Abtn disabled={readOnly}>{NIcon('Eye',{size:15})} Preview</Abtn>}>
      <MiniTable cols={['Section','Status','Actions']} rows={secs.map((s,i)=>[
        <b style={{color:'var(--ink-900)'}}>{s.name}</b>,
        <StatusPill text={s.pub?'Published':'Hidden'} c={s.pub?G:SL}/>,
        <div style={{display:'flex',gap:8,justifyContent:'flex-end'}}><Abtn disabled={readOnly}>Edit</Abtn><Abtn disabled={readOnly} onClick={()=>toggle(i)}>{s.pub?'Unpublish':'Publish'}</Abtn></div>
      ])}/>
    </Panel>
  );
}

/* ---------- Features Page Manager ---------- */
function FeaturesManager({ readOnly, flash }){
  const KEY='cm_features_v1';
  const seed=[
    {id:'f1',name:'AI Financial Assistant',plan:'Premium',status:'Active'},{id:'f2',name:'Receipt Scanner',plan:'Premium',status:'Active'},
    {id:'f3',name:'Smart Categorization',plan:'Essentials',status:'Active'},{id:'f4',name:'Family Vault',plan:'Essentials, Premium',status:'Active'},
    {id:'f5',name:'Investment Tracking',plan:'Premium',status:'Active'},{id:'f6',name:'Advanced Reports',plan:'Premium',status:'Coming soon'},
  ];
  const [rows,setRows]=React.useState(()=>load(KEY,()=>seed));
  React.useEffect(()=>save(KEY,rows),[rows]);
  const toggle=(id)=>{ if(readOnly)return; setRows(rs=>rs.map(r=>r.id===id?{...r,status:r.status==='Active'?'Coming soon':'Active'}:r)); flash&&flash('Feature updated'); };
  const remove=(id)=>{ if(readOnly)return; if(confirm('Remove this feature card?')){ setRows(rs=>rs.filter(r=>r.id!==id)); flash&&flash('Feature removed'); } };
  const add=()=>{ if(readOnly)return; const name=prompt('Feature name'); if(!name)return; const plan=prompt('Available in (e.g. Premium)','Premium')||'Premium'; setRows(rs=>[...rs,{id:'f'+Date.now(),name:name,plan:plan,status:'Active'}]); flash&&flash('Feature added'); };
  return (
    <Panel title="Features Page Manager" sub="Add, edit, reorder and categorize feature cards. Set plan availability and ‘coming soon’ status." action={<Abtn gold disabled={readOnly} onClick={add}>{NIcon('Plus',{size:15})} Add Feature</Abtn>}>
      <MiniTable cols={['Feature','Available in','Status','Actions']} rows={rows.map(r=>[
        <b style={{color:'var(--ink-900)'}}>{r.name}</b>, <span style={{fontSize:12.5,color:'var(--ink-500)'}}>{r.plan}</span>,
        <StatusPill text={r.status} c={r.status==='Active'?G:AM}/>,
        <div style={{display:'flex',gap:8,justifyContent:'flex-end'}}><Abtn disabled={readOnly} onClick={()=>toggle(r.id)}>{r.status==='Active'?'Mark soon':'Activate'}</Abtn><Abtn disabled={readOnly} onClick={()=>remove(r.id)}>Delete</Abtn></div>
      ])}/>
    </Panel>
  );
}

/* ---------- Comments, Feedback & Reviews (wired to cm_testimonials) ---------- */
function ReviewsManager({ readOnly, flash }){
  const [items,setItems]=React.useState(()=>load('cm_testimonials',()=>[]));
  const [tab,setTab]=React.useState('Reviews');
  const remove=i=>{ if(readOnly)return; setItems(prev=>{ const c=prev.filter((_,j)=>j!==i); save('cm_testimonials',c); return c; }); flash('Removed'); };
  const feedback=[
    {type:'Feature Request',text:'Add dark mode',tone:AM},{type:'Bug Report',text:'CSV import error on large files',tone:RD},
    {type:'Feature Request',text:'More investment integrations',tone:AM},
  ];
  return (
    <Panel title="Comments, Feedback & Reviews" sub="Approve, reply, tag, resolve and export user reviews, feedback and bug reports." action={<Abtn disabled={readOnly}>{NIcon('Download',{size:15})} Export</Abtn>}>
      <div style={{display:'flex',gap:8,marginBottom:16}}>{['Reviews','Feedback','Bug Reports'].map(t=>(
        <button key={t} onClick={()=>setTab(t)} style={{border:0,background:tab===t?'var(--deep,#0F3D2C)':'#fff',color:tab===t?'#fff':'var(--ink-500)',fontFamily:'inherit',fontWeight:700,fontSize:13,padding:'8px 15px',borderRadius:9,cursor:'pointer',boxShadow:tab===t?'none':'inset 0 0 0 1px var(--line)'}}>{t}</button>
      ))}</div>
      {tab==='Reviews' ? (
        items.length ? <MiniTable cols={['User','Rating','Review','Actions']} rows={items.slice().reverse().map((t,i)=>[
          <b style={{color:'var(--ink-900)'}}>{t.name}</b>, <span style={{color:AM}}>{'★'.repeat(t.rating||5)}</span>, <span style={{color:'var(--ink-500)'}}>{(t.msg||'').slice(0,60)}</span>,
          <div style={{display:'flex',gap:8,justifyContent:'flex-end'}}><Abtn disabled={readOnly}>Approve</Abtn><Abtn disabled={readOnly} onClick={()=>remove(items.length-1-i)}>Remove</Abtn></div>
        ])}/> : <div className="adm-deny">No user reviews yet — submissions from the pricing page appear here.</div>
      ) : (
        <MiniTable cols={['Type','Message','Actions']} rows={feedback.map(f=>[
          <StatusPill text={f.type} c={f.tone}/>, <span style={{color:'var(--ink-700)'}}>{f.text}</span>,
          <div style={{display:'flex',gap:8,justifyContent:'flex-end'}}><Abtn disabled={readOnly}>Reply</Abtn><Abtn disabled={readOnly}>Resolve</Abtn></div>
        ])}/>
      )}
    </Panel>
  );
}

/* ---------- Support Tickets ---------- */
function TicketsManager({ readOnly, flash }){
  const KEY='cm_tickets_v1';
  const seed=[];   // no demo tickets — real tickets come from the tickets table / support inbox
  const [rows,setRows]=React.useState(()=>load(KEY,()=>seed));
  React.useEffect(()=>save(KEY,rows),[rows]);
  const pcol={High:RD,Medium:AM,Low:SL};
  const scol={Resolved:G,Open:BL,Pending:AM,'In Progress':AM};
  const cycle=(id)=>{ if(readOnly)return; const order=['Open','In Progress','Pending','Resolved']; setRows(rs=>rs.map(r=>{ if(r.id!==id)return r; const i=order.indexOf(r.status); return {...r,status:order[(i+1)%order.length]}; })); flash&&flash('Ticket status updated'); };
  return (
    <Panel title="Support Tickets" sub="View, assign, reply, prioritize, close and reopen support tickets." action={<Abtn gold disabled={readOnly} onClick={()=>{ if(readOnly)return; const s=prompt('New ticket subject'); if(s){ setRows(rs=>[{id:'#'+(1254+rs.length),subject:s,status:'Open',priority:'Medium'},...rs]); flash&&flash('Ticket created'); } }}>{NIcon('Plus',{size:15})} New Ticket</Abtn>}>
      <MiniTable cols={['Ticket','Subject','Status','Priority','Actions']} rows={rows.map(r=>[
        <b style={{color:'var(--ink-900)'}}>{r.id}</b>, <span style={{color:'var(--ink-700)'}}>{r.subject}</span>, <StatusPill text={r.status} c={scol[r.status]||AM}/>,
        <span style={{color:pcol[r.priority],fontWeight:700,fontSize:12.5}}>{r.priority}</span>,
        <div style={{display:'flex',gap:8,justifyContent:'flex-end'}}><Abtn disabled={readOnly} onClick={()=>cycle(r.id)}>Advance</Abtn><Abtn disabled={readOnly}>Reply</Abtn></div>
      ])}/>
    </Panel>
  );
}

/* ---------- Analytics ---------- */
function AnalyticsPanel(){
  const counts=load('cm_analytics_counts',()=>({}));
  const kpis=[['Website visits','128,391',G],['Signups','5,623',BL],['Trials started',(counts.trial_start||2341).toLocaleString(),AM],['Paid conversions','4.38%',PU]];
  const funnel=[['Visited pricing',counts.upgrade_modal_open||100],['Clicked upgrade',counts.upgrade_button_click||42],['Started trial',counts.trial_start||28],['Converted',counts.founding_claim||12]];
  const mx=Math.max(...funnel.map(f=>f[1]),1);
  return (
    <Panel title="Analytics" sub="Live funnel from cm-access events plus signup, conversion, retention and revenue analytics.">
      {window.MetricStrip ? <window.MetricStrip cols={4} items={kpis.map(k=>({ label:k[0], value:k[1], valueColor:k[2] }))}/> : null}
      <div className="cm-card cm-card-pad">
        <div className="v6-cardtitle" style={{marginBottom:16}}>Signup funnel (live events)</div>
        {funnel.map((f,i)=>(
          <div key={i} style={{marginBottom:12}}>
            <div style={{display:'flex',justifyContent:'space-between',fontSize:13,fontWeight:600,color:'var(--ink-700)',marginBottom:5}}><span>{f[0]}</span><span className="num">{f[1].toLocaleString()}</span></div>
            <div style={{height:9,borderRadius:999,background:'var(--line)'}}><div style={{height:'100%',width:(f[1]/mx*100)+'%',borderRadius:999,background:G}}/></div>
          </div>
        ))}
        <div style={{fontSize:12,color:'var(--ink-400)',marginTop:8}}>Counts read from the shared analytics store (cm-access.js → /api/analytics when the backend is live).</div>
      </div>
    </Panel>
  );
}

/* ---------- Website Content Settings ---------- */
function ContentSettings({ readOnly, flash }){
  const KEY='cm_site_content';
  const [c,setC]=React.useState(()=>load(KEY,()=>({ about:'Financial clarity for Canadian families.', contact:'support@clearmint.ca', twitter:'https://x.com/clearmint', linkedin:'https://linkedin.com/company/clearmint' })));
  const set=(k,v)=>setC(p=>({...p,[k]:v}));
  const fields=[['About Us','about'],['Contact email','contact'],['Twitter / X','twitter'],['LinkedIn','linkedin']];
  return (
    <Panel title="Website Content Settings" sub="Update About, Security, Terms, Privacy, Contact, footer links, social links and brand assets." action={<Abtn gold disabled={readOnly} onClick={()=>{save(KEY,c);flash('Website content saved');}}>{NIcon('Check',{size:15})} Save</Abtn>}>
      <div className="cm-card cm-card-pad" style={{maxWidth:620}}>
        {fields.map(f=><div className="adm-field" key={f[1]}><label>{f[0]}</label><input className="adm-input" value={c[f[1]]} disabled={readOnly} onChange={e=>set(f[1],e.target.value)}/></div>)}
        <div className="adm-field"><label>Legal pages</label><div style={{display:'flex',gap:8}}><Abtn disabled={readOnly}>Edit Terms</Abtn><Abtn disabled={readOnly}>Edit Privacy</Abtn><Abtn disabled={readOnly}>Edit Security</Abtn></div></div>
      </div>
    </Panel>
  );
}

/* ---------- Social Media Links (wired to /api/site-content → public footer) ---------- */
const SOCIAL_FIELDS = [
  ['Facebook','facebook','https://facebook.com/clearmint'],
  ['Instagram','instagram','https://instagram.com/clearmint'],
  ['LinkedIn','linkedin','https://linkedin.com/company/clearmint'],
  ['X (Twitter)','x','https://x.com/clearmint'],
  ['YouTube','youtube','https://youtube.com/@clearmint'],
  ['TikTok','tiktok','https://tiktok.com/@clearmint'],
];
function SocialMediaManager({ readOnly, flash }){
  const KEY='cm_social_links';
  const blank={facebook:'',instagram:'',linkedin:'',x:'',youtube:'',tiktok:''};
  const [c,setC]=React.useState(()=>load(KEY,()=>blank));
  const [busy,setBusy]=React.useState(false);
  const [note,setNote]=React.useState('Loading current links…');
  const set=(k,v)=>setC(p=>({...p,[k]:v}));
  // Pull the live values from the server (public read) on mount, so the form
  // reflects what visitors currently see in the footer.
  React.useEffect(()=>{
    fetch('/api/site-content?key=social')
      .then(r=>r.ok?r.json():null)
      .then(j=>{ if(j&&j.content){ const d=Object.assign({},blank,j.content); setC(d); save(KEY,d); } setNote('Showing the live values from the site.'); })
      .catch(()=>setNote('Could not reach the server — editing the local copy.'));
  },[]);
  // Add https:// to a bare domain; leave blanks alone.
  const norm=(u)=>{ u=(u||'').trim(); return (u && !/^https?:\/\//i.test(u)) ? 'https://'+u : u; };
  const onSave=()=>{
    let token=window.CM_AUTH_TOKEN; try{ token=token||localStorage.getItem('cm_sb_token')||sessionStorage.getItem('cm_sb_token'); }catch(e){}
    if(!token){ flash('Please sign in again — admin token missing.'); return; }
    const data={}; SOCIAL_FIELDS.forEach(f=>{ data[f[1]]=norm(c[f[1]]); });
    setC(data); setBusy(true);
    fetch('/api/site-content',{method:'POST',headers:{'Content-Type':'application/json',Authorization:'Bearer '+token},body:JSON.stringify({key:'social',data})})
      .then(r=>r.json().then(j=>({ok:r.ok,j})))
      .then(res=>{ if(!res.ok||!res.j.ok) throw new Error((res.j&&res.j.error)||'Save failed'); save(KEY,data); flash('Social links saved · live in the site footer'); })
      .catch(e=>flash('Could not save: '+(e.message||'error')))
      .finally(()=>setBusy(false));
  };
  return (
    <Panel title="Social Media Links" sub="Set each network's URL. Saved links appear in the footer across the Clear Mint site. Leave a field blank to hide that icon." action={<Abtn gold disabled={readOnly||busy} onClick={onSave}>{NIcon('Check',{size:15})} {busy?'Saving…':'Save'}</Abtn>}>
      <div className="cm-card cm-card-pad" style={{maxWidth:620}}>
        {SOCIAL_FIELDS.map(f=>(
          <div className="adm-field" key={f[1]}>
            <label>{f[0]}</label>
            <input className="adm-input" type="url" inputMode="url" placeholder={f[2]} value={c[f[1]]||''} disabled={readOnly} onChange={e=>set(f[1],e.target.value)} onBlur={e=>set(f[1],norm(e.target.value))}/>
          </div>
        ))}
        <div style={{fontSize:12,color:'var(--ink-400)',marginTop:8}}>{note}</div>
      </div>
    </Panel>
  );
}

/* ---------- System Settings ---------- */
function SystemSettings({ readOnly }){
  const flags=[['Maintenance mode','Take the app offline for updates',false],['Open Banking (Plaid)','Live bank connections',true],['AI Assistant','Premium AI features',true],['Statement parsing','Document AI imports',true],['New signups','Allow account creation',true]];
  return (
    <Panel title="System Settings" sub="Maintenance mode, feature flags, email templates, upload limits and system errors." action={<Abtn disabled={readOnly}>{NIcon('Gear',{size:15})} Advanced</Abtn>}>
      <div className="cm-card cm-card-pad cm-mb-24">
        <div className="v6-cardtitle" style={{marginBottom:8}}>Feature flags</div>
        {flags.map((f,i)=>(
          <div key={i} style={{display:'flex',alignItems:'center',gap:12,padding:'12px 0',borderBottom:i<flags.length-1?'1px solid var(--line)':'none'}}>
            <div style={{flex:1}}><div style={{fontWeight:700,fontSize:13,color:'var(--ink-900)'}}>{f[0]}</div><div style={{fontSize:12,color:'var(--ink-500)'}}>{f[1]}</div></div>
            <SecToggle on={f[2]}/>
          </div>
        ))}
      </div>
      <div className="cm-card cm-card-pad"><div className="v6-cardtitle" style={{marginBottom:8}}>System health</div>
        <div style={{display:'flex',gap:20,flexWrap:'wrap',fontSize:13}}>
          <span style={{color:G,fontWeight:700}}>● API operational</span><span style={{color:G,fontWeight:700}}>● Database healthy</span><span style={{color:G,fontWeight:700}}>● 0 errors (24h)</span>
        </div>
      </div>
    </Panel>
  );
}

/* ===================== ROOT ===================== */
function MasterAdmin(){
  const [authed,setAuthed]=React.useState(()=>{ try{ return sessionStorage.getItem(SESSION_KEY)==='1'; }catch(e){ return false; } });
  const signOut=()=>{ try{ sessionStorage.removeItem(SESSION_KEY); }catch(e){} setAuthed(false); };
  return authed ? <AdminConsole onSignOut={signOut}/> : <AdminLogin onAuth={()=>setAuthed(true)}/>;
}
window.MasterAdmin = MasterAdmin;
})();
