{"version":3,"sources":["../src/index.ts","../src/core/session-storage.ts","../src/types.ts","../src/core/correlation.ts","../src/version.ts","../src/core/logger.ts","../src/core/http.ts","../src/services/session/session.api.ts","../src/services/session/session.ts","../src/core/telemetry.ts","../src/core/response-shape.ts","../src/services/calls/call.ts","../src/core/diagnostics.ts","../src/core/events.ts","../src/ui/call-window.ts","../src/services/calls/calls.api.ts","../src/services/calls/calls.ts","../src/core/permissions.ts","../src/ui/dialer.ts","../src/ui/trigger-button.ts","../src/widget.ts","../src/element.ts"],"sourcesContent":["import { registerKasookooDialer } from \"./element\"\nregisterKasookooDialer()\n\nexport { KasookooDialerElement, registerKasookooDialer, type KasookooDialerConfig } from \"./element\"\n\nexport { KasookooClickToCall } from \"./widget\"\nexport { KasookooError } from \"./types\"\nexport { Call } from \"./services/calls/call\"\nexport { initKasookooTelemetry, type TelemetryConfig } from \"./core/telemetry\"\n\nexport type {\n    KasookooClickToCallConfig,\n    KasookooLoggingConfig,\n    KasookooLogLevel,\n    KasookooTelemetryConfig,\n    SessionInfo,\n    CallState,\n    RemoteParty,\n    CallIntent,\n    CallIntentEndpoint,\n    CallIntentEndpointConfig,\n} from \"./types\"\n","const memoryStore = new Map<string, string>()\n\nconst hasDocumentCookie = (): boolean => typeof document !== \"undefined\"\n\nexport function setSessionCookie(name: string, value: string): void {\n    if (!hasDocumentCookie()) {\n        memoryStore.set(name, value)\n        return\n    }\n    const secure = typeof location !== \"undefined\" && location.protocol === \"https:\" ? \"; Secure\" : \"\"\n    document.cookie = `${name}=${encodeURIComponent(value)}; Path=/; SameSite=Strict${secure}`\n}\n\nexport function getSessionCookie(name: string): string | null {\n    if (!hasDocumentCookie()) {\n        return memoryStore.get(name) ?? null\n    }\n    const match = document.cookie.split(\"; \").find((row) => row.startsWith(`${name}=`))\n    return match ? decodeURIComponent(match.slice(name.length + 1)) : null\n}\n\nexport function removeSessionCookie(name: string): void {\n    if (!hasDocumentCookie()) {\n        memoryStore.delete(name)\n        return\n    }\n    document.cookie = `${name}=; Path=/; SameSite=Strict; Expires=Thu, 01 Jan 1970 00:00:00 GMT`\n}\n","import type { Call } from \"./services/calls/call\"\n\n/** Every error the widget throws or emits. Branch on `code`, not `message`. */\nexport class KasookooError extends Error {\n    readonly code: string\n    readonly status?: number\n    readonly details?: unknown\n\n    /** @internal */\n    constructor(code: string, message: string, options?: { status?: number; details?: unknown }) {\n        super(message)\n        this.name = \"KasookooError\"\n        this.code = code\n        this.status = options?.status\n        this.details = options?.details\n    }\n}\n\nexport type KasookooLogLevel = \"debug\" | \"info\" | \"warn\" | \"error\"\n\nexport interface KasookooLoggingConfig {\n    /** Emit structured JSON logs to the browser console. Defaults to true. */\n    enabled?: boolean\n    /** Minimum log level. Defaults to info. */\n    level?: KasookooLogLevel\n    /** Logical service name in logs — defaults to kasookoo-click-to-call-widget. */\n    service?: string\n    /** Host label — defaults to window.location.hostname. */\n    host?: string\n}\n\n/**\n * OpenTelemetry trace/log export. There is nothing to switch on: it runs\n * automatically whenever the optional `@opentelemetry/*` peer dependencies\n * are installed, and does nothing at all when they aren't — no console\n * warning, no network calls. It cannot be turned off from config; to stop\n * it, don't install those packages.\n */\nexport interface KasookooTelemetryConfig {\n    /**\n     * Your own OTLP/HTTP traces endpoint(s), e.g.\n     * `https://your-collector.example.com/v1/traces`. Optional — exported to\n     * *in addition to* Kasookoo's own monitoring collector, which is always\n     * active whenever telemetry is, and cannot be disabled or\n     * replaced. Pass an array to export to more than one collector of your own.\n     */\n    endpoint?: string | string[]\n    /**\n     * OTLP/HTTP logs endpoint(s) for the collector(s) in `endpoint` above —\n     * ships the same structured logs that print to the console (see\n     * `logging`), unredacted. Defaults to each traces endpoint with a\n     * trailing `/v1/traces` swapped for `/v1/logs`; set this explicitly if\n     * yours doesn't follow that convention. When `endpoint` is an array,\n     * pass an array of the same length, matched up by position. Requires the\n     * optional `@opentelemetry/sdk-logs` and\n     * `@opentelemetry/exporter-logs-otlp-http` peer deps — silently falls\n     * back to traces-only if they're not installed.\n     */\n    logsEndpoint?: string | string[]\n    /** OTel `service.name` — defaults to `kasookoo-click-to-call-widget`. */\n    serviceName?: string\n    /** `deployment.environment` label — defaults to `production`. */\n    environment?: string\n}\n\n/**\n * A call intent your own backend created — via `kasookoo-server-sdk`'s\n * `callIntents.create()` — authorizing this widget to place one specific\n * outbound call. Mirrors what `kasookoo-sdk`'s `initSipCall()` takes on the\n * frontend, since both place a SIP call the same way, through the same API.\n */\nexport interface CallIntent {\n    intentId: string\n    clientSecret: string\n}\n\n/**\n * Config form of `intentEndpoint`, for routes that need more than a bare\n * URL — a bearer token, a custom header, cookies, or a different request\n * body shape. Everything about the outgoing request is configurable here,\n * so `intentEndpoint` can point directly at a third-party or already-built\n * API instead of requiring a translation route in front of it.\n */\nexport interface CallIntentEndpointConfig {\n    /** URL of the call-intent route. */\n    url: string\n    /**\n     * Extra headers to send with the request, e.g.\n     * `{ Authorization: \"Bearer ...\" }`. Can be a function (sync or async) so\n     * a token can be looked up or refreshed right before each call.\n     */\n    headers?: Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>)\n    /**\n     * Fetch `credentials` mode — set to `\"include\"` to send cookies (e.g. a\n     * session cookie your backend uses to authenticate the caller) with the\n     * request. Left unset, the fetch default (`\"same-origin\"`) applies.\n     */\n    credentials?: RequestCredentials\n    /**\n     * Overrides the POST body. Defaults to `{ phoneNumber }`. Use this when\n     * the route expects different field names or extra fixed fields, e.g.\n     * `(phoneNumber) => ({ phone_number: phoneNumber })`. Can be async.\n     */\n    body?: (phoneNumber: string) => Record<string, unknown> | Promise<Record<string, unknown>>\n}\n\n/**\n * Your call-intent route: either a bare URL — POSTed `{ phoneNumber }` with\n * no extra headers — or a `CallIntentEndpointConfig` for full control over\n * headers, cookies, and the request body shape.\n */\nexport type CallIntentEndpoint = string | CallIntentEndpointConfig\n\n/**\n * Passed once to `KasookooClickToCall.init()` at app startup. Every\n * `<kasookoo-dialer>` tag on the page shares the identity/session this\n * creates — they don't take their own publishable key or subject.\n */\nexport interface KasookooClickToCallConfig {\n    /** Publishable key from the Kasookoo dashboard. */\n    publishableKey: string\n    /**\n     * Backend base URL (no trailing slash).\n     * Defaults to https://sdk-test.kasookoo.ai\n     */\n    baseUrl?: string\n    /**\n     * A display name for the caller placing calls through this widget —\n     * shown to agents/CDR as the caller's identity. Any free-form string, not\n     * an email or a registered account — a page visitor's name is fine.\n     */\n    subject: string\n    /**\n     * The endpoint on **your own backend** the widget calls, right before\n     * every dial, to get a call intent for the number about to be called.\n     * Applies to every way a call gets placed — the dial pad, a static\n     * button, or `dial()` — with no per-tag wiring needed.\n     *\n     * Pass a bare URL string, or a `CallIntentEndpointConfig` object if the\n     * route needs a bearer token, another custom header, cookies, or a\n     * different request body shape — enough control to point this directly\n     * at an existing API rather than requiring a translation route in front\n     * of it.\n     *\n     * By default the widget sends `POST { phoneNumber }` and reads the\n     * response for an intent id and client secret; override `body` in the\n     * config form to change the request shape. Your endpoint creates those\n     * with\n     * `kasookoo-server-sdk`'s `callIntents.create()` — this is the one place\n     * your organization's secret key is used; the widget never sees it, only\n     * the short-lived intent your endpoint hands back.\n     *\n     * The response is parsed leniently: any JSON shape works as long as the\n     * two values appear somewhere in it under a recognizable key\n     * (`intentId`/`intent_id`/`id`, `clientSecret`/`client_secret`/`secret`,\n     * case- and nesting-insensitive) — so wrapping them in `{ data: ... }`,\n     * an envelope with other fields, snake_case, etc. all work without\n     * needing to reshape your response to match.\n     */\n    intentEndpoint: CallIntentEndpoint\n    /**\n     * How long an outbound call rings before the widget gives up and cancels\n     * it automatically. Defaults to `60000` (60 seconds). Pass `false` to\n     * disable it — the call then rings until the phone number answers or the\n     * user cancels manually.\n     */\n    callRingTimeoutMs?: number | false\n    /** Structured JSON console logging. */\n    logging?: KasookooLoggingConfig\n    /** Optional OpenTelemetry trace/log export. Off by default. */\n    telemetry?: KasookooTelemetryConfig\n}\n\n/** `\"connecting\"` → `\"connected\"` → `\"ended\"`. Every call placed by this widget is outbound, so there is no `\"incoming\"` state. */\nexport type CallState = \"connecting\" | \"connected\" | \"ended\"\n\nexport interface SessionInfo {\n    sessionId: string\n    /** The `subject` display name passed to `init()`. */\n    subject: string\n    organizationId: string\n    expiresAt: number\n}\n\n/**\n * @internal — POST /api/v1/sdk/auth/client-sessions/full. Validity is a\n * plain HTTP-status concern, handled by `request()`. The `/full` variant is\n * used (over the bare `/client-sessions` route) specifically because it\n * returns `session_id`, `organization_id`, and `allowed_scopes` directly, so\n * no separate introspect round-trip is needed to resolve them.\n */\nexport interface ClientSessionResponse {\n    token: string\n    token_type: string\n    session_id: string\n    organization_id: string\n    expires_in: number\n    allowed_scopes: string[]\n}\n\n/** @internal */\nexport interface PersistedSession {\n    token: string\n    sessionId: string\n    subject: string\n    organizationId: string\n    expiresAt: number\n    allowedScopes: string[]\n}\n\n/** Parameters for placing an outbound phone call. */\nexport interface DialParams {\n    /** Destination phone number in E.164 format, e.g. `\"+447783021617\"`. Required. */\n    phoneNumber: string\n    /** Room/call identifier. Auto-generated when omitted — pass your own only if you need to correlate it elsewhere. */\n    roomName?: string\n    /** Display name for the caller on this call. Defaults to the `subject` given at `init()`. */\n    participantName?: string\n    /** Text shown on the call window instead of the phone number. Display only — the number is still what's dialed. */\n    label?: string\n}\n\nexport interface RemoteParty {\n    name: string\n    /** Display label shown on the call window in place of `name` (the phone number), when set. */\n    label?: string\n    type?: string\n    id?: string\n}\n\n/** @internal — `DialParams` plus the call intent resolved for this dial. */\nexport interface SipDialParams extends DialParams {\n    intentId: string\n    clientSecret: string\n}\n\n/** @internal */\nexport interface SipCallData {\n    access_token: string\n    room_name: string\n    room_session_id: string\n    dialed_number: string\n    caller_id: string\n    participant_identity: string\n    status: string\n    ws_url: string\n}\n\n/** @internal */\nexport interface SipCallResponse {\n    success: boolean\n    message: string\n    data: SipCallData\n    error: string | null\n}\n\nexport type KasookooWidgetEvents = {\n    \"session:created\": SessionInfo\n    \"session:refreshed\": SessionInfo\n    \"session:expired\": { reason: string }\n    /** Fired whenever a new call is placed (right after `dial()`/a dialer click). Use `call.on(\"state\", ...)` for lifecycle. */\n    \"call:started\": Call\n    error: KasookooError\n}\n","\nexport const FEATURE = {\n    SIP_CALL: \"sip_call\",\n} as const\n\nexport type FeatureType = (typeof FEATURE)[keyof typeof FEATURE]\n\nexport const CORRELATION_HEADERS = {\n    REQUEST_ID: \"X-Request-ID\",\n    CALL_TRACE_ID: \"X-Call-Trace-ID\",\n    USER_ID: \"X-User-ID\",\n    FEATURE_TYPE: \"X-Feature-Type\",\n} as const\n\nexport interface CorrelationContext {\n    callTraceId?: string\n    userId?: string\n    featureType?: FeatureType\n    requestId?: string\n}\n\nexport function newRequestId(): string {\n    return crypto.randomUUID().replace(/-/g, \"\")\n}\n\nexport function newCallTraceId(): string {\n    return crypto.randomUUID().replace(/-/g, \"\")\n}\n\nexport function buildCorrelationHeaders(correlation?: CorrelationContext): Record<string, string> {\n    const requestId = correlation?.requestId?.trim() || newRequestId()\n    const headers: Record<string, string> = {\n        [CORRELATION_HEADERS.REQUEST_ID]: requestId,\n    }\n    const callTraceId = correlation?.callTraceId?.trim()\n    if (callTraceId) {\n        headers[CORRELATION_HEADERS.CALL_TRACE_ID] = callTraceId\n    }\n    const userId = correlation?.userId?.trim()\n    if (userId) {\n        headers[CORRELATION_HEADERS.USER_ID] = userId\n    }\n    const featureType = correlation?.featureType?.trim()\n    if (featureType) {\n        headers[CORRELATION_HEADERS.FEATURE_TYPE] = featureType\n    }\n    return headers\n}\n","export const WIDGET_VERSION = \"0.1.0\"\n","import { WIDGET_VERSION } from \"../version\"\n\nexport type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\"\n\nconst LEVEL_RANK: Record<LogLevel, number> = {\n    debug: 10,\n    info: 20,\n    warn: 30,\n    error: 40,\n}\n\nexport interface LoggerConfig {\n    /** Emit structured JSON to the console. Defaults to true. */\n    enabled?: boolean\n    /** Minimum level to emit. Defaults to info. */\n    level?: LogLevel\n    /** Logical service name — defaults to kasookoo-click-to-call-widget. */\n    service?: string\n    /** Host identifier — defaults to window.location.hostname in browsers. */\n    host?: string\n}\n\ninterface ResolvedLoggerConfig {\n    enabled: boolean\n    level: LogLevel\n    service: string\n    version: string\n    host: string\n}\n\nconst DEFAULT_HOST =\n    typeof window !== \"undefined\" && window.location?.hostname ? window.location.hostname : \"browser\"\n\nlet config: ResolvedLoggerConfig = {\n    enabled: true,\n    level: \"info\",\n    service: \"kasookoo-click-to-call-widget\",\n    version: WIDGET_VERSION,\n    host: DEFAULT_HOST,\n}\n\nconst SENSITIVE_KEYS = [\"password\", \"token\", \"access_token\", \"refresh_token\", \"authorization\", \"api_key\", \"secret\"]\n\n/**\n * Sink registered by `core/telemetry.ts` once OTel log export is initialized.\n * Receives every log entry regardless of console `enabled`/`level` — kept\n * decoupled so `logger.ts` has no dependency on the optional OTel packages.\n */\ntype OtelLogSink = (level: LogLevel, entry: Record<string, unknown>) => void\nlet otelSink: OtelLogSink | null = null\n\n/** @internal Registered by `initKasookooTelemetry` when log export is enabled. */\nexport function setOtelLogSink(sink: OtelLogSink | null): void {\n    otelSink = sink\n}\n\n/** Configure global log metadata (call once from `KasookooClickToCall.init`). */\nexport function configureLogger(options: LoggerConfig = {}): void {\n    config = {\n        enabled: options.enabled ?? config.enabled,\n        level: options.level ?? config.level,\n        service: options.service?.trim() || config.service,\n        version: config.version,\n        host: options.host?.trim() || config.host,\n    }\n}\n\nexport interface StructuredLogger {\n    debug(message: string | Record<string, unknown>): void\n    info(message: string | Record<string, unknown>): void\n    warn(message: string | Record<string, unknown>): void\n    error(message: string | Record<string, unknown>): void\n}\n\nexport function getLogger(name: string): StructuredLogger {\n    return {\n        debug: (message) => emit(\"debug\", name, message),\n        info: (message) => emit(\"info\", name, message),\n        warn: (message) => emit(\"warn\", name, message),\n        error: (message) => emit(\"error\", name, message),\n    }\n}\n\nfunction emit(level: LogLevel, logger: string, message: string | Record<string, unknown>): void {\n    const consoleAllowed = config.enabled && LEVEL_RANK[level] >= LEVEL_RANK[config.level]\n\n    // Nothing to do if this line goes nowhere — no console (gated by `config`)\n    // and no OTel sink registered (`telemetry.enabled` was never turned on).\n    if (!consoleAllowed && !otelSink) return\n\n    const entry = buildLogEntry(level, logger, message)\n\n    // OTel export is intentionally independent of the console settings above:\n    // it fires for every level, regardless of `config.enabled`/`config.level`.\n    // A sink only exists when `telemetry.enabled` successfully initialized\n    // log export — that's its own on/off switch.\n    otelSink?.(level, entry)\n\n    if (!consoleAllowed) return\n\n    const line = JSON.stringify(entry)\n\n    switch (level) {\n        case \"debug\":\n            console.debug(line)\n            break\n        case \"info\":\n            console.info(line)\n            break\n        case \"warn\":\n            console.warn(line)\n            break\n        case \"error\":\n            console.error(line)\n            break\n    }\n}\n\nfunction buildLogEntry(level: LogLevel, logger: string, message: string | Record<string, unknown>): Record<string, unknown> {\n    const entry: Record<string, unknown> = {\n        level,\n        ts: Date.now() / 1000,\n        logger,\n        service: config.service,\n        host: config.host,\n        version: config.version,\n    }\n\n    if (typeof message === \"string\") {\n        entry.msg = message\n    } else {\n        const payload = sanitizeLogData(message)\n        const msg =\n            (typeof payload.msg === \"string\" && payload.msg) ||\n            (typeof payload.event === \"string\" && payload.event) ||\n            \"log_entry\"\n        const rest = { ...payload }\n        delete rest.msg\n        entry.msg = msg\n        Object.assign(entry, rest)\n    }\n\n    if (entry.request_id && !entry.trace_id) {\n        entry.trace_id = entry.request_id\n    }\n\n    return entry\n}\n\nfunction sanitizeLogData(data: Record<string, unknown>): Record<string, unknown> {\n    const out: Record<string, unknown> = {}\n    for (const [key, value] of Object.entries(data)) {\n        if (isSensitiveKey(key)) {\n            out[key] = \"***REDACTED***\"\n            continue\n        }\n        if (value && typeof value === \"object\" && !Array.isArray(value)) {\n            out[key] = sanitizeLogData(value as Record<string, unknown>)\n        } else {\n            out[key] = value\n        }\n    }\n    return out\n}\n\nfunction isSensitiveKey(key: string): boolean {\n    const lower = key.toLowerCase()\n    return SENSITIVE_KEYS.some((part) => lower.includes(part))\n}\n\n/** Parse path (+ query) from a request URL for access logs. */\nexport function pathFromUrl(url: string): string {\n    try {\n        const parsed = new URL(url, typeof window !== \"undefined\" ? window.location.origin : undefined)\n        return `${parsed.pathname}${parsed.search}`\n    } catch {\n        return url\n    }\n}\n","import { KasookooError } from \"../types\"\nimport { buildCorrelationHeaders, type CorrelationContext } from \"./correlation\"\nimport { getLogger, pathFromUrl } from \"./logger\"\n\nconst httpLogger = getLogger(\"kasookoo-click-to-call.http\")\n\nexport type CorrelationRequestObserver = (info: {\n    url: string\n    method: string\n    requestId: string\n    callTraceId?: string\n    userId?: string\n    status?: number\n    ok?: boolean\n}) => void\n\nlet requestObserver: CorrelationRequestObserver | null = null\n\nexport function setCorrelationRequestObserver(observer: CorrelationRequestObserver | null): void {\n    requestObserver = observer\n}\n\nfunction extractDetail(data: unknown): string {\n    if (typeof data !== \"object\" || data === null || !(\"detail\" in data)) return \"\"\n    const detail = (data as { detail: unknown }).detail\n\n    if (typeof detail === \"string\") return detail\n    if (Array.isArray(detail)) {\n        return detail\n            .map((item) => {\n                if (typeof item === \"object\" && item !== null && \"msg\" in item) {\n                    const loc = Array.isArray((item as { loc?: unknown }).loc)\n                        ? (item as { loc: unknown[] }).loc.join(\".\") + \": \"\n                        : \"\"\n                    return loc + String((item as { msg: unknown }).msg)\n                }\n                return JSON.stringify(item)\n            })\n            .join(\"; \")\n    }\n    if (detail != null) return JSON.stringify(detail)\n    return \"\"\n}\n\nfunction extractError(data: unknown): { code?: string; message: string } {\n    if (typeof data !== \"object\" || data === null) return { message: \"\" }\n\n    const error = (data as { error?: unknown }).error\n    if (typeof error === \"object\" && error !== null && \"message\" in error) {\n        const { code, message, details } = error as { code?: unknown; message?: unknown; details?: unknown }\n\n        const fields = Array.isArray(details)\n            ? details\n                  .map((item) =>\n                      typeof item === \"object\" && item !== null && \"field\" in item\n                          ? `${String((item as { field: unknown }).field)}: ${String(\n                                (item as { issue?: unknown }).issue ?? \"invalid\"\n                            )}`\n                          : \"\"\n                  )\n                  .filter(Boolean)\n            : []\n\n        return {\n            code: typeof code === \"string\" ? code : undefined,\n            message: String(message) + (fields.length ? ` (${fields.join(\"; \")})` : \"\"),\n        }\n    }\n\n    return { message: extractDetail(data) }\n}\n\nexport interface HttpOptions {\n    method?: \"GET\" | \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\"\n    body?: unknown\n    token?: string\n    correlation?: CorrelationContext\n    /** Extra headers — merged in after the token/correlation headers, so these win on conflict. */\n    headers?: Record<string, string>\n    /** Fetch `credentials` mode, e.g. `\"include\"` to send cookies cross-origin. */\n    credentials?: RequestCredentials\n}\n\ninterface HttpResultMeta {\n    requestId: string\n    callTraceId?: string\n}\n\nfunction correlationMeta(headers: Record<string, string>): HttpResultMeta {\n    return {\n        requestId: headers[\"X-Request-ID\"] ?? \"\",\n        callTraceId: headers[\"X-Call-Trace-ID\"],\n    }\n}\n\nfunction correlationLogFields(meta: HttpResultMeta, correlation?: CorrelationContext): Record<string, unknown> {\n    const fields: Record<string, unknown> = {\n        request_id: meta.requestId,\n        trace_id: meta.requestId,\n    }\n    if (meta.callTraceId) fields.call_trace_id = meta.callTraceId\n    if (correlation?.userId) fields.user_id = correlation.userId\n    if (correlation?.featureType) fields.feature_type = correlation.featureType\n    return fields\n}\n\nfunction logHttpAccess(\n    level: \"info\" | \"warn\" | \"error\",\n    params: {\n        method: string\n        path: string\n        statusCode?: number\n        ok?: boolean\n        executionTimeSeconds: number\n        meta: HttpResultMeta\n        correlation?: CorrelationContext\n        errorCode?: string\n    }\n): void {\n    const statusText = params.statusCode !== undefined ? String(params.statusCode) : \"network_error\"\n    const payload: Record<string, unknown> = {\n        msg: `${params.method} ${params.path} ${statusText}`,\n        event: \"http_access\",\n        method: params.method,\n        path: params.path,\n        execution_time_seconds: Math.round(params.executionTimeSeconds * 10_000) / 10_000,\n        ...correlationLogFields(params.meta, params.correlation),\n    }\n    if (params.statusCode !== undefined) payload.status_code = params.statusCode\n    if (params.ok !== undefined) payload.ok = params.ok\n    if (params.errorCode) payload.error_code = params.errorCode\n\n    httpLogger[level](payload)\n}\n\nexport async function request<T>(url: string, options: HttpOptions = {}): Promise<T> {\n    const method = options.method ?? \"GET\"\n    const path = pathFromUrl(url)\n    const correlationHeaders = buildCorrelationHeaders(options.correlation)\n    const meta = correlationMeta(correlationHeaders)\n    const started = performance.now()\n\n    requestObserver?.({\n        url,\n        method,\n        requestId: meta.requestId,\n        callTraceId: meta.callTraceId,\n        userId: options.correlation?.userId,\n    })\n\n    let response: Response\n    try {\n        response = await fetch(url, {\n            method,\n            headers: {\n                Accept: \"application/json\",\n                ...(options.body !== undefined ? { \"Content-Type\": \"application/json\" } : {}),\n                ...(options.token ? { Authorization: `Bearer ${options.token}` } : {}),\n                ...correlationHeaders,\n                ...options.headers,\n            },\n            body: options.body !== undefined ? JSON.stringify(options.body) : undefined,\n            ...(options.credentials ? { credentials: options.credentials } : {}),\n        })\n    } catch (err) {\n        const elapsed = (performance.now() - started) / 1000\n        logHttpAccess(\"error\", {\n            method,\n            path,\n            ok: false,\n            executionTimeSeconds: elapsed,\n            meta,\n            correlation: options.correlation,\n            errorCode: \"network_error\",\n        })\n        requestObserver?.({\n            url,\n            method,\n            requestId: meta.requestId,\n            callTraceId: meta.callTraceId,\n            userId: options.correlation?.userId,\n            ok: false,\n        })\n        throw new KasookooError(\"network_error\", \"Network request failed. Please check your connection and try again.\", {\n            details: err,\n        })\n    }\n\n    const elapsed = (performance.now() - started) / 1000\n    logHttpAccess(response.ok ? \"info\" : response.status >= 500 ? \"error\" : \"warn\", {\n        method,\n        path,\n        statusCode: response.status,\n        ok: response.ok,\n        executionTimeSeconds: elapsed,\n        meta,\n        correlation: options.correlation,\n    })\n\n    requestObserver?.({\n        url,\n        method,\n        requestId: meta.requestId,\n        callTraceId: meta.callTraceId,\n        userId: options.correlation?.userId,\n        status: response.status,\n        ok: response.ok,\n    })\n\n    const text = await response.text()\n    let data: unknown = undefined\n    if (text) {\n        try {\n            data = JSON.parse(text)\n        } catch {\n            data = text\n        }\n    }\n\n    if (!response.ok) {\n        const { code, message } = extractError(data)\n        throw new KasookooError(code ?? \"api_error\", message || `Request failed with status ${response.status}`, {\n            status: response.status,\n            details: data,\n        })\n    }\n\n    return data as T\n}\n","import { request } from \"../../core/http\"\nimport type { ClientSessionResponse } from \"../../types\"\n\nexport interface SessionApiContext {\n    baseUrl: string\n    token: string\n}\n\n/**\n * Creates a client session — the `/full` variant returns `session_id`,\n * `organization_id`, and `allowed_scopes` directly, so no separate\n * introspect round-trip is needed to resolve them. An invalid publishable\n * key surfaces as a non-2xx response — `request()` already throws the\n * backend's own error code/message for that, so there's nothing further to\n * check here.\n */\nexport function createClientSessionRequest(\n    baseUrl: string,\n    publishableKey: string,\n    subject: string\n): Promise<ClientSessionResponse> {\n    return request<ClientSessionResponse>(`${baseUrl}/api/v1/sdk/auth/client-sessions/full`, {\n        method: \"POST\",\n        body: {\n            publishable_key: publishableKey,\n            subject,\n        },\n    })\n}\n\n/** Revokes a client session. */\nexport function revokeClientSessionRequest(ctx: SessionApiContext, sessionId: string): Promise<void> {\n    return request(`${ctx.baseUrl}/api/v1/sdk/auth/sessions/${encodeURIComponent(sessionId)}`, {\n        method: \"DELETE\",\n        token: ctx.token,\n    })\n}\n","import { getSessionCookie, removeSessionCookie, setSessionCookie } from \"../../core/session-storage\"\nimport { KasookooError, type SessionInfo, type PersistedSession } from \"../../types\"\nimport { createClientSessionRequest, revokeClientSessionRequest } from \"./session.api\"\n\nconst COOKIE_NAME = \"kasookoo_ctc_session\"\nconst REFRESH_BUFFER_SECONDS = 60\n\nexport interface SessionManagerOptions {\n    baseUrl: string\n    publishableKey: string\n    subject: string\n    onCreated: (info: SessionInfo) => void\n    onRefreshed: (info: SessionInfo) => void\n    onExpired: (reason: string) => void\n    onError: (error: KasookooError) => void\n}\n\n/**\n * Owns the client-session lifecycle — identical scheduling pattern to\n * kasookoo-sdk's `SessionManager`:\n *  - creates the session with the Kasookoo backend\n *  - persists the token in a session cookie (survives reloads, dies with the browser tab)\n *  - schedules an automatic re-fetch `REFRESH_BUFFER_SECONDS` before expiry,\n *    re-armed from each response's `expires_in`\n *\n * Nothing runs at construction — the session is established only via `start()`.\n */\nexport class SessionManager {\n    private readonly opts: SessionManagerOptions\n    private session: PersistedSession | null = null\n    private refreshTimer: ReturnType<typeof setTimeout> | null = null\n    private destroyed = false\n\n    constructor(opts: SessionManagerOptions) {\n        this.opts = opts\n    }\n\n    /**\n     * Establishes the session: reuses a still-valid token from the session\n     * cookie (page reload), otherwise calls the API. Always schedules a refresh.\n     */\n    async start(): Promise<SessionInfo> {\n        const restored = this.restoreFromCookie()\n        if (restored) {\n            this.session = restored\n            this.scheduleRefresh(restored.expiresAt - Date.now())\n        } else {\n            await this.createSession()\n        }\n        const info = this.toInfo(this.session!)\n        this.opts.onCreated(info)\n        return info\n    }\n\n    /** Current bearer token — used by the calls module. */\n    getToken(): string {\n        if (!this.session || this.session.expiresAt <= Date.now()) {\n            throw new KasookooError(\n                \"no_active_session\",\n                \"No active client session. Call KasookooClickToCall.init() and wait for it to resolve.\"\n            )\n        }\n        return this.session.token\n    }\n\n    getInfo(): SessionInfo | null {\n        return this.session ? this.toInfo(this.session) : null\n    }\n\n    /** @internal — capability check used by `assertSipConfigured()`; not part of the public `SessionInfo` shape. */\n    getAllowedScopes(): string[] {\n        return this.session ? [...this.session.allowedScopes] : []\n    }\n\n    /**\n     * Stops the refresh scheduler, revokes the session with the backend\n     * (fire-and-forget — teardown must not block on a network round-trip),\n     * and clears the stored token.\n     */\n    close(): void {\n        this.destroyed = true\n        if (this.refreshTimer) clearTimeout(this.refreshTimer)\n        this.refreshTimer = null\n        if (this.session) {\n            const { token, sessionId } = this.session\n            revokeClientSessionRequest({ baseUrl: this.opts.baseUrl, token }, sessionId).catch(() => {\n                // Best effort — the session will simply expire naturally server-side.\n            })\n        }\n        this.session = null\n        removeSessionCookie(COOKIE_NAME)\n    }\n\n    // ------------------------------------------------------------------ internals\n\n    private restoreFromCookie(): PersistedSession | null {\n        const raw = getSessionCookie(COOKIE_NAME)\n        if (!raw) return null\n        try {\n            const parsed = JSON.parse(raw) as PersistedSession\n            const usable =\n                parsed.token &&\n                parsed.organizationId &&\n                parsed.subject === this.opts.subject &&\n                parsed.expiresAt - Date.now() > REFRESH_BUFFER_SECONDS * 1000\n            return usable ? parsed : null\n        } catch {\n            removeSessionCookie(COOKIE_NAME)\n            return null\n        }\n    }\n\n    private async createSession(): Promise<void> {\n        const res = await createClientSessionRequest(this.opts.baseUrl, this.opts.publishableKey, this.opts.subject)\n\n        this.session = {\n            token: res.token,\n            sessionId: res.session_id,\n            subject: this.opts.subject,\n            organizationId: res.organization_id,\n            expiresAt: Date.now() + res.expires_in * 1000,\n            allowedScopes: res.allowed_scopes,\n        }\n        setSessionCookie(COOKIE_NAME, JSON.stringify(this.session))\n        this.scheduleRefresh(res.expires_in * 1000)\n    }\n\n    /** Schedules the refresh to fire REFRESH_BUFFER_SECONDS before the token expires. */\n    private scheduleRefresh(lifetimeMs: number): void {\n        if (this.destroyed) return\n        if (this.refreshTimer) clearTimeout(this.refreshTimer)\n\n        const delay = Math.max(0, lifetimeMs - REFRESH_BUFFER_SECONDS * 1000)\n        this.refreshTimer = setTimeout(() => void this.refresh(), delay)\n    }\n\n    private async refresh(): Promise<void> {\n        if (this.destroyed) return\n        try {\n            await this.createSession()\n            this.opts.onRefreshed(this.toInfo(this.session!))\n        } catch (err) {\n            const error =\n                err instanceof KasookooError\n                    ? err\n                    : new KasookooError(\"refresh_failed\", \"Failed to refresh client session\", { details: err })\n            this.opts.onError(error)\n            this.session = null\n            removeSessionCookie(COOKIE_NAME)\n            this.opts.onExpired(`Session refresh failed: ${error.message}`)\n        }\n    }\n\n    private toInfo(session: PersistedSession): SessionInfo {\n        return {\n            sessionId: session.sessionId,\n            subject: session.subject,\n            organizationId: session.organizationId,\n            expiresAt: session.expiresAt,\n        }\n    }\n}\n","/**\n * Optional OpenTelemetry integration for the widget.\n *\n * Activates automatically if the optional `@opentelemetry/*` peer deps are\n * installed — no config needed, and no way to turn it off from config.\n * Without them installed, it does nothing and the widget keeps working exactly as before, with\n * console logging only.\n */\n\nimport { CORRELATION_HEADERS } from \"./correlation\"\nimport { setOtelLogSink, type LogLevel } from \"./logger\"\n\n// Type-only — erased at compile time, so these don't pull the optional\n// peer packages into the runtime bundle. Only used to type the resource-\n// override wrappers below.\nimport type { Context } from \"@opentelemetry/api\"\nimport type { LogRecord, LogRecordProcessor } from \"@opentelemetry/sdk-logs\"\nimport type { Resource } from \"@opentelemetry/resources\"\nimport type { ReadableSpan, Span, SpanProcessor } from \"@opentelemetry/sdk-trace-base\"\n\nexport interface TelemetryConfig {\n    /**\n     * Your own OTLP/HTTP traces endpoint(s), e.g.\n     * `https://monitoring.example.com/v1/traces`. Optional — exported to *in\n     * addition to* Kasookoo's own monitoring collector, which is always\n     * active whenever telemetry runs and cannot be disabled or replaced.\n     * Pass an array to export to more than one collector of your own.\n     */\n    endpoint?: string | string[]\n    /**\n     * OTLP/HTTP logs endpoint(s) for the collector(s) in `endpoint` above.\n     * Defaults to each traces endpoint with a trailing `/v1/traces` swapped\n     * for `/v1/logs` — set this explicitly if yours doesn't follow that\n     * convention. When `endpoint` is an array, pass an array of the same\n     * length, matched up by position.\n     */\n    logsEndpoint?: string | string[]\n    /** OTel service.name — defaults to kasookoo-click-to-call-widget */\n    serviceName?: string\n    /** deployment.environment — defaults to production */\n    environment?: string\n}\n\nconst DEFAULT_SERVICE_NAME = \"kasookoo-click-to-call-widget\"\nconst OTEL_SEVERITY: Record<LogLevel, number> = { debug: 5, info: 9, warn: 13, error: 17 }\n\n/**\n * Kasookoo's own monitoring collector. Always exported to once telemetry is\n * running, regardless of `TelemetryConfig.endpoint` — this is how we monitor\n * SDK health and diagnose integration issues, so it isn't optional and\n * can't be disabled or overridden by host config.\n */\nconst MANDATORY_TRACES_ENDPOINT = \"https://monitoring-test.kasookoo.ai/v1/traces\"\n\nlet initialized = false\n\nfunction normalizeEndpoints(value: string | string[] | undefined): string[] {\n    const list = Array.isArray(value) ? value : value !== undefined ? [value] : []\n    return [...new Set(list.map((entry) => entry.trim()).filter(Boolean))]\n}\n\nfunction deriveLogsEndpoint(tracesEndpoint: string): string | undefined {\n    if (tracesEndpoint.endsWith(\"/v1/traces\")) {\n        return tracesEndpoint.slice(0, -\"/v1/traces\".length) + \"/v1/logs\"\n    }\n    return undefined\n}\n\n/**\n * A span covering an entire multi-request lifecycle (e.g. a phone call from\n * dial to hangup). Returned by `startCallSpan` — never constructed directly.\n */\nexport interface CallSpan {\n    /**\n     * Runs `fn` with this span active. A `fetch()` call made *synchronously*\n     * inside `fn` — before its first `await` — is picked up by\n     * `FetchInstrumentation` as a child of this span rather than starting its\n     * own independent trace. An `await` before the `fetch()` call breaks that\n     * (the browser's default context manager doesn't propagate active\n     * context across async boundaries without zone.js) — keep the actual\n     * `request()`/`fetch()` call as the first awaited thing inside `fn`.\n     */\n    runInContext<T>(fn: () => T): T\n    /** Attaches an extra attribute to the span (e.g. a final status). */\n    setAttribute(key: string, value: string | number | boolean): void\n    /** Adds a timestamped event to the span (e.g. `mic_permission`), shown on the trace timeline. */\n    addEvent(name: string, attributes?: Record<string, string | number | boolean>): void\n    /** Marks the span as failed and records the error on it. */\n    recordError(err: unknown): void\n    /** Ends the span, finalizing its duration in the exported trace. */\n    end(): void\n}\n\nconst noopCallSpan: CallSpan = {\n    runInContext: (fn) => fn(),\n    setAttribute: () => {},\n    addEvent: () => {},\n    recordError: () => {},\n    end: () => {},\n}\n\n/**\n * Starts a span meant to stay open across an entire action's lifecycle,\n * rather than the one-fetch-one-span default. Every `fetch()` run via the\n * returned handle's `runInContext` nests under it as a child span instead of\n * becoming its own independent trace.\n *\n * Safe to call unconditionally: no-ops (returns a handle whose methods do\n * nothing) if `@opentelemetry/api` isn't installed, and produces genuinely\n * inert spans — not errors — if telemetry never started, since\n * `@opentelemetry/api` itself defaults to a no-op tracer with no SDK\n * registered.\n */\nexport async function startCallSpan(\n    name: string,\n    attributes: Record<string, string | undefined> = {}\n): Promise<CallSpan> {\n    try {\n        const { trace, context, SpanStatusCode } = await import(\"@opentelemetry/api\")\n        const tracer = trace.getTracer(DEFAULT_SERVICE_NAME)\n        const span = tracer.startSpan(name)\n        for (const [key, value] of Object.entries(attributes)) {\n            if (value !== undefined) span.setAttribute(key, value)\n        }\n        const activeContext = trace.setSpan(context.active(), span)\n\n        return {\n            runInContext: (fn) => context.with(activeContext, fn),\n            setAttribute: (key, value) => span.setAttribute(key, value),\n            addEvent: (eventName, eventAttributes) => span.addEvent(eventName, eventAttributes),\n            recordError: (err) => {\n                span.recordException(err instanceof Error ? err : String(err))\n                span.setStatus({ code: SpanStatusCode.ERROR })\n                // The machine-readable code is what you filter on in Tempo.\n                const known = err as { code?: unknown; status?: unknown }\n                if (typeof known?.code === \"string\") span.setAttribute(\"error.code\", known.code)\n                if (typeof known?.status === \"number\") span.setAttribute(\"error.status\", known.status)\n            },\n            end: () => span.end(),\n        }\n    } catch {\n        return noopCallSpan\n    }\n}\n\n/**\n * Wraps a span processor so every span it sees is re-stamped with `resource`\n * before being forwarded — used to give the mandatory Kasookoo processor a\n * fixed identity, independent of `serviceName`/`environment` in host config.\n * Resource lives on the span instance, not the processor, so this clones\n * each span rather than mutating it — mutating in place would leak the\n * override into every *other* processor registered on the same provider,\n * since they all see the same span object.\n */\nfunction withFixedResource(processor: SpanProcessor, resource: Resource): SpanProcessor {\n    return {\n        onStart: (span: Span, parentContext: Context) => processor.onStart(span, parentContext),\n        onEnd: (span: ReadableSpan) =>\n            processor.onEnd(Object.assign(Object.create(Object.getPrototypeOf(span)), span, { resource })),\n        forceFlush: () => processor.forceFlush(),\n        shutdown: () => processor.shutdown(),\n    }\n}\n\n/** Same idea as `withFixedResource`, for the log pipeline. */\nfunction withFixedLogResource(processor: LogRecordProcessor, resource: Resource): LogRecordProcessor {\n    return {\n        onEmit: (logRecord: LogRecord, context?: Context) =>\n            processor.onEmit(Object.assign(Object.create(Object.getPrototypeOf(logRecord)), logRecord, { resource }), context),\n        forceFlush: () => processor.forceFlush(),\n        shutdown: () => processor.shutdown(),\n    }\n}\n\n/**\n * Initialize OpenTelemetry trace (and, if the extra peer deps are present,\n * log) export for the host application. Always exports to Kasookoo's own\n * monitoring collector, plus any `endpoint`(s) the host supplies. Returns\n * `false` when the required OTel packages are not installed — the widget\n * still works, just without telemetry.\n */\nexport async function initKasookooTelemetry(\n    config: TelemetryConfig = {},\n    /** @internal — suppresses the \"packages not installed\" warning for automatic, non-explicit probing. */\n    opts: { silent?: boolean } = {}\n): Promise<boolean> {\n    if (initialized) return true\n    initialized = true\n\n    const clientEndpoints = normalizeEndpoints(config.endpoint).filter(\n        (endpoint) => endpoint !== MANDATORY_TRACES_ENDPOINT\n    )\n    const traceEndpoints = [MANDATORY_TRACES_ENDPOINT, ...clientEndpoints]\n    const clientLogsEndpoints = normalizeEndpoints(config.logsEndpoint)\n\n    try {\n        const [\n            { WebTracerProvider },\n            { BatchSpanProcessor },\n            { OTLPTraceExporter },\n            { registerInstrumentations },\n            { FetchInstrumentation },\n            { Resource },\n            { ATTR_SERVICE_NAME },\n        ] = await Promise.all([\n            import(\"@opentelemetry/sdk-trace-web\"),\n            import(\"@opentelemetry/sdk-trace-base\"),\n            import(\"@opentelemetry/exporter-trace-otlp-http\"),\n            import(\"@opentelemetry/instrumentation\"),\n            import(\"@opentelemetry/instrumentation-fetch\"),\n            import(\"@opentelemetry/resources\"),\n            import(\"@opentelemetry/semantic-conventions\"),\n        ])\n\n        const serviceName = config.serviceName?.trim() || DEFAULT_SERVICE_NAME\n        const resourceAttributes = {\n            [ATTR_SERVICE_NAME]: serviceName,\n            \"deployment.environment\": config.environment?.trim() || \"production\",\n        }\n        // Kasookoo's own collector always sees this fixed identity — never\n        // `config.serviceName`/`config.environment` — so a host relabeling\n        // its own telemetry can't also relabel what Kasookoo receives.\n        const mandatoryResource = new Resource({\n            [ATTR_SERVICE_NAME]: DEFAULT_SERVICE_NAME,\n            \"deployment.environment\": \"production\",\n        })\n\n        const provider = new WebTracerProvider({ resource: new Resource(resourceAttributes) })\n        traceEndpoints.forEach((tracesEndpoint, index) => {\n            const processor = new BatchSpanProcessor(new OTLPTraceExporter({ url: tracesEndpoint }))\n            // Index 0 is always the mandatory Kasookoo collector.\n            provider.addSpanProcessor(index === 0 ? withFixedResource(processor, mandatoryResource) : processor)\n        })\n        provider.register()\n\n        registerInstrumentations({\n            instrumentations: [\n                new FetchInstrumentation({\n                    propagateTraceHeaderCorsUrls: [/.*/],\n                    applyCustomAttributesOnSpan: (span, request) => {\n                        const headers =\n                            request instanceof Request\n                                ? request.headers\n                                : new Headers((request as RequestInit).headers ?? undefined)\n                        const requestId = headers.get(CORRELATION_HEADERS.REQUEST_ID)\n                        const callTraceId = headers.get(CORRELATION_HEADERS.CALL_TRACE_ID)\n                        const userId = headers.get(CORRELATION_HEADERS.USER_ID)\n                        const featureType = headers.get(CORRELATION_HEADERS.FEATURE_TYPE)\n                        if (requestId) span.setAttribute(\"request_id\", requestId)\n                        if (callTraceId) span.setAttribute(\"call_trace_id\", callTraceId)\n                        if (userId) span.setAttribute(\"user_id\", userId)\n                        if (featureType) span.setAttribute(\"feature_type\", featureType)\n                    },\n                }),\n            ],\n        })\n\n        // Ships the widget's structured logs (core/logger.ts) to the same\n        // collector(s) — kept in its own try/catch so a missing/incompatible\n        // log-export package degrades to \"traces only\" instead of killing\n        // telemetry entirely.\n        try {\n            const [{ LoggerProvider, BatchLogRecordProcessor }, { OTLPLogExporter }] = await Promise.all([\n                import(\"@opentelemetry/sdk-logs\"),\n                import(\"@opentelemetry/exporter-logs-otlp-http\"),\n            ])\n\n            const loggerProvider = new LoggerProvider({ resource: new Resource(resourceAttributes) })\n            let logsEndpointsAdded = 0\n\n            traceEndpoints.forEach((tracesEndpoint, index) => {\n                // Index 0 is always the mandatory Kasookoo collector — its\n                // logs endpoint is always derived, never taken from host\n                // config, and its resource is fixed too, matching the fact\n                // that neither can be overridden.\n                const explicit = index === 0 ? undefined : clientLogsEndpoints[index - 1]\n                const logsEndpoint = explicit || deriveLogsEndpoint(tracesEndpoint)\n                if (!logsEndpoint) return\n                const processor = new BatchLogRecordProcessor(new OTLPLogExporter({ url: logsEndpoint }))\n                loggerProvider.addLogRecordProcessor(\n                    index === 0 ? withFixedLogResource(processor, mandatoryResource) : processor\n                )\n                logsEndpointsAdded++\n            })\n\n            if (logsEndpointsAdded === 0) {\n                console.warn(\n                    \"[kasookoo-click-to-call] Could not derive a telemetry logs endpoint — log export disabled. \" +\n                        \"Pass telemetry.logsEndpoint explicitly to enable it.\"\n                )\n            } else {\n                const otelLogger = loggerProvider.getLogger(serviceName)\n\n                setOtelLogSink((level, entry) => {\n                    const { msg, ...attributes } = entry\n                    otelLogger.emit({\n                        severityNumber: OTEL_SEVERITY[level],\n                        severityText: level,\n                        body: typeof msg === \"string\" ? msg : JSON.stringify(entry),\n                        // Log entries are built from JSON-serializable primitives\n                        // only (see logger.ts#sanitizeLogData) — safe to widen.\n                        attributes: attributes as Record<string, string | number | boolean>,\n                    })\n                })\n            }\n        } catch (logErr) {\n            console.warn(\n                \"[kasookoo-click-to-call] OpenTelemetry log packages not installed — log export disabled. \" +\n                    \"Install @opentelemetry/sdk-logs and @opentelemetry/exporter-logs-otlp-http to export widget logs.\",\n                logErr\n            )\n        }\n\n        return true\n    } catch (err) {\n        if (!opts.silent) {\n            console.warn(\n                \"[kasookoo-click-to-call] OpenTelemetry packages not installed — telemetry disabled. \" +\n                    \"Install @opentelemetry/sdk-trace-web and related packages to enable traces.\",\n                err\n            )\n        }\n        initialized = false\n        return false\n    }\n}\n","import type { CallIntent } from \"../types\"\n\n// Case/separator-insensitive: \"intentId\", \"intent_id\", \"IntentID\" all normalize the same.\nfunction normalizeKey(key: string): string {\n    return key.toLowerCase().replace(/[_-]/g, \"\")\n}\n\nconst INTENT_ID_ALIASES = [\"intentid\", \"callintentid\", \"id\"].map(normalizeKey)\nconst CLIENT_SECRET_ALIASES = [\"clientsecret\", \"clienttoken\", \"secret\"].map(normalizeKey)\n\nconst MAX_SEARCH_DEPTH = 5\n\n/**\n * Walks an arbitrarily-shaped parsed JSON body looking for a string/number\n * value under a key matching one of `aliases` — breadth-first per level, so\n * a match at the top of the response wins over one nested deeper. Used to\n * tolerate whatever shape a caller's `intentEndpoint` responds with, as long\n * as the field is in there somewhere under a recognizable name.\n */\nfunction findByAliases(value: unknown, aliases: string[], depth = 0, seen = new Set<object>()): string | undefined {\n    if (depth > MAX_SEARCH_DEPTH || value === null || typeof value !== \"object\") return undefined\n    if (seen.has(value)) return undefined\n    seen.add(value)\n\n    const entries = Array.isArray(value) ? value.map((v, i) => [String(i), v] as const) : Object.entries(value)\n\n    for (const [key, val] of entries) {\n        if ((typeof val === \"string\" || typeof val === \"number\") && String(val).trim() && aliases.includes(normalizeKey(key))) {\n            return String(val)\n        }\n    }\n    for (const [, val] of entries) {\n        if (val !== null && typeof val === \"object\") {\n            const found = findByAliases(val, aliases, depth + 1, seen)\n            if (found !== undefined) return found\n        }\n    }\n    return undefined\n}\n\n/**\n * Pulls `{ intentId, clientSecret }` out of a call-intent response of\n * whatever shape — top-level, nested under `data`/`result`/etc, snake_case,\n * camelCase — as long as the two values are present under a recognizable\n * key. Returns `null` if either is missing, regardless of the rest of the\n * shape.\n */\nexport function extractCallIntent(raw: unknown): CallIntent | null {\n    const intentId = findByAliases(raw, INTENT_ID_ALIASES)\n    const clientSecret = findByAliases(raw, CLIENT_SECRET_ALIASES)\n    if (!intentId || !clientSecret) return null\n    return { intentId, clientSecret }\n}\n","import { Room, RoomEvent, Track, type RemoteTrack } from \"livekit-client\"\nimport { TypedEmitter } from \"../../core/events\"\nimport { KasookooError, type CallState, type RemoteParty } from \"../../types\"\nimport { newCallTraceId } from \"../../core/correlation\"\nimport type { CallSpan } from \"../../core/telemetry\"\nimport { logError, logEvent } from \"../../core/diagnostics\"\nimport type { LogLevel } from \"../../core/logger\"\n\ntype CallEvents = {\n    state: CallState\n    error: KasookooError\n}\n\nconst RING_TIMEOUT_MS = 60_000\n\n\nconst CALL_PROGRESS_ATTR = \"sip.callStatus\"\nconst CALL_PROGRESS_ANSWERED = \"active\"\nconst CALL_PROGRESS_OVER = \"hangup\"\n\nexport interface CallHandlers {\n    /** Ends a SIP call, whether or not the far end answered. */\n    endSipCall: (call: Call) => Promise<unknown>\n}\n\n/**\n * A single outbound phone call, from dial to hangup, driven entirely by\n * `state`: `\"connecting\"` → `\"connected\"` → `\"ended\"`. Every call this\n * widget places is outbound (there is no \"incoming\" state — a click-to-call\n * widget never rings in). An unanswered call cancels itself automatically\n * after the configured ring timeout (60s by default, see\n * `KasookooClickToCallConfig.callRingTimeoutMs`).\n */\nexport class Call extends TypedEmitter<CallEvents> {\n    readonly roomName: string\n    /** Stable lifecycle id — sent as X-Call-Trace-ID on all related API calls. */\n    readonly callTraceId: string\n    /** Caller id for correlation (when known). */\n    readonly userId?: string\n    /** The other side of the call — the dialed phone number. Use this for display. */\n    readonly remote: RemoteParty\n\n    private readonly room = new Room()\n    private readonly handlers: CallHandlers\n    private readonly telemetrySpan?: CallSpan\n    private _state: CallState = \"connecting\"\n    private _muted = false\n    private ringTimeout: ReturnType<typeof setTimeout> | null = null\n    // Why the call ended — recorded once, by whichever path got there first.\n    private endReason?: string\n\n    /**\n     * @internal — calls are created by the widget, never directly by the\n     * host application. `reveal` hands the caller a one-time capability to\n     * actually join the call's room — it's kept off the instance itself (a\n     * true private field) so a consumer holding a `Call` can't invoke or\n     * replay it.\n     */\n    constructor(params: {\n        roomName: string\n        remote: RemoteParty\n        handlers: CallHandlers\n        callTraceId?: string\n        userId?: string\n        /** `false` disables the ring timeout entirely; omit for the 60s default. */\n        ringTimeoutMs?: number | false\n        reveal: (connect: (wsUrl: string, accessToken: string) => Promise<void>) => void\n        /** @internal — the span covering this call's whole lifecycle, from `CallsManager`. */\n        telemetrySpan?: CallSpan\n    }) {\n        super()\n        this.roomName = params.roomName\n        this.callTraceId = params.callTraceId ?? newCallTraceId()\n        this.userId = params.userId\n        this.remote = params.remote\n        this.handlers = params.handlers\n        this.telemetrySpan = params.telemetrySpan\n\n        const timeoutMs = params.ringTimeoutMs === false ? null : (params.ringTimeoutMs ?? RING_TIMEOUT_MS)\n        if (timeoutMs !== null) {\n            this.ringTimeout = setTimeout(() => this.onRingTimeout(), timeoutMs)\n        }\n\n        params.reveal((wsUrl, accessToken) => this.#connect(wsUrl, accessToken))\n    }\n\n    /** Where the call is right now. Follow it with `call.on(\"state\", ...)`. */\n    get state(): CallState {\n        return this._state\n    }\n\n    /** Whether the local microphone is muted. */\n    get muted(): boolean {\n        return this._muted\n    }\n\n    // The ring clock ran out with nobody having picked up — cancel exactly as\n    // if the user had hung up manually (setState clears this timer on any transition).\n    private onRingTimeout(): void {\n        if (this._state === \"connecting\") {\n            this.diag(\"warn\", \"ring_timeout\", this.callFields())\n            this.endReason ??= \"ring_timeout\"\n            void this.end()\n        }\n    }\n\n    /** Mutes/unmutes the local microphone. */\n    async setMuted(muted: boolean): Promise<void> {\n        await this.room.localParticipant.setMicrophoneEnabled(!muted)\n        this._muted = muted\n    }\n\n    /** Hangs up. Works whether or not the phone number has answered yet. */\n    async end(): Promise<void> {\n        if (this._state === \"ended\") return\n        this.endReason ??= \"local_hangup\"\n        // A SIP call ends the same way whether or not the far end answered.\n        this.notifyBackend(this.inSpan(() => this.handlers.endSipCall(this)), \"call_end_failed\", \"the call ended\")\n        await this.room.disconnect()\n        this.finish(\"local_hangup\") // safety net if the Disconnected event never fires\n    }\n\n    async #connect(ws_url: string, accessToken: string): Promise<void> {\n        this.room\n            .on(RoomEvent.TrackSubscribed, (track, _pub, participant) => {\n                this.attachAudio(track, participant.identity)\n            })\n            .on(RoomEvent.TrackUnsubscribed, (track) => {\n                track.detach().forEach((el) => el.remove())\n            })\n            .on(RoomEvent.ParticipantConnected, () => this.checkProgress())\n            .on(RoomEvent.ParticipantAttributesChanged, () => this.checkProgress())\n            .on(RoomEvent.ParticipantDisconnected, () => {\n                this.endReason ??= \"remote_left\"\n                void this.room.disconnect()\n            })\n            .on(RoomEvent.Disconnected, (reason) => {\n                this.diag(\"info\", \"room_disconnected\", { ...this.callFields(), livekit_reason: reason })\n                this.cleanupAudio()\n                this.finish(\"room_disconnected\")\n            })\n\n        try {\n            await this.room.connect(ws_url, accessToken)\n            this.diag(\"info\", \"room_connected\", this.callFields())\n            await this.room.localParticipant.setMicrophoneEnabled(true, {\n                echoCancellation: true,\n                noiseSuppression: true,\n                autoGainControl: true,\n            })\n            // The phone leg may already have joined before us.\n            this.checkProgress()\n        } catch (err) {\n            const reason = err instanceof Error ? `${err.name}: ${err.message}` : String(err)\n            this.endReason ??= \"connect_failed\"\n            this.diagError(\"call_connect_failed\", err, this.callFields())\n            this.telemetrySpan?.recordError(err)\n            this.emit(\n                \"error\",\n                err instanceof KasookooError\n                    ? err\n                    : new KasookooError(\"call_connect_failed\", `Failed to connect to the call room — ${reason}`, {\n                          details: err,\n                      })\n            )\n            await this.end()\n        }\n    }\n\n    // ------------------------------------------------------------------ internals\n\n    // Fire-and-forget: a failed request must not keep the user stuck waiting\n    // on a hangup. Failures surface via `error`.\n    private notifyBackend(promise: Promise<unknown>, code: string, what: string): void {\n        promise.catch((err) => {\n            this.diagError(code, err, this.callFields())\n            this.telemetrySpan?.recordError(err)\n            this.emit(\n                \"error\",\n                err instanceof KasookooError\n                    ? err\n                    : new KasookooError(code, `Failed to notify the backend that ${what}`, { details: err })\n            )\n        })\n    }\n\n    // Runs `fn` with this call's lifecycle span active, so a `fetch()` made\n    // synchronously inside it (before its first `await`) nests under that\n    // span instead of starting its own independent trace.\n    private inSpan<T>(fn: () => T): T {\n        return this.telemetrySpan ? this.telemetrySpan.runInContext(fn) : fn()\n    }\n\n    // Being in the room isn't the same as having answered — the phone leg\n    // joins as soon as dialing starts, and lingers after it hangs up. Drive\n    // the state off what the far end reports; if it reports nothing, fall\n    // back to presence so we can't get stuck.\n    private checkProgress(): void {\n        if (this._state === \"ended\") return\n\n        for (const participant of this.room.remoteParticipants.values()) {\n            const progress = participant.attributes?.[CALL_PROGRESS_ATTR]\n\n            // Rejected or hung up. Don't wait for the room to drop them.\n            if (progress === CALL_PROGRESS_OVER) {\n                this.endReason ??= \"remote_hangup\"\n                void this.room.disconnect()\n                this.finish(\"remote_hangup\")\n                return\n            }\n\n            if (this._state === \"connecting\" && (progress === undefined || progress === CALL_PROGRESS_ANSWERED)) {\n                this.setState(\"connected\")\n                return\n            }\n        }\n    }\n\n    // Same as logEvent/logError, but also lands on this call's own trace.\n    private diag(level: LogLevel, event: string, fields: Record<string, unknown> = {}): void {\n        logEvent(level, event, fields, this.telemetrySpan)\n    }\n\n    private diagError(event: string, err: unknown, fields: Record<string, unknown> = {}): void {\n        logError(event, err, fields, \"error\", this.telemetrySpan)\n    }\n\n    private callFields(): Record<string, unknown> {\n        return { call_trace_id: this.callTraceId, room_name: this.roomName, call_kind: \"sip\", direction: \"outgoing\" }\n    }\n\n    // Notes why the call is ending (first reason wins), then moves to \"ended\".\n    private finish(reason: string): void {\n        this.endReason ??= reason\n        this.setState(\"ended\")\n    }\n\n    private setState(state: CallState): void {\n        if (this._state === state || this._state === \"ended\") return\n        const previous = this._state\n        this._state = state\n        this.diag(\"info\", \"call_state\", {\n            ...this.callFields(),\n            from: previous,\n            state,\n            end_reason: state === \"ended\" ? (this.endReason ?? \"unknown\") : undefined,\n        })\n        if (state === \"ended\") this.telemetrySpan?.setAttribute(\"call.end_reason\", this.endReason ?? \"unknown\")\n        if (this.ringTimeout) {\n            clearTimeout(this.ringTimeout)\n            this.ringTimeout = null\n        }\n        this.emit(\"state\", state)\n        // The call's whole lifecycle — dial through hangup — is one span;\n        // \"ended\" is the single terminal state (see the class doc comment),\n        // so it's the one reliable place to close it out.\n        if (state === \"ended\") this.telemetrySpan?.end()\n    }\n\n    private attachAudio(track: RemoteTrack, participantIdentity: string): void {\n        if (track.kind !== Track.Kind.Audio || typeof document === \"undefined\") return\n\n        const el = track.attach()\n        el.dataset.kasookooCtcAudio = participantIdentity\n        el.autoplay = true\n        document.body.appendChild(el)\n\n        // Recover from browser autoplay blocking on the next user gesture.\n        el.play().catch(() => {\n            this.diag(\"warn\", \"audio_autoplay_blocked\", this.callFields())\n            const resume = () => void el.play().catch(() => {})\n            window.addEventListener(\"click\", resume, { once: true })\n            window.addEventListener(\"touchstart\", resume, { once: true })\n        })\n    }\n\n    private cleanupAudio(): void {\n        if (typeof document === \"undefined\") return\n        document.querySelectorAll(\"audio[data-kasookoo-ctc-audio]\").forEach((el) => el.remove())\n    }\n}\n","/**\n * Frontend diagnostics — named log events for things that go wrong (or just\n * happen) in the browser rather than in an API request: permissions, the\n * push listener, the service worker, session lifecycle, call lifecycle.\n *\n * Everything goes through the structured logger, so it reaches the console\n * and — whenever OpenTelemetry is active — the Kasookoo collector, tagged\n * with the same ids as the HTTP logs. Fields are deliberately limited to\n * states, error codes and correlation ids: never phone numbers, push\n * payloads, tokens or raw error objects.\n */\n\nimport { getLogger, type LogLevel } from \"./logger\"\nimport type { CallSpan } from \"./telemetry\"\n\nconst diagnosticsLogger = getLogger(\"kasookoo-click-to-call.diagnostics\")\n\nexport type DiagnosticFields = Record<string, unknown>\n\n// While `init()` runs, its events are also added to this span, so a failed\n// init shows its permission / push / registration steps on one trace.\nlet initSpan: CallSpan | null = null\n\n/** @internal Set by `KasookooClient.init()` for the duration of the init. */\nexport function setDiagnosticsSpan(span: CallSpan | null): void {\n    initSpan = span\n}\n\n/** @internal Closes the init span, marking it failed when `err` is given. */\nexport function endDiagnosticsSpan(err?: unknown): void {\n    if (!initSpan) return\n    if (err !== undefined) initSpan.recordError(err)\n    initSpan.end()\n    initSpan = null\n}\n\n/** Span events only take primitive attributes. */\nfunction spanAttributes(fields: DiagnosticFields): Record<string, string | number | boolean> {\n    const out: Record<string, string | number | boolean> = {}\n    for (const [key, value] of Object.entries(fields)) {\n        if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") out[key] = value\n    }\n    return out\n}\n\n/**\n * Logs one named diagnostic event. It is also added to `span` (a call's\n * span) or, outside a call, to the span of the `init()` currently running.\n */\nexport function logEvent(level: LogLevel, event: string, fields: DiagnosticFields = {}, span?: CallSpan): void {\n    diagnosticsLogger[level]({ msg: event, event, ...fields })\n    ;(span ?? initSpan)?.addEvent(event, spanAttributes({ level, ...fields }))\n}\n/** Reduces anything thrown to a loggable `{ name: message }` string — no stacks, no payloads. */\nfunction describeCause(cause: unknown): string | undefined {\n    if (cause === undefined || cause === null) return undefined\n    if (cause instanceof Error) return `${cause.name}: ${cause.message}`\n    if (typeof cause === \"string\") return cause\n    const named = cause as { name?: unknown; message?: unknown }\n    if (typeof named.name === \"string\") return `${named.name}${typeof named.message === \"string\" ? `: ${named.message}` : \"\"}`\n    return undefined\n}\n\n/** Logs an error as a named event, keeping its machine-readable `code` and HTTP `status` when it has them. */\nexport function logError(\n    event: string,\n    err: unknown,\n    fields: DiagnosticFields = {},\n    level: LogLevel = \"error\",\n    span?: CallSpan\n): void {\n    const known = err as { code?: unknown; status?: unknown; message?: unknown; details?: unknown }\n    const entry = {\n        error_code: typeof known?.code === \"string\" ? known.code : undefined,\n        error_status: typeof known?.status === \"number\" ? known.status : undefined,\n        error_message: typeof known?.message === \"string\" ? known.message : describeCause(err),\n        error_cause: describeCause(known?.details),\n        ...fields,\n    }\n    diagnosticsLogger[level]({ msg: event, event, ...entry })\n    ;(span ?? initSpan)?.addEvent(event, spanAttributes({ level, ...entry }))\n}\n","import { logError } from \"./diagnostics\"\n\nexport class TypedEmitter<Events extends Record<string, unknown>> {\n    private listeners = new Map<keyof Events, Set<(payload: never) => void>>()\n\n    on<K extends keyof Events>(event: K, listener: (payload: Events[K]) => void): () => void {\n        let set = this.listeners.get(event)\n        if (!set) {\n            set = new Set()\n            this.listeners.set(event, set)\n        }\n        set.add(listener as (payload: never) => void)\n        return () => this.off(event, listener)\n    }\n\n    off<K extends keyof Events>(event: K, listener: (payload: Events[K]) => void): void {\n        this.listeners.get(event)?.delete(listener as (payload: never) => void)\n    }\n\n    protected emit<K extends keyof Events>(event: K, payload: Events[K]): void {\n        this.listeners.get(event)?.forEach((listener) => {\n            try {\n                ;(listener as (payload: Events[K]) => void)(payload)\n            } catch (err) {\n                console.error(`[kasookoo-click-to-call] listener for \"${String(event)}\" threw:`, err)\n                logError(\"listener_threw\", err, { widget_event: String(event) })\n            }\n        })\n    }\n\n    protected removeAllListeners(): void {\n        this.listeners.clear()\n    }\n}\n","import type { Call } from \"../services/calls/call\"\nimport type { CallState } from \"../types\"\n\n/**\n * The widget's built-in call window — a draggable floating card, always on.\n * There is no custom-renderer option: every call placed through this widget\n * shows this same UI. Mounted once per call and removed automatically when\n * the call ends.\n */\nexport function mountCallWindow(call: Call): void {\n    if (typeof document === \"undefined\") return\n\n    injectStyles()\n    const stack = getCallsStack()\n    const container = document.createElement(\"div\")\n    container.dataset.kasookooCtcCallWindow = call.roomName\n    stack.appendChild(container)\n\n    const cleanup = renderCallWindow(container, call)\n\n    call.on(\"state\", (state) => {\n        if (state !== \"ended\") return\n        try {\n            cleanup()\n        } finally {\n            container.remove()\n            if (!stack.childElementCount) stack.remove()\n        }\n    })\n}\n\n// ---------------------------------------------------------------- built-in UI\n\nconst STYLE_ID = \"kasookoo-ctc-call-window-styles\"\nconst CALLS_STACK_ID = \"kasookoo-ctc-calls-stack\"\n\nconst MIC_ICON = `<svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\"/><path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/><line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\"/></svg>`\nconst PHONE_OFF_ICON = `<svg width=\"22\" height=\"22\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M10.68 13.31a16 16 0 0 0 3.41 2.6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7 2 2 0 0 1 1.72 2v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.42 19.42 0 0 1-3.33-2.67m-2.67-3.34a19.79 19.79 0 0 1-3.07-8.63A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91\"/><line x1=\"22\" x2=\"2\" y1=\"2\" y2=\"22\"/></svg>`\n\nexport function injectStyles(): void {\n    if (document.getElementById(STYLE_ID)) return\n    const style = document.createElement(\"style\")\n    style.id = STYLE_ID\n    style.textContent = `\n        .kasookoo-ctc-cw{display:flex;flex-direction:column;align-items:center;width:280px;border-radius:16px;overflow:hidden;background:#fff;box-shadow:0 8px 30px rgba(0,0,0,.25);font-family:system-ui,-apple-system,sans-serif;user-select:none}\n        .kasookoo-ctc-cw__header{width:100%;background:#7DBAAB;color:#fff;text-align:center;padding:8px 0;cursor:move}\n        .kasookoo-ctc-cw__status{margin:0;font-size:13px;font-weight:600}\n        .kasookoo-ctc-cw__timer{margin:0;font-size:11px;opacity:.85}\n        .kasookoo-ctc-cw__body{display:flex;flex-direction:column;align-items:center;padding:16px 0}\n        .kasookoo-ctc-cw__avatar{width:72px;height:72px;border-radius:50%;border:4px solid #5C0F8B;background:#f3e8ff;color:#5C0F8B;display:flex;align-items:center;justify-content:center;font-size:24px;font-weight:700}\n        .kasookoo-ctc-cw__name{margin:12px 0 0;font-size:16px;font-weight:600;color:#5C0F8B}\n        .kasookoo-ctc-cw__controls{display:flex;align-items:center;justify-content:center;gap:16px;width:100%;padding:12px 0;background:#7DBAAB;border-radius:24px 24px 0 0}\n        .kasookoo-ctc-cw__btn{display:flex;align-items:center;justify-content:center;width:44px;height:44px;border-radius:50%;border:2px solid #fff;cursor:pointer;transition:background .15s,color .15s}\n        .kasookoo-ctc-cw__btn--mic{background:#fff;color:#5C0F8B}\n        .kasookoo-ctc-cw__btn--mic.is-muted{background:rgba(255,255,255,.15);color:#fff}\n        .kasookoo-ctc-cw__btn--end{background:#ef4444;color:#fff;border-color:#ef4444}\n        .kasookoo-ctc-cw__btn--end:hover{background:#dc2626}\n        #${CALLS_STACK_ID}{position:fixed;bottom:24px;right:24px;z-index:2147483000;display:flex;flex-direction:column-reverse;align-items:flex-end;gap:12px}\n    `\n    document.head.appendChild(style)\n}\n\nfunction getCallsStack(): HTMLElement {\n    let stack = document.getElementById(CALLS_STACK_ID)\n    if (!stack) {\n        injectStyles()\n        stack = document.createElement(\"div\")\n        stack.id = CALLS_STACK_ID\n        document.body.appendChild(stack)\n    }\n    return stack\n}\n\nconst STATUS_LABEL: Record<CallState, string> = {\n    connecting: \"Calling...\",\n    connected: \"Connected\",\n    ended: \"Call ended\",\n}\n\nfunction renderCallWindow(container: HTMLElement, call: Call): () => void {\n    const card = document.createElement(\"div\")\n    card.className = \"kasookoo-ctc-cw\"\n    card.innerHTML = `\n        <div class=\"kasookoo-ctc-cw__header\">\n            <p class=\"kasookoo-ctc-cw__status\"></p>\n            <p class=\"kasookoo-ctc-cw__timer\" hidden>0:00</p>\n        </div>\n        <div class=\"kasookoo-ctc-cw__body\">\n            <div class=\"kasookoo-ctc-cw__avatar\">${PHONE_OFF_ICON.replace(\"width=\\\"22\\\" height=\\\"22\\\"\", \"width=\\\"28\\\" height=\\\"28\\\"\")}</div>\n            <h2 class=\"kasookoo-ctc-cw__name\">${escapeHtml(call.remote.label || call.remote.name)}</h2>\n        </div>\n        <div class=\"kasookoo-ctc-cw__controls\"></div>`\n    container.appendChild(card)\n\n    const status = card.querySelector<HTMLElement>(\".kasookoo-ctc-cw__status\")!\n    const timer = card.querySelector<HTMLElement>(\".kasookoo-ctc-cw__timer\")!\n    const controls = card.querySelector<HTMLElement>(\".kasookoo-ctc-cw__controls\")!\n\n    let seconds = 0\n    let interval: ReturnType<typeof setInterval> | null = null\n    const startTimer = () => {\n        timer.hidden = false\n        interval = setInterval(() => {\n            seconds += 1\n            const m = Math.floor(seconds / 60)\n            const s = String(seconds % 60).padStart(2, \"0\")\n            timer.textContent = `${m}:${s}`\n        }, 1000)\n    }\n\n    const render = () => {\n        status.textContent = STATUS_LABEL[call.state]\n\n        const micButton =\n            call.state === \"connected\"\n                ? `<button class=\"kasookoo-ctc-cw__btn kasookoo-ctc-cw__btn--mic\" title=\"Mute microphone\">${MIC_ICON}</button>`\n                : \"\"\n        controls.innerHTML = `${micButton} <button class=\"kasookoo-ctc-cw__btn kasookoo-ctc-cw__btn--end\" title=\"${\n            call.state === \"connected\" ? \"End call\" : \"Cancel call\"\n        }\">${PHONE_OFF_ICON}</button>`\n        controls.querySelector(\".kasookoo-ctc-cw__btn--end\")!.addEventListener(\"click\", () => void call.end())\n\n        const micBtn = controls.querySelector<HTMLButtonElement>(\".kasookoo-ctc-cw__btn--mic\")\n        micBtn?.addEventListener(\"click\", () => {\n            void call.setMuted(!call.muted).then(() => {\n                micBtn.classList.toggle(\"is-muted\", call.muted)\n                micBtn.title = call.muted ? \"Unmute microphone\" : \"Mute microphone\"\n            })\n        })\n\n        if (call.state === \"connected\" && !interval) startTimer()\n    }\n\n    render()\n    const offState = call.on(\"state\", render)\n    makeDraggable(container, card.querySelector<HTMLElement>(\".kasookoo-ctc-cw__header\")!)\n\n    return () => {\n        offState()\n        if (interval) clearInterval(interval)\n    }\n}\n\nfunction makeDraggable(moved: HTMLElement, handle: HTMLElement): void {\n    let drag: { startX: number; startY: number; baseX: number; baseY: number } | null = null\n    let offset = { x: 0, y: 0 }\n    handle.addEventListener(\"pointerdown\", (e) => {\n        drag = { startX: e.clientX, startY: e.clientY, baseX: offset.x, baseY: offset.y }\n        handle.setPointerCapture(e.pointerId)\n    })\n    handle.addEventListener(\"pointermove\", (e) => {\n        if (!drag) return\n        offset = { x: drag.baseX + e.clientX - drag.startX, y: drag.baseY + e.clientY - drag.startY }\n        moved.style.transform = `translate(${offset.x}px, ${offset.y}px)`\n    })\n    handle.addEventListener(\"pointerup\", () => (drag = null))\n}\n\nfunction escapeHtml(text: string): string {\n    return text.replace(/[&<>\"']/g, (c) => `&#${c.charCodeAt(0)};`)\n}\n","import { request } from \"../../core/http\"\nimport { FEATURE, type CorrelationContext } from \"../../core/correlation\"\nimport { KasookooError, type SipCallResponse, type SipDialParams } from \"../../types\"\nimport type { Call } from \"./call\"\n\nexport interface CallsApiContext {\n    baseUrl: string\n    token: string\n    /** Resolved caller identifier for the X-User-ID correlation header, if any. */\n    userId?: string\n}\n\nfunction correlationForCall(ctx: CallsApiContext, call: Call): CorrelationContext {\n    return {\n        callTraceId: call.callTraceId,\n        userId: ctx.userId ?? call.userId,\n        featureType: FEATURE.SIP_CALL,\n    }\n}\n\nfunction correlationForLifecycle(ctx: CallsApiContext, callTraceId: string): CorrelationContext {\n    return {\n        callTraceId,\n        userId: ctx.userId,\n        featureType: FEATURE.SIP_CALL,\n    }\n}\n\n/**\n * Places a call to an external phone number — the same `/api/v1/sip/calls/make`\n * endpoint and `intent_id`/`client_secret` fields `kasookoo-sdk`'s\n * `initSipCall()` uses on the frontend.\n */\nexport async function makeSipCallRequest(\n    ctx: CallsApiContext,\n    params: SipDialParams & { roomName: string },\n    callTraceId: string\n): Promise<SipCallResponse> {\n    const res = await request<SipCallResponse>(`${ctx.baseUrl}/api/v1/sip/calls/make`, {\n        method: \"POST\",\n        token: ctx.token,\n        correlation: correlationForLifecycle(ctx, callTraceId),\n        body: {\n            phone_number: params.phoneNumber,\n            room_name: params.roomName,\n            intent_id: params.intentId,\n            client_secret: params.clientSecret,\n            ...(params.participantName !== undefined ? { participant_name: params.participantName } : {}),\n        },\n    })\n\n    if (res?.success === false) {\n        throw new KasookooError(\"call_start_failed\", res.message || \"Failed to start the call\", { details: res })\n    }\n    if (!res?.data?.ws_url || !res?.data?.access_token) {\n        throw new KasookooError(\"invalid_call_tokens\", \"Received an unexpected response while starting the call\", {\n            details: res,\n        })\n    }\n    return res\n}\n\n/** Ends a call placed to an external phone number, answered or not. */\nexport function endSipCallRequest(ctx: CallsApiContext, call: Call, participantIdentity?: string): Promise<unknown> {\n    return request(`${ctx.baseUrl}/api/v1/sip/calls/end`, {\n        method: \"POST\",\n        token: ctx.token,\n        correlation: correlationForCall(ctx, call),\n        body: {\n            room_name: call.roomName,\n            ...(participantIdentity !== undefined ? { participant_identity: participantIdentity } : {}),\n        },\n    })\n}\n","import { KasookooError, type CallIntent, type CallIntentEndpoint, type DialParams } from \"../../types\"\nimport { newCallTraceId } from \"../../core/correlation\"\nimport { getLogger } from \"../../core/logger\"\nimport { startCallSpan } from \"../../core/telemetry\"\nimport { request } from \"../../core/http\"\nimport { extractCallIntent } from \"../../core/response-shape\"\nimport { Call, type CallHandlers } from \"./call\"\nimport { mountCallWindow } from \"../../ui/call-window\"\nimport { endSipCallRequest, makeSipCallRequest } from \"./calls.api\"\n\nconst callsLogger = getLogger(\"kasookoo-click-to-call.calls\")\n\nexport interface CallsManagerOptions {\n    baseUrl: string\n    getToken: () => string\n    /** Caller identifier for correlation headers, if known. */\n    getUserId?: () => string | undefined\n    /** The `subject` given to `init()` — sent as part of the default call-intent request body; see `getCallIntent` below. */\n    subject: string\n    /** How long an unanswered call rings before giving up. `false` disables it. Defaults to 60s. */\n    ringTimeoutMs?: number | false\n    /** Your backend's call-intent endpoint — see `KasookooClickToCallConfig.intentEndpoint`. */\n    intentEndpoint: CallIntentEndpoint\n    onError: (error: KasookooError) => void\n}\n\n/**\n * Outbound calling: `dial()` places a call to a phone number and tracks it\n * until it ends. Only one call may be active at a time — same rule as\n * kasookoo-sdk's CallsManager, simplified to the SIP-only, always-outgoing\n * case a click-to-call widget needs.\n */\nexport class CallsManager {\n    private readonly opts: CallsManagerOptions\n    private readonly calls = new Map<string, Call>()\n    // getActiveCall() only sees a call once it's tracked, which happens after\n    // the token request resolves — without this, rapid repeat clicks each\n    // pass that check before the first one lands, placing one call per click.\n    private placingCall = false\n\n    constructor(opts: CallsManagerOptions) {\n        this.opts = opts\n    }\n\n    /**\n     * Places a call to an external phone number:\n     *  1. asks your backend's `intentEndpoint` for a call intent\n     *  2. requests SIP call tokens from Kasookoo, authorized by that intent\n     *  3. connects to the LiveKit room and publishes the microphone\n     *  4. shows the built-in call window\n     * Resolves with the `Call` handle as soon as the connection starts.\n     */\n    async dial(params: DialParams): Promise<Call> {\n        if (!params?.phoneNumber) {\n            throw new KasookooError(\"invalid_params\", \"`phoneNumber` is required\")\n        }\n        if (this.getActiveCall() || this.placingCall) {\n            throw new KasookooError(\"call_in_progress\", \"Another call is already active. End it first.\")\n        }\n\n        const roomName = params.roomName || `ctc_${crypto.randomUUID()}`\n        const callTraceId = newCallTraceId()\n        const callSpan = await startCallSpan(\"sip_call\", {\n            call_trace_id: callTraceId,\n            feature_type: \"sip_call\",\n            user_id: this.opts.getUserId?.(),\n            room_name: roomName,\n            phone_number: params.phoneNumber,\n        })\n        callsLogger.info({\n            msg: \"sip_call_started\",\n            event: \"sip_call_started\",\n            room_name: roomName,\n            phone_number: params.phoneNumber,\n            call_trace_id: callTraceId,\n            feature_type: \"sip_call\",\n            user_id: this.opts.getUserId?.(),\n            request_id: callTraceId,\n            trace_id: callTraceId,\n        })\n        this.placingCall = true\n        try {\n            const intent = await callSpan.runInContext(() => this.getCallIntent(params.phoneNumber))\n            const res = await callSpan.runInContext(() =>\n                makeSipCallRequest(\n                    this.ctx(),\n                    { ...params, roomName, intentId: intent.intentId, clientSecret: intent.clientSecret },\n                    callTraceId\n                )\n            )\n            const data = res.data\n            const phoneNumber = data.dialed_number || params.phoneNumber\n\n            let connect: ((wsUrl: string, accessToken: string) => Promise<void>) | undefined\n            const call = new Call({\n                roomName: data.room_name || roomName,\n                remote: { name: phoneNumber, type: \"sip\", label: params.label },\n                callTraceId,\n                userId: this.opts.getUserId?.(),\n                handlers: this.handlers(data.participant_identity),\n                ringTimeoutMs: this.opts.ringTimeoutMs,\n                telemetrySpan: callSpan,\n                reveal: (fn) => {\n                    connect = fn\n                },\n            })\n            this.track(call)\n            callsLogger.info({\n                msg: \"sip_call_connecting\",\n                event: \"sip_call_connecting\",\n                room_name: data.room_name || roomName,\n                phone_number: phoneNumber,\n                call_trace_id: callTraceId,\n                feature_type: \"sip_call\",\n                user_id: this.opts.getUserId?.(),\n                request_id: callTraceId,\n                trace_id: callTraceId,\n            })\n            void connect!(data.ws_url, data.access_token)\n            return call\n        } catch (err) {\n            callSpan.recordError(err)\n            callSpan.end()\n            throw err\n        } finally {\n            this.placingCall = false\n        }\n    }\n\n    /** The call currently connecting/connected, if any. */\n    getActiveCall(): Call | null {\n        for (const call of this.calls.values()) {\n            if (call.state === \"connecting\" || call.state === \"connected\") return call\n        }\n        return null\n    }\n\n    close(): void {\n        this.calls.forEach((call) => void call.end())\n        this.calls.clear()\n    }\n\n    // ------------------------------------------------------------- internals\n\n    /**\n     * POSTs `{ phoneNumber, subject }` to your `intentEndpoint` and parses\n     * the response leniently — any shape works as long as an intent id and\n     * client secret are in there somewhere under a recognizable key. `subject`\n     * is always the same value given to `init()` — Kasookoo rejects a call\n     * intent whose `subject` doesn't match the session's, so this can't be\n     * left for the caller to remember to pass through themselves. Retries\n     * once on failure, since this call sits right before every dial and a\n     * single transient blip shouldn't block the user from placing a call.\n     */\n    private async getCallIntent(phoneNumber: string): Promise<CallIntent> {\n        const endpoint = this.opts.intentEndpoint\n        const url = typeof endpoint === \"string\" ? endpoint : endpoint.url\n        const headers = typeof endpoint === \"string\" ? undefined : await resolveHeaders(endpoint.headers)\n        const credentials = typeof endpoint === \"string\" ? undefined : endpoint.credentials\n        const body =\n            typeof endpoint === \"string\" || !endpoint.body\n                ? { phoneNumber, subject: this.opts.subject }\n                : await endpoint.body(phoneNumber)\n\n        let raw: unknown\n        try {\n            raw = await request<unknown>(url, { method: \"POST\", body, headers, credentials })\n        } catch (err) {\n            if (err instanceof KasookooError && err.status !== undefined && err.status < 500) throw err\n            raw = await request<unknown>(url, { method: \"POST\", body, headers, credentials })\n        }\n\n        const intent = extractCallIntent(raw)\n        if (!intent) {\n            throw new KasookooError(\n                \"missing_call_intent\",\n                `\\`intentEndpoint\\` (${url}) must respond with a body containing an intent id and client secret ` +\n                    `(e.g. { intentId, clientSecret }, { intent_id, client_secret }, or nested under a wrapper — any shape is fine as long as both are present) — got neither`,\n                { details: raw }\n            )\n        }\n        return intent\n    }\n\n    private ctx() {\n        return {\n            baseUrl: this.opts.baseUrl,\n            token: this.opts.getToken(),\n            userId: this.opts.getUserId?.(),\n        }\n    }\n\n    private track(call: Call): void {\n        this.calls.set(call.roomName, call)\n        call.on(\"state\", (state) => {\n            if (state === \"ended\") this.calls.delete(call.roomName)\n        })\n        mountCallWindow(call)\n    }\n\n    private handlers(participantIdentity: string): CallHandlers {\n        return {\n            endSipCall: (call) => endSipCallRequest(this.ctx(), call, participantIdentity),\n        }\n    }\n}\n\nasync function resolveHeaders(\n    headers: Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>) | undefined\n): Promise<Record<string, string> | undefined> {\n    if (typeof headers === \"function\") return await headers()\n    return headers\n}\n","import { KasookooError } from \"../types\"\nimport { logError, logEvent } from \"./diagnostics\"\n\nexport async function requestMicPermissions(): Promise<void> {\n    if (typeof navigator === \"undefined\" || !navigator.mediaDevices?.getUserMedia) {\n        const error = new KasookooError(\n            \"microphone_unavailable\",\n            \"Microphone access is not available in this environment (requires a secure browser context)\"\n        )\n        logError(\"mic_permission\", error, { state: \"unavailable\", secure_context: globalThis.isSecureContext }, \"warn\")\n        throw error\n    }\n    try {\n        const stream = await navigator.mediaDevices.getUserMedia({ audio: true })\n        stream.getTracks().forEach((track) => track.stop())\n        logEvent(\"info\", \"mic_permission\", { state: \"granted\" })\n    } catch (err) {\n        const failure = micFailure(err)\n        logError(\"mic_permission\", failure, { state: failure.code, browser_error: (err as { name?: string })?.name }, \"warn\")\n        throw failure\n    }\n}\n\nfunction micFailure(err: unknown): KasookooError {\n    const name = (err as { name?: string })?.name\n    if (name === \"NotFoundError\" || name === \"OverconstrainedError\") {\n        return new KasookooError(\n            \"microphone_not_found\",\n            \"No microphone device was found. Connect a microphone and try again.\",\n            { details: err }\n        )\n    }\n    if (name === \"NotReadableError\" || name === \"AbortError\") {\n        return new KasookooError(\n            \"microphone_in_use\",\n            \"The microphone is busy or unreadable (possibly used by another application).\",\n            { details: err }\n        )\n    }\n    return new KasookooError(\n        \"microphone_permission_denied\",\n        \"Microphone permission was denied (or dismissed, or blocked by browser settings). \" +\n            \"Reset it via the lock/tune icon next to the address bar → Site settings → Microphone → Allow.\",\n        { details: err }\n    )\n}\n","export interface DialerOptions {\n    /** Called when the user presses the call button with a non-empty number. */\n    onDial: (phoneNumber: string) => void\n    /**\n     * Prefilled dialing prefix shown in the input on mount, e.g. `\"+1\"`.\n     * Purely a starting value — the user can freely edit or clear it.\n     */\n    defaultCountryCode?: string\n    /** Placeholder text for the number input. Defaults to \"Enter phone number\". */\n    placeholder?: string\n}\n\nexport interface DialerHandle {\n    /** Removes the dialer from the DOM and detaches its listeners. */\n    destroy(): void\n    /** Disables the call button and digit pad, e.g. while a call is already active. */\n    setDisabled(disabled: boolean): void\n}\n\nconst STYLE_ID = \"kasookoo-ctc-dialer-styles\"\n\nconst KEYS: Array<{ digit: string; letters?: string }> = [\n    { digit: \"1\" },\n    { digit: \"2\", letters: \"ABC\" },\n    { digit: \"3\", letters: \"DEF\" },\n    { digit: \"4\", letters: \"GHI\" },\n    { digit: \"5\", letters: \"JKL\" },\n    { digit: \"6\", letters: \"MNO\" },\n    { digit: \"7\", letters: \"PQRS\" },\n    { digit: \"8\", letters: \"TUV\" },\n    { digit: \"9\", letters: \"WXYZ\" },\n    { digit: \"*\" },\n    { digit: \"0\", letters: \"+\" },\n    { digit: \"#\" },\n]\n\nconst BACKSPACE_ICON = `<svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\"><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/></svg>`\n\n/** The only characters this dial pad ever produces — digits plus the two DTMF symbols and the international-dialing prefix. */\nconst ALLOWED_CHARS = /[^0-9*#+]/g\nconst CALL_ICON = `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"currentColor\" stroke=\"none\"><path d=\"M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z\"/></svg>`\n\n/**\n * Injects the dial pad's styles into `root` — a `ShadowRoot` when the dialer\n * is mounted inside one (the normal case, for CSS isolation from the host\n * page), or `document` otherwise. Idempotent per root.\n */\nfunction injectStyles(root: Document | ShadowRoot): void {\n    const target: ParentNode = root instanceof Document ? root.head : root\n    if (target.querySelector(`#${STYLE_ID}`)) return\n    const style = document.createElement(\"style\")\n    style.id = STYLE_ID\n    style.textContent = `\n        .kasookoo-ctc-dialer{display:flex;flex-direction:column;align-items:center;width:260px;padding:20px 16px;border-radius:20px;background:#fff;box-shadow:0 8px 30px rgba(0,0,0,.18);font-family:system-ui,-apple-system,sans-serif;user-select:none}\n        .kasookoo-ctc-dialer__input-row{display:flex;align-items:center;width:100%;margin-bottom:16px}\n        .kasookoo-ctc-dialer__input{flex:1;border:none;outline:none;font-size:20px;font-weight:600;color:#1f2933;text-align:center;background:transparent;min-width:0}\n        .kasookoo-ctc-dialer__backspace{display:flex;align-items:center;justify-content:center;width:32px;height:32px;border:none;background:transparent;color:#94a3b8;cursor:pointer;border-radius:8px;flex-shrink:0}\n        .kasookoo-ctc-dialer__backspace:hover{background:#f1f5f9;color:#475569}\n        .kasookoo-ctc-dialer__backspace:disabled{visibility:hidden}\n        .kasookoo-ctc-dialer__pad{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;width:100%;margin-bottom:18px}\n        .kasookoo-ctc-dialer__key{display:flex;flex-direction:column;align-items:center;justify-content:center;aspect-ratio:1;border-radius:50%;border:none;background:#f1f5f9;color:#1f2933;font-size:20px;font-weight:600;cursor:pointer;transition:background .12s}\n        .kasookoo-ctc-dialer__key:hover{background:#e2e8f0}\n        .kasookoo-ctc-dialer__key:active{background:#cbd5e1}\n        .kasookoo-ctc-dialer__key-letters{font-size:9px;font-weight:600;letter-spacing:.05em;color:#94a3b8;margin-top:1px}\n        .kasookoo-ctc-dialer__call{display:flex;align-items:center;justify-content:center;width:56px;height:56px;border-radius:50%;border:none;background:#22c55e;color:#fff;cursor:pointer;transition:background .15s,opacity .15s}\n        .kasookoo-ctc-dialer__call:hover:not(:disabled){background:#16a34a}\n        .kasookoo-ctc-dialer__call:disabled{opacity:.5;cursor:not-allowed}\n    `\n    target.appendChild(style)\n}\n\n/**\n * Renders the widget's built-in full numeric dial pad into `container`.\n * There is no custom-renderer option — this is the only dialer UI the\n * widget ships. `onDial` fires with the number as typed (E.164 recommended,\n * but the widget does not itself validate format — the backend does).\n *\n * Styles are injected into `container`'s root (its `ShadowRoot`, normally —\n * see the custom element — or `document` if mounted directly), so the dial\n * pad never leaks styles into, or picks up styles from, the host page.\n */\nexport function mountDialer(container: HTMLElement, options: DialerOptions): DialerHandle {\n    const styleRoot = (container.getRootNode() as Document | ShadowRoot) ?? document\n    injectStyles(styleRoot)\n\n    const root = document.createElement(\"div\")\n    root.className = \"kasookoo-ctc-dialer\"\n    root.innerHTML = `\n        <div class=\"kasookoo-ctc-dialer__input-row\">\n            <input class=\"kasookoo-ctc-dialer__input\" type=\"tel\" inputmode=\"tel\"\n                placeholder=\"${escapeAttr(options.placeholder ?? \"Enter phone number\")}\"\n                value=\"${escapeAttr((options.defaultCountryCode ?? \"\").replace(ALLOWED_CHARS, \"\"))}\" />\n            <button class=\"kasookoo-ctc-dialer__backspace\" type=\"button\" title=\"Delete\" disabled>${BACKSPACE_ICON}</button>\n        </div>\n        <div class=\"kasookoo-ctc-dialer__pad\"></div>\n        <button class=\"kasookoo-ctc-dialer__call\" type=\"button\" title=\"Call\">${CALL_ICON}</button>\n    `\n    container.appendChild(root)\n\n    const input = root.querySelector<HTMLInputElement>(\".kasookoo-ctc-dialer__input\")!\n    const backspace = root.querySelector<HTMLButtonElement>(\".kasookoo-ctc-dialer__backspace\")!\n    const pad = root.querySelector<HTMLElement>(\".kasookoo-ctc-dialer__pad\")!\n    const callBtn = root.querySelector<HTMLButtonElement>(\".kasookoo-ctc-dialer__call\")!\n\n    const syncBackspace = () => (backspace.disabled = input.value.length === 0)\n\n    KEYS.forEach(({ digit, letters }) => {\n        const key = document.createElement(\"button\")\n        key.type = \"button\"\n        key.className = \"kasookoo-ctc-dialer__key\"\n        key.innerHTML = `<span>${digit}</span>${letters ? `<span class=\"kasookoo-ctc-dialer__key-letters\">${letters}</span>` : \"\"}`\n        key.addEventListener(\"click\", () => {\n            input.value += digit\n            input.focus()\n            syncBackspace()\n        })\n        pad.appendChild(key)\n    })\n\n    backspace.addEventListener(\"click\", () => {\n        input.value = input.value.slice(0, -1)\n        input.focus()\n        syncBackspace()\n    })\n\n    input.addEventListener(\"input\", () => {\n        const sanitized = input.value.replace(ALLOWED_CHARS, \"\")\n        if (sanitized !== input.value) {\n            const caret = input.selectionStart ?? sanitized.length\n            input.value = sanitized\n            input.setSelectionRange(caret - 1, caret - 1)\n        }\n        syncBackspace()\n    })\n    input.addEventListener(\"keydown\", (e) => {\n        if (e.key === \"Enter\") attemptDial()\n    })\n    input.addEventListener(\"paste\", (e) => {\n        e.preventDefault()\n        const pasted = (e.clipboardData?.getData(\"text\") ?? \"\").replace(ALLOWED_CHARS, \"\")\n        const start = input.selectionStart ?? input.value.length\n        const end = input.selectionEnd ?? input.value.length\n        input.value = input.value.slice(0, start) + pasted + input.value.slice(end)\n        input.setSelectionRange(start + pasted.length, start + pasted.length)\n        syncBackspace()\n    })\n\n    const attemptDial = () => {\n        const value = input.value.trim()\n        if (!value || callBtn.disabled) return\n        options.onDial(value)\n    }\n    callBtn.addEventListener(\"click\", attemptDial)\n\n    syncBackspace()\n\n    return {\n        destroy() {\n            root.remove()\n        },\n        setDisabled(disabled: boolean) {\n            callBtn.disabled = disabled\n            input.disabled = disabled\n            pad.querySelectorAll(\"button\").forEach((btn) => (btn.disabled = disabled))\n        },\n    }\n}\n\nfunction escapeAttr(text: string): string {\n    return text.replace(/[&<>\"']/g, (c) => `&#${c.charCodeAt(0)};`)\n}\n","import { mountDialer, type DialerHandle } from \"./dialer\"\n\nexport interface TriggerButtonOptions {\n    /** Presence makes this a \"static\" button showing this number and calling it directly, no dial pad. */\n    fixedNumber?: string\n    /** Static only. Text shown on the button (and in the confirmation modal) instead of the number. */\n    label?: string\n    /** Static only. Show a confirmation modal before dialing. Defaults to `true`. */\n    confirmBeforeCall?: boolean\n    /** Static only. Show a call icon beside the number on hover. Defaults to `true`. */\n    showCallIconOnHover?: boolean\n    /** Called with the number to dial — the fixed number in static mode, or whatever the user typed in dynamic mode. */\n    onDial: (phoneNumber: string) => void\n    /** Prefilled dialing prefix shown in the dial pad, e.g. `\"+1\"`. Dynamic mode only. */\n    defaultCountryCode?: string\n    /** Placeholder text for the dial pad's number input. Dynamic mode only. */\n    placeholder?: string\n    /** Raw CSS injected into this mount's own shadow root — reaches the trigger button, the dial pad, and the confirmation modal. */\n    customCss?: string\n}\n\nexport interface TriggerButtonHandle {\n    /** Removes the button (and any open popup/modal) from the DOM. */\n    destroy(): void\n    /** Disables the trigger and, if open, the dial pad inside it — e.g. while a call is active. */\n    setDisabled(disabled: boolean): void\n}\n\nconst STYLE_ID = \"kasookoo-ctc-trigger-styles\"\nconst CUSTOM_STYLE_ID = \"kasookoo-ctc-custom-styles\"\n\nconst DOTS_ICON = `<svg width=\"22\" height=\"22\" viewBox=\"0 0 24 24\" fill=\"currentColor\" stroke=\"none\"><circle cx=\"5\" cy=\"12\" r=\"2.2\"/><circle cx=\"12\" cy=\"12\" r=\"2.2\"/><circle cx=\"19\" cy=\"12\" r=\"2.2\"/></svg>`\nconst CALL_ICON = `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"currentColor\" stroke=\"none\"><path d=\"M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z\"/></svg>`\n\nfunction injectStyles(root: Document | ShadowRoot): void {\n    const target: ParentNode = root instanceof Document ? root.head : root\n    if (target.querySelector(`#${STYLE_ID}`)) return\n    const style = document.createElement(\"style\")\n    style.id = STYLE_ID\n    style.textContent = `\n        .kasookoo-ctc-trigger-wrap{position:relative;display:inline-block;font-family:system-ui,-apple-system,sans-serif}\n        .kasookoo-ctc-trigger{display:flex;align-items:center;justify-content:center;width:56px;height:56px;border-radius:50%;border:none;background:#7DBAAB;color:#fff;cursor:pointer;box-shadow:0 4px 14px rgba(0,0,0,.2);transition:background .15s,box-shadow .15s,opacity .15s}\n        .kasookoo-ctc-trigger:hover:not(:disabled){background:#6aa998}\n        .kasookoo-ctc-trigger:disabled{opacity:.5;cursor:not-allowed}\n        .kasookoo-ctc-trigger--static{width:auto;height:auto;border-radius:8px;padding:8px 12px;gap:0;background:transparent;color:#1f2933;box-shadow:0 1px 6px rgba(0,0,0,.08);font-size:15px;font-weight:600;white-space:nowrap}\n        .kasookoo-ctc-trigger--static:hover:not(:disabled){background:rgba(0,0,0,.04);box-shadow:0 2px 10px rgba(0,0,0,.12)}\n        .kasookoo-ctc-trigger__number{overflow:hidden}\n        .kasookoo-ctc-trigger__hover-icon{display:inline-flex;align-items:center;justify-content:center;opacity:0;max-width:0;overflow:hidden;transition:opacity .15s ease,max-width .15s ease}\n        .kasookoo-ctc-trigger--static:hover:not(:disabled) .kasookoo-ctc-trigger__hover-icon,\n        .kasookoo-ctc-trigger--static:focus-visible .kasookoo-ctc-trigger__hover-icon{opacity:1;max-width:24px;margin-left:8px}\n        .kasookoo-ctc-trigger-popup{position:absolute;z-index:2147483000}\n        .kasookoo-ctc-trigger-popup--above{bottom:calc(100% + 12px)}\n        .kasookoo-ctc-trigger-popup--below{top:calc(100% + 12px)}\n        .kasookoo-ctc-trigger-popup--right{right:0}\n        .kasookoo-ctc-trigger-popup--left{left:0}\n        .kasookoo-ctc-confirm-overlay{position:fixed;inset:0;z-index:2147483001;display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,.45);font-family:system-ui,-apple-system,sans-serif}\n        .kasookoo-ctc-confirm{width:min(340px,calc(100vw - 48px));background:#fff;border-radius:16px;padding:20px 24px;box-shadow:0 12px 40px rgba(0,0,0,.35)}\n        .kasookoo-ctc-confirm__text{margin:0 0 20px;font-size:14px;line-height:1.5;color:#1f2933}\n        .kasookoo-ctc-confirm__actions{display:flex;justify-content:flex-end;gap:10px}\n        .kasookoo-ctc-confirm__btn{padding:8px 16px;border-radius:10px;border:none;font-size:14px;font-weight:600;cursor:pointer}\n        .kasookoo-ctc-confirm__btn--cancel{background:#f1f5f9;color:#1f2933}\n        .kasookoo-ctc-confirm__btn--confirm{background:#22c55e;color:#fff}\n        .kasookoo-ctc-confirm__btn--confirm:hover{background:#16a34a}\n    `\n    target.appendChild(style)\n}\n\n/**\n * Injects `customCss` verbatim, as the last `<style>` in `root` — later\n * source order wins ties in specificity, so an override using the widget's\n * own class names (`.kasookoo-ctc-trigger`, `.kasookoo-ctc-dialer__call`,\n * ...) beats the built-in styles above without needing `!important`.\n * Re-append this after mounting anything else into the same root (e.g. the\n * dial pad popup opening later) to keep that guarantee.\n */\nfunction applyCustomCss(root: Document | ShadowRoot, css: string | undefined): HTMLStyleElement | null {\n    if (!css) return null\n    const target: ParentNode = root instanceof Document ? root.head : root\n    let style = target.querySelector<HTMLStyleElement>(`#${CUSTOM_STYLE_ID}`)\n    if (!style) {\n        style = document.createElement(\"style\")\n        style.id = CUSTOM_STYLE_ID\n        target.appendChild(style)\n    } else {\n        target.appendChild(style) // move to the end\n    }\n    style.textContent = css\n    return style\n}\n\n/** Strips everything but digits and a leading `+` — what's actually dialed, independent of how the number is displayed. */\nfunction sanitizePhoneNumber(raw: string): string {\n    return raw.replace(/[^0-9+]/g, \"\")\n}\n\n/**\n * Shown before a static button dials. Resolves `true` on confirm, `false` on\n * cancel/dismiss. `root` can't be appended to directly when it's the\n * `Document` itself — a document may only ever have one root element — so a\n * plain `document` falls back to `document.body`, same as any other\n * page-level overlay.\n */\nfunction showConfirmModal(root: Document | ShadowRoot, phoneNumber: string): Promise<boolean> {\n    const mountTarget: ParentNode = root instanceof Document ? root.body : root\n    return new Promise((resolve) => {\n        const overlay = document.createElement(\"div\")\n        overlay.className = \"kasookoo-ctc-confirm-overlay\"\n        overlay.innerHTML = `\n            <div class=\"kasookoo-ctc-confirm\" role=\"alertdialog\" aria-modal=\"true\">\n                <p class=\"kasookoo-ctc-confirm__text\">Are you sure you want to call <strong>${escapeHtml(phoneNumber)}</strong>?</p>\n                <div class=\"kasookoo-ctc-confirm__actions\">\n                    <button class=\"kasookoo-ctc-confirm__btn kasookoo-ctc-confirm__btn--cancel\">Cancel</button>\n                    <button class=\"kasookoo-ctc-confirm__btn kasookoo-ctc-confirm__btn--confirm\">Call</button>\n                </div>\n            </div>`\n        mountTarget.appendChild(overlay)\n\n        const close = (answer: boolean) => {\n            overlay.remove()\n            resolve(answer)\n        }\n        overlay.querySelector(\".kasookoo-ctc-confirm__btn--cancel\")!.addEventListener(\"click\", () => close(false))\n        overlay.querySelector(\".kasookoo-ctc-confirm__btn--confirm\")!.addEventListener(\"click\", () => close(true))\n        overlay.addEventListener(\"click\", (e) => {\n            if (e.target === overlay) close(false)\n        })\n    })\n}\n\n/**\n * Renders the widget's trigger button into `container`. With `fixedNumber`\n * set, it shows that number as a static button that dials it directly\n * (optionally behind a confirmation modal, with a call icon appearing on\n * hover); otherwise it shows a dots icon that opens a popup with the full\n * dial pad.\n */\nexport function mountTriggerButton(container: HTMLElement, options: TriggerButtonOptions): TriggerButtonHandle {\n    const styleRoot = (container.getRootNode() as Document | ShadowRoot) ?? document\n    injectStyles(styleRoot)\n    applyCustomCss(styleRoot, options.customCss)\n\n    const isStatic = !!options.fixedNumber?.trim()\n    const confirmBeforeCall = options.confirmBeforeCall ?? true\n    const showHoverIcon = options.showCallIconOnHover ?? true\n    const displayText = options.label?.trim() || options.fixedNumber?.trim() || \"\"\n    const dialTarget = isStatic ? sanitizePhoneNumber(options.fixedNumber!.trim()) : \"\"\n\n    const wrap = document.createElement(\"div\")\n    wrap.className = \"kasookoo-ctc-trigger-wrap\"\n\n    const button = document.createElement(\"button\")\n    button.type = \"button\"\n    button.className = isStatic ? \"kasookoo-ctc-trigger kasookoo-ctc-trigger--static\" : \"kasookoo-ctc-trigger\"\n    button.title = isStatic ? `Call ${displayText}` : \"Open dial pad\"\n    button.innerHTML = isStatic\n        ? `<span class=\"kasookoo-ctc-trigger__number\">${escapeHtml(displayText)}</span>${\n              showHoverIcon ? `<span class=\"kasookoo-ctc-trigger__hover-icon\">${CALL_ICON}</span>` : \"\"\n          }`\n        : DOTS_ICON\n\n    wrap.appendChild(button)\n    container.appendChild(wrap)\n\n    let popupEl: HTMLElement | null = null\n    let dialerHandle: DialerHandle | null = null\n    let disabled = false\n\n    const closePopup = () => {\n        dialerHandle?.destroy()\n        dialerHandle = null\n        popupEl?.remove()\n        popupEl = null\n        document.removeEventListener(\"click\", onOutsideClick, true)\n    }\n\n    // Not e.target: a click inside a shadow root (this popup lives in one)\n    // is retargeted to the shadow host for listeners outside it, so\n    // wrap.contains(e.target) is always false and \"outside click\" would\n    // fire for every click anywhere inside the dial pad. composedPath()\n    // isn't retargeted — it lists the real originating node.\n    const onOutsideClick = (e: MouseEvent) => {\n        if (popupEl && !e.composedPath().includes(wrap)) closePopup()\n    }\n\n    // Roughly the dial pad's rendered size (see dialer.ts's styles) — used\n    // only to decide which side has room, not for exact layout.\n    const ESTIMATED_POPUP_HEIGHT = 400\n    const ESTIMATED_POPUP_WIDTH = 260\n\n    const openPopup = () => {\n        if (popupEl) return\n        popupEl = document.createElement(\"div\")\n        const rect = button.getBoundingClientRect()\n        const opensBelow = rect.top < ESTIMATED_POPUP_HEIGHT\n        const opensLeft = rect.right - ESTIMATED_POPUP_WIDTH < 0\n        popupEl.className = [\n            \"kasookoo-ctc-trigger-popup\",\n            opensBelow ? \"kasookoo-ctc-trigger-popup--below\" : \"kasookoo-ctc-trigger-popup--above\",\n            opensLeft ? \"kasookoo-ctc-trigger-popup--left\" : \"kasookoo-ctc-trigger-popup--right\",\n        ].join(\" \")\n        wrap.appendChild(popupEl)\n\n        dialerHandle = mountDialer(popupEl, {\n            onDial: (phoneNumber) => {\n                closePopup()\n                options.onDial(phoneNumber)\n            },\n            defaultCountryCode: options.defaultCountryCode,\n            placeholder: options.placeholder,\n        })\n        dialerHandle.setDisabled(disabled)\n        // The dial pad's own stylesheet was just injected into the same\n        // root — keep the custom override last so it still wins ties.\n        applyCustomCss(styleRoot, options.customCss)\n\n        // Deferred one tick so the click that opened the popup doesn't\n        // immediately close it via this same listener.\n        setTimeout(() => document.addEventListener(\"click\", onOutsideClick, true), 0)\n    }\n\n    const placeStaticCall = async () => {\n        if (confirmBeforeCall) {\n            const confirmed = await showConfirmModal(styleRoot, displayText)\n            if (!confirmed) return\n        }\n        options.onDial(dialTarget)\n    }\n\n    button.addEventListener(\"click\", () => {\n        if (disabled) return\n        if (isStatic) {\n            void placeStaticCall()\n            return\n        }\n        if (popupEl) closePopup()\n        else openPopup()\n    })\n\n    return {\n        destroy() {\n            closePopup()\n            wrap.remove()\n        },\n        setDisabled(value: boolean) {\n            disabled = value\n            button.disabled = value\n            dialerHandle?.setDisabled(value)\n        },\n    }\n}\n\nfunction escapeHtml(text: string): string {\n    return text.replace(/[&<>\"']/g, (c) => `&#${c.charCodeAt(0)};`)\n}\n","import { SessionManager } from \"./services/session/session\"\nimport { CallsManager } from \"./services/calls/calls\"\nimport type { Call } from \"./services/calls/call\"\nimport { TypedEmitter } from \"./core/events\"\nimport { requestMicPermissions } from \"./core/permissions\"\nimport { configureLogger, getLogger } from \"./core/logger\"\nimport { initKasookooTelemetry, startCallSpan } from \"./core/telemetry\"\nimport { endDiagnosticsSpan, logError, logEvent, setDiagnosticsSpan } from \"./core/diagnostics\"\nimport { mountTriggerButton, type TriggerButtonHandle } from \"./ui/trigger-button\"\nimport {\n    KasookooError,\n    type DialParams,\n    type KasookooClickToCallConfig,\n    type KasookooWidgetEvents,\n    type SessionInfo,\n} from \"./types\"\n\nconst DEFAULT_BASE_URL = \"https://sdk-test.kasookoo.ai\"\nconst bootstrapLogger = getLogger(\"kasookoo-click-to-call.widget\")\n\n// A <kasookoo-dialer> tag upgrades — and calls getInstance() — the instant\n// the custom element is registered, which happens as soon as this package's\n// side-effect import runs. That can happen before a later init() call in the\n// very same script even executes, so getInstance() can't just check whether\n// init() has already been called — it has to be able to wait for one that's\n// about to be. NOT_INITIALIZED_TIMEOUT_MS is the longest it'll wait for that\n// before giving up and surfacing a real \"you forgot to call init()\" error.\nconst NOT_INITIALIZED_TIMEOUT_MS = 8000\n\ninterface InstanceWaiter {\n    resolve: (widget: WidgetCore) => void\n    reject: (err: KasookooError) => void\n}\n\n/** @internal — WidgetCore.mount() options. Not part of the public API; use `<kasookoo-dialer>` instead. */\nexport interface MountOptions {\n    /** Presence makes this mount a \"static\" button that calls this number directly, skipping the dial pad. */\n    fixedNumber?: string\n    /** Static (`fixedNumber`) mounts only. Shown on the button, confirmation modal and call window instead of the number. */\n    label?: string\n    /** Static (`fixedNumber`) mounts only. Show a confirmation modal before dialing. Defaults to `true`. */\n    confirmBeforeCall?: boolean\n    /** Static (`fixedNumber`) mounts only. Show a call icon beside the number on hover. Defaults to `true`. */\n    showCallIconOnHover?: boolean\n    /** Display name for the caller on calls placed from this mount. Defaults to the `subject` given to `init()`. */\n    participantName?: string\n    /** Prefilled dialing prefix shown in the dial pad, e.g. `\"+1\"`. Dynamic mounts only. */\n    defaultCountryCode?: string\n    /** Placeholder text for the dial pad's number input. Dynamic mounts only. */\n    placeholder?: string\n    /**\n     * Raw CSS injected alongside this mount's own styles — reaches the\n     * trigger button, the dial pad, and (static mounts) the confirmation\n     * modal, all scoped to `container`'s own shadow root. It does not reach\n     * the floating in-call window, which is shared page-level UI.\n     */\n    customCss?: string\n}\n\n/**\n * @internal Full widget implementation — session, calls, and trigger-button\n * mounting/disabling. Not exported from the package's public entry point:\n * `<kasookoo-dialer>` (see element.ts) is the only supported way to place a\n * button on the page and is the sole consumer of `mount()`/`.on()`. Host\n * apps get the rest (`dial()`/`close()`/`session`/`activeCall`) through the\n * public `KasookooClickToCall` facade below.\n */\nexport class WidgetCore extends TypedEmitter<KasookooWidgetEvents> {\n    // Every event the widget raises is also recorded, so a failure the host\n    // page never wired a listener for still leaves a trace behind.\n    protected override emit<K extends keyof KasookooWidgetEvents>(event: K, payload: KasookooWidgetEvents[K]): void {\n        switch (event) {\n            case \"error\":\n                logError(\"widget_error\", payload)\n                break\n            case \"session:created\":\n            case \"session:refreshed\": {\n                const info = payload as SessionInfo\n                logEvent(\"info\", event === \"session:created\" ? \"session_created\" : \"session_refreshed\", {\n                    session_id: info.sessionId,\n                    expires_at: info.expiresAt,\n                })\n                break\n            }\n            case \"session:expired\":\n                logEvent(\"warn\", \"session_expired\", { reason: (payload as { reason: string }).reason })\n                break\n        }\n        super.emit(event, payload)\n    }\n\n    private static sharedInitPromise: Promise<WidgetCore> | null = null\n    private static sharedInitKey: string | null = null\n    private static instanceWaiters: InstanceWaiter[] = []\n\n    private sessions: SessionManager | null = null\n    private calls: CallsManager | null = null\n    private readonly mountHandles = new Set<TriggerButtonHandle>()\n    private destroyed = false\n\n    private constructor() {\n        super()\n    }\n\n    /**\n     * Initializes the widget: requests microphone permission and establishes\n     * a backend session. **Idempotent** — call it as many times as you like;\n     * only the first call's config is used, and every call resolves to the\n     * same shared instance. Throws if the first call's setup fails — mic\n     * permission denied, network error, invalid config, or an invalid\n     * publishable key. A failed attempt does not stick — the next `init()`\n     * call tries again from scratch.\n     */\n    static init(config: KasookooClickToCallConfig): Promise<WidgetCore> {\n        if (WidgetCore.sharedInitPromise) {\n            const key = `${config?.publishableKey} ${config?.subject}`\n            if (WidgetCore.sharedInitKey !== null && WidgetCore.sharedInitKey !== key) {\n                bootstrapLogger.warn({\n                    msg: \"init_called_again_with_different_config\",\n                    event: \"init_called_again_with_different_config\",\n                })\n            }\n            return WidgetCore.sharedInitPromise\n        }\n\n        WidgetCore.sharedInitKey = `${config?.publishableKey} ${config?.subject}`\n        WidgetCore.sharedInitPromise = WidgetCore.create(config).then(\n            (widget) => {\n                endDiagnosticsSpan()\n                WidgetCore.instanceWaiters.splice(0).forEach((waiter) => waiter.resolve(widget))\n                return widget\n            },\n            (err) => {\n                logError(\"init_failed\", err)\n                endDiagnosticsSpan(err)\n                // A failed attempt must not stick — let the next init() call retry from scratch.\n                WidgetCore.sharedInitPromise = null\n                WidgetCore.sharedInitKey = null\n                const error =\n                    err instanceof KasookooError\n                        ? err\n                        : new KasookooError(\"init_failed\", \"KasookooClickToCall.init() failed\", { details: err })\n                WidgetCore.instanceWaiters.splice(0).forEach((waiter) => waiter.reject(error))\n                throw err\n            }\n        )\n        return WidgetCore.sharedInitPromise\n    }\n\n    /**\n     * @internal Used by `<kasookoo-dialer>` to get the shared widget. A tag\n     * upgrades — and calls this — the instant the custom element is\n     * registered, which can happen before a same-script `init()` call further\n     * down even runs, so this can't just check whether `init()` has already\n     * been called: if it hasn't, it waits for one to happen, up to\n     * `NOT_INITIALIZED_TIMEOUT_MS`, before giving up with `not_initialized`.\n     */\n    static getInstance(): Promise<WidgetCore> {\n        if (WidgetCore.sharedInitPromise) return WidgetCore.sharedInitPromise\n\n        return new Promise((resolve, reject) => {\n            const waiter: InstanceWaiter = {\n                resolve: (widget) => {\n                    clearTimeout(timer)\n                    resolve(widget)\n                },\n                reject: (err) => {\n                    clearTimeout(timer)\n                    reject(err)\n                },\n            }\n            const timer = setTimeout(() => {\n                const idx = WidgetCore.instanceWaiters.indexOf(waiter)\n                if (idx !== -1) WidgetCore.instanceWaiters.splice(idx, 1)\n                reject(\n                    new KasookooError(\n                        \"not_initialized\",\n                        \"Call KasookooClickToCall.init() once, before mounting any <kasookoo-dialer> tags.\"\n                    )\n                )\n            }, NOT_INITIALIZED_TIMEOUT_MS)\n            WidgetCore.instanceWaiters.push(waiter)\n        })\n    }\n\n    private static async create(config: KasookooClickToCallConfig): Promise<WidgetCore> {\n        if (!config?.publishableKey) {\n            throw new KasookooError(\"invalid_config\", \"`publishableKey` is required\")\n        }\n        if (!config?.subject) {\n            throw new KasookooError(\"invalid_config\", \"`subject` is required\")\n        }\n        const intentUrl = typeof config.intentEndpoint === \"string\" ? config.intentEndpoint : config.intentEndpoint?.url\n        if (!intentUrl?.trim()) {\n            throw new KasookooError(\n                \"invalid_config\",\n                \"`intentEndpoint` is required — your call-intent endpoint (see kasookoo-server-sdk), either as a URL string or a `{ url, headers?, credentials?, body? }` object. The widget POSTs { phoneNumber } (or your `body` override) there before every call and reads the response for an intent id and client secret.\"\n            )\n        }\n        if (\n            config.callRingTimeoutMs !== undefined &&\n            config.callRingTimeoutMs !== false &&\n            (typeof config.callRingTimeoutMs !== \"number\" || config.callRingTimeoutMs <= 0)\n        ) {\n            throw new KasookooError(\n                \"invalid_config\",\n                \"`callRingTimeoutMs` must be a positive number of milliseconds, or `false` to disable it\"\n            )\n        }\n\n        const widget = new WidgetCore()\n        const baseUrl = (config.baseUrl?.trim() || DEFAULT_BASE_URL).replace(/\\/+$/, \"\")\n\n        configureLogger({\n            enabled: config.logging?.enabled,\n            level: config.logging?.level,\n            service: config.logging?.service,\n            host: config.logging?.host,\n        })\n\n        bootstrapLogger.info({\n            msg: \"logging_configured\",\n            event: \"logging_configured\",\n            base_url: baseUrl,\n            logging_enabled: config.logging?.enabled ?? true,\n        })\n\n        // Always on when the optional @opentelemetry/* peer packages are\n        // installed — there is no opt-out. Silent (no \"packages not installed\" warning) unless the\n        // host wrote a `telemetry` config at all, since for most consumers\n        // \"packages absent\" is just the normal off state, not a mistake.\n        await initKasookooTelemetry(\n            {\n                endpoint: config.telemetry?.endpoint,\n                logsEndpoint: config.telemetry?.logsEndpoint,\n                serviceName: config.telemetry?.serviceName,\n                environment: config.telemetry?.environment,\n            },\n            { silent: config.telemetry === undefined }\n        )\n\n        // One span for the whole init, so its steps read as a single trace.\n        // Ended by `init()`.\n        setDiagnosticsSpan(await startCallSpan(\"widget_init\", { feature_type: \"widget_init\" }))\n\n        // Asked only now, after telemetry is up, so a denied microphone\n        // prompt is recorded rather than lost.\n        await requestMicPermissions()\n\n        widget.sessions = new SessionManager({\n            baseUrl,\n            publishableKey: config.publishableKey,\n            subject: config.subject,\n            onCreated: (info) => widget.emit(\"session:created\", info),\n            onRefreshed: (info) => widget.emit(\"session:refreshed\", info),\n            onExpired: (reason) => widget.emit(\"session:expired\", { reason }),\n            onError: (error) => widget.emit(\"error\", error),\n        })\n        await widget.sessions.start()\n\n        widget.calls = new CallsManager({\n            baseUrl,\n            getToken: () => widget.sessions!.getToken(),\n            subject: config.subject,\n            ringTimeoutMs: config.callRingTimeoutMs,\n            intentEndpoint: config.intentEndpoint,\n            onError: (error) => widget.emit(\"error\", error),\n        })\n\n        return widget\n    }\n\n    /** Current session info, or `null` if the widget is not initialized. */\n    get session(): SessionInfo | null {\n        return this.sessions?.getInfo() ?? null\n    }\n\n    private isScopeGranted(scope: string): boolean {\n        return this.sessions?.getAllowedScopes().includes(scope) ?? false\n    }\n\n    private assertSipConfigured(): void {\n        if (!this.isScopeGranted(\"sip_calling\")) {\n            throw new KasookooError(\n                \"missing_scope\",\n                \"This publishable key's session is not granted the `sip_calling` capability\"\n            )\n        }\n    }\n\n    /**\n     * Mounts a trigger button into `container`. Every mount shares this same\n     * widget instance's session and active-call state — placing a call from\n     * one disables every other mounted trigger (anywhere on the page) until\n     * it ends. Call this as many times as you have places to put a button;\n     * each call is independent and returns its own handle to unmount later.\n     *\n     * With `fixedNumber` set, the button shows that number and calls it\n     * directly (a \"static\" button); otherwise it opens the full dial pad (a\n     * \"dynamic\" button).\n     */\n    mount(container: HTMLElement, options: MountOptions = {}): TriggerButtonHandle {\n        if (!container) {\n            throw new KasookooError(\"invalid_params\", \"`container` is required\")\n        }\n\n        const handle = mountTriggerButton(container, {\n            fixedNumber: options.fixedNumber,\n            label: options.label,\n            confirmBeforeCall: options.confirmBeforeCall,\n            showCallIconOnHover: options.showCallIconOnHover,\n            customCss: options.customCss,\n            onDial: (phoneNumber) => {\n                void this.dial({\n                    phoneNumber,\n                    participantName: options.participantName,\n                    label: options.fixedNumber?.trim() ? options.label?.trim() || undefined : undefined,\n                }).catch((err) => {\n                    this.emit(\n                        \"error\",\n                        err instanceof KasookooError\n                            ? err\n                            : new KasookooError(\"call_start_failed\", \"Failed to start the call\", { details: err })\n                    )\n                })\n            },\n            defaultCountryCode: options.defaultCountryCode,\n            placeholder: options.placeholder,\n        })\n        this.mountHandles.add(handle)\n\n        const syncDisabled = () => handle.setDisabled(this.activeCall !== null)\n        syncDisabled()\n        const offCallStarted = this.on(\"call:started\", (call) => {\n            syncDisabled()\n            call.on(\"state\", syncDisabled)\n        })\n\n        return {\n            destroy: () => {\n                offCallStarted()\n                this.mountHandles.delete(handle)\n                handle.destroy()\n            },\n            setDisabled: (disabled) => handle.setDisabled(disabled),\n        }\n    }\n\n    /**\n     * Places a call to an external phone number directly, without any\n     * trigger button UI — for a number only known at runtime. Shares the\n     * same active-call rule as every mounted button: throws\n     * `call_in_progress` if another call (from anywhere) is already active.\n     */\n    async dial(params: DialParams): Promise<Call> {\n        if (!this.calls) {\n            throw new KasookooError(\n                \"not_initialized\",\n                \"Widget is not initialized. Call KasookooClickToCall.init() and wait for it to resolve.\"\n            )\n        }\n        try {\n            this.assertSipConfigured()\n            const call = await this.calls.dial(params)\n            this.emit(\"call:started\", call)\n            return call\n        } catch (err) {\n            logError(\"dial_failed\", err)\n            throw err\n        }\n    }\n\n    /** The call currently connecting/connected, if any. */\n    get activeCall(): Call | null {\n        return this.calls?.getActiveCall() ?? null\n    }\n\n    /**\n     * Tears down the widget: removes every mounted trigger button, clears\n     * the session. Safe to call more than once; this instance cannot be\n     * reused afterward — a later `init()` call creates a fresh one.\n     *\n     * Throws `call_in_progress` if a call is currently active — end it first.\n     */\n    close(): void {\n        if (this.destroyed) return\n        if (this.activeCall !== null) {\n            throw new KasookooError(\"call_in_progress\", \"Another call is already active. End it first.\")\n        }\n        this.destroyed = true\n        this.mountHandles.forEach((handle) => handle.destroy())\n        this.mountHandles.clear()\n        this.calls?.close()\n        this.sessions?.close()\n        this.removeAllListeners()\n        if (WidgetCore.sharedInitPromise) {\n            // Let a later init() call start over instead of forever resolving to this closed instance.\n            void WidgetCore.sharedInitPromise.then((instance) => {\n                if (instance === this) {\n                    WidgetCore.sharedInitPromise = null\n                    WidgetCore.sharedInitKey = null\n                }\n            })\n        }\n    }\n}\n\n/**\n * @internal Used only by `<kasookoo-dialer>` to reach `mount()`/`dial()`/\n * `.on()` — not part of the public API. A real user click on a rendered\n * `<kasookoo-dialer>` tag is the only way to place a call; host apps get\n * `close()`/`session`/`activeCall` through the public `KasookooClickToCall`\n * facade instead.\n */\nexport function getInternalWidget(): Promise<WidgetCore> {\n    return WidgetCore.getInstance()\n}\n\nconst facades = new WeakMap<WidgetCore, KasookooClickToCall>()\n\n/**\n * Entry point of the Kasookoo click-to-call widget — a built-in dial pad and\n * call window for placing outbound calls to phone numbers over WebRTC.\n * Framework-agnostic: works the same in a plain script tag, React, Angular,\n * or Vue, since it only ever touches the DOM element you hand it.\n *\n * `init()` is a **singleton** — call it once, at app startup, before any\n * `<kasookoo-dialer>` tags render. Every `<kasookoo-dialer>` tag on the page\n * shares the one session and the one active-call state this creates; a\n * second call is placed nowhere, it just throws `call_in_progress`.\n *\n * ```ts\n * import { KasookooClickToCall } from \"kasookoo-click-to-call-widget\"\n *\n * await KasookooClickToCall.init({\n *     publishableKey: \"pk_live_...\",\n *     subject: \"Website visitor\",\n * })\n * ```\n */\nexport class KasookooClickToCall {\n    readonly #core: WidgetCore\n\n    private constructor(core: WidgetCore) {\n        this.#core = core\n    }\n\n    /**\n     * Initializes the widget: requests microphone permission and establishes\n     * a backend session. **Idempotent** — call it as many times as you like\n     * (e.g. once per component that needs the widget); only the first call's\n     * config is used, and every call resolves to the same shared instance.\n     * Throws if the first call's setup fails — mic permission denied,\n     * network error, invalid config, or an invalid publishable key. A failed\n     * attempt does not stick — the next `init()` call tries again from\n     * scratch.\n     */\n    static async init(config: KasookooClickToCallConfig): Promise<KasookooClickToCall> {\n        const core = await WidgetCore.init(config)\n        let facade = facades.get(core)\n        if (!facade) {\n            facade = new KasookooClickToCall(core)\n            facades.set(core, facade)\n        }\n        return facade\n    }\n\n    /** Current session info, or `null` if the widget is not initialized. */\n    get session(): SessionInfo | null {\n        return this.#core.session\n    }\n\n    /** The call currently connecting/connected, if any. */\n    get activeCall(): Call | null {\n        return this.#core.activeCall\n    }\n\n    /**\n     * Tears down the widget: removes every mounted `<kasookoo-dialer>`\n     * trigger button, clears the session. Safe to call more than once; this\n     * instance cannot be reused afterward — a later `init()` call creates a\n     * fresh one.\n     *\n     * Throws `call_in_progress` if a call is currently active — end it first.\n     */\n    close(): void {\n        this.#core.close()\n    }\n}\n","import { getInternalWidget, type WidgetCore } from \"./widget\"\nimport { KasookooError } from \"./types\"\nimport type { TriggerButtonHandle } from \"./ui/trigger-button\"\n\nexport interface KasookooDialerConfig {\n    participantName?: string\n    /** Prefilled dialing prefix shown in the dial pad, e.g. `\"+1\"`. Ignored when `fixed-number` is set. */\n    defaultCountryCode?: string\n    placeholder?: string\n    customCss?: string\n}\n\nconst OBSERVED_ATTRIBUTES = [\"fixed-number\", \"label\", \"confirm-before-call\", \"show-call-icon-on-hover\"] as const\n\nfunction errorDetail(err: unknown): { code: string; message: string } {\n    if (err instanceof KasookooError) return { code: err.code, message: err.message }\n    return { code: \"unknown_error\", message: err instanceof Error ? err.message : String(err) }\n}\n\nfunction readBooleanAttribute(el: Element, name: string, defaultValue: boolean): boolean {\n    const value = el.getAttribute(name)\n    if (value === null) return defaultValue\n    return value !== \"false\"\n}\nexport class KasookooDialerElement extends HTMLElement {\n    static get observedAttributes(): readonly string[] {\n        return OBSERVED_ATTRIBUTES\n    }\n\n    private readonly mountPoint: HTMLElement\n    private mountHandle: TriggerButtonHandle | null = null\n    private widget: WidgetCore | null = null\n    private readonly unsubscribers: Array<() => void> = []\n    private starting = false\n    private started = false\n    private _config: KasookooDialerConfig = {}\n\n    constructor() {\n        super()\n        const shadow = this.attachShadow({ mode: \"open\" })\n        this.mountPoint = document.createElement(\"div\")\n        shadow.appendChild(this.mountPoint)\n    }\n\n    get config(): KasookooDialerConfig {\n        return this._config\n    }\n\n    set config(value: KasookooDialerConfig) {\n        this._config = value ?? {}\n        if (this.started) this.remountButton()\n    }\n\n    dial(phoneNumber?: string): void {\n        const fixedNumber = this.getAttribute(\"fixed-number\")?.trim()\n        const target = fixedNumber || phoneNumber\n        const label = fixedNumber ? this.getAttribute(\"label\")?.trim() || undefined : undefined\n        if (!target) {\n            this.dispatchEvent(\n                new CustomEvent(\"call-error\", {\n                    detail: { code: \"invalid_params\", message: \"`phoneNumber` is required when `fixed-number` is not set\" },\n                })\n            )\n            return\n        }\n        this.placeCall(target, label)\n    }\n\n    private placeCall(phoneNumber: string, label?: string): void {\n        getInternalWidget()\n            .then((widget) => widget.dial({ phoneNumber, participantName: this._config.participantName, label }))\n            .catch((err) => this.dispatchEvent(new CustomEvent(\"call-error\", { detail: errorDetail(err) })))\n    }\n\n    connectedCallback(): void {\n        void this.start()\n    }\n\n    disconnectedCallback(): void {\n        this.mountHandle?.destroy()\n        this.mountHandle = null\n        this.unsubscribers.splice(0).forEach((off) => off())\n        this.widget = null\n        this.started = false\n    }\n\n    attributeChangedCallback(): void {\n        if (this.started) this.remountButton()\n    }\n\n    private remountButton(): void {\n        if (!this.widget) return\n        this.mountHandle?.destroy()\n        this.mountHandle = this.mountTriggerButton(this.widget)\n    }\n\n    private mountTriggerButton(widget: WidgetCore): TriggerButtonHandle {\n        return widget.mount(this.mountPoint, {\n            fixedNumber: this.getAttribute(\"fixed-number\")?.trim() || undefined,\n            label: this.getAttribute(\"fixed-number\")?.trim() ? this.getAttribute(\"label\")?.trim() || undefined : undefined,\n            confirmBeforeCall: readBooleanAttribute(this, \"confirm-before-call\", true),\n            showCallIconOnHover: readBooleanAttribute(this, \"show-call-icon-on-hover\", true),\n            participantName: this._config.participantName,\n            defaultCountryCode: this._config.defaultCountryCode,\n            placeholder: this._config.placeholder,\n            customCss: this._config.customCss,\n        })\n    }\n\n    private async start(): Promise<void> {\n        if (this.starting || this.started) return\n        this.starting = true\n        try {\n            const widget = await getInternalWidget()\n            this.widget = widget\n            this.started = true\n\n            this.mountHandle = this.mountTriggerButton(widget)\n\n            this.unsubscribers.push(\n                widget.on(\"session:expired\", (info) => {\n                    this.dispatchEvent(new CustomEvent(\"session-expired\", { detail: info }))\n                }),\n                widget.on(\"error\", (err) => {\n                    this.dispatchEvent(new CustomEvent(\"call-error\", { detail: errorDetail(err) }))\n                }),\n                widget.on(\"call:started\", (call) => {\n                    const detail = () => ({ state: call.state, phoneNumber: call.remote.name, ...(call.remote.label ? { label: call.remote.label } : {}) })\n                    this.dispatchEvent(new CustomEvent(\"call-state\", { detail: detail() }))\n                    call.on(\"state\", () => this.dispatchEvent(new CustomEvent(\"call-state\", { detail: detail() })))\n                    call.on(\"error\", (err) => this.dispatchEvent(new CustomEvent(\"call-error\", { detail: errorDetail(err) })))\n                })\n            )\n        } catch (err) {\n            this.dispatchEvent(new CustomEvent(\"call-error\", { detail: errorDetail(err) }))\n        } finally {\n            this.starting = false\n        }\n    }\n}\n\nexport function registerKasookooDialer(tagName = \"kasookoo-dialer\"): void {\n    if (typeof customElements === \"undefined\") return\n    if (!customElements.get(tagName)) {\n        customElements.define(tagName, KasookooDialerElement)\n    }\n}\n"],"mappings":"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","names":["elapsed","config","request","STYLE_ID","injectStyles","STYLE_ID","CALL_ICON","injectStyles","escapeHtml","config"]}