/* app.jsx — Resum3 shell: nav, routing, generate flow, tweaks */
(function () {
  const { useState, useEffect, useRef } = React;
  const Icon = window.Icon;

  const GEN_STEPS = [
    'Parsing your resume…',
    'Reading the job description…',
    'Matching ATS keywords…',
    'Building keyword evidence map…',
    'Tailoring wording to the role…',
    'Flagging claims that need review…',
    'Scoring your fit…',
  ];

  function GenOverlay({ onDone }) {
    const [step, setStep] = useState(0);
    useEffect(() => {
      let i = 0;
      const id = setInterval(() => {
        i += 1;
        if (i >= GEN_STEPS.length) { clearInterval(id); setTimeout(onDone, 480); }
        setStep(i);
      }, 520);
      return () => clearInterval(id);
    }, []);
    const pct = Math.min(100, Math.round((step / GEN_STEPS.length) * 100));
    return React.createElement('div', { className: 'gen-overlay' },
      React.createElement('div', { className: 'gen-card' },
        React.createElement('div', { className: 'gen-orb' }, React.createElement(Icon.sparkle, null)),
        React.createElement('div', { className: 'gen-title' }, 'Tailoring your application'),
        React.createElement('div', { className: 'gen-step' }, GEN_STEPS[Math.min(step, GEN_STEPS.length - 1)]),
        React.createElement('div', { className: 'gen-bar' }, React.createElement('div', { style: { width: pct + '%' } })),
        React.createElement('div', { className: 'gen-steps' },
          GEN_STEPS.map((s, i) => React.createElement('div', {
            key: i, className: 'gen-li' + (i < step ? ' done' : i === step ? ' active' : '') },
            React.createElement('div', { className: 'tick' }, i < step && React.createElement(Icon.check, null)),
            s.replace('…', ''))),
        ),
      ),
    );
  }

  function Nav({ route, go, credits, account, onAccount }) {
    const links = [
      { id: 'workspace', label: 'Dashboard' },
      { id: 'history', label: 'History' },
      { id: 'pricing', label: 'Pricing' },
    ];
    return React.createElement('header', { className: 'nav' },
      React.createElement('div', { className: 'wrap nav-inner' },
        React.createElement('div', { className: 'brand', onClick: () => go('workspace'), style: { cursor: 'pointer' } },
          React.createElement('div', { className: 'brand-mark' }, React.createElement(Icon.bolt, { fill: 'currentColor' })),
          React.createElement('span', null, 'Resum', React.createElement('b', null, '3')),
        ),
        React.createElement('nav', { className: 'nav-links' },
          links.map((l) => React.createElement('button', {
            key: l.id,
            className: 'nav-link' + ((route === l.id || (l.id === 'workspace' && route === 'results')) ? ' active' : ''),
            onClick: () => go(l.id),
          }, l.label)),
        ),
        React.createElement('div', { className: 'nav-right' },
          React.createElement('div', { className: 'credits' + (credits <= 2 ? ' low' : '') },
            React.createElement('span', { className: 'dot' }),
            account && account.isPro
              ? React.createElement(React.Fragment, null, React.createElement('b', null, 'Pro'), ' active')
              : credits > 0
                ? React.createElement(React.Fragment, null, React.createElement('b', null, credits), credits === 1 ? ' packet left' : ' packets left')
                : React.createElement(React.Fragment, null, React.createElement('b', null, '$5'), ' or Pro')),
          React.createElement('button', { className: 'avatar', title: account?.email || 'Account', onClick: onAccount },
            account?.email ? account.email.slice(0, 2).toUpperCase() : 'ME'),
        ),
      ),
    );
  }

  function AccountModal({ open, email, setEmail, password, setPassword, onSave, onClose }) {
    if (!open) return null;
    return React.createElement('div', { className: 'overlay', onClick: onClose },
      React.createElement('div', { className: 'account-modal card', onClick: (e) => e.stopPropagation() },
        React.createElement('button', { className: 'modal-close', onClick: onClose }, React.createElement(Icon.x, null)),
        React.createElement('div', { className: 'modal-badge' }, React.createElement(Icon.lock, null), 'Website account'),
        React.createElement('h2', { className: 'modal-title' }, 'Create your Resum3 account'),
        React.createElement('p', { className: 'modal-sub' }, 'Add an email and password so your one-time packets and Pro access stay connected to your account.'),
        React.createElement('label', { className: 'account-label' }, 'Email address'),
        React.createElement('input', {
          className: 'account-input',
          type: 'email',
          value: email,
          onChange: (e) => setEmail(e.target.value),
          placeholder: 'you@example.com',
          autoFocus: true,
        }),
        React.createElement('label', { className: 'account-label' }, 'Create password'),
        React.createElement('input', {
          className: 'account-input',
          type: 'password',
          value: password,
          onChange: (e) => setPassword(e.target.value),
          placeholder: 'At least 8 characters',
        }),
        React.createElement('button', { className: 'btn btn-primary btn-lg btn-block', onClick: onSave },
          React.createElement(Icon.check, null), 'Create account / sign in'),
      ),
    );
  }

  function planLabel(account) {
    if (!account) return 'No account connected';
    if (account.isPro) return 'Resum3 Pro monthly';
    if ((account.oneTimeCredits || 0) > 0) {
      return `${account.oneTimeCredits} single application ${account.oneTimeCredits === 1 ? 'packet' : 'packets'}`;
    }
    return 'Free account';
  }

  function ProfileModal({ open, account, currentPassword, setCurrentPassword, newPassword, setNewPassword, saving, onChangePassword, onClose }) {
    if (!open || !account) return null;
    return React.createElement('div', { className: 'overlay', onClick: onClose },
      React.createElement('div', { className: 'account-modal profile-modal card', onClick: (e) => e.stopPropagation() },
        React.createElement('button', { className: 'modal-close', onClick: onClose }, React.createElement(Icon.x, null)),
        React.createElement('div', { className: 'modal-badge' }, React.createElement(Icon.lock, null), 'Your profile'),
        React.createElement('h2', { className: 'modal-title' }, 'Account details'),
        React.createElement('p', { className: 'modal-sub' }, 'View the email and plan connected to this Resum3 account.'),
        React.createElement('div', { className: 'profile-summary' },
          React.createElement('div', { className: 'profile-row' },
            React.createElement('span', null, 'Email'),
            React.createElement('b', null, account.email)),
          React.createElement('div', { className: 'profile-row' },
            React.createElement('span', null, 'Current plan'),
            React.createElement('b', null, planLabel(account))),
        ),
        React.createElement('div', { className: 'profile-password' },
          React.createElement('div', { className: 'profile-section-title' },
            React.createElement(Icon.lock, null),
            React.createElement('span', null, 'Change password')),
          React.createElement('label', { className: 'account-label' }, 'Current password'),
          React.createElement('input', {
            className: 'account-input',
            type: 'password',
            value: currentPassword,
            onChange: (e) => setCurrentPassword(e.target.value),
            placeholder: 'Enter current password',
            autoComplete: 'current-password',
          }),
          React.createElement('label', { className: 'account-label' }, 'New password'),
          React.createElement('input', {
            className: 'account-input',
            type: 'password',
            value: newPassword,
            onChange: (e) => setNewPassword(e.target.value),
            placeholder: 'At least 8 characters',
            autoComplete: 'new-password',
          }),
          React.createElement('button', { className: 'btn btn-primary btn-lg btn-block', onClick: onChangePassword, disabled: saving },
            React.createElement(Icon.check, null), saving ? 'Updating password...' : 'Update password'),
        ),
      ),
    );
  }

  const ACCENTS = ['#0f9d6e', '#2f6df0', '#7257e6', '#e0723a', '#475569'];

  function PublicFooter() {
    return React.createElement('footer', { className: 'public-footer' },
      React.createElement('div', { className: 'wrap footer-inner' },
        React.createElement('div', null,
          React.createElement('b', null, 'Resum3'),
          React.createElement('span', null, 'AI resume tailoring for real job applications.'),
        ),
        React.createElement('div', { className: 'footer-links' },
          React.createElement('a', { href: '/privacy', target: '_blank', rel: 'noreferrer' }, 'Privacy'),
          React.createElement('a', { href: '/terms', target: '_blank', rel: 'noreferrer' }, 'Terms of Service'),
          React.createElement('a', { href: 'mailto:joshpaul6506@gmail.com?subject=Resum3%20support' }, 'Contact'),
        ),
      ),
    );
  }

  function applyGeneratedData(data) {
    if (!data || data.demo) return;
    const atsScore = Math.max(0, Math.min(99, Number(data.ats_score) || 0));
    const mapped = {
      MATCHED: data.matched_keywords || window.DATA.MATCHED,
      MISSING: data.missing_keywords || window.DATA.MISSING,
      EVIDENCE_MAP: data.keyword_evidence_map || window.DATA.EVIDENCE_MAP,
      MISSING_EXPERIENCE: data.missing_experience_questions || window.DATA.MISSING_EXPERIENCE,
      RECRUITER_SKIM: data.recruiter_skim || window.DATA.RECRUITER_SKIM,
      APPLICATION_CONFIDENCE: data.application_confidence || buildConfidenceFromScore(atsScore, data),
      INTERVIEW_PREP: data.interview_prep || window.DATA.INTERVIEW_PREP,
      COVER_LETTER: data.cover_letter || window.DATA.COVER_LETTER,
      TAILORED_RESUME: data.tailored_resume || window.DATA.TAILORED_RESUME,
    };
    window.DATA = Object.assign({}, window.DATA, mapped);
    if (data.ats_score) {
      window.DATA.SCORE_BREAKDOWN = window.DATA.SCORE_BREAKDOWN.map((item) =>
        item.label === 'Skills Match' ? Object.assign({}, item, { score: atsScore }) : item
      );
    }
  }

  function buildConfidenceFromScore(score, data = {}) {
    const missingCount = (data.missing_keywords || window.DATA.MISSING || []).length;
    if (score >= 78) {
      return {
        label: 'Apply',
        score,
        summary: 'This is strong enough to apply now, with a few targeted fixes before sending.',
        reasons: ['Core role keywords are supported', 'Tailored materials are ready to review', missingCount ? `${missingCount} gaps should be checked first` : 'No major keyword gaps found'],
        nextStep: 'Review unsupported claims, then download the final packet.',
      };
    }
    if (score >= 58) {
      return {
        label: 'Improve',
        score,
        summary: 'This can become competitive, but it needs a few fixes before you send it.',
        reasons: ['Some important keywords are missing', 'Evidence needs tightening', 'The recruiter skim may raise questions'],
        nextStep: 'Answer the missing-experience questions and strengthen the top resume bullets.',
      };
    }
    return {
      label: 'Risky',
      score,
      summary: 'This application is likely to underperform unless you can add truthful supporting evidence.',
      reasons: ['Several role requirements are not supported', 'Important keywords are missing', 'The resume may read like a stretch for this posting'],
      nextStep: 'Use this as a gap analysis before applying.',
    };
  }

  function downloadFile(filename, content, type = 'text/plain') {
    const blob = new Blob([content], { type });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = filename;
    document.body.appendChild(a);
    a.click();
    a.remove();
    URL.revokeObjectURL(url);
  }

  function buildApplicationPacket() {
    const D = window.DATA;
    const evidence = (D.EVIDENCE_MAP || []).map((item) =>
      `- ${item.keyword}: ${item.status} (${item.confidence})\n  Job: ${item.jobEvidence}\n  Resume: ${item.resumeEvidence}\n  Action: ${item.action}`
    ).join('\n');
    const prep = D.INTERVIEW_PREP || {};
    return [
      'RESUM3 APPLICATION PACKET',
      '',
      'TAILORED RESUME',
      D.TAILORED_RESUME || D.SAMPLE_RESUME,
      '',
      'COVER LETTER',
      D.COVER_LETTER,
      '',
      'KEYWORD EVIDENCE MAP',
      evidence,
      '',
      'INTERVIEW PREP',
      prep.tellMe || '',
      '',
      ...(prep.talkingPoints || []).map((p) => '- ' + p),
    ].join('\n');
  }

  function ChatAssistant({ onToast }) {
    const [open, setOpen] = useState(false);
    const [input, setInput] = useState('');
    const [busy, setBusy] = useState(false);
    const [messages, setMessages] = useState([
      {
        role: 'assistant',
        content: 'Hi, I can help with Resum3, resumes, cover letters, ATS keywords, checkout, and using the site.',
      },
    ]);
    const listRef = useRef(null);

    useEffect(() => {
      if (open && listRef.current) {
        listRef.current.scrollTop = listRef.current.scrollHeight;
      }
    }, [open, messages, busy]);

    const ask = async (text) => {
      const clean = String(text || input).trim();
      if (!clean || busy) return;
      const next = messages.concat({ role: 'user', content: clean });
      setMessages(next);
      setInput('');
      setBusy(true);
      try {
        const response = await fetch('/api/chat', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ messages: next }),
        });
        const data = await response.json();
        if (!response.ok) throw new Error(data.error || 'Assistant could not reply.');
        setMessages(next.concat({ role: 'assistant', content: data.reply }));
      } catch (error) {
        onToast(error.message || 'Assistant could not reply.', 'x');
        setMessages(next.concat({ role: 'assistant', content: 'I had trouble replying. Please try again in a moment.' }));
      } finally {
        setBusy(false);
      }
    };

    const quick = [
      'How do I use Resum3?',
      'Why do I need to pay first?',
      'Help me improve my resume summary.',
    ];

    return React.createElement('div', { className: 'chat' + (open ? ' open' : '') },
      open && React.createElement('div', { className: 'chat-panel card' },
        React.createElement('div', { className: 'chat-head' },
          React.createElement('div', { className: 'chat-title' },
            React.createElement('div', { className: 'chat-mark' }, React.createElement(Icon.sparkle, null)),
            React.createElement('div', null,
              React.createElement('b', null, 'Resum3 Assistant'),
              React.createElement('span', null, 'Ask about resumes, ATS, payment, or the site'),
            ),
          ),
          React.createElement('button', { className: 'chat-close', onClick: () => setOpen(false), 'aria-label': 'Close assistant' }, React.createElement(Icon.x, null)),
        ),
        React.createElement('a', { className: 'chat-support', href: 'mailto:joshpaul6506@gmail.com?subject=Resum3%20support' },
          'Need direct help? Email joshpaul6506@gmail.com'),
        React.createElement('div', { className: 'chat-list', ref: listRef },
          messages.map((msg, i) => React.createElement('div', { key: i, className: 'chat-msg ' + msg.role }, msg.content)),
          busy && React.createElement('div', { className: 'chat-msg assistant typing' }, 'Thinking...'),
        ),
        React.createElement('div', { className: 'chat-quick' },
          quick.map((q) => React.createElement('button', { key: q, onClick: () => ask(q), disabled: busy }, q)),
        ),
        React.createElement('form', { className: 'chat-form', onSubmit: (e) => { e.preventDefault(); ask(); } },
          React.createElement('input', {
            value: input,
            onChange: (e) => setInput(e.target.value),
            placeholder: 'Ask anything about Resum3...',
            maxLength: 700,
          }),
          React.createElement('button', { className: 'btn btn-primary btn-sm', disabled: busy || !input.trim() }, React.createElement(Icon.arrowRight, null)),
        ),
      ),
      React.createElement('button', { className: 'chat-fab', onClick: () => setOpen((v) => !v), 'aria-label': 'Open assistant' },
        open ? React.createElement(Icon.x, null) : React.createElement(Icon.sparkle, null),
      ),
    );
  }

  function App() {
    const { useTweaks, TweaksPanel, TweakSection, TweakColor, TweakRadio, TweakSlider, TweakToggle } = window;
    const urlParams = new URLSearchParams(window.location.search);
    const demoMode = urlParams.get('demo') === '1';
    const viewParam = urlParams.get('view');
    const initialRoute = ['results', 'history'].includes(viewParam) ? viewParam : 'workspace';
    const initialPaywall = viewParam === 'pricing';
    const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
      accent: '#0f9d6e',
      dark: false,
      density: 'regular',
      radius: 18,
      font: 'grotesque',
    }/*EDITMODE-END*/;
    const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);

    const [route, setRoute] = useState(initialRoute);
    const [resume, setResume] = useState(demoMode ? window.DATA.SAMPLE_RESUME : '');
    const [jd, setJd] = useState(demoMode ? window.DATA.SAMPLE_JD : '');
    const [mode, setMode] = useState('full');
    const [trustMode, setTrustMode] = useState('balanced');
    const [generating, setGenerating] = useState(false);
    const [overlayDone, setOverlayDone] = useState(false);
    const [generationResult, setGenerationResult] = useState(null);
    const [credits, setCredits] = useState(0);
    const [account, setAccount] = useState(null);
    const [email, setEmail] = useState(localStorage.getItem('tailorcv_email') || '');
    const [password, setPassword] = useState('');
    const [sessionToken, setSessionToken] = useState(localStorage.getItem('tailorcv_token') || '');
    const [accountOpen, setAccountOpen] = useState(false);
    const [profileOpen, setProfileOpen] = useState(false);
    const [currentPassword, setCurrentPassword] = useState('');
    const [newPassword, setNewPassword] = useState('');
    const [savingPassword, setSavingPassword] = useState(false);
    const [unlocked, setUnlocked] = useState(false);
    const [paywall, setPaywall] = useState(initialPaywall);
    const [toast, setToast] = useState(null);

    const showToast = (msg, icon) => {
      const id = Date.now();
      setToast({ id, msg, icon });
      setTimeout(() => setToast((cur) => (cur && cur.id === id ? null : cur)), 2400);
    };

    const go = (r) => {
      if (r === 'pricing') { setPaywall(true); return; }
      setRoute(r);
      window.scrollTo({ top: 0, behavior: 'smooth' });
    };

    const syncAccount = async (nextEmail = email, nextPassword = password) => {
      const clean = String(nextEmail || '').trim().toLowerCase();
      if (!clean || !clean.includes('@')) {
        setAccountOpen(true);
        showToast('Enter a valid email to continue.', 'x');
        return null;
      }
      if (!nextPassword || nextPassword.length < 8) {
        setAccountOpen(true);
        showToast('Enter a password with at least 8 characters.', 'x');
        return null;
      }
      const response = await fetch('/api/session', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ email: clean, password: nextPassword }),
      });
      const data = await response.json();
      if (!response.ok) throw new Error(data.error || 'Could not load account.');
      localStorage.setItem('tailorcv_email', clean);
      localStorage.setItem('tailorcv_token', data.token);
      setEmail(clean);
      setSessionToken(data.token);
      setAccount(data.user);
      setCredits(data.user.credits);
      setUnlocked(data.user.isPro || data.user.oneTimeCredits > 0);
      return { user: data.user, token: data.token };
    };

    useEffect(() => {
      if (!sessionToken) {
        setAccountOpen(true);
        return;
      }
      fetch('/api/user?token=' + encodeURIComponent(sessionToken))
        .then((response) => response.json().then((data) => ({ response, data })))
        .then(({ response, data }) => {
          if (!response.ok) throw new Error(data.error || 'Please sign in again.');
          setAccount(data.user);
          setCredits(data.user.credits);
          setUnlocked(data.user.isPro || data.user.oneTimeCredits > 0);
        })
        .catch(() => {
          localStorage.removeItem('tailorcv_token');
          setSessionToken('');
          setAccountOpen(true);
        });
    }, []);

    useEffect(() => {
      const checkout = urlParams.get('checkout');
      const sessionId = urlParams.get('session_id');
      if (checkout === 'success') {
        if (!sessionId) {
          showToast('Checkout returned without a session ID.', 'x');
          window.history.replaceState({}, '', window.location.pathname);
          return;
        }
        fetch('/api/checkout-session?session_id=' + encodeURIComponent(sessionId))
          .then((response) => response.json().then((data) => ({ response, data })))
          .then(({ response, data }) => {
            if (!response.ok || !data.paid) throw new Error(data.error || 'Checkout could not be verified.');
            if (data.user) {
              setAccount(data.user);
              setCredits(data.user.credits);
            }
            setUnlocked(data.user?.isPro || data.plan === 'once');
            showToast('Payment complete. Resum3 is unlocked on this browser.', 'checkCircle');
          })
          .catch((error) => showToast(error.message || 'Checkout could not be verified.', 'x'));
        window.history.replaceState({}, '', window.location.pathname);
      }
      if (checkout === 'cancelled') {
        showToast('Checkout cancelled. No payment was taken.', 'x');
        window.history.replaceState({}, '', window.location.pathname);
      }
    }, []);

    useEffect(() => {
      if (!generating || !overlayDone || !generationResult) return;
      setGenerating(false);
      setOverlayDone(false);
      if (generationResult.error) {
        showToast(generationResult.error, 'x');
        return;
      }
      applyGeneratedData(generationResult);
      if (generationResult.user) {
        setAccount(generationResult.user);
        setCredits(generationResult.user.credits);
        setUnlocked(generationResult.user.isPro || generationResult.user.oneTimeCredits > 0);
      }
      if (generationResult.warning) showToast(generationResult.warning, 'checkCircle');
      setRoute('results');
      window.scrollTo({ top: 0 });
    }, [generating, overlayDone, generationResult]);

    const onGenerate = async () => {
      let activeAccount = account;
      let activeToken = sessionToken || localStorage.getItem('tailorcv_token') || '';
      if (!activeAccount) {
        setAccountOpen(true);
        showToast('Create an account or sign in before using Resum3 AI.', 'lock');
        return;
      }
      if (!activeAccount) return;
      if (!activeAccount.isPro && activeAccount.oneTimeCredits <= 0) { setPaywall(true); return; }
      setGenerationResult(null);
      setOverlayDone(false);
      setGenerating(true);
      try {
        const response = await fetch('/api/generate', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ resume, jobDescription: jd, mode, trustMode, token: activeToken }),
        });
        const data = await response.json();
        if (!response.ok) throw new Error(data.error || 'Generation failed.');
        setGenerationResult(data);
      } catch (error) {
        setGenerationResult({ error: error.message || 'Generation failed.' });
      }
    };
    const onClear = () => { setResume(''); setJd(''); showToast('Inputs cleared', 'trash'); };

    const onDownload = (kind) => {
      if (!account || !unlocked) { setPaywall(true); return; }
      const safeDate = new Date().toISOString().slice(0, 10);
      if (kind === 'PDF') {
        downloadFile(`resum3-resume-${safeDate}.txt`, window.DATA.TAILORED_RESUME || window.DATA.SAMPLE_RESUME);
      } else if (kind === 'DOCX') {
        downloadFile(`resum3-resume-${safeDate}.html`, `<pre>${(window.DATA.TAILORED_RESUME || window.DATA.SAMPLE_RESUME).replace(/[&<>]/g, (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;' }[c]))}</pre>`, 'text/html');
      } else {
        downloadFile(`resum3-application-packet-${safeDate}.txt`, buildApplicationPacket());
      }
      showToast(kind === 'all' ? 'Downloaded full application packet' : 'Downloaded ' + kind, 'download');
    };
    const onConfirm = async (planId) => {
      try {
        let activeToken = sessionToken || localStorage.getItem('tailorcv_token') || '';
        let activeAccount = account;
        if (!activeAccount) {
          setAccountOpen(true);
          showToast('Create an account or sign in before choosing a plan.', 'lock');
          return;
        }
        if (!activeAccount) return;
        const response = await fetch('/api/create-checkout-session', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ plan: planId, token: activeToken }),
        });
        const data = await response.json();
        if (!response.ok) throw new Error(data.error || 'Checkout is not configured.');
        if (data.url) {
          window.location.href = data.url;
          return;
        }
        throw new Error(data.error || 'Checkout is not configured.');
      } catch (error) {
        showToast(error.message, 'x');
      }
    };

    const onChangePassword = async () => {
      const activeToken = sessionToken || localStorage.getItem('tailorcv_token') || '';
      if (!activeToken) {
        setProfileOpen(false);
        setAccountOpen(true);
        showToast('Sign in again before changing your password.', 'x');
        return;
      }
      if (!currentPassword || newPassword.length < 8) {
        showToast('Enter your current password and a new password with at least 8 characters.', 'x');
        return;
      }
      setSavingPassword(true);
      try {
        const response = await fetch('/api/change-password', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ token: activeToken, currentPassword, newPassword }),
        });
        const data = await response.json();
        if (!response.ok) throw new Error(data.error || 'Could not update password.');
        localStorage.setItem('tailorcv_token', data.token);
        setSessionToken(data.token);
        setAccount(data.user);
        setCurrentPassword('');
        setNewPassword('');
        showToast('Password updated.', 'checkCircle');
      } catch (error) {
        showToast(error.message, 'x');
      } finally {
        setSavingPassword(false);
      }
    };

    const rootStyle = {
      '--accent': t.accent,
      '--radius': (t.radius || 18) + 'px',
    };

    return React.createElement('div', {
      className: 'app', style: rootStyle,
      'data-theme': t.dark ? 'dark' : 'light',
      'data-density': t.density,
      'data-font': t.font === 'grotesque' ? 'default' : t.font,
    },
      React.createElement(Nav, { route, go, credits, account, onAccount: () => account ? setProfileOpen(true) : setAccountOpen(true) }),

      route === 'workspace' && React.createElement(window.Workspace, {
        resume, setResume, jd, setJd, mode, setMode, onGenerate, onClear, trustMode, setTrustMode }),
      route === 'results' && React.createElement(window.Results, {
        mode, trustMode, onBack: () => go('workspace'), onDownload, onToast: showToast }),
      route === 'history' && React.createElement(window.History, {
        onView: () => go('workspace'), onToast: showToast }),

      generating && React.createElement(GenOverlay, { onDone: () => setOverlayDone(true) }),
      React.createElement(window.Paywall, { open: paywall, onClose: () => setPaywall(false), onConfirm }),
      React.createElement(AccountModal, {
        open: accountOpen,
        email,
        setEmail,
        password,
        setPassword,
        onClose: () => setAccountOpen(false),
        onSave: () => syncAccount(email, password).then(() => {
          setAccountOpen(false);
          showToast('Credits are now connected to your email.', 'checkCircle');
        }).catch((error) => showToast(error.message, 'x')),
      }),
      React.createElement(ProfileModal, {
        open: profileOpen,
        account,
        currentPassword,
        setCurrentPassword,
        newPassword,
        setNewPassword,
        saving: savingPassword,
        onChangePassword,
        onClose: () => setProfileOpen(false),
      }),
      React.createElement(PublicFooter, null),
      React.createElement(ChatAssistant, { onToast: showToast }),
      React.createElement(window.UI.Toast, { toast }),

      React.createElement(TweaksPanel, null,
        React.createElement(TweakSection, { label: 'Accent' }),
        React.createElement(TweakColor, { label: 'Accent color', value: t.accent, options: ACCENTS, onChange: (v) => setTweak('accent', v) }),
        React.createElement(TweakSection, { label: 'Theme' }),
        React.createElement(TweakToggle, { label: 'Dark mode', value: t.dark, onChange: (v) => setTweak('dark', v) }),
        React.createElement(TweakRadio, { label: 'Type', value: t.font, options: ['grotesque', 'humanist', 'editorial'], onChange: (v) => setTweak('font', v) }),
        React.createElement(TweakSection, { label: 'Layout' }),
        React.createElement(TweakRadio, { label: 'Density', value: t.density, options: ['compact', 'regular', 'comfy'], onChange: (v) => setTweak('density', v) }),
        React.createElement(TweakSlider, { label: 'Roundness', value: t.radius, min: 6, max: 26, unit: 'px', onChange: (v) => setTweak('radius', v) }),
      ),
    );
  }

  window.App = App;
})();
