// Jobs, Pricing, Auth, Guides pages

// Filter group — collapsible section with title.
// NOTE: pages-main.jsx defines an identical FilterGroup. Both files run in the
// same global Babel scope, and pages-other.jsx loads later — so this version
// is the one that wins at runtime. Keep both definitions in sync (or delete
// one and rely on a single shared definition exported via window).
const FilterGroup = ({ title, children, defaultOpen = true }) => {
  const [open, setOpen] = useState(defaultOpen);
  return (
    <div style={{paddingBottom:16, borderBottom:'1px solid var(--t-line)', marginBottom:16}}>
      <button onClick={() => setOpen(!open)} style={{
        display:'flex', justifyContent:'space-between', alignItems:'center', width:'100%',
        background:'none', border:'none', padding:'6px 0', cursor:'pointer',
        fontSize:14, fontWeight:600, letterSpacing:'-0.005em', color:'var(--t-ink)',
        marginBottom: open ? 12 : 0,
      }}>
        {title}
        <span style={{color:'var(--t-ink-muted)', fontSize:14, transform: open ? 'rotate(180deg)' : 'rotate(0deg)', transition:'transform 0.15s'}}>⌄</span>
      </button>
      {open && <div>{children}</div>}
    </div>
  );
};

const FilterCheckbox = ({ label, checked, onChange, count }) => (
  <label style={{display:'flex', alignItems:'center', gap:10, padding:'5px 0', cursor:'pointer', fontSize:13.5, color:'var(--t-ink)'}}>
    <input type="checkbox" checked={checked} onChange={onChange} style={{accentColor:'var(--trust)', width:15, height:15, flexShrink:0}}/>
    <span style={{flex:1}}>{label}</span>
    {count != null && <span style={{fontSize:11, color:'var(--t-ink-muted)'}}>{count}</span>}
  </label>
);

const JobsPage = ({ go, role, loggedIn }) => {
  const { t, lang } = window.useI18n();
  const taxLabel = (x) => window.pickLocalised(x, 'label', lang) || x.label;
  const { jobs } = window.MOCK_DATA;
  const tax = window.SKILL_TAXONOMY;

  const [markets, setMarkets] = useState([]);
  const [positions, setPositions] = useState([]);
  const [jobTypes, setJobTypes] = useState([]);
  // "Available after" filter: '' = no filter, otherwise YYYY-MM-DD — show
  // jobs whose start date is ON or AFTER the picked date (employer wants to
  // start later than this). Inclusive comparison for clarity.
  const [startDate, setStartDate] = useState('');
  const [languages, setLanguages] = useState([]);
  const [mainSkills, setMainSkills] = useState([]);
  const [sortBy, setSortBy] = useState('recent');

  const toggle = (arr, setArr, v) => setArr(arr.includes(v) ? arr.filter(x => x !== v) : [...arr, v]);
  const clearAll = () => { setMarkets([]); setPositions([]); setJobTypes([]); setStartDate(''); setLanguages([]); setMainSkills([]); };

  const filtered = jobs.filter(j => {
    if (markets.length && !markets.includes(j.market)) return false;
    if (positions.length && !positions.includes(j.jobType)) return false;
    if (jobTypes.length && !jobTypes.includes(j.type)) return false;
    // "Available after [picked]" — show jobs whose latest possible start
    // (j.startDate + j.flexibility window) is on or after the picked date.
    // This way a flexible job qualifies even if its preferred date is earlier.
    if (startDate && j.startDate) {
      const flexDays = (window.JOB_FLEX_DAYS && window.JOB_FLEX_DAYS[j.flexibility]) || 0;
      const latestStart = new Date(j.startDate);
      latestStart.setDate(latestStart.getDate() + flexDays);
      const picked = new Date(startDate);
      if (picked > latestStart) return false;
    }
    if (languages.length && !languages.some(l => j.reqLanguages?.includes(l))) return false;
    if (mainSkills.length && !mainSkills.some(s => j.reqMainSkills?.includes(s))) return false;
    return true;
  });

  const activeCount = markets.length + positions.length + jobTypes.length + languages.length + mainSkills.length + (startDate ? 1 : 0);
  const showPostCta = role === 'employer' || !loggedIn;
  const handlePost = () => {
    if (!loggedIn) { go('auth:login'); return; }
    go('post-job');
  };
  const [mobileFiltersOpen, setMobileFiltersOpen] = useState(false);

  return (
    <div className="page">
      <div className="container-wide" style={{padding:'32px 32px 80px'}}>
        <div style={{display:'flex', justifyContent:'space-between', alignItems:'flex-end', gap:20, marginBottom:28, flexWrap:'wrap'}}>
          <div>
            <div className="eyebrow">{t('jobs.eyebrow')}</div>
            <h1 className="display" style={{fontSize:38, marginBottom:6}}>{t('jobs.heading')}</h1>
          </div>
          <div style={{display:'flex', gap:10, alignItems:'center', flexWrap:'wrap'}}>
            <button className="btn btn-outline btn-sm jobs-mobile-filters-btn" onClick={() => setMobileFiltersOpen(true)}>
              <Icon name="filter" size={14}/> {t('jobs.filters')} {activeCount > 0 && <span style={{fontSize:11, padding:'1px 7px', borderRadius:99, background:'var(--trust)', color:'white', fontWeight:700, marginLeft:2}}>{activeCount}</span>}
            </button>
            {showPostCta && (
              <button className="btn btn-primary" onClick={handlePost}>
                <Icon name="briefcase" size={14}/> {t('jobs.postNew')}
              </button>
            )}
          </div>
        </div>

        <div className="jobs-layout" style={{display:'grid', gridTemplateColumns:'260px 1fr', gap:32, alignItems:'flex-start'}}>
          {/* ===== LEFT FILTER SIDEBAR ===== */}
          <aside className={`jobs-sidebar ${mobileFiltersOpen ? 'open' : ''}`}>
            <div className="jobs-sidebar-scrim" onClick={() => setMobileFiltersOpen(false)}/>
            <div className="jobs-sidebar-panel card-flat" style={{padding:20}}>
              <div style={{display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:16, gap:12}}>
                <div style={{fontSize:15, fontWeight:700, whiteSpace:'nowrap'}}>{t('jobs.filters')}</div>
                <div style={{display:'flex', gap:8, alignItems:'center'}}>
                  {activeCount > 0 && (
                    <button onClick={clearAll} style={{background:'none', border:'none', color:'var(--trust)', fontSize:12, fontWeight:600, cursor:'pointer', padding:0}}>
                      {t('jobs.clearN', {n: activeCount})}
                    </button>
                  )}
                  <button onClick={() => setMobileFiltersOpen(false)} className="jobs-sidebar-close" aria-label={t('jobs.closeFilters')} style={{background:'none', border:'none', padding:4, cursor:'pointer', color:'var(--t-ink-muted)'}}>
                    <Icon name="x" size={18}/>
                  </button>
                </div>
              </div>

              <FilterGroup title={t('jobs.filterGroup.location')}>
                {[
                  ['Taiwan',     t('helpers.markets.taiwan')],
                  ['Hong Kong',  t('helpers.markets.hongKong')],
                  ['Singapore',  t('helpers.markets.singapore')],
                ].map(([id, label]) => (
                  <FilterCheckbox key={id} label={label} checked={markets.includes(id)} onChange={() => toggle(markets, setMarkets, id)} count={jobs.filter(j => j.market === id).length}/>
                ))}
              </FilterGroup>

              <FilterGroup title={t('jobs.filterGroup.startDate')}>
                <div style={{fontSize:11.5, color:'var(--t-ink-muted)', marginBottom:6}}>{t('jobs.availableAfterLabel')}</div>
                <input type="date" className="input" value={startDate} onChange={e=>setStartDate(e.target.value)} placeholder={t('helpers.startDatePlaceholder')} style={{width:'100%', fontSize:13}}/>
                {startDate && (
                  <button onClick={()=>setStartDate('')} style={{marginTop:6, background:'none', border:'none', color:'var(--trust)', fontSize:11.5, fontWeight:600, cursor:'pointer', padding:0}}>{t('common.clear')}</button>
                )}
              </FilterGroup>

              <FilterGroup title={t('jobs.filterGroup.position')}>
                {['Domestic Helper','Nanny','Caregiver','Cook','Driver'].map(p => (
                  <FilterCheckbox key={p} label={t('forms.enum.position.' + p)} checked={positions.includes(p)} onChange={() => toggle(positions, setPositions, p)} count={jobs.filter(j => j.jobType === p).length}/>
                ))}
              </FilterGroup>

              <FilterGroup title={t('jobs.filterGroup.jobType')}>
                {['full-time','part-time','temporary'].map(typ => (
                  <FilterCheckbox key={typ} label={t('forms.enum.jobType.' + typ)} checked={jobTypes.includes(typ)} onChange={() => toggle(jobTypes, setJobTypes, typ)} count={jobs.filter(j => j.type === typ).length}/>
                ))}
              </FilterGroup>

              <FilterGroup title={t('jobs.filterGroup.language')} defaultOpen={false}>
                {tax.languages.map(l => (
                  <FilterCheckbox key={l.id} label={<span>{l.flag} {taxLabel(l)}</span>} checked={languages.includes(l.id)} onChange={() => toggle(languages, setLanguages, l.id)}/>
                ))}
              </FilterGroup>

              <FilterGroup title={t('jobs.filterGroup.mainSkills')} defaultOpen={false}>
                {tax.mainSkills.filter(s => s.label !== 'Marketing').map(s => (
                  <FilterCheckbox key={s.id} label={taxLabel(s)} checked={mainSkills.includes(s.id)} onChange={() => toggle(mainSkills, setMainSkills, s.id)}/>
                ))}
              </FilterGroup>

              <div style={{paddingBottom:0, marginBottom:0}}>
                {/* last group has no border */}
              </div>

              <div className="jobs-sidebar-actions">
                <button className="btn btn-outline btn-block" onClick={clearAll} disabled={activeCount === 0}>{t('jobs.clearAll')}</button>
                <button className="btn btn-trust btn-block" onClick={() => setMobileFiltersOpen(false)}>{t('jobs.showN', {n: filtered.length})}</button>
              </div>
            </div>
          </aside>

          {/* ===== JOB RESULTS ===== */}
          <div>
            <div style={{display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:18, flexWrap:'wrap', gap:12}}>
              <div style={{fontSize:14, color:'var(--t-ink-muted)'}}>
                <strong style={{color:'var(--t-ink)'}}>{filtered.length}</strong>{' '}
                {filtered.length === 1 ? t('jobs.countOne') : t('jobs.countMany')}
                {activeCount > 0 && ' ' + t('jobs.matchingFilters')}
              </div>
              <div style={{display:'flex', alignItems:'center', gap:8, fontSize:13}}>
                <span style={{color:'var(--t-ink-muted)'}}>{t('jobs.sortBy')}</span>
                <select className="select" value={sortBy} onChange={e => setSortBy(e.target.value)} style={{padding:'6px 28px 6px 12px', fontSize:13, width:'auto'}}>
                  <option value="recent">{t('jobs.sortMostRecent')}</option>
                  <option value="salary">{t('jobs.sortHighestSalary')}</option>
                  <option value="applicants">{t('jobs.sortFewestApplicants')}</option>
                </select>
              </div>
            </div>

            {filtered.length === 0 ? (
              <div className="card-flat" style={{padding:60, textAlign:'center'}}>
                <div style={{fontSize:42, marginBottom:12, opacity:0.5}}>🔍</div>
                <div style={{fontSize:17, fontWeight:600, marginBottom:6}}>{t('jobs.emptyTitle')}</div>
                <div style={{color:'var(--t-ink-muted)', fontSize:14, marginBottom:20}}>{t('jobs.emptyBody')}</div>
                <button className="btn btn-outline" onClick={clearAll}>{t('jobs.emptyCta')}</button>
              </div>
            ) : (
              <div style={{display:'grid', gridTemplateColumns:'1fr 1fr', gap:18}}>
                {filtered.map(j => <JobCard key={j.id} job={j} go={go}/>)}
              </div>
            )}
          </div>
        </div>
      </div>
    </div>
  );
};

// ===== Job Requirements Group =====
// Mirrors SkillsGroup on the single helper page so candidate / employer detail
// pages render identically. Section header: 40×40 disc + 24px line-art icon.
// Chips: outline pill + 26px disc with FlatIcon (or flag emoji for languages).
const REQ_HEADER_ICON = {
  language: 'cat-language',
  main:     'cat-main',
  cooking:  'cat-cooking',
  other:    'cat-other',
  personality: 'cat-personality',
};
const ReqGroup = ({ title, items, required, category = 'main', headerIconKey }) => {
  if (!items || items.length === 0) return null;
  const { t, lang } = window.useI18n();
  const c = window.SKILL_CAT_COLORS[category] || window.SKILL_CAT_COLORS.main;
  const itemLabel = (x) => window.pickLocalised(x, 'label', lang) || x.label || x;
  const iconKey = headerIconKey || REQ_HEADER_ICON[category];
  return (
    <div>
      <div style={{display:'flex', alignItems:'center', gap:11, marginBottom:14}}>
        {iconKey && (
          <span style={{display:'grid', placeItems:'center', width:40, height:40, borderRadius:10, background:c.bg, color:c.fg, flexShrink:0}}>
            <window.SkillIcon name={iconKey} size={24}/>
          </span>
        )}
        <h4 className="display" style={{fontSize:15, fontWeight:600, letterSpacing:'-0.01em', color:'var(--t-ink)', margin:0}}>{title}</h4>
        {required && <span style={{fontSize:11, color:'var(--coral-dark)', fontWeight:700, background:'var(--coral-bg)', padding:'2px 7px', borderRadius:99, letterSpacing:'0.04em'}}>{t('forms.common.required')}</span>}
      </div>
      <div style={{display:'flex', flexWrap:'wrap', gap:7}}>
        {items.map(x => {
          const flatDef = window.FLAT_ICONS && window.FLAT_ICONS[x.id];
          const discBg = flatDef && window.CAT_BG ? (window.CAT_BG[flatDef.cat] || c.bg) : c.bg;
          const isLang = category === 'language';
          return (
            <div key={x.id || x} style={{
              display:'inline-flex', alignItems:'center', gap:8,
              padding:'4px 13px 4px 4px', background:'var(--t-paper)',
              border:'1px solid var(--t-line)', borderRadius:99, fontSize:13,
            }}>
              <span style={{
                display:'grid', placeItems:'center', width:26, height:26, borderRadius:99,
                background: discBg, color: c.fg, flexShrink:0,
                fontSize: isLang ? 15 : undefined, lineHeight: 1,
              }}>
                {isLang
                  ? (x.flag || null)
                  : (flatDef
                      ? <window.FlatIcon name={x.id} size={18}/>
                      : <window.SkillIcon name={x.id} size={14}/>)}
              </span>
              <span style={{fontWeight:500, whiteSpace:'nowrap'}}>{itemLabel(x)}</span>
            </div>
          );
        })}
      </div>
    </div>
  );
};

const JobDetailPage = ({ id, go, role, loggedIn }) => {
  const { t } = window.useI18n();
  const j = window.MOCK_DATA.jobs.find(x => x.id === parseInt(id));
  if (!j) return <div className="container" style={{padding:60}}>{t('jobs.jobNotFound')}</div>;
  const tax = window.SKILL_TAXONOMY;
  const langItems = tax.languages.filter(x => j.reqLanguages?.includes(x.id));
  const mainItems = tax.mainSkills.filter(x => j.reqMainSkills?.includes(x.id));
  const cookItems = tax.cookingSkills.filter(x => j.reqCookingSkills?.includes(x.id));
  const otherItems = tax.otherSkills.filter(x => j.reqOtherSkills?.includes(x.id));

  const [showResumeGate, setShowResumeGate] = useState(false);
  // Approval gate (see CANDIDATE_REVIEW_FLOW.md). Only helpers in 'approved'
  // state can submit applications. Pending / rejected helpers see a status-
  // specific modal instead of the application confirmation.
  const [showReviewGate, setShowReviewGate] = useState(null);  // null | 'pending_review' | 'rejected'
  // Success modal — replaces the old alert(). Title + body explicitly state the
  // asymmetric messaging rule: helper can only wait for the employer to reach
  // out; helper cannot initiate a thread (see DOMAIN_MODEL.md §4.13 + §4.15).
  const [showApplied, setShowApplied] = useState(false);

  const handleApply = () => {
    // Employers or not-logged-in — keep simple ack modal (visitor demo)
    if (!loggedIn || role !== 'helper') { setShowApplied(true); return; }
    // Helpers — check resume completion first, then review status
    let done = false;
    try { done = localStorage.getItem('hm_resume_complete') === '1'; } catch(e) {}
    if (!done) { setShowResumeGate(true); return; }
    let status = 'approved';
    try { status = localStorage.getItem('hm_review_status') || 'approved'; } catch(e) {}
    if (status === 'pending_review' || status === 'rejected') {
      setShowReviewGate(status);
      return;
    }
    setShowApplied(true);
  };

  // Infer a start date ~ posted date + 2 weeks (mock)
  const startDate = j.startDate || t('jobs.asapStart');

  const BasicRow = ({ icon, label, value }) => (
    <div style={{display:'flex', gap:14, padding:'14px 0', borderBottom:'1px solid var(--t-line)'}}>
      <div style={{width:36, height:36, borderRadius:10, background:'var(--trust-bg)', color:'var(--trust)', display:'grid', placeItems:'center', flexShrink:0}}>
        <Icon name={icon} size={16}/>
      </div>
      <div style={{flex:1, minWidth:0}}>
        <div style={{fontSize:11, fontWeight:700, letterSpacing:'0.06em', textTransform:'uppercase', color:'var(--t-ink-muted)', marginBottom:3}}>{label}</div>
        <div style={{fontSize:15, fontWeight:500, color:'var(--t-ink)'}}>{value}</div>
      </div>
    </div>
  );

  return (
    <div className="page has-sticky-cta">
      <div className="container-wide" style={{padding:'24px 32px 80px'}}>
        <button className="btn btn-ghost btn-sm" onClick={()=>go('jobs')} style={{marginBottom:20}}><Icon name="arrowLeft" size={14}/> {t('jobs.backToList')}</button>
        <div style={{display:'grid', gridTemplateColumns:'1fr 360px', gap:40}}>
          <div>
            <div style={{display:'flex', gap:8, marginBottom:14, flexWrap:'wrap'}}>
              <span className="chip chip-coral">{j.market}</span>
              <span className="chip">{t('forms.enum.jobType.' + j.type) || j.type}</span>
              <span className="chip chip-ghost">{t('forms.enum.position.' + j.jobType) || j.jobType}</span>
            </div>
            <h1 className="display" style={{fontSize:38, marginBottom:12}}>{window.pickLocalised(j, 'title') || j.title}</h1>
            <div style={{display:'flex', gap:20, fontSize:14, color:'var(--t-ink-muted)', marginBottom:32, flexWrap:'wrap'}}>
              <span style={{display:'flex', alignItems:'center', gap:6}}><Icon name="location" size={14}/> {j.city}</span>
              <span style={{display:'flex', alignItems:'center', gap:6}}><Icon name="clock" size={14}/> {t('jobs.posted')} {j.posted}</span>
            </div>

            {/* ===== BASICS BLOCK (structured) =====
                Day off + accommodation come from the post-a-job form's
                Offer section. Skip accommodation when the employer chose
                "Dont mention" so the row isn't a placeholder. */}
            <div className="card-flat" style={{padding:'8px 28px 20px', marginBottom:32}}>
              <h3 className="display" style={{fontSize:22, margin:'18px 0 4px'}}>{t('jobs.detail.basics')}</h3>
              <div style={{display:'grid', gridTemplateColumns:'1fr 1fr', gap:'0 32px', marginTop:14}}>
                <BasicRow icon="briefcase" label={t('jobs.detail.position')} value={t('forms.enum.position.' + j.jobType) || j.jobType}/>
                <BasicRow icon="clock" label={t('jobs.detail.jobType')} value={t('forms.enum.jobType.' + j.type) || j.type}/>
                <BasicRow icon="location" label={t('jobs.detail.location')} value={`${j.city}, ${j.market}`}/>
                <BasicRow icon="calendar" label={t('jobs.detail.startDate')} value={startDate}/>
                <BasicRow icon="user" label={t('jobs.detail.household')} value={j.familySize}/>
                <BasicRow icon="sparkle" label={t('jobs.detail.salary')} value={j.salary}/>
                {j.jobDayOff && (
                  <BasicRow icon="calendar" label={t('jobs.detail.dayOff')} value={t('forms.enum.dayOff.' + j.jobDayOff) || j.jobDayOff}/>
                )}
                {j.jobAccommodation && j.jobAccommodation !== 'Dont mention' && (
                  <BasicRow icon="home" label={t('jobs.detail.accommodation')} value={t('forms.enum.jobAccommodation.' + j.jobAccommodation) || j.jobAccommodation}/>
                )}
              </div>
            </div>

            {/* ===== REQUIREMENTS ===== */}
            <div className="card-flat" style={{padding:28, marginBottom:32}}>
              <h3 className="display" style={{fontSize:22, marginBottom:6}}>{t('jobs.detail.requirements')}</h3>
              <p style={{color:'var(--t-ink-muted)', fontSize:13, marginBottom:22}}>{t('jobs.detail.requirementsSub')}</p>

              <div style={{display:'grid', gridTemplateColumns:'1fr 1fr', gap:'22px 28px'}}>
                <ReqGroup title={t('detail.skillCat.language')} items={langItems} category="language" required/>
                <ReqGroup title={t('detail.skillCat.mainSkills')} items={mainItems} category="main" required/>
                <ReqGroup title={t('detail.skillCat.cookingSkills')} items={cookItems} category="cooking"/>
                <ReqGroup title={t('detail.skillCat.otherSkills')} items={otherItems} category="other"/>
              </div>
            </div>

            {/* ===== JOB DESCRIPTION (rich-text "About" from post-a-job form) ===== */}
            {(window.pickLocalised(j, 'description') || j.description) && (
              <div className="card-flat" style={{padding:28, marginBottom:32}}>
                <h3 className="display" style={{fontSize:22, marginBottom:18}}>{t('jobs.detail.description')}</h3>
                <div
                  className="rich-content"
                  style={{fontSize:16, lineHeight:1.75, color:'var(--t-ink)'}}
                  dangerouslySetInnerHTML={{__html: window.pickLocalised(j, 'description') || j.description}}
                />
              </div>
            )}
          </div>
          <aside>
            <div style={{position:'sticky', top:96}}>
              <div className="card-flat" style={{padding:28}}>
                <div style={{marginBottom:16}}>
                  <div style={{fontSize:13, color:'var(--t-ink-muted)', marginBottom:4}}>{t('jobs.detail.salary')}</div>
                  <div className="display" style={{fontSize:32}}>{j.salary}</div>
                </div>
                <button className="btn btn-primary btn-lg btn-block" onClick={handleApply}>{t('jobs.detail.applyNow')}</button>
                <button className="btn btn-outline btn-block" style={{marginTop:10}}>{t('jobs.saveJob')}</button>
              </div>
            </div>
          </aside>
        </div>
      </div>

      {/* Sticky mobile CTA bar */}
      <div className="sticky-cta-bar">
        <button className="btn btn-outline btn-icon" aria-label={t('jobs.saveJobAria')}>
          <Icon name="heart" size={18}/>
        </button>
        <div className="cta-meta">
          <strong>{j.salary}</strong>
          <span>{(window.pickLocalised(j, 'title') || j.title) || t('jobs.mobileApplyTitle')}</span>
        </div>
        <button className="btn btn-primary" onClick={handleApply}>{t('jobs.detail.applyNow')}</button>
      </div>

      {showResumeGate && (
        <div onClick={()=>setShowResumeGate(false)} style={{position:'fixed', inset:0, background:'rgba(22,18,15,0.55)', display:'grid', placeItems:'center', zIndex:100, padding:20}}>
          <div onClick={e=>e.stopPropagation()} className="card-flat" style={{maxWidth:480, width:'100%', padding:36, background:'var(--t-paper)', borderRadius:16, boxShadow:'0 24px 60px rgba(0,0,0,0.3)'}}>
            <div style={{width:56, height:56, borderRadius:99, background:'var(--trust-bg)', color:'var(--trust)', display:'grid', placeItems:'center', marginBottom:18}}>
              <Icon name="user" size={24}/>
            </div>
            <h2 className="display" style={{fontSize:24, marginBottom:10}}>{t('jobs.detail.gateTitle')}</h2>
            <p style={{color:'var(--t-ink-soft)', fontSize:15, lineHeight:1.6, marginBottom:24}}>
              {t('jobs.detail.gateBody')}
            </p>
            <div style={{display:'flex', gap:10}}>
              <button className="btn btn-ghost" onClick={()=>setShowResumeGate(false)}>{t('jobs.detail.gateLater')}</button>
              <button className="btn btn-trust" style={{flex:1}} onClick={()=>{ setShowResumeGate(false); go('create-profile'); }}>
                {t('jobs.detail.gateContinue')} <Icon name="arrow" size={14}/>
              </button>
            </div>
          </div>
        </div>
      )}

      {/* Review-status gate modal — surfaces when an unapproved helper tries
          to apply (see CANDIDATE_REVIEW_FLOW.md). Two variants by status. */}
      {showReviewGate && (
        <div onClick={()=>setShowReviewGate(null)} style={{position:'fixed', inset:0, background:'rgba(22,18,15,0.55)', display:'grid', placeItems:'center', zIndex:100, padding:20}}>
          <div onClick={e=>e.stopPropagation()} className="card-flat" style={{maxWidth:480, width:'100%', padding:36, background:'var(--t-paper)', borderRadius:16, boxShadow:'0 24px 60px rgba(0,0,0,0.3)'}}>
            {showReviewGate === 'pending_review' ? (
              <>
                <div style={{width:56, height:56, borderRadius:99, background:'#FDECC8', color:'#7A4F00', display:'grid', placeItems:'center', marginBottom:18}}>
                  <Icon name="clock" size={24}/>
                </div>
                <h2 className="display" style={{fontSize:24, marginBottom:10}}>{t('jobs.detail.reviewGate.pendingTitle')}</h2>
                <p style={{color:'var(--t-ink-soft)', fontSize:15, lineHeight:1.6, marginBottom:24}}>
                  {t('jobs.detail.reviewGate.pendingBody')}
                </p>
                <button className="btn btn-trust btn-block" onClick={()=>setShowReviewGate(null)}>
                  {t('jobs.detail.reviewGate.gotIt')}
                </button>
              </>
            ) : (
              <>
                <div style={{width:56, height:56, borderRadius:99, background:'var(--coral-bg)', color:'var(--coral-dark)', display:'grid', placeItems:'center', marginBottom:18}}>
                  <Icon name="x" size={24}/>
                </div>
                <h2 className="display" style={{fontSize:24, marginBottom:10}}>{t('jobs.detail.reviewGate.rejectedTitle')}</h2>
                <p style={{color:'var(--t-ink-soft)', fontSize:15, lineHeight:1.6, marginBottom:24}}>
                  {t('jobs.detail.reviewGate.rejectedBody')}
                </p>
                <div style={{display:'flex', gap:10}}>
                  <button className="btn btn-ghost" onClick={()=>setShowReviewGate(null)}>{t('jobs.detail.reviewGate.later')}</button>
                  <button className="btn btn-trust" style={{flex:1}} onClick={()=>{ setShowReviewGate(null); go('create-profile'); }}>
                    {t('jobs.detail.reviewGate.editResume')} <Icon name="arrow" size={14}/>
                  </button>
                </div>
              </>
            )}
          </div>
        </div>
      )}

      {/* Apply success modal — replaces the prototype's old alert(). Body
          explicitly states the asymmetric messaging rule: helper can only
          wait for the employer to make first contact. */}
      {showApplied && (
        <div onClick={()=>setShowApplied(false)} style={{position:'fixed', inset:0, background:'rgba(22,18,15,0.55)', display:'grid', placeItems:'center', zIndex:100, padding:20}}>
          <div onClick={e=>e.stopPropagation()} className="card-flat" style={{maxWidth:480, width:'100%', padding:36, background:'var(--t-paper)', borderRadius:16, boxShadow:'0 24px 60px rgba(0,0,0,0.3)'}}>
            <div style={{width:56, height:56, borderRadius:99, background:'var(--mint-bg, #DCF5E6)', color:'var(--mint-dark, #1F8A4C)', display:'grid', placeItems:'center', marginBottom:18}}>
              <Icon name="check" size={26}/>
            </div>
            <h2 className="display" style={{fontSize:24, marginBottom:10}}>{t('jobs.detail.appliedModal.title')}</h2>
            <p style={{color:'var(--t-ink-soft)', fontSize:15, lineHeight:1.6, marginBottom:24}}>
              {t('jobs.detail.appliedModal.body')}
            </p>
            <div style={{display:'flex', gap:10}}>
              <button className="btn btn-ghost" onClick={()=>setShowApplied(false)}>{t('jobs.detail.appliedModal.dismiss')}</button>
              <button className="btn btn-trust" style={{flex:1}} onClick={()=>{ setShowApplied(false); go('jobs'); }}>
                {t('jobs.detail.appliedModal.browseMore')} <Icon name="arrow" size={14}/>
              </button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
};

const PricingPage = ({ go, setSubscription, subscription }) => {
  const { t } = window.useI18n();
  const { plans } = window.MOCK_DATA;
  return (
    <div className="page">
      <div className="container" style={{padding:'48px 32px 80px'}}>
        <div style={{textAlign:'center', marginBottom:48}}>
          <div className="eyebrow">{t('pricing.eyebrow')}</div>
          <h1 className="display" style={{fontSize:48, marginBottom:14}}>{t('pricing.title')}</h1>
          <p style={{fontSize:17, color:'var(--t-ink-muted)', maxWidth:600, margin:'0 auto'}}>
            {t('pricing.sub')}
          </p>
        </div>
        <div style={{display:'grid', gridTemplateColumns:'repeat(3,1fr)', gap:20, marginBottom:48, paddingTop:16}}>
          {plans.map(p => (
            <div key={p.id} className="card" style={{padding:32, border: p.featured ? '2px solid var(--mint)' : undefined, position:'relative', overflow:'visible'}}>
              {p.featured && <div style={{position:'absolute', top:-12, left:'50%', transform:'translateX(-50%)', background:'var(--mint)', color:'white', padding:'4px 14px', borderRadius:99, fontSize:12, fontWeight:700, letterSpacing:'0.06em'}}>{t('pricing.most')}</div>}
              <div style={{fontSize:14, color:'var(--t-ink-muted)', marginBottom:6}}>{p.name}</div>
              <div style={{display:'flex', alignItems:'baseline', gap:6, marginBottom:6}}>
                <span className="display" style={{fontSize:44}}>{p.price === 0 ? t('pricing.free') : `${p.currency}${p.price.toLocaleString()}`}</span>
              </div>
              <div style={{color:'var(--t-ink-muted)', fontSize:13, marginBottom:20}}>{t('pricing.perPeriod', {period: p.period})}</div>
              <div style={{fontSize:14, color:'var(--t-ink-soft)', marginBottom:24, lineHeight:1.6}}>{p.tagline}</div>
              <button
                className={`btn btn-block ${p.featured ? 'btn-mint' : p.id === 'free' ? 'btn-outline' : 'btn-dark'}`}
                onClick={() => { setSubscription(p.id); alert(`Switched to ${p.name} plan.`); }}
                disabled={subscription === p.id}
              >
                {subscription === p.id ? t('pricing.currentPlan') : p.cta}
              </button>
              <ul style={{listStyle:'none', display:'flex', flexDirection:'column', gap:10, marginTop:24, paddingTop:24, borderTop:'1px solid var(--t-line)'}}>
                {p.features.map((f,i) => (
                  <li key={i} style={{display:'flex', alignItems:'flex-start', gap:10, fontSize:14, color: f.yes?'var(--t-ink)':'var(--t-ink-muted)'}}>
                    {f.yes ? <Icon name="check" size={16} className="" /> : <Icon name="x" size={16}/>}
                    <span>{f.text}</span>
                  </li>
                ))}
              </ul>
            </div>
          ))}
        </div>
        <div className="card-flat" style={{padding:32, background:'var(--coral-bg)', borderColor:'var(--coral-light)'}}>
          <div style={{display:'flex', gap:16, alignItems:'flex-start'}}>
            <Icon name="sparkle" size={20} className="" />
            <div>
              <div style={{fontWeight:600, fontSize:16, marginBottom:6}}>{t('pricing.whyTitle')}</div>
              <div style={{fontSize:14, color:'var(--t-ink-soft)', lineHeight:1.6}}>
                {t('pricing.whyBody')}
              </div>
            </div>
          </div>
        </div>
        <div style={{marginTop:56}}>
          <h2 className="display" style={{fontSize:28, marginBottom:20, textAlign:'center'}}>{t('pricing.faqTitle')}</h2>
          <div style={{display:'grid', gridTemplateColumns:'1fr 1fr', gap:16, maxWidth:900, margin:'0 auto'}}>
            {[
              ['What counts as a "contact"?','Opening a new message thread with a helper you haven\'t messaged before. Continuing an existing conversation never counts.'],
              ['Does the same video count twice?','No. If you watch the same assessment video multiple times, it only counts once — across all your subscriptions.'],
              ['Does my subscription auto-renew?','Never. When your plan expires you can browse profiles for free or buy a new plan.'],
              ['What happens after my plan expires?','You keep access to message threads you\'ve already started (read-only), and can resubscribe at any time to continue.'],
            ].map(([q,a],i) => (
              <div key={i} className="card-flat" style={{padding:20}}>
                <div style={{fontWeight:600, fontSize:15, marginBottom:8}}>{q}</div>
                <div style={{fontSize:14, color:'var(--t-ink-muted)', lineHeight:1.6}}>{a}</div>
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
};

const AuthPage = ({ mode, go, login, setRole: setAppRole }) => {
  const { t } = window.useI18n();
  const [role, setRole] = useState('employer');
  const [step, setStep] = useState('form');
  const isLogin = mode === 'login';

  const submit = () => {
    // Propagate selected role to app state on signup; login keeps existing role
    if (!isLogin && setAppRole) setAppRole(role);
    if (login) login();
    // Both roles land on dashboard; helpers can complete their resume later.
    // New helper accounts enter the review pipeline at 'pending_resume' (see
    // Shared/CANDIDATE_REVIEW_FLOW.md). The status flag is read by the
    // helper dashboard banner and the JobDetail Apply gate.
    if (!isLogin && role === 'helper') {
      try {
        localStorage.setItem('hm_resume_complete', '0');
        localStorage.setItem('hm_review_status', 'pending_resume');
        window.dispatchEvent(new Event('hm-review-status-changed'));
      } catch(e) {}
    }
    go('dashboard');
  };

  return (
    <div className="page">
      <div className="auth-split" style={{display:'grid', gridTemplateColumns:'1fr 1fr', minHeight:'calc(100vh - 72px)'}}>
        <div style={{padding:'64px 48px', display:'flex', flexDirection:'column', justifyContent:'center', maxWidth:520, margin:'0 auto', width:'100%'}}>
          <div className="eyebrow">{isLogin ? t('auth.login.eyebrow') : t('auth.register.eyebrow')}</div>
          <h1 className="display" style={{fontSize:36, marginBottom:12}}>
            {isLogin ? t('auth.login.title') : t('auth.register.title')}
          </h1>
          <p style={{color:'var(--t-ink-muted)', fontSize:15, marginBottom:32}}>
            {isLogin ? t('auth.login.title') : t('auth.register.title')}
          </p>

          {!isLogin && (
            <div style={{display:'grid', gridTemplateColumns:'1fr 1fr', gap:10, marginBottom:24}}>
              <button onClick={()=>setRole('employer')} className={`card-flat`} style={{padding:20, textAlign:'left', border: role==='employer'?'2px solid var(--t-accent)':'1.5px solid var(--t-line)', cursor:'pointer', background:'var(--t-paper)'}}>
                <div style={{fontSize:24, marginBottom:6}}>🏠</div>
                <div style={{fontWeight:600, marginBottom:4}}>{t('auth.employer')}</div>
              </button>
              <button onClick={()=>setRole('helper')} className={`card-flat`} style={{padding:20, textAlign:'left', border: role==='helper'?'2px solid var(--t-accent)':'1.5px solid var(--t-line)', cursor:'pointer', background:'var(--t-paper)'}}>
                <div style={{fontSize:24, marginBottom:6}}>👋</div>
                <div style={{fontWeight:600, marginBottom:4}}>{t('auth.helper')}</div>
              </button>
            </div>
          )}

          <div style={{display:'flex', flexDirection:'column', gap:14, marginBottom:20}}>
            {!isLogin && (
              <div>
                <label className="label">{t('dash.account.fullName')}</label>
                <input className="input" placeholder="Jane Chen"/>
              </div>
            )}
            <div>
              <label className="label">{t('auth.email')}</label>
              <input className="input" placeholder="you@example.com" type="email"/>
            </div>
            <div>
              <label className="label">{t('auth.password')}</label>
              <input className="input" placeholder="••••••••" type="password"/>
            </div>
          </div>

          <button className="btn btn-primary btn-lg btn-block" onClick={submit} style={{marginBottom:16}}>
            {isLogin ? t('auth.submitLogin') : t('auth.submitRegister')}
          </button>

          <div style={{display:'flex', alignItems:'center', gap:12, color:'var(--t-ink-muted)', fontSize:13, margin:'12px 0'}}>
            <div style={{flex:1, height:1, background:'var(--t-line)'}}/> {t('auth.orWith')} <div style={{flex:1, height:1, background:'var(--t-line)'}}/>
          </div>
          <button className="btn btn-outline btn-block" style={{marginBottom:10}}>{t('auth.google')}</button>
          <button className="btn btn-outline btn-block">{t('auth.apple')}</button>

          <div style={{marginTop:28, fontSize:14, color:'var(--t-ink-muted)', textAlign:'center'}}>
            {isLogin ? (
              <>{t('auth.switchToRegister')} <a style={{color:'var(--t-accent)', fontWeight:600, cursor:'pointer'}} onClick={()=>go('auth:register')}>{t('auth.submitRegister')}</a></>
            ) : (
              <>{t('auth.switchToLogin')} <a style={{color:'var(--t-accent)', fontWeight:600, cursor:'pointer'}} onClick={()=>go('auth:login')}>{t('auth.submitLogin')}</a></>
            )}
          </div>
        </div>
        <div className="auth-marketing" style={{background:`linear-gradient(135deg, rgba(40,25,15,0.3), rgba(40,25,15,0.5)), url(https://images.unsplash.com/photo-1600880292203-757bb62b4baf?w=1200&q=80)`, backgroundSize:'cover', backgroundPosition:'center', padding:56, color:'white', display:'flex', flexDirection:'column', justifyContent:'flex-end'}}>
          <div style={{maxWidth:420}}>
            <div className="stars">★★★★★</div>
            <p className="display" style={{fontSize:26, margin:'16px 0 20px', color:'white', lineHeight:1.4}}>
              "We found Maria after watching three assessment videos on a Sunday morning. She moved in three weeks later."
            </p>
            <div style={{display:'flex', alignItems:'center', gap:12}}>
              <Avatar person={{initials:'W', color:'#E8856A'}} size={40}/>
              <div>
                <div style={{fontWeight:600}}>The Wong family</div>
                <div style={{fontSize:13, opacity:0.8}}>Taipei · Standard member</div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};

const GuidesPage = ({ go }) => {
  const { guides } = window.MOCK_DATA;
  return (
    <div className="page">
      <div className="container-wide" style={{padding:'48px 32px 80px'}}>
        <div style={{marginBottom:48, maxWidth:700}}>
          <div className="eyebrow">Guides</div>
          <h1 className="display" style={{fontSize:44, marginBottom:14}}>Everything you need to hire confidently</h1>
          <p style={{fontSize:17, color:'var(--t-ink-muted)'}}>
            Clear, practical articles on foreign helper hiring in Taiwan, Hong Kong, and Singapore. Written by our editorial team.
          </p>
        </div>
        <div style={{display:'grid', gridTemplateColumns:'2fr 1fr 1fr', gap:20, marginBottom:48}}>
          {/* Featured */}
          <div className="card" style={{padding:0, overflow:'hidden', cursor:'pointer'}} onClick={()=>go(`guide:${guides[0].slug}`)}>
            <div style={{height:360, background:`linear-gradient(135deg, #E8856A, #B8543A)`, backgroundImage:`linear-gradient(rgba(40,25,15,0.3),rgba(40,25,15,0.5)), url(https://images.unsplash.com/photo-1556909114-f6e7ad7d3136?w=1600&q=80)`, backgroundSize:'cover', backgroundPosition:'center'}}/>
            <div style={{padding:32}}>
              <div style={{display:'flex', gap:12, alignItems:'center', marginBottom:12, fontSize:13, color:'var(--t-ink-muted)'}}>
                <span className="chip chip-coral" style={{fontSize:11}}>{guides[0].category}</span>
                <span>· {guides[0].readTime} read · {guides[0].date}</span>
              </div>
              <h2 className="display" style={{fontSize:28, marginBottom:10, letterSpacing:'-0.01em'}}>{guides[0].title}</h2>
              <p style={{fontSize:15, color:'var(--t-ink-muted)', lineHeight:1.6}}>{guides[0].excerpt}</p>
            </div>
          </div>
          {guides.slice(1, 3).map((g, i) => (
            <div key={g.slug} className="card" style={{padding:0, overflow:'hidden', cursor:'pointer', display:'flex', flexDirection:'column'}} onClick={()=>go(`guide:${g.slug}`)}>
              <div style={{height:170, background:`linear-gradient(135deg, ${i===0?'#48B8A0':'#B8865B'}, ${i===0?'#2E8B74':'#8B6914'})`}}/>
              <div style={{padding:20, flex:1, display:'flex', flexDirection:'column'}}>
                <div style={{display:'flex', gap:12, alignItems:'center', marginBottom:10, fontSize:12, color:'var(--t-ink-muted)'}}>
                  <span className="chip" style={{fontSize:11}}>{g.category}</span>
                  <span>· {g.readTime}</span>
                </div>
                <h3 style={{fontSize:18, fontWeight:600, marginBottom:8, lineHeight:1.35, letterSpacing:'-0.01em'}}>{g.title}</h3>
                <p style={{fontSize:14, color:'var(--t-ink-muted)', lineHeight:1.55, flex:1}}>{g.excerpt}</p>
              </div>
            </div>
          ))}
        </div>

        <h2 className="display" style={{fontSize:28, marginBottom:20}}>More articles</h2>
        <div style={{display:'grid', gridTemplateColumns:'repeat(3,1fr)', gap:20}}>
          {guides.slice(3).map(g => (
            <div key={g.slug} className="card-flat" style={{padding:24, cursor:'pointer'}} onClick={()=>go(`guide:${g.slug}`)}>
              <div style={{display:'flex', gap:10, marginBottom:12, fontSize:12, color:'var(--t-ink-muted)'}}>
                <span className="chip" style={{fontSize:11}}>{g.category}</span>
                <span>· {g.readTime} · {g.date}</span>
              </div>
              <h3 style={{fontSize:17, fontWeight:600, marginBottom:8, lineHeight:1.35, letterSpacing:'-0.01em'}}>{g.title}</h3>
              <p style={{fontSize:14, color:'var(--t-ink-muted)', lineHeight:1.55, marginBottom:14}}>{g.excerpt}</p>
              <span style={{fontSize:13, color:'var(--t-accent)', fontWeight:600}}>Read article <Icon name="arrow" size={12}/></span>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
};

const AgenciesPage = ({ go }) => {
  const agencies = [
    { id:1, name:'Sunrise Care Agency', city:'Taipei', market:'Taiwan', rating:4.8, placements:420, fee:'NT$18,000', lead:'2–3 weeks', tags:['Live-in','Elder care','Full service'], blurb:'Established 2009. Specialises in elder care placements with Indonesian helpers. Bilingual Mandarin/English coordinator.' },
    { id:2, name:'Harmony Household HK', city:'Hong Kong', market:'Hong Kong', rating:4.7, placements:890, fee:'HK$4,500', lead:'3–4 weeks', tags:['Live-in','Childcare','Replacement guarantee'], blurb:'Full-service agency covering contract, visa, medical, and airport pickup. 6-month replacement guarantee included.' },
    { id:3, name:'Lotus Family Services', city:'Singapore', market:'Singapore', rating:4.9, placements:1240, fee:'S$988', lead:'2 weeks', tags:['Live-in','Infant care','Cooking focus'], blurb:'Top-rated agency in Tanjong Pagar. Strong roster of Filipino helpers with infant-care certification.' },
    { id:4, name:'Ivy Bridge Recruitment', city:'Taichung', market:'Taiwan', rating:4.6, placements:310, fee:'NT$16,500', lead:'3 weeks', tags:['Driver','Housekeeping'], blurb:'Smaller boutique agency. Personal matching with home visits before placement.' },
    { id:5, name:'Pearl Domestic Helpers', city:'Kowloon', market:'Hong Kong', rating:4.5, placements:610, fee:'HK$3,900', lead:'4 weeks', tags:['Live-in','Elder care'], blurb:'Budget-friendly option. Large roster from Indonesia and the Philippines, with monthly orientation sessions.' },
    { id:6, name:'Eastbloom Caregivers', city:'Kaohsiung', market:'Taiwan', rating:4.7, placements:245, fee:'NT$17,500', lead:'2 weeks', tags:['Elder care','Live-in'], blurb:'Focus on southern Taiwan households. All helpers complete a 2-week in-house assessment before being listed.' },
  ];
  const [market, setMarket] = useState('All');
  const filtered = market === 'All' ? agencies : agencies.filter(a => a.market === market);

  return (
    <div className="page">
      <div className="container-wide" style={{padding:'32px 32px 80px'}}>
        <div style={{marginBottom:28}}>
          <div className="eyebrow">Partner network</div>
          <h1 className="display" style={{fontSize:38, marginBottom:6}}>Hiring agencies we partner with</h1>
          <div style={{color:'var(--t-ink-muted)', maxWidth:640, lineHeight:1.6}}>Prefer someone to handle contracts, visas, and logistics end-to-end? These partner agencies in Taiwan, Hong Kong, and Singapore have been reviewed by our team and can take over the process for a flat fee.</div>
        </div>

        <div style={{display:'flex', gap:8, marginBottom:24, flexWrap:'wrap'}}>
          {['All','Taiwan','Hong Kong','Singapore'].map(m => (
            <button key={m} className={`chip ${market===m?'chip-coral':'chip-outline'}`} style={{padding:'8px 16px', fontSize:13, cursor:'pointer'}} onClick={()=>setMarket(m)}>{m}</button>
          ))}
        </div>

        <div style={{display:'grid', gridTemplateColumns:'repeat(auto-fill, minmax(360px, 1fr))', gap:20}}>
          {filtered.map(a => (
            <div key={a.id} className="card" style={{padding:24, display:'flex', flexDirection:'column', gap:14}}>
              <div style={{display:'flex', justifyContent:'space-between', alignItems:'flex-start', gap:12}}>
                <div style={{minWidth:0}}>
                  <div style={{fontSize:17, fontWeight:700, letterSpacing:'-0.01em', marginBottom:2}}>{a.name}</div>
                  <div style={{fontSize:12, color:'var(--t-ink-muted)'}}><Icon name="location" size={11}/> {a.city} · {a.market}</div>
                </div>
                <div style={{display:'flex', alignItems:'center', gap:4, fontSize:13, fontWeight:600, color:'#D4A554', flexShrink:0}}>★ {a.rating}</div>
              </div>
              <p style={{fontSize:13, lineHeight:1.6, color:'var(--t-ink-soft)', margin:0}}>{a.blurb}</p>
              <div style={{display:'flex', gap:6, flexWrap:'wrap'}}>
                {a.tags.map(t => <span key={t} className="chip chip-ghost" style={{fontSize:11, padding:'4px 10px'}}>{t}</span>)}
              </div>
              <div style={{display:'grid', gridTemplateColumns:'1fr 1fr 1fr', gap:10, paddingTop:12, borderTop:'1px solid var(--t-line)', fontSize:12}}>
                <div><div style={{color:'var(--t-ink-muted)', marginBottom:2}}>Placements</div><div style={{fontWeight:700}}>{a.placements}+</div></div>
                <div><div style={{color:'var(--t-ink-muted)', marginBottom:2}}>Service fee</div><div style={{fontWeight:700}}>{a.fee}</div></div>
                <div><div style={{color:'var(--t-ink-muted)', marginBottom:2}}>Lead time</div><div style={{fontWeight:700}}>{a.lead}</div></div>
              </div>
              <div style={{display:'flex', gap:8, marginTop:4}}>
                <button className="btn btn-primary btn-sm" style={{flex:1}}>Request intro</button>
                <button className="btn btn-outline btn-sm">View profile</button>
              </div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
};

// ===== Guide article detail =====
const GuideArticlePage = ({ slug, go }) => {
  const { guides } = window.MOCK_DATA;
  const g = guides.find(x => x.slug === slug) || guides[0];
  const idx = guides.indexOf(g);
  const related = guides.filter(x => x.slug !== g.slug && x.category === g.category).concat(guides.filter(x => x.slug !== g.slug && x.category !== g.category)).slice(0, 3);

  // Hero images by category/slug
  const heroImages = {
    'taiwan-foreign-helper-application-2026': 'https://images.unsplash.com/photo-1582407947304-fd86f028f716?w=1600&q=80',
    'interview-questions-helper': 'https://images.unsplash.com/photo-1573497019940-1c28c88b4f3e?w=1600&q=80',
    'evaluate-assessment-videos': 'https://images.unsplash.com/photo-1551836022-deb4988cc6c0?w=1600&q=80',
    'hong-kong-minimum-allowable-wage': 'https://images.unsplash.com/photo-1536599018102-9f803c140fc1?w=1600&q=80',
    'singapore-levy-concession': 'https://images.unsplash.com/photo-1525625293386-3f8f99389edd?w=1600&q=80',
    'first-week-onboarding': 'https://images.unsplash.com/photo-1484771586062-9e7195f56665?w=1600&q=80',
  };
  const hero = heroImages[g.slug] || 'https://images.unsplash.com/photo-1556909114-f6e7ad7d3136?w=1600&q=80';

  // Article content pools — consistent shape: lead + sections. Keep short and practical.
  const articleBodies = {
    'taiwan-foreign-helper-application-2026': {
      lead: 'Hiring a foreign domestic helper in Taiwan is a regulated process managed by the Ministry of Labor (MOL). Done well, it takes 6–10 weeks from application to arrival. Here is what to prepare, the order to do it in, and where most families get stuck.',
      sections: [
        { h: 'Before you apply: eligibility check', p: 'Most families qualify if they have an elderly parent needing care, a child under the age of 6, or a severely disabled family member. A Barthel Index evaluation from a designated hospital is usually required. Book this first — wait times for evaluations can be 2–3 weeks in Taipei.' },
        { h: 'Step 1 — Submit the MOL application', p: 'File Form 1 (Application for Employment Permit) with the Workforce Development Agency. You will need the medical evaluation, ID copies, and proof of household registration. Expect 10–14 business days for approval.' },
        { h: 'Step 2 — Select a helper', p: 'You can go through a licensed agency or use a platform like HelperMatch to meet helpers directly. Either way, verify the helper has a valid passport, medical clearance, and no overstayed previous contracts.', list: ['Passport with 12+ months validity','Medical exam from an MOL-approved clinic','Signed employment contract in Chinese and English','Reference letters from previous employers'] },
        { h: 'Step 3 — Visa and entry', p: 'Once the helper is matched, your agency or lawyer files for the work visa. After approval, the helper enters Taiwan, completes the 3-day orientation, and receives their ARC (Alien Resident Certificate) within 30 days of arrival.' },
        { h: 'Where families get stuck', p: 'The most common delays are: incomplete medical files, mismatched names on passport vs. contract, and missing signatures on the Chinese version of the contract. Check every document twice before submitting.' },
      ],
    },
    'interview-questions-helper': {
      lead: 'A resume tells you what someone has done. A good interview tells you how they think, how they handle pressure, and whether their values fit your household. Here are 12 questions we think every family should ask.',
      sections: [
        { h: 'Values and fit', p: 'The goal of these questions is not to catch anyone out — it is to understand how the helper approaches care, privacy, and daily decisions.', list: [
          'Describe a difficult day in your last job. What did you do?',
          'What does a typical morning look like, from wake-up to lunch?',
          'When you disagree with an employer, how do you usually handle it?',
          'What would you do if a child refused to eat what you prepared?',
        ] },
        { h: 'Skills in practice', p: 'Ask open-ended questions that require a story, not a yes/no.', list: [
          'Walk me through how you would prepare a meal for an elderly person with diabetes.',
          'How do you keep small children entertained indoors on a rainy day?',
          'Tell me about the hardest person you cared for. What made it hard?',
          'What household tasks do you find most tedious? How do you stay on top of them?',
        ] },
        { h: 'Life outside work', p: 'You are sharing a home with this person. These four questions surface red flags fast.', list: [
          'What do you do on your rest day?',
          'How often do you send money home? To whom?',
          'What are you hoping to get out of this placement, beyond salary?',
          'Is there anything you want to ask us?',
        ] },
      ],
    },
    'evaluate-assessment-videos': {
      lead: 'Our A / B / C / D tiers are the output of a structured 2-hour assessment run at our Surabaya center. They are not scores of a person — they are a measurement of demonstrated proficiency on the specific day of the assessment.',
      sections: [
        { h: 'What the assessment measures', p: 'Each helper is assessed on cooking (execution and cleanup), housekeeping (thoroughness and speed), caregiving (gentleness and protocol adherence), and language (English and Mandarin comprehension). Each area is scored independently.' },
        { h: 'Tier definitions', p: 'Here is what each tier generally corresponds to, though individual strengths vary.', list: [
          'Tier A — Strong across at least 3 of 4 areas, ready for senior placements',
          'Tier B — Reliable in 2–3 areas, solid default choice for most families',
          'Tier C — Competent fundamentals, excels in 1 focused skill area',
          'Tier D — Just completed training, best suited to simpler households',
        ] },
        { h: 'What tiers do NOT tell you', p: 'Personality, communication warmth, and cultural fit. A tier is a floor on skill, not a ceiling on character. Watch the full assessment video and have a real conversation before deciding.' },
      ],
    },
    'hong-kong-minimum-allowable-wage': {
      lead: 'As of September 2025, Hong Kong\'s Minimum Allowable Wage (MAW) for foreign domestic helpers is HK$4,990 per month. The food allowance is HK$1,236 if food is not provided. Here is what changed and what it means for your contract.',
      sections: [
        { h: 'What is the MAW?', p: 'The Minimum Allowable Wage is the lowest monthly salary a foreign domestic helper can be paid in Hong Kong. It applies to all new contracts signed after the effective date. Existing contracts continue at their original rate until renewal.' },
        { h: 'Food: cash or kind?', p: 'Employers must either provide food or pay a monthly allowance of HK$1,236. Most families opt to provide food, but clear it with the helper in writing. Mixed arrangements (some meals provided, partial allowance) are technically non-compliant.' },
        { h: 'What this means for renewals', p: 'If your helper\'s 2-year contract is up for renewal, the new MAW applies automatically. Make sure the new employment contract reflects the updated figure before you both sign. The Immigration Department checks this.' },
      ],
    },
    'singapore-levy-concession': {
      lead: 'The Singapore MDW levy is S$300/month at the standard rate, or S$60/month with the concession. Over a 2-year contract, that is a S$5,760 difference. Here is who qualifies and how to apply.',
      sections: [
        { h: 'Who qualifies', p: 'You qualify for the concessionary levy if your household has one of the following: a child under 16, a senior aged 67 or above, or a person with disability certified by a medical practitioner.', list: [
          'Young child concession — child must be a Singapore citizen',
          'Aged person concession — senior must be a Singapore citizen and living at the same address',
          'Person with disability concession — requires signed PWD form from a registered doctor',
        ] },
        { h: 'How to apply', p: 'Apply online via the MOM Work Permit Online portal. You will need the NRIC of the qualifying family member, proof of relationship, and (for disability cases) the PWD form. Approval is typically instant for citizens.' },
        { h: 'Renewals and losing eligibility', p: 'The concession is tied to the qualifying person, not the helper. If your child turns 16 or the senior moves out, you lose the concession in the following month. MOM does not backdate.' },
      ],
    },
    'first-week-onboarding': {
      lead: 'The first week sets the tone for everything that follows. A helper who feels welcomed, oriented, and respected is far more likely to stay, care well, and communicate when something is wrong. Here is a simple day-by-day plan.',
      sections: [
        { h: 'Day 1 — Arrival and home tour', p: 'Pick them up yourself if you can. Give them time to unpack and rest. Do a 30-minute home tour — which cupboard has what, where cleaning supplies live, what is off-limits. Introduce every family member by name, slowly.' },
        { h: 'Day 2 — Kitchen and food', p: 'Cook one meal together. Show them your pantry, your fridge rules, and any dietary needs. Ask them to cook something familiar for dinner so they feel at home. This is also when you share the weekly menu if you have one.' },
        { h: 'Day 3–5 — Shadow routines', p: 'Have them observe the morning and evening routines for the first few days. Do not hand over full responsibility on day 1. Let them ask questions. Write a simple routine sheet and post it on the fridge.', list: [
          'Morning: wake-up times, breakfast, school drop-off',
          'Afternoon: nap, pickup, snack, homework',
          'Evening: dinner prep, bath, bedtime',
        ] },
        { h: 'Day 6 — First rest day', p: 'Make sure they know how to use the MRT/bus, have a SIM card, and know your address in the local language. Give them some cash, the family WhatsApp group, and tell them to text if anything feels off.' },
        { h: 'Day 7 — Check in', p: 'Sit down for 15 minutes. Ask what is working, what is confusing, and what they need. Listen more than you talk. Adjust expectations, not the person.' },
      ],
    },
  };

  const body = articleBodies[g.slug] || articleBodies['interview-questions-helper'];

  return (
    <div className="page">
      {/* Hero */}
      <div style={{position:'relative', width:'100%', height:420, overflow:'hidden'}}>
        <div style={{position:'absolute', inset:0, backgroundImage:`linear-gradient(rgba(30,20,15,0.35), rgba(30,20,15,0.65)), url(${hero})`, backgroundSize:'cover', backgroundPosition:'center'}}/>
        <div className="container" style={{position:'relative', height:'100%', display:'flex', flexDirection:'column', justifyContent:'flex-end', padding:'0 32px 48px', color:'white'}}>
          <button className="btn btn-ghost btn-sm" onClick={()=>go('guides')} style={{marginBottom:16, color:'white', background:'rgba(255,255,255,0.12)', alignSelf:'flex-start', border:'1px solid rgba(255,255,255,0.25)'}}>
            <Icon name="arrowLeft" size={13}/> All guides
          </button>
          <div style={{display:'flex', gap:10, alignItems:'center', marginBottom:14, fontSize:13, opacity:0.95}}>
            <span className="chip chip-coral" style={{fontSize:11}}>{g.category}</span>
            <span>· {g.readTime} read · {g.date}</span>
          </div>
          <h1 className="display" style={{fontSize:44, lineHeight:1.15, maxWidth:880, letterSpacing:'-0.02em'}}>{g.title}</h1>
          <div style={{fontSize:17, marginTop:12, maxWidth:720, opacity:0.92, lineHeight:1.5}}>{g.excerpt}</div>
        </div>
      </div>

      <div className="container" style={{padding:'48px 32px 80px', display:'grid', gridTemplateColumns:'minmax(0, 720px) 260px', gap:56, alignItems:'start'}}>
        {/* Article body */}
        <article style={{minWidth:0}}>
          {/* Byline */}
          <div style={{display:'flex', alignItems:'center', gap:12, paddingBottom:24, marginBottom:32, borderBottom:'1px solid var(--t-line)'}}>
            <div style={{width:44, height:44, borderRadius:99, background:'linear-gradient(135deg, #E8856A, #C06848)', color:'white', display:'grid', placeItems:'center', fontWeight:700, fontSize:15}}>HM</div>
            <div style={{flex:1}}>
              <div style={{fontSize:14, fontWeight:600}}>HelperMatch Editorial Team</div>
              <div style={{fontSize:12, color:'var(--t-ink-muted)'}}>Last updated {g.date}</div>
            </div>
            <button className="btn btn-ghost btn-sm" title="Share">Share</button>
          </div>

          <p style={{fontSize:19, lineHeight:1.7, color:'var(--t-ink)', marginBottom:36, letterSpacing:'-0.005em'}}>{body.lead}</p>

          {body.sections.map((s, i) => (
            <section key={i} style={{marginBottom:36}}>
              <h2 className="display" style={{fontSize:24, marginBottom:12, letterSpacing:'-0.015em'}}>{s.h}</h2>
              <p style={{fontSize:16, lineHeight:1.75, color:'var(--t-ink-soft)', marginBottom: s.list ? 16 : 0}}>{s.p}</p>
              {s.list && (
                <ul style={{listStyle:'none', padding:0, display:'flex', flexDirection:'column', gap:10}}>
                  {s.list.map((li, j) => (
                    <li key={j} style={{display:'flex', gap:12, alignItems:'flex-start', fontSize:15, lineHeight:1.6, color:'var(--t-ink)'}}>
                      <span style={{flexShrink:0, width:20, height:20, borderRadius:99, background:'var(--trust-bg)', color:'var(--trust)', display:'grid', placeItems:'center', marginTop:2}}>
                        <Icon name="check" size={11}/>
                      </span>
                      <span>{li}</span>
                    </li>
                  ))}
                </ul>
              )}
            </section>
          ))}

          {/* CTA block */}
          <div style={{marginTop:48, padding:32, background:'var(--trust-bg)', border:'1px solid var(--trust-soft)', borderRadius:16}}>
            <div style={{fontSize:12, fontWeight:700, color:'var(--trust-ink)', textTransform:'uppercase', letterSpacing:'0.08em', marginBottom:8}}>Ready to start?</div>
            <h3 className="display" style={{fontSize:22, marginBottom:8}}>Meet verified helpers who fit your criteria</h3>
            <p style={{fontSize:15, color:'var(--t-ink-soft)', marginBottom:16, lineHeight:1.6}}>Browse assessed profiles, watch video introductions, and contact helpers directly — no middleman required.</p>
            <div style={{display:'flex', gap:10, flexWrap:'wrap'}}>
              <button className="btn btn-trust" onClick={()=>go('candidates')}>Browse helpers</button>
              <button className="btn btn-outline" onClick={()=>go('pricing')}>See pricing</button>
            </div>
          </div>

          {/* Prev / Next */}
          <div style={{marginTop:56, paddingTop:32, borderTop:'1px solid var(--t-line)', display:'grid', gridTemplateColumns:'1fr 1fr', gap:16}}>
            {idx > 0 ? (
              <button className="card-flat" style={{padding:20, textAlign:'left', cursor:'pointer', background:'none'}} onClick={()=>go(`guide:${guides[idx-1].slug}`)}>
                <div style={{fontSize:11, color:'var(--t-ink-muted)', textTransform:'uppercase', letterSpacing:'0.08em', fontWeight:600, marginBottom:6}}>← Previous</div>
                <div style={{fontSize:14, fontWeight:600, lineHeight:1.4}}>{guides[idx-1].title}</div>
              </button>
            ) : <div/>}
            {idx < guides.length-1 ? (
              <button className="card-flat" style={{padding:20, textAlign:'right', cursor:'pointer', background:'none'}} onClick={()=>go(`guide:${guides[idx+1].slug}`)}>
                <div style={{fontSize:11, color:'var(--t-ink-muted)', textTransform:'uppercase', letterSpacing:'0.08em', fontWeight:600, marginBottom:6}}>Next →</div>
                <div style={{fontSize:14, fontWeight:600, lineHeight:1.4}}>{guides[idx+1].title}</div>
              </button>
            ) : <div/>}
          </div>
        </article>

        {/* Sidebar */}
        <aside>
          <div style={{position:'sticky', top:96, display:'flex', flexDirection:'column', gap:24}}>
            {/* TOC */}
            <div>
              <div style={{fontSize:11, fontWeight:700, color:'var(--t-ink-muted)', textTransform:'uppercase', letterSpacing:'0.08em', marginBottom:12}}>In this article</div>
              <ol style={{listStyle:'none', padding:0, display:'flex', flexDirection:'column', gap:10, borderLeft:'2px solid var(--t-line)'}}>
                {body.sections.map((s, i) => (
                  <li key={i} style={{paddingLeft:14, marginLeft:-1, borderLeft: i===0 ? '2px solid var(--t-accent)' : '2px solid transparent', fontSize:13, lineHeight:1.45, color:'var(--t-ink-soft)', cursor:'pointer'}}>{s.h}</li>
                ))}
              </ol>
            </div>

            {/* Related */}
            <div>
              <div style={{fontSize:11, fontWeight:700, color:'var(--t-ink-muted)', textTransform:'uppercase', letterSpacing:'0.08em', marginBottom:12}}>Related reading</div>
              <div style={{display:'flex', flexDirection:'column', gap:14}}>
                {related.map(r => (
                  <div key={r.slug} style={{cursor:'pointer'}} onClick={()=>go(`guide:${r.slug}`)}>
                    <div style={{fontSize:11, color:'var(--t-ink-muted)', marginBottom:4}}>{r.category} · {r.readTime}</div>
                    <div style={{fontSize:13, fontWeight:600, lineHeight:1.4, color:'var(--t-ink)'}}>{r.title}</div>
                  </div>
                ))}
              </div>
            </div>
          </div>
        </aside>
      </div>
    </div>
  );
};

Object.assign(window, { JobsPage, JobDetailPage, PricingPage, AuthPage, GuidesPage, AgenciesPage, GuideArticlePage });
