<sectionclass="hero"id="dashboard"><div><pclass="eyebrow">EVIDENCE-LED PROSPECTING</p><h1>Good morning, Alex <span>✦</span></h1><pclass="hero-sub">Your pipeline has <strongid="heroCount">0 prospects</strong> ready for review.</p></div><buttonclass="button primary"data-scroll="#add">+ Add prospect</button></section>
<divclass="discovery-hero panel"><div><pclass="eyebrow">SOURCE INTELLIGENCE</p><h2id="discoveryWorkspaceTitle">Discovery runs</h2><pclass="muted">Build a criteria-first run across approved sources, monitor it live, and review every result with provenance before it enters your pipeline.</p></div><spanclass="discovery-badge">Bounded · review first</span></div>
<articleclass="panel direct-discovery-form-panel"><divclass="panel-heading"><div><pclass="eyebrow">RUN BUILDER</p><h3>Define your market</h3></div><spanclass="small-label">Max 20 pages · 50 candidates</span></div>
<formid="directDiscoveryForm"><divclass="form-grid"><label>Category / keyword<inputid="directDiscoveryKeywords"name="keywords"requiredmaxlength="240"placeholder="e.g. solar installers"></label><label>City<inputid="directDiscoveryCity"name="city"maxlength="80"placeholder="Cape Town"></label><label>Province / state<inputid="directDiscoveryProvince"name="province"maxlength="80"placeholder="Western Cape"></label><label>Country<inputid="directDiscoveryCountry"name="country"maxlength="80"placeholder="South Africa"></label></div><label>Approved sources <spanclass="optional">multi-select · only enabled sources can run</span><selectid="directDiscoverySources"name="source_ids"multiplesize="4"aria-label="Approved discovery sources"><optionvalue="">Loading approved sources…</option></select></label><divclass="discovery-limit-grid"><label>Max records<selectid="directDiscoveryMaxCandidates"name="max_candidates"><optionvalue="10">10 records</option><optionvalue="25"selected>25 records</option><optionvalue="50">50 records</option></select></label><label>Daily limit<inputid="directDiscoveryDailyLimit"name="daily_limit"type="number"min="1"max="1000"value="100"></label><label>Schedule<selectid="directDiscoverySchedule"name="schedule"><optionvalue="now">Run now</option><optionvalue="daily">Daily · 09:00</option><optionvalue="weekdays">Weekdays · 09:00</option><optionvalue="weekly">Weekly · Monday</option></select></label><label>Page limit<selectid="directDiscoveryMaxPages"name="max_pages"><optionvalue="5">5 pages</option><optionvalue="10"selected>10 pages</option><optionvalue="20">20 pages</option></select></label></div><detailsclass="advanced-discovery"><summary>Advanced run options</summary><label>Public seed URLs <spanclass="optional">optional · up to 5, one per line</span><textareaid="directDiscoverySeeds"name="seed_urls"rows="3"placeholder="https://directory.example/"></textarea></label><labelclass="checkbox-label"><inputtype="checkbox"name="dry_run"id="directDiscoveryDryRun"> Dry run · validate the plan without creating a job</label></details><divclass="form-footer"><pid="directDiscoveryMessage"class="form-message"role="status"aria-live="polite"></p><buttonclass="button primary"id="directDiscoveryRunBtn"type="submit">Start discovery <spanaria-hidden="true">→</span></button></div></form>
<divclass="panel discovery-results-panel"id="directDiscoveryResultsPanel"><divclass="panel-heading"><div><pclass="eyebrow">ACTIVE RUN</p><h3id="directDiscoveryResultTitle">Select a run to inspect results</h3></div><spanid="directDiscoveryResultStatus"class="small-label">No run selected</span></div><divid="directDiscoveryResultState"aria-live="polite"><pclass="muted">Progress, metrics, live events, and per-source health appear here.</p></div></div>
<aclass="metric-card metric-link"data-dashboard-filter="fresh"href="#explorer"><divclass="metric-icon blue">◷</div><div><p>Freshness under 7d</p><h2id="metricFresh">0%</h2><spanclass="trend neutral">● Evidence coverage</span></div></a>
<aclass="metric-card metric-link"data-dashboard-filter="suppressed"href="#explorer"><divclass="metric-icon violet">⊘</div><div><p>Suppressed</p><h2id="metricSuppressed">0</h2><spanclass="trend neutral">● Do not contact</span></div></a>
<sectionclass="score-overview"aria-label="Score overview"><articleclass="panel score-distribution-panel"id="scoreDistributionPanel"data-smoke="score-distribution"><divclass="detail-loading"aria-live="polite">Sign in to load score distribution…</div></article></section>
<sectionclass="score-rules-section"id="scoreRules"aria-labelledby="scoreRulesTitle"><articleclass="panel"id="scoreRulesPanel"data-smoke="score-rules"><divclass="detail-loading"aria-live="polite">Sign in to load score rules…</div></article></section>
<divclass="filters"><labelclass="search-wrap"><span>⌕</span><inputid="searchInput"type="search"placeholder="Search companies, domains, locations…"autocomplete="off"></label><selectid="sourceFilter"aria-label="Filter by source"><optionvalue="all">All sources</option></select><selectid="geographyFilter"aria-label="Filter by geography"><optionvalue="all">All geographies</option></select><selectid="categoryFilter"aria-label="Filter by category"><optionvalue="all">All categories</option></select><selectid="websiteClassFilter"aria-label="Filter by website or domain status"><optionvalue="all">Website / domain status</option><optionvalue="business_site">Business site</option><optionvalue="social_profile">Social profile</option><optionvalue="missing">Missing website</option></select><selectid="contactStatusFilter"aria-label="Filter by contact status"><optionvalue="all">All contact status</option><optionvalue="present">Contact present</option><optionvalue="missing">Contact missing</option><optionvalue="suppressed">Do not contact</option></select><selectid="scoreFilter"aria-label="Filter by score"><optionvalue="all">All scores</option><optionvalue="high">High fit · 80+</option><optionvalue="medium">Medium · 60–79</option><optionvalue="low">Low · under 60</option></select><selectid="statusFilter"aria-label="Filter by review status"><optionvalue="all">All review states</option><optionvalue="review">Needs review</option><optionvalue="reviewed">Reviewed</option><optionvalue="suppressed">Suppressed</option></select><selectid="pipelineFilter"aria-label="Filter by pipeline stage"><optionvalue="all">All pipeline stages</option><optionvalue="new">New</option><optionvalue="contacted">Contacted</option><optionvalue="qualified">Qualified</option><optionvalue="proposal">Proposal</option><optionvalue="negotiation">Negotiation</option><optionvalue="won">Won</option><optionvalue="lost">Lost</option></select></div>
<asideclass="detail-panel panel"id="detailPanel"><divclass="empty-detail"><spanclass="empty-icon">◒</span><h3>Select a prospect</h3><p>Review evidence, confidence, and eligibility before taking action.</p></div></aside>
<div><pclass="eyebrow">OPERATIONS</p><h2id="jobsTitle">Job monitor</h2><pclass="muted">Track authenticated workspace jobs and their progress. No job data is shown until the API responds.</p></div>
<divclass="jobs-list panel"><divclass="panel-heading"><div><pclass="eyebrow">QUEUE</p><h3>Recent jobs</h3></div><spanid="jobsUpdatedAt"class="small-label">Not loaded</span></div><divid="jobsList"class="jobs-list-body"><divclass="job-empty">Sign in to load jobs from the workspace.</div></div></div>
<asideclass="job-detail panel"id="jobDetailPanel"><divclass="empty-detail"><spanclass="empty-icon">◷</span><h3>Select a job</h3><p>Inspect progress, structured errors, and the event timeline.</p></div></aside>
<divclass="sources-header panel"><div><pclass="eyebrow">GOVERNANCE</p><h2id="sourcesTitle">Sources</h2><pclass="muted">Review source ownership, terms, limits, and health before using discovery.</p></div><buttonclass="button ghost"id="sourcesRefreshBtn"type="button">↻ Refresh</button></div>
<divclass="source-safety"role="note"><strong>Discovery is disabled by default.</strong> No live source is enabled in this workspace. Enable a source only after its terms, owner, rate limit, and health have been reviewed.</div>
<articleclass="panel source-config-panel"><divclass="panel-heading"><div><pclass="eyebrow">CONFIGURATION</p><h3>Add a source</h3></div><spanclass="small-label">Manual or CSV</span></div><formid="sourceForm"><divclass="form-grid"><label>Source name<inputname="name"requiredplaceholder="Public business directory"></label><label>Source type<selectname="source_type"id="sourceType"><optionvalue="manual">Manual / API</option><optionvalue="csv">CSV upload</option></select></label><label>Source URL <spanclass="optional">optional</span><inputname="url"type="url"placeholder="https://…"></label><label>Terms URL <spanclass="optional">required for enablement</span><inputname="terms_url"type="url"placeholder="https://…/terms"></label><label>Owner<inputname="owner"requiredplaceholder="Team or accountable person"></label><label>Rate limit<inputname="rate_limit"requiredplaceholder="e.g. 60 requests/hour"></label></div><labelclass="source-csv-field"id="sourceCsvField"hidden>CSV content<textareaname="csv_content"id="sourceCsvContent"rows="4"placeholder="Paste CSV content; it is sent only when you save this source."></textarea></label><divclass="form-footer"><pid="sourceFormMessage"class="form-message"role="status"></p><buttonclass="button primary"type="submit">Save source</button></div></form></article>
<articleclass="panel discovery-panel"><divclass="panel-heading"><div><pclass="eyebrow">DISCOVERY</p><h3>Query a source</h3></div><spanclass="small-label">No automatic runs</span></div><formid="discoveryForm"><label>Source<selectname="source_id"id="discoverySource"required><optionvalue="">Select a source</option></select></label><label>Query<inputname="query"requiredplaceholder="e.g. renewable energy firms in Cape Town"></label><labelclass="checkbox-label"><inputtype="checkbox"name="dry_run"id="discoveryDryRun"checked> Dry run (preview only)</label><divclass="form-footer"><pid="discoveryMessage"class="form-message"role="status"></p><divclass="discovery-actions"><buttonclass="button ghost"id="discoveryDryRunBtn"type="submit">Validate query</button><buttonclass="button primary"id="discoveryRunBtn"type="button">Run discovery</button></div></div></form></article>
</div>
<divclass="sources-list panel"><divclass="panel-heading"><div><pclass="eyebrow">REGISTRY</p><h3>Configured sources</h3></div><spanid="sourcesUpdatedAt"class="small-label">Not loaded</span></div><divid="sourcesList"class="sources-list-body"><divclass="source-empty">Sign in to load sources from the workspace.</div></div></div>
<divclass="source-records panel"><divclass="panel-heading"><div><pclass="eyebrow">RECENT OUTPUT</p><h3>Recent source records</h3></div></div><divid="sourceRecordsList"class="source-records-body"><divclass="source-empty">No records loaded.</div></div></div>
<sectionclass="lower-grid"id="add"><articleclass="panel add-panel"><divclass="panel-heading"><div><pclass="eyebrow">INTAKE</p><h2>Add a prospect</h2></div><spanclass="small-label">Manual entry</span></div><formid="addForm"><divclass="form-grid"><label>Company name<inputrequiredname="name"placeholder="Acme Inc."></label><label>Website <spanclass="optional">optional</span><inputname="website"type="url"placeholder="https://acme.com"></label><label>Location<inputname="location"placeholder="Cape Town, ZA"></label><label>Notes <spanclass="optional">optional</span><inputname="description"placeholder="Why this is a fit…"></label></div><divclass="form-footer"><pid="formMessage"class="form-message"role="status"></p><buttonclass="button primary"type="submit">Add to review queue</button></div></form></article>
<articleclass="panel csv-panel"><divclass="panel-heading"><div><pclass="eyebrow">BULK INTAKE</p><h2>CSV preview</h2></div><labelclass="button ghost upload-label"for="csvInput">↑ Choose CSV</label><inputid="csvInput"type="file"accept=".csv,text/csv"hidden></div><pclass="muted">Preview rows before adding them to your review queue.</p><divid="csvPreview"class="csv-empty"><span>⊞</span><p>No file selected</p><small>CSV stays in your browser until you confirm.</small></div></article></section>
<divclass="crm-header panel"><div><pclass="eyebrow">CRM WORKFLOW</p><h2id="crmPipelineTitle">Pipeline board</h2><pclass="muted">Move prospects through explicit human stages. Stage changes never send outreach.</p></div><divclass="crm-actions"><buttonclass="button ghost"id="crmRefreshBtn"type="button">↻ Refresh CRM</button><buttonclass="button ghost"id="pipelineViewToggle"type="button"aria-pressed="false">☷ List view</button></div></div>
<divclass="crm-safety"role="note"><strong>No outreach from this workspace.</strong> Pipeline actions, interactions, and follow-ups are internal CRM records only. Suppressed or unreviewed prospects remain unavailable for contact.</div>
<divclass="crm-header panel"><div><pclass="eyebrow">RELATIONSHIP HISTORY</p><h2id="crmActivityTitle">Interactions & follow-ups</h2><pclass="muted">Capture outcomes and next steps without contacting anyone.</p></div></div>
<divclass="crm-two-col"><articleclass="panel interaction-panel"><divid="interactionState"class="detail-loading">Select a prospect to load interactions.</div></article><articleclass="panel"><divclass="panel-heading"><div><pclass="eyebrow">ADD RECORD</p><h3>Log an interaction</h3></div><spanclass="small-label">Internal only</span></div><formid="interactionForm"class="crm-form"><label>Channel<selectname="kind"><optionvalue="note">Note</option><optionvalue="phone">Phone</option><optionvalue="email">Email (record only)</option><optionvalue="meeting">Meeting</option><optionvalue="other">Other</option></select></label><label>Outcome<selectname="outcome"><optionvalue="other"selected>Other / not specified</option><optionvalue="connected">Connected</option><optionvalue="no_answer">No answer</option><optionvalue="left_message">Left message</option><optionvalue="meeting_booked">Meeting booked</option><optionvalue="meeting_held">Meeting held</option><optionvalue="qualified">Qualified</option><optionvalue="disqualified">Disqualified</option><optionvalue="won">Won</option><optionvalue="lost">Lost</option></select></label><label>Follow-up date <spanclass="optional">optional</span><inputname="follow_up_at"type="date"></label><label>Body<textareaname="body"rows="4"requiredplaceholder="What happened? Keep this an internal record."></textarea></label><pid="interactionMessage"class="form-message"role="status"></p><buttonclass="button primary"type="submit">Save interaction</button></form></article></div>
<divclass="crm-header panel"><div><pclass="eyebrow">REPORTING</p><h2id="crmReportsTitle">CRM reports</h2><pclass="muted">Tenant-scoped pipeline, outcomes, and activity summaries from the API.</p></div><buttonclass="button ghost"id="reportsRefreshBtn"type="button">↻ Refresh reports</button></div>
<divclass="suppression-warning"role="alert"><strong>Suppression always wins.</strong> Suppressed contacts and domains cannot be contacted, regardless of score, stage, or interaction outcome.</div>
<sectionclass="crm-section outreach-settings-section"id="outreachSettings"aria-labelledby="outreachSettingsTitle"data-smoke="outreach-provider-policy"><divclass="crm-header panel"><div><pclass="eyebrow">GOVERNANCE</p><h2id="outreachSettingsTitle">Outreach provider policy</h2><pclass="muted">View approved provider status without exposing credentials or secrets.</p></div><buttonclass="button ghost"id="outreachPolicyRefreshBtn"type="button">↻ Refresh policy</button></div><divclass="outreach-settings-safety"role="note"><strong>Sending is disabled by default.</strong> This panel is status-only. Provider configuration never creates a send trigger, and no credentials are displayed.</div><divid="providerPolicyPanel"class="provider-policy-panel"aria-live="polite"><divclass="detail-loading">Sign in to load provider policy.</div></div></section>
<sectionclass="crm-section ai-provider-settings-section"id="aiProviderSettings"aria-labelledby="aiProviderSettingsTitle"data-smoke="ai-provider-settings"><divclass="crm-header panel"><div><pclass="eyebrow">SYSTEM CONFIGURATION</p><h2id="aiProviderSettingsTitle">AI Provider Settings</h2><pclass="muted">Configure the approved Nous Portal service and the internal SearXNG service used by workspace AI research.</p></div><buttonclass="button ghost"id="aiProviderRefreshBtn"type="button">↻ Refresh status</button></div><divclass="ai-provider-safety"role="note"><strong>Admin-only and write-only credentials.</strong> Keys are sent only over the authenticated API, are never displayed or stored in this browser, and updating settings does not start discovery or AI work.</div><divid="aiProviderAdminState"class="provider-state"role="status"hidden></div><divclass="ai-provider-grid"><articleclass="panel ai-provider-form-panel"><divclass="panel-heading"><div><pclass="eyebrow">PROVIDER CONFIGURATION</p><h3>Service connection</h3></div><spanclass="small-label">Approved providers only</span></div><formid="aiProviderForm"><divclass="form-grid"><label>AI provider<selectid="aiProvider"name="provider"><optionvalue="nous_portal">Nous Portal</option><optionvalue="stepfun">StepFun</option></select></label><label>Nous Portal model<inputid="nousModel"name="nous_model"requiredmaxlength="160"placeholder="Hermes 4 405B"autocomplete="off"></label><label>Nous Portal base URL<inputid="nousBaseUrl"name="nous_base_url"type="url"requiredplaceholder="https://inference-api.nousresearch.com/v1"autocomplete="off"></label><label>Nous Portal API key <spanclass="optional">write-only · leave blank to keep</span><inputid="nousApiKey"name="nous_api_key"type="password"maxlength="512"placeholder="Enter a new key to rotate"autocomplete="new-password"></label><label>SearXNG base URL <spanclass="optional">internal · leave default</span><inputid="searxngBaseUrl"name="searxng_base_url"type="url"placeholder="http://searxng:8080"autocomplete="off"></label></div><divclass="form-footer"><pid="aiProviderMessage"class="form-message"role="status"aria-live="polite"></p><buttonclass="button primary"id="saveAiProviderBtn"type="submit">Save provider settings</button></div></form></article><asideclass="panel ai-provider-status-panel"><divclass="panel-heading"><div><pclass="eyebrow">SAFE STATUS</p><h3>Connection status</h3></div><buttonclass="button ghost compact"id="testAiProviderBtn"type="button">Test connection</button></div><divid="aiProviderStatus"aria-live="polite"><divclass="detail-loading">Sign in to load provider status.</div></div></aside></div></section>
<divclass="merge-dialog-card"><divclass="panel-heading"><div><pclass="eyebrow">REVIEW REQUIRED</p><h2id="mergeDialogTitle">Confirm merge</h2></div><buttonclass="icon-button"id="cancelMergeBtn"type="button"aria-label="Close merge confirmation">×</button></div><pid="mergeDialogCopy"></p><divclass="merge-warning"><strong>This action is reversible.</strong> The merge will be recorded in history and can be reversed later.</div><pid="mergeDialogMessage"class="form-message"role="alert"aria-live="polite"></p><divclass="merge-dialog-actions"><buttonclass="button ghost"id="cancelMergeBtnSecondary"type="button">Cancel</button><buttonclass="button primary"id="confirmMergeBtn"type="button">Confirm merge</button></div></div>