// onboard-step-work.jsx — Wizard Step 2 (rich company context).
//
// R03 / T0007. We capture the structured fields the wizard + downstream
// agents need to do useful work: website + links + stage + founders +
// employees + HQ + mission + products + target buyers.
//
// Most of these can be auto-filled by clicking "Learn from my website",
// which calls the `learnAboutWorkspace` Cloud Function — a Gemini agent
// with Google Search grounding that reads the website (+ optional
// LinkedIn / Crunchbase / GitHub / Twitter / Companies House / pasted
// context) and proposes values. The user reviews + edits before saving.
//
// Persists to `workspaces/{wid}` + materialises each detected product
// as a `workspaces/{wid}/products/{slug}` doc. Exposes window.StepWork.

(function (window) {
  'use strict';

  const { useAuth, db } = window.exoteamAuth || {};
  if (!useAuth) {
    console.error('onboard-step-work.jsx: window.exoteamAuth missing');
    return;
  }

  const STAGES = [
    { v: '', label: '— pick one —' },
    { v: 'idea', label: 'Idea / pre-product' },
    { v: 'pre-launch', label: 'Pre-launch' },
    { v: 'pre-revenue', label: 'Pre-revenue (live, no customers yet)' },
    { v: 'early-revenue', label: 'Early revenue' },
    { v: 'scaling', label: 'Scaling' },
    { v: 'mature', label: 'Mature / established' },
  ];

  function StepWork({ navigate, onBack }) {
    const { user } = useAuth();
    const [workspaceId, setWorkspaceId] = React.useState(null);
    const [saving, setSaving] = React.useState(false);
    const [learning, setLearning] = React.useState(false);
    const [error, setError] = React.useState(null);
    const [enrichmentNote, setEnrichmentNote] = React.useState(null);
    const [showAdvanced, setShowAdvanced] = React.useState(false);
    // Number of documents that count toward "we have something to learn
    // from". Two sources combine into `uploadCount`:
    //  - existingUploadCount: docs already in the workspace's content/
    //    subcollection (returning user mid-onboarding).
    //  - sessionUploadCount: docs uploaded in *this* DropZone instance.
    // The button gates on URL || uploadCount > 0.
    const [existingUploadCount, setExistingUploadCount] = React.useState(0);
    const [sessionUploadCount, setSessionUploadCount] = React.useState(0);
    const uploadCount = existingUploadCount + sessionUploadCount;

    // Form state
    const [form, setForm] = React.useState({
      display_name: '',
      website_url: '',
      linkedin_url: '',
      crunchbase_url: '',
      github_url: '',
      twitter_url: '',
      companies_house_number: '',
      industry: '',
      stage: '',
      founders_count: '',
      employees_count: '',
      hq_city: '',
      hq_country: '',
      mission: '',
      value_proposition: '',
      main_products: '',  // textarea, parsed to array on save
      target_buyers: '',  // textarea, parsed to array on save
      extra_context: '',  // not persisted; only used for enrichment call
      // R10 Sprint 2 — how the company gets paid. Surfaces as a picker
      // on the work step; feeds outreach cadence + proposal templates.
      revenue_model: '',  // 'subscription' | 'project' | 'commission' | 'grant' | 'donation' | 'goods' | 'mixed' | ''
      // R10T14 — optional workspace-level brand voice (overrides per-user
      // voice when drafting AS the brand: grant applications, public
      // copy). Per-user voice still wins for outreach DMs.
      brand_voice: '',  // textarea, parsed to brand_voice_samples[]
    });
    // R10T01 — org_kind inferred by enrichment; user can correct via
    // confirm chip after Learn.
    const [orgKind, setOrgKind] = React.useState('');
    const [orgKindConfidence, setOrgKindConfidence] = React.useState(null);
    const [orgKindPickerOpen, setOrgKindPickerOpen] = React.useState(false);
    const [openQuestions, setOpenQuestions] = React.useState([]);
    // Per-question draft + per-question save state for the inline
    // answer UI. Answers are persisted as `decisions/{slug}` spine
    // entities via `recordDecisionFromOpenQuestion`. Once enough are
    // saved the user can click "Refine" to re-prompt Gemini with the
    // new decisions in context.
    const [questionDrafts, setQuestionDrafts] = React.useState({});
    const [savingQuestion, setSavingQuestion] = React.useState(null);
    const [savedQuestions, setSavedQuestions] = React.useState([]); // local-only display state
    const [questionError, setQuestionError] = React.useState({});
    const [refining, setRefining] = React.useState(false);
    const [refineError, setRefineError] = React.useState(null);
    const [refineToast, setRefineToast] = React.useState(null);
    const [citations, setCitations] = React.useState([]);
    // R10 v2 — track which fields were pre-filled by the Learn call so
    // we can render a small "✨ inferred" chip next to them. Editing a
    // field clears the chip (the value is now user-typed). Learn only
    // marks a field as inferred if it returned a NON-EMPTY value —
    // low-confidence fields stay empty rather than being hallucinated.
    const [prefilledFields, setPrefilledFields] = React.useState(() => new Set());

    function update(field, value) {
      setForm((prev) => ({ ...prev, [field]: value }));
      // User edited — drop the inferred chip for this field.
      setPrefilledFields((prev) => {
        if (!prev.has(field)) return prev;
        const next = new Set(prev);
        next.delete(field);
        return next;
      });
    }

    // Small "✨ inferred" pill, mounted inline next to field labels.
    function InferredChip({ field }) {
      if (!prefilledFields.has(field)) return null;
      return (
        <span
          style={{
            display: 'inline-block', marginLeft: 8,
            fontSize: 10.5, fontWeight: 500,
            padding: '1px 7px', borderRadius: 999,
            background: 'rgba(91,141,239,0.10)',
            color: '#3a6ddb', verticalAlign: 'middle',
          }}
          title="Pre-filled from your site + uploaded docs. Edit to override."
        >
          ✨ inferred
        </span>
      );
    }

    // Resolve workspace id from membership.
    React.useEffect(() => {
      if (!user) return;
      db.collection('memberships')
        .where('user_id', '==', user.uid)
        .limit(1)
        .get()
        .then((snap) => {
          if (!snap.empty) setWorkspaceId(snap.docs[0].data().workspace_id);
        })
        .catch((err) => {
          console.error('StepWork: membership lookup failed', err);
          setError('Could not load your workspace.');
        });
    }, [user]);

    // Seed `existingUploadCount` from the workspace's content/
    // subcollection so returning users see the button enabled when
    // they already uploaded docs in a previous session.
    React.useEffect(() => {
      if (!workspaceId) return;
      db.collection('workspaces').doc(workspaceId)
        .collection('content')
        .where('medium', '==', 'uploaded-document')
        .where('status', '==', 'active')
        .get()
        .then((snap) => setExistingUploadCount(snap.size))
        .catch((err) => {
          // Non-fatal — the button just stays disabled until the user
          // adds a URL or a fresh upload. Log so we can spot rule issues.
          console.warn('StepWork: content count query failed', err);
        });
    }, [workspaceId]);

    // The four list fields (main_products, target_buyers, competitors,
    // collaborators) live in spine SUBCOLLECTIONS (products/, customers/,
    // competitors/, people/), not on the workspace doc. Read them
    // directly so the textareas show the actual persisted truth — not
    // just whatever the most recent enrichment-response happened to
    // return in its flat-string projection.
    React.useEffect(() => {
      if (!workspaceId) return;
      const wsRef = db.collection('workspaces').doc(workspaceId);
      const collect = (subPath) => wsRef.collection(subPath)
        .where('status', '==', 'active').get()
        .then((snap) => snap.docs
          .map((d) => (d.data() || {}).display_name)
          .filter((s) => typeof s === 'string' && s.trim()))
        .catch((err) => {
          console.warn(`StepWork: ${subPath} prefill failed`, err);
          return [];
        });
      Promise.all([
        collect('products'),
        collect('customers'),
        collect('competitors'),
        collect('people'),
      ]).then(([products, customers, competitors, people]) => {
        setForm((prev) => ({
          ...prev,
          // Only overwrite if (a) the field is currently blank AND (b)
          // we found something. Avoids stomping on user edits.
          main_products: prev.main_products || products.join('\n'),
          target_buyers: prev.target_buyers || customers.join('\n'),
          competitors:   prev.competitors   || competitors.join('\n'),
          collaborators: prev.collaborators || people.join('\n'),
        }));
      });
    }, [workspaceId]);

    // Prefill from workspace doc.
    React.useEffect(() => {
      if (!workspaceId) return;
      db.collection('workspaces')
        .doc(workspaceId)
        .get()
        .then((snap) => {
          if (!snap.exists) return;
          const d = snap.data() || {};
          setForm((prev) => ({
            ...prev,
            display_name: d.display_name || prev.display_name,
            website_url: d.website_url || prev.website_url,
            linkedin_url: d.linkedin_url || prev.linkedin_url,
            crunchbase_url: d.crunchbase_url || prev.crunchbase_url,
            github_url: d.github_url || prev.github_url,
            twitter_url: d.twitter_url || prev.twitter_url,
            companies_house_number: d.companies_house_number || prev.companies_house_number,
            industry: d.industry || prev.industry,
            stage: d.stage || prev.stage,
            founders_count: d.founders_count == null ? prev.founders_count : String(d.founders_count),
            employees_count: d.employees_count == null ? prev.employees_count : String(d.employees_count),
            hq_city: d.hq_city || prev.hq_city,
            hq_country: d.hq_country || prev.hq_country,
            mission: d.mission || prev.mission,
            value_proposition: d.value_proposition || prev.value_proposition,
            target_buyers: Array.isArray(d.target_buyers) && d.target_buyers.length
              ? d.target_buyers.join('\n')
              : prev.target_buyers,
            revenue_model: d.revenue_model || prev.revenue_model,
            brand_voice: prev.brand_voice
              || (Array.isArray(d.brand_voice_samples) ? d.brand_voice_samples.join('\n\n---\n\n') : ''),
          }));
          if (d.org_kind) {
            setOrgKind(d.org_kind);
            setOrgKindConfidence(d.org_kind_confidence || null);
          }
          if (d.enrichment && Array.isArray(d.enrichment.open_questions)) {
            setOpenQuestions(d.enrichment.open_questions);
          }
          if (d.enrichment && Array.isArray(d.enrichment.citations)) {
            setCitations(d.enrichment.citations);
          }
        })
        .catch((err) => console.error('StepWork: workspace prefill', err));
      // Pre-existing products (if any) populate the main_products textarea.
      db.collection('workspaces')
        .doc(workspaceId)
        .collection('products')
        .limit(20)
        .get()
        .then((snap) => {
          if (snap.empty) return;
          const names = snap.docs
            .map((d) => (d.data() || {}).display_name)
            .filter(Boolean);
          if (names.length) {
            setForm((prev) => ({
              ...prev,
              main_products: names.join('\n'),
            }));
          }
        })
        .catch((err) => console.error('StepWork: products prefill', err));
    }, [workspaceId]);

    async function saveAnswer(question) {
      const answer = (questionDrafts[question] || '').trim();
      if (!answer) {
        setQuestionError((e) => ({ ...e, [question]: 'Type an answer first.' }));
        return;
      }
      setSavingQuestion(question);
      setQuestionError((e) => ({ ...e, [question]: null }));
      try {
        const callable = window.exoteamAuth.fns.httpsCallable('recordDecisionFromOpenQuestion');
        await callable({ workspace_id: workspaceId, question, answer });
        // Mark locally-saved so the row collapses; the workspace
        // listener will re-read enrichment.open_questions[] shortly and
        // remove the question from the list. Until then, hide it
        // optimistically to give the user immediate feedback.
        setSavedQuestions((s) => s.includes(question) ? s : [...s, question]);
        setQuestionDrafts((d) => {
          const copy = { ...d };
          delete copy[question];
          return copy;
        });
      } catch (err) {
        console.error('StepWork: saveAnswer failed', err);
        let message = err.message || String(err);
        if (err.code === 'already-exists') {
          message = 'This question already has a saved decision.';
        }
        setQuestionError((e) => ({ ...e, [question]: message }));
      } finally {
        setSavingQuestion(null);
      }
    }

    async function refineEnrichment() {
      setRefining(true);
      setRefineError(null);
      setRefineToast(null);
      try {
        const callable = window.exoteamAuth.fns.httpsCallable('refineWorkspaceEnrichment');
        const { data } = await callable({ workspace_id: workspaceId });
        const remaining = Array.isArray(data && data.open_questions) ? data.open_questions.length : 0;
        setOpenQuestions(Array.isArray(data && data.open_questions) ? data.open_questions : []);
        // Pick up updated workspace fields too.
        if (data && data.workspace) {
          setForm((prev) => ({
            ...prev,
            mission: data.workspace.mission || prev.mission,
            industry: data.workspace.industry || prev.industry,
            stage: data.workspace.stage || prev.stage,
            value_proposition: data.workspace.value_proposition || prev.value_proposition,
          }));
        }
        setSavedQuestions([]); // Firestore truth is back; drop optimistic hides
        setRefineToast(`Refined. ${remaining} open question${remaining === 1 ? '' : 's'} remaining.`);
        setTimeout(() => setRefineToast(null), 6000);
      } catch (err) {
        console.error('StepWork: refine failed', err);
        setRefineError(err.message || String(err));
      } finally {
        setRefining(false);
      }
    }

    async function runEnrichment() {
      if (!form.website_url.trim() && uploadCount === 0) {
        setError("Add a website URL and/or upload at least one document (PDF, DOCX, TXT, MD) — the agent needs something to read.");
        return;
      }
      setLearning(true);
      setError(null);
      setEnrichmentNote('Reading your site + searching the web for context. This takes ~15-30s…');
      try {
        const callable = window.exoteamAuth.fns.httpsCallable('learnAboutWorkspace');
        const { data } = await callable({
          workspace_id: workspaceId,
          website_url: form.website_url.trim(),
          linkedin_url: form.linkedin_url.trim() || null,
          crunchbase_url: form.crunchbase_url.trim() || null,
          github_url: form.github_url.trim() || null,
          twitter_url: form.twitter_url.trim() || null,
          companies_house_number: form.companies_house_number.trim() || null,
          extra_context: form.extra_context.trim() || null,
        });
        const e = (data && data.enrichment) || {};
        // Track which fields got a non-empty value from Learn so we can
        // show the "✨ inferred" chip. Skip fields where Learn returned
        // null / empty — leaving them empty rather than fabricating a
        // value is the explicit "don't make things up" invariant.
        const inferred = new Set();
        setForm((prev) => {
          const next = { ...prev };
          const apply = (key, val) => {
            if (val == null || val === '' || (Array.isArray(val) && val.length === 0)) return;
            next[key] = Array.isArray(val) ? val.join('\n') : (typeof val === 'number' ? String(val) : val);
            inferred.add(key);
          };
          apply('display_name', e.display_name);
          apply('industry', e.industry);
          apply('stage', e.stage);
          apply('founders_count', e.founders_count);
          apply('employees_count', e.employees_count);
          apply('hq_city', e.hq_city);
          apply('hq_country', e.hq_country);
          apply('companies_house_number', e.companies_house_number);
          apply('mission', e.mission);
          apply('value_proposition', e.value_proposition);
          apply('main_products', e.main_products);
          apply('target_buyers', e.target_buyers);
          return next;
        });
        setPrefilledFields((prev) => {
          const merged = new Set(prev);
          for (const k of inferred) merged.add(k);
          return merged;
        });
        // R10T01 — classifier result. The chip appears once we have a
        // value; user can confirm or change.
        if (e.org_kind) {
          setOrgKind(e.org_kind);
          setOrgKindConfidence(e.org_kind_confidence || null);
        }
        setOpenQuestions(Array.isArray(e.open_questions) ? e.open_questions : []);
        setCitations(Array.isArray(e.citations) ? e.citations : []);
        const conf = e.confidence ? ` (confidence: ${e.confidence})` : '';
        setEnrichmentNote(
          `Pre-filled from ${(e.citations || []).length} sources${conf}. ` +
            'Review + edit anything that looks off, then Continue.',
        );
      } catch (err) {
        console.error('learnAboutWorkspace failed', err);
        setError(err.message || String(err));
        setEnrichmentNote(null);
      } finally {
        setLearning(false);
      }
    }

    function parseList(text) {
      if (!text) return [];
      return text
        .split(/[\n,]+/)
        .map((s) => s.trim())
        .filter(Boolean)
        .slice(0, 20);
    }

    function slugify(s) {
      return (s || '')
        .toLowerCase()
        .normalize('NFKD')
        .replace(/[̀-ͯ]/g, '')
        .replace(/[^a-z0-9]+/g, '-')
        .replace(/^-+|-+$/g, '')
        .slice(0, 40);
    }

    async function persistAndAdvance({ skipped }) {
      if (!workspaceId) return;
      setSaving(true);
      setError(null);
      try {
        const brand = form.display_name.trim();
        if (!skipped && !brand) {
          setError('Brand / company name is required, or click "Skip for now".');
          setSaving(false);
          return;
        }

        const products = parseList(form.main_products);
        const targetBuyers = parseList(form.target_buyers);

        const update = {
          display_name: brand || (skipped ? 'My company' : ''),
          website_url: form.website_url.trim() || null,
          linkedin_url: form.linkedin_url.trim() || null,
          crunchbase_url: form.crunchbase_url.trim() || null,
          github_url: form.github_url.trim() || null,
          twitter_url: form.twitter_url.trim() || null,
          companies_house_number: form.companies_house_number.trim() || null,
          industry: form.industry.trim() || null,
          stage: form.stage || null,
          founders_count: form.founders_count ? parseInt(form.founders_count, 10) || null : null,
          employees_count: form.employees_count ? parseInt(form.employees_count, 10) || null : null,
          hq_city: form.hq_city.trim() || null,
          hq_country: form.hq_country.trim() || null,
          mission: form.mission.trim() || null,
          value_proposition: form.value_proposition.trim() || null,
          target_buyers: targetBuyers,
          revenue_model: form.revenue_model || null,
          brand_voice_samples: (function () {
            const t = (form.brand_voice || '').trim();
            if (!t) return null;
            return t.split(/\n\s*-{3,}\s*\n|\n\n+/).map((s) => s.trim()).filter((s) => s.length >= 30).slice(0, 4);
          })(),
          onboarding: {
            current_step: 'icp',
            completed_steps: firebase.firestore.FieldValue.arrayUnion({
              step: 'work',
              skipped: !!skipped,
              at: firebase.firestore.Timestamp.now(),
            }),
            last_advanced_at: firebase.firestore.FieldValue.serverTimestamp(),
          },
        };

        const batch = db.batch();
        const wsRef = db.collection('workspaces').doc(workspaceId);
        batch.set(wsRef, update, { merge: true });

        // Materialise each product as a subcollection doc.
        for (const productName of products) {
          const slug = slugify(productName);
          if (!slug) continue;
          batch.set(
            wsRef.collection('products').doc(slug),
            {
              slug,
              display_name: productName,
              source: 'onboard-step-work',
              created_at: firebase.firestore.FieldValue.serverTimestamp(),
            },
            { merge: true },
          );
        }

        await batch.commit();
        // R10 v2 — six-slot wizard. Work step → Pair always; module-
        // specific setup (ICP / Funder / Audience) is now a native-app
        // inline panel (see R11 roadmap).
        navigate('pair');
      } catch (err) {
        console.error('StepWork: persist failed', err);
        setError(err.message || String(err));
      } finally {
        setSaving(false);
      }
    }

    if (!workspaceId) {
      return <p className="exo-auth-body">Loading your workspace…</p>;
    }

    const busy = saving || learning;

    return (
      <form
        className="exo-step exo-work-step"
        onSubmit={(e) => {
          e.preventDefault();
          persistAndAdvance({ skipped: false });
        }}
      >
        <style>{`
/* .exo-work-step max-width now inherits from .exo-step (720px base,
   880px ≥1280px). Keeping the class for future per-step tweaks. */
.exo-work-step .exo-step-title { font-size: 32px; letter-spacing: -0.02em; font-weight: 600; line-height: 1.1; margin: 0 0 12px; }
.exo-work-step .exo-step-body { font-size: 15px; color: #6e6e73; line-height: 1.55; margin: 0 0 24px; }
.exo-work-section-h { font-size: 11.5px; color: #86868b; font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em; margin: 28px 0 10px; }
.exo-work-section-h:first-of-type { margin-top: 16px; }
/* Multi-column rows flow with the container width — each cell holds a
   ~220px minimum so labels + inputs don't get crushed. Drops to 2 then
   1 col automatically as the card narrows, no manual breakpoint. */
.exo-work-row   { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px; }
.exo-work-row-3 { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px; }
.exo-work-field { display: flex; flex-direction: column; gap: 4px; margin-bottom: 12px; }
.exo-work-label { font-size: 12.5px; color: #424245; font-weight: 500; }
.exo-work-hint { font-size: 11.5px; color: #86868b; }
.exo-work-input, .exo-work-select, .exo-work-textarea {
  font: inherit; font-size: 14px; padding: 9px 12px; border: 1px solid rgba(0,0,0,0.12); border-radius: 8px;
  background: #fff; color: #1d1d1f; transition: border-color 0.15s ease;
}
.exo-work-input:focus, .exo-work-select:focus, .exo-work-textarea:focus { outline: none; border-color: #5b8def; }
.exo-work-textarea { min-height: 64px; resize: vertical; }
.exo-work-learn-card {
  background: linear-gradient(135deg, rgba(91,141,239,0.04), rgba(124,105,224,0.04));
  border: 1px solid rgba(91,141,239,0.18); border-radius: 14px;
  padding: 14px 16px; margin: 8px 0 20px;
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
}
.exo-work-learn-text { flex: 1; min-width: 220px; font-size: 13.5px; color: #1d1d1f; line-height: 1.5; }
.exo-work-learn-text strong { font-weight: 600; }
.exo-work-learn-cta {
  font: inherit; font-size: 13px; font-weight: 500;
  padding: 9px 16px; border-radius: 999px;
  background: #1d1d1f; color: #fff; border: none; cursor: pointer;
  transition: opacity 0.15s ease;
}
.exo-work-learn-cta:disabled { opacity: 0.5; cursor: default; }
.exo-work-note {
  font-size: 12.5px; color: #4a4a52; margin: 4px 0 16px;
  padding: 8px 12px; background: rgba(91,141,239,0.08); border-radius: 8px;
}
.exo-work-questions {
  margin: 12px 0; padding: 12px 14px; background: rgba(232,158,91,0.08);
  border-left: 3px solid #e89e5b; border-radius: 6px; font-size: 13px; color: #424245;
}
.exo-work-questions strong { font-weight: 600; }
.exo-work-questions ul { margin: 6px 0 0; padding-left: 18px; }
.exo-work-questions li { margin-bottom: 4px; }
.exo-work-citations { font-size: 11.5px; color: #86868b; margin: 4px 0 8px; overflow-wrap: anywhere; word-break: break-word; }
.exo-work-citations a { color: #5b8def; text-decoration: none; }
.exo-work-citations a:hover { text-decoration: underline; }
.exo-work-advanced-toggle {
  background: none; border: none; padding: 0; cursor: pointer;
  font: inherit; font-size: 12.5px; color: #5b8def; margin: 4px 0 12px;
}
.exo-work-advanced-toggle:hover { text-decoration: underline; }
@media (max-width: 600px) {
  .exo-work-row, .exo-work-row-3 { grid-template-columns: 1fr; }
}
        `}</style>

        <h1 className="exo-step-title">Tell us about your work</h1>
        <p className="exo-step-body">
          The more context we have, the better your daily reports + outreach
          drafts get. Drop your website URL below and we'll fill in what we
          can — review + edit before continuing.
        </p>

        <div className="exo-work-section-h">Your company</div>

        <div className="exo-work-row">
          <div className="exo-work-field">
            <label className="exo-work-label" htmlFor="wk-name">Brand / company name *<InferredChip field="display_name" /></label>
            <input
              id="wk-name"
              type="text"
              autoFocus
              className="exo-work-input"
              placeholder="e.g. Untold Garden"
              value={form.display_name}
              onChange={(e) => update('display_name', e.target.value)}
              disabled={busy}
            />
          </div>
          <div className="exo-work-field">
            <label className="exo-work-label" htmlFor="wk-url">Website URL</label>
            <input
              id="wk-url"
              type="url"
              className="exo-work-input"
              placeholder="https://your-company.com"
              value={form.website_url}
              onChange={(e) => update('website_url', e.target.value)}
              disabled={busy}
            />
          </div>
        </div>

        <div className="exo-work-field">
          <label className="exo-work-label">
            Documents
            {' '}<span style={{ color: '#86868b', fontWeight: 400 }}>— pitch deck, brief, overview (PDF, DOCX, TXT, MD)</span>
          </label>
          {window.DocumentDropZone ? (
            <window.DocumentDropZone
              workspaceId={workspaceId}
              disabled={busy}
              onUploadCountChange={setSessionUploadCount}
            />
          ) : (
            <span className="exo-work-hint">Upload component not loaded.</span>
          )}
          <span className="exo-work-hint">
            Combine with the URL above for the richest enrichment, or use
            documents alone if you don't have a public site yet. Bytes land
            in your Workspace and Gemini extracts the text — the agent
            reads everything as ground truth.
          </span>
        </div>

        <div className="exo-work-learn-card">
          <div className="exo-work-learn-text">
            <strong>Learn from what you've given us</strong> — Gemini reads
            your site + uploaded docs + searches the web (press, LinkedIn,
            Companies House) and pre-fills the rest of this form. Takes ~15-30s.
          </div>
          <button
            type="button"
            className="exo-work-learn-cta"
            disabled={busy || (!form.website_url.trim() && uploadCount === 0)}
            onClick={runEnrichment}
          >
            {learning ? 'Reading…' : 'Learn →'}
          </button>
        </div>

        {enrichmentNote && <div className="exo-work-note">{enrichmentNote}</div>}

        {openQuestions.length > 0 && (() => {
          const remaining = openQuestions.filter((q) => !savedQuestions.includes(q));
          const answeredCount = openQuestions.length - remaining.length;
          return (
            <div className="exo-work-questions">
              <strong>Gaps the agent couldn't fill from public sources</strong>
              <p style={{ margin: '4px 0 12px', fontSize: 12.5, color: '#6e6e73' }}>
                Answer any that you can — each becomes a permanent decision the
                outreach drafter, grant researcher, and proposal writer all consult.
                Then click <em>Refine</em> to fold your answers back in.
              </p>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
                {remaining.map((q) => (
                  <div key={q} style={{ display: 'flex', flexDirection: 'column', gap: 6, padding: 12, border: '1px solid rgba(0,0,0,0.08)', borderRadius: 10, background: 'rgba(0,0,0,0.02)' }}>
                    <div style={{ fontSize: 13.5, color: 'var(--exo-ink, #1d1d1f)', fontWeight: 500 }}>{q}</div>
                    <textarea
                      className="exo-work-textarea"
                      style={{ minHeight: 56, fontSize: 13 }}
                      placeholder="Type a short answer (or leave blank to skip)…"
                      value={questionDrafts[q] || ''}
                      onChange={(e) => setQuestionDrafts((d) => ({ ...d, [q]: e.target.value }))}
                      disabled={busy || savingQuestion === q}
                    />
                    {questionError[q] && (
                      <div style={{ fontSize: 12, color: '#b3261e' }}>{questionError[q]}</div>
                    )}
                    <div style={{ display: 'flex', justifyContent: 'flex-end' }}>
                      <button
                        type="button"
                        className="exo-link"
                        style={{ fontSize: 12.5 }}
                        onClick={() => saveAnswer(q)}
                        disabled={busy || savingQuestion === q || !(questionDrafts[q] || '').trim()}
                      >
                        {savingQuestion === q ? 'Saving…' : 'Save answer →'}
                      </button>
                    </div>
                  </div>
                ))}
                {remaining.length === 0 && (
                  <div style={{ fontSize: 13, color: '#5db98a' }}>
                    All answered. Click Refine to fold these back into the enrichment.
                  </div>
                )}
              </div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginTop: 14 }}>
                <button
                  type="button"
                  className="exo-link"
                  onClick={refineEnrichment}
                  disabled={busy || refining || answeredCount === 0}
                  style={{ fontSize: 13 }}
                  title={answeredCount === 0 ? 'Save at least one answer first.' : 'Re-run enrichment with your answers in context.'}
                >
                  {refining ? 'Refining…' : `Refine with ${answeredCount} answer${answeredCount === 1 ? '' : 's'} →`}
                </button>
                {refineToast && <span style={{ fontSize: 12, color: '#5db98a' }}>{refineToast}</span>}
                {refineError && <span style={{ fontSize: 12, color: '#b3261e' }}>{refineError}</span>}
              </div>
            </div>
          );
        })()}

        <button
          type="button"
          className="exo-work-advanced-toggle"
          onClick={() => setShowAdvanced(!showAdvanced)}
        >
          {showAdvanced ? '− Hide' : '+ Show'} optional secondary sources (LinkedIn, Crunchbase, GitHub, X, Companies House, pasted text)
        </button>

        {showAdvanced && (
          <>
            <div className="exo-work-row">
              <div className="exo-work-field">
                <label className="exo-work-label" htmlFor="wk-li">LinkedIn company URL</label>
                <input
                  id="wk-li" type="url" className="exo-work-input"
                  placeholder="https://www.linkedin.com/company/…"
                  value={form.linkedin_url}
                  onChange={(e) => update('linkedin_url', e.target.value)}
                  disabled={busy}
                />
              </div>
              <div className="exo-work-field">
                <label className="exo-work-label" htmlFor="wk-cb">Crunchbase URL</label>
                <input
                  id="wk-cb" type="url" className="exo-work-input"
                  placeholder="https://www.crunchbase.com/organization/…"
                  value={form.crunchbase_url}
                  onChange={(e) => update('crunchbase_url', e.target.value)}
                  disabled={busy}
                />
              </div>
            </div>
            <div className="exo-work-row">
              <div className="exo-work-field">
                <label className="exo-work-label" htmlFor="wk-gh">GitHub org URL</label>
                <input
                  id="wk-gh" type="url" className="exo-work-input"
                  placeholder="https://github.com/your-org"
                  value={form.github_url}
                  onChange={(e) => update('github_url', e.target.value)}
                  disabled={busy}
                />
              </div>
              <div className="exo-work-field">
                <label className="exo-work-label" htmlFor="wk-tw">Twitter / X URL</label>
                <input
                  id="wk-tw" type="url" className="exo-work-input"
                  placeholder="https://x.com/your-handle"
                  value={form.twitter_url}
                  onChange={(e) => update('twitter_url', e.target.value)}
                  disabled={busy}
                />
              </div>
            </div>
            <div className="exo-work-field">
              <label className="exo-work-label" htmlFor="wk-ch">UK Companies House number</label>
              <input
                id="wk-ch" type="text" className="exo-work-input"
                placeholder="e.g. 09876543"
                value={form.companies_house_number}
                onChange={(e) => update('companies_house_number', e.target.value)}
                disabled={busy}
              />
              <span className="exo-work-hint">UK Ltd only. The agent will look up directors, address, SIC code.</span>
            </div>
            {/* R10T14 — optional workspace-level brand voice. Overrides
                per-user voice when the agent drafts AS the brand
                (grant applications, public-facing copy). Per-user
                voice still wins for outreach DMs. */}
            <div className="exo-work-field">
              <label className="exo-work-label" htmlFor="wk-brand-voice">
                Brand voice samples <span style={{ color: '#86868b', fontWeight: 400 }}>(optional — overrides personal voice for grant + public copy)</span>
              </label>
              <textarea
                id="wk-brand-voice" className="exo-work-textarea"
                style={{ minHeight: 110 }}
                placeholder={'Paste 2-4 paragraphs from a grant application, brand manifesto, or public-facing copy.\n\nLeave blank to use each team member\'s personal voice.'}
                value={form.brand_voice}
                onChange={(e) => update('brand_voice', e.target.value)}
                disabled={busy}
              />
              <span className="exo-work-hint">Used by the grant writer and proposal writer; outreach DMs stay in the sender's personal voice.</span>
            </div>
            {/* DocumentDropZone moved to first-class position above the
                "Learn" card so URL-less founders see it immediately. */}
            <div className="exo-work-field">
              <label className="exo-work-label" htmlFor="wk-ctx">Extra context (fallback — paste)</label>
              <textarea
                id="wk-ctx" className="exo-work-textarea"
                style={{ minHeight: 100 }}
                placeholder="Paste pitch deck text, brief, or anything else the agent should know about your company."
                value={form.extra_context}
                onChange={(e) => update('extra_context', e.target.value)}
                disabled={busy}
              />
              <span className="exo-work-hint">Not saved — only used for the next "Learn from my website" call. Prefer the upload widget above.</span>
            </div>
          </>
        )}

        <div className="exo-work-section-h">What you do</div>

        <div className="exo-work-field">
          <label className="exo-work-label" htmlFor="wk-mission">Mission / one-line description<InferredChip field="mission" /></label>
          <textarea
            id="wk-mission" className="exo-work-textarea"
            placeholder="What your company exists to do, in 1-2 sentences."
            value={form.mission}
            onChange={(e) => update('mission', e.target.value)}
            disabled={busy}
          />
        </div>

        <div className="exo-work-field">
          <label className="exo-work-label" htmlFor="wk-vp">Value proposition<InferredChip field="value_proposition" /></label>
          <input
            id="wk-vp" type="text" className="exo-work-input"
            placeholder="One sentence on why customers pick you."
            value={form.value_proposition}
            onChange={(e) => update('value_proposition', e.target.value)}
            disabled={busy}
          />
        </div>

        {/* R10T01 — confirm chip. Visible once enrichment classifies.
            Click to open a picker. */}
        {orgKind && window.ExoteamOrgKind && (() => {
          const meta = window.ExoteamOrgKind.meta(orgKind);
          const isUncertain = orgKindConfidence === 'low';
          return (
            <div style={{
              margin: '14px 0', padding: '10px 14px',
              background: 'rgba(91,141,239,0.07)',
              border: '1px solid rgba(91,141,239,0.18)',
              borderRadius: 10, fontSize: 13, color: '#4a4a52',
              display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap',
            }}>
              <span>Looks like you're a <strong>{meta.label}</strong>{isUncertain && ' (?)'}.</span>
              <button
                type="button"
                onClick={() => setOrgKindPickerOpen(true)}
                style={{
                  font: 'inherit', fontSize: 12, padding: '4px 10px',
                  background: '#fff', color: '#4a4a52',
                  border: '1px solid rgba(10,10,26,0.14)', borderRadius: 14,
                  cursor: 'pointer',
                }}
              >
                Change →
              </button>
            </div>
          );
        })()}

        {orgKindPickerOpen && window.ExoteamOrgKind && (
          <div style={{
            margin: '0 0 14px', padding: 16,
            background: '#fff', border: '1px solid rgba(10,10,26,0.10)',
            borderRadius: 10,
          }}>
            <div style={{ fontSize: 12.5, color: '#4a4a52', marginBottom: 10 }}>
              Pick the closest match — the agent uses this to choose the right vocabulary on later steps.
            </div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
              {window.ExoteamOrgKind.ORG_KINDS.map((k) => (
                <button
                  key={k.id}
                  type="button"
                  onClick={() => {
                    setOrgKind(k.id);
                    setOrgKindPickerOpen(false);
                    if (workspaceId) {
                      db.collection('workspaces').doc(workspaceId).set({
                        org_kind: k.id,
                        org_kind_user_set: true,
                      }, { merge: true }).catch((err) => console.warn('org_kind save failed', err));
                    }
                  }}
                  style={{
                    font: 'inherit', textAlign: 'left',
                    padding: '8px 12px', borderRadius: 8,
                    background: orgKind === k.id ? 'rgba(91,141,239,0.10)' : '#fff',
                    border: '1px solid ' + (orgKind === k.id ? 'rgba(91,141,239,0.30)' : 'rgba(10,10,26,0.08)'),
                    cursor: 'pointer',
                  }}
                >
                  <div style={{ fontWeight: 600, fontSize: 13.5 }}>{k.label}</div>
                  <div style={{ fontSize: 12, color: '#6e6e73', marginTop: 2 }}>{k.blurb}{k.example && ` · e.g. ${k.example}`}</div>
                </button>
              ))}
            </div>
          </div>
        )}

        {(() => {
          const vocab = (window.ExoteamOrgKind && window.ExoteamOrgKind.get(orgKind)) || {};
          return (
            <div className="exo-work-field">
              <label className="exo-work-label" htmlFor="wk-prods">{vocab.products_label || 'Main products / services'}<InferredChip field="main_products" /></label>
              <textarea
                id="wk-prods" className="exo-work-textarea"
                placeholder={vocab.products_placeholder || 'One per line, e.g.\nMeadow platform\nClient AR commissions'}
                value={form.main_products}
                onChange={(e) => update('main_products', e.target.value)}
                disabled={busy}
              />
              <span className="exo-work-hint">{vocab.products_hint || 'Each becomes a Product you can target outreach + grants against.'}</span>
            </div>
          );
        })()}

        {/* R10T09 — "Who pays you" picker. Shapes proposal templates +
            outreach cadence downstream. Optional but cheap to surface. */}
        <div className="exo-work-field">
          <label className="exo-work-label">Who pays you <span style={{ color: '#86868b', fontWeight: 400 }}>(optional)</span></label>
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginTop: 4 }}>
            {[
              { id: 'subscription', label: 'Subscription' },
              { id: 'project',      label: 'Project / SOW' },
              { id: 'commission',   label: 'Commission' },
              { id: 'grant',        label: 'Grant' },
              { id: 'donation',     label: 'Donation' },
              { id: 'goods',        label: 'Goods sale' },
              { id: 'mixed',        label: 'Mixed' },
            ].map((m) => {
              const picked = form.revenue_model === m.id;
              return (
                <button
                  key={m.id}
                  type="button"
                  disabled={busy}
                  onClick={() => update('revenue_model', picked ? '' : m.id)}
                  style={{
                    font: 'inherit', fontSize: 12.5, padding: '6px 12px',
                    background: picked ? 'var(--exo-ink, #1d1d1f)' : '#fff',
                    color: picked ? '#fff' : '#4a4a52',
                    border: '1px solid ' + (picked ? 'var(--exo-ink, #1d1d1f)' : 'rgba(10,10,26,0.14)'),
                    borderRadius: 14,
                    cursor: 'pointer',
                  }}
                >
                  {m.label}
                </button>
              );
            })}
          </div>
        </div>

        <div className="exo-work-field">
          <label className="exo-work-label" htmlFor="wk-buyers">Target buyers / personas<InferredChip field="target_buyers" /></label>
          <textarea
            id="wk-buyers" className="exo-work-textarea"
            placeholder={'One per line, e.g.\nHead of Digital, museum\nCreative Director, agency\nFounder, immersive studio'}
            value={form.target_buyers}
            onChange={(e) => update('target_buyers', e.target.value)}
            disabled={busy}
          />
        </div>

        <div className="exo-work-section-h">Shape + scale</div>

        <div className="exo-work-row">
          <div className="exo-work-field">
            <label className="exo-work-label" htmlFor="wk-industry">Industry / sector<InferredChip field="industry" /></label>
            <input
              id="wk-industry" type="text" className="exo-work-input"
              placeholder="e.g. creative arts + spatial computing"
              value={form.industry}
              onChange={(e) => update('industry', e.target.value)}
              disabled={busy}
            />
          </div>
          <div className="exo-work-field">
            <label className="exo-work-label" htmlFor="wk-stage">Stage<InferredChip field="stage" /></label>
            <select
              id="wk-stage" className="exo-work-select"
              value={form.stage}
              onChange={(e) => update('stage', e.target.value)}
              disabled={busy}
            >
              {STAGES.map((s) => (
                <option key={s.v} value={s.v}>{s.label}</option>
              ))}
            </select>
          </div>
        </div>

        <div className="exo-work-row-3">
          <div className="exo-work-field">
            <label className="exo-work-label" htmlFor="wk-founders">Founders<InferredChip field="founders_count" /></label>
            <input
              id="wk-founders" type="number" min="0" max="20" className="exo-work-input"
              placeholder="e.g. 3"
              value={form.founders_count}
              onChange={(e) => update('founders_count', e.target.value)}
              disabled={busy}
            />
          </div>
          <div className="exo-work-field">
            <label className="exo-work-label" htmlFor="wk-emp">Employees (incl. founders)<InferredChip field="employees_count" /></label>
            <input
              id="wk-emp" type="number" min="0" max="100000" className="exo-work-input"
              placeholder="e.g. 5"
              value={form.employees_count}
              onChange={(e) => update('employees_count', e.target.value)}
              disabled={busy}
            />
          </div>
          <div className="exo-work-field">
            <label className="exo-work-label" htmlFor="wk-hq-city">HQ city<InferredChip field="hq_city" /></label>
            <input
              id="wk-hq-city" type="text" className="exo-work-input"
              placeholder="e.g. London"
              value={form.hq_city}
              onChange={(e) => update('hq_city', e.target.value)}
              disabled={busy}
            />
          </div>
        </div>

        <div className="exo-work-field">
          <label className="exo-work-label" htmlFor="wk-hq-country">HQ country<InferredChip field="hq_country" /></label>
          <input
            id="wk-hq-country" type="text" className="exo-work-input"
            placeholder="e.g. United Kingdom"
            value={form.hq_country}
            onChange={(e) => update('hq_country', e.target.value)}
            disabled={busy}
          />
        </div>

        {citations.length > 0 && (() => {
          // Vertex AI grounding routes every citation through an opaque
          // vertexaisearch.cloud.google.com redirect URL. Newer
          // enrichments include `display_title` (the publisher name
          // pulled from the grounding chunk metadata) so we render
          // that instead of the redirect host. Older enrichments fall
          // back to extracting the hostname from `url`. Either way we
          // dedupe so the same publisher doesn't show up six times.
          const REDIRECT_HOST = 'vertexaisearch.cloud.google.com';
          const labelFor = (c) => {
            if (c.display_title) return c.display_title;
            try {
              const h = new URL(c.url).hostname;
              return h === REDIRECT_HOST ? null : h;
            } catch (_e) { return null; }
          };
          const seen = new Set();
          const shown = [];
          for (const c of citations) {
            const label = labelFor(c);
            if (!label) continue;
            const key = label.toLowerCase();
            if (seen.has(key)) continue;
            seen.add(key);
            shown.push({ ...c, _label: label });
          }
          if (shown.length === 0) return null;
          return (
            <div className="exo-work-citations">
              <strong>Sources consulted:</strong>{' '}
              {shown.map((c, i) => (
                <React.Fragment key={i}>
                  {i > 0 && ' · '}
                  <a href={c.url} target="_blank" rel="noopener noreferrer" title={c.what_it_provided || c._label}>
                    {c._label}
                  </a>
                </React.Fragment>
              ))}
            </div>
          );
        })()}

        {error && <p className="exo-auth-error">{error}</p>}

        <div style={{ display: 'flex', gap: 14, alignItems: 'center', marginTop: 20 }}>
          {onBack && (
            <button
              type="button"
              onClick={onBack}
              disabled={busy}
              className="exo-step-back"
              aria-label="Go to previous step"
            >
              ← Back
            </button>
          )}
          <div style={{ marginLeft: 'auto', display: 'flex', alignItems: 'center', gap: 14 }}>
            <button
              type="submit"
              className="exo-auth-submit"
              disabled={busy || !form.display_name.trim()}
              style={{ maxWidth: 200 }}
            >
              {saving ? 'Saving…' : 'Continue →'}
            </button>
            <button
              type="button"
              className="exo-link"
              disabled={busy}
              onClick={() => persistAndAdvance({ skipped: true })}
            >
              Skip for now
            </button>
          </div>
        </div>
      </form>
    );
  }

  window.StepWork = StepWork;
})(window);
