{"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/client.ts","../src/chat/config.ts","../src/chat/session.ts","../src/chat/validate.ts","../src/chat/template.ts","../src/chat/countries.ts","../src/chat/styles.ts","../src/chat/dom.ts","../src/chat/index.ts","../src/index.ts"],"names":[],"mappings":"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AA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA,cAAA,EA0DhD,MAAM,CAAA;AAAA,SAAA,EACX,UAAU,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,cAAA,EAoGL,MAAM,CAAA;AAAA,SAAA,EACX,UAAU,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAA,EA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","file":"index.cjs","sourcesContent":["export class NexorError extends Error {\n  constructor(message: string) {\n    super(message);\n    this.name = \"NexorError\";\n  }\n}\n\nexport class NexorAPIError extends NexorError {\n  status: number;\n  code: string;\n  body: unknown;\n  requestId?: string;\n\n  constructor(opts: {\n    status: number;\n    code?: string;\n    message: string;\n    body?: unknown;\n    requestId?: string;\n  }) {\n    super(opts.message);\n    this.name = \"NexorAPIError\";\n    this.status = opts.status;\n    this.code = opts.code ?? statusToCode(opts.status);\n    this.body = opts.body;\n    this.requestId = opts.requestId;\n  }\n}\n\nexport class NexorAuthError extends NexorAPIError {\n  constructor(opts: { message: string; body?: unknown; requestId?: string }) {\n    super({ status: 401, code: \"unauthorized\", ...opts });\n    this.name = \"NexorAuthError\";\n  }\n}\n\nexport class NexorValidationError extends NexorAPIError {\n  constructor(opts: { message: string; body?: unknown; requestId?: string }) {\n    super({ status: 400, code: \"validation_error\", ...opts });\n    this.name = \"NexorValidationError\";\n  }\n}\n\nexport class NexorNetworkError extends NexorError {\n  cause?: unknown;\n  constructor(message: string, cause?: unknown) {\n    super(message);\n    this.name = \"NexorNetworkError\";\n    this.cause = cause;\n  }\n}\n\nfunction statusToCode(status: number): string {\n  if (status === 400) return \"validation_error\";\n  if (status === 401) return \"unauthorized\";\n  if (status === 403) return \"forbidden\";\n  if (status === 404) return \"not_found\";\n  if (status === 409) return \"conflict\";\n  if (status === 422) return \"unprocessable_entity\";\n  if (status === 429) return \"rate_limited\";\n  if (status >= 500) return \"server_error\";\n  return \"http_error\";\n}\n","import {\n  NexorAPIError,\n  NexorAuthError,\n  NexorNetworkError,\n  NexorValidationError,\n} from \"./errors\";\nimport type { ClientOptions, RequestOptions } from \"./types\";\n\nconst DEFAULT_BASE_URL = \"https://api.getnexor.ai\";\nconst DEFAULT_TIMEOUT_MS = 30_000;\nconst DEFAULT_MAX_RETRIES = 2;\nconst SDK_VERSION = \"0.1.0\";\n\nexport interface ResolvedConfig {\n  apiKey: string;\n  baseUrl: string;\n  timeoutMs: number;\n  maxRetries: number;\n  fetchImpl: typeof fetch;\n  userAgent: string;\n}\n\nexport function resolveConfig(opts: ClientOptions): ResolvedConfig {\n  if (!opts || typeof opts.apiKey !== \"string\" || opts.apiKey.trim() === \"\") {\n    throw new Error(\n      \"Nexor SDK: `apiKey` is required. Get one in the dashboard at https://app.getnexor.ai\",\n    );\n  }\n  const fetchImpl =\n    opts.fetch ??\n    (typeof globalThis !== \"undefined\" && typeof globalThis.fetch === \"function\"\n      ? globalThis.fetch.bind(globalThis)\n      : (undefined as unknown as typeof fetch));\n  if (!fetchImpl) {\n    throw new Error(\n      \"Nexor SDK: no global fetch found. Pass a `fetch` implementation via init() or upgrade to Node 18+.\",\n    );\n  }\n  const ua = `nexor-sdk-js/${SDK_VERSION}${opts.userAgentSuffix ? ` ${opts.userAgentSuffix}` : \"\"}`;\n  return {\n    apiKey: opts.apiKey.trim(),\n    baseUrl: stripTrailingSlash(opts.baseUrl ?? DEFAULT_BASE_URL),\n    timeoutMs: opts.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n    maxRetries: opts.maxRetries ?? DEFAULT_MAX_RETRIES,\n    fetchImpl,\n    userAgent: ua,\n  };\n}\n\ninterface HttpRequest {\n  method: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\" | \"PATCH\";\n  path: string;\n  query?: Record<string, string | number | boolean | string[] | undefined | null>;\n  body?: unknown;\n  options?: RequestOptions;\n}\n\nexport async function request<T>(\n  cfg: ResolvedConfig,\n  req: HttpRequest,\n): Promise<T> {\n  const url = buildUrl(cfg.baseUrl, req.path, req.query);\n  const headers: Record<string, string> = {\n    \"X-API-Key\": cfg.apiKey,\n    Accept: \"application/json\",\n    \"User-Agent\": cfg.userAgent,\n  };\n  if (req.options?.idempotencyKey) {\n    headers[\"Idempotency-Key\"] = req.options.idempotencyKey;\n  }\n  let body: BodyInit | undefined;\n  if (req.body !== undefined) {\n    headers[\"Content-Type\"] = \"application/json\";\n    body = JSON.stringify(req.body);\n  }\n\n  const timeoutMs = req.options?.timeoutMs ?? cfg.timeoutMs;\n  const maxRetries = req.options?.maxRetries ?? cfg.maxRetries;\n  let lastErr: unknown;\n\n  for (let attempt = 0; attempt <= maxRetries; attempt++) {\n    const controller = new AbortController();\n    const externalSignal = req.options?.signal;\n    const onAbort = () => controller.abort();\n    if (externalSignal) {\n      if (externalSignal.aborted) controller.abort();\n      else externalSignal.addEventListener(\"abort\", onAbort);\n    }\n    const timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n\n    try {\n      const res = await cfg.fetchImpl(url, {\n        method: req.method,\n        headers,\n        body,\n        signal: controller.signal,\n      });\n      clearTimeout(timeoutId);\n      externalSignal?.removeEventListener(\"abort\", onAbort);\n\n      const requestId = res.headers.get(\"x-request-id\") ?? undefined;\n\n      if (res.ok) {\n        if (res.status === 204) return undefined as T;\n        const text = await res.text();\n        if (!text) return undefined as T;\n        try {\n          return JSON.parse(text) as T;\n        } catch {\n          throw new NexorAPIError({\n            status: res.status,\n            message: \"Failed to parse JSON response\",\n            body: text,\n            requestId,\n          });\n        }\n      }\n\n      // Non-2xx: parse and throw a typed error.\n      const errBody = await safeJson(res);\n      const message = pickMessage(errBody) ?? `HTTP ${res.status}`;\n      const err = makeError(res.status, message, errBody, requestId);\n\n      // Retry on 429 + 5xx with exponential backoff.\n      if (shouldRetry(res.status) && attempt < maxRetries) {\n        await sleep(backoffMs(attempt, res));\n        lastErr = err;\n        continue;\n      }\n      throw err;\n    } catch (err) {\n      clearTimeout(timeoutId);\n      externalSignal?.removeEventListener(\"abort\", onAbort);\n      if (err instanceof NexorAPIError) throw err;\n      const isAbort =\n        err instanceof Error &&\n        (err.name === \"AbortError\" || /abort/i.test(err.message));\n      if (isAbort && externalSignal?.aborted) throw err;\n      // Network or timeout: retry.\n      lastErr = err;\n      if (attempt < maxRetries) {\n        await sleep(backoffMs(attempt));\n        continue;\n      }\n      throw new NexorNetworkError(\n        isAbort ? `Request timed out after ${timeoutMs}ms` : `Network error: ${(err as Error)?.message ?? String(err)}`,\n        err,\n      );\n    }\n  }\n  throw lastErr ?? new NexorNetworkError(\"Request failed\");\n}\n\nfunction makeError(\n  status: number,\n  message: string,\n  body: unknown,\n  requestId?: string,\n): NexorAPIError {\n  if (status === 401 || status === 403) {\n    return new NexorAuthError({ message, body, requestId });\n  }\n  if (status === 400 || status === 422) {\n    return new NexorValidationError({ message, body, requestId });\n  }\n  return new NexorAPIError({ status, message, body, requestId });\n}\n\nfunction pickMessage(body: unknown): string | undefined {\n  if (!body || typeof body !== \"object\") return undefined;\n  const b = body as Record<string, unknown>;\n  if (typeof b.message === \"string\") return b.message;\n  if (typeof b.error === \"string\") return b.error;\n  return undefined;\n}\n\nasync function safeJson(res: Response): Promise<unknown> {\n  try {\n    const txt = await res.text();\n    if (!txt) return null;\n    try {\n      return JSON.parse(txt);\n    } catch {\n      return txt;\n    }\n  } catch {\n    return null;\n  }\n}\n\nfunction shouldRetry(status: number): boolean {\n  return status === 429 || (status >= 500 && status <= 599);\n}\n\nfunction backoffMs(attempt: number, res?: Response): number {\n  if (res) {\n    const ra = res.headers.get(\"retry-after\");\n    if (ra) {\n      const n = Number(ra);\n      if (!Number.isNaN(n) && n > 0) return Math.min(n * 1000, 10_000);\n    }\n  }\n  const base = 300 * 2 ** attempt;\n  return base + Math.floor(Math.random() * 200);\n}\n\nfunction sleep(ms: number): Promise<void> {\n  return new Promise((r) => setTimeout(r, ms));\n}\n\nfunction stripTrailingSlash(s: string): string {\n  return s.endsWith(\"/\") ? s.slice(0, -1) : s;\n}\n\nfunction buildUrl(\n  baseUrl: string,\n  path: string,\n  query?: HttpRequest[\"query\"],\n): string {\n  const p = path.startsWith(\"/\") ? path : `/${path}`;\n  const qs = encodeQuery(query);\n  return `${baseUrl}${p}${qs ? `?${qs}` : \"\"}`;\n}\n\nfunction encodeQuery(query?: HttpRequest[\"query\"]): string {\n  if (!query) return \"\";\n  const parts: string[] = [];\n  for (const [k, v] of Object.entries(query)) {\n    if (v === undefined || v === null) continue;\n    if (Array.isArray(v)) {\n      if (v.length === 0) continue;\n      parts.push(`${encodeURIComponent(k)}=${encodeURIComponent(v.join(\",\"))}`);\n    } else {\n      parts.push(`${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`);\n    }\n  }\n  return parts.join(\"&\");\n}\n","import { request, resolveConfig, type ResolvedConfig } from \"./http\";\nimport type {\n  AutomationInput,\n  Campaign,\n  ClientOptions,\n  CreateLeadBulkResponse,\n  CreateLeadInput,\n  CreateLeadResponse,\n  CreateMeetingInput,\n  GetLeadHistoryParams,\n  GetLeadHistoryResponse,\n  GetLeadResponse,\n  IsPausedResponse,\n  Lead,\n  ListTemplatesParams,\n  MeetingNotesInput,\n  RequestOptions,\n  ResumeAutomationInput,\n  SendMessageInput,\n  SyncTagsInput,\n  SyncTagsResponse,\n  UUID,\n  WhatsAppTemplate,\n  Workflow,\n} from \"./types\";\n\nconst PUBLIC_PREFIX = \"/api/public\";\n\n/**\n * Low-level Nexor API client.\n *\n * Most users should call `init()` / `createClient()` instead of instantiating\n * this directly, but it's exported for advanced cases (DI, mocking).\n */\nexport class NexorClient {\n  private cfg: ResolvedConfig;\n\n  constructor(opts: ClientOptions) {\n    this.cfg = resolveConfig(opts);\n  }\n\n  // ─── Leads ───────────────────────────────────────────────────────────────\n\n  /** Create a single lead, optionally assigning it to a workflow. */\n  createLead(\n    input: CreateLeadInput,\n    options?: RequestOptions,\n  ): Promise<CreateLeadResponse> {\n    return request<CreateLeadResponse>(this.cfg, {\n      method: \"POST\",\n      path: `${PUBLIC_PREFIX}/leads`,\n      body: { ...input, skip_first_message: true },\n      options,\n    });\n  }\n\n  /** Create many leads in one request (max 1000). */\n  createLeadsBulk(\n    inputs: CreateLeadInput[],\n    options?: RequestOptions,\n  ): Promise<CreateLeadBulkResponse> {\n    return request<CreateLeadBulkResponse>(this.cfg, {\n      method: \"POST\",\n      path: `${PUBLIC_PREFIX}/leads`,\n      body: inputs.map((i) => ({ ...i, skip_first_message: true })),\n      options,\n    });\n  }\n\n  /** Update an existing lead. metadata is shallow-merged server-side. */\n  updateLead(\n    leadId: UUID,\n    updates: Partial<CreateLeadInput>,\n    options?: RequestOptions,\n  ): Promise<{ success: true; lead: Lead }> {\n    return request(this.cfg, {\n      method: \"PUT\",\n      path: `${PUBLIC_PREFIX}/leads/${encodeURIComponent(leadId)}`,\n      body: updates,\n      options,\n    });\n  }\n\n  /** Fetch a lead with its captured variables and per-channel engagement. */\n  getLead(leadId: UUID, options?: RequestOptions): Promise<GetLeadResponse> {\n    return request<GetLeadResponse>(this.cfg, {\n      method: \"GET\",\n      path: `${PUBLIC_PREFIX}/leads/${encodeURIComponent(leadId)}`,\n      options,\n    });\n  }\n\n  /** Full chronological history: messages, transcripts, activity. */\n  getLeadHistory(\n    leadId: UUID,\n    params: GetLeadHistoryParams = {},\n    options?: RequestOptions,\n  ): Promise<GetLeadHistoryResponse> {\n    const channel = Array.isArray(params.channel)\n      ? params.channel\n      : params.channel\n        ? [params.channel]\n        : undefined;\n    return request<GetLeadHistoryResponse>(this.cfg, {\n      method: \"GET\",\n      path: `${PUBLIC_PREFIX}/leads/${encodeURIComponent(leadId)}/history`,\n      query: { channel, limit: params.limit, offset: params.offset },\n      options,\n    });\n  }\n\n  /** Has automation been paused (human takeover) for this lead? */\n  isLeadPaused(\n    leadId: UUID,\n    params: { workflow_id?: UUID } = {},\n    options?: RequestOptions,\n  ): Promise<IsPausedResponse> {\n    return request<IsPausedResponse>(this.cfg, {\n      method: \"GET\",\n      path: `${PUBLIC_PREFIX}/leads/${encodeURIComponent(leadId)}/is_paused`,\n      query: { workflow_id: params.workflow_id },\n      options,\n    });\n  }\n\n  /** Pause automation (engage human takeover) on a specific workflow run. */\n  stopAutomation(\n    leadId: UUID,\n    input: AutomationInput,\n    options?: RequestOptions,\n  ): Promise<unknown> {\n    return request(this.cfg, {\n      method: \"POST\",\n      path: `${PUBLIC_PREFIX}/leads/${encodeURIComponent(leadId)}/automation/stop`,\n      body: input,\n      options,\n    });\n  }\n\n  /** Resume automation; pass resume_cadence: true to restart scheduled touches. */\n  resumeAutomation(\n    leadId: UUID,\n    input: ResumeAutomationInput,\n    options?: RequestOptions,\n  ): Promise<unknown> {\n    return request(this.cfg, {\n      method: \"POST\",\n      path: `${PUBLIC_PREFIX}/leads/${encodeURIComponent(leadId)}/automation/resume`,\n      body: input,\n      options,\n    });\n  }\n\n  /**\n   * Replace the tag set on a lead (identified by lead_id OR email).\n   * Tags missing from the input are unassigned; new tags are find-or-created.\n   */\n  syncLeadTags(\n    input: SyncTagsInput,\n    options?: RequestOptions,\n  ): Promise<SyncTagsResponse> {\n    return request<SyncTagsResponse>(this.cfg, {\n      method: \"POST\",\n      path: `${PUBLIC_PREFIX}/leads/tags`,\n      body: input,\n      options,\n    });\n  }\n\n  /** All meetings on file for a lead (optionally filter by status). */\n  listLeadMeetings(\n    leadId: UUID,\n    params: { status?: string | string[] } = {},\n    options?: RequestOptions,\n  ): Promise<unknown> {\n    const status = Array.isArray(params.status)\n      ? params.status.join(\",\")\n      : params.status;\n    return request(this.cfg, {\n      method: \"GET\",\n      path: `${PUBLIC_PREFIX}/leads/${encodeURIComponent(leadId)}/meetings`,\n      query: { status },\n      options,\n    });\n  }\n\n  // ─── Workflows / Campaigns / Templates ──────────────────────────────────\n\n  /** Active workflows in your account. */\n  listWorkflows(\n    options?: RequestOptions,\n  ): Promise<{ success: true; workflows: Workflow[] }> {\n    return request(this.cfg, {\n      method: \"GET\",\n      path: `${PUBLIC_PREFIX}/workflows`,\n      options,\n    });\n  }\n\n  /** Campaigns in your account. */\n  listCampaigns(\n    options?: RequestOptions,\n  ): Promise<{ success: true; campaigns: Campaign[] }> {\n    return request(this.cfg, {\n      method: \"GET\",\n      path: `${PUBLIC_PREFIX}/campaigns`,\n      options,\n    });\n  }\n\n  /** Approved WhatsApp templates. */\n  listTemplates(\n    params: ListTemplatesParams = {},\n    options?: RequestOptions,\n  ): Promise<{ success: true; templates: WhatsAppTemplate[] }> {\n    return request(this.cfg, {\n      method: \"GET\",\n      path: `${PUBLIC_PREFIX}/templates`,\n      query: { status: params.status, category: params.category },\n      options,\n    });\n  }\n\n  // ─── Messages ───────────────────────────────────────────────────────────\n\n  /** Send a one-off message (WhatsApp/email) or trigger a call. */\n  sendMessage(\n    input: SendMessageInput,\n    options?: RequestOptions,\n  ): Promise<unknown> {\n    return request(this.cfg, {\n      method: \"POST\",\n      path: `${PUBLIC_PREFIX}/messages`,\n      body: input,\n      options,\n    });\n  }\n\n  // ─── Meetings ───────────────────────────────────────────────────────────\n\n  /** Log a booked meeting against an existing lead (matched by email). */\n  createMeeting(\n    input: CreateMeetingInput,\n    options?: RequestOptions,\n  ): Promise<unknown> {\n    return request(this.cfg, {\n      method: \"POST\",\n      path: `${PUBLIC_PREFIX}/meetings`,\n      body: input,\n      options,\n    });\n  }\n\n  /** Push a note-taker transcript / summary / action items to a meeting. */\n  createMeetingNotes(\n    input: MeetingNotesInput,\n    options?: RequestOptions,\n  ): Promise<unknown> {\n    return request(this.cfg, {\n      method: \"POST\",\n      path: `${PUBLIC_PREFIX}/meeting-notes`,\n      body: input,\n      options,\n    });\n  }\n\n  // ─── Chat (used by initChat widget) ─────────────────────────────────────\n\n  /**\n   * Fetch the dashboard-authored web-chat config for a workflow. Backed by\n   * GET /api/public/chat/config. The widget calls this once on init to learn\n   * whether web chat is enabled and to get the static opening message\n   * (`initial_message`, a RAW template that may contain {{variables}} — the\n   * widget substitutes them client-side before painting the greeting).\n   *\n   * Most users will not call this directly — `initChat()` handles it.\n   */\n  getChatConfig(\n    workflowId: UUID,\n    options?: RequestOptions,\n  ): Promise<{\n    success: true;\n    enabled: boolean;\n    initial_message: string | null;\n  }> {\n    return request(this.cfg, {\n      method: \"GET\",\n      path: `${PUBLIC_PREFIX}/chat/config`,\n      query: { workflow_id: workflowId },\n      options,\n    });\n  }\n\n  /**\n   * Send a turn in a browser-embedded chat session. Backed by\n   * POST /api/public/chat on the Nexor API.\n   *\n   * Most users will not call this directly — `initChat()` handles it.\n   */\n  chat(\n    input: {\n      workflow_id: UUID;\n      session_id: string;\n      message: string;\n      system_prompt?: string;\n      client_prompt?: string;\n      /** The opening message the widget actually displayed (keeps the agent's\n       *  <webchat_opening> in sync with a per-page override). */\n      opening_shown?: string;\n      /** Start over as a brand-new lead: the API skips email/phone/session\n       *  matching and mints a fresh lead with no prior conversation context. */\n      new_lead?: boolean;\n      /** Keep the same lead but start a fresh conversation episode: the API\n       *  deactivates the prior run + thread and clears this workflow's collected\n       *  variables, so the agent sees no prior context. */\n      reset_episode?: boolean;\n      lead?: {\n        first_name?: string;\n        last_name?: string;\n        email?: string;\n        phone?: string;\n        metadata?: Record<string, unknown>;\n      };\n      metadata?: Record<string, unknown>;\n    },\n    options?: RequestOptions,\n  ): Promise<{\n    success: true;\n    reply: string;\n    session_id: string;\n    lead_id?: UUID;\n    workflow_run_id?: UUID;\n    /** True when the API recognised an existing lead (returning visitor). */\n    matched_existing?: boolean;\n  }> {\n    return request(this.cfg, {\n      method: \"POST\",\n      path: `${PUBLIC_PREFIX}/chat`,\n      body: input,\n      options,\n    });\n  }\n\n  /**\n   * Create (or upsert) a lead from the web chat widget and force its FIRST\n   * contact to go out on a chosen channel — used when a visitor clicks\n   * \"call me\" / \"email me\" instead of opening the chat. Backed by\n   * POST /api/public/leads with `force_first_channel`.\n   *\n   * Unlike a literal `force_first_message`, `force_first_channel` pins the\n   * channel and lets the workflow's own agent compose the first outreach. The\n   * `metadata` you pass (page URL, requested channel, a note that the visitor\n   * asked to be contacted from the website) is stored on the lead so the agent\n   * has that context.\n   *\n   * Most users will not call this directly — `initChat()`'s contact-request\n   * form handles it.\n   */\n  requestContact(\n    input: {\n      workflow_id: UUID;\n      first_name?: string;\n      last_name?: string;\n      email?: string;\n      phone?: string;\n      /** Force the first contact onto this channel (agent composes the message). */\n      force_first_channel: \"call\" | \"email\" | \"whatsapp\";\n      /** Context stored on the lead (page URL, requested channel, free-form note). */\n      metadata?: Record<string, unknown>;\n      /** Lead source label. Defaults to \"web-chat\" server-side handling. */\n      source?: string;\n    },\n    options?: RequestOptions,\n  ): Promise<{\n    success: true;\n    lead: { id: UUID; first_name?: string; email?: string; phone?: string };\n    existed?: boolean;\n    workflow_run?: { id: UUID };\n    force_first_channel?: { channel: string; applied: boolean };\n    warning?: string;\n  }> {\n    return request(this.cfg, {\n      method: \"POST\",\n      path: `${PUBLIC_PREFIX}/leads`,\n      body: input,\n      options,\n    });\n  }\n}\n","/**\n * Chat widget configuration types + defaults.\n *\n * Kept separate from the widget's runtime code so other modules (and the\n * top-level `nexor.initChat()` re-export) can pull types without dragging in\n * the DOM construction code.\n */\nimport type { UUID } from \"../types\";\n\n// ─── Public option / handle types ──────────────────────────────────────────\n\nexport interface ChatLeadCapture {\n  /** Which fields to ask for before chatting. Defaults to [\"first_name\", \"email\"]. */\n  fields?: Array<\"first_name\" | \"last_name\" | \"email\" | \"phone\">;\n  /** \"before\" gates chat behind the form; \"skip\" never asks. Default \"before\". */\n  mode?: \"before\" | \"skip\";\n  /** Create the lead in Nexor the INSTANT the form is submitted (via POST\n   *  /leads), instead of waiting for the visitor's first chat message. Captures\n   *  visitors who fill the form but never send a message. Default false. */\n  createLeadOnSubmit?: boolean;\n  /** Heading rendered above the form (its own view). */\n  label?: string;\n  /** Submit button label. */\n  submitLabel?: string;\n  /** Per-field placeholder overrides (for localization). */\n  placeholders?: Partial<\n    Record<\"first_name\" | \"last_name\" | \"email\" | \"phone\", string>\n  >;\n  /** Default country for the phone field — a dial code (\"+56\") or ISO (\"CL\").\n   *  Sets the initial flag, prefix and max length. */\n  phoneCountryCode?: string;\n  /** Restrict the phone country selector to these ISO codes (e.g. [\"CL\",\"AR\"]),\n   *  in this order. Omit to offer the full built-in list. */\n  phoneCountries?: string[];\n  /** Validation error copy (for localization). */\n  errorMessages?: {\n    required?: string;\n    email?: string;\n    phone?: string;\n  };\n}\n\n/** The actions that can appear in the hover/speed-dial fan above the launcher. */\nexport type ChatChannelKey = \"whatsapp\" | \"call\" | \"email\" | \"instagram\" | \"chat\";\n\n/** Channels that can open the in-widget contact-request form. */\nexport type ContactRequestChannel = \"call\" | \"email\" | \"whatsapp\";\n\n/**\n * Turns the `call` / `email` (optionally `whatsapp`) fan buttons into an\n * in-widget contact-request FORM instead of a tel:/mailto: link. The visitor\n * fills name + email + phone, and on submit the widget creates a lead in Nexor\n * and forces the FIRST contact to go out on that channel (the workflow's agent\n * composes the message), with context that they requested it from the website.\n *\n * All copy is per-channel so it can be localized; sensible English defaults\n * apply when omitted.\n */\nexport interface ChatRequestContact {\n  /** Fan channels that open the form instead of navigating. Default [\"call\",\"email\"]. */\n  channels?: ContactRequestChannel[];\n  /** Heading above the form, per channel. */\n  title?: Partial<Record<ContactRequestChannel, string>>;\n  /** Explainer line (e.g. \"we need this info to contact you\"), per channel. */\n  subtitle?: Partial<Record<ContactRequestChannel, string>>;\n  /** Submit button label, per channel. */\n  submitLabel?: Partial<Record<ContactRequestChannel, string>>;\n  /** Confirmation shown after a successful request, per channel. */\n  successText?: Partial<Record<ContactRequestChannel, string>>;\n  /** Label for the button that dismisses the success screen. Default \"Done\". */\n  doneLabel?: string;\n  /** Error shown when the request fails. */\n  errorText?: string;\n}\n\n/**\n * Optional \"speed-dial\" channels shown when the visitor hovers (desktop) or taps\n * (touch) the launcher bubble. Instead of opening the chat immediately, the\n * launcher fans out a column of round buttons — WhatsApp, call, email, Instagram,\n * and an \"open chat\" button — letting the visitor pick a channel.\n *\n * If only `chat` would be enabled (no other channel supplied), the fan is skipped\n * and the launcher keeps its default behaviour (click opens the chat).\n */\nexport interface ChatChannels {\n  /** WhatsApp number in international format (e.g. \"+56912345678\"). Opens wa.me. */\n  whatsapp?: string;\n  /** Pre-filled WhatsApp message text. */\n  whatsappText?: string;\n  /** Phone number for the call button (e.g. \"+56912345678\"). Opens tel:. */\n  call?: string;\n  /** Email address. Opens mailto:. */\n  email?: string;\n  /** Instagram handle (\"nexor.ai\") or full profile URL. */\n  instagram?: string;\n  /** Include a button that opens the chat panel. Defaults to true. */\n  chat?: boolean;\n  /** Top-to-bottom order of the fan buttons. Defaults to the order below. */\n  order?: ChatChannelKey[];\n  /** Accessible labels / hover tooltips per channel. */\n  labels?: Partial<Record<ChatChannelKey, string>>;\n  /** Turn `call`/`email` (and optionally `whatsapp`) into an in-widget\n   *  contact-request form that creates a lead and forces first contact on that\n   *  channel, instead of opening a tel:/mailto: link. Omit to keep magic links. */\n  requestContact?: ChatRequestContact;\n}\n\nexport interface ChatInitOptions {\n  /** Workflow that handles this chat conversation. Required. */\n  workflowId: UUID;\n\n  // ── Identity / branding ──\n  title?: string;\n  subtitle?: string;\n  /**\n   * Force the opening message for this widget instance. Highest priority —\n   * WINS over the dashboard `initial_message` and over `greeting`. Use it for\n   * per-page openings (e.g. an ecommerce-specific greeting on /ecommerce).\n   * Supports the same {{first_name}} / {{last_name}} / {{full_name}} / {{email}}\n   * / {{phone}} tokens, substituted from the captured/known lead.\n   */\n  openingMessage?: string;\n  /** Fallback opening, used only when neither `openingMessage` nor the\n   *  dashboard `initial_message` is set. */\n  greeting?: string;\n  /** Shown when a turn fails or the server returns no reply. */\n  errorText?: string;\n  /** Shown when web chat is disabled for the workflow (channel turned off in\n   *  the dashboard, or the API reports it unavailable). */\n  disabledText?: string;\n  /** BCP-47 locale for timestamps (e.g. \"es\", \"en-US\"). Defaults to the browser. */\n  locale?: string;\n  /** Hex colour for bubble + accents. Defaults to #111827. */\n  accentColor?: string;\n  /** Text colour rendered on top of the accent. Defaults to white. */\n  accentTextColor?: string;\n  /** Show the \"Powered by Nexor\" footer. Defaults to true. */\n  showBranding?: boolean;\n  /** Composer placeholder once chat is active. Default \"Type a message…\". */\n  inputPlaceholder?: string;\n  /** Show a header \"start over\" control that wipes the conversation and starts a\n   *  BRAND-NEW lead (the backend won't re-match the old one). Default true. */\n  showRestart?: boolean;\n  /** aria-label / tooltip for the header restart control. Default \"Start over\". */\n  restartLabel?: string;\n\n  // ── Behaviour ──\n  position?: \"bottom-right\" | \"bottom-left\";\n  /** Auto-open the panel on first load. Defaults to false. */\n  openOnLoad?: boolean;\n  /**\n   * Turn the launcher into a hover/tap \"speed-dial\" that fans out channel\n   * buttons (WhatsApp, call, email, Instagram, chat) instead of opening the\n   * chat right away. Omit for the classic click-to-open launcher.\n   */\n  channels?: ChatChannels;\n  /** Coalesce rapid-fire messages: wait this many ms of quiet, then send the\n   *  buffered messages as one combined turn. Defaults to 700. 0 = per message. */\n  debounceMs?: number;\n  /** Split a bot reply into separate bubbles on blank lines (paragraph breaks),\n   *  WhatsApp-style. Defaults to true. Set false to keep one bubble per reply. */\n  splitReplies?: boolean;\n  /** Fixed typing pause (ms) shown between split bubbles. Omit for a natural\n   *  3000–5000ms pause scaled by the length of the next message (longer text\n   *  reads as more time spent typing). */\n  splitDelayMs?: number;\n  /** Per-turn request timeout (ms). Agent turns can legitimately take 10-20s,\n   *  so this is generous (default 60000). Chat turns never retry — a timeout\n   *  surfaces the error once rather than re-sending the message. */\n  requestTimeoutMs?: number;\n  /** Append the widget to a custom element. Defaults to document.body. */\n  container?: HTMLElement;\n\n  // ── Prompt injection forwarded to the agent for THIS widget instance ──\n  // ADDITIVE: the API appends these to the workflow prompt (wrapped in\n  // <page_context>), it does NOT replace it. Use for per-page context, e.g. on\n  // /ecommerce: \"The visitor is browsing ecommerce; focus on cart recovery…\".\n  systemPrompt?: string;\n  clientPrompt?: string;\n\n  // ── Lead linking ──\n  /** Pre-known lead info (e.g. a logged-in user). Skips capture if complete. */\n  lead?: {\n    first_name?: string;\n    last_name?: string;\n    email?: string;\n    phone?: string;\n    metadata?: Record<string, unknown>;\n  };\n  capture?: ChatLeadCapture;\n  /** Arbitrary metadata passed with each turn (page URL, UTM, …). Pass a\n   *  FUNCTION to have it resolved fresh on every turn — useful for SPA values\n   *  that change without re-mounting the widget (e.g. the current route). */\n  metadata?:\n    | Record<string, unknown>\n    | (() => Record<string, unknown> | undefined);\n\n  // ── Returning-visitor resume banner ──\n  /** Banner text when a prior conversation is restored but we have no name.\n   *  Default \"Continuing your conversation\". */\n  resumeText?: string;\n  /** Banner text when we know the visitor. `{name}` is replaced with their\n   *  first name (or email / phone as a fallback). Default \"Continuing as {name}\". */\n  resumeWithNameText?: string;\n  /** Label for the reset action in the resume banner. Default \"Start over\". */\n  startOverText?: string;\n\n  // ── Callbacks ──\n  onOpen?: () => void;\n  onClose?: () => void;\n  onMessage?: (msg: { role: \"user\" | \"bot\"; text: string }) => void;\n  onLeadCaptured?: (leadId: UUID) => void;\n  onError?: (err: Error) => void;\n}\n\nexport interface ChatHandle {\n  open(): void;\n  close(): void;\n  toggle(): void;\n  /** Programmatically send a user message. */\n  send(text: string): Promise<void>;\n  /** Tear down the widget and remove all DOM. */\n  destroy(): void;\n  /** Read the current session id (auto-generated on first open). */\n  getSessionId(): string;\n}\n\n// ─── Internal resolved-config type ─────────────────────────────────────────\n\n/** Fully-resolved capture config — every field present, no `undefined`. */\nexport interface ResolvedCapture {\n  fields: Array<\"first_name\" | \"last_name\" | \"email\" | \"phone\">;\n  mode: \"before\" | \"skip\";\n  createLeadOnSubmit: boolean;\n  label: string;\n  submitLabel: string;\n  placeholders: Partial<\n    Record<\"first_name\" | \"last_name\" | \"email\" | \"phone\", string>\n  >;\n  phoneCountryCode: string;\n  phoneCountries: string[];\n  errorMessages: { required: string; email: string; phone: string };\n}\n\n/** One ready-to-render fan button: an icon key + an href (null = open chat). */\nexport interface ResolvedChannel {\n  key: ChatChannelKey;\n  /** Navigation target. `null` for JS-handled actions (chat + contact form). */\n  href: string | null;\n  /** Open in a new tab? (WhatsApp / Instagram). tel:/mailto: stay in place. */\n  external: boolean;\n  label: string;\n  /** JS-handled action: \"contact\" opens the contact-request form (the `chat`\n   *  key opens the panel). Absent → a plain navigation link. */\n  action?: \"contact\";\n}\n\n/** Fully-resolved contact-request config (every field present). */\nexport interface ResolvedRequestContact {\n  channels: ContactRequestChannel[];\n  title: Partial<Record<ContactRequestChannel, string>>;\n  subtitle: Partial<Record<ContactRequestChannel, string>>;\n  submitLabel: Partial<Record<ContactRequestChannel, string>>;\n  successText: Partial<Record<ContactRequestChannel, string>>;\n  doneLabel: string;\n  errorText: string;\n}\n\nexport interface ResolvedCfg {\n  workflowId: UUID;\n  title: string;\n  subtitle: string;\n  openingMessage?: string;\n  greeting: string;\n  errorText: string;\n  disabledText: string;\n  locale?: string;\n  accentColor: string;\n  accentTextColor: string;\n  showBranding: boolean;\n  inputPlaceholder: string;\n  showRestart: boolean;\n  restartLabel: string;\n  position: \"bottom-right\" | \"bottom-left\";\n  openOnLoad: boolean;\n  /** Resolved fan buttons. Empty array → classic launcher (no fan). */\n  channels: ResolvedChannel[];\n  /** Resolved contact-request copy/behaviour (undefined when not configured). */\n  requestContact?: ResolvedRequestContact;\n  debounceMs: number;\n  splitReplies: boolean;\n  splitDelayMs: number;\n  requestTimeoutMs: number;\n  container?: HTMLElement;\n  systemPrompt?: string;\n  clientPrompt?: string;\n  lead?: ChatInitOptions[\"lead\"];\n  capture: ResolvedCapture;\n  metadata?:\n    | Record<string, unknown>\n    | (() => Record<string, unknown> | undefined);\n  resumeText: string;\n  resumeWithNameText: string;\n  startOverText: string;\n  onOpen?: () => void;\n  onClose?: () => void;\n  onMessage?: (msg: { role: \"user\" | \"bot\"; text: string }) => void;\n  onLeadCaptured?: (leadId: UUID) => void;\n  onError?: (err: Error) => void;\n}\n\n/**\n * Normalize user-provided options into a complete config object with every\n * field set. Downstream code reads from ResolvedCfg and never has to deal\n * with `undefined` for branding / behaviour fields.\n */\nexport function applyDefaults(o: ChatInitOptions): ResolvedCfg {\n  return {\n    workflowId: o.workflowId,\n    title: o.title ?? \"Chat with us\",\n    subtitle: o.subtitle ?? \"We typically reply in a few minutes\",\n    openingMessage: o.openingMessage,\n    greeting: o.greeting ?? \"Hi there! 👋 How can we help?\",\n    errorText:\n      o.errorText ?? \"Sorry, something went wrong. Please try again in a moment.\",\n    disabledText:\n      o.disabledText ?? \"Chat isn't available right now. Please reach us on another channel.\",\n    locale:\n      o.locale ??\n      (typeof navigator !== \"undefined\" ? navigator.language : undefined),\n    accentColor: o.accentColor ?? \"#111827\",\n    accentTextColor: o.accentTextColor ?? \"#ffffff\",\n    showBranding: o.showBranding ?? true,\n    inputPlaceholder: o.inputPlaceholder ?? \"Type a message…\",\n    showRestart: o.showRestart ?? true,\n    restartLabel: o.restartLabel ?? \"Start over\",\n    position: o.position ?? \"bottom-right\",\n    openOnLoad: o.openOnLoad ?? false,\n    channels: resolveChannels(o.channels),\n    requestContact: resolveRequestContact(o.channels?.requestContact),\n    debounceMs: o.debounceMs ?? 700,\n    splitReplies: o.splitReplies ?? true,\n    splitDelayMs: o.splitDelayMs ?? 0, // 0 = auto (random 1000–1500ms per bubble)\n    requestTimeoutMs: o.requestTimeoutMs ?? 60_000,\n    container: o.container,\n    systemPrompt: o.systemPrompt,\n    clientPrompt: o.clientPrompt,\n    lead: o.lead,\n    capture: {\n      fields: o.capture?.fields ?? [\"first_name\", \"email\"],\n      mode: o.capture?.mode ?? \"before\",\n      createLeadOnSubmit: o.capture?.createLeadOnSubmit ?? false,\n      label: o.capture?.label ?? \"Tell us a bit about you to get started:\",\n      submitLabel: o.capture?.submitLabel ?? \"Start chat\",\n      placeholders: o.capture?.placeholders ?? {},\n      phoneCountryCode: o.capture?.phoneCountryCode ?? \"\",\n      phoneCountries: o.capture?.phoneCountries ?? [],\n      errorMessages: {\n        required: o.capture?.errorMessages?.required ?? \"Please complete this field.\",\n        email: o.capture?.errorMessages?.email ?? \"Enter a valid email address.\",\n        phone:\n          o.capture?.errorMessages?.phone ??\n          \"Enter a valid phone number, including the country code.\",\n      },\n    },\n    metadata: o.metadata,\n    resumeText: o.resumeText ?? \"Continuing your conversation\",\n    resumeWithNameText: o.resumeWithNameText ?? \"Continuing as {name}\",\n    startOverText: o.startOverText ?? \"Start over\",\n    onOpen: o.onOpen,\n    onClose: o.onClose,\n    onMessage: o.onMessage,\n    onLeadCaptured: o.onLeadCaptured,\n    onError: o.onError,\n  };\n}\n\n// ─── Channel (speed-dial) resolution ───────────────────────────────────────\n\nconst DEFAULT_CHANNEL_ORDER: ChatChannelKey[] = [\n  \"whatsapp\",\n  \"call\",\n  \"email\",\n  \"instagram\",\n  \"chat\",\n];\n\nconst DEFAULT_CHANNEL_LABELS: Record<ChatChannelKey, string> = {\n  whatsapp: \"WhatsApp\",\n  call: \"Call\",\n  email: \"Email\",\n  instagram: \"Instagram\",\n  chat: \"Chat\",\n};\n\n/**\n * Turn the user's `channels` option into a flat, ordered list of fan buttons.\n *\n * A button is only included when its underlying value is present (a WhatsApp\n * number, a phone number, …). The chat button is included unless explicitly\n * disabled. If the result would be \"chat only\" (no real channel to dial), the\n * fan is pointless, so we return `[]` and the launcher keeps its classic\n * click-to-open behaviour.\n */\nexport function resolveChannels(c?: ChatChannels): ResolvedChannel[] {\n  if (!c) return [];\n  const order = c.order ?? DEFAULT_CHANNEL_ORDER;\n  const label = (k: ChatChannelKey) =>\n    c.labels?.[k] ?? DEFAULT_CHANNEL_LABELS[k];\n\n  // Channels routed through the in-widget contact-request form (JS-handled),\n  // not a tel:/mailto:/wa.me link. A contact channel shows its button even\n  // without an underlying value — the form collects the VISITOR's details.\n  const contactChannels = new Set<ContactRequestChannel>(\n    c.requestContact ? c.requestContact.channels ?? [\"call\", \"email\"] : [],\n  );\n  const contactBtn = (key: ChatChannelKey): ResolvedChannel => ({\n    key,\n    href: null,\n    external: false,\n    action: \"contact\",\n    label: label(key),\n  });\n\n  // De-dupe while preserving the requested order.\n  const seen = new Set<ChatChannelKey>();\n  const out: ResolvedChannel[] = [];\n\n  for (const key of order) {\n    if (seen.has(key)) continue;\n    seen.add(key);\n\n    switch (key) {\n      case \"whatsapp\": {\n        if (contactChannels.has(\"whatsapp\")) { out.push(contactBtn(key)); break; }\n        if (!c.whatsapp) break;\n        const digits = c.whatsapp.replace(/[^\\d]/g, \"\");\n        if (!digits) break;\n        const qs = c.whatsappText\n          ? `?text=${encodeURIComponent(c.whatsappText)}`\n          : \"\";\n        out.push({ key, href: `https://wa.me/${digits}${qs}`, external: true, label: label(key) });\n        break;\n      }\n      case \"call\": {\n        if (contactChannels.has(\"call\")) { out.push(contactBtn(key)); break; }\n        if (!c.call) break;\n        const tel = c.call.replace(/[^\\d+]/g, \"\");\n        if (!tel) break;\n        out.push({ key, href: `tel:${tel}`, external: false, label: label(key) });\n        break;\n      }\n      case \"email\": {\n        if (contactChannels.has(\"email\")) { out.push(contactBtn(key)); break; }\n        if (!c.email) break;\n        out.push({ key, href: `mailto:${c.email}`, external: false, label: label(key) });\n        break;\n      }\n      case \"instagram\": {\n        if (!c.instagram) break;\n        const href = /^https?:\\/\\//i.test(c.instagram)\n          ? c.instagram\n          : `https://instagram.com/${c.instagram.replace(/^@/, \"\")}`;\n        out.push({ key, href, external: true, label: label(key) });\n        break;\n      }\n      case \"chat\": {\n        if (c.chat === false) break;\n        out.push({ key, href: null, external: false, label: label(key) });\n        break;\n      }\n    }\n  }\n\n  // \"chat only\" → no real channel to dial, so the fan adds nothing. Fall back\n  // to the classic launcher.\n  if (out.every((ch) => ch.key === \"chat\")) return [];\n  return out;\n}\n\n// Default English copy for the contact-request form. Spanish (and any other\n// locale) is supplied by the embedder via channels.requestContact.\nconst DEFAULT_CONTACT_TITLE: Record<ContactRequestChannel, string> = {\n  call: \"Request a call\",\n  email: \"Request an email\",\n  whatsapp: \"Request a message\",\n};\nconst DEFAULT_CONTACT_SUBTITLE: Record<ContactRequestChannel, string> = {\n  call: \"Leave your details and we'll call you. We need this to reach you.\",\n  email: \"Leave your details and we'll email you. We need this to reach you.\",\n  whatsapp: \"Leave your details and we'll message you. We need this to reach you.\",\n};\nconst DEFAULT_CONTACT_SUBMIT: Record<ContactRequestChannel, string> = {\n  call: \"Request call\",\n  email: \"Request email\",\n  whatsapp: \"Request message\",\n};\nconst DEFAULT_CONTACT_SUCCESS: Record<ContactRequestChannel, string> = {\n  call: \"Thanks! We'll call you shortly.\",\n  email: \"Thanks! We'll email you shortly.\",\n  whatsapp: \"Thanks! We'll message you shortly.\",\n};\n\n/**\n * Resolve the contact-request config, filling English defaults. Returns\n * undefined when the embedder didn't opt in (so the fan keeps magic links).\n */\nexport function resolveRequestContact(\n  rc?: ChatRequestContact,\n): ResolvedRequestContact | undefined {\n  if (!rc) return undefined;\n  const channels: ContactRequestChannel[] =\n    rc.channels && rc.channels.length ? rc.channels : [\"call\", \"email\"];\n  const pick = (\n    over: Partial<Record<ContactRequestChannel, string>> | undefined,\n    def: Record<ContactRequestChannel, string>,\n  ): Partial<Record<ContactRequestChannel, string>> => {\n    const out: Partial<Record<ContactRequestChannel, string>> = {};\n    for (const ch of channels) out[ch] = over?.[ch] ?? def[ch];\n    return out;\n  };\n  return {\n    channels,\n    title: pick(rc.title, DEFAULT_CONTACT_TITLE),\n    subtitle: pick(rc.subtitle, DEFAULT_CONTACT_SUBTITLE),\n    submitLabel: pick(rc.submitLabel, DEFAULT_CONTACT_SUBMIT),\n    successText: pick(rc.successText, DEFAULT_CONTACT_SUCCESS),\n    doneLabel: rc.doneLabel ?? \"Done\",\n    errorText: rc.errorText ?? \"Something went wrong. Please try again.\",\n  };\n}\n\n/**\n * Does this widget need to show a lead-capture form before chat?\n *   - \"skip\" mode → no\n *   - Pre-known lead already covers every required field → no\n *   - Otherwise → yes\n */\nexport function needsCapture(cfg: ResolvedCfg): boolean {\n  if (cfg.capture.mode === \"skip\") return false;\n  if (cfg.lead) {\n    const have = cfg.lead;\n    return cfg.capture.fields.some((f) => !have[f]);\n  }\n  return true;\n}\n","/**\n * Browser-side session-id management for the chat widget.\n *\n * The session id links anonymous turns to the same lead across page reloads.\n * It's persisted in localStorage with a last-activity timestamp and a sliding\n * retention window: a conversation is kept for at least SESSION_RETENTION_MS\n * after the last activity, after which a fresh session (and transcript) starts.\n * If storage is unavailable (private mode, sandboxed iframe) we fall back to a\n * per-tab id and accept that a refresh starts a new conversation.\n */\n\nconst SESSION_KEY = \"nexor.chat.session_id\";\n\n/** Keep a conversation (session + transcript) this long after the last\n *  activity, so a returning visitor can resume it. Reused by the transcript\n *  cache in `./index`. The host (e.g. the landing widget) decides when to\n *  auto-resume vs. prompt \"continue or start new\". */\nexport const SESSION_RETENTION_MS = 30 * 24 * 60 * 60 * 1000; // 30 days\n\n/**\n * Return the persisted session id, generating one on first use or once the\n * retention window has lapsed. Reading it slides the window forward.\n */\nexport function ensureSessionId(): string {\n  const now = Date.now();\n  try {\n    const rec = readRecord();\n    if (rec && now - rec.ts < SESSION_RETENTION_MS) {\n      writeRecord(rec.id, now); // slide the window on activity\n      return rec.id;\n    }\n  } catch {\n    /* localStorage may be unavailable (private mode, sandboxed iframe). */\n  }\n  const id = `sess_${randomHex(16)}`;\n  try {\n    writeRecord(id, now);\n  } catch {\n    /* ignore — id is still valid for this page load. */\n  }\n  return id;\n}\n\n/**\n * Mint a brand-new session id (and persist it), discarding the current one.\n * Used by the widget's \"start over\" action so a returning visitor can begin a\n * fresh conversation instead of resuming the persisted transcript.\n */\nexport function resetSession(): string {\n  const id = `sess_${randomHex(16)}`;\n  try {\n    writeRecord(id, Date.now());\n  } catch {\n    /* ignore — id is still valid for this page load. */\n  }\n  return id;\n}\n\n/** Bump the session's last-activity timestamp (slides the retention window). */\nexport function touchSession(): void {\n  try {\n    const rec = readRecord();\n    if (rec) writeRecord(rec.id, Date.now());\n  } catch {\n    /* ignore */\n  }\n}\n\nfunction readRecord(): { id: string; ts: number } | null {\n  const raw = window.localStorage.getItem(SESSION_KEY);\n  if (!raw) return null;\n  try {\n    const o = JSON.parse(raw);\n    if (o && typeof o.id === \"string\" && typeof o.ts === \"number\") return o;\n  } catch {\n    /* legacy value was a plain \"sess_…\" string — adopt it below. */\n  }\n  if (raw.startsWith(\"sess_\")) return { id: raw, ts: Date.now() };\n  return null;\n}\n\nfunction writeRecord(id: string, ts: number): void {\n  window.localStorage.setItem(SESSION_KEY, JSON.stringify({ id, ts }));\n}\n\n/**\n * Hex string from cryptographically-strong randomness when available, with\n * a Math.random() fallback for very old browsers.\n */\nfunction randomHex(bytes: number): string {\n  const arr = new Uint8Array(bytes);\n  if (typeof crypto !== \"undefined\" && crypto.getRandomValues) {\n    crypto.getRandomValues(arr);\n  } else {\n    for (let i = 0; i < bytes; i++) arr[i] = Math.floor(Math.random() * 256);\n  }\n  return Array.from(arr, (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n}\n","/**\n * Lightweight capture-field validation.\n *\n * Goal: reject input that's *obviously* wrong (no country code, junk length,\n * malformed email) without pretending to be a full libphonenumber. Kept\n * dependency-free and permissive enough not to block real users.\n */\n\n/**\n * Email sanity check: `local@domain.tld`, no spaces, a dotted domain with a 2+\n * letter TLD, and sane lengths. Deliberately not RFC-5322-exhaustive, but tight\n * enough to reject the common mistakes the loose `[^\\s@]+@[^\\s@]+\\.[^\\s@]{2,}`\n * pattern used to wave through: double \"@\" (`a@@b.com`), consecutive or edge\n * dots (`a@b..com`, `.a@b.com`, `a.@b.com`), and numeric-only TLDs (`a@b.12`).\n *\n * Enforces, beyond the regex:\n *   - RFC 5321 length limits (254 total, 64 for the local part)\n *   - exactly one \"@\" with a non-empty local and domain part\n *   - no leading / trailing / consecutive dots in either part\n *   - a domain TLD of at least two letters\n */\nconst EMAIL_RE =\n  /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$/;\n\nexport function isValidEmail(value: string): boolean {\n  const s = (value || \"\").trim();\n  if (s.length < 6 || s.length > 254) return false;\n\n  const at = s.lastIndexOf(\"@\");\n  if (at < 1) return false;\n\n  const local = s.slice(0, at);\n  const domain = s.slice(at + 1);\n\n  if (local.length > 64) return false;\n  if (local.startsWith(\".\") || local.endsWith(\".\") || local.includes(\"..\")) {\n    return false;\n  }\n  if (domain.includes(\"..\")) return false;\n\n  // TLD must be at least two letters (rejects \"a@b\", \"a@b.1\", \"a@b.c\").\n  if (!/\\.[a-zA-Z]{2,}$/.test(domain)) return false;\n\n  return EMAIL_RE.test(s);\n}\n\n/**\n * Normalize a typed phone number toward E.164 (`+<country><national>`):\n *   - strip spaces, dashes, dots, parens\n *   - `00<cc>…` → `+<cc>…` (international call prefix)\n *   - no leading `+` but a `defaultDialCode` is configured → assume the number\n *     is national: drop a trunk \"0\" and prepend the dial code\n * Anything already starting with `+` is left as-is (minus formatting).\n */\nexport function normalizePhone(raw: string, defaultDialCode?: string): string {\n  let s = (raw || \"\").trim().replace(/[\\s().-]/g, \"\");\n  if (s.startsWith(\"00\")) s = \"+\" + s.slice(2);\n  if (!s.startsWith(\"+\") && defaultDialCode) {\n    const dial = defaultDialCode.replace(/[^\\d]/g, \"\");\n    if (dial) s = \"+\" + dial + s.replace(/^0+/, \"\");\n  }\n  return s;\n}\n\n/**\n * Validate an already-normalized phone string. Requires a country code (leading\n * `+`) and an E.164-plausible length (8–15 digits total, country code never\n * starts with 0). This is the \"has a country code and a sane length\" check the\n * widget enforces.\n */\nexport function isValidPhone(e164: string): boolean {\n  if (!/^\\+\\d+$/.test(e164)) return false; // must be \"+\" then digits only\n  const digits = e164.slice(1);\n  if (digits.length < 8 || digits.length > 15) return false;\n  if (digits.startsWith(\"0\")) return false; // no valid calling code starts with 0\n  return true;\n}\n","/**\n * Client-side {{lead variable}} substitution for the web-chat opening message.\n *\n * The dashboard-authored opening (`ai_config.webchat.initial_message`, returned\n * by GET /api/public/chat/config) is a RAW template like\n * \"Hola {{first_name}}, ¿en qué te ayudamos?\". The widget renders it here before\n * painting the greeting bubble.\n *\n * This MUST stay in lockstep with the server's renderer\n * (nexor-node-api `src/shared/render-lead-template.js`) so the visitor sees the\n * same greeting the agent is told was shown. Same tokens, aliases, and tidy-up.\n *\n * Tokens are case-insensitive and tolerate inner spaces: {{name}}, {{ Name }}.\n * Unknown tokens are left untouched. Missing/empty values resolve to \"\" and the\n * result is tidied so \"Hola {{first_name}},\" with no name reads \"Hola,\".\n */\n\nexport interface TemplateLead {\n  first_name?: string;\n  last_name?: string;\n  email?: string;\n  phone?: string;\n}\n\n// Friendly aliases → canonical lead field. Keep in sync with the server's\n// ALIASES map and the dashboard's LEAD_TEMPLATE_VARIABLES.\nconst ALIASES: Record<string, keyof TemplateLead | \"full_name\"> = {\n  first_name: \"first_name\",\n  name: \"first_name\",\n  lead_first_name: \"first_name\",\n  last_name: \"last_name\",\n  lastname: \"last_name\",\n  lead_last_name: \"last_name\",\n  full_name: \"full_name\",\n  fullname: \"full_name\",\n  email: \"email\",\n  phone: \"phone\",\n};\n\nfunction clean(v: unknown): string {\n  return v == null ? \"\" : String(v).trim();\n}\n\nfunction leadValue(lead: TemplateLead | null | undefined, canonical: string): string {\n  if (!lead) return \"\";\n  switch (canonical) {\n    case \"first_name\":\n      return clean(lead.first_name);\n    case \"last_name\":\n      return clean(lead.last_name);\n    case \"full_name\":\n      return [clean(lead.first_name), clean(lead.last_name)].filter(Boolean).join(\" \");\n    case \"email\":\n      return clean(lead.email);\n    case \"phone\":\n      return clean(lead.phone);\n    default:\n      return \"\";\n  }\n}\n\n/**\n * Render a template against a lead. Returns \"\" for empty/non-string input.\n */\nexport function renderLeadTemplate(\n  template: string | null | undefined,\n  lead: TemplateLead | null | undefined,\n): string {\n  if (typeof template !== \"string\" || !template) return \"\";\n\n  const replaced = template.replace(/\\{\\{\\s*([a-zA-Z_]+)\\s*\\}\\}/g, (match, raw: string) => {\n    const canonical = ALIASES[raw.toLowerCase()];\n    if (!canonical) return match; // leave unknown tokens as-authored\n    return leadValue(lead, canonical);\n  });\n\n  // Tidy leftovers from empty substitutions (mirrors the server):\n  //   \"Hola ,\"  → \"Hola,\"   ·   \"Hola  Ana\" → \"Hola Ana\"\n  //   \", hola\"  → \"hola\"     ·   trim trailing space per line, then overall.\n  return replaced\n    .replace(/[ \\t]+([,.!?;:])/g, \"$1\")\n    .replace(/[ \\t]{2,}/g, \" \")\n    .replace(/^[ \\t]*[,;:][ \\t]*/gm, \"\")\n    .replace(/[ \\t]+$/gm, \"\")\n    .trim();\n}\n","/**\n * Country table for the phone capture field.\n *\n * The ONE place to manage dial codes, flags and number lengths. To add/adjust a\n * country, edit a row here — the flag selector, the max-length cap on the input,\n * and validation all read from this. `nsn` is the national significant number\n * length (digits AFTER the dial code) as [min, max].\n *\n * Flags are emoji (regional-indicator pairs) so there are no image assets; they\n * render natively on macOS/iOS/Android. Windows falls back to the ISO letters.\n */\nexport interface Country {\n  iso: string; // ISO-3166 alpha-2, e.g. \"CL\"\n  name: string;\n  dial: string; // E.164 calling code with leading \"+\", e.g. \"+56\"\n  flag: string; // emoji flag\n  nsn: [number, number]; // national number length [min, max] in digits\n}\n\n/** Fallback when no default resolves — also the first row in the list. */\nexport const FALLBACK_COUNTRY: Country = {\n  iso: \"CL\",\n  name: \"Chile\",\n  dial: \"+56\",\n  flag: \"🇨🇱\",\n  nsn: [9, 9],\n};\n\nexport const COUNTRIES: Country[] = [\n  FALLBACK_COUNTRY,\n  { iso: \"MX\", name: \"México\", dial: \"+52\", flag: \"🇲🇽\", nsn: [10, 10] },\n  { iso: \"AR\", name: \"Argentina\", dial: \"+54\", flag: \"🇦🇷\", nsn: [10, 11] },\n  { iso: \"CO\", name: \"Colombia\", dial: \"+57\", flag: \"🇨🇴\", nsn: [10, 10] },\n  { iso: \"PE\", name: \"Perú\", dial: \"+51\", flag: \"🇵🇪\", nsn: [9, 9] },\n  { iso: \"BR\", name: \"Brasil\", dial: \"+55\", flag: \"🇧🇷\", nsn: [10, 11] },\n  { iso: \"EC\", name: \"Ecuador\", dial: \"+593\", flag: \"🇪🇨\", nsn: [8, 9] },\n  { iso: \"UY\", name: \"Uruguay\", dial: \"+598\", flag: \"🇺🇾\", nsn: [8, 8] },\n  { iso: \"US\", name: \"United States\", dial: \"+1\", flag: \"🇺🇸\", nsn: [10, 10] },\n  { iso: \"ES\", name: \"España\", dial: \"+34\", flag: \"🇪🇸\", nsn: [9, 9] },\n  { iso: \"GB\", name: \"United Kingdom\", dial: \"+44\", flag: \"🇬🇧\", nsn: [10, 10] },\n];\n\n/** Longest national number across all rows — used as a safe input maxlength fallback. */\nexport function maxNsn(c: Country): number {\n  return c.nsn[1];\n}\n\nexport function countryByIso(iso?: string): Country | undefined {\n  if (!iso) return undefined;\n  const up = iso.toUpperCase();\n  return COUNTRIES.find((c) => c.iso === up);\n}\n\n/** First country matching a dial code (\"+1\" → US). */\nexport function countryByDial(dial?: string): Country | undefined {\n  if (!dial) return undefined;\n  const norm = dial.startsWith(\"+\") ? dial : `+${dial.replace(/^\\+?/, \"\")}`;\n  return COUNTRIES.find((c) => c.dial === norm);\n}\n\n/**\n * Resolve the default country from a `phoneCountryCode` (a dial like \"+56\") or an\n * ISO code, falling back to the first row.\n */\nexport function resolveDefaultCountry(codeOrIso?: string): Country {\n  const v = (codeOrIso || \"\").trim();\n  return countryByDial(v) || countryByIso(v) || FALLBACK_COUNTRY;\n}\n","/**\n * Scoped CSS for the chat widget.\n *\n * Everything is namespaced under `.nexor-chat` so it cannot leak into the host\n * page, and properties that hosts commonly override (color, font, line-height)\n * are set explicitly here so the host's reset can't bleed in.\n *\n * Animations are GPU-friendly (transform + opacity only — no layout-trashing\n * properties like top/left) and use modest durations so the widget feels\n * responsive on low-end devices.\n */\nexport const widgetCss = (accent: string, accentText: string): string => `\n.nexor-chat,\n.nexor-chat * {\n  box-sizing: border-box;\n  font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n}\n\n.nexor-chat {\n  position: fixed;\n  z-index: 2147483640;\n  bottom: 20px;\n  right: 20px;\n  font-size: 14px;\n  line-height: 1.4;\n  color: #111;\n}\n\n.nexor-chat[data-position=\"bottom-left\"] {\n  right: auto;\n  left: 20px;\n}\n\n/* ── Launcher wrapper (anchors the optional speed-dial fan) ───────── */\n.nexor-chat__launcher-wrap {\n  position: relative;\n  display: inline-flex;\n}\n\n/* ── Launcher bubble ─────────────────────────────────────────────── */\n.nexor-chat__launcher {\n  width: 56px;\n  height: 56px;\n  border-radius: 9999px;\n  background: ${accent};\n  color: ${accentText};\n  border: none;\n  cursor: pointer;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);\n  transition: transform 160ms cubic-bezier(.2,.7,.2,1.1),\n              box-shadow 160ms ease,\n              background 200ms ease;\n  padding: 0;\n  position: relative;\n  animation: nexor-launcher-in 360ms cubic-bezier(.2,.7,.2,1.1) both;\n}\n.nexor-chat__launcher:hover {\n  transform: translateY(-2px) scale(1.04);\n  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.24);\n}\n.nexor-chat__launcher:active {\n  transform: translateY(0) scale(0.97);\n  transition-duration: 80ms;\n}\n.nexor-chat__launcher:focus-visible {\n  outline: 2px solid ${accent};\n  outline-offset: 2px;\n}\n.nexor-chat[data-open=\"true\"] .nexor-chat__launcher {\n  transform: scale(0.85);\n  opacity: 0.75;\n}\n/* While the chat panel is open the launcher is dormant: no hover fan, no\n   clicks. The visitor closes the chat (header ✕) to reach the channels again.\n   pointer-events:none also stops the CSS :hover that would reveal the fan. */\n.nexor-chat[data-open=\"true\"] .nexor-chat__launcher-wrap {\n  pointer-events: none;\n}\n.nexor-chat__launcher svg { width: 24px; height: 24px; transition: transform 200ms ease; }\n.nexor-chat[data-open=\"true\"] .nexor-chat__launcher svg { transform: rotate(8deg); }\n\n.nexor-chat__unread {\n  position: absolute;\n  top: -4px;\n  right: -4px;\n  min-width: 18px;\n  height: 18px;\n  background: #ef4444;\n  color: #fff;\n  border-radius: 9999px;\n  font-size: 11px;\n  font-weight: 600;\n  padding: 0 5px;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  border: 2px solid #fff;\n  animation: nexor-pop-in 300ms cubic-bezier(.2,.7,.2,1.1) both;\n}\n\n@keyframes nexor-launcher-in {\n  from { transform: translateY(20px) scale(0.6); opacity: 0; }\n  to   { transform: translateY(0) scale(1);     opacity: 1; }\n}\n@keyframes nexor-pop-in {\n  from { transform: scale(0); }\n  to   { transform: scale(1); }\n}\n\n/* ── Speed-dial channel fan ───────────────────────────────────────── */\n/* Sits above the launcher, out of normal flow so it never shifts the bubble.\n   Hidden until the wrapper is hovered (pointer devices) or tapped open\n   (data-expanded, set by JS — the only path on touch). */\n.nexor-chat__channels {\n  position: absolute;\n  /* Anchor the fan's box to the top of the launcher and push the buttons up\n     with padding instead of a gap. This keeps the launcher + fan a single,\n     continuous hover surface — moving the cursor from the bubble up to the\n     buttons never crosses dead space, so the drawer no longer snaps shut. */\n  bottom: 100%;\n  right: 0;\n  padding-bottom: 14px;\n  display: flex;\n  flex-direction: column;\n  gap: 12px;\n  align-items: flex-end;\n  opacity: 0;\n  visibility: hidden;\n  pointer-events: none;\n  transform: translateY(10px);\n  transition: opacity 180ms ease, transform 180ms ease, visibility 180ms;\n}\n.nexor-chat[data-position=\"bottom-left\"] .nexor-chat__channels {\n  right: auto;\n  left: 0;\n  align-items: flex-start;\n}\n\n@media (hover: hover) and (pointer: fine) {\n  .nexor-chat__launcher-wrap:hover .nexor-chat__channels {\n    opacity: 1;\n    visibility: visible;\n    pointer-events: auto;\n    transform: translateY(0);\n  }\n}\n.nexor-chat__launcher-wrap[data-expanded=\"true\"] .nexor-chat__channels {\n  opacity: 1;\n  visibility: visible;\n  pointer-events: auto;\n  transform: translateY(0);\n}\n\n/* Subtle rise-and-stagger as each item appears (nearest the launcher first). */\n.nexor-chat__channel-item {\n  display: flex;\n  align-items: center;\n  gap: 10px;\n  transform: translateY(8px);\n  opacity: 0;\n  transition: transform 200ms cubic-bezier(.2,.7,.2,1.1), opacity 200ms ease;\n}\n.nexor-chat[data-position=\"bottom-left\"] .nexor-chat__channel-item {\n  flex-direction: row-reverse;\n}\n.nexor-chat__launcher-wrap[data-expanded=\"true\"] .nexor-chat__channel-item,\n.nexor-chat__launcher-wrap:hover .nexor-chat__channel-item {\n  transform: translateY(0);\n  opacity: 1;\n}\n.nexor-chat__channel-item:nth-last-child(1) { transition-delay: 0ms; }\n.nexor-chat__channel-item:nth-last-child(2) { transition-delay: 40ms; }\n.nexor-chat__channel-item:nth-last-child(3) { transition-delay: 80ms; }\n.nexor-chat__channel-item:nth-last-child(4) { transition-delay: 120ms; }\n.nexor-chat__channel-item:nth-last-child(5) { transition-delay: 160ms; }\n\n/* The round mini-button for each channel. */\n.nexor-chat__channel {\n  width: 46px;\n  height: 46px;\n  border-radius: 9999px;\n  border: none;\n  cursor: pointer;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  padding: 0;\n  background: ${accent};\n  color: ${accentText};\n  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);\n  text-decoration: none;\n  transition: transform 140ms cubic-bezier(.2,.7,.2,1.1), box-shadow 140ms ease, filter 140ms ease;\n}\n.nexor-chat__channel:hover {\n  transform: scale(1.08);\n  box-shadow: 0 8px 18px rgba(0, 0, 0, 0.26);\n  filter: brightness(1.05);\n}\n.nexor-chat__channel:active { transform: scale(0.94); }\n.nexor-chat__channel:focus-visible { outline: 2px solid ${accent}; outline-offset: 2px; }\n.nexor-chat__channel svg { width: 24px; height: 24px; display: block; }\n\n/* Brand colours win over the accent where a channel has a recognisable hue. */\n.nexor-chat__channel--whatsapp { background: #25d366; color: #fff; }\n.nexor-chat__channel--instagram {\n  background: radial-gradient(circle at 30% 110%, #fdf497 0%, #fd5949 45%, #d6249f 70%, #285aeb 100%);\n  color: #fff;\n}\n\n/* Label pill beside each button. */\n.nexor-chat__channel-label {\n  background: #fff;\n  color: #111;\n  font-size: 12px;\n  font-weight: 600;\n  padding: 5px 10px;\n  border-radius: 8px;\n  white-space: nowrap;\n  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.16);\n}\n\n/* ── Panel ────────────────────────────────────────────────────────── */\n.nexor-chat__panel {\n  position: absolute;\n  bottom: 72px;\n  right: 0;\n  width: 360px;\n  max-width: calc(100vw - 32px);\n  height: 540px;\n  max-height: calc(100vh - 120px);\n  background: #fff;\n  border-radius: 14px;\n  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.22);\n  display: flex;\n  flex-direction: column;\n  overflow: hidden;\n  transform: translateY(14px) scale(0.96);\n  opacity: 0;\n  pointer-events: none;\n  transition: transform 220ms cubic-bezier(.2,.7,.2,1.1),\n              opacity 220ms ease;\n  border: 1px solid rgba(0, 0, 0, 0.06);\n  /* Use visibility so screen readers don't read collapsed content */\n  visibility: hidden;\n}\n.nexor-chat[data-position=\"bottom-left\"] .nexor-chat__panel {\n  right: auto;\n  left: 0;\n}\n.nexor-chat[data-open=\"true\"] .nexor-chat__panel {\n  transform: translateY(0) scale(1);\n  opacity: 1;\n  pointer-events: auto;\n  visibility: visible;\n}\n\n.nexor-chat__header {\n  background: ${accent};\n  color: ${accentText};\n  padding: 14px 16px;\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  gap: 12px;\n}\n.nexor-chat__title {\n  font-weight: 600;\n  font-size: 15px;\n  margin: 0;\n}\n.nexor-chat__subtitle {\n  font-size: 12px;\n  opacity: 0.85;\n  margin: 2px 0 0;\n  line-height: 1.4;\n}\n.nexor-chat__status-dot {\n  display: inline-block;\n  width: 8px;\n  height: 8px;\n  border-radius: 9999px;\n  background: #34d399;\n  margin-right: 6px;\n  vertical-align: 1px;\n  animation: nexor-pulse 2.4s ease-in-out infinite;\n  box-shadow: 0 0 0 0 rgba(52, 211, 153, 0.6);\n}\n@keyframes nexor-pulse {\n  0%, 100% { box-shadow: 0 0 0 0 rgba(52, 211, 153, 0.55); }\n  50%      { box-shadow: 0 0 0 6px rgba(52, 211, 153, 0);    }\n}\n.nexor-chat__close {\n  background: transparent;\n  border: none;\n  color: inherit;\n  cursor: pointer;\n  padding: 4px;\n  border-radius: 6px;\n  opacity: 0.9;\n  transition: background 140ms ease, transform 140ms ease;\n}\n.nexor-chat__close:hover { background: rgba(255,255,255,0.18); opacity: 1; }\n.nexor-chat__close:active { transform: scale(0.92); }\n.nexor-chat__close svg { width: 18px; height: 18px; display: block; }\n/* Keep the title left and group the action buttons on the right. */\n.nexor-chat__header > div { margin-right: auto; min-width: 0; }\n.nexor-chat__restart {\n  background: transparent;\n  border: none;\n  color: inherit;\n  cursor: pointer;\n  padding: 4px;\n  border-radius: 6px;\n  opacity: 0.7;\n  transition: background 140ms ease, transform 200ms ease, opacity 140ms ease;\n}\n.nexor-chat__restart:hover { background: rgba(255,255,255,0.18); opacity: 1; }\n.nexor-chat__restart:active { transform: rotate(-90deg) scale(0.9); }\n.nexor-chat__restart svg { width: 17px; height: 17px; display: block; }\n/* Nothing to reset on the capture screen — hide it there. */\n.nexor-chat__panel[data-view=\"capture\"] .nexor-chat__restart { display: none; }\n\n/* ── Body / messages ──────────────────────────────────────────────── */\n.nexor-chat__body {\n  flex: 1;\n  overflow-y: auto;\n  padding: 14px;\n  background: #f6f7f9;\n  display: flex;\n  flex-direction: column;\n  gap: 8px;\n  scroll-behavior: smooth;\n  /* Prevent layout shift when scrollbar appears */\n  scrollbar-gutter: stable;\n}\n.nexor-chat__body::-webkit-scrollbar { width: 6px; }\n.nexor-chat__body::-webkit-scrollbar-thumb {\n  background: rgba(0,0,0,0.15);\n  border-radius: 9999px;\n}\n\n.nexor-chat__msg {\n  max-width: 80%;\n  padding: 8px 12px;\n  border-radius: 14px;\n  white-space: pre-wrap;\n  word-wrap: break-word;\n  animation: nexor-msg-in 240ms cubic-bezier(.2,.7,.2,1.1) both;\n  will-change: transform, opacity;\n}\n.nexor-chat__msg--bot {\n  background: #fff;\n  align-self: flex-start;\n  border: 1px solid rgba(0,0,0,0.06);\n  border-bottom-left-radius: 4px;\n  box-shadow: 0 1px 2px rgba(0,0,0,0.04);\n}\n.nexor-chat__msg--user {\n  background: ${accent};\n  color: ${accentText};\n  align-self: flex-end;\n  border-bottom-right-radius: 4px;\n  animation-name: nexor-msg-in-user;\n}\n.nexor-chat__msg--system {\n  background: transparent;\n  color: #6b7280;\n  font-size: 12px;\n  align-self: center;\n  text-align: center;\n  max-width: 100%;\n  animation-name: nexor-fade-in;\n}\n.nexor-chat__msg-time {\n  display: block;\n  margin-top: 4px;\n  font-size: 10px;\n  line-height: 1;\n  opacity: 0.55;\n  text-align: right;\n}\n.nexor-chat__msg--bot .nexor-chat__msg-time { text-align: left; }\n\n@keyframes nexor-msg-in {\n  from { transform: translateY(8px) scale(0.96); opacity: 0; }\n  to   { transform: translateY(0) scale(1);     opacity: 1; }\n}\n@keyframes nexor-msg-in-user {\n  from { transform: translateY(8px) translateX(8px) scale(0.96); opacity: 0; }\n  to   { transform: translateY(0) translateX(0) scale(1);        opacity: 1; }\n}\n@keyframes nexor-fade-in {\n  from { opacity: 0; }\n  to   { opacity: 1; }\n}\n\n.nexor-chat__typing {\n  align-self: flex-start;\n  background: #fff;\n  border: 1px solid rgba(0,0,0,0.06);\n  border-radius: 14px;\n  border-bottom-left-radius: 4px;\n  padding: 10px 14px;\n  display: inline-flex;\n  gap: 4px;\n  animation: nexor-msg-in 240ms cubic-bezier(.2,.7,.2,1.1) both;\n}\n.nexor-chat__typing span {\n  width: 6px; height: 6px; border-radius: 9999px;\n  background: #9ca3af;\n  display: inline-block;\n  animation: nexor-blink 1.2s infinite ease-in-out;\n}\n.nexor-chat__typing span:nth-child(2) { animation-delay: 0.15s; }\n.nexor-chat__typing span:nth-child(3) { animation-delay: 0.30s; }\n@keyframes nexor-blink {\n  0%, 60%, 100% { opacity: 0.3; transform: translateY(0); }\n  30%           { opacity: 1;   transform: translateY(-3px); }\n}\n\n/* ── Resume banner (returning visitor) ────────────────────────────── */\n.nexor-chat__resume {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  gap: 10px;\n  background: #fff;\n  border: 1px solid rgba(0,0,0,0.06);\n  border-radius: 10px;\n  padding: 8px 12px;\n  margin-bottom: 4px;\n  box-shadow: 0 1px 2px rgba(0,0,0,0.04);\n  animation: nexor-fade-in 240ms ease both;\n}\n.nexor-chat__resume-text {\n  font-size: 12px;\n  color: #6b7280;\n  min-width: 0;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n.nexor-chat__resume-reset {\n  flex: none;\n  background: transparent;\n  border: none;\n  color: ${accent};\n  font: inherit;\n  font-size: 12px;\n  font-weight: 600;\n  cursor: pointer;\n  padding: 2px 4px;\n  border-radius: 6px;\n  text-decoration: underline;\n  text-underline-offset: 2px;\n  transition: opacity 140ms ease;\n}\n.nexor-chat__resume-reset:hover { opacity: 0.7; }\n.nexor-chat__resume-reset:active { opacity: 0.5; }\n\n/* ── Capture as its own full-panel view ───────────────────────────── */\n/* The form is a distinct screen, not a card wedged into the message list.\n   data-view swaps between the capture screen and the chat (body + composer). */\n.nexor-chat__capture-view {\n  min-height: 0;\n  overflow-y: auto;\n  padding: 16px;\n  background: #f6f7f9;\n  display: flex;\n  flex-direction: column;\n  animation: nexor-fade-in 200ms ease both;\n}\n/* In the form view the panel hugs the form — no fixed 540px height leaving\n   empty gaps above and below the card. It still can't exceed max-height. */\n.nexor-chat__panel[data-view=\"capture\"] {\n  height: auto;\n}\n.nexor-chat__panel[data-view=\"chat\"] .nexor-chat__capture-view { display: none; }\n.nexor-chat__panel[data-view=\"capture\"] .nexor-chat__body,\n.nexor-chat__panel[data-view=\"capture\"] .nexor-chat__composer { display: none; }\n.nexor-chat__capture-view .nexor-chat__capture-label {\n  font-size: 13px;\n  font-weight: 600;\n  color: #374151;\n}\n\n/* ── Lead capture form ────────────────────────────────────────────── */\n.nexor-chat__capture {\n  background: #fff;\n  border: 1px solid rgba(0,0,0,0.06);\n  border-radius: 12px;\n  padding: 12px;\n  display: flex;\n  flex-direction: column;\n  gap: 8px;\n  margin-top: 4px;\n  animation: nexor-msg-in 280ms cubic-bezier(.2,.7,.2,1.1) both;\n  box-shadow: 0 2px 8px rgba(0,0,0,0.05);\n}\n.nexor-chat__capture-label {\n  font-size: 12px;\n  color: #6b7280;\n  margin: 0;\n}\n.nexor-chat__capture-row {\n  display: flex;\n  gap: 8px;\n}\n.nexor-chat__capture-row > * { flex: 1; }\n.nexor-chat__input,\n.nexor-chat__capture input {\n  font: inherit;\n  padding: 8px 10px;\n  border: 1px solid #d1d5db;\n  border-radius: 8px;\n  background: #fff;\n  color: #111;\n  outline: none;\n  width: 100%;\n  transition: border-color 140ms ease, box-shadow 140ms ease;\n}\n/* Composer textarea: auto-grows (height managed in JS) up to ~4 lines, then\n   scrolls. resize:none disables the manual drag handle. */\ntextarea.nexor-chat__input {\n  display: block;\n  resize: none;\n  overflow-y: auto;\n  line-height: 20px;\n  max-height: 98px; /* 4 lines (20×4) + 16 padding + 2 border */\n  white-space: pre-wrap;\n  word-break: break-word;\n}\n.nexor-chat__input:focus,\n.nexor-chat__capture input:focus {\n  border-color: ${accent};\n  box-shadow: 0 0 0 3px ${accent}33;\n}\n.nexor-chat__input--error,\n.nexor-chat__capture input.nexor-chat__input--error {\n  border-color: #ef4444;\n  box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.16);\n}\n.nexor-chat__capture-error {\n  font-size: 12px;\n  color: #ef4444;\n  margin: 0;\n}\n.nexor-chat__capture-error[hidden] { display: none; }\n\n/* ── Phone field (flag + dial code selector joined to a digit input) ── */\n.nexor-chat__phone {\n  display: flex;\n  align-items: stretch;\n  width: 100%;\n  border: 1px solid #d1d5db;\n  border-radius: 8px;\n  background: #fff;\n  overflow: hidden;\n  transition: border-color 140ms ease, box-shadow 140ms ease;\n}\n.nexor-chat__phone:focus-within {\n  border-color: ${accent};\n  box-shadow: 0 0 0 3px ${accent}33;\n}\n.nexor-chat__phone.nexor-chat__input--error {\n  border-color: #ef4444;\n  box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.16);\n}\n.nexor-chat__phone-country {\n  flex: none;\n  border: none;\n  border-right: 1px solid #e5e7eb;\n  background: #f9fafb;\n  color: #111;\n  font: inherit;\n  padding: 0 12px 0 10px;\n  cursor: pointer;\n  outline: none;\n}\n.nexor-chat__phone-number.nexor-chat__input {\n  border: none;\n  border-radius: 0;\n  box-shadow: none;\n  flex: 1;\n  min-width: 0;\n}\n\n.nexor-chat__capture-submit {\n  background: ${accent};\n  color: ${accentText};\n  border: none;\n  border-radius: 8px;\n  padding: 8px 12px;\n  font: inherit;\n  font-weight: 600;\n  cursor: pointer;\n  transition: transform 140ms ease, filter 140ms ease;\n}\n.nexor-chat__capture-submit:hover { filter: brightness(1.08); }\n.nexor-chat__capture-submit:active { transform: scale(0.97); }\n.nexor-chat__capture-submit[disabled] { opacity: 0.6; cursor: not-allowed; }\n\n/* ── Contact-request view (call me / email me) ────────────────────── */\n/* Its own full-panel screen, opened from a \"call\"/\"email\" fan button. Reuses\n   the capture form styling (.nexor-chat__capture) for the fields. */\n.nexor-chat__contact-view {\n  min-height: 0;\n  overflow-y: auto;\n  padding: 16px;\n  background: #f6f7f9;\n  display: flex;\n  flex-direction: column;\n  animation: nexor-fade-in 200ms ease both;\n}\n/* Show the contact view only in its own data-view; hug the form (no fixed\n   height leaving gaps), but never exceed the panel's max-height. */\n.nexor-chat__panel[data-view=\"contact\"] { height: auto; }\n.nexor-chat__panel:not([data-view=\"contact\"]) .nexor-chat__contact-view { display: none; }\n.nexor-chat__panel[data-view=\"contact\"] .nexor-chat__capture-view,\n.nexor-chat__panel[data-view=\"contact\"] .nexor-chat__body,\n.nexor-chat__panel[data-view=\"contact\"] .nexor-chat__composer { display: none; }\n.nexor-chat__panel[data-view=\"contact\"] .nexor-chat__restart { display: none; }\n\n/* The contact form lives under the header, which carries its title/explainer;\n   the live-status dot (\"we're listening\") makes no sense for a form. */\n.nexor-chat__panel[data-view=\"contact\"] .nexor-chat__status-dot { display: none; }\n\n/* form ↔ success swap, driven by the view's data-state */\n.nexor-chat__contact-view[data-state=\"sent\"] .nexor-chat__contact-form { display: none; }\n.nexor-chat__contact-view:not([data-state=\"sent\"]) .nexor-chat__contact-success { display: none; }\n\n.nexor-chat__contact-success {\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  text-align: center;\n  gap: 12px;\n  padding: 28px 12px 12px;\n  animation: nexor-msg-in 280ms cubic-bezier(.2,.7,.2,1.1) both;\n}\n.nexor-chat__contact-success-icon {\n  width: 48px;\n  height: 48px;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  border-radius: 50%;\n  background: ${accent};\n  color: ${accentText};\n}\n.nexor-chat__contact-success-icon svg { width: 26px; height: 26px; }\n.nexor-chat__contact-success-text {\n  font-size: 14px;\n  color: #374151;\n  margin: 0;\n  line-height: 1.5;\n}\n.nexor-chat__contact-success .nexor-chat__capture-submit {\n  margin-top: 4px;\n  align-self: stretch;\n}\n\n/* ── Composer ─────────────────────────────────────────────────────── */\n.nexor-chat__composer {\n  display: flex;\n  gap: 8px;\n  padding: 10px;\n  background: #fff;\n  border-top: 1px solid rgba(0,0,0,0.06);\n  /* Pin the send button to the bottom so it stays put as the textarea grows. */\n  align-items: flex-end;\n}\n.nexor-chat__send {\n  background: ${accent};\n  color: ${accentText};\n  border: none;\n  border-radius: 8px;\n  padding: 0 14px;\n  font: inherit;\n  font-weight: 600;\n  cursor: pointer;\n  min-width: 44px;\n  height: 38px; /* matches the one-line textarea height */\n  flex: none;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  transition: transform 140ms ease, filter 140ms ease;\n}\n.nexor-chat__send:hover { filter: brightness(1.08); }\n.nexor-chat__send:active { transform: scale(0.95); }\n.nexor-chat__send[disabled] {\n  opacity: 0.6;\n  cursor: not-allowed;\n  transform: none;\n}\n.nexor-chat__send svg {\n  width: 18px;\n  height: 18px;\n  transition: transform 200ms ease;\n}\n.nexor-chat__send:not([disabled]):hover svg { transform: translateX(2px); }\n\n/* Small spinner inside the send button while a turn is in flight */\n.nexor-chat__send--loading svg { display: none; }\n.nexor-chat__send--loading::after {\n  content: \"\";\n  width: 14px;\n  height: 14px;\n  border-radius: 9999px;\n  border: 2px solid currentColor;\n  border-top-color: transparent;\n  animation: nexor-spin 700ms linear infinite;\n}\n@keyframes nexor-spin {\n  to { transform: rotate(360deg); }\n}\n\n.nexor-chat__footer {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  gap: 5px;\n  font-size: 11px;\n  color: #9ca3af;\n  padding: 6px;\n  background: #fff;\n  border-top: 1px solid rgba(0,0,0,0.04);\n}\n.nexor-chat__footer a {\n  color: inherit;\n  text-decoration: none;\n  font-weight: 600;\n}\n/* \"Powered by\" + the Nexor wordmark (same mark as the site navbar). Plain\n   attribution — not a link, but hovering shows a getnexor.ai tooltip. */\n.nexor-chat__brand {\n  position: relative;\n  display: inline-flex;\n  align-items: center;\n  cursor: help; /* hover reveals the getnexor.ai tooltip; not a link */\n}\n.nexor-chat__brand-logo {\n  height: 13px;\n  width: auto;\n  display: block;\n}\n/* Custom tooltip (instant + reliable across browsers, unlike a native SVG\n   <title>). Sits above the logo and fades in on hover/focus. */\n.nexor-chat__brand-tip {\n  position: absolute;\n  bottom: calc(100% + 7px);\n  left: 50%;\n  transform: translateX(-50%) translateY(4px);\n  background: #111827;\n  color: #fff;\n  font-size: 11px;\n  font-weight: 500;\n  line-height: 1;\n  letter-spacing: 0.01em;\n  padding: 5px 8px;\n  border-radius: 6px;\n  white-space: nowrap;\n  opacity: 0;\n  pointer-events: none;\n  box-shadow: 0 4px 12px rgba(0,0,0,0.18);\n  transition: opacity 140ms ease, transform 140ms ease;\n  z-index: 5;\n}\n.nexor-chat__brand-tip::after {\n  content: \"\";\n  position: absolute;\n  top: 100%;\n  left: 50%;\n  transform: translateX(-50%);\n  border: 4px solid transparent;\n  border-top-color: #111827;\n}\n.nexor-chat__brand:hover .nexor-chat__brand-tip {\n  opacity: 1;\n  transform: translateX(-50%) translateY(0);\n}\n\n/* ── Mobile: full-screen panel with an obvious close affordance ───── */\n@media (max-width: 480px) {\n  /* The panel takes over the whole viewport so the keyboard + messages have\n     room. 100dvh tracks the dynamic viewport as mobile browser chrome shows/\n     hides, avoiding a cut-off composer. */\n  .nexor-chat__panel {\n    position: fixed;\n    inset: 0;\n    top: 0;\n    left: 0;\n    right: 0;\n    bottom: 0;\n    width: 100%;\n    max-width: 100%;\n    height: 100vh;\n    height: 100dvh;\n    max-height: none;\n    border-radius: 0;\n    border: none;\n    transform: translateY(100%);\n  }\n  .nexor-chat[data-position=\"bottom-left\"] .nexor-chat__panel { left: 0; }\n  .nexor-chat[data-open=\"true\"] .nexor-chat__panel { transform: translateY(0); }\n  /* Keep the form view full-screen on phones too (overrides the desktop\n     hug-the-form height). */\n  .nexor-chat__panel[data-view=\"capture\"] {\n    height: 100vh;\n    height: 100dvh;\n  }\n  .nexor-chat__panel[data-view=\"capture\"] .nexor-chat__capture-view {\n    justify-content: center;\n  }\n\n  /* Hide the launcher (and any open fan) while the full-screen panel is up —\n     the in-header close button is the way back out. */\n  .nexor-chat[data-open=\"true\"] .nexor-chat__launcher-wrap {\n    opacity: 0;\n    pointer-events: none;\n  }\n\n  /* Roomier header + a bigger, unmistakable close target on touch. */\n  .nexor-chat__header {\n    padding: 16px 14px 16px 18px;\n    padding-top: max(16px, env(safe-area-inset-top));\n  }\n  .nexor-chat__close {\n    padding: 10px;\n    background: rgba(255, 255, 255, 0.16);\n  }\n  .nexor-chat__close svg { width: 24px; height: 24px; }\n\n  /* Keep the composer clear of the home-indicator / gesture bar. */\n  .nexor-chat__composer {\n    padding-bottom: max(10px, env(safe-area-inset-bottom));\n  }\n}\n\n/* Respect users who request reduced motion. */\n@media (prefers-reduced-motion: reduce) {\n  .nexor-chat,\n  .nexor-chat * {\n    animation-duration: 0.001ms !important;\n    transition-duration: 0.001ms !important;\n  }\n  .nexor-chat__status-dot { animation: none; }\n}\n`;\n","/**\n * Pure DOM construction for the chat widget.\n *\n * Each `build*` function returns a fully-formed sub-tree plus refs to the\n * inner nodes the orchestrator (initChat) wires events to. No side effects\n * here other than calling `injectStyles()` once per page.\n *\n * Why split this out from index.ts?\n *   - The DOM layer doesn't depend on the NexorClient or sessionId — keeping\n *     it pure makes the widget easy to reason about and easy to dry-run in\n *     unit tests by mocking `document`.\n *   - The orchestrator becomes a 150-line state machine instead of a\n *     600-line god-function.\n */\nimport {\n  needsCapture,\n  type ResolvedCfg,\n  type ResolvedChannel,\n  type ChatChannelKey,\n} from \"./config\";\nimport {\n  COUNTRIES,\n  countryByIso,\n  maxNsn,\n  resolveDefaultCountry,\n  type Country,\n} from \"./countries\";\nimport { widgetCss } from \"./styles\";\n\nconst STYLE_ATTR = \"data-nexor-chat-styles\";\n\n// ─── Stylesheet (singleton per page) ───────────────────────────────────────\n\n/**\n * Inject the widget's stylesheet once per page. If multiple widgets mount,\n * they share styles and the first widget's accent colour wins. Two widgets\n * with different accents on one page is an unsupported use case.\n */\nexport function injectStyles(accent: string, accentText: string): void {\n  if (document.querySelector(`style[${STYLE_ATTR}]`)) return;\n  const style = document.createElement(\"style\");\n  style.setAttribute(STYLE_ATTR, \"1\");\n  style.textContent = widgetCss(accent, accentText);\n  document.head.appendChild(style);\n}\n\n// ─── Launcher ──────────────────────────────────────────────────────────────\n\nexport interface ChannelButtonRef {\n  key: ChatChannelKey;\n  /** The clickable element — an <a> for links, a <button> for JS actions. */\n  el: HTMLAnchorElement | HTMLButtonElement;\n  /** \"contact\" → opens the contact-request form; undefined → chat/navigation. */\n  action?: \"contact\";\n}\n\nexport interface LauncherRefs {\n  /** The outer container — also the hover target for the speed-dial fan. */\n  wrap: HTMLDivElement;\n  /** The main bubble button. */\n  el: HTMLButtonElement;\n  badge: HTMLSpanElement;\n  /** The fan container (null when no channels are configured). */\n  fan: HTMLDivElement | null;\n  /** Resolved fan buttons, in render order. Empty when no fan. */\n  channelButtons: ChannelButtonRef[];\n}\n\n// Speech-bubble icon — SVG rather than emoji for crisp rendering at any DPR.\nconst CHAT_ICON = `\n  <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n    <path d=\"M4 5.5C4 4.67 4.67 4 5.5 4h13c.83 0 1.5.67 1.5 1.5v9c0 .83-.67 1.5-1.5 1.5H9l-4 4V5.5Z\"\n          stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linejoin=\"round\"/>\n  </svg>`;\n\nconst CHANNEL_ICONS: Record<ChatChannelKey, string> = {\n  whatsapp: `\n    <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n      <path d=\"M.057 24l1.687-6.163a11.867 11.867 0 0 1-1.587-5.946C.16 5.335 5.495 0 12.05 0a11.817 11.817 0 0 1 8.413 3.488 11.824 11.824 0 0 1 3.48 8.414c-.003 6.557-5.338 11.892-11.893 11.892a11.9 11.9 0 0 1-5.688-1.448L.057 24zm6.597-3.807c1.676.995 3.276 1.591 5.392 1.592 5.448 0 9.886-4.434 9.889-9.885.002-5.462-4.415-9.89-9.881-9.892-5.452 0-9.887 4.434-9.889 9.884a9.82 9.82 0 0 0 1.5 5.245l-.999 3.648 3.738-.981zm11.387-5.464c-.074-.124-.272-.198-.57-.347-.297-.149-1.758-.868-2.031-.967-.272-.099-.47-.149-.669.149-.198.297-.768.967-.941 1.165-.173.198-.347.223-.644.074-.297-.149-1.255-.462-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.297-.347.446-.521.151-.172.2-.296.3-.495.099-.198.05-.372-.025-.521-.075-.148-.669-1.611-.916-2.206-.242-.579-.487-.501-.669-.51l-.57-.01c-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.263.489 1.694.626.712.226 1.36.194 1.872.118.571-.085 1.758-.719 2.006-1.413.248-.695.248-1.29.173-1.414z\"/>\n    </svg>`,\n  call: `\n    <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n      <path d=\"M6.6 10.8c1.4 2.8 3.8 5.1 6.6 6.6l2.2-2.2c.3-.3.7-.4 1-.2 1.1.4 2.3.6 3.5.6.6 0 1 .4 1 1V20c0 .6-.4 1-1 1C10.5 21 3 13.5 3 4.5c0-.6.4-1 1-1h3.5c.6 0 1 .4 1 1 0 1.2.2 2.4.6 3.5.1.4 0 .8-.2 1L6.6 10.8Z\"/>\n    </svg>`,\n  email: `\n    <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n      <rect x=\"3\" y=\"5\" width=\"18\" height=\"14\" rx=\"2\" stroke=\"currentColor\" stroke-width=\"1.8\"/>\n      <path d=\"m4 7 8 6 8-6\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linejoin=\"round\"/>\n    </svg>`,\n  instagram: `\n    <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n      <rect x=\"3.5\" y=\"3.5\" width=\"17\" height=\"17\" rx=\"5\" stroke=\"currentColor\" stroke-width=\"1.8\"/>\n      <circle cx=\"12\" cy=\"12\" r=\"4\" stroke=\"currentColor\" stroke-width=\"1.8\"/>\n      <circle cx=\"17.2\" cy=\"6.8\" r=\"1.2\" fill=\"currentColor\"/>\n    </svg>`,\n  chat: CHAT_ICON,\n};\n\n/**\n * Build the launcher. When `cfg.channels` is non-empty the launcher becomes a\n * speed-dial that fans out channel buttons (revealed on hover / tap). Otherwise\n * it's the classic single bubble that opens the chat on click.\n */\nexport function buildLauncher(cfg: ResolvedCfg): LauncherRefs {\n  const wrap = document.createElement(\"div\");\n  wrap.className = \"nexor-chat__launcher-wrap\";\n\n  const hasFan = cfg.channels.length > 0;\n\n  const { fan, channelButtons } = hasFan\n    ? buildChannelFan(cfg.channels)\n    : { fan: null, channelButtons: [] as ChannelButtonRef[] };\n  if (fan) wrap.appendChild(fan);\n\n  const el = document.createElement(\"button\");\n  el.type = \"button\";\n  el.className = \"nexor-chat__launcher\";\n  // With a fan, the bubble toggles the channel menu; without it, it opens chat.\n  el.setAttribute(\"aria-label\", hasFan ? \"Contact us\" : \"Open chat\");\n  if (hasFan) {\n    el.setAttribute(\"aria-haspopup\", \"true\");\n    el.setAttribute(\"aria-expanded\", \"false\");\n  }\n  el.innerHTML = CHAT_ICON;\n\n  const badge = document.createElement(\"span\");\n  badge.className = \"nexor-chat__unread\";\n  badge.style.display = \"none\";\n  el.appendChild(badge);\n  wrap.appendChild(el);\n\n  return { wrap, el, badge, fan, channelButtons };\n}\n\nfunction buildChannelFan(channels: ResolvedChannel[]): {\n  fan: HTMLDivElement;\n  channelButtons: ChannelButtonRef[];\n} {\n  const fan = document.createElement(\"div\");\n  fan.className = \"nexor-chat__channels\";\n  fan.setAttribute(\"role\", \"menu\");\n\n  const channelButtons: ChannelButtonRef[] = [];\n  for (const ch of channels) {\n    const item = document.createElement(\"div\");\n    item.className = \"nexor-chat__channel-item\";\n\n    const labelEl = document.createElement(\"span\");\n    labelEl.className = \"nexor-chat__channel-label\";\n    labelEl.textContent = ch.label;\n\n    let el: HTMLAnchorElement | HTMLButtonElement;\n    if (ch.href === null) {\n      // The chat action is wired up in JS (opens the panel), not a navigation.\n      const btn = document.createElement(\"button\");\n      btn.type = \"button\";\n      el = btn;\n    } else {\n      const a = document.createElement(\"a\");\n      a.href = ch.href;\n      if (ch.external) {\n        a.target = \"_blank\";\n        a.rel = \"noopener noreferrer\";\n      }\n      el = a;\n    }\n    el.className = `nexor-chat__channel nexor-chat__channel--${ch.key}`;\n    el.setAttribute(\"role\", \"menuitem\");\n    el.setAttribute(\"aria-label\", ch.label);\n    el.innerHTML = CHANNEL_ICONS[ch.key];\n\n    // Label sits to the side (left of a right-anchored widget, right of a\n    // left-anchored one — handled in CSS). Both share the item row.\n    item.appendChild(labelEl);\n    item.appendChild(el);\n    fan.appendChild(item);\n    channelButtons.push({ key: ch.key, el, action: ch.action });\n  }\n  return { fan, channelButtons };\n}\n\n// ─── Panel ─────────────────────────────────────────────────────────────────\n\ntype CaptureField = \"first_name\" | \"last_name\" | \"email\" | \"phone\";\n\nexport interface PanelRefs {\n  el: HTMLDivElement;\n  closeBtn: HTMLButtonElement;\n  restartBtn: HTMLButtonElement | null;\n  /** Header title + subtitle — re-contextualized when the contact form opens. */\n  headerTitle: HTMLParagraphElement;\n  headerSubtitle: HTMLParagraphElement;\n  headerSubtitleText: HTMLSpanElement;\n  body: HTMLDivElement;\n  form: HTMLFormElement;\n  input: HTMLTextAreaElement;\n  send: HTMLButtonElement;\n  /** Full-panel capture screen (null when this widget never captures). */\n  captureView: HTMLDivElement | null;\n  captureForm: HTMLFormElement | null;\n  captureError: HTMLParagraphElement | null;\n  /** Country <select> for the phone field (flag + dial code), null if no phone. */\n  phoneCountry: HTMLSelectElement | null;\n  captureInputs: Partial<Record<CaptureField, HTMLInputElement>>;\n  /** Contact-request view (null when requestContact isn't configured). */\n  contact: ContactViewRefs | null;\n}\n\n/** Refs for the in-widget contact-request form + its success state. */\nexport interface ContactViewRefs {\n  view: HTMLDivElement;\n  form: HTMLFormElement;\n  inputs: Partial<Record<CaptureField, HTMLInputElement>>;\n  error: HTMLParagraphElement;\n  phoneCountry: HTMLSelectElement | null;\n  submitBtn: HTMLButtonElement;\n  /** Success panel (hidden until a request succeeds). */\n  success: HTMLDivElement;\n  successText: HTMLParagraphElement;\n  successBtn: HTMLButtonElement;\n}\n\nexport function buildPanel(cfg: ResolvedCfg): PanelRefs {\n  const el = document.createElement(\"div\");\n  el.className = \"nexor-chat__panel\";\n  el.setAttribute(\"role\", \"dialog\");\n  el.setAttribute(\"aria-label\", cfg.title);\n\n  const { header, closeBtn, restartBtn, titleEl, subtitleEl, subtitleTextEl } =\n    buildHeader(cfg);\n  const body = buildBody();\n  const { form, input, send } = buildComposer(cfg);\n  const footer = cfg.showBranding ? buildFooter() : null;\n\n  // The capture form is its OWN view (a full-panel screen), not a card mixed in\n  // with the messages. `data-view` toggles between the capture screen and the\n  // chat (body + composer); see styles.ts.\n  const captureInputs: Partial<Record<CaptureField, HTMLInputElement>> = {};\n  let captureView: HTMLDivElement | null = null;\n  let captureForm: HTMLFormElement | null = null;\n  let captureError: HTMLParagraphElement | null = null;\n  let phoneCountry: HTMLSelectElement | null = null;\n  if (needsCapture(cfg)) {\n    const built = buildCaptureView(cfg, captureInputs);\n    captureView = built.view;\n    captureForm = built.form;\n    captureError = built.error;\n    phoneCountry = built.phoneCountry;\n  }\n\n  // Contact-request view: an alternate full-panel screen opened when a visitor\n  // taps a \"call me\" / \"email me\" fan button. Built once; its copy is set per\n  // channel at click time.\n  const contact: ContactViewRefs | null = cfg.requestContact\n    ? buildContactView(cfg)\n    : null;\n\n  el.setAttribute(\"data-view\", captureView ? \"capture\" : \"chat\");\n\n  el.appendChild(header);\n  if (captureView) el.appendChild(captureView);\n  if (contact) el.appendChild(contact.view);\n  el.appendChild(body);\n  el.appendChild(form);\n  if (footer) el.appendChild(footer);\n\n  return {\n    el,\n    closeBtn,\n    restartBtn,\n    headerTitle: titleEl,\n    headerSubtitle: subtitleEl,\n    headerSubtitleText: subtitleTextEl,\n    body,\n    form,\n    input,\n    send,\n    captureView,\n    captureForm,\n    captureError,\n    phoneCountry,\n    captureInputs,\n    contact,\n  };\n}\n\nfunction buildHeader(cfg: ResolvedCfg): {\n  header: HTMLDivElement;\n  closeBtn: HTMLButtonElement;\n  restartBtn: HTMLButtonElement | null;\n  titleEl: HTMLParagraphElement;\n  subtitleEl: HTMLParagraphElement;\n  subtitleTextEl: HTMLSpanElement;\n} {\n  const header = document.createElement(\"div\");\n  header.className = \"nexor-chat__header\";\n\n  // Title + subtitle are built as elements (not innerHTML) so the orchestrator\n  // can re-contextualize them — e.g. when the contact-request form is open the\n  // header becomes the form's title/explainer instead of the chat title.\n  const info = document.createElement(\"div\");\n\n  const titleEl = document.createElement(\"p\");\n  titleEl.className = \"nexor-chat__title\";\n  titleEl.textContent = cfg.title;\n  info.appendChild(titleEl);\n\n  // The status dot signals \"we're live and listening\" — purely cosmetic, but a\n  // strong UX signal. Hidden from assistive tech (title carries the meaning) and\n  // hidden by CSS in the contact-form view (a form isn't \"live and listening\").\n  const subtitleEl = document.createElement(\"p\");\n  subtitleEl.className = \"nexor-chat__subtitle\";\n  const dot = document.createElement(\"span\");\n  dot.className = \"nexor-chat__status-dot\";\n  dot.setAttribute(\"aria-hidden\", \"true\");\n  const subtitleTextEl = document.createElement(\"span\");\n  subtitleTextEl.className = \"nexor-chat__subtitle-text\";\n  subtitleTextEl.textContent = cfg.subtitle ?? \"\";\n  subtitleEl.appendChild(dot);\n  subtitleEl.appendChild(subtitleTextEl);\n  if (!cfg.subtitle) subtitleEl.hidden = true;\n  info.appendChild(subtitleEl);\n\n  header.appendChild(info);\n\n  // Restart: wipes the conversation and starts a brand-new lead. Lives next to\n  // close so it's reachable any time the chat is open (not just from the resume\n  // banner). Hidden on the capture screen via CSS — nothing to reset yet.\n  let restartBtn: HTMLButtonElement | null = null;\n  if (cfg.showRestart) {\n    restartBtn = document.createElement(\"button\");\n    restartBtn.type = \"button\";\n    restartBtn.className = \"nexor-chat__restart\";\n    restartBtn.setAttribute(\"aria-label\", cfg.restartLabel);\n    restartBtn.title = cfg.restartLabel;\n    restartBtn.innerHTML = `\n      <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n        <path d=\"M4 5v5h5M20 19v-5h-5\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n        <path d=\"M19 10a7 7 0 0 0-12-3L4 10M5 14a7 7 0 0 0 12 3l3-3\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n      </svg>\n    `;\n    header.appendChild(restartBtn);\n  }\n\n  const closeBtn = document.createElement(\"button\");\n  closeBtn.type = \"button\";\n  closeBtn.className = \"nexor-chat__close\";\n  closeBtn.setAttribute(\"aria-label\", \"Close chat\");\n  closeBtn.innerHTML = `\n    <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n      <path d=\"M6 6l12 12M6 18L18 6\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n    </svg>\n  `;\n  header.appendChild(closeBtn);\n  return { header, closeBtn, restartBtn, titleEl, subtitleEl, subtitleTextEl };\n}\n\nfunction buildBody(): HTMLDivElement {\n  const body = document.createElement(\"div\");\n  body.className = \"nexor-chat__body\";\n  return body;\n}\n\n/** Full-panel capture screen: a centered card that owns the whole view. */\nfunction buildCaptureView(\n  cfg: ResolvedCfg,\n  inputsOut: Partial<Record<CaptureField, HTMLInputElement>>,\n): {\n  view: HTMLDivElement;\n  form: HTMLFormElement;\n  error: HTMLParagraphElement;\n  phoneCountry: HTMLSelectElement | null;\n} {\n  const view = document.createElement(\"div\");\n  view.className = \"nexor-chat__capture-view\";\n  const { form, error, phoneCountry } = buildCaptureForm(cfg, inputsOut);\n  view.appendChild(form);\n  return { view, form, error, phoneCountry };\n}\n\nconst DEFAULT_FIELD_PLACEHOLDERS: Record<CaptureField, string> = {\n  first_name: \"First name\",\n  last_name: \"Last name\",\n  email: \"Email\",\n  phone: \"Phone\",\n};\n\nfunction buildCaptureForm(\n  cfg: ResolvedCfg,\n  inputsOut: Partial<Record<CaptureField, HTMLInputElement>>,\n): {\n  form: HTMLFormElement;\n  error: HTMLParagraphElement;\n  phoneCountry: HTMLSelectElement | null;\n} {\n  const form = document.createElement(\"form\");\n  form.className = \"nexor-chat__capture\";\n  form.noValidate = true;\n  let phoneCountry: HTMLSelectElement | null = null;\n\n  const label = document.createElement(\"p\");\n  label.className = \"nexor-chat__capture-label\";\n  label.textContent = cfg.capture.label;\n  form.appendChild(label);\n\n  const fields = cfg.capture.fields;\n  const ph = (f: CaptureField) =>\n    cfg.capture.placeholders[f] ?? DEFAULT_FIELD_PLACEHOLDERS[f];\n\n  // first_name + last_name share a row to feel like a single \"your name\" prompt.\n  if (fields.includes(\"first_name\") || fields.includes(\"last_name\")) {\n    const row = document.createElement(\"div\");\n    row.className = \"nexor-chat__capture-row\";\n    if (fields.includes(\"first_name\")) {\n      inputsOut.first_name = makeInput(\"first_name\", ph(\"first_name\"), \"text\", cfg.lead?.first_name);\n      row.appendChild(inputsOut.first_name);\n    }\n    if (fields.includes(\"last_name\")) {\n      inputsOut.last_name = makeInput(\"last_name\", ph(\"last_name\"), \"text\", cfg.lead?.last_name);\n      row.appendChild(inputsOut.last_name);\n    }\n    if (row.childElementCount > 0) form.appendChild(row);\n  }\n  if (fields.includes(\"email\")) {\n    inputsOut.email = makeInput(\"email\", ph(\"email\"), \"email\", cfg.lead?.email);\n    form.appendChild(inputsOut.email);\n  }\n  if (fields.includes(\"phone\")) {\n    const built = buildPhoneField(cfg, ph(\"phone\"));\n    inputsOut.phone = built.input;\n    phoneCountry = built.select;\n    form.appendChild(built.wrap);\n  }\n\n  // Inline validation message (hidden until a submit fails). role=alert so\n  // assistive tech announces it.\n  const error = document.createElement(\"p\");\n  error.className = \"nexor-chat__capture-error\";\n  error.setAttribute(\"role\", \"alert\");\n  error.hidden = true;\n  form.appendChild(error);\n\n  const submit = document.createElement(\"button\");\n  submit.type = \"submit\";\n  submit.className = \"nexor-chat__capture-submit\";\n  submit.textContent = cfg.capture.submitLabel;\n  form.appendChild(submit);\n\n  return { form, error, phoneCountry };\n}\n\n/** The countries to offer, in order. Filtered to `capture.phoneCountries` (ISO\n *  codes) when provided, else the full table. */\nfunction resolveCountryList(isos: string[]): Country[] {\n  if (!isos.length) return COUNTRIES;\n  const picked = isos\n    .map((i) => countryByIso(i))\n    .filter((c): c is Country => Boolean(c));\n  return picked.length ? picked : COUNTRIES;\n}\n\n/**\n * The phone field: a country <select> (flag + dial code) joined to a digit-only\n * input. The input's maxlength tracks the selected country's number length, so a\n * visitor can't type more digits than the country needs (index.ts also strips\n * non-digits + re-caps on country change).\n */\nfunction buildPhoneField(\n  cfg: ResolvedCfg,\n  placeholder: string,\n): { wrap: HTMLDivElement; select: HTMLSelectElement; input: HTMLInputElement } {\n  const wrap = document.createElement(\"div\");\n  wrap.className = \"nexor-chat__phone\";\n\n  const list = resolveCountryList(cfg.capture.phoneCountries);\n  const def = resolveDefaultCountry(cfg.capture.phoneCountryCode);\n\n  const select = document.createElement(\"select\");\n  select.className = \"nexor-chat__phone-country\";\n  select.name = \"phone_country\";\n  select.setAttribute(\"aria-label\", \"Country code\");\n  for (const c of list) {\n    const opt = document.createElement(\"option\");\n    opt.value = c.iso;\n    opt.textContent = `${c.flag} ${c.dial}`;\n    if (c.iso === def.iso) opt.selected = true;\n    select.appendChild(opt);\n  }\n\n  const input = document.createElement(\"input\");\n  input.name = \"phone\";\n  input.type = \"tel\";\n  input.inputMode = \"numeric\";\n  input.autocomplete = \"tel-national\";\n  input.placeholder = placeholder;\n  input.className = \"nexor-chat__input nexor-chat__phone-number\";\n  input.maxLength = maxNsn(def);\n  // Prefill from a known lead phone: strip the dial, keep national digits.\n  if (cfg.lead?.phone) {\n    const digits = String(cfg.lead.phone).replace(/\\D/g, \"\");\n    const dialDigits = def.dial.replace(/\\D/g, \"\");\n    const national = digits.startsWith(dialDigits) ? digits.slice(dialDigits.length) : digits;\n    input.value = national.slice(0, input.maxLength);\n  }\n\n  wrap.appendChild(select);\n  wrap.appendChild(input);\n  return { wrap, select, input };\n}\n\n// ─── Contact-request view (call me / email me) ──────────────────────────────\n\nconst CONTACT_FIELDS: CaptureField[] = [\"first_name\", \"last_name\", \"email\", \"phone\"];\n\n/**\n * The contact-request screen: a back control, a channel-specific title +\n * subtitle, the same name/email/phone fields as capture, and a success panel.\n * Title / subtitle / submit / success copy are filled per channel by the\n * orchestrator (index.ts) when the visitor opens the form, since the chosen\n * channel isn't known at build time.\n */\nfunction buildContactView(cfg: ResolvedCfg): ContactViewRefs {\n  const rc = cfg.requestContact;\n  const view = document.createElement(\"div\");\n  view.className = \"nexor-chat__contact-view\";\n  // \"form\" → fields shown; \"sent\" → success panel shown (CSS-driven toggle).\n  view.setAttribute(\"data-state\", \"form\");\n\n  // No in-body title/subtitle and no \"back\" control: the panel HEADER carries\n  // the form's title + explainer (set per channel by the orchestrator), so the\n  // black header itself reads as a form rather than a chat. The header × closes.\n  const form = document.createElement(\"form\");\n  form.className = \"nexor-chat__capture nexor-chat__contact-form\";\n  form.noValidate = true;\n\n  const inputs: Partial<Record<CaptureField, HTMLInputElement>> = {};\n  const ph = (f: CaptureField) =>\n    cfg.capture.placeholders[f] ?? DEFAULT_FIELD_PLACEHOLDERS[f];\n\n  // Always collect first/last name (shared row), email and phone — the visitor\n  // gave no info yet, so we ask for everything we'd need to reach them.\n  const row = document.createElement(\"div\");\n  row.className = \"nexor-chat__capture-row\";\n  inputs.first_name = makeInput(\"first_name\", ph(\"first_name\"), \"text\", cfg.lead?.first_name);\n  inputs.last_name = makeInput(\"last_name\", ph(\"last_name\"), \"text\", cfg.lead?.last_name);\n  row.appendChild(inputs.first_name);\n  row.appendChild(inputs.last_name);\n  form.appendChild(row);\n\n  inputs.email = makeInput(\"email\", ph(\"email\"), \"email\", cfg.lead?.email);\n  form.appendChild(inputs.email);\n\n  const phone = buildPhoneField(cfg, ph(\"phone\"));\n  inputs.phone = phone.input;\n  const phoneCountry = phone.select;\n  form.appendChild(phone.wrap);\n\n  const error = document.createElement(\"p\");\n  error.className = \"nexor-chat__capture-error\";\n  error.setAttribute(\"role\", \"alert\");\n  error.hidden = true;\n  form.appendChild(error);\n\n  const submitBtn = document.createElement(\"button\");\n  submitBtn.type = \"submit\";\n  submitBtn.className = \"nexor-chat__capture-submit\";\n  form.appendChild(submitBtn);\n  view.appendChild(form);\n\n  // Success panel — shown in place of the form once the request lands\n  // (visibility driven by the view's data-state, see styles.ts).\n  const success = document.createElement(\"div\");\n  success.className = \"nexor-chat__contact-success\";\n  const successIcon = document.createElement(\"div\");\n  successIcon.className = \"nexor-chat__contact-success-icon\";\n  successIcon.innerHTML = `\n    <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n      <path d=\"M5 13l4 4L19 7\" stroke=\"currentColor\" stroke-width=\"2.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n    </svg>`;\n  const successText = document.createElement(\"p\");\n  successText.className = \"nexor-chat__contact-success-text\";\n  const successBtn = document.createElement(\"button\");\n  successBtn.type = \"button\";\n  successBtn.className = \"nexor-chat__capture-submit\";\n  successBtn.textContent = rc?.doneLabel ?? \"Done\";\n  success.appendChild(successIcon);\n  success.appendChild(successText);\n  success.appendChild(successBtn);\n  view.appendChild(success);\n\n  // CONTACT_FIELDS documents the field set above; referenced to keep the\n  // constant \"used\" for tree-shaking-friendly builds.\n  void CONTACT_FIELDS;\n\n  return {\n    view,\n    form,\n    inputs,\n    error,\n    phoneCountry,\n    submitBtn,\n    success,\n    successText,\n    successBtn,\n  };\n}\n\nfunction buildComposer(cfg: ResolvedCfg): {\n  form: HTMLFormElement;\n  input: HTMLTextAreaElement;\n  send: HTMLButtonElement;\n} {\n  const form = document.createElement(\"form\");\n  form.className = \"nexor-chat__composer\";\n\n  // Auto-growing textarea: starts at one line, expands to ~4 lines, then scrolls.\n  // Enter sends; Shift+Enter inserts a newline (wired in index.ts).\n  const input = document.createElement(\"textarea\");\n  input.className = \"nexor-chat__input\";\n  input.placeholder = cfg.inputPlaceholder;\n  input.rows = 1;\n  input.setAttribute(\"autocomplete\", \"off\");\n\n  const send = document.createElement(\"button\");\n  send.type = \"submit\";\n  send.className = \"nexor-chat__send\";\n  send.setAttribute(\"aria-label\", \"Send message\");\n  // Paper-airplane icon — language-agnostic, recognisable, replaces \"Send\" text.\n  send.innerHTML = `\n    <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n      <path d=\"M3.4 11.2 20.5 4.3c.7-.3 1.4.4 1.1 1.1l-6.9 17.1c-.3.8-1.4.8-1.8 0L10 14l-7.5-3c-.8-.3-.8-1.5 0-1.8Z\"\n            stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linejoin=\"round\" fill=\"currentColor\"/>\n    </svg>\n  `;\n\n  form.appendChild(input);\n  form.appendChild(send);\n  return { form, input, send };\n}\n\n// The Nexor wordmark — the SAME mark the site navbar uses (src NexorLogo.jsx),\n// inlined as SVG so the bundle stays asset-free. The gradient id is namespaced\n// to avoid colliding with a host page that also renders the Nexor logo.\nconst NEXOR_WORDMARK = `\n  <svg viewBox=\"0 0 1722 505\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" class=\"nexor-chat__brand-logo\" role=\"img\" aria-label=\"Nexor\">\n    <defs>\n      <linearGradient id=\"nexorChatBrandGrad\" x1=\"1195.44\" y1=\"21.3423\" x2=\"1195.44\" y2=\"504.454\" gradientUnits=\"userSpaceOnUse\">\n        <stop stop-color=\"#232522\"/>\n        <stop offset=\"1\" stop-color=\"#A1A1A1\"/>\n      </linearGradient>\n    </defs>\n    <path d=\"M31.824 416.676V103.332H67.32L82.008 147.396C92.412 125.976 125.46 99.0477 196.452 99.0477C299.268 99.0477 319.464 159.024 319.464 247.764V416.676H254.592V242.256C254.592 186.564 244.8 153.516 178.092 153.516C111.384 153.516 97.308 185.952 97.308 242.256V416.676H31.824ZM506.373 420.96C380.301 420.96 349.089 343.236 349.089 259.392C349.089 175.548 380.913 99.0477 505.761 99.0477C621.429 99.0477 653.865 187.176 645.909 285.708H417.021C420.693 339.564 447.621 370.776 503.925 370.776C555.945 370.776 572.469 345.684 578.589 320.592H647.133C641.625 373.836 604.905 420.96 506.373 420.96ZM417.633 233.688H578.589V232.464C579.201 189.624 559.005 149.844 499.641 149.844C438.441 149.844 420.693 187.788 417.633 233.688ZM622.452 416.676L747.912 254.496L631.02 103.332H706.296L788.916 217.164L872.76 103.332H946.2L829.92 254.496L955.38 416.676H876.432L789.528 290.604L702.012 416.676H622.452Z\" fill=\"#232522\"/>\n    <path d=\"M1195.22 21.3423C1199.01 21.3424 1202.55 23.2768 1205.81 26.6265C1209.06 29.9743 1212.14 34.8402 1215.03 40.9858C1220.81 53.2843 1225.98 70.9957 1230.31 92.7749C1236.49 123.842 1240.99 163.329 1243.06 207.497C1245.04 168.74 1249.06 134.088 1254.51 106.604C1258.48 86.5946 1263.23 70.315 1268.53 59.0063C1271.18 53.3557 1274 48.8741 1277 45.7866C1279.99 42.6974 1283.27 40.8979 1286.78 40.8979C1290.29 40.8981 1293.56 42.6975 1296.56 45.7866C1299.55 48.8741 1302.37 53.3556 1305.03 59.0063C1310.33 70.315 1315.07 86.5945 1319.04 106.604C1324.73 135.304 1328.87 171.821 1330.75 212.666C1332.39 186.451 1335.28 162.981 1339.08 144C1342.12 128.775 1345.76 116.368 1349.84 107.735C1351.88 103.422 1354.07 99.9788 1356.4 97.5962C1358.73 95.2117 1361.31 93.7866 1364.11 93.7866C1366.91 93.7866 1369.5 95.2116 1371.83 97.5962C1374.16 99.9788 1376.34 103.422 1378.38 107.735C1382.46 116.368 1386.1 128.775 1389.15 144C1393.72 166.881 1396.98 196.283 1398.32 229.154C1399.23 221.906 1400.42 215.317 1401.84 209.621C1403.54 202.788 1405.59 197.165 1407.92 193.217C1410.19 189.36 1412.99 186.675 1416.33 186.675C1419.68 186.676 1422.47 189.36 1424.75 193.217C1427.07 197.165 1429.12 202.788 1430.83 209.621C1434.24 223.306 1436.33 242.142 1436.33 262.898C1436.33 283.654 1434.24 302.489 1430.83 316.174C1429.12 323.007 1427.07 328.631 1424.75 332.579C1422.47 336.436 1419.68 339.119 1416.33 339.12C1412.99 339.12 1410.19 336.436 1407.92 332.579C1405.59 328.631 1403.54 323.007 1401.84 316.174C1400.42 310.478 1399.23 303.889 1398.32 296.641C1396.98 329.512 1393.72 358.915 1389.15 381.796C1386.1 397.021 1382.46 409.428 1378.38 418.061C1376.34 422.374 1374.16 425.816 1371.83 428.199C1369.5 430.583 1366.91 432.009 1364.11 432.009C1361.31 432.009 1358.73 430.584 1356.4 428.199C1354.07 425.816 1351.88 422.374 1349.84 418.061C1345.76 409.428 1342.12 397.021 1339.08 381.796C1335.28 362.814 1332.39 339.344 1330.75 313.129C1328.87 353.974 1324.73 390.492 1319.04 419.192C1315.07 439.201 1310.33 455.481 1305.03 466.79C1302.37 472.44 1299.55 476.922 1296.56 480.009C1293.56 483.098 1290.29 484.898 1286.78 484.898C1283.27 484.898 1279.99 483.098 1277 480.009C1274 476.922 1271.18 472.44 1268.53 466.79C1263.23 455.481 1258.48 439.201 1254.51 419.192C1249.06 391.708 1245.04 357.055 1243.06 318.298C1240.99 362.466 1236.49 401.953 1230.31 433.021C1225.98 454.8 1220.81 472.512 1215.03 484.81C1212.14 490.956 1209.06 495.822 1205.81 499.169C1202.55 502.519 1199.01 504.454 1195.22 504.454C1191.44 504.454 1187.89 502.519 1184.64 499.169C1181.38 495.822 1178.31 490.956 1175.42 484.81C1169.64 472.512 1164.46 454.8 1160.13 433.021C1153.95 401.956 1149.46 362.472 1147.39 318.308C1145.4 357.061 1141.38 391.71 1135.93 419.192C1131.96 439.202 1127.22 455.481 1121.91 466.79C1119.26 472.44 1116.44 476.922 1113.45 480.009C1110.45 483.098 1107.18 484.898 1103.67 484.898C1100.16 484.898 1096.88 483.098 1093.89 480.009C1090.89 476.922 1088.07 472.44 1085.42 466.79C1080.12 455.481 1075.37 439.202 1071.4 419.192C1065.71 390.491 1061.58 353.973 1059.69 313.128C1058.05 339.344 1055.16 362.814 1051.37 381.796C1048.32 397.021 1044.68 409.428 1040.6 418.061C1038.56 422.374 1036.38 425.816 1034.05 428.199C1031.72 430.583 1029.14 432.009 1026.33 432.009C1023.53 432.009 1020.95 430.584 1018.62 428.199C1016.29 425.816 1014.11 422.374 1012.07 418.061C1007.99 409.428 1004.34 397.021 1001.3 381.796C996.723 358.916 993.462 329.514 992.122 296.645C991.214 303.891 990.024 310.479 988.604 316.174C986.901 323.007 984.852 328.631 982.525 332.579C980.252 336.436 977.453 339.12 974.111 339.12C970.77 339.12 967.97 336.436 965.697 332.579C963.371 328.631 961.321 323.007 959.618 316.174C956.207 302.489 954.111 283.654 954.111 262.898C954.111 242.142 956.207 223.306 959.618 209.621C961.321 202.788 963.371 197.165 965.697 193.217C967.97 189.36 970.77 186.675 974.111 186.675C977.453 186.675 980.252 189.36 982.525 193.217C984.852 197.165 986.901 202.788 988.604 209.621C990.024 215.316 991.214 221.904 992.122 229.15C993.462 196.281 996.723 166.88 1001.3 144C1004.34 128.775 1007.99 116.368 1012.07 107.735C1014.11 103.422 1016.29 99.9787 1018.62 97.5962C1020.95 95.2115 1023.53 93.7866 1026.33 93.7866C1029.14 93.7868 1031.72 95.2116 1034.05 97.5962C1036.38 99.9787 1038.56 103.422 1040.6 107.735C1044.68 116.368 1048.32 128.775 1051.37 144C1055.16 162.981 1058.05 186.451 1059.69 212.666C1061.58 171.821 1065.71 135.304 1071.4 106.604C1075.37 86.5944 1080.12 70.315 1085.42 59.0063C1088.07 53.3558 1090.89 48.8741 1093.89 45.7866C1096.88 42.6974 1100.16 40.8979 1103.67 40.8979C1107.18 40.898 1110.45 42.6975 1113.45 45.7866C1116.44 48.8741 1119.26 53.3558 1121.91 59.0063C1127.22 70.315 1131.96 86.5945 1135.93 106.604C1141.38 134.086 1145.4 168.735 1147.39 207.487C1149.46 163.323 1153.95 123.84 1160.13 92.7749C1164.46 70.9957 1169.64 53.2843 1175.42 40.9858C1178.31 34.8403 1181.38 29.9743 1184.64 26.6265C1187.89 23.2769 1191.44 21.3423 1195.22 21.3423Z\" fill=\"url(#nexorChatBrandGrad)\"/>\n    <path d=\"M1490.82 416.676V103.332H1525.71L1541.01 146.784C1559.98 106.392 1596.7 95.3758 1652.39 99.0477V155.964C1588.13 146.784 1556.31 177.996 1556.31 251.436V416.676H1490.82Z\" fill=\"#232522\"/>\n    <path d=\"M1681.68 78.9118C1650.58 78.9118 1642.32 61.0558 1642.32 39.3598C1642.32 17.9518 1650.86 -0.000219345 1681.68 -0.000219345C1712.88 -0.000219345 1721.04 17.9518 1721.04 39.4558C1721.04 61.0558 1712.88 78.9118 1681.68 78.9118ZM1651.82 39.4558C1651.82 57.3118 1658.26 70.7518 1681.68 70.7518C1705.2 70.7518 1711.54 57.3118 1711.54 39.4558C1711.54 21.5998 1705.2 8.15978 1681.68 8.15978C1658.35 8.15978 1651.82 21.6958 1651.82 39.4558ZM1662.1 39.8398C1662.1 28.2238 1666.9 18.3358 1681.87 18.3358C1693.87 18.3358 1700.11 25.0558 1700.11 36.1918H1691.28C1690.7 29.2798 1687.82 26.3998 1681.78 26.3998C1674.1 26.3998 1671.02 31.2958 1671.02 39.5518C1671.02 47.9038 1674.1 52.8958 1681.78 52.8958C1687.82 52.8958 1690.8 50.0158 1691.28 43.3918H1700.11C1700.11 54.6238 1694.16 61.0558 1682.16 61.0558C1666.9 61.0558 1662.1 51.2638 1662.1 39.8398Z\" fill=\"#232522\"/>\n  </svg>`;\n\nfunction buildFooter(): HTMLDivElement {\n  const el = document.createElement(\"div\");\n  el.className = \"nexor-chat__footer\";\n  // Brand attribution only — not a link (intentionally not clickable). A custom\n  // CSS tooltip (instant, reliable — unlike a native SVG <title>) surfaces the\n  // site on hover so visitors know where to find Nexor.\n  el.innerHTML = `<span>Powered by</span><span class=\"nexor-chat__brand\" aria-label=\"Nexor\"><span class=\"nexor-chat__brand-tip\" role=\"tooltip\">getnexor.ai</span>${NEXOR_WORDMARK}</span>`;\n  return el;\n}\n\n// ─── Message bubbles ───────────────────────────────────────────────────────\n\nexport type MessageRole = \"user\" | \"bot\" | \"system\";\n\n/**\n * Build a chat bubble. `textContent` is used (never innerHTML) so user input\n * is rendered as plain text — no XSS surface from message payloads.\n */\nexport function buildMessage(\n  role: MessageRole,\n  text: string,\n  ts?: number,\n  locale?: string,\n): HTMLDivElement {\n  const el = document.createElement(\"div\");\n  el.className = `nexor-chat__msg nexor-chat__msg--${role}`;\n  const body = document.createElement(\"span\");\n  body.className = \"nexor-chat__msg-text\";\n  body.textContent = text;\n  el.appendChild(body);\n  // Relative time under user/bot messages (not system notices). `data-ts` lets\n  // the widget refresh the label as time passes (see index.ts).\n  if (role !== \"system\" && ts) {\n    const time = document.createElement(\"time\");\n    time.className = \"nexor-chat__msg-time\";\n    time.dataset.ts = String(ts);\n    time.textContent = formatRelativeTime(ts, locale);\n    el.appendChild(time);\n  }\n  return el;\n}\n\n/**\n * Relative within the last week (\"ahora\", \"hace 3 minutos\", \"hace 2 horas\",\n * \"ayer\"), then an absolute date (\"12 may\"). Localized via Intl; falls back to\n * a plain clock time if Intl.RelativeTimeFormat is unavailable.\n */\nexport function formatRelativeTime(\n  ts: number,\n  locale?: string,\n  now: number = Date.now(),\n): string {\n  try {\n    const diff = Math.max(0, now - ts);\n    const min = Math.round(diff / 60000);\n    const hr = Math.round(diff / 3600000);\n    const day = Math.round(diff / 86400000);\n    const rtf = new Intl.RelativeTimeFormat(locale, { numeric: \"auto\" });\n    if (diff < 45000) return rtf.format(0, \"second\"); // \"ahora\" / \"now\"\n    if (min < 60) return rtf.format(-min, \"minute\");\n    if (hr < 24) return rtf.format(-hr, \"hour\");\n    if (day < 7) return rtf.format(-day, \"day\"); // includes \"ayer\"/\"yesterday\"\n    return new Date(ts).toLocaleDateString(locale, {\n      day: \"numeric\",\n      month: \"short\",\n    });\n  } catch {\n    try {\n      return new Date(ts).toLocaleTimeString(locale, {\n        hour: \"2-digit\",\n        minute: \"2-digit\",\n      });\n    } catch {\n      return \"\";\n    }\n  }\n}\n\n// ─── Resume banner (returning visitor) ──────────────────────────────────────\n\nexport interface ResumeBannerRefs {\n  el: HTMLDivElement;\n  resetBtn: HTMLButtonElement;\n}\n\n/**\n * A slim banner shown at the top of a restored conversation: it tells the\n * visitor we kept their chat (with their name/email when known) and offers a\n * \"start over\" reset. Replaces the broken state where the capture form rendered\n * on top of an existing conversation.\n */\nexport function buildResumeBanner(\n  text: string,\n  resetLabel: string,\n): ResumeBannerRefs {\n  const el = document.createElement(\"div\");\n  el.className = \"nexor-chat__resume\";\n\n  const label = document.createElement(\"span\");\n  label.className = \"nexor-chat__resume-text\";\n  label.textContent = text;\n\n  const resetBtn = document.createElement(\"button\");\n  resetBtn.type = \"button\";\n  resetBtn.className = \"nexor-chat__resume-reset\";\n  resetBtn.textContent = resetLabel;\n\n  el.appendChild(label);\n  el.appendChild(resetBtn);\n  return { el, resetBtn };\n}\n\n/** Three-dot typing indicator. Animation lives in styles.ts. */\nexport function buildTypingIndicator(): HTMLDivElement {\n  const el = document.createElement(\"div\");\n  el.className = \"nexor-chat__typing\";\n  el.innerHTML = \"<span></span><span></span><span></span>\";\n  return el;\n}\n\n// ─── Helpers ───────────────────────────────────────────────────────────────\n\nfunction makeInput(\n  name: string,\n  placeholder: string,\n  type: string,\n  value?: string,\n): HTMLInputElement {\n  const i = document.createElement(\"input\");\n  i.name = name;\n  i.type = type;\n  i.placeholder = placeholder;\n  if (value) i.value = value;\n  return i;\n}\n\n/**\n * Escape strings before interpolation into innerHTML. Used only for\n * SDK-controlled config values (title, subtitle) — user-typed messages\n * always go through textContent, which doesn't need escaping.\n */\nfunction escapeHtml(s: string): string {\n  return s\n    .replace(/&/g, \"&amp;\")\n    .replace(/</g, \"&lt;\")\n    .replace(/>/g, \"&gt;\")\n    .replace(/\"/g, \"&quot;\")\n    .replace(/'/g, \"&#039;\");\n}\n","/**\n * Chat widget orchestrator.\n *\n * Responsibilities (everything else lives in sibling files):\n *   - apply defaults / validate options (`./config`)\n *   - manage session id (`./session`)\n *   - build DOM (`./dom`)\n *   - inject CSS (`./dom`)\n *\n * What stays here:\n *   - the open/close state machine\n *   - wiring DOM events to the NexorClient.chat() call\n *   - lead-capture submission flow\n *   - the public ChatHandle returned to callers\n */\nimport type { NexorClient } from \"../client\";\nimport type { UUID } from \"../types\";\nimport {\n  applyDefaults,\n  needsCapture,\n  type ChatInitOptions,\n  type ChatHandle,\n  type ResolvedCfg,\n  type ContactRequestChannel,\n} from \"./config\";\nimport {\n  ensureSessionId,\n  touchSession,\n  SESSION_RETENTION_MS,\n} from \"./session\";\nimport { isValidEmail } from \"./validate\";\nimport { renderLeadTemplate } from \"./template\";\nimport { countryByIso, maxNsn, resolveDefaultCountry } from \"./countries\";\nimport {\n  buildLauncher,\n  buildMessage,\n  buildPanel,\n  buildResumeBanner,\n  buildTypingIndicator,\n  formatRelativeTime,\n  injectStyles,\n  type LauncherRefs,\n  type MessageRole,\n  type PanelRefs,\n} from \"./dom\";\n\n// Re-export the public types so consumers can `import type { ChatHandle } from \"@getnexorai/sdk\"`.\nexport type {\n  ChatInitOptions,\n  ChatHandle,\n  ChatLeadCapture,\n  ChatChannels,\n  ChatChannelKey,\n} from \"./config\";\n\n/**\n * Mount the chat widget and return a handle for programmatic control.\n *\n * @param client  The NexorClient instance that will send turns.\n * @param options User-facing widget configuration. See ChatInitOptions.\n * @throws If called outside a browser, or without a workflowId.\n */\nexport function initChat(\n  client: NexorClient,\n  options: ChatInitOptions,\n): ChatHandle {\n  ensureBrowser();\n  if (!options || !options.workflowId) {\n    throw new Error(\"Nexor SDK: initChat() requires `workflowId`.\");\n  }\n\n  const cfg = applyDefaults(options);\n  injectStyles(cfg.accentColor, cfg.accentTextColor);\n\n  // Mutable: \"start over\" mints a fresh session id (and history key) without\n  // tearing down the widget.\n  let sessionId = ensureSessionId();\n  let historyKey = `nexor.chat.history.${sessionId}`;\n  const root = buildRoot(cfg);\n  const launcher = buildLauncher(cfg);\n  const panel = buildPanel(cfg);\n  root.appendChild(launcher.wrap);\n  root.appendChild(panel.el);\n  (cfg.container ?? document.body).appendChild(root);\n\n  const hasFan = launcher.channelButtons.length > 0;\n\n  // ─── State (closure-private — no external observers needed) ─────────────\n  const state = {\n    isOpen: false,\n    expanded: false, // speed-dial fan visible (touch/click-pinned)\n    unread: 0,\n    leadId: undefined as UUID | undefined,\n    captured: !needsCapture(cfg),\n    pendingLead: { ...(cfg.lead ?? {}) },\n    history: [] as Array<{ role: \"user\" | \"bot\"; text: string; ts?: number }>,\n    // Dashboard-authored web-chat config (fetched once on init). Until it\n    // resolves, assume enabled and fall back to the host-provided `greeting`.\n    webchatEnabled: true,\n    serverInitialMessage: null as string | null,\n    configResolved: false,\n    disabledShown: false,\n    // The opening message actually displayed to the visitor — sent to the API\n    // so the agent's <webchat_opening> matches what was shown (esp. for a\n    // per-page openingMessage override).\n    shownOpening: null as string | null,\n    // Set by \"start over\" → the next turn tells the API to reset the conversation\n    // episode (keep the lead, clear its prior run/thread/variables). Cleared once\n    // that turn lands.\n    resetEpisode: false,\n    // True when this page load started with NO restored transcript. Used to\n    // decide whether to offer the \"continue / start fresh\" choice when the API\n    // reports it recognised a returning lead (matched_existing).\n    freshLocalSession: false,\n    // Ensures the returning-lead choice banner is offered at most once.\n    episodeChoiceOffered: false,\n    // The channel a visitor picked in the contact-request form (call/email/...).\n    contactChannel: null as ContactRequestChannel | null,\n    // In-flight \"create lead on form submit\" request — the first chat turn waits\n    // on it so the backend matches that lead (no duplicate) rather than racing it.\n    leadCreating: null as Promise<void> | null,\n  };\n\n  // Resolves once GET /chat/config returns (or fails). The greeting waits on\n  // this so it can use the dashboard `initial_message` rather than the fallback.\n  let configReady: Promise<void>;\n\n  // Composer/send state, hoisted above DOM wiring + history restore so the\n  // call chain `restore → appendBubble → appendNode → send.typing` (and the\n  // openOnLoad → appendBot greeting path) doesn't hit a TDZ. See the\n  // debounced/coalesced send logic further down for how this is used.\n  const send = {\n    pending: [] as string[],\n    timer: 0,\n    inFlight: false,\n    typing: null as HTMLElement | null,\n    splitTimer: 0, // staggers multi-bubble bot replies\n  };\n\n  // First-impression delay: the lazy-greet bubble used to appear instantly,\n  // which read as canned. Show typing dots for ~2s first so the greeting feels\n  // composed in the moment. Cancelled if the visitor sends before it fires.\n  const greeting = { pending: false, timer: 0 };\n  const GREETING_DELAY_MS = 2000;\n\n  // ─── DOM event wiring ───────────────────────────────────────────────────\n  // Without a fan the bubble simply opens/closes the chat. With a fan, the\n  // bubble toggles the channel menu (desktop also reveals it on hover via CSS);\n  // the \"chat\" button inside the fan is what actually opens the panel.\n  launcher.el.addEventListener(\"click\", hasFan ? toggleFan : toggle);\n  panel.closeBtn.addEventListener(\"click\", close);\n  panel.restartBtn?.addEventListener(\"click\", startOver);\n  panel.form.addEventListener(\"submit\", onComposerSubmit);\n  // Composer textarea: grow with content, and Enter sends / Shift+Enter newline.\n  panel.input.addEventListener(\"input\", autosizeComposer);\n  panel.input.addEventListener(\"keydown\", (e: KeyboardEvent) => {\n    // `isComposing` guards IME (e.g. accents, CJK) — don't send mid-composition.\n    if (e.key === \"Enter\" && !e.shiftKey && !e.isComposing) {\n      e.preventDefault();\n      onComposerSubmit(e);\n    }\n  });\n  panel.captureForm?.addEventListener(\"submit\", onCaptureSubmit);\n  // Clear the inline validation error as soon as the visitor edits any field.\n  for (const input of Object.values(panel.captureInputs)) {\n    input?.addEventListener(\"input\", clearCaptureError);\n  }\n  // Phone field (chat capture): digits only, capped to the selected country's\n  // number length; re-cap (and trim any excess) when the country changes.\n  if (panel.phoneCountry && panel.captureInputs.phone) {\n    wirePhoneCap(panel.phoneCountry, panel.captureInputs.phone, clearCaptureError);\n  }\n\n  // ─── Contact-request form wiring (call me / email me) ────────────────────\n  if (panel.contact) {\n    const c = panel.contact;\n    c.form.addEventListener(\"submit\", onContactSubmit);\n    for (const input of Object.values(c.inputs)) {\n      input?.addEventListener(\"input\", clearContactError);\n    }\n    if (c.phoneCountry && c.inputs.phone) {\n      wirePhoneCap(c.phoneCountry, c.inputs.phone, clearContactError);\n    }\n    // \"Done\" (success) dismisses the form; close() restores the base view so a\n    // re-open shows the normal chat/capture screen, not a stale success panel.\n    c.successBtn.addEventListener(\"click\", close);\n  }\n\n  // Wire the fan buttons: the chat action opens the panel; channel links just\n  // collapse the fan once tapped (they navigate natively).\n  let onDocPointerDown: ((e: Event) => void) | null = null;\n  if (hasFan) {\n    for (const btn of launcher.channelButtons) {\n      btn.el.addEventListener(\"click\", () => {\n        if (btn.key === \"chat\") {\n          collapseFan();\n          open();\n        } else if (btn.action === \"contact\") {\n          collapseFan();\n          openContact(btn.key as ContactRequestChannel);\n        } else {\n          collapseFan(); // link navigates on its own\n        }\n      });\n    }\n    // Tap/click anywhere outside the launcher collapses the fan (touch devices\n    // have no hover-out to rely on).\n    onDocPointerDown = (e: Event) => {\n      if (state.expanded && !launcher.wrap.contains(e.target as Node)) collapseFan();\n    };\n    document.addEventListener(\"pointerdown\", onDocPointerDown);\n  }\n\n  // Track the resume banner so \"start over\" can remove it.\n  let resumeBanner: HTMLElement | null = null;\n\n  // Restore a prior transcript (persisted up to SESSION_RETENTION_MS) so a\n  // page reload keeps the conversation. A returning visitor is ALREADY past the\n  // capture form — re-showing it on top of an existing conversation (the broken\n  // state) makes no sense. So when there's history we: keep their known info,\n  // mark them captured, hide the form, and show a \"continue or start over\"\n  // banner above the messages.\n  const persisted = loadPersisted();\n  // No restored transcript → a \"returning lead\" can only be discovered from the\n  // API (matched_existing), so the choice banner is offered then. With restored\n  // history we already show the resume banner below, so skip the API-driven one.\n  state.freshLocalSession = persisted.history.length === 0;\n  if (persisted.history.length) {\n    state.history = persisted.history;\n    if (persisted.lead) state.pendingLead = { ...state.pendingLead, ...persisted.lead };\n    state.captured = true;\n    setView(\"chat\");\n    renderResumeBanner();\n    for (const m of persisted.history) {\n      appendBubble(m.role === \"user\" ? \"user\" : \"bot\", m.text, m.ts);\n    }\n    scrollToBottom();\n  }\n\n  // Lock/unlock the composer to match the (possibly just-restored) captured state.\n  syncComposerLock();\n\n  // Fetch the dashboard-authored web-chat config (enabled flag + opening\n  // message) once. Fire-and-forget; the greeting awaits `configReady`.\n  configReady = loadServerConfig();\n\n  if (cfg.openOnLoad) open();\n\n  // ─── State machine ──────────────────────────────────────────────────────\n\n  // ─── Speed-dial fan (channels) ──────────────────────────────────────────\n\n  function toggleFan(): void {\n    state.expanded ? collapseFan() : expandFan();\n  }\n  function expandFan(): void {\n    state.expanded = true;\n    launcher.wrap.setAttribute(\"data-expanded\", \"true\");\n    launcher.el.setAttribute(\"aria-expanded\", \"true\");\n  }\n  function collapseFan(): void {\n    if (!state.expanded) return;\n    state.expanded = false;\n    launcher.wrap.setAttribute(\"data-expanded\", \"false\");\n    launcher.el.setAttribute(\"aria-expanded\", \"false\");\n  }\n\n  function open(): void {\n    collapseFan(); // the panel takes over; no need for the fan underneath\n    if (state.isOpen) return;\n    state.isOpen = true;\n    root.setAttribute(\"data-open\", \"true\");\n    clearUnread();\n    // Web chat turned off in the dashboard → no capture, no greeting, just a notice.\n    if (!state.webchatEnabled) {\n      showDisabled();\n      cfg.onOpen?.();\n      return;\n    }\n    // Lazy-greet: first time the panel opens, drop the greeting message.\n    if (state.history.length === 0 && state.captured && canGreet()) {\n      scheduleGreeting();\n    }\n    // Focus the first thing the visitor should fill: the capture form when it's\n    // gating chat, otherwise the composer.\n    if (!state.captured) {\n      const first = cfg.capture.fields[0];\n      ((first && panel.captureInputs[first]) || panel.input).focus();\n    } else {\n      panel.input.focus();\n    }\n    cfg.onOpen?.();\n  }\n\n  function close(): void {\n    if (!state.isOpen) return;\n    state.isOpen = false;\n    root.setAttribute(\"data-open\", \"false\");\n    // Leaving the contact-request screen → restore the normal view AND the chat\n    // header, so a re-open shows chat/capture (not the form or a stale success).\n    if (panel.el.getAttribute(\"data-view\") === \"contact\") {\n      state.contactChannel = null;\n      setView(baseView());\n      restoreHeader();\n    }\n    cfg.onClose?.();\n  }\n\n  /** Restore the chat title/subtitle in the header after the contact form. */\n  function restoreHeader(): void {\n    panel.headerTitle.textContent = cfg.title;\n    panel.headerSubtitleText.textContent = cfg.subtitle ?? \"\";\n    panel.headerSubtitle.hidden = !cfg.subtitle;\n  }\n\n  function toggle(): void {\n    state.isOpen ? close() : open();\n  }\n\n  // ─── Capture flow ───────────────────────────────────────────────────────\n\n  function onCaptureSubmit(e: Event): void {\n    e.preventDefault();\n    clearCaptureError();\n    const collected = readCaptureFields(panel);\n    const required = cfg.capture.fields;\n    const msgs = cfg.capture.errorMessages;\n\n    // 1) Every required field must be filled.\n    for (const f of required) {\n      if (!collected[f]) return failCapture(f, msgs.required);\n    }\n    // 2) Email must look like an email.\n    if (required.includes(\"email\") && !isValidEmail(collected.email ?? \"\")) {\n      return failCapture(\"email\", msgs.email);\n    }\n    // 3) Phone: the national digit count must match the selected country, then\n    //    store the full E.164 (dial + digits) so the backend gets a clean number.\n    if (required.includes(\"phone\")) {\n      const country = countryByIso(panel.phoneCountry?.value);\n      const digits = (collected.phone ?? \"\").replace(/\\D/g, \"\");\n      if (!country || digits.length < country.nsn[0] || digits.length > country.nsn[1]) {\n        return failCapture(\"phone\", msgs.phone);\n      }\n      collected.phone = `${country.dial}${digits}`;\n    }\n\n    state.pendingLead = { ...state.pendingLead, ...collected };\n    state.captured = true;\n    // Create the lead in Nexor now (opt-in) — don't wait for the first message.\n    persistCapturedLead();\n    setView(\"chat\"); // leave the capture screen, reveal the conversation\n    syncComposerLock();\n    panel.input.focus();\n    // Greet once capture clears, so the greeting feels like a response to \"I'm ready\".\n    if (state.history.length === 0 && canGreet()) scheduleGreeting();\n  }\n\n  /**\n   * Create the lead in Nexor the instant the capture form is submitted (opt-in\n   * via capture.createLeadOnSubmit), so a visitor who fills the form but never\n   * sends a message is still captured. Fire-and-forget: the chat flow never waits\n   * on it and a failure never blocks chatting. The first chat turn then MATCHES\n   * this lead by email/phone, so there's no duplicate.\n   */\n  function persistCapturedLead(): void {\n    if (!cfg.capture.createLeadOnSubmit || state.leadId) return;\n    const lead = state.pendingLead;\n    if (!lead.first_name && !lead.email && !lead.phone) return;\n    const resolvedMeta =\n      typeof cfg.metadata === \"function\" ? cfg.metadata() : cfg.metadata;\n    state.leadCreating = client\n      .createLead({\n        first_name: lead.first_name || \"Web visitor\",\n        last_name: lead.last_name,\n        email: lead.email,\n        phone: lead.phone,\n        source: \"web-chat\",\n        metadata: {\n          ...(resolvedMeta as Record<string, unknown> | undefined),\n          web_chat_session_id: sessionId,\n        },\n      })\n      .then((res) => {\n        if (res?.lead?.id && !state.leadId) {\n          state.leadId = res.lead.id;\n          cfg.onLeadCaptured?.(res.lead.id);\n        }\n        // A brand-new lead isn't a \"returning visitor\": suppress the\n        // matched_existing resume banner the first chat turn would otherwise\n        // raise (that turn WILL match this just-created lead by identity).\n        if (res && !res.existed) state.episodeChoiceOffered = true;\n      })\n      .catch((err) => {\n        // Non-blocking: the first chat turn still creates/matches the lead.\n        cfg.onError?.(err as Error);\n      })\n      .finally(() => {\n        state.leadCreating = null;\n      });\n  }\n\n  // ─── Capture validation feedback ────────────────────────────────────────\n\n  function failCapture(field: keyof typeof panel.captureInputs, message: string): void {\n    showCaptureError(message);\n    const input = panel.captureInputs[field];\n    // For phone, outline the whole composite (flag + input), not just the input.\n    const target = (input?.closest(\".nexor-chat__phone\") as HTMLElement | null) || input;\n    target?.classList.add(\"nexor-chat__input--error\");\n    input?.focus();\n  }\n  function showCaptureError(message: string): void {\n    if (!panel.captureError) return;\n    panel.captureError.textContent = message;\n    panel.captureError.hidden = false;\n  }\n  function clearCaptureError(): void {\n    if (panel.captureError) {\n      panel.captureError.textContent = \"\";\n      panel.captureError.hidden = true;\n    }\n    // Covers both plain inputs and the phone composite wrapper.\n    panel.captureForm\n      ?.querySelectorAll(\".nexor-chat__input--error\")\n      .forEach((el) => el.classList.remove(\"nexor-chat__input--error\"));\n  }\n\n  // ─── Contact-request flow (call me / email me) ──────────────────────────\n\n  /** Cap a phone input to its country's digit length + strip non-digits live.\n   *  Shared by the chat-capture and contact-request phone fields. */\n  function wirePhoneCap(\n    select: HTMLSelectElement,\n    input: HTMLInputElement,\n    onChange?: () => void,\n  ): void {\n    const cap = (): void => {\n      const c = countryByIso(select.value);\n      const max = c ? maxNsn(c) : 15;\n      input.maxLength = max;\n      const digits = input.value.replace(/\\D/g, \"\").slice(0, max);\n      if (input.value !== digits) input.value = digits;\n    };\n    input.addEventListener(\"input\", cap);\n    select.addEventListener(\"change\", () => {\n      cap();\n      onChange?.();\n    });\n  }\n\n  /** Open the panel straight into the contact-request form for `channel`. */\n  function openContact(channel: ContactRequestChannel): void {\n    const c = panel.contact;\n    const rc = cfg.requestContact;\n    if (!c || !rc) return;\n    state.contactChannel = channel;\n\n    // Re-contextualize the panel HEADER as the form's title + explainer, so the\n    // black bar itself reads as a form (the chat \"we reply in minutes\" subtitle\n    // and the live-status dot — hidden via CSS in this view — make no sense here).\n    panel.headerTitle.textContent = rc.title[channel] ?? cfg.title;\n    panel.headerSubtitleText.textContent = rc.subtitle[channel] ?? \"\";\n    panel.headerSubtitle.hidden = !rc.subtitle[channel];\n    c.submitBtn.textContent = rc.submitLabel[channel] ?? \"\";\n    c.successText.textContent = rc.successText[channel] ?? \"\";\n\n    // Reset to a clean form state (clear any prior success / errors / values).\n    c.view.setAttribute(\"data-state\", \"form\");\n    c.submitBtn.disabled = false;\n    clearContactError();\n    resetContactForm();\n\n    // Open the panel into the contact view — skip the greeting/capture logic.\n    cancelGreeting();\n    state.isOpen = true;\n    root.setAttribute(\"data-open\", \"true\");\n    clearUnread();\n    setView(\"contact\");\n    // Focus the first field still needing input (skip any we pre-filled).\n    const firstEmpty = [c.inputs.first_name, c.inputs.email, c.inputs.phone].find(\n      (i) => i && !i.value,\n    );\n    (firstEmpty ?? c.inputs.first_name ?? null)?.focus();\n    cfg.onOpen?.();\n  }\n\n  /**\n   * Reset the contact form to the freshest known lead before each open: clears\n   * any stale data a visitor typed but didn't submit, and pre-fills whatever we\n   * already know (e.g. from a chat capture earlier this session) so they don't\n   * retype it. Mirrors buildPhoneField's national-number prefill.\n   */\n  function resetContactForm(): void {\n    const c = panel.contact;\n    if (!c) return;\n    const lead = state.pendingLead;\n    if (c.inputs.first_name) c.inputs.first_name.value = lead.first_name ?? \"\";\n    if (c.inputs.last_name) c.inputs.last_name.value = lead.last_name ?? \"\";\n    if (c.inputs.email) c.inputs.email.value = lead.email ?? \"\";\n    const def = resolveDefaultCountry(cfg.capture.phoneCountryCode);\n    if (c.phoneCountry) c.phoneCountry.value = def.iso;\n    if (c.inputs.phone) {\n      let national = \"\";\n      if (lead.phone) {\n        const digits = String(lead.phone).replace(/\\D/g, \"\");\n        const dialDigits = def.dial.replace(/\\D/g, \"\");\n        national = (digits.startsWith(dialDigits) ? digits.slice(dialDigits.length) : digits).slice(\n          0,\n          maxNsn(def),\n        );\n      }\n      c.inputs.phone.maxLength = maxNsn(def);\n      c.inputs.phone.value = national;\n    }\n  }\n\n  function onContactSubmit(e: Event): void {\n    e.preventDefault();\n    const c = panel.contact;\n    const channel = state.contactChannel;\n    if (!c || !channel) return;\n    clearContactError();\n    const msgs = cfg.capture.errorMessages;\n\n    const first = c.inputs.first_name?.value.trim() ?? \"\";\n    const last = c.inputs.last_name?.value.trim() ?? \"\";\n    const email = c.inputs.email?.value.trim() ?? \"\";\n    const phoneDigits = (c.inputs.phone?.value ?? \"\").replace(/\\D/g, \"\");\n\n    // First name is always required.\n    if (!first) return failContact(\"first_name\", msgs.required);\n\n    // Email: required for the email channel; whenever provided, must be valid.\n    const needEmail = channel === \"email\";\n    if (needEmail && !email) return failContact(\"email\", msgs.required);\n    if (email && !isValidEmail(email)) return failContact(\"email\", msgs.email);\n\n    // Phone: required for call/whatsapp; whenever provided, must fit its country.\n    const needPhone = channel === \"call\" || channel === \"whatsapp\";\n    let e164: string | undefined;\n    if (needPhone || phoneDigits) {\n      const country = countryByIso(c.phoneCountry?.value);\n      if (!country || phoneDigits.length < country.nsn[0] || phoneDigits.length > country.nsn[1]) {\n        return failContact(\"phone\", msgs.phone);\n      }\n      e164 = `${country.dial}${phoneDigits}`;\n    }\n\n    void submitContact(channel, { first, last, email, phone: e164 });\n  }\n\n  async function submitContact(\n    channel: ContactRequestChannel,\n    data: { first: string; last: string; email: string; phone?: string },\n  ): Promise<void> {\n    const c = panel.contact;\n    const rc = cfg.requestContact;\n    if (!c || !rc) return;\n\n    c.submitBtn.disabled = true;\n    const resolvedMeta =\n      typeof cfg.metadata === \"function\" ? cfg.metadata() : cfg.metadata;\n    const meta = (resolvedMeta as Record<string, unknown> | undefined) ?? undefined;\n    const pageUrl =\n      (meta && meta.page_url) ||\n      (typeof window !== \"undefined\" ? window.location.href : undefined);\n\n    try {\n      const res = await client.requestContact(\n        {\n          workflow_id: cfg.workflowId,\n          first_name: data.first,\n          last_name: data.last || undefined,\n          email: data.email || undefined,\n          phone: data.phone,\n          force_first_channel: channel,\n          source: \"web-chat\",\n          // Context for the agent's first outreach: they were on the site and\n          // explicitly asked to be reached on this channel.\n          metadata: {\n            ...(meta ?? {}),\n            contact_request: true,\n            requested_channel: channel,\n            requested_at: new Date().toISOString(),\n            context_note: `Website visitor asked to be contacted via ${channel}${pageUrl ? ` from ${pageUrl}` : \"\"}.`,\n          },\n        },\n        { timeoutMs: cfg.requestTimeoutMs, maxRetries: 0 },\n      );\n      if (res?.lead?.id && !state.leadId) {\n        state.leadId = res.lead.id;\n        cfg.onLeadCaptured?.(res.lead.id);\n      }\n      // Re-assert the success copy for the channel actually submitted; drop the\n      // header explainer (they've submitted — \"leave your details\" no longer\n      // applies), keep the title, and swap to the success panel.\n      c.successText.textContent = rc.successText[channel] ?? \"\";\n      panel.headerSubtitle.hidden = true;\n      c.view.setAttribute(\"data-state\", \"sent\");\n    } catch (err) {\n      c.submitBtn.disabled = false;\n      showContactError(rc.errorText);\n      cfg.onError?.(err as Error);\n    }\n  }\n\n  // ─── Contact validation feedback ────────────────────────────────────────\n\n  function failContact(\n    field: \"first_name\" | \"last_name\" | \"email\" | \"phone\",\n    message: string,\n  ): void {\n    const c = panel.contact;\n    if (!c) return;\n    showContactError(message);\n    const input = c.inputs[field];\n    // For phone, outline the whole composite (flag + input), not just the input.\n    const target = (input?.closest(\".nexor-chat__phone\") as HTMLElement | null) || input;\n    target?.classList.add(\"nexor-chat__input--error\");\n    input?.focus();\n  }\n  function showContactError(message: string): void {\n    const c = panel.contact;\n    if (!c) return;\n    c.error.textContent = message;\n    c.error.hidden = false;\n  }\n  function clearContactError(): void {\n    const c = panel.contact;\n    if (!c) return;\n    c.error.textContent = \"\";\n    c.error.hidden = true;\n    c.form\n      .querySelectorAll(\".nexor-chat__input--error\")\n      .forEach((el) => el.classList.remove(\"nexor-chat__input--error\"));\n  }\n\n  // ─── Panel view (\"capture\" screen vs \"chat\") + \"start over\" reset ───────\n\n  /** Swap the panel between the capture form, the chat, and the contact form. */\n  function setView(view: \"capture\" | \"chat\" | \"contact\"): void {\n    panel.el.setAttribute(\"data-view\", view);\n  }\n\n  /** The normal screen for this widget — capture if still gating, else chat. */\n  function baseView(): \"capture\" | \"chat\" {\n    return state.captured ? \"chat\" : \"capture\";\n  }\n\n  /** Banner text for a restored conversation, personalised when we know who it is. */\n  function identityText(): string {\n    const l = state.pendingLead;\n    const who = (l.first_name || l.email || l.phone || \"\").trim();\n    return who ? cfg.resumeWithNameText.replace(\"{name}\", who) : cfg.resumeText;\n  }\n\n  function renderResumeBanner(prepend = false): void {\n    if (resumeBanner) return; // already showing\n    const banner = buildResumeBanner(identityText(), cfg.startOverText);\n    banner.resetBtn.addEventListener(\"click\", startOver);\n    // Restore path: body is empty, append → ends up on top, messages follow.\n    // API-driven path: messages already exist, so insert at the very top.\n    if (prepend && panel.body.firstChild) {\n      panel.body.insertBefore(banner.el, panel.body.firstChild);\n    } else {\n      panel.body.appendChild(banner.el);\n    }\n    resumeBanner = banner.el;\n  }\n\n  /**\n   * \"Clear and start again\" — start a fresh conversation EPISODE on the SAME\n   * lead. We keep the visitor's identity (no re-capture, no duplicate lead) and\n   * just clear the local transcript; the next turn tells the API to reset the\n   * episode (deactivate the prior run/thread + clear the workflow's variables),\n   * so the agent no longer brings up the previous conversation.\n   */\n  function startOver(): void {\n    cancelGreeting();\n    if (send.timer) {\n      window.clearTimeout(send.timer);\n      send.timer = 0;\n    }\n    if (send.splitTimer) {\n      window.clearTimeout(send.splitTimer);\n      send.splitTimer = 0;\n    }\n    send.pending = [];\n    hideTyping();\n\n    // Wipe the local transcript AND the persisted session (history + the known\n    // lead), so nothing about the previous visitor survives the reset.\n    try {\n      window.localStorage.removeItem(historyKey);\n    } catch {\n      /* ignore */\n    }\n    state.history = [];\n    state.shownOpening = null;\n    resumeBanner = null;\n    panel.body.replaceChildren();\n\n    // Lead-capture widgets: \"start again\" is a clean slate → forget the known\n    // identity and send the visitor BACK TO THE FORM. The next submit creates a\n    // fresh lead; the first chat turn carries reset_episode so that if they\n    // re-enter the same email, the server clears the old run/thread/variables\n    // (no prior context bleeds in). A genuinely new email just makes a new lead.\n    if (panel.captureView) {\n      state.pendingLead = { ...(cfg.lead ?? {}) };\n      state.captured = false;\n      state.leadId = undefined;\n      state.episodeChoiceOffered = false;\n      state.resetEpisode = true;\n      resetCaptureForm();\n      setView(\"capture\");\n      syncComposerLock();\n      const first = cfg.capture.fields[0];\n      ((first && panel.captureInputs[first]) || panel.input).focus();\n      return;\n    }\n\n    // No capture form (skip mode): keep the lead, reset the episode server-side,\n    // and drop straight into a fresh greeting.\n    state.resetEpisode = true;\n    setView(\"chat\");\n    syncComposerLock();\n    if (state.captured && canGreet()) scheduleGreeting();\n    panel.input.focus();\n  }\n\n  /** Clear the capture form back to the configured lead (used by \"start again\"). */\n  function resetCaptureForm(): void {\n    const lead = state.pendingLead;\n    if (panel.captureInputs.first_name) panel.captureInputs.first_name.value = lead.first_name ?? \"\";\n    if (panel.captureInputs.last_name) panel.captureInputs.last_name.value = lead.last_name ?? \"\";\n    if (panel.captureInputs.email) panel.captureInputs.email.value = lead.email ?? \"\";\n    const def = resolveDefaultCountry(cfg.capture.phoneCountryCode);\n    if (panel.phoneCountry) panel.phoneCountry.value = def.iso;\n    if (panel.captureInputs.phone) {\n      let national = \"\";\n      if (lead.phone) {\n        const digits = String(lead.phone).replace(/\\D/g, \"\");\n        const dialDigits = def.dial.replace(/\\D/g, \"\");\n        national = (digits.startsWith(dialDigits) ? digits.slice(dialDigits.length) : digits).slice(\n          0,\n          maxNsn(def),\n        );\n      }\n      panel.captureInputs.phone.maxLength = maxNsn(def);\n      panel.captureInputs.phone.value = national;\n    }\n    clearCaptureError();\n  }\n\n  // ─── Composer / send (debounced + coalesced) ────────────────────────────\n  //\n  // Visitors fire several short messages in a row (WhatsApp-style). We mirror\n  // the WhatsApp contract — batch at the source, one LLM call per batch — by\n  // buffering rapid messages in the browser and POSTing them as a SINGLE\n  // combined turn after a short quiet window. The composer never locks, so the\n  // user can keep typing and sending freely; messages that land mid-request are\n  // sent in the next batch. (`const send` itself is declared near `state`\n  // above so DOM-wiring callbacks don't hit a TDZ on it.)\n\n  function onComposerSubmit(e: Event): void {\n    e.preventDefault();\n    const text = panel.input.value.trim();\n    if (!text) return;\n    panel.input.value = \"\";\n    autosizeComposer(); // collapse the textarea back to one line\n    queueMessage(text);\n  }\n\n  // Grow the composer textarea to fit its content. CSS max-height caps it at ~4\n  // lines and switches on the scrollbar; box-sizing is border-box, so add the\n  // 2px vertical border back so one line doesn't show a phantom scrollbar.\n  function autosizeComposer(): void {\n    const el = panel.input;\n    el.style.height = \"auto\";\n    el.style.height = `${el.scrollHeight + 2}px`;\n  }\n\n  function queueMessage(text: string): void {\n    if (!state.captured) {\n      const first = cfg.capture.fields[0];\n      ((first && panel.captureInputs[first]) || panel.input).focus();\n      return;\n    }\n    // Visitor engaged before the greeting fired — drop it. Showing a canned\n    // greeting *after* their first real message would feel out of order.\n    cancelGreeting();\n    appendUser(text);\n    send.pending.push(text);\n    scheduleFlush();\n  }\n\n  /**\n   * The opening message: the dashboard-authored `initial_message` (with\n   * {{variables}} substituted from the lead we know) when present, else the\n   * host-provided `greeting` fallback.\n   */\n  // Priority: host openingMessage override > dashboard initial_message > greeting.\n  function greetingText(): string {\n    const raw = cfg.openingMessage || state.serverInitialMessage;\n    if (raw) return renderLeadTemplate(raw, state.pendingLead);\n    return cfg.greeting ?? \"\";\n  }\n\n  /** Is there (or might there still be) an opening message worth showing? */\n  function canGreet(): boolean {\n    if (!state.webchatEnabled) return false;\n    if (cfg.openingMessage) return true; // explicit override always greets\n    // Config not back yet → it might still supply an opening, so allow it.\n    if (!state.configResolved) return true;\n    return !!state.serverInitialMessage || !!cfg.greeting;\n  }\n\n  function scheduleGreeting(): void {\n    if (greeting.pending) return;\n    greeting.pending = true;\n    showTyping();\n    greeting.timer = window.setTimeout(async () => {\n      // An explicit openingMessage override wins regardless of server config, so\n      // we can paint immediately. Otherwise wait for the dashboard config so we\n      // show `initial_message` rather than the fallback (dots stay up meanwhile).\n      if (!cfg.openingMessage) await configReady;\n      if (!greeting.pending) return; // cancelled while waiting\n      greeting.pending = false;\n      greeting.timer = 0;\n      hideTyping();\n      const text = greetingText();\n      if (text) {\n        state.shownOpening = text; // tell the agent the exact opening shown\n        appendBot(text);\n      }\n    }, GREETING_DELAY_MS);\n  }\n\n  function cancelGreeting(): void {\n    if (!greeting.pending) return;\n    if (greeting.timer) window.clearTimeout(greeting.timer);\n    greeting.timer = 0;\n    greeting.pending = false;\n    hideTyping();\n  }\n\n  // ─── Server web-chat config (enabled + dashboard opening message) ────────\n\n  async function loadServerConfig(): Promise<void> {\n    try {\n      const res = await client.getChatConfig(cfg.workflowId, {\n        timeoutMs: 10_000,\n        maxRetries: 1,\n      });\n      applyServerConfig(res.enabled !== false, res.initial_message ?? null);\n    } catch {\n      // Config fetch failed (offline, or an API without /chat/config): keep the\n      // widget usable with the host-provided greeting and assume chat is on.\n      applyServerConfig(true, null);\n    }\n  }\n\n  function applyServerConfig(\n    enabled: boolean,\n    initialMessage: string | null,\n  ): void {\n    state.configResolved = true;\n    state.serverInitialMessage = initialMessage;\n    state.webchatEnabled = enabled;\n    if (!enabled) {\n      // Web chat is off for this workflow: pull the \"chat\" speed-dial option and,\n      // if the panel is already open, swap to the unavailable notice.\n      hideChatChannelButton();\n      cancelGreeting();\n      if (state.isOpen) showDisabled();\n    }\n  }\n\n  /** Render the \"chat unavailable\" state inside the panel. */\n  function showDisabled(): void {\n    setView(\"chat\");\n    if (!state.disabledShown) {\n      appendSystem(cfg.disabledText);\n      state.disabledShown = true;\n    }\n    panel.input.disabled = true;\n    panel.send.disabled = true;\n    panel.input.placeholder = cfg.disabledText;\n  }\n\n  /** Drop just the \"chat\" button from the speed-dial fan (other channels stay). */\n  function hideChatChannelButton(): void {\n    for (const btn of launcher.channelButtons) {\n      if (btn.key !== \"chat\") continue;\n      const item = btn.el.closest(\".nexor-chat__channel-item\");\n      if (item instanceof HTMLElement) item.style.display = \"none\";\n    }\n  }\n\n  // Show the typing dots the INSTANT a message is queued. We still hold the\n  // actual send for the quiet window, but the visitor gets immediate \"I heard\n  // you, I'm responding\" feedback — the dots persist across the debounce + the\n  // request, so there's never a dead 2.5s gap after they hit send.\n  function showTyping(): void {\n    if (send.typing) {\n      // Already up — keep it pinned below the latest message.\n      panel.body.appendChild(send.typing);\n      scrollToBottom();\n      return;\n    }\n    send.typing = appendNode(buildTypingIndicator());\n  }\n\n  function hideTyping(): void {\n    send.typing?.remove();\n    send.typing = null;\n  }\n\n  function scheduleFlush(): void {\n    showTyping();\n    if (send.timer) window.clearTimeout(send.timer);\n    send.timer = window.setTimeout(() => void flush(), cfg.debounceMs);\n  }\n\n  async function flush(): Promise<void> {\n    if (send.inFlight || send.pending.length === 0) return;\n    const batch = send.pending.splice(0, send.pending.length);\n    const message = batch.join(\"\\n\");\n    send.inFlight = true;\n    // If the lead is being pre-created from the capture form, let it settle so\n    // the backend matches that lead by identity instead of racing it into a\n    // duplicate. Best-effort: a failed/slow create never blocks the turn forever\n    // (createLead has its own timeout) and the turn would create the lead anyway.\n    if (state.leadCreating) {\n      try {\n        await state.leadCreating;\n      } catch {\n        /* ignore — the turn still creates/matches the lead */\n      }\n    }\n    // Whether THIS turn resets the episode. Captured before the await so a\n    // concurrent reset doesn't flip it mid-request.\n    const turnResetsEpisode = state.resetEpisode;\n\n    try {\n      const res = await client.chat(\n        {\n          workflow_id: cfg.workflowId,\n          session_id: sessionId,\n          message,\n          // Additive page/instance prompt injection (API appends to the\n          // workflow persona). Per route, the host passes different values.\n          system_prompt: cfg.systemPrompt,\n          client_prompt: cfg.clientPrompt,\n          // The opening the visitor actually saw, so the agent doesn't repeat\n          // or contradict a per-page opening override.\n          opening_shown: state.shownOpening ?? undefined,\n          // First turn after \"start over\" → reset the conversation episode on\n          // the same lead (clear prior run/thread/variables server-side).\n          reset_episode: turnResetsEpisode || undefined,\n          lead: Object.keys(state.pendingLead).length ? state.pendingLead : undefined,\n          // Resolve metadata per-turn so a function form picks up live SPA state\n          // (e.g. the current route) without re-mounting the widget.\n          metadata: typeof cfg.metadata === \"function\" ? cfg.metadata() : cfg.metadata,\n        },\n        // A chat turn is NOT idempotent (re-sending re-runs the LLM and\n        // re-inserts the message). Never retry; just give it a generous timeout.\n        { timeoutMs: cfg.requestTimeoutMs, maxRetries: 0 },\n      );\n      // Episode reset has landed; subsequent turns continue this fresh episode.\n      if (turnResetsEpisode) state.resetEpisode = false;\n      if (res.lead_id && !state.leadId) {\n        state.leadId = res.lead_id;\n        cfg.onLeadCaptured?.(state.leadId);\n      }\n      // Returning visitor recognised by the backend on a fresh local session →\n      // offer \"continue / start fresh\" once (the API may have surfaced prior\n      // context in this reply). With restored local history the resume banner\n      // already covered this, so freshLocalSession gates it.\n      if (\n        res.matched_existing &&\n        state.freshLocalSession &&\n        !state.episodeChoiceOffered &&\n        !turnResetsEpisode\n      ) {\n        state.episodeChoiceOffered = true;\n        renderResumeBanner(true);\n      }\n      const reply = (res.reply ?? \"\").trim();\n      hideTyping(); // clear the dots right before the reply lands\n      if (reply) {\n        appendBotReply(reply);\n      } else {\n        // No text came back (empty completion / tool-only turn). Never render a\n        // blank bubble — show the fallback and surface it to the host.\n        appendSystem(cfg.errorText);\n        cfg.onError?.(new Error(\"Nexor SDK: empty reply from server\"));\n      }\n    } catch (err) {\n      hideTyping();\n      // The workflow's web-chat channel was turned off server-side (403).\n      // Surface the unavailable notice rather than a generic error.\n      if (/web chat is not enabled/i.test((err as Error)?.message || \"\")) {\n        applyServerConfig(false, state.serverInitialMessage);\n      } else {\n        appendSystem(cfg.errorText);\n      }\n      cfg.onError?.(err as Error);\n    } finally {\n      // Safety net — never leave dangling dots. But a split reply is mid-stagger\n      // here (its first inter-bubble dots are already showing and its timer is\n      // armed); clearing them would make the first gap flicker dot-less. Skip the\n      // cleanup while the stagger owns the typing indicator.\n      if (!send.splitTimer) hideTyping();\n      send.inFlight = false;\n      panel.input.focus();\n      // Anything queued while the request was in flight goes out next.\n      if (send.pending.length) scheduleFlush();\n    }\n  }\n\n  // ─── Message rendering ──────────────────────────────────────────────────\n\n  function appendUser(text: string): void {\n    const ts = Date.now();\n    appendBubble(\"user\", text, ts);\n    state.history.push({ role: \"user\", text, ts });\n    saveHistory();\n    cfg.onMessage?.({ role: \"user\", text });\n  }\n\n  // `showTime` is false for the non-final bubbles of a split reply: those arrive\n  // in the same moment, so only the LAST bubble carries the timestamp. Persisted\n  // the same way (ts omitted) so a reload renders identically.\n  function appendBot(text: string, showTime = true): void {\n    const ts = showTime ? Date.now() : undefined;\n    appendBubble(\"bot\", text, ts);\n    state.history.push({ role: \"bot\", text, ts });\n    saveHistory();\n    if (!state.isOpen) bumpUnread();\n    cfg.onMessage?.({ role: \"bot\", text });\n  }\n\n  // Render a bot reply, WhatsApp-style: split it on blank lines into separate\n  // bubbles that arrive one after another with a short typing pause between.\n  function appendBotReply(text: string): void {\n    const parts = cfg.splitReplies ? splitReply(text) : [text];\n    if (parts.length <= 1) {\n      appendBot(text);\n      return;\n    }\n    const [first, ...rest] = parts;\n    appendBot(first ?? text, false); // first bubble lands immediately, no timestamp\n    let i = 0;\n    const sendNext = (): void => {\n      const part = rest[i];\n      if (part === undefined) return;\n      const isLast = i === rest.length - 1; // timestamp goes only on the last bubble\n      i++;\n      showTyping(); // dots between bubbles, like someone typing the next message\n      // A human-feeling \"typing\" pause before this bubble appears: fixed if the\n      // host set one, otherwise 3.0–5.0s scaled by how long THIS message is —\n      // longer text reads as more time spent typing — plus a little jitter so the\n      // cadence never feels mechanical.\n      const delay = cfg.splitDelayMs > 0 ? cfg.splitDelayMs : typingDelayFor(part);\n      send.splitTimer = window.setTimeout(() => {\n        send.splitTimer = 0;\n        hideTyping();\n        appendBot(part, isLast);\n        sendNext();\n      }, delay);\n    };\n    sendNext();\n  }\n\n  /** Split on blank lines (one or more) → one bubble per paragraph block. */\n  function splitReply(text: string): string[] {\n    const parts = text\n      .split(/\\n[ \\t]*\\n+/)\n      .map((s) => s.trim())\n      .filter(Boolean);\n    return parts.length ? parts : [text];\n  }\n\n  /** \"Typing\" pause (ms) before a split bubble: 3.0–5.0s, scaled by length. */\n  function typingDelayFor(text: string): number {\n    const MIN = 3000;\n    const MAX = 5000;\n    const FULL_AT = 180; // message length (chars) at which the pause hits MAX\n    const scaled = MIN + Math.min(text.length, FULL_AT) * ((MAX - MIN) / FULL_AT);\n    const jitter = Math.random() * 300 - 150; // ±150ms so it never feels mechanical\n    return Math.round(Math.max(MIN, Math.min(MAX, scaled + jitter)));\n  }\n\n  // ─── Transcript persistence (survives reloads up to SESSION_RETENTION_MS) ──\n\n  function saveHistory(): void {\n    try {\n      window.localStorage.setItem(\n        historyKey,\n        // Persist the known lead alongside the transcript so a returning visitor\n        // is recognised (and not re-asked for their details) after a reload.\n        JSON.stringify({\n          ts: Date.now(),\n          history: state.history,\n          lead: state.pendingLead,\n        }),\n      );\n      touchSession(); // keep the session alive in step with the transcript\n    } catch {\n      /* storage unavailable — in-memory history still works for this load. */\n    }\n  }\n\n  function loadPersisted(): {\n    history: Array<{ role: \"user\" | \"bot\"; text: string; ts?: number }>;\n    lead: ChatInitOptions[\"lead\"] | undefined;\n  } {\n    const empty = { history: [], lead: undefined };\n    try {\n      const raw = window.localStorage.getItem(historyKey);\n      if (!raw) return empty;\n      const o = JSON.parse(raw);\n      if (!o || !Array.isArray(o.history)) return empty;\n      if (Date.now() - (o.ts || 0) > SESSION_RETENTION_MS) {\n        window.localStorage.removeItem(historyKey);\n        return empty;\n      }\n      return {\n        history: o.history,\n        lead: o.lead && typeof o.lead === \"object\" ? o.lead : undefined,\n      };\n    } catch {\n      return empty;\n    }\n  }\n\n  function appendSystem(text: string): void {\n    appendBubble(\"system\", text);\n  }\n\n  function appendBubble(\n    role: MessageRole,\n    text: string,\n    ts?: number,\n  ): HTMLDivElement {\n    return appendNode(buildMessage(role, text, ts, cfg.locale));\n  }\n\n  // Keep relative timestamps (\"hace 3 minutos\") fresh while the panel is open.\n  const refreshTimer = window.setInterval(() => {\n    panel.body\n      .querySelectorAll<HTMLTimeElement>(\".nexor-chat__msg-time[data-ts]\")\n      .forEach((el) => {\n        const ts = Number(el.dataset.ts);\n        if (ts) el.textContent = formatRelativeTime(ts, cfg.locale);\n      });\n  }, 60_000);\n\n  function appendNode<T extends HTMLElement>(node: T): T {\n    panel.body.appendChild(node);\n    // Keep the typing indicator pinned to the bottom: if the visitor fires\n    // another message while we're awaiting a reply, the dots must stay BELOW\n    // it (the bot hasn't \"typed\" yet), not stranded between messages.\n    if (send.typing && send.typing !== node) panel.body.appendChild(send.typing);\n    scrollToBottom();\n    return node;\n  }\n\n  function scrollToBottom(): void {\n    panel.body.scrollTop = panel.body.scrollHeight;\n  }\n\n  // ─── Unread badge ───────────────────────────────────────────────────────\n\n  function bumpUnread(): void {\n    state.unread++;\n    launcher.badge.textContent = String(state.unread);\n    launcher.badge.style.display = \"flex\";\n  }\n  function clearUnread(): void {\n    state.unread = 0;\n    launcher.badge.style.display = \"none\";\n  }\n\n  // ─── Composer lock (used while capture form is visible) ─────────────────\n\n  function syncComposerLock(): void {\n    const lock = !state.captured;\n    panel.input.disabled = lock;\n    panel.send.disabled = lock;\n    panel.input.placeholder = lock\n      ? \"Complete the form above to start…\"\n      : cfg.inputPlaceholder;\n  }\n\n  // ─── Public handle ──────────────────────────────────────────────────────\n\n  return {\n    open,\n    close,\n    toggle,\n    // Programmatic send goes through the same debounce/coalesce path. Resolves\n    // immediately — the message is queued, not necessarily sent yet.\n    send: (text: string) => {\n      queueMessage(text);\n      return Promise.resolve();\n    },\n    destroy: () => {\n      if (send.timer) window.clearTimeout(send.timer);\n      if (send.splitTimer) window.clearTimeout(send.splitTimer);\n      if (greeting.timer) window.clearTimeout(greeting.timer);\n      window.clearInterval(refreshTimer);\n      if (onDocPointerDown) document.removeEventListener(\"pointerdown\", onDocPointerDown);\n      root.remove();\n    },\n    getSessionId: () => sessionId,\n  };\n}\n\n// ─── Module-scoped helpers ────────────────────────────────────────────────\n\nfunction ensureBrowser(): void {\n  if (typeof window === \"undefined\" || typeof document === \"undefined\") {\n    throw new Error(\"Nexor SDK: initChat() requires a browser environment.\");\n  }\n}\n\nfunction buildRoot(cfg: ResolvedCfg): HTMLDivElement {\n  const root = document.createElement(\"div\");\n  root.className = \"nexor-chat\";\n  root.setAttribute(\"data-position\", cfg.position);\n  root.setAttribute(\"data-open\", \"false\");\n  return root;\n}\n\nfunction readCaptureFields(panel: PanelRefs): Record<string, string> {\n  const out: Record<string, string> = {};\n  const inputs = panel.captureInputs;\n  if (inputs.first_name) out.first_name = inputs.first_name.value.trim();\n  if (inputs.last_name) out.last_name = inputs.last_name.value.trim();\n  if (inputs.email) out.email = inputs.email.value.trim();\n  // Phone holds national digits only; onCaptureSubmit prepends the country dial.\n  if (inputs.phone) out.phone = inputs.phone.value.replace(/\\D/g, \"\");\n  return out;\n}\n\n// Used by initChat's launcher → keeps the ref objects in scope for TS.\ntype _Refs = LauncherRefs & PanelRefs;\nvoid (null as unknown as _Refs);\n","import { NexorClient } from \"./client\";\nimport { initChat as initChatImpl, type ChatInitOptions, type ChatHandle } from \"./chat\";\nimport type { ClientOptions } from \"./types\";\n\nexport { NexorClient } from \"./client\";\nexport {\n  NexorError,\n  NexorAPIError,\n  NexorAuthError,\n  NexorValidationError,\n  NexorNetworkError,\n} from \"./errors\";\nexport * from \"./types\";\nexport type {\n  ChatInitOptions,\n  ChatHandle,\n  ChatLeadCapture,\n  ChatChannels,\n  ChatChannelKey,\n} from \"./chat\";\n\n/**\n * Singleton API. After `init({apiKey})`, call top-level helpers like\n * `createLead`, `getLead`, `initChat`, etc.\n *\n *   import nexor from \"@getnexorai/sdk\";\n *   nexor.init({ apiKey: \"nx_live_…\" });\n *   await nexor.createLead({ first_name: \"Ada\", email: \"ada@example.com\" });\n *\n * For multi-tenant / server-side use where a singleton doesn't fit, instantiate\n * the underlying client directly:\n *\n *   import { NexorClient } from \"@getnexorai/sdk\";\n *   const client = new NexorClient({ apiKey });\n */\nexport function createClient(opts: ClientOptions): NexorClient {\n  return new NexorClient(opts);\n}\n\nlet _client: NexorClient | null = null;\n\nfunction getClient(): NexorClient {\n  if (!_client) {\n    throw new Error(\n      \"Nexor SDK: call `nexor.init({ apiKey })` before using the API.\",\n    );\n  }\n  return _client;\n}\n\nfunction init(opts: ClientOptions): NexorClient {\n  _client = new NexorClient(opts);\n  return _client;\n}\n\nfunction isInitialized(): boolean {\n  return _client !== null;\n}\n\nfunction reset(): void {\n  _client = null;\n}\n\n/**\n * The default export — a ready-to-use, lazily-initialized singleton.\n *\n * Every method below proxies to the underlying NexorClient created by `init()`,\n * so the surface mirrors NexorClient one-for-one with no boilerplate.\n */\nexport const nexor = {\n  init,\n  isInitialized,\n  reset,\n  get client(): NexorClient {\n    return getClient();\n  },\n\n  // Leads\n  createLead: ((...args) => getClient().createLead(...args)) as NexorClient[\"createLead\"],\n  createLeadsBulk: ((...args) =>\n    getClient().createLeadsBulk(...args)) as NexorClient[\"createLeadsBulk\"],\n  updateLead: ((...args) => getClient().updateLead(...args)) as NexorClient[\"updateLead\"],\n  getLead: ((...args) => getClient().getLead(...args)) as NexorClient[\"getLead\"],\n  getLeadHistory: ((...args) =>\n    getClient().getLeadHistory(...args)) as NexorClient[\"getLeadHistory\"],\n  isLeadPaused: ((...args) => getClient().isLeadPaused(...args)) as NexorClient[\"isLeadPaused\"],\n  stopAutomation: ((...args) => getClient().stopAutomation(...args)) as NexorClient[\"stopAutomation\"],\n  resumeAutomation: ((...args) =>\n    getClient().resumeAutomation(...args)) as NexorClient[\"resumeAutomation\"],\n  syncLeadTags: ((...args) => getClient().syncLeadTags(...args)) as NexorClient[\"syncLeadTags\"],\n  listLeadMeetings: ((...args) =>\n    getClient().listLeadMeetings(...args)) as NexorClient[\"listLeadMeetings\"],\n\n  // Workflows / Campaigns / Templates\n  listWorkflows: ((...args) => getClient().listWorkflows(...args)) as NexorClient[\"listWorkflows\"],\n  listCampaigns: ((...args) => getClient().listCampaigns(...args)) as NexorClient[\"listCampaigns\"],\n  listTemplates: ((...args) => getClient().listTemplates(...args)) as NexorClient[\"listTemplates\"],\n\n  // Messages\n  sendMessage: ((...args) => getClient().sendMessage(...args)) as NexorClient[\"sendMessage\"],\n\n  // Meetings\n  createMeeting: ((...args) => getClient().createMeeting(...args)) as NexorClient[\"createMeeting\"],\n  createMeetingNotes: ((...args) =>\n    getClient().createMeetingNotes(...args)) as NexorClient[\"createMeetingNotes\"],\n\n  // Chat widget\n  initChat: (options: ChatInitOptions): ChatHandle =>\n    initChatImpl(getClient(), options),\n};\n\nexport default nexor;\n"]}