@touchcastllc/napster-companion-api-dev 1.6.0-alpha.8 → 2.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -56,6 +56,59 @@ No bundler? Drop in the standalone build with a `<script>` tag — styles are in
56
56
  </script>
57
57
  ```
58
58
 
59
+ ### Branding
60
+
61
+ Give the widget your own accent color with `style.accentColor` — it replaces
62
+ the default pink everywhere the SDK uses one brand hue: the mic button, the
63
+ microphone-recovery card, and the connecting/loading animation.
64
+
65
+ ```js
66
+ await napsterCompanionApiSDK.init(() => fetchConnectionToken(), {
67
+ style: {
68
+ view: "round",
69
+ accentColor: "#0091ff",
70
+ },
71
+ });
72
+ ```
73
+
74
+ Update it later at runtime the same way you switch `view`:
75
+
76
+ ```js
77
+ widget.updateStyle({ accentColor: "#0091ff" });
78
+ ```
79
+
80
+ ### Silhouette view & green screen
81
+
82
+ `style.view: "silhouette"` cuts the avatar out of its background — but the SDK
83
+ does that with a plain color-based chroma-key, not real segmentation: it strips
84
+ whatever pixels fall in a green range from the video, nothing smarter. Two things have
85
+ to be true for it to actually produce a cutout:
86
+
87
+ - `features.backgroundRemoval.enabled` must be `true`. It is by default — only turn it
88
+ off if you deliberately want silhouette's shape/loading conventions without the
89
+ per-frame chroma-key pass.
90
+ - The video itself has to actually be a green-screen feed. If it isn't, you get a raw,
91
+ unprocessed rectangle instead of a cutout — silently, no error.
92
+
93
+ Whether the feed *is* green-screen depends on how you mint the connection token, and
94
+ the two connection flows handle it differently:
95
+
96
+ ```js
97
+ // Companion-based connections (POST /public/connections) — a per-request field:
98
+ {
99
+ providerConfig: {
100
+ // ...
101
+ useGreenVideo: true,
102
+ },
103
+ }
104
+ ```
105
+
106
+ Agent-based connections (`POST /public/agents/{agentId}/connections`) don't accept this
107
+ field at all. Green screen there is a property of the agent's own WebRTC channel, set
108
+ once ahead of time in the CMS's channel editor — there is no client-side override. If
109
+ that agent's channel doesn't have it enabled, silhouette will never produce a cutout for
110
+ it, no matter what the SDK config says.
111
+
59
112
  ### Click-to-start
60
113
 
61
114
  By default `init()` connects immediately. To show an entry point and connect on
@@ -80,6 +133,11 @@ widget.end(); // back to idle; the entry point reappears and can start another s
80
133
  `start()` never throws — a failed attempt is reported through your `onError` callback
81
134
  and the entry point returns to idle, so there is nothing to catch around it.
82
135
 
136
+ `agent.photoUrl` isn't just the entry card's photo — it's the only source of a
137
+ companion photo anywhere in the widget (the loading/ready-audio placeholder and the
138
+ video poster included). Omit it and every one of those falls back to a bundled
139
+ generic icon/gradient instead.
140
+
83
141
  The controller return type is selected from the config **literal**:
84
142
 
85
143
  ```ts
@@ -1,8 +1,8 @@
1
- import "./Button.css";
1
+ import { type EntryPointCardElements } from "../components/Avatar/EntryPoint";
2
2
  export interface ButtonElementOptions {
3
3
  label: string;
4
4
  avatarUrl?: string;
5
5
  description?: string;
6
6
  onClick: () => void;
7
7
  }
8
- export declare function createButtonElement(options: ButtonElementOptions): HTMLButtonElement;
8
+ export declare function createButtonElement(options: ButtonElementOptions): EntryPointCardElements;
@@ -2,7 +2,15 @@ import type { NapsterCompanionApiConfig, NapsterCompanionApiController, NapsterC
2
2
  export interface ButtonSessionDeps {
3
3
  /** The SDK-owned root the card mounts into. */
4
4
  root: HTMLElement;
5
- /** Run one session attempt: epoch, mic gate, mint, connect. Resolves when connected. */
5
+ /**
6
+ * Run one session attempt: epoch, mic gate, mint, connect. Resolves when
7
+ * connected.
8
+ *
9
+ * Contract: must synchronously dispatch some non-"entry" SessionStatus
10
+ * before its promise's async work yields control elsewhere — otherwise the
11
+ * trigger stays clickable ("idle") while an attempt is already underway.
12
+ * A future host-provided implementation must uphold this too.
13
+ */
6
14
  startSession: () => Promise<NapsterCompanionApiInstance>;
7
15
  /** End the live session but keep the root and trigger mounted. */
8
16
  endSession: () => void;
@@ -41,5 +49,28 @@ export interface ButtonSessionDeps {
41
49
  * idle and must NOT report through `onError`.
42
50
  */
43
51
  onSessionEnded: (handler: () => void) => () => void;
52
+ /**
53
+ * Register a handler for an attempt abandoned at the microphone permission
54
+ * prompt: the native prompt went unanswered for 30s and the mic gate
55
+ * collapsed the attempt back to the entry point (first try or a "Check
56
+ * again" retry). Returns an unsubscribe.
57
+ *
58
+ * Needed because `startSession()` resolves with an instance for EVERY gate
59
+ * outcome — it resolves when the gate settles, not when a connection comes
60
+ * up — so a dismissed attempt still hands back a full, live-looking
61
+ * instance that nothing ever connected. Without this channel that fake
62
+ * instance gets latched, and `start()`'s `if (instance) return instance`
63
+ * re-entrancy guard then short-circuits every future click forever, leaving
64
+ * a clickable-looking trigger that does nothing.
65
+ *
66
+ * This fires BEFORE `startSession()`'s promise resolves, so `backToIdle()`
67
+ * has already nulled `pending` by the time `start()` resumes from its await
68
+ * and its `superseded()` check discards that late resolution — the same
69
+ * ordering `onSessionFailed`/`onSessionEnded` already rely on.
70
+ *
71
+ * A dismiss is a clean return to idle, not a failure: the handler must NOT
72
+ * report through `onError`.
73
+ */
74
+ onSessionDismissed: (handler: () => void) => () => void;
44
75
  }
45
76
  export declare function createButtonSession(deps: ButtonSessionDeps, config: Partial<NapsterCompanionApiConfig>): NapsterCompanionApiController;
@@ -1,3 +1,4 @@
1
+ import "./Button.css";
1
2
  import type { ButtonConfig } from "../types";
2
3
  export type TriggerState = "idle" | "connecting" | "active";
3
4
  export interface Trigger {
@@ -12,7 +13,7 @@ export declare function resolveTriggerNode(element: HTMLElement | string): HTMLE
12
13
  * avatar swap via the root's `data-np-state`, which createButtonSession sets —
13
14
  * so all this has to do is keep the card from taking a second click.
14
15
  */
15
- export declare function createSdkTrigger(root: HTMLElement, config: ButtonConfig, onClick: () => void): Trigger;
16
+ export declare function createSdkTrigger(root: HTMLElement, config: ButtonConfig, photoUrl: string | undefined, onClick: () => void): Trigger;
16
17
  /**
17
18
  * A host-owned node. The SDK never moves, reparents or restyles it beyond
18
19
  * hiding it for the duration of a session — and puts back exactly what it
@@ -0,0 +1,58 @@
1
+ import "./EntryPoint.css";
2
+ /**
3
+ * The circular photo composition Figma calls "Agent Bubble"/"Agent Loading"
4
+ * — a 106px box holding a 96.36px gradient-backed circle with the
5
+ * companion's photo inset. Shared between the Entry Point card below and
6
+ * the standalone loading/ready-audio bubble (Avatar/index.ts) — both use
7
+ * the exact same Figma composition, just in different surrounding contexts
8
+ * (with the "Ask {name}" card vs. alone while the session connects).
9
+ */
10
+ export declare function createCompanionPhotoBubble(previewUrl: string | undefined): HTMLDivElement;
11
+ /**
12
+ * The card itself — photo bubble + heading + optional description, with its
13
+ * glass frame — shared between the default (non-button) flow's Entry Point
14
+ * (below) and button mode's own trigger (src/button/element.ts). Takes the
15
+ * final display text directly (no "Ask {name}" derivation here — callers
16
+ * that want that convention compute it themselves, see createEntryPoint()
17
+ * below); button mode's `label` is host-supplied verbatim instead.
18
+ *
19
+ * Returns `wrap` (NOT further wrapped in the default flow's absolutely-
20
+ * positioned, avatar-container-sized `.np_companion-entry-point`) — it's
21
+ * unstyled beyond `position: relative` and hugs its own content's natural
22
+ * size via normal block flow, so it drops into any layout context, including
23
+ * button mode's shrink-to-fit trigger root.
24
+ */
25
+ export interface EntryPointCardElements {
26
+ wrap: HTMLDivElement;
27
+ bubble: HTMLButtonElement;
28
+ }
29
+ export declare function createEntryPointCard(options: {
30
+ heading: string;
31
+ description?: string;
32
+ previewUrl?: string;
33
+ onClick: () => void;
34
+ }): EntryPointCardElements;
35
+ /**
36
+ * NOT the same "entry point" as button mode's trigger (src/button/*) — that's
37
+ * the click-to-start button for the OPT-IN button flow, built from
38
+ * createEntryPointCard() directly (see that file). This is the SDK's own
39
+ * card for the DEFAULT (non-button) flow's `SessionStatus === "entry"` state,
40
+ * wrapped in the absolutely-positioned, avatar-container-sized
41
+ * `.np_companion-entry-point` that centers it within that container.
42
+ *
43
+ * Same card for round/rectangle/silhouette — no per-shape branching. Figma
44
+ * (`104:2308`, page "Web Agent [Jul 29]") only defines this card under its
45
+ * "Variant 1 - Rectangle" section, and the card's own natural width (~402px:
46
+ * 106px photo + 22px gap + 196px text, plus 2×39px padding) doesn't fit
47
+ * inside round's 212px container — it's allowed to visually extend past a
48
+ * round/silhouette container's own edges, the same way the previous
49
+ * bubble+tooltip design already did on a smaller scale. Confirmed with the
50
+ * user rather than assumed: one Entry Point experience regardless of shape.
51
+ */
52
+ export interface EntryPointElements {
53
+ root: HTMLDivElement;
54
+ bubble: HTMLButtonElement;
55
+ }
56
+ export declare function createEntryPoint(companion: {
57
+ avatarUrl?: string;
58
+ }, onStart: () => void): EntryPointElements;
@@ -1,8 +1,15 @@
1
1
  import "./Avatar.css";
2
+ import "./loadingPulse.css";
2
3
  import { type ControlBarOptions } from "../ControlBar";
3
4
  import type { EventMessage, FeatureConfig, BaseController, NapsterCompanionApiConfig } from "../../types";
4
5
  export interface AvatarOptions {
5
- avatarStyle?: NapsterCompanionApiConfig["avatarStyle"];
6
+ avatarStyle?: NapsterCompanionApiConfig["style"];
7
+ /** The companion photo shown in the Entry Point bubble, the loading/
8
+ * ready-audio placeholder background, and the photo bubble — sourced
9
+ * from `config.agent?.photoUrl` (see `src/index.ts`). Omitted → falls
10
+ * back to a bundled placeholder (PLACEHOLDER_BACKGROUND_URL below, and
11
+ * EntryPoint.ts's own icon fallback). */
12
+ avatarUrl?: string;
6
13
  showAvatarInactiveOverlay?: boolean;
7
14
  onAvatarReady?: (isReady?: boolean) => void;
8
15
  onData?: (data: EventMessage) => void;
@@ -13,6 +20,20 @@ export interface AvatarOptions {
13
20
  onScreenShareToggle?: () => void;
14
21
  isScreenSharing?: boolean;
15
22
  isScreenShareSupported?: boolean;
23
+ /**
24
+ * True when the SDK is running in button (click-to-start) mode
25
+ * (`config.button?.enabled === true`). Button mode has its own trigger
26
+ * (src/button/*) — the Entry Point bubble below must not also render.
27
+ */
28
+ buttonMode?: boolean;
29
+ /**
30
+ * Fired when the Entry Point bubble is clicked at `SessionStatus ===
31
+ * "entry"` (CA-834 sub-project 2). NOT the same "entry point" as button
32
+ * mode's trigger — see EntryPoint.ts's own comment. The caller (src/index.ts)
33
+ * wires this to the same session-start path button mode's trigger already
34
+ * uses.
35
+ */
36
+ onEntryPointStart?: () => void;
16
37
  }
17
38
  export interface StreamsUpdate {
18
39
  videoStream?: MediaStream | null;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * A minimal, structurally-compatible subset of `DOMRect`/`DOMRectReadOnly`
3
+ * — a real `getBoundingClientRect()` result satisfies this interface as-is
4
+ * (TypeScript structural typing), while tests can pass a plain object with
5
+ * just these two fields instead of constructing a full `DOMRect`.
6
+ */
7
+ export interface RootHeightRect {
8
+ top: number;
9
+ bottom: number;
10
+ }
11
+ /**
12
+ * Reduces `rect`'s natural height so the box stops short of both viewport
13
+ * edges, without any knowledge of which edge (if any) is CSS-anchored —
14
+ * see the design doc (`docs/proposals/widget-container-sizing.md`,
15
+ * "Clamp: viewport-overflow check") for why both directions are always
16
+ * checked unconditionally: for a box truly anchored on a single edge, the
17
+ * *other* direction's overflow is physically impossible by construction,
18
+ * so the unused branch is always a no-op for it.
19
+ *
20
+ * Known imprecision: for a box centered via transform (e.g. App.css's
21
+ * `.np_companion-center`, `top: 50%; transform: translate(-50%, -50%)`),
22
+ * both edges can genuinely overflow AT ONCE and are coupled — shrinking a
23
+ * centered box moves both edges toward the middle simultaneously, so the
24
+ * real correction needed is roughly half of each overflow, not the full
25
+ * sum this function applies. Not handled here: the design this function
26
+ * implements was scoped to single-edge anchoring (see the design doc's
27
+ * Requirement 1), and centered widgets are rare enough relative to that
28
+ * scope that over-shrinking slightly in this one case was accepted rather
29
+ * than complicating the formula for it.
30
+ *
31
+ * Never returns less than `floorHeight` — the smallest legitimate size the
32
+ * caller ever wants this box to render at (e.g. the Entry Point card's own
33
+ * natural height). Below that floor there's nothing more useful to shrink
34
+ * into; the box renders at the floor and lets any remaining overflow be
35
+ * visually cut off by the viewport edge.
36
+ */
37
+ export declare function computeClampedHeight(rect: RootHeightRect, viewportHeight: number, floorHeight: number): number;
@@ -1,7 +1,7 @@
1
1
  import "./ControlBar.css";
2
2
  import { BaseController, NapsterCompanionApiConfig } from "../../types";
3
3
  export interface ControlBarOptions {
4
- avatarStyle?: NapsterCompanionApiConfig["avatarStyle"];
4
+ avatarStyle?: NapsterCompanionApiConfig["style"];
5
5
  isAvatarSpeaking?: boolean;
6
6
  isMuted: boolean;
7
7
  selectedMicrophone?: MediaDeviceInfo | null;
@@ -3,7 +3,10 @@ import "../../App.css";
3
3
  import type { EventMessage, FeatureConfig, BaseController, NapsterCompanionApiConfig } from "../../types";
4
4
  import type { StreamsUpdate } from "../Avatar";
5
5
  export interface EmbedOptions {
6
- avatarStyle?: NapsterCompanionApiConfig["avatarStyle"];
6
+ avatarStyle?: NapsterCompanionApiConfig["style"];
7
+ /** See `AvatarOptions.avatarUrl` (`Avatar/index.ts`) — threaded through
8
+ * unchanged. Sourced from `config.agent?.photoUrl`, see `src/index.ts`. */
9
+ avatarUrl?: string;
7
10
  onData?: (data: EventMessage) => void;
8
11
  onAvatarReady?: (isReady?: boolean) => void;
9
12
  onDestroy?: (cb?: () => void) => void;
@@ -13,6 +16,8 @@ export interface EmbedOptions {
13
16
  onScreenShareToggle?: () => void;
14
17
  isScreenSharing?: boolean;
15
18
  isScreenShareSupported?: boolean;
19
+ buttonMode?: boolean;
20
+ onEntryPointStart?: () => void;
16
21
  }
17
22
  export interface EmbedController extends BaseController<EmbedOptions> {
18
23
  updateStreams: (streams: StreamsUpdate) => void;
@@ -5,10 +5,41 @@ import "./MicPermission.css";
5
5
  * without the mic, so instead of tearing the widget down we keep it mounted and
6
6
  * walk the user back to a working state (CA-622).
7
7
  */
8
- export type MicPermissionState = "blocked" | "stillBlocked" | "step1" | "step2" | "step3";
8
+ export type MicPermissionState = "pending" | "blocked" | "stillBlocked" | "step1" | "step2" | "step3";
9
9
  export interface MicPermissionOptions {
10
- /** Re-probe the microphone. Resolves true once access is granted. */
11
- onCheckAgain: () => Promise<boolean>;
10
+ /**
11
+ * Re-probe the microphone. Resolves with the retry's real outcome — the
12
+ * three are genuinely different for this card, so this deliberately is not
13
+ * a boolean:
14
+ * - "granted": the caller resumes the session and disposes this controller.
15
+ * - "denied": still blocked, this card stays up and moves to stillBlocked.
16
+ * - "dismissed": the retry's own native prompt went unanswered for 30s and
17
+ * the caller has ALREADY destroyed this controller — there is nothing
18
+ * left to repaint.
19
+ */
20
+ onCheckAgain: () => Promise<"granted" | "denied" | "dismissed">;
21
+ /**
22
+ * Screen to open on. Defaults to "blocked" — every pre-existing call site
23
+ * creates this card only after a real denial, so nothing else needs to
24
+ * pass this. "pending" (CA-834, replaces PermissionPrompt entirely) is for
25
+ * micGate.ts mounting this same card during the FIRST getUserMedia()
26
+ * prompt, before any grant/denial is known — see that state's own SCREENS
27
+ * comment for why it has no buttons.
28
+ */
29
+ state?: MicPermissionState;
30
+ /**
31
+ * Which avatar shape's Permission States card to render (Figma:
32
+ * `Variant 1/2/3 - Permissions`, one set of five cards per shape — all
33
+ * three confirmed to exist). This component mounts directly into
34
+ * `#np_companion-sdk-root`, outside `#np_companion-avatar-container`'s
35
+ * own subtree, so it cannot inherit a view class via CSS cascade the way
36
+ * every other shape-aware card in this codebase does — it has to be told
37
+ * explicitly. Set once at creation, matching every other ancillary card
38
+ * this session (no live-view-sync mechanism, since none of these
39
+ * short-lived cards persist across a runtime `updateStyle()` call
40
+ * the way the avatar's own wrap does).
41
+ */
42
+ view: string | undefined;
12
43
  }
13
44
  export type MicPermissionController = BaseController<MicPermissionOptions> & {
14
45
  getElement(): HTMLElement;
@@ -1,9 +1,13 @@
1
1
  /**
2
2
  * Base element shared by every control-bar button.
3
3
  *
4
- * Presentation lives in ControlBar.css (`.np_companion-ctl-btn`) rather than
5
- * in inline styles, because inline styles cannot express `:hover` or
6
- * `:focus-visible`. This is also the single place role, tabindex and key
7
- * handling are added later (CA-841).
4
+ * A real `<button>` (CA-841), not a `<div>` — role, focusability, tabindex
5
+ * and Enter/Space key handling all come free from the browser instead of
6
+ * being hand-rolled and kept in sync. `type="button"` keeps it from acting
7
+ * as an implicit form submit if a host page ever nests the widget in a
8
+ * `<form>`. Presentation lives in ControlBar.css (`.np_companion-ctl-btn`,
9
+ * which resets the UA button chrome — border/padding/font/appearance)
10
+ * rather than in inline styles, because inline styles cannot express
11
+ * `:hover` or `:focus-visible`.
8
12
  */
9
- export declare function createControlButton(extraClass?: string): HTMLDivElement;
13
+ export declare function createControlButton(extraClass?: string): HTMLButtonElement;
package/lib/index.css CHANGED
@@ -1 +1 @@
1
- .np_companion-live-container,.np_companion-preview-container{height:100%;margin:0;padding:0;position:absolute;transition:opacity .3s ease-in-out;width:100%}.np_companion-preview-container{opacity:1;z-index:2}.np_companion-preview-container.np_companion-fade-out{opacity:0;pointer-events:none;transition:opacity .5s ease-out}.np_companion-live-container{opacity:0;z-index:1}.np_companion-live-container.np_companion-fade-in{opacity:1;z-index:3}:root{--base-border-radius:10px;--base-gap:20px}*,:after,:before{-webkit-box-sizing:border-box;box-sizing:border-box}::-webkit-input-placeholder{color:hsla(0,0%,100%,.4)}::-moz-placeholder{color:hsla(0,0%,100%,.4)}:-ms-input-placeholder{color:hsla(0,0%,100%,.4)}:-moz-placeholder{color:hsla(0,0%,100%,.4)}a,input{outline:none}.np_companion-hide{display:none!important}.np_companion-align-middle{align-items:center;display:flex;justify-content:center}.np_companion-align-between{align-items:center;display:flex;justify-content:space-between}.np_companion-align-end{align-items:center;display:flex;justify-content:flex-end}.np_companion-align-start{align-items:flex-start;display:flex;justify-content:flex-start}.np_companion__d-none{display:none!important}#np_companion-sdk-root.np_companion-container-fixed{height:500px;position:fixed;transition:top .3s ease-in-out,right .3s ease-in-out,bottom .3s ease-in-out,left .3s ease-in-out,width .3s ease-in-out,height .3s ease-in-out;width:400px;z-index:9999}#np_companion-sdk-root.np_companion-container-fixed.np_companion-view-rectangle{height:460px;width:402px}#np_companion-sdk-root.np_companion-container-fixed.np_companion-view-silhouette{height:400px}#np_companion-sdk-root.np_companion-container-fixed.np_companion-view-round{height:360px;width:250px}#np_companion-sdk-root.np_companion-container-fixed.np_companion-view-round.np_companion_disclaimer-disabled{height:320px!important}#np_companion-sdk-root.np_companion-container-fixed.np_companion-bottom-right{bottom:0;right:0}#np_companion-sdk-root.np_companion-container-fixed.np_companion-bottom-left{bottom:0;left:0}#np_companion-sdk-root.np_companion-container-fixed.np_companion-bottom-center{bottom:0;left:50%;transform:translateX(-50%)}#np_companion-sdk-root.np_companion-container-fixed.np_companion-top-right{right:0;top:0}#np_companion-sdk-root.np_companion-container-fixed.np_companion-top-left{left:0;top:0}#np_companion-sdk-root.np_companion-container-fixed.np_companion-top-center{left:50%;top:0;transform:translateX(-50%)}#np_companion-sdk-root.np_companion-container-fixed.np_companion-center{left:50%;top:50%;transform:translate(-50%,-50%)}#np_companion-sdk-root.np_companion-container-inline{aspect-ratio:4/5;height:100%;position:relative;width:100%}#np_companion-sdk-root.np_companion-container-inline.np_companion-view-round{aspect-ratio:1/1;container-type:size}.np_companion-avatar{height:100%;position:relative;width:100%}#np_companion-avatar-container{background:transparent;border-radius:var(--base-border-radius);height:100%;overflow:hidden;position:absolute;width:100%}#np_companion-avatar-container:not(.np_companion-view-silhouette){box-shadow:0 0 #0000,0 0 #0000,0 0 #0000,0 0 #0000,0 10px 15px -3px color-mix(in oklab,#00000080 100%,transparent),0 4px 6px -4px color-mix(in oklab,#00000080 100%,transparent)}.np_companion-avatar.np_companion-bg-transparent #np_companion-avatar-container.np_companion-view-silhouette{filter:drop-shadow(0 10px 15px rgba(0,0,0,.5)) drop-shadow(0 4px 6px rgba(0,0,0,.5))}.np_companion-container-fixed #np_companion-avatar-container.np_companion-view-round{border-radius:50%;height:212px;left:50%;transform:translate(-50%,12%);width:212px}.np_companion-container-fixed #np_companion-avatar-container.np_companion-view-rectangle,.np_companion-container-fixed #np_companion-avatar-container.np_companion-view-silhouette{left:50%;transform:translateX(-50%)}#np_companion-avatar-container.np_companion-view-rectangle:before{backdrop-filter:blur(11.059px);content:"";height:180px;inset:auto 0 0 0;-webkit-mask-image:linear-gradient(180deg,transparent 0,#000 65%);mask-image:linear-gradient(180deg,transparent 0,#000 65%);pointer-events:none;position:absolute;z-index:15}.np_companion-container-inline #np_companion-avatar-container.np_companion-view-round{border-radius:50%;height:min(100cqw,calc(100cqh - var(--np-controls-band, 88px)));left:50%;top:0;transform:translateX(-50%);width:min(100cqw,calc(100cqh - var(--np-controls-band, 88px)))}.np_companion-avatar-video{height:100%;inset:0;object-fit:cover;pointer-events:none;position:absolute;transition:opacity .3s ease-in-out;width:100%;z-index:10}.np_companion-avatar-video.no-opacity{opacity:0}.np_companion-avatar-canvas{background:transparent;height:100%;object-fit:cover;position:relative;width:100%;z-index:1}#np_companion-avatar-container.np_companion-loader-pulse:after,.np_companion-container-fixed #np_companion-avatar-container.np_companion-loader-pulse:after{animation:pulse 1.5s ease-in-out infinite;background-color:var(--np-loader-bg-color);border-radius:var(--base-border-radius);content:"";display:block;height:100%;left:0;opacity:.6;overflow:hidden;position:absolute;top:0;width:100%}.np_companion-avatar.np_companion-bg-transparent #np_companion-avatar-container:after{display:none}.np_companion-avatar:has(#np_companion-avatar-container.np_companion-view-round):after{display:none}#np_companion-avatar-container.np_companion-loader-pulse.loader-container.np_companion-view-round:after{animation:pulse 1.5s ease-in-out infinite;background-color:var(--np-loader-bg-color);border-radius:50%;content:"";display:block;height:100%;left:0;opacity:.6;overflow:hidden;position:absolute;top:0;width:100%}.np_companion-avatar.np_companion-bg-transparent #np_companion-avatar-container.np_companion-view-round:after{display:none}@keyframes pulse{0%,to{opacity:.5}50%{opacity:.2}}.np_companion-disclaimer-text{-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;color:#fff;font-size:10px;line-height:12px;margin:auto auto 16px;max-width:940px;opacity:.7;overflow:hidden;padding:0 16px;text-align:center;z-index:12}.np_companion-disclaimer-text a{color:#fff}.np_companion-disclaimer-text a:hover{color:#fff;text-decoration:underline}.np_companion-disclaimer-text a:focus,.np_companion-disclaimer-text a:visited{color:#fff}.np_companion-action-btn-container-wrapper{pointer-events:auto;width:100%}.np_companion-avatar-control-container{backdrop-filter:blur(19px);background:none;background-color:rgba(52,51,51,.6);border-radius:16px;bottom:0;box-shadow:0 4px 4px 0 rgba(0,0,0,.25),2px 2px 8px 0 rgba(0,0,0,.12);left:50%;max-width:90%;min-width:210px;opacity:1;position:absolute;transform:translateX(-50%);transition:opacity .4s cubic-bezier(.4,0,.2,1);z-index:99}.np_companion-avatar-control-container.np_companion-action-btn-container-collapse{opacity:0}.np_companion-avatar-control-container.np_companion-avatar-control-view-rectangle{backdrop-filter:none;background:none;background-color:transparent;box-shadow:none}.np_companion-avatar-control-container:not(.np_companion-avatar-control-view-round){bottom:16px}.np_companion-avatar:not(.np_companion-bg-transparent) .np_companion-loader-spinner:not(.np_companion-view-silhouette){backdrop-filter:blur(19px);background-color:color-mix(in oklab,var(--np-loader-bg-color) 100%,transparent)!important;filter:none!important;height:100%;width:100%}.np_companion-loader-spinner .loader-container{left:50%;position:absolute;top:50%;transform:translate(-50%,-50%)}.np_companion-loader-spinner .loader-container .loader{--_m:conic-gradient(#0000 10%,#000),linear-gradient(#000 0 0) content-box;animation:l3 1s linear infinite;aspect-ratio:1;background:var(--np-loader-color);border-radius:50%;-webkit-mask:var(--_m);mask:var(--_m);-webkit-mask-composite:source-out;mask-composite:subtract;padding:4px;width:24px}@keyframes l3{to{transform:rotate(1turn)}}.np_companion-loader-spinner.np_companion-view-round .loader-container .loader{padding:4px;width:212px}.np_companion-bg-transparent .np_companion-loader-spinner .loader-container{display:none}:root{--np-ctl-btn-size:48px}.np_companion-controls-container{align-items:center;background:hsla(0,0%,100%,.3);border:.5px solid #fff;border-radius:12px;bottom:20px;box-shadow:0 1px 1px rgba(0,0,0,.267),0 2px 5px rgba(0,0,0,.267),0 3px 8px rgba(0,0,0,.267);display:flex;gap:8px;left:50%;max-width:360px;pointer-events:auto;position:absolute;transform:translateX(-50%);transform-origin:bottom center;transition:width .3s ease-in-out;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:auto;z-index:99}.np_companion-controls-container.collapsed{gap:0}.np_companion-time-running{color:#fff}.np_companion-controls-time-action-btn-container{align-items:center;background:hsla(0,0%,100%,.1);border-radius:8px;display:flex;filter:grayscale(1);flex-shrink:0;gap:8px;height:32px;padding-left:8px;padding-right:8px;transition:filter .3s ease}.np_companion-controls-mic-control,.np_companion-controls-stop-control{cursor:pointer;display:flex;margin:0 5px;overflow:hidden;transition:opacity .3s ease-in-out,width .3s ease-in-out;width:47px}.np_companion-controls-mic-control.visible,.np_companion-controls-stop-control.visible{opacity:1}.np_companion-controls-mic-control.visible{width:1em}.np_companion-controls-stop-control.visible{width:1.5em}.np_companion-controls-mic-control.hidden,.np_companion-controls-stop-control.hidden{margin:0;opacity:0;padding:0;pointer-events:none;width:0}.np_companion-controls-mic-control:hover svg path{fill:red}.np_companion-controls-stop-control{display:flex;margin:0 5px 0 0}.np_companion-controls-stop-control:hover svg .stop-circle{fill:red}.np_companion-controls-stop-control:hover svg .stop-square{fill:#fff}.np_companion-mic-dropdown{background:#2b2c32;border-radius:4px;border-radius:6px;bottom:35px;box-shadow:0 10px 15px -3px rgba(0,0,0,.2),0 4px 6px -4px rgba(0,0,0,.2),0 0 0 1px #46464d;color:#fff;font-size:14px;list-style-type:none;margin:0;max-height:200px;min-width:300px;overflow-y:auto;overflow:auto;padding:5px;pointer-events:auto;position:absolute;width:auto;z-index:1000}.np_companion-mic-dropdown li{cursor:pointer;padding:8px 12px}.np_companion-mic-dropdown li:hover{background-color:#000}.np_companion-action-btn-container-container{background:transparent;border-radius:80px;gap:8px;padding:16px 16px 12px;transition:all .3s ease-in-out}.np_companion-action-btn-container-container.np_companion_disclaimer-disabled{padding-bottom:16px}.np_companion-action-btn-container-container .np_companion-chat-question-bar-container{border-radius:16px;gap:8px}.np_companion-dark-grey-bg{background:linear-gradient(0deg,#5e5e5e14 0 100%),#ffffff0f}.np_companion-grey-bg{background:linear-gradient(0deg,rgba(94,94,94,.07),rgba(94,94,94,.07)),hsla(0,0%,100%,.04)}.np_companion-ctl-btn{align-items:center;background:linear-gradient(0deg,#5e5e5e14 0 100%),#ffffff0f;border-radius:80px;color:#fff;cursor:pointer;display:flex;height:var(--np-ctl-btn-size);justify-content:center;transition:all .3s ease-in-out;width:var(--np-ctl-btn-size)}.np_companion-action-btn-container-view-rectangle .np_companion-ctl-btn:not(.np_companion-ctl-btn--mic){backdrop-filter:blur(50.7px);background:hsla(0,0%,7%,.2);border:1px solid #fff;box-sizing:border-box}.np_companion-ctl-btn--mic{background:radial-gradient(10px 10px at 10% 81%,hsla(24,91%,91%,.5) 0,hsla(24,91%,91%,0) 100%),linear-gradient(180deg,transparent 0,rgba(0,0,0,.5)),#be369d;box-shadow:inset 0 2.203px 3.305px rgba(255,150,217,.5),inset 0 -2.203px 3.305px rgba(0,0,0,.15)}.np_companion-ctl-btn--mic.np_companion-muted{background:#ff708f;box-shadow:none}@media (hover:hover){.np_companion-ctl-btn:hover{background:#fff;box-shadow:none;color:#000}}.np_companion-ctl-btn svg{height:28px;width:28px}.np_companion-inactive-overlay{align-items:center;bottom:0;display:flex;justify-content:center;left:0;pointer-events:auto;position:absolute;right:0;top:0;z-index:9999}.np_companion-inactive-dialog{backdrop-filter:blur(19px);background:hsla(0,0%,50%,.3);background-blend-mode:luminosity;border-radius:16px;max-width:500px;overflow:hidden;padding:24px 16px;position:relative;text-align:center;width:100%}@supports (-moz-appearance:none){.np_companion-inactive-dialog{background:rgba(32,32,34,.88);background-blend-mode:normal}}.np_companion-inactive-dialog:before{background:linear-gradient(180deg,hsla(0,0%,100%,.4),hsla(0,0%,100%,0),hsla(0,0%,100%,0),hsla(0,0%,100%,.1));border-radius:16px;content:"";inset:0;-webkit-mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);-webkit-mask-composite:destination-out;mask-composite:exclude;padding:1.473px;pointer-events:none;position:absolute}.np_companion-inactive-message{color:#fff;font-size:16px;line-height:1.5;margin-bottom:24px;margin-top:0}.np_companion-inactive-timer{display:flex;justify-content:center;margin:24px 0;pointer-events:none}.np_companion-timer-circle{align-items:center;display:flex;height:80px;justify-content:center;position:relative;width:80px}.np_companion-timer-circle svg{height:100%;transform:rotate(-90deg);width:100%}.np_companion-timer-circle path{transition:stroke-dasharray .3s ease}.np_companion-timer-number{color:#fff;font-size:24px;font-weight:500;position:absolute}.np_companion-inactive-buttons{display:flex;gap:12px;justify-content:center}.np_companion-inactive-buttons button{border:none;border-radius:8px;cursor:pointer;font-size:14px;font-weight:500;padding:12px 24px;transition:background-color .2s ease}.np_companion-end-button{background:hsla(0,0%,100%,.1);color:#fff}.np_companion-end-button:hover{background:hsla(0,0%,100%,.2)}.np_companion-continue-button{background:#3c19cd;color:#fff}.np_companion-continue-button:hover{background:#2f13a0}#np_companion-sdk-root[data-np-state=active] .np_button,#np_companion-sdk-root[data-np-state=connecting] .np_button,#np_companion-sdk-root[data-np-state=idle] .np_companion-live-container{display:none}#np_companion-sdk-root[data-np-state=idle].np_companion-container-fixed{height:auto;width:auto}.np_button{align-items:center;background:#16c784;border:0;border-radius:999px;box-shadow:0 10px 30px rgba(0,0,0,.45);color:#000;cursor:pointer;display:inline-flex;font:inherit;font-size:14px;font-weight:700;gap:10px;line-height:1;padding:13px 20px}.np_button:focus-visible{outline:2px solid #063;outline-offset:2px}.np_button--pending{cursor:progress;opacity:.7}.np_button-avatar{border-radius:50%;flex:none;height:24px;object-fit:cover;width:24px}.np_button-label{white-space:nowrap}.np_button-dot{background:#063;border-radius:50%;box-shadow:0 0 0 4px rgba(22,199,132,.22);flex:none;height:9px;width:9px}.np_button--pending .np_button-dot{animation:np_button-pulse 1s ease-in-out infinite}@keyframes np_button-pulse{0%,to{opacity:1}50%{opacity:.3}}@media (prefers-reduced-motion:reduce){.np_button--pending .np_button-dot{animation:none}}.np_button-description{display:block;font-size:12px;line-height:1.35;margin-top:2px;opacity:.72}.np_button-text{align-items:flex-start;display:flex;flex-direction:column;min-width:0}.np_site-frame{backface-visibility:hidden;border:0;height:100vh;height:100dvh;inset:0;position:fixed;transform:translateZ(0);width:100%;z-index:100000000}.np_site-progress{animation:np_site-progress-grow 6s cubic-bezier(.15,.75,.25,1) forwards;background:var(--np-persist-progress-color,#be369d);border-end-end-radius:3px;box-shadow:0 0 10px var(--np-persist-progress-color,#be369d);height:var(--np-persist-progress-height,3px);left:0;pointer-events:none;position:fixed;top:0;width:0;z-index:100000002}@keyframes np_site-progress-grow{0%{width:0}to{width:92%}}.np_site-progress--done{animation:none;opacity:0;transition:width .14s ease-out,opacity .24s ease-out .12s;width:100%}@media (prefers-reduced-motion:reduce){.np_site-progress{animation:none;width:92%}.np_site-progress--done{transition:opacity .14s linear}}.np_companion-mic-permission{--np-mic-permission-accent:#be369d;--np-mic-permission-accent-hover:#a62d88;--np-mic-permission-card-bg:hsla(0,0%,4%,.8);--np-mic-permission-card-radius:27px;align-items:flex-end;display:flex;inset:0;justify-content:center;padding:8px;pointer-events:auto;position:absolute;z-index:9999}.np_companion-mic-permission-card{backdrop-filter:blur(19px);background:var(--np-mic-permission-card-bg);border-radius:var(--np-mic-permission-card-radius);box-sizing:border-box;max-width:386px;padding:15px;text-align:center;width:100%}.np_companion-mic-permission-pagination{align-items:center;display:flex;gap:4px;justify-content:center;margin-bottom:8px}.np_companion-mic-permission-pagination[hidden]{display:none}.np_companion-mic-permission-dot{background:hsla(0,0%,100%,.4);border-radius:2px;height:4px;transition:width .2s ease,background .2s ease;width:4px}.np_companion-mic-permission-dot--active{background:#fff;width:16px}.np_companion-mic-permission-heading{color:#fff;font-family:inherit;font-size:18px;font-style:normal;font-weight:700;letter-spacing:-.18px;line-height:21.6px;margin:0 0 4px;text-transform:none}.np_companion-mic-permission-subheading{color:hsla(0,0%,100%,.5);font-family:inherit;font-size:14px;font-style:normal;font-weight:400;letter-spacing:-.28px;line-height:19.6px;margin:0 0 20px;text-transform:none}.np_companion-mic-permission-em--semibold{font-weight:600}.np_companion-mic-permission-em--bold{font-weight:700}.np_companion-mic-permission-actions{align-items:stretch;display:flex;flex-direction:column;gap:8px}.np_companion-mic-permission-actions button{border:0;color:#fff;cursor:pointer;font-family:inherit;font-style:normal;font-weight:600;text-transform:none;transition:background .2s ease}.np_companion-mic-permission-actions button:disabled{cursor:progress;opacity:.6}.np_companion-mic-permission-actions button:focus-visible{outline:2px solid #fff;outline-offset:2px}.np_companion-mic-permission-primary{background:var(--np-mic-permission-accent);border-radius:999px;font-size:15px;letter-spacing:-.15px;line-height:22px;min-height:48px;padding:7px 15px}.np_companion-mic-permission-primary:hover:not(:disabled){background:var(--np-mic-permission-accent-hover)}.np_companion-mic-permission-secondary{background:transparent;font-size:14px;letter-spacing:-.14px;line-height:19.6px;min-height:32px;padding:4px}.np_companion-mic-permission-secondary:hover:not(:disabled){color:hsla(0,0%,100%,.8)}.np_companion-mic-permission-live{clip:rect(0,0,0,0);border:0;height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;white-space:nowrap;width:1px}
1
+ .np_companion-live-container,.np_companion-preview-container{height:100%;margin:0;padding:0;position:absolute;transition:opacity .3s ease-in-out;width:100%}.np_companion-preview-container{opacity:1;z-index:2}.np_companion-preview-container.np_companion-fade-out{opacity:0;pointer-events:none;transition:opacity .5s ease-out}.np_companion-live-container{opacity:0;z-index:1}.np_companion-live-container.np_companion-fade-in{opacity:1;z-index:3}:root{--base-border-radius:10px;--base-gap:20px;--np-ready-grow-duration:150ms}*,:after,:before{-webkit-box-sizing:border-box;box-sizing:border-box}::-webkit-input-placeholder{color:hsla(0,0%,100%,.4)}::-moz-placeholder{color:hsla(0,0%,100%,.4)}:-ms-input-placeholder{color:hsla(0,0%,100%,.4)}:-moz-placeholder{color:hsla(0,0%,100%,.4)}a,input{outline:none}.np_companion-hide{display:none!important}.np_companion-align-middle{align-items:center;display:flex;justify-content:center}.np_companion-align-between{align-items:center;display:flex;justify-content:space-between}.np_companion-align-end{align-items:center;display:flex;justify-content:flex-end}.np_companion-align-start{align-items:flex-start;display:flex;justify-content:flex-start}.np_companion__d-none{display:none!important}#np_companion-sdk-root.np_companion-container-fixed{aspect-ratio:4/5;position:fixed;width:240px;z-index:9999}#np_companion-sdk-root.np_companion-container-fixed.np_companion-view-round{aspect-ratio:1/1}#np_companion-sdk-root.np_companion-container-fixed.np_companion-bottom-right{bottom:16px;right:16px}#np_companion-sdk-root.np_companion-container-fixed.np_companion-bottom-left{bottom:16px;left:16px}#np_companion-sdk-root.np_companion-container-fixed.np_companion-bottom-center{bottom:16px;left:50%;transform:translateX(-50%)}#np_companion-sdk-root.np_companion-container-fixed.np_companion-top-right{right:16px;top:16px}#np_companion-sdk-root.np_companion-container-fixed.np_companion-top-left{left:16px;top:16px}#np_companion-sdk-root.np_companion-container-fixed.np_companion-top-center{left:50%;top:16px;transform:translateX(-50%)}#np_companion-sdk-root.np_companion-container-fixed.np_companion-center{left:50%;top:50%;transform:translate(-50%,-50%)}#np_companion-sdk-root.np_companion-container-inline{aspect-ratio:4/5;height:100%;position:relative;width:100%}#np_companion-sdk-root.np_companion-container-inline.np_companion-view-round{aspect-ratio:1/1}#np_companion-avatar-container,.np_companion-avatar{height:100%;position:relative;width:100%}#np_companion-avatar-container{background:transparent;border-radius:var(--base-border-radius);overflow:hidden}#np_companion-avatar-container:not(.np_companion-view-silhouette){box-shadow:0 0 #0000,0 0 #0000,0 0 #0000,0 0 #0000,0 10px 15px -3px color-mix(in oklab,#00000080 100%,transparent),0 4px 6px -4px color-mix(in oklab,#00000080 100%,transparent)}.np_companion-avatar.np_companion-bg-transparent #np_companion-avatar-container.np_companion-view-silhouette{filter:drop-shadow(0 10px 15px rgba(0,0,0,.5)) drop-shadow(0 4px 6px rgba(0,0,0,.5))}#np_companion-avatar-container.np_companion-mic-muted-shape:not(.np_companion-view-silhouette){outline:4px solid #ff0037;outline-offset:0}.np_companion-avatar-wrap{inset:0;position:absolute}.np_companion-avatar-wrap.np_companion-view-round{aspect-ratio:1/1;height:auto}#np_companion-avatar-container.np_companion-view-rectangle.np_companion-status-ready-video:before{backdrop-filter:blur(11.059px);border-radius:0 0 32px 32px;content:"";height:180px;inset:auto 0 0 0;-webkit-mask-image:linear-gradient(180deg,transparent 0,#000 65%);mask-image:linear-gradient(180deg,transparent 0,#000 65%);opacity:1;pointer-events:none;position:absolute;transition:opacity .4s cubic-bezier(.4,0,.2,1);z-index:15}#np_companion-avatar-container.np_companion-view-rectangle.np_companion-status-ready-video:after{background:linear-gradient(180deg,transparent 0,rgba(0,0,0,.5) 62.109%);border-radius:0 0 32px 32px;content:"";height:116px;inset:auto 0 0 0;opacity:1;pointer-events:none;position:absolute;transition:opacity .4s cubic-bezier(.4,0,.2,1);z-index:15}.np_companion-avatar:has(.np_companion-avatar-control-wrap.np_companion-action-btn-container-collapse) #np_companion-avatar-container.np_companion-view-rectangle:after,.np_companion-avatar:has(.np_companion-avatar-control-wrap.np_companion-action-btn-container-collapse) #np_companion-avatar-container.np_companion-view-rectangle:before{opacity:0}#np_companion-avatar-container.np_companion-view-round{aspect-ratio:1/1;border-radius:50%;height:auto}.np_companion-avatar-video{border-radius:inherit;height:100%;inset:0;object-fit:cover;overflow:hidden;pointer-events:none;position:absolute;transition:opacity .3s ease-in-out;width:100%;z-index:10}@keyframes np-ready-grow-in{0%{border-radius:50%;height:var(--np-ready-grow-size,135px);width:var(--np-ready-grow-size,135px)}to{border-radius:var(--np-ready-grow-end-radius,50%);height:100%;width:100%}}#np_companion-avatar-container.np_companion-view-rectangle,#np_companion-avatar-container.np_companion-view-silhouette{--np-ready-grow-end-radius:32px}.np_companion-avatar-canvas.np_companion-ready-growing,.np_companion-avatar-video.np_companion-ready-growing{animation:np-ready-grow-in var(--np-ready-grow-duration,.45s) ease-out forwards;margin:auto;z-index:13}.np_companion-avatar-video.no-opacity{opacity:0}.np_companion-avatar-canvas{background-image:var(--np-placeholder-bg-image);background-position:50%;background-size:cover;border-radius:inherit;height:100%;inset:0;object-fit:cover;overflow:hidden;pointer-events:none;position:absolute;width:100%;z-index:1}#np_companion-avatar-container.np_companion-status-entry .np_companion-avatar-canvas,#np_companion-avatar-container.np_companion-status-loading .np_companion-avatar-canvas,#np_companion-avatar-container.np_companion-status-permission-blocked .np_companion-avatar-canvas,#np_companion-avatar-container.np_companion-status-permission-pending .np_companion-avatar-canvas{background-image:none}.np_companion-avatar:has(#np_companion-avatar-container.np_companion-view-round):after{display:none}.np_companion-disclaimer-text{-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;color:#fff;font-size:10px;line-height:12px;margin:auto auto 16px;max-width:940px;opacity:.7;overflow:hidden;padding:0 16px;text-align:center;z-index:12}.np_companion-disclaimer-text a{color:#fff}.np_companion-disclaimer-text a:hover{color:#fff;text-decoration:underline}.np_companion-disclaimer-text a:focus,.np_companion-disclaimer-text a:visited{color:#fff}.np_companion-action-btn-container-wrapper{pointer-events:auto;width:100%}.np_companion-avatar-control-wrap{bottom:16px;left:50%;max-width:calc(100% - 8px);opacity:1;position:absolute;transform:translateX(-50%);transition:opacity .4s cubic-bezier(.4,0,.2,1);z-index:99}.np_companion-avatar-control-wrap.np_companion-action-btn-container-collapse{opacity:0}.np_companion-avatar-control-wrap.np_companion-avatar-control-view-round{bottom:0}.np_companion-avatar-control-container{background-color:#111;border-radius:32px;box-shadow:0 4px 4px 0 rgba(0,0,0,.25),2px 2px 8px 0 rgba(0,0,0,.12);display:flow-root;position:relative}.np_companion-avatar-control-container.np_companion-avatar-control-view-rectangle{backdrop-filter:none;background-color:transparent;box-shadow:none}.np_companion-avatar:not(.np_companion-bg-transparent) .np_companion-loader-spinner:not(.np_companion-view-silhouette){backdrop-filter:blur(19px);backdrop-filter:none!important;background-color:color-mix(in oklab,hsla(0,0%,87%,.6) 100%,transparent)!important;background-color:transparent!important;filter:none!important;height:100%;width:100%}.np_companion-loader-spinner .loader-container{display:none;left:50%;position:absolute;top:50%;transform:translate(-50%,-50%)}.np_companion-loader-spinner .loader-container .loader{--_m:conic-gradient(#0000 10%,#000),linear-gradient(#000 0 0) content-box;animation:l3 1s linear infinite;aspect-ratio:1;background:#585858;border-radius:50%;-webkit-mask:var(--_m);mask:var(--_m);-webkit-mask-composite:source-out;mask-composite:subtract;padding:4px;width:24px}@keyframes l3{to{transform:rotate(1turn)}}.np_companion-loader-spinner.np_companion-view-round .loader-container .loader{padding:4px;width:212px}#np_companion-avatar-container.np_companion-status-entry .np_companion-entry-point{display:flex}#np_companion-avatar-container .np_companion-loading-photo-bubble{display:none;inset:0;margin:auto;position:absolute;z-index:20}#np_companion-avatar-container.np_companion-status-loading .np_companion-loading-photo-bubble{display:block}#np_companion-avatar-container .np_companion-loading-photo-bubble{height:135px;width:135px}#np_companion-avatar-container .np_companion-loading-photo-bubble .np_companion-photo-bubble-inner{border:3px solid var(--np-accent-color,#be369d);border-radius:100px;inset:6.15px}#np_companion-avatar-container.np_companion-status-loading:not(.np_companion-view-round),#np_companion-avatar-container.np_companion-status-permission-blocked:not(.np_companion-view-round),#np_companion-avatar-container.np_companion-status-permission-pending:not(.np_companion-view-round){border-radius:32px}#np_companion-avatar-container.np_companion-status-entry,#np_companion-avatar-container.np_companion-status-loading,#np_companion-avatar-container.np_companion-status-permission-blocked,#np_companion-avatar-container.np_companion-status-permission-pending{box-shadow:none!important}#np_companion-avatar-container.np_companion-status-entry,#np_companion-avatar-container.np_companion-status-permission-pending{overflow:visible}#np_companion-avatar-container .np_companion-placeholder-bg{border-radius:inherit;display:none;inset:0;overflow:hidden;position:absolute;z-index:11}#np_companion-avatar-container .np_companion-placeholder-bg:before{background-image:linear-gradient(var(--np-placeholder-bg-overlay,hsla(0,0%,7%,.7)),var(--np-placeholder-bg-overlay,hsla(0,0%,7%,.7))),var(--np-placeholder-bg-image);background-position:50%;background-size:cover;content:"";position:absolute}#np_companion-avatar-container.np_companion-view-rectangle .np_companion-placeholder-bg:before,#np_companion-avatar-container.np_companion-view-round .np_companion-placeholder-bg:before,#np_companion-avatar-container.np_companion-view-silhouette .np_companion-placeholder-bg:before{--np-placeholder-bg-overlay:hsla(0,0%,7%,.2);filter:blur(12px);inset:-35px}#np_companion-avatar-container.np_companion-status-loading .np_companion-placeholder-bg{display:block}#np_companion-avatar-container.np_companion-status-permission-blocked .np_companion-avatar-canvas,#np_companion-avatar-container.np_companion-status-permission-blocked .np_companion-avatar-video,#np_companion-avatar-container.np_companion-status-permission-pending .np_companion-avatar-canvas,#np_companion-avatar-container.np_companion-status-permission-pending .np_companion-avatar-video{display:none}#np_companion-avatar-container.np_companion-placeholder-lingering .np_companion-placeholder-bg{display:block}@keyframes np-placeholder-fade-out{0%{opacity:1}to{opacity:0}}#np_companion-avatar-container.np_companion-view-silhouette.np_companion-placeholder-lingering .np_companion-placeholder-bg{animation:np-placeholder-fade-out var(--np-ready-grow-duration,.45s) ease-out forwards}@keyframes np-loading-pulse{0%,to{transform:scale(1)}50%{transform:scale(.92)}}#np_companion-avatar-container.np_companion-status-loading .np_companion-loading-photo-bubble,#np_companion-avatar-container.np_companion-status-permission-pending .np_companion-loading-photo-bubble{animation:np-loading-pulse 1.8s ease-in-out infinite;transform-origin:center;will-change:transform}@media (prefers-reduced-motion:reduce){#np_companion-avatar-container.np_companion-status-loading .np_companion-loading-photo-bubble,#np_companion-avatar-container.np_companion-status-permission-pending .np_companion-loading-photo-bubble{animation:none}}:root{--np-ctl-btn-size:36px}.np_companion-controls-container{align-items:center;background:hsla(0,0%,100%,.3);border:.5px solid #fff;border-radius:12px;bottom:20px;box-shadow:0 1px 1px rgba(0,0,0,.267),0 2px 5px rgba(0,0,0,.267),0 3px 8px rgba(0,0,0,.267);display:flex;gap:8px;left:50%;max-width:360px;pointer-events:auto;position:absolute;transform:translateX(-50%);transform-origin:bottom center;transition:width .3s ease-in-out;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:auto;z-index:99}.np_companion-controls-container.collapsed{gap:0}.np_companion-time-running{color:#fff}.np_companion-controls-time-action-btn-container{align-items:center;background:hsla(0,0%,100%,.1);border-radius:8px;display:flex;filter:grayscale(1);flex-shrink:0;gap:8px;height:32px;padding-left:8px;padding-right:8px;transition:filter .3s ease}.np_companion-controls-mic-control,.np_companion-controls-stop-control{cursor:pointer;display:flex;margin:0 5px;overflow:hidden;transition:opacity .3s ease-in-out,width .3s ease-in-out;width:47px}.np_companion-controls-mic-control.visible,.np_companion-controls-stop-control.visible{opacity:1}.np_companion-controls-mic-control.visible{width:1em}.np_companion-controls-stop-control.visible{width:1.5em}.np_companion-controls-mic-control.hidden,.np_companion-controls-stop-control.hidden{margin:0;opacity:0;padding:0;pointer-events:none;width:0}.np_companion-controls-mic-control:hover svg path{fill:red}.np_companion-controls-stop-control{display:flex;margin:0 5px 0 0}.np_companion-controls-stop-control:hover svg .stop-circle{fill:red}.np_companion-controls-stop-control:hover svg .stop-square{fill:#fff}.np_companion-mic-dropdown{background:#2b2c32;border-radius:4px;border-radius:6px;bottom:35px;box-shadow:0 10px 15px -3px rgba(0,0,0,.2),0 4px 6px -4px rgba(0,0,0,.2),0 0 0 1px #46464d;color:#fff;font-size:14px;list-style-type:none;margin:0;max-height:200px;min-width:300px;overflow-y:auto;overflow:auto;padding:5px;pointer-events:auto;position:absolute;width:auto;z-index:1000}.np_companion-mic-dropdown li{cursor:pointer;padding:8px 12px}.np_companion-mic-dropdown li:hover{background-color:#000}.np_companion-action-btn-container-container{background:transparent;border-radius:80px;gap:8px;padding:12px 16px;transition:all .3s ease-in-out}.np_companion-action-btn-container-container.np_companion_disclaimer-disabled{padding-bottom:16px}.np_companion-action-btn-container-container .np_companion-chat-question-bar-container{border-radius:16px;gap:8px}.np_companion-dark-grey-bg{background:linear-gradient(0deg,#5e5e5e14 0 100%),#ffffff0f}.np_companion-grey-bg{background:linear-gradient(0deg,rgba(94,94,94,.07),rgba(94,94,94,.07)),hsla(0,0%,100%,.04)}#np_companion-sdk-root .np_companion-ctl-btn{align-items:center;appearance:none;border:none;border-radius:80px;box-sizing:border-box;color:#fff;cursor:pointer;display:flex;flex-shrink:0;font:inherit;height:var(--np-ctl-btn-size);justify-content:center;padding:0;transition:all .3s ease-in-out;width:var(--np-ctl-btn-size)}#np_companion-sdk-root .np_companion-ctl-btn:not(.np_companion-ctl-btn--mic){backdrop-filter:blur(50.7px);background:hsla(0,0%,7%,.2);border:none;position:relative}#np_companion-sdk-root .np_companion-ctl-btn:not(.np_companion-ctl-btn--mic):before{background:linear-gradient(135deg,hsla(0,0%,100%,.35),rgba(16,0,38,.35) 50%,hsla(0,0%,100%,.35));border-radius:inherit;content:"";inset:0;-webkit-mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);-webkit-mask-composite:xor;mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);mask-composite:exclude;padding:1px;pointer-events:none;position:absolute}#np_companion-sdk-root .np_companion-ctl-btn--mic{background:radial-gradient(10px 10px at 10% 81%,hsla(24,91%,91%,.5) 0,hsla(24,91%,91%,0) 100%),linear-gradient(to bottom,transparent 0,rgba(0,0,0,.5) 100%),var(--np-accent-color,#be369d);box-shadow:inset 0 2.203px 3.305px rgba(255,150,217,.5),inset 0 -2.203px 3.305px rgba(0,0,0,.15)}#np_companion-sdk-root .np_companion-ctl-btn--mic.np_companion-muted{background:#ff0037;box-shadow:none}@media (hover:hover){#np_companion-sdk-root .np_companion-ctl-btn:hover{background:#fff;box-shadow:none;color:#000}}#np_companion-sdk-root .np_companion-ctl-btn svg{height:20px;width:20px}.np_companion-inactive-overlay{align-items:center;bottom:0;display:flex;justify-content:center;left:0;pointer-events:auto;position:absolute;right:0;top:0;z-index:9999}.np_companion-inactive-dialog{backdrop-filter:blur(19px);background:hsla(0,0%,50%,.3);background-blend-mode:luminosity;border-radius:16px;max-width:500px;overflow:hidden;padding:24px 16px;position:relative;text-align:center;width:100%}@supports (-moz-appearance:none){.np_companion-inactive-dialog{background:rgba(32,32,34,.88);background-blend-mode:normal}}.np_companion-inactive-dialog:before{background:linear-gradient(180deg,hsla(0,0%,100%,.4),hsla(0,0%,100%,0),hsla(0,0%,100%,0),hsla(0,0%,100%,.1));border-radius:16px;content:"";inset:0;-webkit-mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);-webkit-mask-composite:destination-out;mask-composite:exclude;padding:1.473px;pointer-events:none;position:absolute}.np_companion-inactive-message{color:#fff;font-size:16px;line-height:1.5;margin-bottom:24px;margin-top:0}.np_companion-inactive-timer{display:flex;justify-content:center;margin:24px 0;pointer-events:none}.np_companion-timer-circle{align-items:center;display:flex;height:80px;justify-content:center;position:relative;width:80px}.np_companion-timer-circle svg{height:100%;transform:rotate(-90deg);width:100%}.np_companion-timer-circle path{transition:stroke-dasharray .3s ease}.np_companion-timer-number{color:#fff;font-size:24px;font-weight:500;position:absolute}.np_companion-inactive-buttons{display:flex;gap:12px;justify-content:center}.np_companion-inactive-buttons button{border:none;border-radius:8px;cursor:pointer;font-size:14px;font-weight:500;padding:12px 24px;transition:background-color .2s ease}.np_companion-end-button{background:hsla(0,0%,100%,.1);color:#fff}.np_companion-end-button:hover{background:hsla(0,0%,100%,.2)}.np_companion-continue-button{background:#3c19cd;color:#fff}.np_companion-continue-button:hover{background:#2f13a0}.np_companion-entry-point{align-items:center;display:none;inset:0;justify-content:center;position:absolute;z-index:20}.np_companion-entry-point-card-wrap{max-width:100%;min-width:0}.np_companion-entry-point-card{align-items:center;background:#111;border:0;border-radius:25px;color:inherit;cursor:pointer;display:flex;font:inherit;gap:8px;max-width:100%;padding:12px;position:relative;text-align:left}.np_companion-photo-bubble{flex-shrink:0;height:64px;position:relative;width:64px}.np_companion-photo-bubble-inner{background:linear-gradient(180deg,#0c010a,#3f236b);border-radius:50%;inset:4px;overflow:hidden;position:absolute}.np_companion-photo-bubble-inner--fallback{background:var(--np-accent-color,#be369d)}.np_companion-photo-bubble-image{height:100%;inset:0;object-fit:cover;position:absolute;width:100%}.np_companion-entry-point-text{color:#fff;display:flex;flex-direction:column;gap:4px;min-width:0;width:153px}.np_companion-entry-point-heading{font-size:16px;font-weight:700;letter-spacing:-.6px;line-height:1.2;margin:0}.np_companion-entry-point-description{font-size:12px;font-weight:400;letter-spacing:-.48px;line-height:1.3;margin:0;opacity:.5}#np_companion-sdk-root[data-np-state=active] .np_button-trigger,#np_companion-sdk-root[data-np-state=connecting] .np_button-trigger,#np_companion-sdk-root[data-np-state=idle] .np_companion-live-container{display:none}#np_companion-sdk-root[data-np-state=idle].np_companion-container-fixed{aspect-ratio:auto!important;height:auto!important;width:auto!important}#np_companion-sdk-root[data-np-state=idle].np_companion-container-inline{aspect-ratio:auto;height:auto}#np_companion-sdk-root[data-np-state=idle].np_companion-container-inline.np_companion-button-align-left{justify-content:flex-start}#np_companion-sdk-root[data-np-state=idle].np_companion-container-inline.np_companion-button-align-right{justify-content:flex-end}.np_site-frame{backface-visibility:hidden;border:0;height:100vh;height:100dvh;inset:0;position:fixed;transform:translateZ(0);width:100%;z-index:100000000}.np_site-progress{animation:np_site-progress-grow 6s cubic-bezier(.15,.75,.25,1) forwards;background:var(--np-persist-progress-color,#be369d);border-end-end-radius:3px;box-shadow:0 0 10px var(--np-persist-progress-color,#be369d);height:var(--np-persist-progress-height,3px);left:0;pointer-events:none;position:fixed;top:0;width:0;z-index:100000002}@keyframes np_site-progress-grow{0%{width:0}to{width:92%}}.np_site-progress--done{animation:none;opacity:0;transition:width .14s ease-out,opacity .24s ease-out .12s;width:100%}@media (prefers-reduced-motion:reduce){.np_site-progress{animation:none;width:92%}.np_site-progress--done{transition:opacity .14s linear}}#np_companion-sdk-root .np_companion-mic-permission{--np-mic-permission-accent:var(--np-accent-color,#be369d);--np-mic-permission-accent-hover:color-mix(in srgb,var(--np-accent-color,#be369d) 85%,#000);--np-mic-permission-card-bg:hsla(0,0%,4%,.8);--np-mic-permission-card-radius:27px;align-items:flex-end;display:flex;inset:0;justify-content:center;padding:8px;pointer-events:auto;position:absolute;z-index:9999}#np_companion-sdk-root .np_companion-mic-permission-card{backdrop-filter:blur(19px);background:var(--np-mic-permission-card-bg);border-radius:var(--np-mic-permission-card-radius);box-sizing:border-box;max-width:386px;padding:15px;text-align:center;width:100%}#np_companion-sdk-root .np_companion-mic-permission.np_companion-view-round{padding:8px 0}#np_companion-sdk-root .np_companion-mic-permission-pagination{align-items:center;display:flex;gap:4px;justify-content:center;margin-bottom:8px}#np_companion-sdk-root .np_companion-mic-permission-pagination[hidden]{display:none}#np_companion-sdk-root .np_companion-mic-permission-dot{background:hsla(0,0%,100%,.4);border-radius:2px;height:4px;transition:width .2s ease,background .2s ease;width:4px}#np_companion-sdk-root .np_companion-mic-permission-dot--active{background:#fff;width:16px}#np_companion-sdk-root .np_companion-mic-permission-heading{color:#fff;font-family:inherit;font-size:18px;font-style:normal;font-weight:700;letter-spacing:-.18px;line-height:21.6px;margin:0 0 4px;text-transform:none}#np_companion-sdk-root .np_companion-mic-permission-subheading{color:hsla(0,0%,100%,.5);font-family:inherit;font-size:14px;font-style:normal;font-weight:400;letter-spacing:-.28px;line-height:19.6px;margin:0 0 20px;text-transform:none}#np_companion-sdk-root .np_companion-mic-permission-card:has(.np_companion-mic-permission-actions[hidden]) .np_companion-mic-permission-subheading{margin-bottom:0}#np_companion-sdk-root .np_companion-mic-permission-em--semibold{font-weight:600}#np_companion-sdk-root .np_companion-mic-permission-em--bold{font-weight:700}#np_companion-sdk-root .np_companion-mic-permission-actions{align-items:stretch;display:flex;flex-direction:column;gap:8px}#np_companion-sdk-root .np_companion-mic-permission-actions[hidden]{display:none}#np_companion-sdk-root .np_companion-mic-permission-actions button{border:0;color:#fff;cursor:pointer;font-family:inherit;font-style:normal;font-weight:600;text-transform:none;transition:background .2s ease}#np_companion-sdk-root .np_companion-mic-permission-actions button:disabled{cursor:progress;opacity:.6}#np_companion-sdk-root .np_companion-mic-permission-actions button:focus-visible{outline:2px solid #fff;outline-offset:2px}#np_companion-sdk-root .np_companion-mic-permission-primary{background:var(--np-mic-permission-accent);border-radius:999px;font-size:15px;letter-spacing:-.15px;line-height:22px;min-height:48px;padding:7px 15px}#np_companion-sdk-root .np_companion-mic-permission-primary:hover:not(:disabled){background:var(--np-mic-permission-accent-hover)}#np_companion-sdk-root .np_companion-mic-permission-secondary{background:transparent;font-size:14px;letter-spacing:-.14px;line-height:19.6px;min-height:32px;padding:4px}#np_companion-sdk-root .np_companion-mic-permission-secondary:hover:not(:disabled){color:hsla(0,0%,100%,.8)}#np_companion-sdk-root .np_companion-mic-permission-live{clip:rect(0,0,0,0);border:0;height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;white-space:nowrap;width:1px}
package/lib/index.d.ts CHANGED
@@ -24,6 +24,7 @@ declare class NapsterCompanionApiSdkVanilla implements NapsterCompanionApiSDK {
24
24
  private persistCtl;
25
25
  private onSessionFailedHandler;
26
26
  private onSessionEndedHandler;
27
+ private onSessionDismissedHandler;
27
28
  private buttonMode;
28
29
  private lastFaceDetected;
29
30
  private userMutedDuringFaceTracking;
@@ -152,7 +153,7 @@ declare class NapsterCompanionApiSdkVanilla implements NapsterCompanionApiSDK {
152
153
  }
153
154
  declare const NapsterCompanionApiSdk: NapsterCompanionApiSdkVanilla;
154
155
  export { NapsterCompanionApiSdk };
155
- export type { NapsterCompanionApiConfig, NapsterCompanionApiInstance, NapsterCompanionApiController, PersistenceOptions, ButtonConfig, CompanionFunction, FeatureConfig, StyleObject, FaceTrackingConfig, FaceTrackingData, FaceTrackingController, MouthLandmarks, } from "./types";
156
+ export type { NapsterCompanionApiConfig, NapsterCompanionApiInstance, NapsterCompanionApiController, PersistenceOptions, ButtonConfig, LayoutConfig, StyleConfig, AgentConfig, CompanionFunction, FeatureConfig, FaceTrackingConfig, FaceTrackingData, FaceTrackingController, MouthLandmarks, } from "./types";
156
157
  export { Position } from "./types";
157
158
  export { DataChannelMessageType } from "./constants/events";
158
159
  export { checkPiPSupport, resetPiPSupportCache } from "./utils/PiPManager";