// Shared UI components

const { useState, useEffect, useRef } = React;

function MenuIconFallback(p = {}) {
  return (
    <svg
      viewBox="0 0 16 16"
      fill="none"
      stroke="currentColor"
      strokeWidth="1.6"
      strokeLinecap="round"
      className={p.className || 'icon'}
      {...p}
    >
      <path d="M3 4.5h10M3 8h10M3 11.5h10" />
    </svg>
  );
}

// ── Top nav ──────────────────────────────────────────────────────────
function Nav({ signedIn, onSignIn, onSignOut, onHome, onNav, hideHeaderCtas }) {
  const [mobileOpen, setMobileOpen] = useState(false);
  const MenuIcon = Icon.Menu || MenuIconFallback;
  const go = (target) => {
    setMobileOpen(false);
    onNav && onNav(target);
  };
  const home = (e) => {
    e.preventDefault();
    setMobileOpen(false);
    onHome && onHome();
  };

  return (
    <nav className={'nav' + (hideHeaderCtas ? ' nav--no-ctas' : '')}>
      <div className="nav-inner">
        <a className="brand" href="#/" onClick={home}>
          <span className="brand-mark">W</span>
          WorkApp<span style={{color: 'var(--muted)', fontWeight: 400}}>.ai</span>
        </a>
        {!hideHeaderCtas && (
        <div className="nav-links">
          <a href="#/workapps" onClick={(e) => { e.preventDefault(); go('directory'); }}>WorkApps</a>
          <a href="#/experts" onClick={(e) => { e.preventDefault(); go('experts'); }}>Experts</a>
          <a href="#/about" onClick={(e) => { e.preventDefault(); go('about'); }}>About</a>
          <a href="#/become" onClick={(e) => { e.preventDefault(); go('become'); }}>For Experts</a>
        </div>
        )}
        <div className="nav-spacer"></div>
        {!hideHeaderCtas && (
        <div className="nav-right">
          {signedIn ? (
            <>
              <button className="btn btn-bare btn-sm" onClick={() => go('myruns')}>My runs</button>
              <button className="btn btn-bare btn-sm" onClick={() => go('account')}>Account</button>
              <button className="btn btn-ghost btn-sm" onClick={onSignOut}>Sign out</button>
            </>
          ) : (
            <button className="btn btn-bare btn-sm" onClick={onSignIn}>Sign in</button>
          )}
        </div>
        )}
        {!hideHeaderCtas && (
        <>
        <button
          className="nav-menu-toggle btn btn-ghost btn-sm"
          type="button"
          aria-label={mobileOpen ? 'Close navigation menu' : 'Open navigation menu'}
          aria-expanded={mobileOpen}
          aria-controls="mobile-nav-menu"
          onClick={() => setMobileOpen(!mobileOpen)}
        >
          <MenuIcon />
        </button>
        {mobileOpen && (
          <div className="mobile-nav-menu" id="mobile-nav-menu">
            <button type="button" onClick={() => go('directory')}>WorkApps</button>
            <button type="button" onClick={() => go('experts')}>Experts</button>
            <button type="button" onClick={() => go('about')}>About</button>
            <button type="button" onClick={() => go('become')}>For Experts</button>
            <div className="mobile-nav-rule"></div>
            {signedIn ? (
              <>
                <button type="button" onClick={() => go('myruns')}>My runs</button>
                <button type="button" onClick={() => go('account')}>Account</button>
                <button type="button" onClick={() => { setMobileOpen(false); onSignOut && onSignOut(); }}>Sign out</button>
              </>
            ) : (
              <button type="button" onClick={() => { setMobileOpen(false); onSignIn && onSignIn(); }}>Sign in</button>
            )}
          </div>
        )}
        </>
        )}
      </div>
    </nav>
  );
}

// ── Expert mini ──────────────────────────────────────────────────────
function ExpertAvatar({ person, name, initial, className = 'expert-avatar', style = {} }) {
  const personName = name || person?.name || person?.expert;
  const photo = person?.photo || (typeof EXPERT_PHOTOS !== 'undefined' ? EXPERT_PHOTOS[personName] : null);
  const fallback = initial || person?.initial || (personName ? personName.charAt(0) : '');
  return (
    <div className={className} style={style} aria-label={personName || fallback}>
      {photo ? <img src={photo} alt={personName || 'Expert'} /> : fallback}
    </div>
  );
}

function ExpertChip({ expert, large, onClick }) {
  const interactive = typeof onClick === 'function';
  const content = (
    <>
      <ExpertAvatar person={expert} style={{background: expert.avatarBg || 'linear-gradient(135deg, #d4a373, #a0522d)'}} />
      <div className="expert-strip-copy">
        <div className="expert-name">{expert.name}</div>
        <div className="expert-title">{expert.title}</div>
        <div className="expert-specialty">{expert.specialty}</div>
      </div>
      {interactive && <span className="expert-profile-cue">Profile <Icon.ArrowRight className="icon-sm" /></span>}
    </>
  );

  if (interactive) {
    return (
      <button
        type="button"
        className="expert-strip expert-strip-action"
        style={large ? {} : {padding: '12px 16px', maxWidth: '100%'}}
        onClick={() => onClick(expert)}
      >
        {content}
      </button>
    );
  }

  return (
    <div className="expert-strip" style={large ? {} : {padding: '12px 16px', maxWidth: '100%'}}>
      {content}
    </div>
  );
}

// ── WorkApp preview ──────────────────────────────────────────────────
function WorkAppCard({ wapp, onClick, variant = 'row' }) {
  const categoryClass = 'cat-' + String(wapp.cat || '').toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
  const volumeSignal = wapp.runs ? `${Number(wapp.runs).toLocaleString()} runs` : wapp.source;
  const outcomeByType = {
    'Asset Review': 'See the specific signals the expert would use to judge whether the asset is ready.',
    Decision: 'Surface the tradeoff, timing, and conditions that make this worth doing now or later.',
    Priority: 'Find the bottleneck to fix before adding more effort, budget, or activity.',
    'Competitor Gap': 'See the visible gap between your approach and the competitor signal that is winning.',
    Opportunity: 'Surface the next useful opening to pursue, and the opportunities to ignore for now.',
    Readiness: 'Learn whether this channel is ready to run, or which foundation has to improve first.',
  };
  const inputByType = {
    'Asset Review': 'Homepage URL',
    Decision: 'Company domain',
    Priority: 'Company domain',
    'Competitor Gap': 'Your domain + competitor',
    Opportunity: 'Company domain',
    Readiness: 'Company domain + context',
  };
  const outcome = wapp.outcome || outcomeByType[wapp.type] || 'Get an expert verdict and next step.';
  const inputNeeded = wapp.input || inputByType[wapp.type] || 'Company context';

  if (variant === 'row') {
    const activate = () => onClick && onClick();
    return (
      <article
        className={`wapp-card wapp-card-row ${categoryClass}`}
        role="link"
        tabIndex="0"
        aria-label={`Open ${wapp.title} by ${wapp.expert}`}
        onClick={activate}
        onKeyDown={(e) => {
          if (e.key === 'Enter' || e.key === ' ') {
            e.preventDefault();
            activate();
          }
        }}
      >
        <div className="wapp-main">
          <div className="wapp-byline">
            <ExpertAvatar person={wapp} name={wapp.expert} className="mini-avatar" style={{background: wapp.bg}} />
            <span>{wapp.expert}</span>
          </div>
          <h3 className="card-q">{wapp.title}</h3>
          <p className="card-outcome">{outcome}</p>
          <div className="card-meta">
            {wapp.cat ? <><span className="cat-chip"><span className="cat-dot"></span>{wapp.cat}</span><span className="dot"></span></> : null}
            <span>{wapp.time}</span>
            {volumeSignal && <span className="dot"></span>}
            {volumeSignal && <span>{volumeSignal}</span>}
          </div>
        </div>
        <div className="wapp-side">
          <div className="card-trust-row" aria-label="WorkApp trust signals">
            <span>Needs: {inputNeeded}</span>
          </div>
          <button
            className="arrow wapp-run-button"
            type="button"
            aria-label={`Run ${wapp.title} by ${wapp.expert}`}
            onClick={(e) => {
              e.stopPropagation();
              activate();
            }}
          >
            Run <Icon.ArrowRight className="icon-sm" />
          </button>
        </div>
      </article>
    );
  }

  return (
    <a
      className={`wapp-card wapp-card-${variant} ${categoryClass}`}
      href={wapp.slug ? '#/w/' + wapp.slug : '#/workapps'}
      aria-label={`Run ${wapp.title} by ${wapp.expert}`}
      onClick={(e) => { e.preventDefault(); onClick && onClick(); }}
    >
      <div className="wapp-main">
        <div className="wapp-byline">
          <ExpertAvatar person={wapp} name={wapp.expert} className="mini-avatar" style={{background: wapp.bg}} />
          <span>{wapp.expert}</span>
        </div>
        <h3 className="card-q">{wapp.title}</h3>
        <p className="card-outcome">{outcome}</p>
        <div className="card-meta">
          <span className="cat-chip"><span className="cat-dot"></span>{wapp.cat}</span>
          <span className="dot"></span>
          <span>{wapp.time}</span>
          {volumeSignal && <span className="dot"></span>}
          {volumeSignal && <span>{volumeSignal}</span>}
        </div>
      </div>
      <div className="wapp-side">
        <div className="card-trust-row" aria-label="WorkApp trust signals">
          <span>Needs: {inputNeeded}</span>
        </div>
        <span className="arrow">Run <Icon.ArrowRight className="icon-sm" /></span>
      </div>
      <div className="card-foot">
        <div className="card-expert">
          <ExpertAvatar person={wapp} name={wapp.expert} className="mini-avatar" style={{background: wapp.bg}} />
          {wapp.expert}
        </div>
        <span className="arrow">Run <Icon.ArrowRight className="icon-sm" /></span>
      </div>
    </a>
  );
}

// ── Modal shell ──────────────────────────────────────────────────────
function Modal({ open, onClose, children }) {
  const modalRef = useRef(null);
  useEffect(() => {
    if (!open) return;
    const previousFocus = document.activeElement;
    setTimeout(() => modalRef.current?.focus(), 0);
    const onKey = (e) => {
      if (e.key === 'Escape') {
        onClose();
        return;
      }
      if (e.key !== 'Tab' || !modalRef.current) return;
      const focusable = modalRef.current.querySelectorAll('a[href], button:not([disabled]), input:not([disabled]), textarea:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])');
      if (!focusable.length) return;
      const first = focusable[0];
      const last = focusable[focusable.length - 1];
      if (e.shiftKey && document.activeElement === first) {
        e.preventDefault();
        last.focus();
      } else if (!e.shiftKey && document.activeElement === last) {
        e.preventDefault();
        first.focus();
      }
    };
    window.addEventListener('keydown', onKey);
    return () => {
      window.removeEventListener('keydown', onKey);
      if (previousFocus && typeof previousFocus.focus === 'function') previousFocus.focus();
    };
  }, [open, onClose]);
  if (!open) return null;
  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div
        className="modal"
        ref={modalRef}
        role="dialog"
        aria-modal="true"
        tabIndex="-1"
        onClick={(e) => e.stopPropagation()}
      >
        {children}
      </div>
    </div>
  );
}

// ── Sign-in modal ────────────────────────────────────────────────────
function SignInModal({ open, onClose, reason }) {
  const [email, setEmail]         = useState('');
  const [sent, setSent]           = useState(false);
  const [busy, setBusy]           = useState(false);
  const [err, setErr]             = useState(null);
  const [otpCode, setOtpCode]     = useState('');
  const [verifying, setVerifying] = useState(false);
  const [verifyErr, setVerifyErr] = useState(null);

  React.useEffect(() => {
    if (!open) { setSent(false); setEmail(''); setOtpCode(''); setErr(null); setVerifyErr(null); }
  }, [open]);

  const submit = async function(e) {
    e.preventDefault();
    setBusy(true); setErr(null);
    try {
      await window.AppData.requestMagicLink(email.trim());
      setSent(true);
    } catch (ex) {
      setErr('Could not send sign-in code — please try again.');
    } finally { setBusy(false); }
  };

  const handleOtpChange = async function(val) {
    const digits = val.replace(/\D/g, '').slice(0, 6);
    setOtpCode(digits); setVerifyErr(null);
    if (digits.length === 6) {
      setVerifying(true);
      try {
        const data = await window.AppData.verifyMagicCode(email.trim(), digits);
        window.location.href = data.redirectUrl || '/';
      } catch (ex) {
        setVerifyErr((ex && ex.message) ? ex.message : 'Invalid or expired code. Please try again.');
        setOtpCode(''); setVerifying(false);
      }
    }
  };

  return (
    <Modal open={open} onClose={onClose}>
      <h3>{reason || 'Sign in to continue'}</h3>
      {!sent ? (
        <form onSubmit={submit}>
          <p style={{color: 'var(--muted)', fontSize: 14, margin: '0 0 20px', lineHeight: 1.5}}>
            {reason ? reason : 'Save results, share privately, and get better recommendations.'}
          </p>
          <input type="email" required value={email} onChange={function(e){ setEmail(e.target.value); }}
            placeholder="your@email.com" className="input" style={{width: '100%', marginBottom: 8}} disabled={busy} />
          {err ? <p style={{fontSize: 12, color: 'var(--bad)', margin: '0 0 8px'}}>{err}</p> : null}
          <button type="submit" disabled={busy || !email} className="btn btn-ink" style={{width: '100%', justifyContent: 'center'}}>
            {busy ? 'Sending…' : 'Send sign-in code'}
          </button>
        </form>
      ) : (
        <div>
          <p style={{color: 'var(--muted)', fontSize: 14, margin: '0 0 16px', lineHeight: 1.5}}>
            We sent a 6-digit code to <strong style={{color: 'var(--ink-2)'}}>{email}</strong>. Enter it below.
          </p>
          <input
            type="text" inputMode="numeric" autoComplete="one-time-code"
            maxLength={6} placeholder="000000" autoFocus
            value={otpCode} onChange={(ev) => handleOtpChange(ev.target.value)}
            disabled={verifying}
            style={{
              width: '100%', height: 48, border: '1px solid var(--hair)', borderRadius: 8,
              padding: '0 12px', fontSize: 22, letterSpacing: '0.2em', color: 'var(--ink)',
              background: 'var(--surface)', fontFamily: 'Geist Mono, monospace',
              textAlign: 'center', opacity: verifying ? 0.6 : 1,
              outline: 'none', boxSizing: 'border-box', marginBottom: 8,
            }}
          />
          {verifyErr
            ? <p style={{fontSize: 12, color: 'var(--bad)', margin: '0 0 8px'}}>{verifyErr}</p>
            : verifying
              ? <p style={{fontSize: 12, color: 'var(--muted)', margin: '0 0 8px'}}>Verifying…</p>
              : <p style={{fontSize: 12, color: 'var(--muted)', margin: '0 0 8px'}}>Auto-submits at 6 digits.</p>
          }
          <button type="button" onClick={() => { setSent(false); setOtpCode(''); setVerifyErr(null); }}
            style={{background: 'none', border: 'none', padding: 0, fontSize: 12, color: 'var(--muted)', cursor: 'pointer', textDecoration: 'underline', textUnderlineOffset: 3}}>
            Use a different email
          </button>
        </div>
      )}
      <div className="modal-foot">
        By continuing you agree to our <a href="#/terms" style={{color: 'var(--ink-2)'}}>Terms</a> and <a href="#/privacy" style={{color: 'var(--ink-2)'}}>Privacy</a>.
      </div>
    </Modal>
  );
}

// ── Qualification modal ──────────────────────────────────────────────
function QualificationModal({ open, onClose, onComplete }) {
  const [role, setRole] = useState('');
  const [stage, setStage] = useState('');
  const [priority, setPriority] = useState('');
  const [errors, setErrors] = useState({});

  const submit = (ev) => {
    ev.preventDefault();
    const nextErrors = {};
    if (!role) nextErrors.role = 'Required.';
    if (!stage) nextErrors.stage = 'Required.';
    if (!priority) nextErrors.priority = 'Required.';
    setErrors(nextErrors);
    if (Object.keys(nextErrors).length === 0) {
      onComplete && onComplete({ role, stage, priority });
    }
  };

  return (
    <Modal open={open} onClose={onClose}>
      <h3>Tell us where to route you.</h3>
      <p>Your account is open. Answer three quick questions so we recommend the right WorkApps and route expert requests responsibly.</p>

      <form className="qualification-card qualification-modal-form" onSubmit={submit}>
        <div className="qualification-head">
          <span>Short questionnaire</span>
          <b>30 seconds</b>
        </div>
        <div className="qualification-grid">
          <label>
            Role
            <select className={'input' + (errors.role ? ' error' : '')} value={role} onChange={(ev) => setRole(ev.target.value)}>
              <option value="">Choose one</option>
              <option>Founder / CEO</option>
              <option>Marketing lead</option>
              <option>Product lead</option>
              <option>Consultant / agency</option>
            </select>
            {errors.role && <span className="field-error"><Icon.Alert className="icon-sm" /> {errors.role}</span>}
          </label>
          <label>
            Company stage
            <select className={'input' + (errors.stage ? ' error' : '')} value={stage} onChange={(ev) => setStage(ev.target.value)}>
              <option value="">Choose one</option>
              <option>Pre-seed / seed</option>
              <option>Series A-B</option>
              <option>Growth</option>
              <option>Not a company</option>
            </select>
            {errors.stage && <span className="field-error"><Icon.Alert className="icon-sm" /> {errors.stage}</span>}
          </label>
          <label className="qualification-wide">
            Current priority
            <select className={'input' + (errors.priority ? ' error' : '')} value={priority} onChange={(ev) => setPriority(ev.target.value)}>
              <option value="">Choose one</option>
              <option>Improve positioning or homepage clarity</option>
              <option>Increase conversion</option>
              <option>Prepare for expert help</option>
              <option>Research WorkApps for later</option>
            </select>
            {errors.priority && <span className="field-error"><Icon.Alert className="icon-sm" /> {errors.priority}</span>}
          </label>
        </div>
        <div className="qualification-note">Used for recommendations and expert routing, not for sales spam.</div>
        <button className="btn btn-primary" type="submit">
          Continue <Icon.ArrowRight className="icon-sm" />
        </button>
      </form>
    </Modal>
  );
}

// ── Share modal ──────────────────────────────────────────────────────
// Strip HTML tags and decode entities into a plain text snippet for use in
// LinkedIn intent text and email bodies. Conservative — pulls headings and
// paragraphs, drops everything else.
function htmlToSnippet(html, maxLen) {
  if (!html || typeof html !== 'string') return '';
  let t = html
    .replace(/<\s*(p|div|h[1-6]|li|br)[^>]*>/gi, '\n')
    .replace(/<[^>]+>/g, ' ')
    .replace(/&nbsp;/g, ' ')
    .replace(/&amp;/g, '&')
    .replace(/&lt;/g, '<')
    .replace(/&gt;/g, '>')
    .replace(/&quot;/g, '"')
    .replace(/&#39;|&apos;/g, "'");
  t = t.replace(/[ \t]+/g, ' ').replace(/\n{2,}/g, '\n').trim();
  if (maxLen && t.length > maxLen) t = t.slice(0, maxLen - 1).trimEnd() + '…';
  return t;
}

function ShareModal({ open, onClose, signedIn, onSignIn, onToast, runId }) {
  const [copied, setCopied] = useState(false);
  const [token, setToken] = useState(null);
  const [err, setErr] = useState(null);
  // Result data fetched after the share token is minted, so we can build
  // rich LinkedIn / email text (not just a bare URL).
  const [result, setResult] = useState(null);

  useEffect(() => {
    if (!open || !runId) return;
    let cancelled = false;
    setToken(null); setErr(null); setResult(null);
    window.AppData.shareRun(runId)
      .then((r) => { if (!cancelled) setToken(r && r.shareToken); })
      .catch((e) => {
        if (cancelled) return;
        if (e && e.status === 401) { onSignIn && onSignIn(); return; }
        setErr(String(e && e.message || e));
      });
    return () => { cancelled = true; };
  }, [open, runId]);

  useEffect(() => {
    if (!token) return;
    let cancelled = false;
    window.AppData.getSharedRun(token)
      .then((d) => { if (!cancelled) setResult(d && d.result); })
      .catch(() => { /* best-effort — share still works with bare URL */ });
    return () => { cancelled = true; };
  }, [token]);

  const url = token ? (window.location.origin.replace(/^https?:\/\//, '') + '/r/' + token) : '';
  const fullUrl = token ? (window.location.origin + '/r/' + token) : '';

  // LinkedIn post — narrative style. Hook → finding → CTA. Designed to read
  // like a real post (not a bulleted summary) so the poster looks credible
  // and the reader is motivated to open the link. Kept under ~700 chars so
  // LinkedIn renders the whole post without "…see more".
  //
  // The URL is included INSIDE the text so LinkedIn's auto-preview attaches
  // the OG card (title/description/image) from /r/:token under the post.
  const linkedInText = (() => {
    if (!result || !fullUrl) return '';
    const expertLine = result.expertName ? ` from ${result.expertName}` : '';
    const headline = (result.verdictHeadline || '').trim();
    const sub = (result.verdictSub || '').trim();
    const rec = (result.recommendation || '').trim();

    if (headline || sub || rec) {
      const lines = [];
      lines.push(`I ran a diagnostic${expertLine} on something I've been going back and forth on.`);
      lines.push('');
      lines.push('The verdict:');
      lines.push('');
      if (headline) lines.push('"' + headline + '"');
      if (sub) { lines.push(''); lines.push(sub); }
      if (rec) {
        lines.push('');
        lines.push('What to do about it → ' + rec);
      }
      lines.push('');
      lines.push('The full breakdown is here — including the evidence and the rewrite the expert suggested:');
      lines.push(fullUrl);
      lines.push('');
      lines.push('Takes ~60s to run on your own work. No sign-up needed to read or run it.');
      return lines.join('\n');
    }

    // Workapp returned an html blob — don't try to embed it (it contains
    // UI scaffolding). Use a generic narrative; the OG card on the shared
    // URL renders the actual content as a preview.
    const lines = [];
    lines.push(`I ran a diagnostic${expertLine} on WorkApp.ai — and the answer was sharper than I expected.`);
    lines.push('');
    lines.push('Worth 60 seconds if any of this sounds like you:');
    lines.push(fullUrl);
    lines.push('');
    lines.push('No sign-up needed. Anyone with the link can read it.');
    return lines.join('\n');
  })();

  const emailSubject = (() => {
    if (!result) return 'A WorkApp result for you';
    const oneLine = (s) => s.replace(/\s+/g, ' ').trim().slice(0, 100);
    const h = (result.verdictHeadline || '').trim();
    if (h) return 'A diagnostic result you should see: ' + oneLine(h);
    return 'A 60-second diagnostic I ran — want to take a look?';
  })();

  const emailBody = (() => {
    if (!fullUrl) return '';
    const expertLine = result?.expertName ? ` by ${result.expertName}` : '';
    const headline = (result?.verdictHeadline || '').trim();
    const sub = (result?.verdictSub || '').trim();
    const rec = (result?.recommendation || '').trim();

    const lines = ['Hey,', ''];
    lines.push(`I ran an expert diagnostic${expertLine} on WorkApp.ai and wanted to send it your way.`);
    lines.push('');
    if (headline) {
      lines.push('The verdict:');
      lines.push('');
      lines.push('"' + headline + '"');
      if (sub) { lines.push(''); lines.push(sub); }
      if (rec) { lines.push(''); lines.push('What to do about it → ' + rec); }
      lines.push('');
      lines.push('Full breakdown (with evidence + the rewrite suggestion):');
    } else {
      lines.push('The full result is here — worth 60 seconds:');
    }
    lines.push(fullUrl);
    lines.push('');
    lines.push('Anyone with the link can read it (no account needed). If you want to run the same diagnostic on your own work, you can do that right from the page.');
    lines.push('');
    lines.push('—');
    return lines.join('\n');
  })();

  // LinkedIn's `share-offsite` doesn't accept a text parameter, but the
  // feed-intent share URL does. Use it so we can pre-fill the post body
  // with our composed text. Falls back to share-offsite when no text yet.
  const linkedInHref = (() => {
    if (!fullUrl) return '#';
    if (linkedInText) {
      return 'https://www.linkedin.com/feed/?shareActive=true'
        + '&text=' + encodeURIComponent(linkedInText + '\n' + fullUrl)
        + '&url=' + encodeURIComponent(fullUrl);
    }
    return 'https://www.linkedin.com/sharing/share-offsite/?url=' + encodeURIComponent(fullUrl);
  })();

  const mailHref = (() => {
    if (!fullUrl) return '#';
    return 'mailto:?subject=' + encodeURIComponent(emailSubject)
      + '&body=' + encodeURIComponent(emailBody);
  })();

  const copy = () => {
    if (!fullUrl) return;
    navigator.clipboard?.writeText(fullUrl).catch(() => {});
    setCopied(true);
    onToast && onToast('Link copied');
    setTimeout(() => setCopied(false), 2000);
  };
  return (
    <Modal open={open} onClose={onClose}>
      <h3>Share this result</h3>
      <p>Copy a public result link for a founder, teammate, advisor, or client. Anyone with the link can read the result without an account.</p>
      <div className="share-option-label">Public result link</div>
      <div className="share-link-row">
        <code>{err ? `Error: ${err}` : (url ? fullUrl : 'Generating link…')}</code>
        <button type="button" className="btn btn-ink btn-sm" onClick={copy} disabled={!fullUrl}>
          {copied ? <><Icon.CheckSm /> Copied</> : <><Icon.Copy className="icon-sm" /> Copy</>}
        </button>
      </div>
      <div style={{display: 'flex', gap: 8, marginTop: 16}}>
        <a
          className="btn btn-ghost btn-sm"
          style={{flex: 1, justifyContent: 'center', pointerEvents: fullUrl ? 'auto' : 'none', opacity: fullUrl ? 1 : 0.5}}
          target="_blank" rel="noopener noreferrer"
          href={linkedInHref}
        >
          <Icon.LinkedIn /> Share on LinkedIn
        </a>
        <a
          className="btn btn-ghost btn-sm"
          style={{flex: 1, justifyContent: 'center', pointerEvents: fullUrl ? 'auto' : 'none', opacity: fullUrl ? 1 : 0.5}}
          href={mailHref}
        >
          <Icon.Mail /> Email
        </a>
      </div>
      <div style={{marginTop: 20, paddingTop: 18, borderTop: '1px solid var(--hair)', fontSize: 13, color: 'var(--muted)'}}>
        {signedIn ? (
          <span style={{display: 'flex', alignItems: 'center', gap: 6}}>
            <Icon.CheckSm /> Private link — only people with this link can view.
          </span>
        ) : (
          <span style={{display: 'flex', alignItems: 'center', gap: 6}}>
            <button type="button" className="btn-bare" style={{padding: 0, color: 'var(--accent)'}} onClick={onSignIn}>Sign in</button> to create a revocable private link.
          </span>
        )}
      </div>
    </Modal>
  );
}

// ── Toast ────────────────────────────────────────────────────────────
function Toast({ message }) {
  if (!message) return null;
  return <div className="toast" role="status" aria-live="polite">{message}</div>;
}

// ── Footer ───────────────────────────────────────────────────────────
function Footer() {
  return (
    <footer className="foot">
      <div className="foot-inner">
        <div>WorkApp.ai · Expertise you can run.</div>
        <div style={{display: 'flex', gap: 18}}>
          <a href="#/about" style={{color: 'var(--muted)', textDecoration: 'none'}}>About</a>
          <a href="#/privacy" style={{color: 'var(--muted)', textDecoration: 'none'}}>Privacy</a>
          <a href="#/terms" style={{color: 'var(--muted)', textDecoration: 'none'}}>Terms</a>
          <a href="#/become" style={{color: 'var(--muted)', textDecoration: 'none'}}>For Experts</a>
        </div>
      </div>
    </footer>
  );
}

Object.assign(window, { Nav, ExpertChip, WorkAppCard, Modal, SignInModal, QualificationModal, ShareModal, Toast, Footer });
