/* FinFlow mobile screens. MobileFlow supplies navigation, role, and in-memory demo state
   to the same interactive phone experience in the screen directory and mobile-app.html. */
const noop = () => {};

const MobileStatusBar = ({ theme = "light" }) => (
  <div style={{
    height:44, display:'flex', alignItems:'center', justifyContent:'space-between',
    padding:'0 22px', fontSize:14, fontWeight:600,
    color: theme === "dark" ? '#fff' : '#15181c'
  }}>
    <span className="ff-tnum">9:41</span>
    <span style={{display:'flex', gap:4, alignItems:'center'}}>
      <i className="ph-bold ph-signal-high" style={{fontSize:13}}/>
      <i className="ph-bold ph-wifi-high" style={{fontSize:13}}/>
      <i className="ph-fill ph-battery-full" style={{fontSize:15}}/>
    </span>
  </div>
);

const MobileFrame = ({ children, theme = "light", scrollable = true, fullbleed = false }) => (
  <div style={fullbleed ? {
    width:'100vw', height:'100dvh', flexShrink:0
  } : {
    width:360, height:760, borderRadius:42, padding:8,
    background: theme === 'dark' ? '#000' : '#15181c',
    boxShadow:'0 24px 60px -20px rgba(0,0,0,0.35)',
    flexShrink: 0
  }}>
    <div data-theme={theme === 'dark' ? 'dark' : 'light'} style={{
      width:'100%', height:'100%', borderRadius: fullbleed ? 0 : 34, overflow:'hidden', position:'relative',
      background:'var(--ff-bg)',
      display:'flex', flexDirection:'column'
    }}>
      {fullbleed && <h1 className="ff-sr-only">FinFlow mobile prototype</h1>}
      {/* On a real phone the OS already shows a real status bar — the faux one
          (fake "9:41", fake battery) is only for the desktop gallery mockup. */}
      {fullbleed ? null : <MobileStatusBar theme={theme}/>}
      <div className="ff-scroll" style={{
        flex:1, overflow: scrollable ? 'auto' : 'hidden',
        paddingTop: fullbleed ? 'env(safe-area-inset-top)' : 0
      }}>{children}</div>
    </div>
  </div>
);

const MobileSignIn = ({ onNav = noop, onRole = noop, role = "employee", allowRoleChange = true, fullbleed = false }) => {
  const [email, setEmail] = React.useState('casey.parker@reyonal.com');
  const [password, setPassword] = React.useState('finflow');
  const [errors, setErrors] = React.useState({});
  const signIn = () => {
    const next = {};
    if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email.trim())) next.email = 'Enter a valid work email.';
    if (!password.trim()) next.password = 'Enter your password.';
    setErrors(next);
    if (!Object.keys(next).length) onNav('home');
  };
  return (
  <MobileFrame theme="dark" fullbleed={fullbleed}>
    <div style={{
      flex:1, display:'flex', flexDirection:'column',
      padding:'48px 24px 32px',
      background:'var(--ff-blue-900)', color:'#fff', height:'100%'
    }}>
      <BrandMark variant="horizontal" theme="dark" size={28} style={{alignSelf:'center'}}/>
      <div style={{flex:1}}/>
      <div style={{fontFamily:'var(--ff-font-sans)', fontWeight:700, fontSize:36, lineHeight:1.1, letterSpacing:'-0.03em'}}>
        Welcome<br/>back, {role === 'manager' ? 'Taylor' : 'Casey'}.
      </div>
      <p style={{opacity:0.7, fontSize:13, marginTop:12}}>{role === 'manager' ? 'Sign in to review your team’s expenses.' : 'Sign in to submit and track your expenses.'}</p>
      <div className="ff-stack" style={{'--ff-stack-gap':'10px', marginTop:24}}>
        <div><input aria-label="Work email" className="ff-input ff-input--lg" placeholder="Work email" value={email} onChange={e=>setEmail(e.target.value)} onBlur={()=>{if(!email.trim())setErrors(current=>({...current,email:'Enter a valid work email.'}));}} style={{background:'rgba(255,255,255,0.08)', border:'1px solid rgba(255,255,255,0.18)', color:'#fff'}}/>{errors.email&&<FieldError error={errors.email}/>}</div>
        <div><input aria-label="Password" className="ff-input ff-input--lg" type="password" placeholder="Password" value={password} onChange={e=>setPassword(e.target.value)} onBlur={()=>{if(!password.trim())setErrors(current=>({...current,password:'Enter your password.'}));}} style={{background:'rgba(255,255,255,0.08)', border:'1px solid rgba(255,255,255,0.18)', color:'#fff'}}/>{errors.password&&<FieldError error={errors.password}/>}</div>
        {allowRoleChange && <div className="ff-segmented ff-segmented--sm" role="group" aria-label="Mobile role"><button aria-pressed={role==='employee'} onClick={()=>onRole('employee')}>Employee</button><button aria-pressed={role==='manager'} onClick={()=>onRole('manager')}>Manager</button></div>}
        <button className="ff-btn ff-btn--accent ff-btn--lg" style={{width:'100%', marginTop:8}} onClick={signIn}>Sign in as {role === 'manager' ? 'Manager' : 'Employee'}</button>
        <button className="ff-btn ff-btn--ghost" style={{color:'#fff', width:'100%'}} onClick={() => {setErrors({});onNav('home');}}><Icon name="fingerprint" size={16}/> Use Face ID</button>
      </div>
      <div style={{textAlign:'center', fontSize:12, opacity:0.6, marginTop:24}}>Reyonal · SSO available</div>
    </div>
  </MobileFrame>
  );
};

const MobileHome = ({ onNav = noop, role = 'employee', onApprove = noop, onReject = noop, notice = '', fullbleed = false }) => {
  const d = FF_DATA;
  if (role === 'manager') return <MobileManagerQueue onNav={onNav} onApprove={onApprove} onReject={onReject} fullbleed={fullbleed}/>;
  return (
    <MobileFrame fullbleed={fullbleed}>
      <div style={{padding:'8px 20px 100px'}}>
        <ActionFeedback message={notice}/>
        <div className="ff-row" style={{justifyContent:'space-between', marginTop:8}}>
          <div>
            <div style={{fontSize:12, color:'var(--ff-fg-muted)'}}>Tuesday</div>
            <div style={{fontFamily:'var(--ff-font-sans)', fontWeight:700, fontSize:26, lineHeight:1.1, letterSpacing:'-0.025em', marginTop:2, whiteSpace:'nowrap'}}>Hi, Casey.</div>
          </div>
          <Avatar initials="CP" name="Casey Parker" size="lg"/>
        </div>

        <div style={{marginTop:20, padding:18, borderRadius:14, background:'linear-gradient(135deg, var(--ff-blue-700), var(--ff-blue-900))', color:'#fff', position:'relative'}}>
          <div style={{fontSize:11, opacity:0.7, textTransform:'uppercase', letterSpacing:'0.1em'}}>My spend · May</div>
          <div style={{fontFamily:'var(--ff-font-sans)', fontWeight:700, fontSize:34, lineHeight:1.0, letterSpacing:'-0.03em', marginTop:6}} className="ff-tnum">$2,184</div>
          <div style={{fontSize:12, opacity:0.7, marginTop:6}}>$316 under your avg · 6 expenses</div>
          <div style={{position:'absolute', top:14, right:14}}><BrandMark variant="mark" size={24} theme="dark"/></div>
        </div>

        <div className="ff-grid ff-grid--2" style={{marginTop:14, gap:10}}>
          <button className="ff-btn ff-btn--lg" style={{flexDirection:'column', height:80, gap:6}} onClick={() => onNav('snap')}>
            <Icon name="camera" size={22} weight="bold"/>
            <span style={{fontSize:13}}>Snap receipt</span>
          </button>
          <button className="ff-btn ff-btn--lg ff-btn--primary" style={{flexDirection:'column', height:80, gap:6}} onClick={() => onNav('new')}>
            <Icon name="plus" size={22} weight="bold"/>
            <span style={{fontSize:13}}>New expense</span>
          </button>
        </div>

        <div style={{marginTop:24}}>
          <div className="ff-row" style={{justifyContent:'space-between', marginBottom:10}}>
            <div className="ff-eyebrow">Recent</div>
            <a href="#" onClick={(e) => { e.preventDefault(); onNav('expenses'); }} style={{fontSize:12}}>See all</a>
          </div>
          <div className="ff-stack" style={{'--ff-stack-gap':'8px'}}>
            {d.expenses.filter(e => e.who === "Casey Parker").map(e => (
              <div key={e.id} onClick={() => onNav('timeline', e.id)} style={{padding:'12px 14px', background:'var(--ff-card)', border:'1px solid var(--ff-border)', borderRadius:10, display:'flex', gap:12, alignItems:'center', cursor:'pointer'}}>
                <div style={{width:36, height:36, borderRadius:8, background:'var(--ff-card-2)', display:'grid', placeItems:'center'}}>
                  {MERCHANT_ICON_MAP[e.merchant] ? <BrandIcon name={MERCHANT_ICON_MAP[e.merchant]} size={18}/> : <Icon name={e.cat === 'me' ? 'coffee' : e.cat === 'sw' ? 'app-window' : e.cat === 'ad' ? 'megaphone' : 'tag'} size={16}/>}
                </div>
                <div style={{flex:1, minWidth:0}}>
                  <div style={{fontWeight:500, fontSize:14}}>{e.merchant}</div>
                  <div style={{fontSize:11, color:'var(--ff-fg-muted)'}}>{e.date.slice(5)} · {FF_DATA.categories.find(c=>c.id===e.cat).name}</div>
                </div>
                <div style={{textAlign:'right'}}>
                  <div className="ff-tnum" style={{fontWeight:500}}><Money value={e.amount}/></div>
                  <StatusBadge status={e.status}/>
                </div>
              </div>
            ))}
          </div>
        </div>
      </div>
      <MobileTabBar current="home" onNav={onNav}/>
    </MobileFrame>
  );
};

const MobileManagerQueue = ({ onNav = noop, onApprove = noop, onReject = noop, fullbleed = false }) => {
  const [rejecting, setRejecting] = React.useState(null);
  const [reason, setReason] = React.useState('');
  const [error, setError] = React.useState('');
  const items = FF_DATA.expenses.filter(e => ['pending','flagged'].includes(e.status)).sort((a,b)=>a.date.localeCompare(b.date));
  const beginReject = id => {setRejecting(id);setReason('');setError('');};
  const submitReject = () => {
    if (!reason.trim()) {setError('Enter a reason for this rejection.');return;}
    onReject(rejecting, reason.trim());
  };
  return <MobileFrame fullbleed={fullbleed}>
    <div style={{padding:'10px 20px 100px'}}>
      <div className="ff-row" style={{justifyContent:'space-between'}}><div><div style={{fontSize:12,color:'var(--ff-fg-muted)'}}>Manager</div><div style={{fontFamily:'var(--ff-font-sans)',fontWeight:700,fontSize:24,letterSpacing:'-0.02em'}}>Approvals</div></div><button className="ff-btn ff-btn--ghost ff-btn--icon" aria-label="Back to sign in" onClick={()=>onNav('signin')}><Icon name="sign-out" size={18}/></button></div>
      <p style={{fontSize:13,color:'var(--ff-fg-muted)',margin:'12px 0 16px'}}>{items.length} expenses awaiting your decision.</p>
      {!items.length ? <EmptyState icon="check-circle" title="You are all caught up" body="New employee expenses will appear here."/> : <div className="ff-stack" style={{'--ff-stack-gap':'10px'}}>{items.map(e=><div key={e.id} style={{padding:14,background:'var(--ff-card)',border:'1px solid var(--ff-border)',borderRadius:12}}><button onClick={()=>onNav('timeline',e.id)} style={{border:0,padding:0,background:'transparent',width:'100%',textAlign:'left',cursor:'pointer',color:'inherit'}}><div className="ff-row" style={{justifyContent:'space-between'}}><span style={{fontWeight:600}}>{e.merchant}</span><span className="ff-tnum" style={{fontWeight:700}}><Money value={e.amount}/></span></div><div style={{fontSize:11,color:'var(--ff-fg-muted)',marginTop:4}}>{e.id} · {e.who} · {e.memo}</div>{e.policy !== 'ok'&&<div style={{fontSize:11,color:'var(--ff-flagged)',marginTop:6}}>Policy flag requires review</div>}</button><div className="ff-grid ff-grid--2" style={{gap:8,marginTop:12}}><button className="ff-btn ff-btn--sm" onClick={()=>beginReject(e.id)}>Reject</button><button className="ff-btn ff-btn--primary ff-btn--sm" onClick={()=>onApprove(e.id)}>Approve</button></div></div>)}</div>}
    </div>
    {rejecting && <div className="ff-modal-backdrop" role="presentation"><div className="ff-modal" role="dialog" aria-modal="true" aria-label="Reject expense"><h3 style={{marginTop:0}}>Reject expense</h3><p style={{fontSize:13,color:'var(--ff-fg-muted)'}}>The submitter will receive this reason.</p><div className="ff-row" style={{gap:6,flexWrap:'wrap',marginBottom:10}}>{['Outside policy','Missing receipt','Needs more detail'].map(value=><button key={value} className="ff-btn ff-btn--sm" onClick={()=>{setReason(value);setError('');}}>{value}</button>)}</div><textarea aria-label="Rejection reason" className="ff-textarea" value={reason} onChange={e=>setReason(e.target.value)} onBlur={()=>!reason.trim()&&setError('Enter a reason for this rejection.')} placeholder="Add a reason"/>{error&&<FieldError error={error}/>}<div className="ff-row" style={{justifyContent:'flex-end',gap:8,marginTop:16}}><button className="ff-btn" onClick={()=>setRejecting(null)}>Cancel</button><button className="ff-btn ff-btn--danger" onClick={submitReject}>Reject expense</button></div></div></div>}
    <MobileTabBar current="home" onNav={onNav} role="manager"/>
  </MobileFrame>;
};

const MobileTabBar = ({ current, onNav = noop, role = 'employee' }) => (
  <div style={{
    position:'absolute', bottom:0, left:0, right:0,
    height:72, paddingBottom:'calc(16px + env(safe-area-inset-bottom))',
    display:'flex', alignItems:'center', justifyContent:'space-around',
    background:'var(--ff-card)', borderTop:'1px solid var(--ff-border)'
  }}>
    {(role === 'manager' ? [
      {id:"home", icon:"check-circle", label:"Approvals"},
      {id:"profile", icon:"user", label:"Profile"}
    ] : [
      {id:"home", icon:"house", label:"Home"},
      {id:"expenses", icon:"receipt", label:"Expenses"},
      {id:"snap", icon:"camera", label:""},
      {id:"cards", icon:"credit-card", label:"Card"},
      {id:"profile", icon:"user", label:"Profile"}
    ]).map(t => (
      t.id === "snap" ? (
        <button key={t.id} onClick={() => onNav('snap')} aria-label="Snap receipt" style={{width:54, height:54, borderRadius:999, background:'var(--ff-primary)', color:'var(--ff-primary-fg)', display:'grid', placeItems:'center', marginTop:-10, boxShadow:'var(--ff-shadow-md)', border:0, cursor:'pointer'}}>
          <Icon name={t.icon} size={22} weight="bold"/>
        </button>
      ) : (
        <a key={t.id} href="#" onClick={(e) => { e.preventDefault(); onNav(t.id); }} style={{display:'flex', flexDirection:'column', alignItems:'center', gap:2, color: current === t.id ? 'var(--ff-primary)' : 'var(--ff-fg-muted)'}}>
          <Icon name={t.icon} size={20}/>
          <span style={{fontSize:10, fontWeight:500}}>{t.label}</span>
        </a>
      )
    ))}
  </div>
);

const MobileSnapReceipt = ({ onNav = noop, fullbleed = false }) => {
  const [flash, setFlash] = React.useState('auto');
  return <MobileFrame theme="dark" scrollable={false} fullbleed={fullbleed}>
    <div style={{height:'100%', background:'#0c0e10', position:'relative', overflow:'hidden', color:'#fff'}}>
      {/* Camera preview */}
      <div style={{position:'absolute', inset:0, background:'radial-gradient(circle at 50% 60%, oklch(0.30 0.02 30), #0c0e10 70%)'}}/>
      {/* Rule-of-thirds guide */}
      <div style={{position:'absolute', inset:0, opacity:0.12}}>
        <div style={{position:'absolute', left:'33.3%', top:0, bottom:0, width:1, background:'#fff'}}/>
        <div style={{position:'absolute', left:'66.6%', top:0, bottom:0, width:1, background:'#fff'}}/>
        <div style={{position:'absolute', top:'33.3%', left:0, right:0, height:1, background:'#fff'}}/>
        <div style={{position:'absolute', top:'66.6%', left:0, right:0, height:1, background:'#fff'}}/>
      </div>
      {/* Receipt preview */}
      <div style={{position:'absolute', top:'18%', left:'14%', right:'14%', bottom:'22%', background:'#fff', borderRadius:8, overflow:'hidden', transform:'rotate(-2deg)', boxShadow:'0 18px 40px rgba(0,0,0,0.5)'}}>
        <img src="assets/starbucks-market-st.jpg" alt="Starbucks Market St receipt" style={{width:'100%', height:'100%', objectFit:'contain'}}/>
      </div>
      {/* Capture frame corners */}
      <CaptureCorners/>
      {/* Top instruction */}
      <div style={{position:'absolute', top:14, left:0, right:0, textAlign:'center', fontSize:13, opacity:0.85}}>
        Hold steady — align receipt in frame
      </div>
      {/* Live detection status */}
      <div style={{position:'absolute', top:46, left:0, right:0, display:'flex', justifyContent:'center'}}>
        <span className="ff-badge ff-badge--on-dark">
          <span className="ff-badge__icon"><Icon name="check-circle" size={12} weight="fill"/></span>Document detected
        </span>
      </div>
      {/* Flash mode label */}
      <div style={{position:'absolute', bottom:88, right:32, fontSize:10, opacity:0.6, textAlign:'center'}}>{flash[0].toUpperCase()+flash.slice(1)}</div>
      {/* Bottom controls */}
      <div style={{position:'absolute', bottom:'calc(30px + env(safe-area-inset-bottom))', left:0, right:0, display:'flex', alignItems:'center', justifyContent:'space-around', padding:'0 32px'}}>
        <button onClick={() => onNav('new',{source:'library'})} aria-label="Choose from photo library" style={{background:'rgba(255,255,255,0.1)', color:'#fff', width:48, height:48, borderRadius:999, border:'1px solid rgba(255,255,255,0.18)'}}><Icon name="image-square" size={20}/></button>
        <button onClick={() => onNav('new')} aria-label="Take photo" style={{background:'#fff', width:72, height:72, borderRadius:999, border:'4px solid rgba(255,255,255,0.3)'}}/>
        <button onClick={() => setFlash(value=>value==='auto'?'on':value==='on'?'off':'auto')} aria-label={`Flash mode: ${flash}`} style={{background:'rgba(255,255,255,0.1)', color:'#fff', width:48, height:48, borderRadius:999, border:'1px solid rgba(255,255,255,0.18)'}}><Icon name="lightning" size={20}/></button>
      </div>
      <div style={{position:'absolute', top:'calc(14px + env(safe-area-inset-top))', left:14}}>
        <button aria-label="Close camera" onClick={() => onNav('back')} style={{background:'rgba(255,255,255,0.1)', color:'#fff', width:44, height:44, borderRadius:999, border:'1px solid rgba(255,255,255,0.18)'}}><Icon name="x" size={16}/></button>
      </div>
    </div>
  </MobileFrame>
  ;
};

const CaptureCorners = () => {
  const corner = {
    position:'absolute', width:32, height:32,
    borderColor:'var(--ff-blue-500)', borderStyle:'solid', borderWidth:0
  };
  return (
    <>
      <div style={{...corner, top:'14%', left:'10%', borderTopWidth:3, borderLeftWidth:3, borderTopLeftRadius:6}}/>
      <div style={{...corner, top:'14%', right:'10%', borderTopWidth:3, borderRightWidth:3, borderTopRightRadius:6}}/>
      <div style={{...corner, bottom:'18%', left:'10%', borderBottomWidth:3, borderLeftWidth:3, borderBottomLeftRadius:6}}/>
      <div style={{...corner, bottom:'18%', right:'10%', borderBottomWidth:3, borderRightWidth:3, borderBottomRightRadius:6}}/>
    </>
  );
};

const MobileNewExpense = ({ onNav = noop, onSubmit = noop, onSaveDraft = noop, fullbleed = false }) => {
  const [form, setForm] = React.useState({merchant:'Starbucks',amount:'42.80',date:'2026-05-21',cat:'me',memo:'Q2 review with marketing team'});
  const [errors, setErrors] = React.useState({});
  const change = (key, value) => {setForm(current=>({...current,[key]:value})); if (errors[key]) setErrors(current=>({...current,[key]:''}));};
  const submit = () => {
    const next = {};
    if (!form.merchant.trim()) next.merchant='Enter a merchant.';
    if (ffAmountError(form.amount)) next.amount=ffAmountError(form.amount);
    const parsedDate = new Date(`${form.date}T00:00:00`);
    if (!/^\d{4}-\d{2}-\d{2}$/.test(form.date) || Number.isNaN(parsedDate.valueOf()) || parsedDate.toISOString().slice(0,10) !== form.date) next.date='Enter a valid date (YYYY-MM-DD).';
    if (!form.cat) next.cat='Choose a category.';
    setErrors(next);
    if (!Object.keys(next).length) onSubmit(form);
  };
  return (
  <MobileFrame fullbleed={fullbleed}>
    <div style={{padding:'10px 20px 100px'}}>
      <div className="ff-row" style={{justifyContent:'space-between'}}>
        <button className="ff-btn ff-btn--ghost ff-btn--icon" onClick={() => onNav('back')} aria-label="Close, discard new expense"><Icon name="x" size={18}/></button>
        <div style={{fontWeight:600, fontSize:15}}>New expense</div>
        <button className="ff-btn ff-btn--ghost" style={{color:'var(--ff-fg-muted)'}} onClick={() => onSaveDraft(form)}>Save draft</button>
      </div>
      <div style={{marginTop:20, padding:14, borderRadius:10, background:'var(--ff-card-2)', border:'1px solid var(--ff-border)', display:'flex', gap:12, alignItems:'center'}}>
        <div style={{width:54, height:68, background:'var(--ff-card)', border:'1px solid var(--ff-border)', borderRadius:6, background:`repeating-linear-gradient(0deg, var(--ff-border) 0 1px, transparent 1px 8px), var(--ff-card)`}}/>
        <div style={{flex:1}}>
          <div style={{fontWeight:600, fontSize:13}}>Receipt attached</div>
          <div style={{fontSize:11, color:'var(--ff-fg-muted)'}}>bluebottle_42.80.jpg · OCR 96%</div>
        </div>
        <button className="ff-btn ff-btn--ghost ff-btn--sm" onClick={() => onNav('snap')}>Replace</button>
      </div>
      <FormSummary errors={errors} title="Check your expense"/>
      <div className="ff-stack" style={{'--ff-stack-gap':'14px', marginTop:20}}>
        <div className="ff-field"><label className="ff-label">Merchant <span aria-hidden="true">*</span></label><input aria-label="Merchant" className="ff-input ff-input--lg" value={form.merchant} onChange={e=>change('merchant',e.target.value)} onBlur={()=>!form.merchant.trim()&&setErrors(current=>({...current,merchant:'Enter a merchant.'}))}/><FieldError error={errors.merchant}/></div>
        <div className="ff-field"><label className="ff-label">Amount <span aria-hidden="true">*</span></label><input aria-label="Amount" inputMode="decimal" className="ff-input ff-input--lg ff-tnum" value={form.amount} onChange={e=>change('amount',e.target.value)} onBlur={()=>{const error=ffAmountError(form.amount);setErrors(current=>({...current,amount:error}));}} style={{fontFamily:'var(--ff-font-sans)', fontWeight:600, fontSize:20, letterSpacing:'-0.02em', height:54}}/><FieldError error={errors.amount}/></div>
        <div className="ff-grid ff-grid--2">
          <div className="ff-field"><label className="ff-label">Date <span aria-hidden="true">*</span></label><input aria-label="Date" className="ff-input ff-input--lg ff-tnum" value={form.date} onChange={e=>change('date',e.target.value)} placeholder="YYYY-MM-DD"/><FieldError error={errors.date}/></div>
          <div className="ff-field"><label className="ff-label">Category <span aria-hidden="true">*</span></label><select aria-label="Category" className="ff-select ff-input--lg" value={form.cat} onChange={e=>change('cat',e.target.value)}><option value="me">Meals</option><option value="tr">Travel</option><option value="sw">Software</option></select><FieldError error={errors.cat}/></div>
        </div>
        <div className="ff-field"><label className="ff-label">Memo</label><textarea aria-label="Memo" className="ff-textarea" value={form.memo} onChange={e=>change('memo',e.target.value)}/></div>
        <div className="ff-field"><label className="ff-label">Payment</label>
          <div style={{padding:14, border:'1px solid var(--ff-border)', borderRadius:10, display:'flex', gap:12, alignItems:'center'}}>
            <div style={{width:34, height:22, borderRadius:3, background:'var(--ff-blue-700)'}}/>
            <div style={{flex:1, fontSize:13}}><div style={{fontWeight:500}}>FinFlow card</div><div className="ff-mono" style={{fontSize:11, color:'var(--ff-fg-muted)'}}>•••• 9032</div></div>
            <Icon name="check-circle" size={18} weight="fill" style={{color:'var(--ff-approved)'}}/>
          </div>
        </div>
      </div>
    </div>
    <div style={{position:'absolute', bottom:0, left:0, right:0, padding:'14px 20px calc(28px + env(safe-area-inset-bottom))', background:'var(--ff-card)', borderTop:'1px solid var(--ff-border)'}}>
      <button className="ff-btn ff-btn--primary ff-btn--lg" style={{width:'100%'}} onClick={submit}>Submit for approval</button>
    </div>
  </MobileFrame>
  );
};

const MobileSubmitSuccess = ({ onNav = noop, expense = JUST_SUBMITTED_EXPENSE, fullbleed = false }) => (
  <MobileFrame fullbleed={fullbleed}>
    <div style={{height:'100%', padding:'32px 24px', display:'flex', flexDirection:'column', alignItems:'center', textAlign:'center', justifyContent:'center', gap:14}}>
      <div style={{width:80, height:80, borderRadius:999, background:'var(--ff-approved-bg)', color:'var(--ff-approved)', display:'grid', placeItems:'center'}}>
        <Icon name="check-circle" size={40} weight="fill"/>
      </div>
      <div style={{fontFamily:'var(--ff-font-sans)', fontWeight:700, fontSize:30, lineHeight:1.1, letterSpacing:'-0.025em', marginTop:8}}>Submitted.</div>
      <p style={{color:'var(--ff-fg-muted)', fontSize:14, maxWidth:280}}>{expense.id} · {expense.merchant} · <strong className="ff-tnum"><Money value={expense.amount}/></strong> · Sent to Taylor for approval.</p>
      <div style={{padding:'14px 16px', background:'var(--ff-card-2)', border:'1px solid var(--ff-border)', borderRadius:10, width:'100%', marginTop:16, textAlign:'left'}}>
        <div className="ff-eyebrow" style={{marginBottom:8}}>What's next</div>
        <ul style={{margin:0, paddingLeft:18, fontSize:13, color:'var(--ff-fg-muted)', lineHeight:1.7}}>
          <li>Taylor Brooks (Manager) reviews</li>
          <li>You'll be notified within ~6h</li>
          <li>Charge already on your card</li>
        </ul>
      </div>
      <div style={{flex:1}}/>
      <button className="ff-btn ff-btn--primary ff-btn--lg" style={{width:'100%'}} onClick={() => onNav('timeline', expense.id)}>Track status</button>
      <button className="ff-btn ff-btn--ghost" style={{width:'100%'}} onClick={() => onNav('home')}>Back to home</button>
    </div>
  </MobileFrame>
);

const MobileDecisionConfirmation = ({ onNav = noop, decision, fullbleed = false }) => {
  if (!decision?.expense) return <EmptyState icon="check-circle" title="No decision recorded yet" body="Choose an expense from the manager queue to see its confirmation." actions={<button className="ff-btn" onClick={()=>onNav('home')}>Back to approvals</button>}/>;
  const { expense, type, reason } = decision;
  const approved = type === 'approved';
  return (
    <MobileFrame fullbleed={fullbleed}>
      <div style={{height:'100%', padding:'32px 24px', display:'flex', flexDirection:'column', alignItems:'center', textAlign:'center', justifyContent:'center', gap:14}}>
        <div style={{width:80, height:80, borderRadius:999, background:approved?'var(--ff-approved-bg)':'var(--ff-rejected-bg)', color:approved?'var(--ff-approved)':'var(--ff-rejected)', display:'grid', placeItems:'center'}}>
          <Icon name={approved ? "check-circle" : "x-circle"} size={40} weight="fill"/>
        </div>
        <div style={{fontFamily:'var(--ff-font-sans)', fontWeight:700, fontSize:30, lineHeight:1.1, letterSpacing:'-0.025em', marginTop:8}}>{approved ? 'Approved.' : 'Rejected.'}</div>
        <p style={{color:'var(--ff-fg-muted)', fontSize:14, maxWidth:290}}>{expense.id} · {expense.merchant} · <strong className="ff-tnum"><Money value={expense.amount}/></strong> {approved ? 'approved and routed to Finance for payment.' : `rejected. The submitter was notified with: “${reason}”.`}</p>
        <div style={{flex:1}}/>
        <button className="ff-btn" style={{width:'100%'}} onClick={()=>onNav('timeline', expense.id)}>View expense</button>
        <button className="ff-btn ff-btn--primary ff-btn--lg" style={{width:'100%'}} onClick={()=>onNav('home')}>Back to approvals</button>
      </div>
    </MobileFrame>
  );
};

/* EXP-2842 doesn't exist in the seed data — it's the expense the user just
   submitted in this session (MobileSubmitSuccess), so it's synthesized here
   to match that screen's copy exactly instead of falling back to nothing. */
const JUST_SUBMITTED_EXPENSE = {
  id: "EXP-2842", merchant: "Starbucks", amount: 42.80, cat: "me",
  date: "2026-05-22", status: "pending", cardLast4: "9032", memo: "Q2 review with marketing team"
};

const MobileStatusTimeline = ({ onNav = noop, role = 'employee', fullbleed = false, expenseId = "EXP-2841" }) => {
  const [moreOpen, setMoreOpen] = React.useState(false);
  const expense = FF_DATA.expenses.find(e => e.id === expenseId)
    || JUST_SUBMITTED_EXPENSE;
  const catName = FF_DATA.categories.find(c => c.id === expense.cat)?.name || "Other";
  const expenseDate = fmtDate(expense.date);
  const timelineSteps = expense.status === "approved"
    ? [
        { icon:"paper-plane-tilt", title:"Submitted", who:"You", ts:expenseDate, done:true },
        { icon:"shield-check", title:"Policy check passed", who:"System", ts:expenseDate, done:true },
        { icon:"user", title:"Manager approved", who:FF_DATA.me.manager.name, ts:expenseDate, done:true },
        { icon:"check", title:"Approved & posted", who:"", ts:"Reimbursed", done:true }
      ]
    : expense.status === "flagged" || expense.status === "rejected"
    ? [
        { icon:"paper-plane-tilt", title:"Submitted", who:"You", ts:expenseDate, done:true },
        { icon:"warning", title: expense.status === "flagged" ? "Policy flag — over limit" : "Rejected", who:"System", ts:expenseDate, active:true },
        { icon:"user", title:"Manager review", who:"Taylor Brooks", ts:"Blocked", done:false }
      ]
    : [
        { icon:"paper-plane-tilt", title:"Submitted", who:"You", ts:"May 22 · 9:12 AM", done:true },
        { icon:"shield-check", title:"Policy check passed", who:"System", ts:"May 22 · 9:12 AM", done:true },
        { icon:"user", title:"Awaiting Taylor Brooks", who:"Manager", ts:"Now", active:true },
        { icon:"user", title:"Finance review", who:"Morgan Ellis", ts:"Next", done:false },
        { icon:"check", title:"Approved & posted", who:"", ts:"Pending finance review", done:false }
      ];
  return (
  <MobileFrame fullbleed={fullbleed}>
    <div style={{padding:'10px 20px 100px'}}>
      <div className="ff-row" style={{justifyContent:'space-between'}}>
        <button className="ff-btn ff-btn--ghost ff-btn--icon" onClick={() => onNav('back')} aria-label="Back"><Icon name="arrow-left" size={18}/></button>
        <div style={{fontWeight:600, fontSize:15}}>{expense.id}</div>
        <button className="ff-btn ff-btn--ghost ff-btn--icon" onClick={() => setMoreOpen(open=>!open)} aria-expanded={moreOpen} aria-label={`More actions for ${expense.id}`}><Icon name="dots-three" size={18}/></button>
      </div>
      {moreOpen && <div style={{marginTop:8,padding:10,border:'1px solid var(--ff-border)',borderRadius:10,background:'var(--ff-card)'}}><button className="ff-btn" style={{width:'100%'}} onClick={()=>onNav(role==='manager'?'home':'expenses')}>{role==='manager'?'Back to approvals':'View in my expenses'}</button></div>}

      <div style={{padding:16, marginTop:14, borderRadius:12, background:'var(--ff-card)', border:'1px solid var(--ff-border)'}}>
        <div className="ff-row" style={{justifyContent:'space-between', alignItems:'flex-start'}}>
          <div>
            <div style={{fontSize:11, color:'var(--ff-fg-muted)', textTransform:'uppercase', letterSpacing:'0.08em'}}>{catName}</div>
            <div className="ff-row" style={{gap:6, fontWeight:600, fontSize:16, marginTop:4}}><MerchantIcon name={expense.merchant} size={15}/> {expense.merchant}</div>
          </div>
          <StatusBadge status={expense.status}/>
        </div>
        <div style={{fontFamily:'var(--ff-font-sans)', fontWeight:700, fontSize:30, lineHeight:1.0, letterSpacing:'-0.025em', marginTop:14}} className="ff-tnum"><Money value={expense.amount}/></div>
        <div style={{fontSize:12, color:'var(--ff-fg-muted)', marginTop:2}}>{fmtDate(expense.date)} · Card •••• {expense.cardLast4}</div>
      </div>
      {expense.status === 'rejected' && expense.decisionNote && <div className="ff-alert ff-alert--error" style={{marginTop:12}}><Icon name="chat-circle-text" size={16}/><div><strong>Reason from Taylor</strong><br/>{expense.decisionNote}</div></div>}

      <div className="ff-eyebrow" style={{marginTop:24, marginBottom:12}}>Timeline</div>
      <div style={{position:'relative', paddingLeft:30}}>
        <div style={{position:'absolute', left:14, top:8, bottom:8, width:1, background:'var(--ff-border)'}}/>
        {timelineSteps.map((s, i) => (
          <div key={i} style={{position:'relative', display:'flex', marginBottom:18, opacity: s.done || s.active ? 1 : 0.5}}>
            <div style={{
              position:'absolute', left:-30, top:0, width:30, height:30, borderRadius:999,
              background: s.done ? 'var(--ff-approved-bg)' : s.active ? 'var(--ff-pending-bg)' : 'var(--ff-card-2)',
              color: s.done ? 'var(--ff-approved)' : s.active ? 'var(--ff-pending)' : 'var(--ff-fg-subtle)',
              display:'grid', placeItems:'center',
              border:'2px solid var(--ff-bg)'
            }}>
              <Icon name={s.done ? "check" : s.icon} size={13}/>
            </div>
            <div style={{flex:1}}>
              <div style={{fontWeight:500, fontSize:14}}>{s.title}</div>
              <div style={{fontSize:11, color:'var(--ff-fg-muted)'}}>{s.who ? `${s.who} · ${s.ts}` : s.ts}</div>
            </div>
          </div>
        ))}
      </div>
    </div>
  </MobileFrame>
  );
};

const MobileExpenses = ({ onNav = noop, fullbleed = false }) => {
  const [filter, setFilter] = React.useState("all");
  const mine = FF_DATA.expenses.filter(e => e.who === "Casey Parker");
  const filtered = filter === "all" ? mine : mine.filter(e => e.status === filter);
  const filters = [
    { id: "all", label: "All" },
    { id: "pending", label: "Pending" },
    { id: "approved", label: "Approved" },
    { id: "flagged", label: "Flagged" }
  ];
  return (
    <MobileFrame fullbleed={fullbleed}>
      <div style={{padding:'10px 20px 100px'}}>
        <div style={{fontFamily:'var(--ff-font-sans)', fontWeight:700, fontSize:24, letterSpacing:'-0.02em'}}>My expenses</div>

        <div style={{marginTop:16}}>
          <ChipBar items={filters} value={filter} onChange={setFilter}/>
        </div>

        <div className="ff-stack" style={{'--ff-stack-gap':'8px', marginTop:16}}>
          {filtered.length === 0 ? (
            <div style={{textAlign:'center', padding:'40px 20px', color:'var(--ff-fg-muted)', fontSize:13}}>
              No {filter === 'all' ? '' : filter} expenses.
            </div>
          ) : filtered.map(e => (
            <div key={e.id} onClick={() => onNav('timeline', e.id)} style={{padding:'12px 14px', background:'var(--ff-card)', border:'1px solid var(--ff-border)', borderRadius:10, display:'flex', gap:12, alignItems:'center', cursor:'pointer'}}>
              <div style={{width:36, height:36, borderRadius:8, background:'var(--ff-card-2)', display:'grid', placeItems:'center', flexShrink:0}}>
                {MERCHANT_ICON_MAP[e.merchant] ? <BrandIcon name={MERCHANT_ICON_MAP[e.merchant]} size={18}/> : <Icon name={e.cat === 'me' ? 'coffee' : e.cat === 'sw' ? 'app-window' : e.cat === 'ad' ? 'megaphone' : 'tag'} size={16}/>}
              </div>
              <div style={{flex:1, minWidth:0}}>
                <div style={{fontWeight:500, fontSize:14}}>{e.merchant}</div>
                <div style={{fontSize:11, color:'var(--ff-fg-muted)'}}>{fmtDate(e.date)} · {e.id}</div>
              </div>
              <div style={{textAlign:'right'}}>
                <div className="ff-tnum" style={{fontWeight:500}}><Money value={e.amount}/></div>
                <StatusBadge status={e.status}/>
              </div>
            </div>
          ))}
        </div>
      </div>
      <MobileTabBar current="expenses" onNav={onNav}/>
    </MobileFrame>
  );
};

const MobileCards = ({ onNav = noop, fullbleed = false }) => {
  const [frozen, setFrozen] = React.useState(false);
  const [notice, setNotice] = React.useState('');
  const card = FF_DATA.cards.find(c => c.holder === "Casey Parker") || FF_DATA.cards.find(c => c.last4 === "9032");
  const pct = Math.round((card.spent / card.limit) * 100);
  const recent = FF_DATA.expenses.filter(e => e.who === "Casey Parker" && e.cardLast4 === card.last4).slice(0, 4);
  return (
    <MobileFrame fullbleed={fullbleed}>
      <div style={{padding:'10px 20px 100px'}}>
        <div style={{fontFamily:'var(--ff-font-sans)', fontWeight:700, fontSize:24, letterSpacing:'-0.02em'}}>My card</div>

        <div style={{marginTop:18, padding:20, borderRadius:16, background: frozen ? 'var(--ff-card-2)' : 'linear-gradient(135deg, var(--ff-blue-700), var(--ff-blue-900))', color: frozen ? 'var(--ff-fg)' : '#fff', position:'relative', opacity: frozen ? 0.6 : 1, transition:'all 200ms'}}>
          <div className="ff-row" style={{justifyContent:'space-between', alignItems:'flex-start'}}>
            <div style={{fontSize:11, opacity:0.7, textTransform:'uppercase', letterSpacing:'0.1em'}}>Virtual · FinFlow</div>
            <BrandMark variant="mark" size={22} theme="dark"/>
          </div>
          <div className="ff-tnum" style={{fontFamily:'var(--ff-font-mono)', fontSize:19, letterSpacing:'0.08em', marginTop:28}}>•••• •••• •••• {card.last4}</div>
          <div className="ff-row" style={{justifyContent:'space-between', marginTop:18}}>
            <div>
              <div style={{fontSize:10, opacity:0.65}}>CARDHOLDER</div>
              <div style={{fontSize:13, fontWeight:500, marginTop:2}}>Casey Parker</div>
            </div>
            {frozen && (
              <span style={{display:'flex', alignItems:'center', gap:4, fontSize:11, fontWeight:600}}>
                <Icon name="snowflake" size={14}/> Frozen
              </span>
            )}
          </div>
        </div>

        <button className="ff-btn ff-btn--lg" style={{width:'100%', marginTop:14}} onClick={() => setFrozen(f => {const next=!f;setNotice(next?'Card frozen. New transactions are blocked.':'Card unfrozen.');return next;})}>
          <Icon name={frozen ? "play" : "snowflake"} size={18}/> {frozen ? "Unfreeze card" : "Freeze card"}
        </button>
        <ActionFeedback message={notice}/>

        <div style={{marginTop:20, padding:16, borderRadius:12, background:'var(--ff-card)', border:'1px solid var(--ff-border)'}}>
          <div className="ff-row" style={{justifyContent:'space-between', marginBottom:10}}>
            <div className="ff-eyebrow">Spend this month</div>
            <span style={{fontSize:12, fontWeight:500}} className="ff-tnum">{pct}%</span>
          </div>
          <div style={{height:6, borderRadius:999, background:'var(--ff-card-2)', overflow:'hidden'}}>
            <div style={{height:'100%', width:`${Math.min(pct,100)}%`, background: pct > 90 ? 'var(--ff-flagged)' : 'var(--ff-primary)', borderRadius:999}}/>
          </div>
          <div className="ff-row" style={{justifyContent:'space-between', marginTop:8}}>
            <span className="ff-tnum" style={{fontSize:13, fontWeight:600}}><Money value={card.spent}/> spent</span>
            <span className="ff-tnum" style={{fontSize:12, color:'var(--ff-fg-muted)'}}>of <Money value={card.limit}/> limit</span>
          </div>
        </div>

        <div style={{marginTop:20}}>
          <div className="ff-eyebrow" style={{marginBottom:10}}>Recent on this card</div>
          <div className="ff-stack" style={{'--ff-stack-gap':'8px'}}>
            {recent.map(e => (
              <div key={e.id} onClick={() => onNav('timeline', e.id)} style={{padding:'12px 14px', background:'var(--ff-card)', border:'1px solid var(--ff-border)', borderRadius:10, display:'flex', gap:12, alignItems:'center', cursor:'pointer'}}>
                <div style={{flex:1, minWidth:0}}>
                  <div className="ff-row" style={{gap:6, fontWeight:500, fontSize:14}}><MerchantIcon name={e.merchant} size={14}/> {e.merchant}</div>
                  <div style={{fontSize:11, color:'var(--ff-fg-muted)'}}>{fmtDate(e.date)}</div>
                </div>
                <div className="ff-tnum" style={{fontWeight:500}}><Money value={e.amount}/></div>
              </div>
            ))}
          </div>
        </div>
      </div>
      <MobileTabBar current="cards" onNav={onNav}/>
    </MobileFrame>
  );
};

const MobileProfile = ({ onNav = noop, role = 'employee', onRole = noop, allowRoleChange = true, fullbleed = false }) => (
  <MobileFrame fullbleed={fullbleed}>
    <div style={{padding:'10px 20px 100px'}}>
      <div className="ff-row" style={{justifyContent:'space-between'}}><div style={{fontFamily:'var(--ff-font-sans)',fontWeight:700,fontSize:24,letterSpacing:'-0.02em'}}>Profile</div><button className="ff-btn ff-btn--ghost ff-btn--icon" aria-label="Back" onClick={()=>onNav('back')}><Icon name="arrow-left" size={18}/></button></div>
      <div style={{marginTop:20,padding:16,border:'1px solid var(--ff-border)',borderRadius:12,display:'flex',gap:12,alignItems:'center'}}><Avatar initials={role==='manager'?'TB':'CP'} name={role==='manager'?'Taylor Brooks':'Casey Parker'} size="lg"/><div><div style={{fontWeight:600}}>{role==='manager'?'Taylor Brooks':'Casey Parker'}</div><div style={{fontSize:12,color:'var(--ff-fg-muted)'}}>{role==='manager'?'Manager':'Employee'}</div></div></div>
      {allowRoleChange && <div style={{marginTop:22}}><div className="ff-eyebrow" style={{marginBottom:8}}>Demo role</div><div className="ff-segmented" role="group" aria-label="Mobile role"><button aria-pressed={role==='employee'} onClick={()=>{onRole('employee');onNav('home');}}>Employee</button><button aria-pressed={role==='manager'} onClick={()=>{onRole('manager');onNav('home');}}>Manager</button></div></div>}
      <button className="ff-btn" style={{width:'100%',marginTop:24}} onClick={()=>onNav('signin')}><Icon name="sign-out" size={16}/> Sign out</button>
    </div>
    <MobileTabBar current="profile" onNav={onNav} role={role}/>
  </MobileFrame>
);

const MobileFlow = ({ fullbleed = false, initialRole = 'employee', lockRole = false }) => {
  const [screen, setScreen] = React.useState('signin');
  const [role, setRole] = React.useState(initialRole === 'manager' ? 'manager' : 'employee');
  const [expenseId, setExpenseId] = React.useState('EXP-2841');
  const [history, setHistory] = React.useState([]);
  const [notice, setNotice] = React.useState('');
  const [decision, setDecision] = React.useState(null);
  const nav = (next, payload) => {
    if (next === 'back') {
      const previous = history[history.length - 1] || 'home';
      setHistory(items=>items.slice(0,-1));
      setScreen(previous);
      return;
    }
    if (next === 'timeline' && payload) setExpenseId(payload);
    if (next !== screen && next !== 'signin') setHistory(items=>[...items,screen]);
    if (next === 'signin') setHistory([]);
    setScreen(next);
  };
  const submitExpense = form => {
    const id = 'EXP-' + (Math.max(2841,...FF_DATA.expenses.map(expense=>Number(expense.id.split('-')[1])))+1);
    FF_DATA.expenses.unshift({id,merchant:form.merchant.trim(),date:form.date,amount:Number(form.amount),cat:form.cat,memo:form.memo.trim()||'No memo',who:'Casey Parker',status:'pending',policy:'ok',cardLast4:'9032',project:'General'});
    setExpenseId(id);
    nav('success',id);
  };
  const saveDraft = form => {
    FF_SESSION.mobileDraft = {...form};
    setNotice('Draft saved on this device.');
    nav('home');
  };
  const approve = id => {
    const expense = FF_DATA.expenses.find(item=>item.id===id);
    if (!expense || role !== 'manager') return;
    expense.status='approved';
    expense.decisionNote='Approved in mobile queue.';
    setDecision({type:'approved',expense:{...expense},actor:FF_DATA.me.manager.name});
    setExpenseId(id);
    nav('decision',id);
  };
  const reject = (id, reason) => {
    const expense = FF_DATA.expenses.find(item=>item.id===id);
    if (!expense || role !== 'manager') return;
    expense.status='rejected';
    expense.decisionNote=reason;
    setDecision({type:'rejected',expense:{...expense},reason,actor:FF_DATA.me.manager.name});
    setExpenseId(id);
    nav('decision',id);
  };
  const changeRole = next => { if (!lockRole) setRole(next); };
  const common = {onNav:nav,fullbleed};
  const expense = FF_DATA.expenses.find(item=>item.id===expenseId) || JUST_SUBMITTED_EXPENSE;
  const screens = {
    signin: <MobileSignIn {...common} role={role} onRole={changeRole} allowRoleChange={!lockRole}/>,
    home: <MobileHome {...common} role={role} onApprove={approve} onReject={reject} notice={notice}/>,
    snap: <MobileSnapReceipt {...common}/>,
    new: <MobileNewExpense {...common} onSubmit={submitExpense} onSaveDraft={saveDraft}/>,
    success: <MobileSubmitSuccess {...common} expense={expense}/>,
    decision: <MobileDecisionConfirmation {...common} decision={decision}/>,
    timeline: <MobileStatusTimeline {...common} role={role} expenseId={expenseId}/>,
    expenses: <MobileExpenses {...common}/>,
    cards: <MobileCards {...common}/>,
    profile: <MobileProfile {...common} role={role} onRole={changeRole} allowRoleChange={!lockRole}/>
  };
  return <div className="ff-mobile-transition" key={`${role}-${screen}`}>{screens[screen] || screens.home}</div>;
};

Object.assign(window, { MobileSignIn, MobileHome, MobileSnapReceipt, MobileNewExpense, MobileSubmitSuccess, MobileDecisionConfirmation, MobileStatusTimeline, MobileExpenses, MobileCards, MobileProfile, MobileFlow });
