@frankieai/react 0.2.20 → 0.2.21

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/dist/index.js CHANGED
@@ -58,6 +58,8 @@ var FrankieClient = class {
58
58
  session;
59
59
  /** Identity (JWT `sub`, else the raw token) the cached session was issued for. */
60
60
  sessionUserKey;
61
+ /** The host token fetched for the latest turn; sent with it so tools get a live one. */
62
+ latestUserToken;
61
63
  get sessionId() {
62
64
  return this.session?.sessionId;
63
65
  }
@@ -119,6 +121,7 @@ var FrankieClient = class {
119
121
  "user_token_unavailable"
120
122
  );
121
123
  }
124
+ this.latestUserToken = userToken;
122
125
  const userKey = sessionIdentity(userToken);
123
126
  if (userKey !== this.sessionUserKey) this.resetSession();
124
127
  if (this.session && new Date(this.session.expiresAt).getTime() > Date.now() + 3e4) return this.session;
@@ -211,7 +214,11 @@ var FrankieClient = class {
211
214
  message: input.message,
212
215
  ...input.context ? { context: input.context } : {},
213
216
  ...input.model ? { model: input.model } : {},
214
- ...input.attachments?.length ? { attachments: input.attachments } : {}
217
+ ...input.attachments?.length ? { attachments: input.attachments } : {},
218
+ ...this.latestUserToken ? { userToken: this.latestUserToken } : {},
219
+ // This widget shows the approval card, so the server may pause writes for it.
220
+ confirmActions: true,
221
+ ...input.confirm ? { confirm: input.confirm } : {}
215
222
  };
216
223
  const response = await this.doFetch(`${this.baseUrl}/v1/chat`, {
217
224
  method: "POST",
@@ -246,7 +253,7 @@ var FrankieClient = class {
246
253
  await this.postToolResult(session, callId, result).catch(() => void 0);
247
254
  }
248
255
  async callHostApi(request) {
249
- const api = this.options.api;
256
+ const api = this.options.api ?? (typeof window !== "undefined" ? { baseUrl: window.location.origin } : void 0);
250
257
  if (!api) {
251
258
  return {
252
259
  status: 0,
@@ -353,6 +360,10 @@ function luminance([r, g, b]) {
353
360
  };
354
361
  return 0.2126 * channel(r) + 0.7152 * channel(g) + 0.0722 * channel(b);
355
362
  }
363
+ function colorful([r, g, b]) {
364
+ const max = Math.max(r, g, b), min = Math.min(r, g, b);
365
+ return max - min >= 40;
366
+ }
356
367
  function contrastRatio(a, b) {
357
368
  const la = luminance(a), lb = luminance(b);
358
369
  return (Math.max(la, lb) + 0.05) / (Math.min(la, lb) + 0.05);
@@ -461,7 +472,7 @@ function inferHostTheme() {
461
472
  break;
462
473
  }
463
474
  const text = parseRgb(style.color);
464
- if (text && text[3] > 0.5 && !sameColor(text, foreground)) {
475
+ if (text && text[3] > 0.5 && !sameColor(text, foreground) && colorful(text)) {
465
476
  accent = text;
466
477
  break;
467
478
  }
@@ -539,6 +550,11 @@ function applyEvent(message, event) {
539
550
  } : tool
540
551
  )
541
552
  };
553
+ case "action_confirm":
554
+ return {
555
+ ...message,
556
+ action: { toolUseId: event.toolUseId, name: event.name, label: event.label, preview: event.preview, state: "pending" }
557
+ };
542
558
  case "tool_denied":
543
559
  return {
544
560
  ...message,
@@ -758,6 +774,7 @@ function useFrankieChatState() {
758
774
  ...context ? { context } : {},
759
775
  ...opts?.model ? { model: opts.model } : {},
760
776
  ...attachments.length ? { attachments } : {},
777
+ ...opts?.confirm ? { confirm: opts.confirm } : {},
761
778
  signal: abort.signal
762
779
  },
763
780
  (event) => {
@@ -828,6 +845,21 @@ function useFrankieChatState() {
828
845
  },
829
846
  [busy, client, context, patchAssistant, restored, followRunningTurn]
830
847
  );
848
+ const answerAction = useCallback(
849
+ async (toolUseId, approved) => {
850
+ if (abortRef.current) return;
851
+ const holder = messagesRef.current.find(
852
+ (message) => message.role === "assistant" && message.action?.toolUseId === toolUseId && message.action.state === "pending"
853
+ );
854
+ if (!holder) return;
855
+ patchAssistant(
856
+ holder.id,
857
+ (message) => message.action ? { ...message, action: { ...message.action, state: approved ? "approved" : "cancelled" } } : message
858
+ );
859
+ await send(approved ? "Go ahead" : "Cancel", { confirm: { toolUseId, approved } });
860
+ },
861
+ [patchAssistant, send]
862
+ );
831
863
  const stop = useCallback(() => {
832
864
  if (!abortRef.current) return;
833
865
  void client.stopTurn();
@@ -848,7 +880,7 @@ function useFrankieChatState() {
848
880
  } catch {
849
881
  }
850
882
  }, [client]);
851
- return { messages, busy, loadedSkills, activeApis, restoring: !restored, ...error ? { error } : {}, send, stop, reset };
883
+ return { messages, busy, loadedSkills, activeApis, restoring: !restored, ...error ? { error } : {}, send, answerAction, stop, reset };
852
884
  }
853
885
  function conversationTitle(messages) {
854
886
  const first = messages.find((message) => message.role === "user" && message.text.trim());
@@ -962,7 +994,7 @@ function useFrankieTheme() {
962
994
  }
963
995
 
964
996
  // src/components/chat/FrankieWidget.tsx
965
- import { MessageCircle, X as X4 } from "lucide-react";
997
+ import { MessageCircle, X as X5 } from "lucide-react";
966
998
  import { useEffect as useEffect6, useRef as useRef5, useState as useState7 } from "react";
967
999
 
968
1000
  // src/lib/styles-ready.ts
@@ -970,7 +1002,7 @@ import { useEffect as useEffect3, useLayoutEffect as useLayoutEffect2, useState
970
1002
 
971
1003
  // src/generated/css-content.ts
972
1004
  var FRANKIE_CSS_CONTENT = `/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
973
- @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-ease:initial}}}@layer theme{.frankie-root{--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-emerald-400:oklch(76.5% .177 163.223);--color-emerald-500:oklch(69.6% .17 162.48);--color-emerald-600:oklch(59.6% .145 163.225);--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--font-weight-medium:500;--font-weight-semibold:600;--leading-tight:1.25;--radius-md:.375rem;--ease-in-out:cubic-bezier(.4, 0, .2, 1);--animate-spin:spin 1s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--color-background:var(--frankie-background);--color-foreground:var(--frankie-foreground);--color-primary:var(--frankie-primary)}}@layer components{.frankie-page-shell{background:var(--frankie-background);height:100%;min-height:0;color:var(--frankie-foreground);flex:1;display:flex}.frankie-page-main{flex-direction:column;flex:1;min-width:0;min-height:0;display:flex}.frankie-history-desktop{border-right:1px solid var(--frankie-border);background:var(--frankie-secondary);flex-direction:column;flex-shrink:0;gap:16px;width:260px;padding:20px 14px;transition:width .16s,padding .16s;display:flex;overflow:auto}.frankie-history-toggle{border:1px solid var(--frankie-border);background:var(--frankie-background);width:32px;height:32px;color:var(--frankie-muted-foreground);cursor:pointer;border-radius:8px;flex-shrink:0;justify-content:center;align-self:flex-end;align-items:center;display:flex}.frankie-history-toggle:hover{color:var(--frankie-foreground)}.frankie-history-collapsed{width:56px;padding:20px 8px;overflow:visible}.frankie-history-collapsed .frankie-history-toggle{align-self:center}.frankie-history-heading{justify-content:space-between;align-items:center;font-size:14px;display:flex}.frankie-new-chat{border:1px solid var(--frankie-border);background:var(--frankie-background);cursor:pointer;border-radius:10px;justify-content:center;align-items:center;gap:8px;min-height:44px;font-weight:600;display:flex}.frankie-history-search>span{color:var(--frankie-muted-foreground);margin-bottom:6px;font-size:12px;display:block}.frankie-history-search input{border:1px solid var(--frankie-border);background:var(--frankie-background);border-radius:8px;width:100%;min-height:40px;padding:8px 10px}.frankie-history-list{flex-direction:column;flex:1;gap:4px;display:flex}.frankie-history-list button{text-align:left;cursor:pointer;background:0 0;border:1px solid #0000;border-radius:8px;flex-direction:column;align-items:flex-start;gap:5px;min-height:54px;padding:10px;display:flex}.frankie-history-list button span{text-overflow:ellipsis;white-space:nowrap;width:100%;font-size:13px;overflow:hidden}.frankie-history-list small{color:var(--frankie-muted-foreground);font-size:11px}.frankie-history-list button:hover,.frankie-history-list button[aria-current]{background:var(--frankie-background);border-color:var(--frankie-border)}.frankie-history-desktop>p,.frankie-history-dialog p{color:var(--frankie-muted-foreground);font-size:13px}.frankie-header-caption{color:var(--frankie-muted-foreground);font-size:12px}.frankie-page-header button{cursor:pointer;justify-content:center;align-items:center;gap:6px;min-width:40px;min-height:40px;display:inline-flex}.frankie-chat-settings{position:relative}.frankie-chat-settings summary{cursor:pointer;border-radius:8px;place-items:center;width:40px;height:40px;list-style:none;display:grid}.frankie-chat-settings summary::-webkit-details-marker{display:none}.frankie-chat-settings>div{z-index:5;border:1px solid var(--frankie-border);background:var(--frankie-background);border-radius:12px;gap:12px;width:min(280px,80vw);padding:16px;font-size:13px;display:grid;position:absolute;top:46px;right:0;box-shadow:0 10px 30px #0002}.frankie-chat-settings p{color:var(--frankie-muted-foreground);margin:0}.frankie-loaded-skills{width:100%;max-width:760px;color:var(--frankie-muted-foreground);font-size:12px}.frankie-loaded-skills summary{cursor:pointer;padding:6px 0}.frankie-loaded-skills ul{margin:0;padding:4px 0;list-style:none}.frankie-loaded-skills li{gap:8px;padding:4px 0;display:flex}.frankie-loaded-skills small{opacity:.7}.frankie-history-dialog{background:var(--frankie-secondary);width:min(320px,86vw);max-width:none;height:100dvh;max-height:none;color:var(--frankie-foreground);border:0;margin:0;padding:0}.frankie-history-dialog::backdrop{background:#0008}.frankie-history-dialog>aside{height:100%;padding:calc(20px + env(safe-area-inset-top)) 16px calc(20px + env(safe-area-inset-bottom));flex-direction:column;gap:16px;display:flex;overflow:auto}.frankie-mobile-only{display:none!important}.frankie-widget-panel{max-height:calc(100dvh - 100px - var(--frankie-lift,0px))}.frankie-root button:focus-visible,.frankie-root summary:focus-visible,.frankie-root input:focus-visible{outline:2px solid var(--frankie-primary);outline-offset:3px}.frankie-root button:disabled{opacity:.5;cursor:not-allowed}@media (max-width:760px){.frankie-history-desktop{display:none}.frankie-mobile-only{display:inline-flex!important}.frankie-header-caption{display:none}.frankie-page-header{padding:6px 10px}.frankie-history-heading button{background:0 0;border:0;justify-content:center;align-items:center;min-width:44px;min-height:44px}.frankie-page-prompts{gap:8px}.frankie-widget-panel{width:calc(100vw - 32px)}}.frankie-root{--frankie-styles-ready:1;--frankie-background:#fff;--frankie-foreground:#0a0a0a;--frankie-primary:#171717;--frankie-primary-foreground:#fafafa;--frankie-secondary:#f5f5f5;--frankie-secondary-foreground:#171717;--frankie-muted:#f5f5f5;--frankie-muted-foreground:#737373;--frankie-border:#e5e5e5;--frankie-radius:.625rem;--frankie-font:ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;font-family:var(--frankie-font);color:var(--frankie-foreground);-webkit-font-smoothing:antialiased;line-height:1.5}.frankie-root.dark{--frankie-background:#0a0a0a;--frankie-foreground:#fafafa;--frankie-primary:#fafafa;--frankie-primary-foreground:#171717;--frankie-secondary:#262626;--frankie-secondary-foreground:#fafafa;--frankie-muted:#262626;--frankie-muted-foreground:#a3a3a3;--frankie-border:#262626}.frankie-root,.frankie-root *,.frankie-root :before,.frankie-root :after{box-sizing:border-box}.frankie-root button,.frankie-root textarea,.frankie-root input{font:inherit;color:inherit;margin:0}.frankie-root button{background-color:#0000;border:0 solid}.frankie-root textarea{background-color:var(--frankie-background)}.frankie-focus:focus-visible{outline:2px solid var(--frankie-primary);outline-offset:2px}.frankie-scroll{scrollbar-width:thin;scrollbar-color:var(--frankie-border) transparent}.frankie-prose>*+*{margin-top:.6rem}.frankie-prose p{white-space:pre-wrap;overflow-wrap:anywhere;margin:0;line-height:1.6}.frankie-prose>.frankie-h{letter-spacing:-.01em;margin-top:1.15rem;line-height:1.3}.frankie-prose>.frankie-h:first-child{margin-top:0}.frankie-prose h3.frankie-h{font-size:1.06em;font-weight:700}.frankie-prose h4.frankie-h{font-size:1em;font-weight:600}.frankie-prose h5.frankie-h{color:var(--frankie-muted-foreground);font-size:.92em;font-weight:600}.frankie-prose strong{font-weight:600}.frankie-prose ul,.frankie-prose ol{flex-direction:column;gap:.35rem;margin:0;padding-left:1.4rem;display:flex}.frankie-prose li{padding-left:.15rem;line-height:1.55}.frankie-prose li::marker{color:var(--frankie-muted-foreground)}.frankie-prose ul{list-style:outside}.frankie-prose ol{list-style:decimal}.frankie-prose a{color:var(--frankie-primary);text-underline-offset:2px;text-decoration:underline}.frankie-prose code{background-color:var(--frankie-muted);border-radius:.25rem;padding:.1em .3em;font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,monospace;font-size:.85em}.frankie-prose pre{border-radius:var(--frankie-radius);background-color:var(--frankie-muted);margin:0;padding:.625rem .75rem;overflow-x:auto}.frankie-prose pre code{background:0 0;padding:0}.frankie-chat-page{background:radial-gradient(60rem 24rem at 50% -12rem, var(--frankie-primary), transparent 65%), var(--frankie-background);flex-direction:column;min-width:0;display:flex;overflow:hidden}@supports (color:color-mix(in lab, red, red)){.frankie-chat-page{background:radial-gradient(60rem 24rem at 50% -12rem, color-mix(in srgb, var(--frankie-primary) 8%, transparent), transparent 65%), var(--frankie-background)}}.frankie-chat-page{color:var(--frankie-foreground)}.frankie-page-header{border-bottom:1px solid var(--frankie-border);background:var(--frankie-background);flex:0 0 56px;justify-content:space-between;align-items:center;gap:16px;min-height:56px;padding:0 24px;display:flex}@supports (color:color-mix(in lab, red, red)){.frankie-page-header{background:color-mix(in srgb, var(--frankie-background) 92%, transparent)}}.frankie-page-header{-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.frankie-page-header>div{align-items:center;gap:10px;display:flex}.frankie-page-header strong{font-size:.925rem;font-weight:650}.frankie-page-status{background:var(--frankie-primary);width:10px;height:10px;box-shadow:0 0 0 4px var(--frankie-primary);border-radius:999px}@supports (color:color-mix(in lab, red, red)){.frankie-page-status{box-shadow:0 0 0 4px color-mix(in srgb, var(--frankie-primary) 16%, transparent)}}.frankie-page-header button{border:1px solid var(--frankie-border);border-radius:calc(var(--frankie-radius) * .9);background:var(--frankie-secondary);cursor:pointer;min-height:36px;padding:0 13px}.frankie-page-header button:hover{border-color:var(--frankie-primary)}.frankie-page-canvas{flex:1;min-width:0;min-height:0;display:flex}.frankie-page-canvas>.frankie-inline{width:100%;max-width:56rem;margin:0 auto}.frankie-page-canvas .frankie-scroll{padding:2rem clamp(1rem,4vw,4rem) 1.25rem}.frankie-page-canvas .frankie-root>.border-t{background:linear-gradient(180deg, transparent, var(--frankie-background) 30%);border-top:0;padding:.75rem clamp(1rem,4vw,4rem) 1.5rem}.frankie-page-empty{text-align:center;flex-direction:column;flex-shrink:0;justify-content:safe center;align-items:center;gap:2rem;width:min(100%,44rem);min-height:100%;margin:auto;padding:clamp(2rem,7vh,4.5rem) 1rem 2rem;display:flex;container-type:inline-size}.frankie-page-welcome h1{letter-spacing:-.02em;margin:0;font-size:clamp(1.55rem,3.4vw,2rem);font-weight:700;line-height:1.15}.frankie-page-welcome p{max-width:34rem;color:var(--frankie-muted-foreground);margin:.6rem auto 0;font-size:1rem}.frankie-page-suggest{flex-direction:column;align-items:center;gap:1rem;width:100%;display:flex}.frankie-page-suggest-label{color:var(--frankie-muted-foreground);letter-spacing:.12em;text-transform:uppercase;margin:0;font-size:.72rem;font-weight:600}.frankie-page-prompts{grid-template-columns:1fr;gap:.75rem;width:100%;display:grid}@container (min-width:30rem){.frankie-page-prompts{grid-template-columns:repeat(2,minmax(0,1fr))}}.frankie-page-prompts button{border:1px solid var(--frankie-border);background:var(--frankie-background);text-align:left;cursor:pointer;border-radius:14px;align-items:flex-start;gap:.85rem;min-height:64px;padding:.9rem 1rem;transition:border-color .15s,background-color .15s,transform .12s;display:flex}.frankie-page-prompts button:hover:not(:disabled){border-color:var(--frankie-primary)}@supports (color:color-mix(in lab, red, red)){.frankie-page-prompts button:hover:not(:disabled){border-color:color-mix(in srgb, var(--frankie-primary) 45%, var(--frankie-border))}}.frankie-page-prompts button:hover:not(:disabled){background:var(--frankie-primary)}@supports (color:color-mix(in lab, red, red)){.frankie-page-prompts button:hover:not(:disabled){background:color-mix(in srgb, var(--frankie-primary) 4%, var(--frankie-background))}}.frankie-page-prompts button:hover:not(:disabled){transform:translateY(-1px)}.frankie-prompt-icon{background:var(--frankie-muted);width:34px;height:34px;color:var(--frankie-foreground);border-radius:9px;flex:none;place-items:center;display:grid}.frankie-prompt-text{flex-direction:column;gap:2px;min-width:0;display:flex}.frankie-prompt-text strong{font-size:.9rem;font-weight:600;line-height:1.3}.frankie-prompt-text small{color:var(--frankie-muted-foreground);font-size:.8rem;line-height:1.35;overflow:hidden}.frankie-page-suggest-hint{color:var(--frankie-muted-foreground);margin:0;font-size:.85rem}.frankie-widget-panel .frankie-page-empty{gap:1rem;padding:1rem .25rem}.frankie-widget-panel .frankie-page-welcome h1{font-size:1.25rem}.frankie-widget-panel .frankie-page-welcome p{margin-top:.35rem;font-size:.88rem;line-height:1.45}.frankie-widget-panel .frankie-page-suggest{gap:.55rem}.frankie-widget-panel .frankie-page-suggest-label{font-size:.66rem}.frankie-widget-panel .frankie-page-prompts{flex-wrap:wrap;justify-content:center;gap:.4rem;display:flex}.frankie-widget-panel .frankie-page-prompts button{border-radius:999px;align-items:center;gap:.4rem;max-width:100%;min-height:34px;padding:.3rem .8rem .3rem .45rem}.frankie-widget-panel .frankie-prompt-icon{border-radius:999px;width:22px;height:22px}.frankie-widget-panel .frankie-prompt-icon svg{width:13px;height:13px}.frankie-widget-panel .frankie-prompt-text strong{white-space:nowrap;text-overflow:ellipsis;font-size:.82rem;font-weight:550;overflow:hidden}.frankie-widget-panel .frankie-prompt-text small,.frankie-widget-panel .frankie-page-suggest-hint{display:none}@media (max-width:640px){.frankie-page-header{flex-basis:52px;min-height:52px;padding:0 12px}.frankie-page-canvas .frankie-scroll{padding:1.25rem .75rem .5rem}.frankie-page-canvas .frankie-root>.border-t{padding:.65rem .75rem calc(.65rem + env(safe-area-inset-bottom))}}}@layer utilities;.frankie-root .\\@container{container-type:inline-size}.frankie-root .invisible{visibility:hidden}.frankie-root .visible{visibility:visible}.frankie-root .absolute{position:absolute}.frankie-root .fixed{position:fixed}.frankie-root .relative{position:relative}.frankie-root .static{position:static}.frankie-root .sticky{position:sticky}.frankie-root .isolate{isolation:isolate}.frankie-root .container{width:100%}@media (min-width:40rem){.frankie-root .container{max-width:40rem}}@media (min-width:48rem){.frankie-root .container{max-width:48rem}}@media (min-width:64rem){.frankie-root .container{max-width:64rem}}@media (min-width:80rem){.frankie-root .container{max-width:80rem}}@media (min-width:96rem){.frankie-root .container{max-width:96rem}}.frankie-root .mt-0{margin-top:0}.frankie-root .mt-0\\.5{margin-top:calc(var(--spacing) * .5)}.frankie-root .mt-1{margin-top:var(--spacing)}.frankie-root .mt-2{margin-top:calc(var(--spacing) * 2)}.frankie-root .block{display:block}.frankie-root .contents{display:contents}.frankie-root .flex{display:flex}.frankie-root .grid{display:grid}.frankie-root .hidden{display:none}.frankie-root .inline{display:inline}.frankie-root .inline-flex{display:inline-flex}.frankie-root .table{display:table}.frankie-root .size-1{width:var(--spacing);height:var(--spacing)}.frankie-root .size-1\\.5{width:calc(var(--spacing) * 1.5);height:calc(var(--spacing) * 1.5)}.frankie-root .size-3{width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}.frankie-root .size-3\\.5{width:calc(var(--spacing) * 3.5);height:calc(var(--spacing) * 3.5)}.frankie-root .size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.frankie-root .size-5{width:calc(var(--spacing) * 5);height:calc(var(--spacing) * 5)}.frankie-root .size-7{width:calc(var(--spacing) * 7);height:calc(var(--spacing) * 7)}.frankie-root .size-8{width:calc(var(--spacing) * 8);height:calc(var(--spacing) * 8)}.frankie-root .size-9{width:calc(var(--spacing) * 9);height:calc(var(--spacing) * 9)}.frankie-root .size-12{width:calc(var(--spacing) * 12);height:calc(var(--spacing) * 12)}.frankie-root .size-full{width:100%;height:100%}.frankie-root .h-8{height:calc(var(--spacing) * 8)}.frankie-root .h-9{height:calc(var(--spacing) * 9)}.frankie-root .h-10{height:calc(var(--spacing) * 10)}.frankie-root .h-\\[32rem\\]{height:32rem}.frankie-root .h-full{height:100%}.frankie-root .h-px{height:1px}.frankie-root .min-h-7{min-height:calc(var(--spacing) * 7)}.frankie-root .min-h-\\[2\\.25rem\\]{min-height:2.25rem}.frankie-root .min-h-screen{min-height:100vh}.frankie-root .w-\\[22rem\\]{width:22rem}.frankie-root .w-full{width:100%}.frankie-root .max-w-\\[12rem\\]{max-width:12rem}.frankie-root .max-w-\\[14rem\\]{max-width:14rem}.frankie-root .max-w-\\[85\\%\\]{max-width:85%}.frankie-root .max-w-\\[calc\\(100vw-2rem\\)\\]{max-width:calc(100vw - 2rem)}.frankie-root .min-w-0{min-width:0}.frankie-root .flex-1{flex:1}.frankie-root .shrink-0{flex-shrink:0}.frankie-root .grow{flex-grow:1}.frankie-root .animate-pulse{animation:var(--animate-pulse)}.frankie-root .animate-spin{animation:var(--animate-spin)}.frankie-root .cursor-pointer{cursor:pointer}.frankie-root .resize{resize:both}.frankie-root .resize-none{resize:none}.frankie-root .list-none{list-style-type:none}.frankie-root .flex-col{flex-direction:column}.frankie-root .flex-wrap{flex-wrap:wrap}.frankie-root .items-center{align-items:center}.frankie-root .items-end{align-items:flex-end}.frankie-root .items-start{align-items:flex-start}.frankie-root .justify-center{justify-content:center}.frankie-root .justify-end{justify-content:flex-end}.frankie-root .gap-1{gap:var(--spacing)}.frankie-root .gap-1\\.5{gap:calc(var(--spacing) * 1.5)}.frankie-root .gap-2{gap:calc(var(--spacing) * 2)}.frankie-root .gap-3{gap:calc(var(--spacing) * 3)}.frankie-root .gap-4{gap:calc(var(--spacing) * 4)}.frankie-root .truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.frankie-root .overflow-hidden{overflow:hidden}.frankie-root .overflow-y-auto{overflow-y:auto}.frankie-root .overscroll-contain{overscroll-behavior:contain}.frankie-root .rounded{border-radius:.25rem}.frankie-root .rounded-\\[calc\\(var\\(--frankie-radius\\)\\+4px\\)\\]{border-radius:calc(var(--frankie-radius) + 4px)}.frankie-root .rounded-\\[calc\\(var\\(--frankie-radius\\)-2px\\)\\]{border-radius:calc(var(--frankie-radius) - 2px)}.frankie-root .rounded-\\[var\\(--frankie-radius\\)\\]{border-radius:var(--frankie-radius)}.frankie-root .rounded-full{border-radius:3.40282e38px}.frankie-root .rounded-md{border-radius:var(--radius-md)}.frankie-root .rounded-none{border-radius:0}.frankie-root .border{border-style:var(--tw-border-style);border-width:1px}.frankie-root .border-0{border-style:var(--tw-border-style);border-width:0}.frankie-root .border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.frankie-root .border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.frankie-root .border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.frankie-root .border-border{border-color:var(--frankie-border)}.frankie-root .border-transparent{border-color:#0000}.frankie-root .bg-background{background-color:var(--frankie-background)}.frankie-root .bg-border{background-color:var(--frankie-border)}.frankie-root .bg-emerald-500{background-color:var(--color-emerald-500)}.frankie-root .bg-emerald-500\\/10{background-color:#00bb7f1a}@supports (color:color-mix(in lab, red, red)){.frankie-root .bg-emerald-500\\/10{background-color:color-mix(in oklab, var(--color-emerald-500) 10%, transparent)}}.frankie-root .bg-muted{background-color:var(--frankie-muted)}.frankie-root .bg-muted-foreground{background-color:var(--frankie-muted-foreground)}.frankie-root .bg-primary{background-color:var(--frankie-primary)}.frankie-root .bg-red-500{background-color:var(--color-red-500)}.frankie-root .bg-red-500\\/10{background-color:#fb2c361a}@supports (color:color-mix(in lab, red, red)){.frankie-root .bg-red-500\\/10{background-color:color-mix(in oklab, var(--color-red-500) 10%, transparent)}}.frankie-root .bg-secondary{background-color:var(--frankie-secondary)}.frankie-root .object-cover{object-fit:cover}.frankie-root .p-3{padding:calc(var(--spacing) * 3)}.frankie-root .p-4{padding:calc(var(--spacing) * 4)}.frankie-root .px-1{padding-inline:var(--spacing)}.frankie-root .px-2{padding-inline:calc(var(--spacing) * 2)}.frankie-root .px-3{padding-inline:calc(var(--spacing) * 3)}.frankie-root .px-4{padding-inline:calc(var(--spacing) * 4)}.frankie-root .px-6{padding-inline:calc(var(--spacing) * 6)}.frankie-root .py-0{padding-block:0}.frankie-root .py-0\\.5{padding-block:calc(var(--spacing) * .5)}.frankie-root .py-1{padding-block:var(--spacing)}.frankie-root .py-2{padding-block:calc(var(--spacing) * 2)}.frankie-root .py-3{padding-block:calc(var(--spacing) * 3)}.frankie-root .pl-2{padding-left:calc(var(--spacing) * 2)}.frankie-root .text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.frankie-root .text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.frankie-root .text-\\[0\\.625rem\\]{font-size:.625rem}.frankie-root .text-\\[0\\.6875rem\\]{font-size:.6875rem}.frankie-root .text-\\[11px\\]{font-size:11px}.frankie-root .leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.frankie-root .font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.frankie-root .font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.frankie-root .whitespace-nowrap{white-space:nowrap}.frankie-root .text-emerald-600{color:var(--color-emerald-600)}.frankie-root .text-foreground{color:var(--frankie-foreground)}.frankie-root .text-muted-foreground{color:var(--frankie-muted-foreground)}.frankie-root .text-primary{color:var(--frankie-primary)}.frankie-root .text-primary-foreground{color:var(--frankie-primary-foreground)}.frankie-root .text-red-600{color:var(--color-red-600)}.frankie-root .text-secondary-foreground{color:var(--frankie-secondary-foreground)}.frankie-root .italic{font-style:italic}.frankie-root .underline-offset-4{text-underline-offset:4px}.frankie-root .opacity-60{opacity:.6}.frankie-root .opacity-70{opacity:.7}.frankie-root .shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.frankie-root .shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.frankie-root .shadow-none{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.frankie-root .outline{outline-style:var(--tw-outline-style);outline-width:1px}.frankie-root .transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.frankie-root .transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.frankie-root .transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.frankie-root .ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.frankie-root .select-all{-webkit-user-select:all;user-select:all}.frankie-root .placeholder\\:text-muted-foreground::placeholder{color:var(--frankie-muted-foreground)}@media (hover:hover){.frankie-root .hover\\:border-border:hover{border-color:var(--frankie-border)}.frankie-root .hover\\:bg-muted:hover{background-color:var(--frankie-muted)}.frankie-root .hover\\:text-foreground:hover{color:var(--frankie-foreground)}.frankie-root .hover\\:underline:hover{text-decoration-line:underline}.frankie-root .hover\\:opacity-90:hover{opacity:.9}.frankie-root .hover\\:opacity-100:hover{opacity:1}}.frankie-root .focus-visible\\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.frankie-root .focus-visible\\:ring-primary:focus-visible{--tw-ring-color:var(--frankie-primary)}.frankie-root .focus-visible\\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.frankie-root .disabled\\:pointer-events-none:disabled{pointer-events:none}.frankie-root .disabled\\:cursor-not-allowed:disabled{cursor:not-allowed}.frankie-root .disabled\\:opacity-50:disabled{opacity:.5}.frankie-root .dark\\:text-emerald-400:where(.dark,.dark *){color:var(--color-emerald-400)}.frankie-root .dark\\:text-red-400:where(.dark,.dark *){color:var(--color-red-400)}.frankie-root .\\[\\&_svg\\]\\:pointer-events-none svg{pointer-events:none}.frankie-root .\\[\\&_svg\\]\\:size-4 svg{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.frankie-root .\\[\\&_svg\\]\\:shrink-0 svg{flex-shrink:0}.frankie-root .\\[\\&\\:\\:-webkit-details-marker\\]\\:hidden::-webkit-details-marker{display:none}.frankie-root.frankie-chat-panel{min-height:0;position:relative}.frankie-root.frankie-widget-panel{box-shadow:0 32px 72px -18px var(--frankie-primary), 0 12px 28px -12px #0f172a47, 0 0 0 1px var(--frankie-foreground)}@supports (color:color-mix(in lab, red, red)){.frankie-root.frankie-widget-panel{box-shadow:0 32px 72px -18px color-mix(in srgb, var(--frankie-primary) 22%, #0f172a6b), 0 12px 28px -12px #0f172a47, 0 0 0 1px color-mix(in srgb, var(--frankie-foreground) 8%, transparent)}}.frankie-root.frankie-widget-panel.dark{box-shadow:0 34px 80px -16px #000000b8, 0 14px 32px -12px #0009, 0 0 0 1px var(--frankie-foreground)}@supports (color:color-mix(in lab, red, red)){.frankie-root.frankie-widget-panel.dark{box-shadow:0 34px 80px -16px #000000b8, 0 14px 32px -12px #0009, 0 0 0 1px color-mix(in srgb, var(--frankie-foreground) 12%, transparent)}}.frankie-root .frankie-agent-context-wrap{flex:none;justify-content:center;padding:12px 10px;display:flex}.frankie-root .frankie-agent-context{max-width:100%;color:var(--frankie-foreground);font-size:13px;position:relative}.frankie-root .frankie-agent-context>summary{border:1px solid var(--frankie-border);background:var(--frankie-background);cursor:pointer;white-space:nowrap;border-radius:999px;justify-content:center;align-items:center;gap:10px;min-height:44px;padding:7px 13px;list-style:none;display:flex;box-shadow:0 1px 3px #0000000d}.frankie-root .frankie-agent-context>summary::-webkit-details-marker{display:none}.frankie-root .frankie-agent-context>summary>svg{color:var(--frankie-muted-foreground);flex:none}.frankie-root .frankie-context-count{background:var(--frankie-muted);color:var(--frankie-muted-foreground);border-radius:999px;padding:2px 10px;font-size:12px}.frankie-root .frankie-context-status{color:var(--frankie-muted-foreground);align-items:center;gap:6px;font-size:12px;display:flex}.frankie-root .frankie-context-status i{background:currentColor;border-radius:50%;width:7px;height:7px}.frankie-root .frankie-context-status[data-active=true]{color:#00976b}.frankie-root .frankie-context-detail{z-index:10;border:1px solid var(--frankie-border);background:var(--frankie-background);border-radius:16px;width:340px;max-width:calc(100vw - 32px);padding:18px;position:absolute;top:calc(100% + 10px);left:50%;transform:translate(-50%);box-shadow:0 12px 32px #00000016}.frankie-root .frankie-context-detail p{color:var(--frankie-muted-foreground);margin:10px 0 0;font-size:12px;line-height:1.6}.frankie-root .frankie-context-detail ul{max-height:220px;margin:12px 0;padding:0;list-style:none;overflow:auto}.frankie-root .frankie-context-detail li{border-bottom:1px solid var(--frankie-border);overflow-wrap:anywhere;justify-content:space-between;gap:12px;padding:8px 0;display:flex}.frankie-root .frankie-context-detail small{color:var(--frankie-muted-foreground);flex:none}.frankie-root .frankie-sr-only{clip:rect(0,0,0,0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.frankie-root.frankie-chat-panel-fill{--frankie-canvas:var(--frankie-background)}@supports (color:color-mix(in lab, red, red)){.frankie-root.frankie-chat-panel-fill{--frankie-canvas:color-mix(in srgb,var(--frankie-background) 60%,var(--frankie-muted))}}.frankie-root.frankie-chat-panel-fill{background:var(--frankie-canvas)}.frankie-root.frankie-chat-panel-fill .frankie-agent-context-wrap{padding:44px 16px 26px}.frankie-root.frankie-chat-panel-fill .frankie-transcript{padding:14px max(24px,50% - 480px) 24px}.frankie-root.frankie-chat-panel-fill .frankie-message-list{gap:38px}.frankie-root.frankie-chat-panel-fill .frankie-user-bubble{background:var(--frankie-muted);color:var(--frankie-foreground);white-space:pre-wrap;overflow-wrap:anywhere;border-radius:24px;padding:12px 20px;font-size:15px}.frankie-root.frankie-chat-panel-fill .frankie-assistant-content{flex:1;max-width:100%;font-size:15px;line-height:1.7}.frankie-root.frankie-chat-panel-fill .frankie-assistant-message{gap:14px}.frankie-root .frankie-thinking{color:var(--frankie-muted-foreground);gap:5px}.frankie-root .frankie-thinking-label{margin-right:6px;font-size:14px}.frankie-root.frankie-chat-panel-fill .frankie-composer-footer{background:0 0;border:0;flex:none;padding:16px max(24px,50% - 500px) 24px}.frankie-root.frankie-chat-panel-fill .frankie-composer{border:1px solid var(--frankie-border);background:var(--frankie-background);border-radius:28px;padding:14px;box-shadow:0 2px 4px #0000000a}.frankie-root.frankie-chat-panel-fill .frankie-composer:focus-within{border-color:var(--frankie-foreground)}@supports (color:color-mix(in lab, red, red)){.frankie-root.frankie-chat-panel-fill .frankie-composer:focus-within{border-color:color-mix(in srgb,var(--frankie-foreground) 32%,var(--frankie-border))}}.frankie-root.frankie-chat-panel-fill .frankie-composer:focus-within{box-shadow:0 0 0 2px var(--frankie-primary)}@supports (color:color-mix(in lab, red, red)){.frankie-root.frankie-chat-panel-fill .frankie-composer:focus-within{box-shadow:0 0 0 2px color-mix(in srgb,var(--frankie-primary) 8%,transparent)}}.frankie-root.frankie-chat-panel-fill .frankie-composer-controls{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.frankie-root.frankie-chat-panel-fill .frankie-composer textarea{resize:none;width:100%;min-height:32px;max-height:140px;color:var(--frankie-foreground);box-shadow:none;background:0 0;border:0;border-radius:0;outline:none;flex:0 0 100%;order:-1;margin-bottom:4px;padding:2px 6px;font-size:16px}.frankie-root.frankie-chat-panel-fill .frankie-composer button[aria-label=Send],.frankie-root.frankie-chat-panel-fill .frankie-composer button[aria-label=Stop]{background:var(--frankie-primary);width:42px;height:42px;color:var(--frankie-primary-foreground);border:0;border-radius:50%;margin-left:auto}.frankie-root.frankie-chat-panel-fill .frankie-composer button[aria-label=Attach\\ files]{border-radius:50%;width:42px;height:42px}.frankie-root .frankie-composer-actions{align-items:center;gap:6px;min-width:0;display:flex}.frankie-root .frankie-composer-meta{align-items:center;gap:8px;margin-top:6px;padding:0 2px;display:flex}.frankie-root .frankie-model-picker{align-items:center;min-width:0;display:inline-flex}.frankie-root .frankie-model-select{appearance:none;max-width:12rem;color:var(--frankie-muted-foreground);font:inherit;cursor:pointer;text-overflow:ellipsis;background-color:#0000;background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%238b8b8b' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");background-position:right 6px center;background-repeat:no-repeat;background-size:11px;border:0;border-radius:8px;padding:5px 22px 5px 8px;font-size:12px;font-weight:500;line-height:1;transition:background-color .12s,color .12s}.frankie-root .frankie-model-select:hover{background-color:var(--frankie-muted);color:var(--frankie-foreground)}.frankie-root .frankie-model-select:disabled{opacity:.5;cursor:not-allowed}.frankie-root .frankie-model-select option{color:var(--frankie-foreground);background:var(--frankie-background);font-weight:400}.frankie-root .frankie-history-desktop{background:var(--frankie-background);width:290px;padding:20px 12px}.frankie-root .frankie-history-collapsed{width:56px;padding:20px 8px}.frankie-root .frankie-new-chat{background:0 0;border:0;justify-content:flex-start;padding:8px 12px;font-size:15px}.frankie-root .frankie-history-heading{color:var(--frankie-muted-foreground);padding:0 12px;font-size:12px;font-weight:400}.frankie-root .frankie-history-list button{min-height:44px;padding:10px 12px}.frankie-root .frankie-history-list button span{font-size:14px}.frankie-root .frankie-history-list button[aria-current],.frankie-root .frankie-history-list button:hover{background:var(--frankie-muted);border-color:#0000}.frankie-root .frankie-history-list small{display:none}.frankie-root .frankie-history-group{flex-direction:column;gap:2px;display:flex}.frankie-root .frankie-history-group+.frankie-history-group{margin-top:12px}.frankie-root .frankie-history-group-label{letter-spacing:.04em;color:var(--frankie-muted-foreground);margin:0;padding:4px 12px;font-size:11px;font-weight:600}.frankie-root .frankie-page-header{background:var(--frankie-background);height:56px;min-height:56px}.frankie-root .frankie-page-header>div{min-width:0}.frankie-root .frankie-thread-title{text-overflow:ellipsis;white-space:nowrap;max-width:55vw;font-weight:500;overflow:hidden}.frankie-root .frankie-page-header button{background:0 0;border-color:#0000}.frankie-root .frankie-page-canvas>.frankie-inline{max-width:none}@media (max-width:760px){.frankie-root.frankie-chat-panel-fill .frankie-agent-context-wrap{padding:20px 8px 14px}.frankie-root.frankie-chat-panel-fill .frankie-transcript{padding:12px 16px 16px}.frankie-root.frankie-chat-panel-fill .frankie-composer-footer{padding:10px 12px calc(12px + env(safe-area-inset-bottom))}.frankie-root .frankie-agent-context>summary{gap:6px;padding:7px 9px;font-size:12px}.frankie-root .frankie-context-count{padding:2px 7px;font-size:11px}.frankie-root .frankie-context-status{gap:4px;font-size:11px}.frankie-root .frankie-agent-context>summary>svg{width:14px}.frankie-root .frankie-thread-title{max-width:42vw}}.frankie-root .frankie-agent-context>summary>svg:first-child{box-sizing:content-box;background:var(--frankie-muted);border-radius:50%;padding:4px}.frankie-root.frankie-chat-panel-fill .frankie-agent-context>summary{font-size:14px}.frankie-root .frankie-agent-context>summary>span:first-of-type{border-right:1px solid var(--frankie-border);padding-right:10px}@media (max-width:760px){.frankie-root .frankie-page-header button>span{display:none}}.frankie-root .frankie-choices{flex-direction:column;gap:8px;margin-top:12px;display:flex}.frankie-root .frankie-choice{text-align:left;cursor:pointer;border:1px solid var(--frankie-border);border-radius:var(--frankie-radius);background:var(--frankie-background);width:100%;color:var(--frankie-foreground);font:inherit;align-items:center;gap:12px;padding:11px 14px;font-size:14px;line-height:1.4;transition:border-color .15s,background-color .15s,transform .12s;display:flex}.frankie-root .frankie-choice:hover:not(:disabled){border-color:var(--frankie-primary)}@supports (color:color-mix(in lab, red, red)){.frankie-root .frankie-choice:hover:not(:disabled){border-color:color-mix(in srgb, var(--frankie-primary) 55%, var(--frankie-border))}}.frankie-root .frankie-choice:hover:not(:disabled){background:var(--frankie-primary)}@supports (color:color-mix(in lab, red, red)){.frankie-root .frankie-choice:hover:not(:disabled){background:color-mix(in srgb, var(--frankie-primary) 6%, var(--frankie-background))}}.frankie-root .frankie-choice:active:not(:disabled){transform:scale(.99)}.frankie-root .frankie-choice:focus-visible{box-shadow:0 0 0 2px var(--frankie-primary);outline:none}@supports (color:color-mix(in lab, red, red)){.frankie-root .frankie-choice:focus-visible{box-shadow:0 0 0 2px color-mix(in srgb, var(--frankie-primary) 40%, transparent)}}.frankie-root .frankie-choice:disabled{opacity:.6;cursor:default}.frankie-root .frankie-choice-index{border:1px solid var(--frankie-border);background:var(--frankie-muted);width:24px;height:24px;color:var(--frankie-muted-foreground);border-radius:50%;flex:none;place-items:center;font-size:12px;font-weight:600;transition:background-color .15s,color .15s,border-color .15s;display:grid}.frankie-root .frankie-choice:hover:not(:disabled) .frankie-choice-index{background:var(--frankie-primary);border-color:var(--frankie-primary);color:var(--frankie-primary-foreground)}.frankie-root .frankie-choice-label{flex:1;min-width:0}.frankie-root .frankie-choice-go{color:var(--frankie-muted-foreground);opacity:0;flex:none;transition:opacity .15s,transform .15s;transform:translate(-4px)}.frankie-root .frankie-choice:hover:not(:disabled) .frankie-choice-go{opacity:1;color:var(--frankie-primary);transform:none}@media (prefers-reduced-motion:reduce){.frankie-root .frankie-choice,.frankie-root .frankie-choice-go,.frankie-root .frankie-choice-index{transition:none}}.frankie-root .frankie-choice-other{color:var(--frankie-muted-foreground);border-style:dashed}.frankie-root .frankie-choice-other .frankie-choice-index{background:0 0}.frankie-root .frankie-choice-other:hover:not(:disabled){color:var(--frankie-foreground)}.frankie-root .frankie-choice-other:hover:not(:disabled) .frankie-choice-index{background:var(--frankie-muted);border-color:var(--frankie-border);color:var(--frankie-foreground)}.frankie-root .frankie-choice-hint{color:var(--frankie-muted-foreground);flex:none;font-size:12px}.frankie-root .frankie-skeleton{flex-direction:column;gap:8px;max-width:min(420px,100%);padding:4px 0 6px;display:flex}.frankie-root .frankie-skeleton-line{background:linear-gradient(90deg, var(--frankie-muted-foreground) 25%, var(--frankie-muted-foreground) 37%, var(--frankie-muted-foreground) 63%);border-radius:6px;height:12px}@supports (color:color-mix(in lab, red, red)){.frankie-root .frankie-skeleton-line{background:linear-gradient(90deg, color-mix(in srgb, var(--frankie-muted-foreground) 11%, transparent) 25%, color-mix(in srgb, var(--frankie-muted-foreground) 19%, transparent) 37%, color-mix(in srgb, var(--frankie-muted-foreground) 11%, transparent) 63%)}}.frankie-root .frankie-skeleton-line{background-size:400% 100%;animation:2.2s ease-in-out infinite frankie-shimmer}.frankie-root .frankie-skeleton.is-delayed{animation:.25s .35s both frankie-skeleton-in}@keyframes frankie-skeleton-in{0%{opacity:0}to{opacity:1}}@keyframes frankie-shimmer{0%{background-position:100%}to{background-position:0}}@keyframes frankie-skeleton-pulse{0%,to{opacity:.45}50%{opacity:.85}}@media (prefers-reduced-motion:reduce){.frankie-root .frankie-skeleton-line{background:var(--frankie-muted-foreground)}@supports (color:color-mix(in lab, red, red)){.frankie-root .frankie-skeleton-line{background:color-mix(in srgb, var(--frankie-muted-foreground) 16%, transparent)}}.frankie-root .frankie-skeleton-line{animation:1.6s ease-in-out infinite frankie-skeleton-pulse}}.frankie-root:not(.frankie-chat-panel-fill) .frankie-composer-controls:has(.frankie-composer-actions>:not(input[hidden])){flex-wrap:wrap;align-items:center;row-gap:8px}.frankie-root:not(.frankie-chat-panel-fill) .frankie-composer-controls:has(.frankie-composer-actions>:not(input[hidden]))>textarea{flex:1 0 100%;order:-1;width:100%}.frankie-root:not(.frankie-chat-panel-fill) .frankie-composer-controls:has(.frankie-composer-actions>:not(input[hidden]))>.frankie-composer-actions{flex:auto}.frankie-root:not(.frankie-chat-panel-fill) .frankie-composer-controls:has(.frankie-composer-actions>:not(input[hidden]))>button{margin-left:auto}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-ease{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}`;
1005
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-ease:initial}}}@layer theme{.frankie-root{--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-emerald-400:oklch(76.5% .177 163.223);--color-emerald-500:oklch(69.6% .17 162.48);--color-emerald-600:oklch(59.6% .145 163.225);--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--font-weight-medium:500;--font-weight-semibold:600;--leading-tight:1.25;--radius-md:.375rem;--ease-in-out:cubic-bezier(.4, 0, .2, 1);--animate-spin:spin 1s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--color-background:var(--frankie-background);--color-foreground:var(--frankie-foreground);--color-primary:var(--frankie-primary)}}@layer components{.frankie-page-shell{background:var(--frankie-background);height:100%;min-height:0;color:var(--frankie-foreground);flex:1;display:flex}.frankie-page-main{flex-direction:column;flex:1;min-width:0;min-height:0;display:flex}.frankie-history-desktop{border-right:1px solid var(--frankie-border);background:var(--frankie-secondary);flex-direction:column;flex-shrink:0;gap:16px;width:260px;padding:20px 14px;transition:width .16s,padding .16s;display:flex;overflow:auto}.frankie-history-toggle{border:1px solid var(--frankie-border);background:var(--frankie-background);width:32px;height:32px;color:var(--frankie-muted-foreground);cursor:pointer;border-radius:8px;flex-shrink:0;justify-content:center;align-self:flex-end;align-items:center;display:flex}.frankie-history-toggle:hover{color:var(--frankie-foreground)}.frankie-history-collapsed{width:56px;padding:20px 8px;overflow:visible}.frankie-history-collapsed .frankie-history-toggle{align-self:center}.frankie-history-heading{justify-content:space-between;align-items:center;font-size:14px;display:flex}.frankie-new-chat{border:1px solid var(--frankie-border);background:var(--frankie-background);cursor:pointer;border-radius:10px;justify-content:center;align-items:center;gap:8px;min-height:44px;font-weight:600;display:flex}.frankie-history-search>span{color:var(--frankie-muted-foreground);margin-bottom:6px;font-size:12px;display:block}.frankie-history-search input{border:1px solid var(--frankie-border);background:var(--frankie-background);border-radius:8px;width:100%;min-height:40px;padding:8px 10px}.frankie-history-list{flex-direction:column;flex:1;gap:4px;display:flex}.frankie-history-list button{text-align:left;cursor:pointer;background:0 0;border:1px solid #0000;border-radius:8px;flex-direction:column;align-items:flex-start;gap:5px;min-height:54px;padding:10px;display:flex}.frankie-history-list button span{text-overflow:ellipsis;white-space:nowrap;width:100%;font-size:13px;overflow:hidden}.frankie-history-list small{color:var(--frankie-muted-foreground);font-size:11px}.frankie-history-list button:hover,.frankie-history-list button[aria-current]{background:var(--frankie-background);border-color:var(--frankie-border)}.frankie-history-desktop>p,.frankie-history-dialog p{color:var(--frankie-muted-foreground);font-size:13px}.frankie-header-caption{color:var(--frankie-muted-foreground);font-size:12px}.frankie-page-header button{cursor:pointer;justify-content:center;align-items:center;gap:6px;min-width:40px;min-height:40px;display:inline-flex}.frankie-chat-settings{position:relative}.frankie-chat-settings summary{cursor:pointer;border-radius:8px;place-items:center;width:40px;height:40px;list-style:none;display:grid}.frankie-chat-settings summary::-webkit-details-marker{display:none}.frankie-chat-settings>div{z-index:5;border:1px solid var(--frankie-border);background:var(--frankie-background);border-radius:12px;gap:12px;width:min(280px,80vw);padding:16px;font-size:13px;display:grid;position:absolute;top:46px;right:0;box-shadow:0 10px 30px #0002}.frankie-chat-settings p{color:var(--frankie-muted-foreground);margin:0}.frankie-loaded-skills{width:100%;max-width:760px;color:var(--frankie-muted-foreground);font-size:12px}.frankie-loaded-skills summary{cursor:pointer;padding:6px 0}.frankie-loaded-skills ul{margin:0;padding:4px 0;list-style:none}.frankie-loaded-skills li{gap:8px;padding:4px 0;display:flex}.frankie-loaded-skills small{opacity:.7}.frankie-history-dialog{background:var(--frankie-secondary);width:min(320px,86vw);max-width:none;height:100dvh;max-height:none;color:var(--frankie-foreground);border:0;margin:0;padding:0}.frankie-history-dialog::backdrop{background:#0008}.frankie-history-dialog>aside{height:100%;padding:calc(20px + env(safe-area-inset-top)) 16px calc(20px + env(safe-area-inset-bottom));flex-direction:column;gap:16px;display:flex;overflow:auto}.frankie-mobile-only{display:none!important}.frankie-widget-panel{max-height:calc(100dvh - 100px - var(--frankie-lift,0px))}.frankie-root button:focus-visible,.frankie-root summary:focus-visible,.frankie-root input:focus-visible{outline:2px solid var(--frankie-primary);outline-offset:3px}.frankie-root button:disabled{opacity:.5;cursor:not-allowed}@media (max-width:760px){.frankie-history-desktop{display:none}.frankie-mobile-only{display:inline-flex!important}.frankie-header-caption{display:none}.frankie-page-header{padding:6px 10px}.frankie-history-heading button{background:0 0;border:0;justify-content:center;align-items:center;min-width:44px;min-height:44px}.frankie-page-prompts{gap:8px}.frankie-widget-panel{width:calc(100vw - 32px)}}.frankie-root{--frankie-styles-ready:1;--frankie-background:#fff;--frankie-foreground:#0a0a0a;--frankie-primary:#171717;--frankie-primary-foreground:#fafafa;--frankie-secondary:#f5f5f5;--frankie-secondary-foreground:#171717;--frankie-muted:#f5f5f5;--frankie-muted-foreground:#737373;--frankie-border:#e5e5e5;--frankie-radius:.625rem;--frankie-font:ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;font-family:var(--frankie-font);color:var(--frankie-foreground);-webkit-font-smoothing:antialiased;line-height:1.5}.frankie-root.dark{--frankie-background:#0a0a0a;--frankie-foreground:#fafafa;--frankie-primary:#fafafa;--frankie-primary-foreground:#171717;--frankie-secondary:#262626;--frankie-secondary-foreground:#fafafa;--frankie-muted:#262626;--frankie-muted-foreground:#a3a3a3;--frankie-border:#262626}.frankie-root,.frankie-root *,.frankie-root :before,.frankie-root :after{box-sizing:border-box}.frankie-root button,.frankie-root textarea,.frankie-root input{font:inherit;color:inherit;margin:0}.frankie-root button{background-color:#0000;border:0 solid}.frankie-root textarea{background-color:var(--frankie-background)}.frankie-focus:focus-visible{outline:2px solid var(--frankie-primary);outline-offset:2px}.frankie-scroll{scrollbar-width:thin;scrollbar-color:var(--frankie-border) transparent}.frankie-prose>*+*{margin-top:.6rem}.frankie-prose p{white-space:pre-wrap;overflow-wrap:anywhere;margin:0;line-height:1.6}.frankie-prose>.frankie-h{letter-spacing:-.01em;margin-top:1.15rem;line-height:1.3}.frankie-prose>.frankie-h:first-child{margin-top:0}.frankie-prose h3.frankie-h{font-size:1.06em;font-weight:700}.frankie-prose h4.frankie-h{font-size:1em;font-weight:600}.frankie-prose h5.frankie-h{color:var(--frankie-muted-foreground);font-size:.92em;font-weight:600}.frankie-prose strong{font-weight:600}.frankie-prose ul,.frankie-prose ol{flex-direction:column;gap:.35rem;margin:0;padding-left:1.4rem;display:flex}.frankie-prose li{padding-left:.15rem;line-height:1.55}.frankie-prose li::marker{color:var(--frankie-muted-foreground)}.frankie-prose ul{list-style:outside}.frankie-prose ol{list-style:decimal}.frankie-prose a{color:var(--frankie-primary);text-underline-offset:2px;text-decoration:underline}.frankie-prose code{background-color:var(--frankie-muted);border-radius:.25rem;padding:.1em .3em;font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,monospace;font-size:.85em}.frankie-prose pre{border-radius:var(--frankie-radius);background-color:var(--frankie-muted);margin:0;padding:.625rem .75rem;overflow-x:auto}.frankie-prose pre code{background:0 0;padding:0}.frankie-chat-page{background:radial-gradient(60rem 24rem at 50% -12rem, var(--frankie-primary), transparent 65%), var(--frankie-background);flex-direction:column;min-width:0;display:flex;overflow:hidden}@supports (color:color-mix(in lab, red, red)){.frankie-chat-page{background:radial-gradient(60rem 24rem at 50% -12rem, color-mix(in srgb, var(--frankie-primary) 8%, transparent), transparent 65%), var(--frankie-background)}}.frankie-chat-page{color:var(--frankie-foreground)}.frankie-page-header{border-bottom:1px solid var(--frankie-border);background:var(--frankie-background);flex:0 0 56px;justify-content:space-between;align-items:center;gap:16px;min-height:56px;padding:0 24px;display:flex}@supports (color:color-mix(in lab, red, red)){.frankie-page-header{background:color-mix(in srgb, var(--frankie-background) 92%, transparent)}}.frankie-page-header{-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.frankie-page-header>div{align-items:center;gap:10px;display:flex}.frankie-page-header strong{font-size:.925rem;font-weight:650}.frankie-page-status{background:var(--frankie-primary);width:10px;height:10px;box-shadow:0 0 0 4px var(--frankie-primary);border-radius:999px}@supports (color:color-mix(in lab, red, red)){.frankie-page-status{box-shadow:0 0 0 4px color-mix(in srgb, var(--frankie-primary) 16%, transparent)}}.frankie-page-header button{border:1px solid var(--frankie-border);border-radius:calc(var(--frankie-radius) * .9);background:var(--frankie-secondary);cursor:pointer;min-height:36px;padding:0 13px}.frankie-page-header button:hover{border-color:var(--frankie-primary)}.frankie-page-canvas{flex:1;min-width:0;min-height:0;display:flex}.frankie-page-canvas>.frankie-inline{width:100%;max-width:56rem;margin:0 auto}.frankie-page-canvas .frankie-scroll{padding:2rem clamp(1rem,4vw,4rem) 1.25rem}.frankie-page-canvas .frankie-root>.border-t{background:linear-gradient(180deg, transparent, var(--frankie-background) 30%);border-top:0;padding:.75rem clamp(1rem,4vw,4rem) 1.5rem}.frankie-page-empty{text-align:center;flex-direction:column;flex-shrink:0;justify-content:safe center;align-items:center;gap:2rem;width:min(100%,44rem);min-height:100%;margin:auto;padding:clamp(2rem,7vh,4.5rem) 1rem 2rem;display:flex;container-type:inline-size}.frankie-page-welcome h1{letter-spacing:-.02em;margin:0;font-size:clamp(1.55rem,3.4vw,2rem);font-weight:700;line-height:1.15}.frankie-page-welcome p{max-width:34rem;color:var(--frankie-muted-foreground);margin:.6rem auto 0;font-size:1rem}.frankie-page-suggest{flex-direction:column;align-items:center;gap:1rem;width:100%;display:flex}.frankie-page-suggest-label{color:var(--frankie-muted-foreground);letter-spacing:.12em;text-transform:uppercase;margin:0;font-size:.72rem;font-weight:600}.frankie-page-prompts{grid-template-columns:1fr;gap:.75rem;width:100%;display:grid}@container (min-width:30rem){.frankie-page-prompts{grid-template-columns:repeat(2,minmax(0,1fr))}}.frankie-page-prompts button{border:1px solid var(--frankie-border);background:var(--frankie-background);text-align:left;cursor:pointer;border-radius:14px;align-items:flex-start;gap:.85rem;min-height:64px;padding:.9rem 1rem;transition:border-color .15s,background-color .15s,transform .12s;display:flex}.frankie-page-prompts button:hover:not(:disabled){border-color:var(--frankie-primary)}@supports (color:color-mix(in lab, red, red)){.frankie-page-prompts button:hover:not(:disabled){border-color:color-mix(in srgb, var(--frankie-primary) 45%, var(--frankie-border))}}.frankie-page-prompts button:hover:not(:disabled){background:var(--frankie-primary)}@supports (color:color-mix(in lab, red, red)){.frankie-page-prompts button:hover:not(:disabled){background:color-mix(in srgb, var(--frankie-primary) 4%, var(--frankie-background))}}.frankie-page-prompts button:hover:not(:disabled){transform:translateY(-1px)}.frankie-prompt-icon{background:var(--frankie-muted);width:34px;height:34px;color:var(--frankie-foreground);border-radius:9px;flex:none;place-items:center;display:grid}.frankie-prompt-text{flex-direction:column;gap:2px;min-width:0;display:flex}.frankie-prompt-text strong{font-size:.9rem;font-weight:600;line-height:1.3}.frankie-prompt-text small{color:var(--frankie-muted-foreground);font-size:.8rem;line-height:1.35;overflow:hidden}.frankie-page-suggest-hint{color:var(--frankie-muted-foreground);margin:0;font-size:.85rem}.frankie-widget-panel .frankie-page-empty{gap:1rem;padding:1rem .25rem}.frankie-widget-panel .frankie-page-welcome h1{font-size:1.25rem}.frankie-widget-panel .frankie-page-welcome p{margin-top:.35rem;font-size:.88rem;line-height:1.45}.frankie-widget-panel .frankie-page-suggest{gap:.55rem}.frankie-widget-panel .frankie-page-suggest-label{font-size:.66rem}.frankie-widget-panel .frankie-page-prompts{flex-wrap:wrap;justify-content:center;gap:.4rem;display:flex}.frankie-widget-panel .frankie-page-prompts button{border-radius:999px;align-items:center;gap:.4rem;max-width:100%;min-height:34px;padding:.3rem .8rem .3rem .45rem}.frankie-widget-panel .frankie-prompt-icon{border-radius:999px;width:22px;height:22px}.frankie-widget-panel .frankie-prompt-icon svg{width:13px;height:13px}.frankie-widget-panel .frankie-prompt-text strong{white-space:nowrap;text-overflow:ellipsis;font-size:.82rem;font-weight:550;overflow:hidden}.frankie-widget-panel .frankie-prompt-text small,.frankie-widget-panel .frankie-page-suggest-hint{display:none}@media (max-width:640px){.frankie-page-header{flex-basis:52px;min-height:52px;padding:0 12px}.frankie-page-canvas .frankie-scroll{padding:1.25rem .75rem .5rem}.frankie-page-canvas .frankie-root>.border-t{padding:.65rem .75rem calc(.65rem + env(safe-area-inset-bottom))}}}@layer utilities;.frankie-root .\\@container{container-type:inline-size}.frankie-root .invisible{visibility:hidden}.frankie-root .visible{visibility:visible}.frankie-root .absolute{position:absolute}.frankie-root .fixed{position:fixed}.frankie-root .relative{position:relative}.frankie-root .static{position:static}.frankie-root .sticky{position:sticky}.frankie-root .isolate{isolation:isolate}.frankie-root .container{width:100%}@media (min-width:40rem){.frankie-root .container{max-width:40rem}}@media (min-width:48rem){.frankie-root .container{max-width:48rem}}@media (min-width:64rem){.frankie-root .container{max-width:64rem}}@media (min-width:80rem){.frankie-root .container{max-width:80rem}}@media (min-width:96rem){.frankie-root .container{max-width:96rem}}.frankie-root .mt-0{margin-top:0}.frankie-root .mt-0\\.5{margin-top:calc(var(--spacing) * .5)}.frankie-root .mt-1{margin-top:var(--spacing)}.frankie-root .mt-2{margin-top:calc(var(--spacing) * 2)}.frankie-root .block{display:block}.frankie-root .contents{display:contents}.frankie-root .flex{display:flex}.frankie-root .grid{display:grid}.frankie-root .hidden{display:none}.frankie-root .inline{display:inline}.frankie-root .inline-flex{display:inline-flex}.frankie-root .table{display:table}.frankie-root .size-1{width:var(--spacing);height:var(--spacing)}.frankie-root .size-1\\.5{width:calc(var(--spacing) * 1.5);height:calc(var(--spacing) * 1.5)}.frankie-root .size-3{width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}.frankie-root .size-3\\.5{width:calc(var(--spacing) * 3.5);height:calc(var(--spacing) * 3.5)}.frankie-root .size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.frankie-root .size-5{width:calc(var(--spacing) * 5);height:calc(var(--spacing) * 5)}.frankie-root .size-7{width:calc(var(--spacing) * 7);height:calc(var(--spacing) * 7)}.frankie-root .size-8{width:calc(var(--spacing) * 8);height:calc(var(--spacing) * 8)}.frankie-root .size-9{width:calc(var(--spacing) * 9);height:calc(var(--spacing) * 9)}.frankie-root .size-12{width:calc(var(--spacing) * 12);height:calc(var(--spacing) * 12)}.frankie-root .size-full{width:100%;height:100%}.frankie-root .h-8{height:calc(var(--spacing) * 8)}.frankie-root .h-9{height:calc(var(--spacing) * 9)}.frankie-root .h-10{height:calc(var(--spacing) * 10)}.frankie-root .h-\\[32rem\\]{height:32rem}.frankie-root .h-full{height:100%}.frankie-root .h-px{height:1px}.frankie-root .min-h-7{min-height:calc(var(--spacing) * 7)}.frankie-root .min-h-\\[2\\.25rem\\]{min-height:2.25rem}.frankie-root .min-h-screen{min-height:100vh}.frankie-root .w-\\[22rem\\]{width:22rem}.frankie-root .w-full{width:100%}.frankie-root .max-w-\\[12rem\\]{max-width:12rem}.frankie-root .max-w-\\[14rem\\]{max-width:14rem}.frankie-root .max-w-\\[85\\%\\]{max-width:85%}.frankie-root .max-w-\\[calc\\(100vw-2rem\\)\\]{max-width:calc(100vw - 2rem)}.frankie-root .min-w-0{min-width:0}.frankie-root .flex-1{flex:1}.frankie-root .shrink-0{flex-shrink:0}.frankie-root .grow{flex-grow:1}.frankie-root .animate-pulse{animation:var(--animate-pulse)}.frankie-root .animate-spin{animation:var(--animate-spin)}.frankie-root .cursor-pointer{cursor:pointer}.frankie-root .resize{resize:both}.frankie-root .resize-none{resize:none}.frankie-root .list-none{list-style-type:none}.frankie-root .flex-col{flex-direction:column}.frankie-root .flex-wrap{flex-wrap:wrap}.frankie-root .items-center{align-items:center}.frankie-root .items-end{align-items:flex-end}.frankie-root .items-start{align-items:flex-start}.frankie-root .justify-center{justify-content:center}.frankie-root .justify-end{justify-content:flex-end}.frankie-root .gap-1{gap:var(--spacing)}.frankie-root .gap-1\\.5{gap:calc(var(--spacing) * 1.5)}.frankie-root .gap-2{gap:calc(var(--spacing) * 2)}.frankie-root .gap-3{gap:calc(var(--spacing) * 3)}.frankie-root .gap-4{gap:calc(var(--spacing) * 4)}.frankie-root .truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.frankie-root .overflow-hidden{overflow:hidden}.frankie-root .overflow-y-auto{overflow-y:auto}.frankie-root .overscroll-contain{overscroll-behavior:contain}.frankie-root .rounded{border-radius:.25rem}.frankie-root .rounded-\\[calc\\(var\\(--frankie-radius\\)\\+4px\\)\\]{border-radius:calc(var(--frankie-radius) + 4px)}.frankie-root .rounded-\\[calc\\(var\\(--frankie-radius\\)-2px\\)\\]{border-radius:calc(var(--frankie-radius) - 2px)}.frankie-root .rounded-\\[var\\(--frankie-radius\\)\\]{border-radius:var(--frankie-radius)}.frankie-root .rounded-full{border-radius:3.40282e38px}.frankie-root .rounded-md{border-radius:var(--radius-md)}.frankie-root .rounded-none{border-radius:0}.frankie-root .border{border-style:var(--tw-border-style);border-width:1px}.frankie-root .border-0{border-style:var(--tw-border-style);border-width:0}.frankie-root .border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.frankie-root .border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.frankie-root .border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.frankie-root .border-border{border-color:var(--frankie-border)}.frankie-root .border-transparent{border-color:#0000}.frankie-root .bg-background{background-color:var(--frankie-background)}.frankie-root .bg-border{background-color:var(--frankie-border)}.frankie-root .bg-emerald-500{background-color:var(--color-emerald-500)}.frankie-root .bg-emerald-500\\/10{background-color:#00bb7f1a}@supports (color:color-mix(in lab, red, red)){.frankie-root .bg-emerald-500\\/10{background-color:color-mix(in oklab, var(--color-emerald-500) 10%, transparent)}}.frankie-root .bg-muted{background-color:var(--frankie-muted)}.frankie-root .bg-muted-foreground{background-color:var(--frankie-muted-foreground)}.frankie-root .bg-primary{background-color:var(--frankie-primary)}.frankie-root .bg-red-500{background-color:var(--color-red-500)}.frankie-root .bg-red-500\\/10{background-color:#fb2c361a}@supports (color:color-mix(in lab, red, red)){.frankie-root .bg-red-500\\/10{background-color:color-mix(in oklab, var(--color-red-500) 10%, transparent)}}.frankie-root .bg-secondary{background-color:var(--frankie-secondary)}.frankie-root .object-cover{object-fit:cover}.frankie-root .p-3{padding:calc(var(--spacing) * 3)}.frankie-root .p-4{padding:calc(var(--spacing) * 4)}.frankie-root .px-1{padding-inline:var(--spacing)}.frankie-root .px-2{padding-inline:calc(var(--spacing) * 2)}.frankie-root .px-3{padding-inline:calc(var(--spacing) * 3)}.frankie-root .px-4{padding-inline:calc(var(--spacing) * 4)}.frankie-root .px-6{padding-inline:calc(var(--spacing) * 6)}.frankie-root .py-0{padding-block:0}.frankie-root .py-0\\.5{padding-block:calc(var(--spacing) * .5)}.frankie-root .py-1{padding-block:var(--spacing)}.frankie-root .py-2{padding-block:calc(var(--spacing) * 2)}.frankie-root .py-3{padding-block:calc(var(--spacing) * 3)}.frankie-root .pl-2{padding-left:calc(var(--spacing) * 2)}.frankie-root .text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.frankie-root .text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.frankie-root .text-\\[0\\.625rem\\]{font-size:.625rem}.frankie-root .text-\\[0\\.6875rem\\]{font-size:.6875rem}.frankie-root .text-\\[11px\\]{font-size:11px}.frankie-root .leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.frankie-root .font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.frankie-root .font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.frankie-root .whitespace-nowrap{white-space:nowrap}.frankie-root .text-emerald-600{color:var(--color-emerald-600)}.frankie-root .text-foreground{color:var(--frankie-foreground)}.frankie-root .text-muted-foreground{color:var(--frankie-muted-foreground)}.frankie-root .text-primary{color:var(--frankie-primary)}.frankie-root .text-primary-foreground{color:var(--frankie-primary-foreground)}.frankie-root .text-red-600{color:var(--color-red-600)}.frankie-root .text-secondary-foreground{color:var(--frankie-secondary-foreground)}.frankie-root .italic{font-style:italic}.frankie-root .underline-offset-4{text-underline-offset:4px}.frankie-root .opacity-60{opacity:.6}.frankie-root .opacity-70{opacity:.7}.frankie-root .shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.frankie-root .shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.frankie-root .shadow-none{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.frankie-root .outline{outline-style:var(--tw-outline-style);outline-width:1px}.frankie-root .transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.frankie-root .transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.frankie-root .transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.frankie-root .ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.frankie-root .select-all{-webkit-user-select:all;user-select:all}.frankie-root .placeholder\\:text-muted-foreground::placeholder{color:var(--frankie-muted-foreground)}@media (hover:hover){.frankie-root .hover\\:border-border:hover{border-color:var(--frankie-border)}.frankie-root .hover\\:bg-muted:hover{background-color:var(--frankie-muted)}.frankie-root .hover\\:text-foreground:hover{color:var(--frankie-foreground)}.frankie-root .hover\\:underline:hover{text-decoration-line:underline}.frankie-root .hover\\:opacity-90:hover{opacity:.9}.frankie-root .hover\\:opacity-100:hover{opacity:1}}.frankie-root .focus-visible\\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.frankie-root .focus-visible\\:ring-primary:focus-visible{--tw-ring-color:var(--frankie-primary)}.frankie-root .focus-visible\\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.frankie-root .disabled\\:pointer-events-none:disabled{pointer-events:none}.frankie-root .disabled\\:cursor-not-allowed:disabled{cursor:not-allowed}.frankie-root .disabled\\:opacity-50:disabled{opacity:.5}.frankie-root .dark\\:text-emerald-400:where(.dark,.dark *){color:var(--color-emerald-400)}.frankie-root .dark\\:text-red-400:where(.dark,.dark *){color:var(--color-red-400)}.frankie-root .\\[\\&_svg\\]\\:pointer-events-none svg{pointer-events:none}.frankie-root .\\[\\&_svg\\]\\:size-4 svg{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.frankie-root .\\[\\&_svg\\]\\:shrink-0 svg{flex-shrink:0}.frankie-root .\\[\\&\\:\\:-webkit-details-marker\\]\\:hidden::-webkit-details-marker{display:none}.frankie-root.frankie-chat-panel{min-height:0;position:relative}.frankie-root.frankie-widget-panel{box-shadow:0 32px 72px -18px var(--frankie-primary), 0 12px 28px -12px #0f172a47, 0 0 0 1px var(--frankie-foreground)}@supports (color:color-mix(in lab, red, red)){.frankie-root.frankie-widget-panel{box-shadow:0 32px 72px -18px color-mix(in srgb, var(--frankie-primary) 22%, #0f172a6b), 0 12px 28px -12px #0f172a47, 0 0 0 1px color-mix(in srgb, var(--frankie-foreground) 8%, transparent)}}.frankie-root.frankie-widget-panel.dark{box-shadow:0 34px 80px -16px #000000b8, 0 14px 32px -12px #0009, 0 0 0 1px var(--frankie-foreground)}@supports (color:color-mix(in lab, red, red)){.frankie-root.frankie-widget-panel.dark{box-shadow:0 34px 80px -16px #000000b8, 0 14px 32px -12px #0009, 0 0 0 1px color-mix(in srgb, var(--frankie-foreground) 12%, transparent)}}.frankie-root .frankie-agent-context-wrap{flex:none;justify-content:center;padding:12px 10px;display:flex}.frankie-root .frankie-agent-context{max-width:100%;color:var(--frankie-foreground);font-size:13px;position:relative}.frankie-root .frankie-agent-context>summary{border:1px solid var(--frankie-border);background:var(--frankie-background);cursor:pointer;white-space:nowrap;border-radius:999px;justify-content:center;align-items:center;gap:10px;min-height:44px;padding:7px 13px;list-style:none;display:flex;box-shadow:0 1px 3px #0000000d}.frankie-root .frankie-agent-context>summary::-webkit-details-marker{display:none}.frankie-root .frankie-agent-context>summary>svg{color:var(--frankie-muted-foreground);flex:none}.frankie-root .frankie-context-count{background:var(--frankie-muted);color:var(--frankie-muted-foreground);border-radius:999px;padding:2px 10px;font-size:12px}.frankie-root .frankie-context-status{color:var(--frankie-muted-foreground);align-items:center;gap:6px;font-size:12px;display:flex}.frankie-root .frankie-context-status i{background:currentColor;border-radius:50%;width:7px;height:7px}.frankie-root .frankie-context-status[data-active=true]{color:#00976b}.frankie-root .frankie-context-detail{z-index:10;border:1px solid var(--frankie-border);background:var(--frankie-background);border-radius:16px;width:340px;max-width:calc(100vw - 32px);padding:18px;position:absolute;top:calc(100% + 10px);left:50%;transform:translate(-50%);box-shadow:0 12px 32px #00000016}.frankie-root .frankie-context-detail p{color:var(--frankie-muted-foreground);margin:10px 0 0;font-size:12px;line-height:1.6}.frankie-root .frankie-context-detail ul{max-height:220px;margin:12px 0;padding:0;list-style:none;overflow:auto}.frankie-root .frankie-context-detail li{border-bottom:1px solid var(--frankie-border);overflow-wrap:anywhere;justify-content:space-between;gap:12px;padding:8px 0;display:flex}.frankie-root .frankie-context-detail small{color:var(--frankie-muted-foreground);flex:none}.frankie-root .frankie-sr-only{clip:rect(0,0,0,0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.frankie-root.frankie-chat-panel-fill{--frankie-canvas:var(--frankie-background)}@supports (color:color-mix(in lab, red, red)){.frankie-root.frankie-chat-panel-fill{--frankie-canvas:color-mix(in srgb,var(--frankie-background) 60%,var(--frankie-muted))}}.frankie-root.frankie-chat-panel-fill{background:var(--frankie-canvas)}.frankie-root.frankie-chat-panel-fill .frankie-agent-context-wrap{padding:44px 16px 26px}.frankie-root.frankie-chat-panel-fill .frankie-transcript{padding:14px max(24px,50% - 480px) 24px}.frankie-root.frankie-chat-panel-fill .frankie-message-list{gap:38px}.frankie-root.frankie-chat-panel-fill .frankie-user-bubble{background:var(--frankie-muted);color:var(--frankie-foreground);white-space:pre-wrap;overflow-wrap:anywhere;border-radius:24px;padding:12px 20px;font-size:15px}.frankie-root.frankie-chat-panel-fill .frankie-assistant-content{flex:1;max-width:100%;font-size:15px;line-height:1.7}.frankie-root.frankie-chat-panel-fill .frankie-assistant-message{gap:14px}.frankie-root .frankie-thinking{color:var(--frankie-muted-foreground);gap:5px}.frankie-root .frankie-thinking-label{margin-right:6px;font-size:14px}.frankie-root.frankie-chat-panel-fill .frankie-composer-footer{background:0 0;border:0;flex:none;padding:16px max(24px,50% - 500px) 24px}.frankie-root.frankie-chat-panel-fill .frankie-composer{border:1px solid var(--frankie-border);background:var(--frankie-background);border-radius:28px;padding:14px;box-shadow:0 2px 4px #0000000a}.frankie-root.frankie-chat-panel-fill .frankie-composer:focus-within{border-color:var(--frankie-foreground)}@supports (color:color-mix(in lab, red, red)){.frankie-root.frankie-chat-panel-fill .frankie-composer:focus-within{border-color:color-mix(in srgb,var(--frankie-foreground) 32%,var(--frankie-border))}}.frankie-root.frankie-chat-panel-fill .frankie-composer:focus-within{box-shadow:0 0 0 2px var(--frankie-primary)}@supports (color:color-mix(in lab, red, red)){.frankie-root.frankie-chat-panel-fill .frankie-composer:focus-within{box-shadow:0 0 0 2px color-mix(in srgb,var(--frankie-primary) 8%,transparent)}}.frankie-root.frankie-chat-panel-fill .frankie-composer-controls{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.frankie-root.frankie-chat-panel-fill .frankie-composer textarea{resize:none;width:100%;min-height:32px;max-height:140px;color:var(--frankie-foreground);box-shadow:none;background:0 0;border:0;border-radius:0;outline:none;flex:0 0 100%;order:-1;margin-bottom:4px;padding:2px 6px;font-size:16px}.frankie-root.frankie-chat-panel-fill .frankie-composer button[aria-label=Send],.frankie-root.frankie-chat-panel-fill .frankie-composer button[aria-label=Stop]{background:var(--frankie-primary);width:42px;height:42px;color:var(--frankie-primary-foreground);border:0;border-radius:50%;margin-left:auto}.frankie-root.frankie-chat-panel-fill .frankie-composer button[aria-label=Attach\\ files]{border-radius:50%;width:42px;height:42px}.frankie-root .frankie-composer-actions{align-items:center;gap:6px;min-width:0;display:flex}.frankie-root .frankie-composer-meta{align-items:center;gap:8px;margin-top:6px;padding:0 2px;display:flex}.frankie-root .frankie-model-picker{align-items:center;min-width:0;display:inline-flex}.frankie-root .frankie-model-select{appearance:none;max-width:12rem;color:var(--frankie-muted-foreground);font:inherit;cursor:pointer;text-overflow:ellipsis;background-color:#0000;background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%238b8b8b' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");background-position:right 6px center;background-repeat:no-repeat;background-size:11px;border:0;border-radius:8px;padding:5px 22px 5px 8px;font-size:12px;font-weight:500;line-height:1;transition:background-color .12s,color .12s}.frankie-root .frankie-model-select:hover{background-color:var(--frankie-muted);color:var(--frankie-foreground)}.frankie-root .frankie-model-select:disabled{opacity:.5;cursor:not-allowed}.frankie-root .frankie-model-select option{color:var(--frankie-foreground);background:var(--frankie-background);font-weight:400}.frankie-root .frankie-history-desktop{background:var(--frankie-background);width:290px;padding:20px 12px}.frankie-root .frankie-history-collapsed{width:56px;padding:20px 8px}.frankie-root .frankie-new-chat{background:0 0;border:0;justify-content:flex-start;padding:8px 12px;font-size:15px}.frankie-root .frankie-history-heading{color:var(--frankie-muted-foreground);padding:0 12px;font-size:12px;font-weight:400}.frankie-root .frankie-history-list button{min-height:44px;padding:10px 12px}.frankie-root .frankie-history-list button span{font-size:14px}.frankie-root .frankie-history-list button[aria-current],.frankie-root .frankie-history-list button:hover{background:var(--frankie-muted);border-color:#0000}.frankie-root .frankie-history-list small{display:none}.frankie-root .frankie-history-group{flex-direction:column;gap:2px;display:flex}.frankie-root .frankie-history-group+.frankie-history-group{margin-top:12px}.frankie-root .frankie-history-group-label{letter-spacing:.04em;color:var(--frankie-muted-foreground);margin:0;padding:4px 12px;font-size:11px;font-weight:600}.frankie-root .frankie-page-header{background:var(--frankie-background);height:56px;min-height:56px}.frankie-root .frankie-page-header>div{min-width:0}.frankie-root .frankie-thread-title{text-overflow:ellipsis;white-space:nowrap;max-width:55vw;font-weight:500;overflow:hidden}.frankie-root .frankie-page-header button{background:0 0;border-color:#0000}.frankie-root .frankie-page-canvas>.frankie-inline{max-width:none}@media (max-width:760px){.frankie-root.frankie-chat-panel-fill .frankie-agent-context-wrap{padding:20px 8px 14px}.frankie-root.frankie-chat-panel-fill .frankie-transcript{padding:12px 16px 16px}.frankie-root.frankie-chat-panel-fill .frankie-composer-footer{padding:10px 12px calc(12px + env(safe-area-inset-bottom))}.frankie-root .frankie-agent-context>summary{gap:6px;padding:7px 9px;font-size:12px}.frankie-root .frankie-context-count{padding:2px 7px;font-size:11px}.frankie-root .frankie-context-status{gap:4px;font-size:11px}.frankie-root .frankie-agent-context>summary>svg{width:14px}.frankie-root .frankie-thread-title{max-width:42vw}}.frankie-root .frankie-agent-context>summary>svg:first-child{box-sizing:content-box;background:var(--frankie-muted);border-radius:50%;padding:4px}.frankie-root.frankie-chat-panel-fill .frankie-agent-context>summary{font-size:14px}.frankie-root .frankie-agent-context>summary>span:first-of-type{border-right:1px solid var(--frankie-border);padding-right:10px}@media (max-width:760px){.frankie-root .frankie-page-header button>span{display:none}}.frankie-root .frankie-choices{flex-direction:column;gap:8px;margin-top:12px;display:flex}.frankie-root .frankie-choice{text-align:left;cursor:pointer;border:1px solid var(--frankie-border);border-radius:var(--frankie-radius);background:var(--frankie-background);width:100%;color:var(--frankie-foreground);font:inherit;align-items:center;gap:12px;padding:11px 14px;font-size:14px;line-height:1.4;transition:border-color .15s,background-color .15s,transform .12s;display:flex}.frankie-root .frankie-choice:hover:not(:disabled){border-color:var(--frankie-primary)}@supports (color:color-mix(in lab, red, red)){.frankie-root .frankie-choice:hover:not(:disabled){border-color:color-mix(in srgb, var(--frankie-primary) 55%, var(--frankie-border))}}.frankie-root .frankie-choice:hover:not(:disabled){background:var(--frankie-primary)}@supports (color:color-mix(in lab, red, red)){.frankie-root .frankie-choice:hover:not(:disabled){background:color-mix(in srgb, var(--frankie-primary) 6%, var(--frankie-background))}}.frankie-root .frankie-choice:active:not(:disabled){transform:scale(.99)}.frankie-root .frankie-choice:focus-visible{box-shadow:0 0 0 2px var(--frankie-primary);outline:none}@supports (color:color-mix(in lab, red, red)){.frankie-root .frankie-choice:focus-visible{box-shadow:0 0 0 2px color-mix(in srgb, var(--frankie-primary) 40%, transparent)}}.frankie-root .frankie-choice:disabled{opacity:.6;cursor:default}.frankie-root .frankie-choice-index{border:1px solid var(--frankie-border);background:var(--frankie-muted);width:24px;height:24px;color:var(--frankie-muted-foreground);border-radius:50%;flex:none;place-items:center;font-size:12px;font-weight:600;transition:background-color .15s,color .15s,border-color .15s;display:grid}.frankie-root .frankie-choice:hover:not(:disabled) .frankie-choice-index{background:var(--frankie-primary);border-color:var(--frankie-primary);color:var(--frankie-primary-foreground)}.frankie-root .frankie-choice-label{flex:1;min-width:0}.frankie-root .frankie-choice-go{color:var(--frankie-muted-foreground);opacity:0;flex:none;transition:opacity .15s,transform .15s;transform:translate(-4px)}.frankie-root .frankie-choice:hover:not(:disabled) .frankie-choice-go{opacity:1;color:var(--frankie-primary);transform:none}@media (prefers-reduced-motion:reduce){.frankie-root .frankie-choice,.frankie-root .frankie-choice-go,.frankie-root .frankie-choice-index{transition:none}}.frankie-root .frankie-choice-other{color:var(--frankie-muted-foreground);border-style:dashed}.frankie-root .frankie-choice-other .frankie-choice-index{background:0 0}.frankie-root .frankie-choice-other:hover:not(:disabled){color:var(--frankie-foreground)}.frankie-root .frankie-choice-other:hover:not(:disabled) .frankie-choice-index{background:var(--frankie-muted);border-color:var(--frankie-border);color:var(--frankie-foreground)}.frankie-root .frankie-choice-hint{color:var(--frankie-muted-foreground);flex:none;font-size:12px}.frankie-root .frankie-skeleton{flex-direction:column;gap:8px;max-width:min(420px,100%);padding:4px 0 6px;display:flex}.frankie-root .frankie-skeleton-line{background:linear-gradient(90deg, var(--frankie-muted-foreground) 25%, var(--frankie-muted-foreground) 37%, var(--frankie-muted-foreground) 63%);border-radius:6px;height:12px}@supports (color:color-mix(in lab, red, red)){.frankie-root .frankie-skeleton-line{background:linear-gradient(90deg, color-mix(in srgb, var(--frankie-muted-foreground) 11%, transparent) 25%, color-mix(in srgb, var(--frankie-muted-foreground) 19%, transparent) 37%, color-mix(in srgb, var(--frankie-muted-foreground) 11%, transparent) 63%)}}.frankie-root .frankie-skeleton-line{background-size:400% 100%;animation:2.2s ease-in-out infinite frankie-shimmer}.frankie-root .frankie-skeleton.is-delayed{animation:.25s .35s both frankie-skeleton-in}@keyframes frankie-skeleton-in{0%{opacity:0}to{opacity:1}}@keyframes frankie-shimmer{0%{background-position:100%}to{background-position:0}}@keyframes frankie-skeleton-pulse{0%,to{opacity:.45}50%{opacity:.85}}@media (prefers-reduced-motion:reduce){.frankie-root .frankie-skeleton-line{background:var(--frankie-muted-foreground)}@supports (color:color-mix(in lab, red, red)){.frankie-root .frankie-skeleton-line{background:color-mix(in srgb, var(--frankie-muted-foreground) 16%, transparent)}}.frankie-root .frankie-skeleton-line{animation:1.6s ease-in-out infinite frankie-skeleton-pulse}}.frankie-root:not(.frankie-chat-panel-fill) .frankie-composer-controls:has(.frankie-composer-actions>:not(input[hidden])){flex-wrap:wrap;align-items:center;row-gap:8px}.frankie-root:not(.frankie-chat-panel-fill) .frankie-composer-controls:has(.frankie-composer-actions>:not(input[hidden]))>textarea{flex:1 0 100%;order:-1;width:100%}.frankie-root:not(.frankie-chat-panel-fill) .frankie-composer-controls:has(.frankie-composer-actions>:not(input[hidden]))>.frankie-composer-actions{flex:auto}.frankie-root:not(.frankie-chat-panel-fill) .frankie-composer-controls:has(.frankie-composer-actions>:not(input[hidden]))>button{margin-left:auto}.frankie-root .frankie-action{border:1px solid var(--frankie-border);border-radius:var(--frankie-radius);background:var(--frankie-background);color:var(--frankie-foreground);flex-direction:column;gap:10px;margin-top:12px;padding:12px 14px;font-size:14px;line-height:1.4;display:flex}.frankie-root .frankie-action.is-pending{border-color:var(--frankie-primary)}@supports (color:color-mix(in lab, red, red)){.frankie-root .frankie-action.is-pending{border-color:color-mix(in srgb, var(--frankie-primary) 45%, var(--frankie-border))}}.frankie-root .frankie-action.is-pending{background:var(--frankie-primary)}@supports (color:color-mix(in lab, red, red)){.frankie-root .frankie-action.is-pending{background:color-mix(in srgb, var(--frankie-primary) 5%, var(--frankie-background))}}.frankie-root .frankie-action-head{align-items:flex-start;gap:10px;display:flex}.frankie-root .frankie-action-icon{color:var(--frankie-primary);flex-shrink:0;margin-top:2px}.frankie-root .frankie-action-title{flex-direction:column;gap:2px;min-width:0;display:flex}.frankie-root .frankie-action-title strong{overflow-wrap:anywhere;font-weight:600}.frankie-root .frankie-action-title span{color:var(--frankie-muted-foreground);font-size:12px}.frankie-root .frankie-action-route{border-radius:calc(var(--frankie-radius) * .6);background:var(--frankie-muted);overflow-wrap:anywhere;padding:6px 8px;font-size:12px;display:block}.frankie-root .frankie-action-route span{font-weight:600}.frankie-root .frankie-action-fields{gap:6px;margin:0;display:grid}.frankie-root .frankie-action-fields>div{grid-template-columns:minmax(0,35%) minmax(0,1fr);gap:10px;display:grid}.frankie-root .frankie-action-fields dt{color:var(--frankie-muted-foreground);overflow-wrap:anywhere;font-size:12px}.frankie-root .frankie-action-fields dd{white-space:pre-wrap;overflow-wrap:anywhere;max-height:8.5em;margin:0;font-size:13px;overflow:auto}.frankie-root .frankie-action-buttons{flex-wrap:wrap;gap:8px;display:flex}.frankie-root .frankie-action-buttons button{cursor:pointer;font:inherit;border-radius:var(--frankie-radius);border:1px solid var(--frankie-border);align-items:center;gap:6px;padding:7px 14px;font-size:14px;font-weight:500;transition:background-color .15s,border-color .15s;display:inline-flex}.frankie-root .frankie-action-approve{background:var(--frankie-primary);color:var(--frankie-primary-foreground);border-color:var(--frankie-primary)}.frankie-root .frankie-action-approve:hover:not(:disabled){background:var(--frankie-primary)}@supports (color:color-mix(in lab, red, red)){.frankie-root .frankie-action-approve:hover:not(:disabled){background:color-mix(in srgb, var(--frankie-primary) 88%, black)}}.frankie-root .frankie-action-cancel{background:var(--frankie-background);color:var(--frankie-foreground)}.frankie-root .frankie-action-cancel:hover:not(:disabled){background:var(--frankie-muted)}.frankie-root .frankie-action-buttons button:disabled{opacity:.55;cursor:not-allowed}.frankie-root .frankie-action-buttons button:focus-visible{box-shadow:0 0 0 2px var(--frankie-primary);outline:none}@supports (color:color-mix(in lab, red, red)){.frankie-root .frankie-action-buttons button:focus-visible{box-shadow:0 0 0 2px color-mix(in srgb, var(--frankie-primary) 40%, transparent)}}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-ease{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}`;
974
1006
 
975
1007
  // src/lib/ensure-frankie-styles.ts
976
1008
  var STYLE_ELEMENT_ID = "frankie-fallback-styles";
@@ -1044,8 +1076,8 @@ function bottomObstruction(root, position, offset) {
1044
1076
  seen.add(bar);
1045
1077
  const rect = bar.getBoundingClientRect();
1046
1078
  const anchoredToBottom = rect.bottom >= height - 4;
1047
- const short = rect.height > 0 && rect.height < height * 0.4;
1048
- if (anchoredToBottom && short) lift = Math.max(lift, height - rect.top);
1079
+ const short2 = rect.height > 0 && rect.height < height * 0.4;
1080
+ if (anchoredToBottom && short2) lift = Math.max(lift, height - rect.top);
1049
1081
  }
1050
1082
  }
1051
1083
  return Math.round(lift);
@@ -1131,7 +1163,7 @@ function Button({ className, variant, size, asChild = false, ...props }) {
1131
1163
  }
1132
1164
 
1133
1165
  // src/components/chat/ChatPanel.tsx
1134
- import { RotateCcw, X as X3 } from "lucide-react";
1166
+ import { RotateCcw, X as X4 } from "lucide-react";
1135
1167
  import { useEffect as useEffect5, useRef as useRef4, useState as useState6 } from "react";
1136
1168
 
1137
1169
  // src/components/ui/avatar.tsx
@@ -1507,7 +1539,7 @@ function readAsBase64(file) {
1507
1539
  }
1508
1540
 
1509
1541
  // src/components/chat/MessageBubble.tsx
1510
- import { Check as Check2, Copy, Paperclip as Paperclip2 } from "lucide-react";
1542
+ import { Check as Check3, Copy, Paperclip as Paperclip2 } from "lucide-react";
1511
1543
  import { memo as memo2, useState as useState5 } from "react";
1512
1544
 
1513
1545
  // src/lib/choices.ts
@@ -1528,9 +1560,68 @@ function parseOptionLines(block) {
1528
1560
  return block.split("\n").map((line) => line.trim().replace(/^([-*+]|\d+[.)])\s+/, "").trim()).filter(Boolean);
1529
1561
  }
1530
1562
 
1563
+ // src/components/chat/ActionConfirm.tsx
1564
+ import { Check, ShieldAlert, X as X2 } from "lucide-react";
1565
+ import { jsx as jsx10, jsxs as jsxs4 } from "react/jsx-runtime";
1566
+ function ActionConfirm({
1567
+ action,
1568
+ onAnswer,
1569
+ disabled,
1570
+ live
1571
+ }) {
1572
+ const pending = action.state === "pending";
1573
+ const fields = inputFields(action.preview.input);
1574
+ const status = pending ? live ? void 0 : "Not run" : action.state === "approved" ? "Approved" : "Cancelled";
1575
+ return /* @__PURE__ */ jsxs4("div", { className: "frankie-action" + (pending && live ? " is-pending" : ""), role: "group", "aria-label": `Approve: ${action.label}`, children: [
1576
+ /* @__PURE__ */ jsxs4("div", { className: "frankie-action-head", children: [
1577
+ /* @__PURE__ */ jsx10(ShieldAlert, { className: "frankie-action-icon size-4", "aria-hidden": true }),
1578
+ /* @__PURE__ */ jsxs4("div", { className: "frankie-action-title", children: [
1579
+ /* @__PURE__ */ jsx10("strong", { children: action.label }),
1580
+ /* @__PURE__ */ jsx10("span", { children: pending && live ? "Needs your approval before it runs" : status })
1581
+ ] })
1582
+ ] }),
1583
+ action.preview.method && action.preview.path ? /* @__PURE__ */ jsxs4("code", { className: "frankie-action-route", children: [
1584
+ /* @__PURE__ */ jsx10("span", { children: action.preview.method }),
1585
+ " ",
1586
+ action.preview.path
1587
+ ] }) : null,
1588
+ fields.length ? /* @__PURE__ */ jsx10("dl", { className: "frankie-action-fields", children: fields.map(([key, value]) => /* @__PURE__ */ jsxs4("div", { children: [
1589
+ /* @__PURE__ */ jsx10("dt", { children: key }),
1590
+ /* @__PURE__ */ jsx10("dd", { children: value })
1591
+ ] }, key)) }) : null,
1592
+ pending && live && onAnswer ? /* @__PURE__ */ jsxs4("div", { className: "frankie-action-buttons", children: [
1593
+ /* @__PURE__ */ jsxs4("button", { type: "button", className: "frankie-action-approve", disabled, onClick: () => onAnswer(action.toolUseId, true), children: [
1594
+ /* @__PURE__ */ jsx10(Check, { className: "size-4", "aria-hidden": true }),
1595
+ " Approve"
1596
+ ] }),
1597
+ /* @__PURE__ */ jsxs4("button", { type: "button", className: "frankie-action-cancel", disabled, onClick: () => onAnswer(action.toolUseId, false), children: [
1598
+ /* @__PURE__ */ jsx10(X2, { className: "size-4", "aria-hidden": true }),
1599
+ " Cancel"
1600
+ ] })
1601
+ ] }) : null
1602
+ ] });
1603
+ }
1604
+ function inputFields(input) {
1605
+ if (input === void 0 || input === null) return [];
1606
+ if (typeof input !== "object" || Array.isArray(input)) return [["input", short(input)]];
1607
+ const rows = [];
1608
+ for (const [key, value] of Object.entries(input)) {
1609
+ if (value === void 0) continue;
1610
+ if (key === "body" && value && typeof value === "object" && !Array.isArray(value)) {
1611
+ for (const [field, inner] of Object.entries(value)) rows.push([field, short(inner)]);
1612
+ continue;
1613
+ }
1614
+ rows.push([key, short(value)]);
1615
+ }
1616
+ return rows;
1617
+ }
1618
+ function short(value) {
1619
+ return typeof value === "string" ? value : JSON.stringify(value, null, 1);
1620
+ }
1621
+
1531
1622
  // src/components/chat/Choices.tsx
1532
1623
  import { ArrowRight, PencilLine } from "lucide-react";
1533
- import { jsx as jsx10, jsxs as jsxs4 } from "react/jsx-runtime";
1624
+ import { jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
1534
1625
  function Choices({
1535
1626
  options,
1536
1627
  onPick,
@@ -1538,8 +1629,8 @@ function Choices({
1538
1629
  disabled
1539
1630
  }) {
1540
1631
  if (options.length === 0) return null;
1541
- return /* @__PURE__ */ jsxs4("div", { className: "frankie-choices", role: "group", "aria-label": "Choose an option", children: [
1542
- options.map((option, index) => /* @__PURE__ */ jsxs4(
1632
+ return /* @__PURE__ */ jsxs5("div", { className: "frankie-choices", role: "group", "aria-label": "Choose an option", children: [
1633
+ options.map((option, index) => /* @__PURE__ */ jsxs5(
1543
1634
  "button",
1544
1635
  {
1545
1636
  type: "button",
@@ -1547,14 +1638,14 @@ function Choices({
1547
1638
  disabled,
1548
1639
  onClick: () => onPick(option),
1549
1640
  children: [
1550
- /* @__PURE__ */ jsx10("span", { className: "frankie-choice-index", "aria-hidden": true, children: index + 1 }),
1551
- /* @__PURE__ */ jsx10("span", { className: "frankie-choice-label", children: option }),
1552
- /* @__PURE__ */ jsx10(ArrowRight, { className: "frankie-choice-go size-4", "aria-hidden": true })
1641
+ /* @__PURE__ */ jsx11("span", { className: "frankie-choice-index", "aria-hidden": true, children: index + 1 }),
1642
+ /* @__PURE__ */ jsx11("span", { className: "frankie-choice-label", children: option }),
1643
+ /* @__PURE__ */ jsx11(ArrowRight, { className: "frankie-choice-go size-4", "aria-hidden": true })
1553
1644
  ]
1554
1645
  },
1555
1646
  `${index}-${option}`
1556
1647
  )),
1557
- onSomethingElse ? /* @__PURE__ */ jsxs4(
1648
+ onSomethingElse ? /* @__PURE__ */ jsxs5(
1558
1649
  "button",
1559
1650
  {
1560
1651
  type: "button",
@@ -1562,9 +1653,9 @@ function Choices({
1562
1653
  disabled,
1563
1654
  onClick: onSomethingElse,
1564
1655
  children: [
1565
- /* @__PURE__ */ jsx10("span", { className: "frankie-choice-index", "aria-hidden": true, children: /* @__PURE__ */ jsx10(PencilLine, { className: "size-3.5" }) }),
1566
- /* @__PURE__ */ jsx10("span", { className: "frankie-choice-label", children: "Something else\u2026" }),
1567
- /* @__PURE__ */ jsx10("span", { className: "frankie-choice-hint", "aria-hidden": true, children: "Type your own" })
1656
+ /* @__PURE__ */ jsx11("span", { className: "frankie-choice-index", "aria-hidden": true, children: /* @__PURE__ */ jsx11(PencilLine, { className: "size-3.5" }) }),
1657
+ /* @__PURE__ */ jsx11("span", { className: "frankie-choice-label", children: "Something else\u2026" }),
1658
+ /* @__PURE__ */ jsx11("span", { className: "frankie-choice-hint", "aria-hidden": true, children: "Type your own" })
1568
1659
  ]
1569
1660
  }
1570
1661
  ) : null
@@ -1573,10 +1664,10 @@ function Choices({
1573
1664
 
1574
1665
  // src/components/chat/Markdown.tsx
1575
1666
  import { Fragment as Fragment2, memo, useMemo as useMemo2 } from "react";
1576
- import { jsx as jsx11 } from "react/jsx-runtime";
1667
+ import { jsx as jsx12 } from "react/jsx-runtime";
1577
1668
  var Markdown = memo(function Markdown2({ text, className }) {
1578
1669
  const blocks = useMemo2(() => renderBlocks(text), [text]);
1579
- return /* @__PURE__ */ jsx11("div", { className: cn("frankie-prose", className), children: blocks });
1670
+ return /* @__PURE__ */ jsx12("div", { className: cn("frankie-prose", className), children: blocks });
1580
1671
  });
1581
1672
  function renderBlocks(text) {
1582
1673
  const lines = text.split("\n");
@@ -1586,13 +1677,13 @@ function renderBlocks(text) {
1586
1677
  let code = null;
1587
1678
  const flushParagraph = () => {
1588
1679
  if (paragraph.length === 0) return;
1589
- blocks.push(/* @__PURE__ */ jsx11("p", { children: renderInline(paragraph.join(" ")) }, `p${blocks.length}`));
1680
+ blocks.push(/* @__PURE__ */ jsx12("p", { children: renderInline(paragraph.join(" ")) }, `p${blocks.length}`));
1590
1681
  paragraph = [];
1591
1682
  };
1592
1683
  const flushList = () => {
1593
1684
  if (!list) return;
1594
- const items = list.items.map((item, index) => /* @__PURE__ */ jsx11("li", { children: renderInline(item) }, index));
1595
- blocks.push(list.ordered ? /* @__PURE__ */ jsx11("ol", { children: items }, `l${blocks.length}`) : /* @__PURE__ */ jsx11("ul", { children: items }, `l${blocks.length}`));
1685
+ const items = list.items.map((item, index) => /* @__PURE__ */ jsx12("li", { children: renderInline(item) }, index));
1686
+ blocks.push(list.ordered ? /* @__PURE__ */ jsx12("ol", { children: items }, `l${blocks.length}`) : /* @__PURE__ */ jsx12("ul", { children: items }, `l${blocks.length}`));
1596
1687
  list = null;
1597
1688
  };
1598
1689
  for (const line of lines) {
@@ -1600,7 +1691,7 @@ function renderBlocks(text) {
1600
1691
  if (fence) {
1601
1692
  if (code) {
1602
1693
  blocks.push(
1603
- /* @__PURE__ */ jsx11("pre", { children: /* @__PURE__ */ jsx11("code", { children: code.lines.join("\n") }) }, `c${blocks.length}`)
1694
+ /* @__PURE__ */ jsx12("pre", { children: /* @__PURE__ */ jsx12("code", { children: code.lines.join("\n") }) }, `c${blocks.length}`)
1604
1695
  );
1605
1696
  code = null;
1606
1697
  } else {
@@ -1637,7 +1728,7 @@ function renderBlocks(text) {
1637
1728
  flushList();
1638
1729
  const level = (heading[1] ?? "#").length;
1639
1730
  const Tag = level <= 1 ? "h3" : level === 2 ? "h4" : "h5";
1640
- blocks.push(/* @__PURE__ */ jsx11(Tag, { className: "frankie-h", children: renderInline(heading[2] ?? "") }, `h${blocks.length}`));
1731
+ blocks.push(/* @__PURE__ */ jsx12(Tag, { className: "frankie-h", children: renderInline(heading[2] ?? "") }, `h${blocks.length}`));
1641
1732
  continue;
1642
1733
  }
1643
1734
  flushList();
@@ -1645,7 +1736,7 @@ function renderBlocks(text) {
1645
1736
  }
1646
1737
  if (code) {
1647
1738
  blocks.push(
1648
- /* @__PURE__ */ jsx11("pre", { children: /* @__PURE__ */ jsx11("code", { children: code.lines.join("\n") }) }, `c${blocks.length}`)
1739
+ /* @__PURE__ */ jsx12("pre", { children: /* @__PURE__ */ jsx12("code", { children: code.lines.join("\n") }) }, `c${blocks.length}`)
1649
1740
  );
1650
1741
  }
1651
1742
  flushParagraph();
@@ -1660,30 +1751,30 @@ function renderInline(text) {
1660
1751
  const token = match[0];
1661
1752
  const start = match.index;
1662
1753
  if (start > lastIndex) nodes.push(text.slice(lastIndex, start));
1663
- nodes.push(/* @__PURE__ */ jsx11(Fragment2, { children: renderToken(token) }, start));
1754
+ nodes.push(/* @__PURE__ */ jsx12(Fragment2, { children: renderToken(token) }, start));
1664
1755
  lastIndex = start + token.length;
1665
1756
  }
1666
1757
  if (lastIndex < text.length) nodes.push(text.slice(lastIndex));
1667
1758
  return nodes;
1668
1759
  }
1669
1760
  function renderToken(token) {
1670
- if (token.startsWith("**")) return /* @__PURE__ */ jsx11("strong", { children: token.slice(2, -2) });
1671
- if (token.startsWith("*")) return /* @__PURE__ */ jsx11("em", { children: token.slice(1, -1) });
1672
- if (token.startsWith("`")) return /* @__PURE__ */ jsx11("code", { children: token.slice(1, -1) });
1761
+ if (token.startsWith("**")) return /* @__PURE__ */ jsx12("strong", { children: token.slice(2, -2) });
1762
+ if (token.startsWith("*")) return /* @__PURE__ */ jsx12("em", { children: token.slice(1, -1) });
1763
+ if (token.startsWith("`")) return /* @__PURE__ */ jsx12("code", { children: token.slice(1, -1) });
1673
1764
  const link = /^\[([^\]]+)\]\(([^)]+)\)$/.exec(token);
1674
1765
  const href = link ? link[2] ?? "" : token;
1675
1766
  const label = link ? link[1] ?? "" : token;
1676
- if (!/^(https?:\/\/|\/)/.test(href)) return token;
1677
- return /* @__PURE__ */ jsx11("a", { href, target: "_blank", rel: "noopener noreferrer nofollow", children: label });
1767
+ if (!/^(https?:\/\/|\/(?![\/\\]))/.test(href)) return token;
1768
+ return /* @__PURE__ */ jsx12("a", { href, target: "_blank", rel: "noopener noreferrer nofollow", children: label });
1678
1769
  }
1679
1770
 
1680
1771
  // src/components/chat/ToolActivityList.tsx
1681
- import { Check, ChevronDown, Loader2, ShieldAlert, Sparkles as Sparkles3, Wrench, X as X2 } from "lucide-react";
1772
+ import { Check as Check2, ChevronDown, Loader2, ShieldAlert as ShieldAlert2, Sparkles as Sparkles3, Wrench, X as X3 } from "lucide-react";
1682
1773
  import { SKILL_TOOL_NAME } from "@frankieai/core";
1683
1774
 
1684
1775
  // src/components/ui/badge.tsx
1685
1776
  import { cva as cva2 } from "class-variance-authority";
1686
- import { jsx as jsx12 } from "react/jsx-runtime";
1777
+ import { jsx as jsx13 } from "react/jsx-runtime";
1687
1778
  var badgeVariants = cva2(
1688
1779
  "inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-[0.6875rem] font-medium",
1689
1780
  {
@@ -1703,46 +1794,46 @@ function Badge({
1703
1794
  variant,
1704
1795
  ...props
1705
1796
  }) {
1706
- return /* @__PURE__ */ jsx12("span", { className: cn(badgeVariants({ variant }), className), ...props });
1797
+ return /* @__PURE__ */ jsx13("span", { className: cn(badgeVariants({ variant }), className), ...props });
1707
1798
  }
1708
1799
 
1709
1800
  // src/components/chat/ToolActivityList.tsx
1710
- import { jsx as jsx13, jsxs as jsxs5 } from "react/jsx-runtime";
1801
+ import { jsx as jsx14, jsxs as jsxs6 } from "react/jsx-runtime";
1711
1802
  function ToolActivityList({ tools, renderTool }) {
1712
1803
  if (tools.length === 0) return null;
1713
1804
  const running = tools.some((tool) => tool.status === "running");
1714
- return /* @__PURE__ */ jsxs5("details", { className: "frankie-tool-activity mt-2", open: running, children: [
1715
- /* @__PURE__ */ jsxs5("summary", { className: "inline-flex min-h-7 cursor-pointer list-none items-center gap-1.5 rounded-md px-1 text-xs font-medium text-muted-foreground hover:bg-muted hover:text-foreground [&::-webkit-details-marker]:hidden", children: [
1716
- /* @__PURE__ */ jsx13(ChevronDown, { className: "frankie-tool-chevron size-3.5 transition-transform", "aria-hidden": "true" }),
1717
- running ? /* @__PURE__ */ jsx13(Loader2, { className: "size-3.5 animate-spin", "aria-hidden": "true" }) : /* @__PURE__ */ jsx13(Wrench, { className: "size-3.5", "aria-hidden": "true" }),
1718
- /* @__PURE__ */ jsx13("span", { children: running ? "Working" : "Activity" }),
1719
- /* @__PURE__ */ jsxs5("span", { className: "text-[11px]", children: [
1805
+ return /* @__PURE__ */ jsxs6("details", { className: "frankie-tool-activity mt-2", open: running, children: [
1806
+ /* @__PURE__ */ jsxs6("summary", { className: "inline-flex min-h-7 cursor-pointer list-none items-center gap-1.5 rounded-md px-1 text-xs font-medium text-muted-foreground hover:bg-muted hover:text-foreground [&::-webkit-details-marker]:hidden", children: [
1807
+ /* @__PURE__ */ jsx14(ChevronDown, { className: "frankie-tool-chevron size-3.5 transition-transform", "aria-hidden": "true" }),
1808
+ running ? /* @__PURE__ */ jsx14(Loader2, { className: "size-3.5 animate-spin", "aria-hidden": "true" }) : /* @__PURE__ */ jsx14(Wrench, { className: "size-3.5", "aria-hidden": "true" }),
1809
+ /* @__PURE__ */ jsx14("span", { children: running ? "Working" : "Activity" }),
1810
+ /* @__PURE__ */ jsxs6("span", { className: "text-[11px]", children: [
1720
1811
  "\xB7 ",
1721
1812
  tools.length,
1722
1813
  " tool call",
1723
1814
  tools.length === 1 ? "" : "s"
1724
1815
  ] })
1725
1816
  ] }),
1726
- /* @__PURE__ */ jsx13("ul", { className: "mt-1 flex flex-col gap-1 border-l border-border pl-2", children: tools.map((tool) => /* @__PURE__ */ jsx13("li", { children: renderTool ? renderTool(tool) : /* @__PURE__ */ jsx13(ToolActivityRow, { tool }) }, tool.id)) })
1817
+ /* @__PURE__ */ jsx14("ul", { className: "mt-1 flex flex-col gap-1 border-l border-border pl-2", children: tools.map((tool) => /* @__PURE__ */ jsx14("li", { children: renderTool ? renderTool(tool) : /* @__PURE__ */ jsx14(ToolActivityRow, { tool }) }, tool.id)) })
1727
1818
  ] });
1728
1819
  }
1729
1820
  function ToolActivityRow({ tool }) {
1730
1821
  const isSkill = tool.name === SKILL_TOOL_NAME;
1731
- return /* @__PURE__ */ jsxs5(Badge, { variant: badgeVariant(tool.status), title: tool.detail ?? tool.name, children: [
1732
- isSkill && tool.status !== "running" ? /* @__PURE__ */ jsx13(Sparkles3, { className: "size-3", "aria-hidden": "true" }) : /* @__PURE__ */ jsx13(ToolIcon, { status: tool.status }),
1733
- /* @__PURE__ */ jsx13("span", { className: "truncate", children: tool.label })
1822
+ return /* @__PURE__ */ jsxs6(Badge, { variant: badgeVariant(tool.status), title: tool.detail ?? tool.name, children: [
1823
+ isSkill && tool.status !== "running" ? /* @__PURE__ */ jsx14(Sparkles3, { className: "size-3", "aria-hidden": "true" }) : /* @__PURE__ */ jsx14(ToolIcon, { status: tool.status }),
1824
+ /* @__PURE__ */ jsx14("span", { className: "truncate", children: tool.label })
1734
1825
  ] });
1735
1826
  }
1736
1827
  function ToolIcon({ status }) {
1737
1828
  switch (status) {
1738
1829
  case "running":
1739
- return /* @__PURE__ */ jsx13(Loader2, { className: "size-3 animate-spin", "aria-hidden": "true" });
1830
+ return /* @__PURE__ */ jsx14(Loader2, { className: "size-3 animate-spin", "aria-hidden": "true" });
1740
1831
  case "done":
1741
- return /* @__PURE__ */ jsx13(Check, { className: "size-3", "aria-hidden": "true" });
1832
+ return /* @__PURE__ */ jsx14(Check2, { className: "size-3", "aria-hidden": "true" });
1742
1833
  case "denied":
1743
- return /* @__PURE__ */ jsx13(ShieldAlert, { className: "size-3", "aria-hidden": "true" });
1834
+ return /* @__PURE__ */ jsx14(ShieldAlert2, { className: "size-3", "aria-hidden": "true" });
1744
1835
  default:
1745
- return /* @__PURE__ */ jsx13(X2, { className: "size-3", "aria-hidden": "true" });
1836
+ return /* @__PURE__ */ jsx14(X3, { className: "size-3", "aria-hidden": "true" });
1746
1837
  }
1747
1838
  }
1748
1839
  function badgeVariant(status) {
@@ -1753,7 +1844,7 @@ function badgeVariant(status) {
1753
1844
  }
1754
1845
 
1755
1846
  // src/components/chat/MessageBubble.tsx
1756
- import { jsx as jsx14, jsxs as jsxs6 } from "react/jsx-runtime";
1847
+ import { jsx as jsx15, jsxs as jsxs7 } from "react/jsx-runtime";
1757
1848
  var MessageBubble = memo2(function MessageBubble2({
1758
1849
  message,
1759
1850
  assistantName,
@@ -1763,40 +1854,50 @@ var MessageBubble = memo2(function MessageBubble2({
1763
1854
  onChoose,
1764
1855
  onRequestInput,
1765
1856
  active,
1766
- busy
1857
+ busy,
1858
+ onAction
1767
1859
  }) {
1768
1860
  if (message.role === "user") {
1769
- return /* @__PURE__ */ jsxs6("div", { className: "frankie-user-message flex flex-col items-end gap-1", children: [
1770
- message.attachments?.length ? /* @__PURE__ */ jsx14("div", { className: "flex max-w-[85%] flex-wrap justify-end gap-1", children: message.attachments.map((file, index) => /* @__PURE__ */ jsxs6(
1861
+ return /* @__PURE__ */ jsxs7("div", { className: "frankie-user-message flex flex-col items-end gap-1", children: [
1862
+ message.attachments?.length ? /* @__PURE__ */ jsx15("div", { className: "flex max-w-[85%] flex-wrap justify-end gap-1", children: message.attachments.map((file, index) => /* @__PURE__ */ jsxs7(
1771
1863
  "span",
1772
1864
  {
1773
1865
  className: "inline-flex max-w-[12rem] items-center gap-1 rounded-[var(--frankie-radius)] border border-border bg-muted px-2 py-1 text-xs",
1774
1866
  children: [
1775
- /* @__PURE__ */ jsx14(Paperclip2, { className: "size-3 shrink-0 opacity-70" }),
1776
- /* @__PURE__ */ jsx14("span", { className: "truncate", children: file.name })
1867
+ /* @__PURE__ */ jsx15(Paperclip2, { className: "size-3 shrink-0 opacity-70" }),
1868
+ /* @__PURE__ */ jsx15("span", { className: "truncate", children: file.name })
1777
1869
  ]
1778
1870
  },
1779
1871
  `${file.name}-${index}`
1780
1872
  )) }) : null,
1781
- message.text ? /* @__PURE__ */ jsxs6("div", { className: "flex max-w-[85%] items-end gap-1", children: [
1782
- /* @__PURE__ */ jsx14("div", { className: "frankie-user-bubble rounded-[var(--frankie-radius)] bg-primary px-3 py-2 text-sm text-primary-foreground", children: message.text }),
1783
- /* @__PURE__ */ jsx14(MessageCopyButton, { text: message.text })
1873
+ message.text ? /* @__PURE__ */ jsxs7("div", { className: "flex max-w-[85%] items-end gap-1", children: [
1874
+ /* @__PURE__ */ jsx15("div", { className: "frankie-user-bubble rounded-[var(--frankie-radius)] bg-primary px-3 py-2 text-sm text-primary-foreground", children: message.text }),
1875
+ /* @__PURE__ */ jsx15(MessageCopyButton, { text: message.text })
1784
1876
  ] }) : null
1785
1877
  ] });
1786
1878
  }
1787
1879
  const { body, options } = extractChoices(message.text);
1788
1880
  const showChoices = Boolean(active && onChoose && options && message.status === "done");
1789
1881
  const waiting = message.status === "streaming" && body.length === 0 && message.tools.length === 0;
1790
- return /* @__PURE__ */ jsxs6("div", { className: "frankie-assistant-message flex gap-2", children: [
1791
- /* @__PURE__ */ jsxs6("div", { className: "frankie-assistant-actions mt-0.5 flex shrink-0 flex-col items-center gap-1", children: [
1792
- /* @__PURE__ */ jsx14(Avatar, { ...avatarUrl ? { src: avatarUrl } : {}, name: assistantName }),
1793
- body ? /* @__PURE__ */ jsx14(MessageCopyButton, { text: body }) : null
1882
+ return /* @__PURE__ */ jsxs7("div", { className: "frankie-assistant-message flex gap-2", children: [
1883
+ /* @__PURE__ */ jsxs7("div", { className: "frankie-assistant-actions mt-0.5 flex shrink-0 flex-col items-center gap-1", children: [
1884
+ /* @__PURE__ */ jsx15(Avatar, { ...avatarUrl ? { src: avatarUrl } : {}, name: assistantName }),
1885
+ body ? /* @__PURE__ */ jsx15(MessageCopyButton, { text: body }) : null
1794
1886
  ] }),
1795
- /* @__PURE__ */ jsxs6("div", { className: "frankie-assistant-content min-w-0 max-w-[85%]", children: [
1796
- message.status === "error" ? /* @__PURE__ */ jsx14("p", { className: "rounded-[var(--frankie-radius)] bg-red-500/10 px-3 py-2 text-sm text-red-600 dark:text-red-400", children: message.error }) : body ? /* @__PURE__ */ jsx14(Markdown, { text: body, className: "text-sm" }) : null,
1797
- showChoices ? /* @__PURE__ */ jsx14(Choices, { options: options ?? [], onPick: onChoose, ...onRequestInput ? { onSomethingElse: onRequestInput } : {}, disabled: busy }) : null,
1798
- showToolActivity ? /* @__PURE__ */ jsx14(ToolActivityList, { tools: message.tools, ...renderTool ? { renderTool } : {} }) : null,
1799
- waiting ? /* @__PURE__ */ jsx14(Thinking, { delayed: true }) : null
1887
+ /* @__PURE__ */ jsxs7("div", { className: "frankie-assistant-content min-w-0 max-w-[85%]", children: [
1888
+ message.status === "error" ? /* @__PURE__ */ jsx15("p", { className: "rounded-[var(--frankie-radius)] bg-red-500/10 px-3 py-2 text-sm text-red-600 dark:text-red-400", children: message.error }) : body ? /* @__PURE__ */ jsx15(Markdown, { text: body, className: "text-sm" }) : null,
1889
+ message.action ? /* @__PURE__ */ jsx15(
1890
+ ActionConfirm,
1891
+ {
1892
+ action: message.action,
1893
+ live: Boolean(active),
1894
+ disabled: busy || message.status === "streaming",
1895
+ ...onAction ? { onAnswer: onAction } : {}
1896
+ }
1897
+ ) : null,
1898
+ showChoices ? /* @__PURE__ */ jsx15(Choices, { options: options ?? [], onPick: onChoose, ...onRequestInput ? { onSomethingElse: onRequestInput } : {}, disabled: busy }) : null,
1899
+ showToolActivity ? /* @__PURE__ */ jsx15(ToolActivityList, { tools: message.tools, ...renderTool ? { renderTool } : {} }) : null,
1900
+ waiting ? /* @__PURE__ */ jsx15(Thinking, { delayed: true }) : null
1800
1901
  ] })
1801
1902
  ] });
1802
1903
  });
@@ -1810,12 +1911,12 @@ function MessageCopyButton({ text }) {
1810
1911
  } catch {
1811
1912
  }
1812
1913
  };
1813
- return /* @__PURE__ */ jsx14("button", { type: "button", onClick: () => void copy(), className: "frankie-message-copy inline-flex size-8 shrink-0 items-center justify-center rounded-md border border-transparent text-muted-foreground transition hover:border-border hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary", "aria-label": copied ? "Copied" : "Copy message", title: copied ? "Copied" : "Copy message", children: copied ? /* @__PURE__ */ jsx14(Check2, { className: "size-3.5", "aria-hidden": "true" }) : /* @__PURE__ */ jsx14(Copy, { className: "size-3.5", "aria-hidden": "true" }) });
1914
+ return /* @__PURE__ */ jsx15("button", { type: "button", onClick: () => void copy(), className: "frankie-message-copy inline-flex size-8 shrink-0 items-center justify-center rounded-md border border-transparent text-muted-foreground transition hover:border-border hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary", "aria-label": copied ? "Copied" : "Copy message", title: copied ? "Copied" : "Copy message", children: copied ? /* @__PURE__ */ jsx15(Check3, { className: "size-3.5", "aria-hidden": "true" }) : /* @__PURE__ */ jsx15(Copy, { className: "size-3.5", "aria-hidden": "true" }) });
1814
1915
  }
1815
1916
  function TypingDots() {
1816
- return /* @__PURE__ */ jsxs6("span", { className: "frankie-thinking inline-flex items-center gap-1 py-2", role: "status", "aria-label": "Thinking", children: [
1817
- /* @__PURE__ */ jsx14("span", { className: "frankie-thinking-label", children: "Thinking" }),
1818
- [0, 1, 2].map((index) => /* @__PURE__ */ jsx14(
1917
+ return /* @__PURE__ */ jsxs7("span", { className: "frankie-thinking inline-flex items-center gap-1 py-2", role: "status", "aria-label": "Thinking", children: [
1918
+ /* @__PURE__ */ jsx15("span", { className: "frankie-thinking-label", children: "Thinking" }),
1919
+ [0, 1, 2].map((index) => /* @__PURE__ */ jsx15(
1819
1920
  "span",
1820
1921
  {
1821
1922
  className: cn("size-1.5 animate-pulse rounded-full bg-muted-foreground"),
@@ -1826,15 +1927,15 @@ function TypingDots() {
1826
1927
  ] });
1827
1928
  }
1828
1929
  function Thinking({ delayed = false }) {
1829
- return /* @__PURE__ */ jsxs6("div", { className: "frankie-skeleton" + (delayed ? " is-delayed" : ""), role: "status", "aria-label": "Thinking", children: [
1830
- /* @__PURE__ */ jsx14("span", { className: "frankie-skeleton-line", style: { width: "62%" } }),
1831
- /* @__PURE__ */ jsx14("span", { className: "frankie-skeleton-line", style: { width: "92%" } }),
1832
- /* @__PURE__ */ jsx14("span", { className: "frankie-skeleton-line", style: { width: "48%" } })
1930
+ return /* @__PURE__ */ jsxs7("div", { className: "frankie-skeleton" + (delayed ? " is-delayed" : ""), role: "status", "aria-label": "Thinking", children: [
1931
+ /* @__PURE__ */ jsx15("span", { className: "frankie-skeleton-line", style: { width: "62%" } }),
1932
+ /* @__PURE__ */ jsx15("span", { className: "frankie-skeleton-line", style: { width: "92%" } }),
1933
+ /* @__PURE__ */ jsx15("span", { className: "frankie-skeleton-line", style: { width: "48%" } })
1833
1934
  ] });
1834
1935
  }
1835
1936
 
1836
1937
  // src/components/chat/ChatPanel.tsx
1837
- import { jsx as jsx15, jsxs as jsxs7 } from "react/jsx-runtime";
1938
+ import { jsx as jsx16, jsxs as jsxs8 } from "react/jsx-runtime";
1838
1939
  function ChatPanel({
1839
1940
  className,
1840
1941
  header,
@@ -1849,7 +1950,7 @@ function ChatPanel({
1849
1950
  }) {
1850
1951
  const { config, configError, loading } = useFrankie();
1851
1952
  const theme = useFrankieTheme();
1852
- const { messages, busy, restoring, error, send, stop, reset } = useFrankieChat();
1953
+ const { messages, busy, restoring, error, send, answerAction, stop, reset } = useFrankieChat();
1853
1954
  const scrollRef = useRef4(null);
1854
1955
  const atBottomRef = useRef4(true);
1855
1956
  const features = config?.features;
@@ -1878,7 +1979,7 @@ function ChatPanel({
1878
1979
  }, [messages]);
1879
1980
  const name = config?.branding.name ?? "Assistant";
1880
1981
  const mode = useResolvedMode(theme?.mode);
1881
- return /* @__PURE__ */ jsxs7(
1982
+ return /* @__PURE__ */ jsxs8(
1882
1983
  Card,
1883
1984
  {
1884
1985
  className: cn(
@@ -1891,22 +1992,22 @@ function ChatPanel({
1891
1992
  style: themeToCssVars(theme),
1892
1993
  "data-frankie-mode": mode,
1893
1994
  children: [
1894
- header === false ? null : header !== void 0 ? header : /* @__PURE__ */ jsxs7(CardHeader, { children: [
1895
- /* @__PURE__ */ jsx15(Avatar, { ...config?.branding.avatarUrl ? { src: config.branding.avatarUrl } : {}, name }),
1896
- /* @__PURE__ */ jsxs7("div", { className: "min-w-0 flex-1", children: [
1897
- /* @__PURE__ */ jsx15(CardTitle, { children: name }),
1898
- config?.branding.tagline ? /* @__PURE__ */ jsx15(CardDescription, { children: config.branding.tagline }) : null
1995
+ header === false ? null : header !== void 0 ? header : /* @__PURE__ */ jsxs8(CardHeader, { children: [
1996
+ /* @__PURE__ */ jsx16(Avatar, { ...config?.branding.avatarUrl ? { src: config.branding.avatarUrl } : {}, name }),
1997
+ /* @__PURE__ */ jsxs8("div", { className: "min-w-0 flex-1", children: [
1998
+ /* @__PURE__ */ jsx16(CardTitle, { children: name }),
1999
+ config?.branding.tagline ? /* @__PURE__ */ jsx16(CardDescription, { children: config.branding.tagline }) : null
1899
2000
  ] }),
1900
- /* @__PURE__ */ jsx15(Button, { size: "icon", variant: "ghost", onClick: reset, "aria-label": "Start a new conversation", title: "New conversation", children: /* @__PURE__ */ jsx15(RotateCcw, {}) }),
1901
- onClose ? /* @__PURE__ */ jsx15(Button, { size: "icon", variant: "ghost", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx15(X3, {}) }) : null
2001
+ /* @__PURE__ */ jsx16(Button, { size: "icon", variant: "ghost", onClick: reset, "aria-label": "Start a new conversation", title: "New conversation", children: /* @__PURE__ */ jsx16(RotateCcw, {}) }),
2002
+ onClose ? /* @__PURE__ */ jsx16(Button, { size: "icon", variant: "ghost", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx16(X4, {}) }) : null
1902
2003
  ] }),
1903
- /* @__PURE__ */ jsx15(AgentContext, {}),
1904
- /* @__PURE__ */ jsx15(CardContent, { className: "frankie-conversation-content", children: /* @__PURE__ */ jsx15(ScrollArea, { ref: scrollRef, className: "frankie-transcript flex h-full flex-col gap-4 p-4", "aria-live": "polite", children: configError ? /* @__PURE__ */ jsxs7("div", { className: "frankie-config-error", role: "alert", children: [
1905
- /* @__PURE__ */ jsx15("strong", { children: "Frankie couldn\u2019t start" }),
1906
- /* @__PURE__ */ jsx15("p", { children: configError }),
1907
- /* @__PURE__ */ jsx15("p", { children: "Refresh this page after checking the workspace\u2019s allowed origin and sign-in settings." })
1908
- ] }) : loading ? /* @__PURE__ */ jsx15("p", { className: "text-sm text-muted-foreground", children: "Starting Frankie\u2026" }) : messages.length === 0 ? emptyState ?? /* @__PURE__ */ jsx15(ChatEmptyState, {}) : /* @__PURE__ */ jsx15("div", { className: "frankie-message-list flex flex-col gap-4", children: messages.map(
1909
- (message, index) => renderMessage ? /* @__PURE__ */ jsx15("div", { children: renderMessage(message) }, message.id) : /* @__PURE__ */ jsx15(
2004
+ config?.agentContext === false ? null : /* @__PURE__ */ jsx16(AgentContext, {}),
2005
+ /* @__PURE__ */ jsx16(CardContent, { className: "frankie-conversation-content", children: /* @__PURE__ */ jsx16(ScrollArea, { ref: scrollRef, className: "frankie-transcript flex h-full flex-col gap-4 p-4", "aria-live": "polite", children: configError ? /* @__PURE__ */ jsxs8("div", { className: "frankie-config-error", role: "alert", children: [
2006
+ /* @__PURE__ */ jsx16("strong", { children: "Frankie couldn\u2019t start" }),
2007
+ /* @__PURE__ */ jsx16("p", { children: configError }),
2008
+ /* @__PURE__ */ jsx16("p", { children: "Refresh this page after checking the workspace\u2019s allowed origin and sign-in settings." })
2009
+ ] }) : loading ? /* @__PURE__ */ jsx16("p", { className: "text-sm text-muted-foreground", children: "Starting Frankie\u2026" }) : messages.length === 0 ? emptyState ?? /* @__PURE__ */ jsx16(ChatEmptyState, {}) : /* @__PURE__ */ jsx16("div", { className: "frankie-message-list flex flex-col gap-4", children: messages.map(
2010
+ (message, index) => renderMessage ? /* @__PURE__ */ jsx16("div", { children: renderMessage(message) }, message.id) : /* @__PURE__ */ jsx16(
1910
2011
  MessageBubble,
1911
2012
  {
1912
2013
  message,
@@ -1917,14 +2018,15 @@ function ChatPanel({
1917
2018
  onChoose: send,
1918
2019
  onRequestInput: focusComposer,
1919
2020
  active: index === messages.length - 1,
1920
- busy
2021
+ busy,
2022
+ onAction: (toolUseId, approved) => void answerAction(toolUseId, approved)
1921
2023
  },
1922
2024
  message.id
1923
2025
  )
1924
2026
  ) }) }) }),
1925
- /* @__PURE__ */ jsxs7(CardFooter, { className: "frankie-composer-footer flex flex-col gap-2", children: [
1926
- error ? /* @__PURE__ */ jsx15("p", { className: "w-full text-xs text-red-600 dark:text-red-400", children: error }) : null,
1927
- /* @__PURE__ */ jsx15("div", { className: "w-full", children: /* @__PURE__ */ jsx15(
2027
+ /* @__PURE__ */ jsxs8(CardFooter, { className: "frankie-composer-footer flex flex-col gap-2", children: [
2028
+ error ? /* @__PURE__ */ jsx16("p", { className: "w-full text-xs text-red-600 dark:text-red-400", children: error }) : null,
2029
+ /* @__PURE__ */ jsx16("div", { className: "w-full", children: /* @__PURE__ */ jsx16(
1928
2030
  Composer,
1929
2031
  {
1930
2032
  onSend: send,
@@ -1946,7 +2048,7 @@ function ChatPanel({
1946
2048
  }
1947
2049
 
1948
2050
  // src/components/chat/FrankieWidget.tsx
1949
- import { jsx as jsx16, jsxs as jsxs8 } from "react/jsx-runtime";
2051
+ import { jsx as jsx17, jsxs as jsxs9 } from "react/jsx-runtime";
1950
2052
  function FrankieWidget({
1951
2053
  position = "bottom-right",
1952
2054
  offset = 24,
@@ -2032,7 +2134,7 @@ function FrankieWidget({
2032
2134
  const label = config?.branding.launcherLabel ?? "Need a hand?";
2033
2135
  const mode = useResolvedMode(theme?.mode);
2034
2136
  const side = position === "bottom-right" ? { right: offset } : { left: offset };
2035
- return /* @__PURE__ */ jsx16(
2137
+ return /* @__PURE__ */ jsx17(
2036
2138
  "div",
2037
2139
  {
2038
2140
  ref: rootRef,
@@ -2040,9 +2142,9 @@ function FrankieWidget({
2040
2142
  style: { ...themeToCssVars(theme), position: "fixed", bottom: lift ? lift + Math.min(offset, 12) : offset, ...side, zIndex, pointerEvents: "none", ["--frankie-lift"]: `${lift}px`, ...stylesReady && themeReady ? null : { opacity: 0 } },
2041
2143
  "data-frankie-mode": mode,
2042
2144
  "data-frankie-styles": stylesReady ? "ready" : "pending",
2043
- children: /* @__PURE__ */ jsxs8("div", { className: cn("flex flex-col gap-3", position === "bottom-left" ? "items-start" : "items-end"), children: [
2044
- open ? /* @__PURE__ */ jsx16("div", { style: { pointerEvents: "auto" }, children: /* @__PURE__ */ jsx16(ChatPanel, { ...panelProps, className: cn("frankie-widget-panel", panelProps.className), onClose: () => setOpen(false), autoFocus: true }) }) : null,
2045
- launcher || renderLauncher ? /* @__PURE__ */ jsx16("div", { style: { pointerEvents: "auto" }, children: renderLauncher ? renderLauncher({ open, toggle: () => setOpen(!open), label }) : /* @__PURE__ */ jsx16(
2145
+ children: /* @__PURE__ */ jsxs9("div", { className: cn("flex flex-col gap-3", position === "bottom-left" ? "items-start" : "items-end"), children: [
2146
+ open ? /* @__PURE__ */ jsx17("div", { style: { pointerEvents: "auto" }, children: /* @__PURE__ */ jsx17(ChatPanel, { ...panelProps, className: cn("frankie-widget-panel", panelProps.className), onClose: () => setOpen(false), autoFocus: true }) }) : null,
2147
+ launcher || renderLauncher ? /* @__PURE__ */ jsx17("div", { style: { pointerEvents: "auto" }, children: renderLauncher ? renderLauncher({ open, toggle: () => setOpen(!open), label }) : /* @__PURE__ */ jsx17(
2046
2148
  Button,
2047
2149
  {
2048
2150
  size: "icon",
@@ -2051,7 +2153,7 @@ function FrankieWidget({
2051
2153
  "aria-expanded": open,
2052
2154
  "aria-label": open ? "Close the assistant" : label,
2053
2155
  title: label,
2054
- children: open ? /* @__PURE__ */ jsx16(X4, { className: "size-5" }) : /* @__PURE__ */ jsx16(MessageCircle, { className: "size-5" })
2156
+ children: open ? /* @__PURE__ */ jsx17(X5, { className: "size-5" }) : /* @__PURE__ */ jsx17(MessageCircle, { className: "size-5" })
2055
2157
  }
2056
2158
  ) }) : null
2057
2159
  ] })
@@ -2061,14 +2163,14 @@ function FrankieWidget({
2061
2163
 
2062
2164
  // src/components/chat/FrankieInline.tsx
2063
2165
  import { useRef as useRef6 } from "react";
2064
- import { jsx as jsx17 } from "react/jsx-runtime";
2166
+ import { jsx as jsx18 } from "react/jsx-runtime";
2065
2167
  function FrankieInline({ className, style, ...panelProps }) {
2066
2168
  const { injectStyles, themeReady } = useFrankie();
2067
2169
  const theme = useFrankieTheme();
2068
2170
  const mode = useResolvedMode(theme?.mode);
2069
2171
  const rootRef = useRef6(null);
2070
2172
  const stylesReady = useStylesReady(rootRef, void 0, injectStyles);
2071
- return /* @__PURE__ */ jsx17(
2173
+ return /* @__PURE__ */ jsx18(
2072
2174
  "div",
2073
2175
  {
2074
2176
  ref: rootRef,
@@ -2076,14 +2178,14 @@ function FrankieInline({ className, style, ...panelProps }) {
2076
2178
  style: { ...themeToCssVars(theme), display: "flex", height: "100%", width: "100%", ...style, ...stylesReady && themeReady ? null : { opacity: 0 } },
2077
2179
  "data-frankie-mode": mode,
2078
2180
  "data-frankie-styles": stylesReady ? "ready" : "pending",
2079
- children: /* @__PURE__ */ jsx17(ChatPanel, { ...panelProps, fill: true })
2181
+ children: /* @__PURE__ */ jsx18(ChatPanel, { ...panelProps, fill: true })
2080
2182
  }
2081
2183
  );
2082
2184
  }
2083
2185
 
2084
2186
  // src/components/chat/FrankieChatPage.tsx
2085
2187
  import { useCallback as useCallback3, useEffect as useEffect8, useRef as useRef7, useState as useState9 } from "react";
2086
- import { ChevronsLeft, ChevronsRight, History, Menu, Plus as Plus2, Settings, X as X5 } from "lucide-react";
2188
+ import { ChevronsLeft, ChevronsRight, History, Menu, Plus as Plus2, Settings, X as X6 } from "lucide-react";
2087
2189
 
2088
2190
  // src/lib/viewport-fill.ts
2089
2191
  import { useEffect as useEffect7, useState as useState8 } from "react";
@@ -2125,7 +2227,7 @@ function useViewportFill(ref, enabled) {
2125
2227
  }
2126
2228
 
2127
2229
  // src/components/chat/FrankieChatPage.tsx
2128
- import { Fragment as Fragment3, jsx as jsx18, jsxs as jsxs9 } from "react/jsx-runtime";
2230
+ import { Fragment as Fragment3, jsx as jsx19, jsxs as jsxs10 } from "react/jsx-runtime";
2129
2231
  function groupByDate(items) {
2130
2232
  const now = /* @__PURE__ */ new Date();
2131
2233
  const startOfToday = new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime();
@@ -2218,70 +2320,70 @@ function PageChrome({ showHistory, navigation, currentId, onSelect, onNew, histo
2218
2320
  close();
2219
2321
  }
2220
2322
  };
2221
- const history = /* @__PURE__ */ jsxs9(Fragment3, { children: [
2222
- /* @__PURE__ */ jsxs9("div", { className: "frankie-history-heading", children: [
2223
- /* @__PURE__ */ jsx18("strong", { children: "Conversations" }),
2224
- /* @__PURE__ */ jsx18("button", { type: "button", className: "frankie-mobile-only", "aria-label": "Close conversations", onClick: close, children: /* @__PURE__ */ jsx18(X5, { size: 18 }) })
2323
+ const history = /* @__PURE__ */ jsxs10(Fragment3, { children: [
2324
+ /* @__PURE__ */ jsxs10("div", { className: "frankie-history-heading", children: [
2325
+ /* @__PURE__ */ jsx19("strong", { children: "Conversations" }),
2326
+ /* @__PURE__ */ jsx19("button", { type: "button", className: "frankie-mobile-only", "aria-label": "Close conversations", onClick: close, children: /* @__PURE__ */ jsx19(X6, { size: 18 }) })
2225
2327
  ] }),
2226
- /* @__PURE__ */ jsxs9("button", { type: "button", className: "frankie-new-chat", disabled: busy, onClick: () => {
2328
+ /* @__PURE__ */ jsxs10("button", { type: "button", className: "frankie-new-chat", disabled: busy, onClick: () => {
2227
2329
  onNew();
2228
2330
  close();
2229
2331
  }, children: [
2230
- /* @__PURE__ */ jsx18(Plus2, { size: 17 }),
2332
+ /* @__PURE__ */ jsx19(Plus2, { size: 17 }),
2231
2333
  "New chat"
2232
2334
  ] }),
2233
- /* @__PURE__ */ jsxs9("label", { className: "frankie-history-search", children: [
2234
- /* @__PURE__ */ jsx18("span", { children: "Search conversations" }),
2235
- /* @__PURE__ */ jsx18("input", { type: "search", placeholder: "Search chats\u2026", value: query, onChange: (event) => setQuery(event.target.value) })
2335
+ /* @__PURE__ */ jsxs10("label", { className: "frankie-history-search", children: [
2336
+ /* @__PURE__ */ jsx19("span", { children: "Search conversations" }),
2337
+ /* @__PURE__ */ jsx19("input", { type: "search", placeholder: "Search chats\u2026", value: query, onChange: (event) => setQuery(event.target.value) })
2236
2338
  ] }),
2237
- /* @__PURE__ */ jsx18("nav", { className: "frankie-history-list", "aria-label": "Conversations", children: groupByDate(conversations.filter((item) => item.title.toLowerCase().includes(query.toLowerCase()))).map((group) => /* @__PURE__ */ jsxs9("div", { className: "frankie-history-group", children: [
2238
- /* @__PURE__ */ jsx18("p", { className: "frankie-history-group-label", children: group.label }),
2239
- group.items.map((item) => /* @__PURE__ */ jsxs9("button", { type: "button", "aria-current": item.id === currentId ? "page" : void 0, disabled: busy, onClick: () => select(item.id), children: [
2240
- /* @__PURE__ */ jsx18("span", { children: item.title }),
2241
- /* @__PURE__ */ jsx18("small", { children: new Date(item.updatedAt).toLocaleDateString() })
2339
+ /* @__PURE__ */ jsx19("nav", { className: "frankie-history-list", "aria-label": "Conversations", children: groupByDate(conversations.filter((item) => item.title.toLowerCase().includes(query.toLowerCase()))).map((group) => /* @__PURE__ */ jsxs10("div", { className: "frankie-history-group", children: [
2340
+ /* @__PURE__ */ jsx19("p", { className: "frankie-history-group-label", children: group.label }),
2341
+ group.items.map((item) => /* @__PURE__ */ jsxs10("button", { type: "button", "aria-current": item.id === currentId ? "page" : void 0, disabled: busy, onClick: () => select(item.id), children: [
2342
+ /* @__PURE__ */ jsx19("span", { children: item.title }),
2343
+ /* @__PURE__ */ jsx19("small", { children: new Date(item.updatedAt).toLocaleDateString() })
2242
2344
  ] }, item.id))
2243
2345
  ] }, group.label)) }),
2244
- historyLoading && !conversations.length ? /* @__PURE__ */ jsx18("p", { role: "status", children: "Loading history\u2026" }) : historyError ? /* @__PURE__ */ jsxs9("p", { role: "status", children: [
2346
+ historyLoading && !conversations.length ? /* @__PURE__ */ jsx19("p", { role: "status", children: "Loading history\u2026" }) : historyError ? /* @__PURE__ */ jsxs10("p", { role: "status", children: [
2245
2347
  historyError,
2246
- /* @__PURE__ */ jsx18("button", { type: "button", onClick: () => void refresh(), children: "Try again" })
2247
- ] }) : !conversations.length && !historyLoading ? /* @__PURE__ */ jsx18("p", { children: config?.allowAnonymous ? "Sign in to sync conversations across devices." : "Your conversations will appear here." }) : null,
2248
- navigation ? /* @__PURE__ */ jsx18("div", { className: "frankie-host-navigation", children: navigation }) : null
2348
+ /* @__PURE__ */ jsx19("button", { type: "button", onClick: () => void refresh(), children: "Try again" })
2349
+ ] }) : !conversations.length && !historyLoading ? /* @__PURE__ */ jsx19("p", { children: config?.allowAnonymous ? "Sign in to sync conversations across devices." : "Your conversations will appear here." }) : null,
2350
+ navigation ? /* @__PURE__ */ jsx19("div", { className: "frankie-host-navigation", children: navigation }) : null
2249
2351
  ] });
2250
- return /* @__PURE__ */ jsxs9("div", { className: "frankie-page-shell" + (mode === "dark" ? " dark" : ""), style: { ...themeToCssVars(theme), ...themeReady ? null : { opacity: 0 } }, children: [
2251
- showHistory ? /* @__PURE__ */ jsxs9("aside", { className: "frankie-history-desktop" + (collapsed ? " frankie-history-collapsed" : ""), children: [
2252
- /* @__PURE__ */ jsx18("button", { type: "button", className: "frankie-history-toggle", "aria-label": collapsed ? "Expand conversations" : "Collapse conversations", "aria-expanded": !collapsed, onClick: () => setCollapsed((value) => !value), children: collapsed ? /* @__PURE__ */ jsx18(ChevronsRight, { size: 16 }) : /* @__PURE__ */ jsx18(ChevronsLeft, { size: 16 }) }),
2352
+ return /* @__PURE__ */ jsxs10("div", { className: "frankie-page-shell" + (mode === "dark" ? " dark" : ""), style: { ...themeToCssVars(theme), ...themeReady ? null : { opacity: 0 } }, children: [
2353
+ showHistory ? /* @__PURE__ */ jsxs10("aside", { className: "frankie-history-desktop" + (collapsed ? " frankie-history-collapsed" : ""), children: [
2354
+ /* @__PURE__ */ jsx19("button", { type: "button", className: "frankie-history-toggle", "aria-label": collapsed ? "Expand conversations" : "Collapse conversations", "aria-expanded": !collapsed, onClick: () => setCollapsed((value) => !value), children: collapsed ? /* @__PURE__ */ jsx19(ChevronsRight, { size: 16 }) : /* @__PURE__ */ jsx19(ChevronsLeft, { size: 16 }) }),
2253
2355
  collapsed ? null : history
2254
2356
  ] }) : null,
2255
- /* @__PURE__ */ jsxs9("div", { className: "frankie-page-main", children: [
2256
- /* @__PURE__ */ jsxs9("header", { className: "frankie-page-header", children: [
2257
- /* @__PURE__ */ jsxs9("div", { children: [
2258
- showHistory ? /* @__PURE__ */ jsx18("button", { type: "button", className: "frankie-mobile-only", ref: menu, "aria-label": "Open conversations", "aria-haspopup": "dialog", "aria-expanded": drawerOpen, onClick: () => setDrawerOpen(true), children: /* @__PURE__ */ jsx18(Menu, { size: 20 }) }) : null,
2259
- /* @__PURE__ */ jsx18("strong", { className: "frankie-thread-title", children: conversations.find((item) => item.id === currentId)?.title ?? messages.find((message) => message.role === "user")?.text ?? "New chat" })
2357
+ /* @__PURE__ */ jsxs10("div", { className: "frankie-page-main", children: [
2358
+ /* @__PURE__ */ jsxs10("header", { className: "frankie-page-header", children: [
2359
+ /* @__PURE__ */ jsxs10("div", { children: [
2360
+ showHistory ? /* @__PURE__ */ jsx19("button", { type: "button", className: "frankie-mobile-only", ref: menu, "aria-label": "Open conversations", "aria-haspopup": "dialog", "aria-expanded": drawerOpen, onClick: () => setDrawerOpen(true), children: /* @__PURE__ */ jsx19(Menu, { size: 20 }) }) : null,
2361
+ /* @__PURE__ */ jsx19("strong", { className: "frankie-thread-title", children: conversations.find((item) => item.id === currentId)?.title ?? messages.find((message) => message.role === "user")?.text ?? "New chat" })
2260
2362
  ] }),
2261
- /* @__PURE__ */ jsxs9("div", { children: [
2262
- /* @__PURE__ */ jsxs9("button", { type: "button", disabled: busy, onClick: onNew, "aria-label": "Start a new conversation", children: [
2263
- /* @__PURE__ */ jsx18(Plus2, { size: 16 }),
2264
- /* @__PURE__ */ jsx18("span", { children: "New chat" })
2363
+ /* @__PURE__ */ jsxs10("div", { children: [
2364
+ /* @__PURE__ */ jsxs10("button", { type: "button", disabled: busy, onClick: onNew, "aria-label": "Start a new conversation", children: [
2365
+ /* @__PURE__ */ jsx19(Plus2, { size: 16 }),
2366
+ /* @__PURE__ */ jsx19("span", { children: "New chat" })
2265
2367
  ] }),
2266
- /* @__PURE__ */ jsxs9("details", { className: "frankie-chat-settings", children: [
2267
- /* @__PURE__ */ jsx18("summary", { "aria-label": "Chat settings", children: /* @__PURE__ */ jsx18(Settings, { size: 19 }) }),
2268
- /* @__PURE__ */ jsxs9("div", { children: [
2269
- /* @__PURE__ */ jsx18("strong", { children: "Chat settings" }),
2270
- /* @__PURE__ */ jsx18("p", { children: "History syncs automatically for signed-in users." }),
2271
- /* @__PURE__ */ jsxs9("button", { type: "button", onClick: () => void refresh(), disabled: historyLoading || !showHistory, children: [
2272
- /* @__PURE__ */ jsx18(History, { size: 16 }),
2368
+ /* @__PURE__ */ jsxs10("details", { className: "frankie-chat-settings", children: [
2369
+ /* @__PURE__ */ jsx19("summary", { "aria-label": "Chat settings", children: /* @__PURE__ */ jsx19(Settings, { size: 19 }) }),
2370
+ /* @__PURE__ */ jsxs10("div", { children: [
2371
+ /* @__PURE__ */ jsx19("strong", { children: "Chat settings" }),
2372
+ /* @__PURE__ */ jsx19("p", { children: "History syncs automatically for signed-in users." }),
2373
+ /* @__PURE__ */ jsxs10("button", { type: "button", onClick: () => void refresh(), disabled: historyLoading || !showHistory, children: [
2374
+ /* @__PURE__ */ jsx19(History, { size: 16 }),
2273
2375
  "Refresh history"
2274
2376
  ] }),
2275
- /* @__PURE__ */ jsx18("small", { children: "Skills are checked at the start of each message." })
2377
+ /* @__PURE__ */ jsx19("small", { children: "Skills are checked at the start of each message." })
2276
2378
  ] })
2277
2379
  ] })
2278
2380
  ] })
2279
2381
  ] }),
2280
- /* @__PURE__ */ jsx18("div", { className: "frankie-page-canvas", children: /* @__PURE__ */ jsx18(FrankieInline, { ...panel, header: panel.header ?? false, placeholder: panel.placeholder ?? `Ask anything about your ${config?.branding.name ?? "Frankie"} workspace\u2026`, emptyState: panel.emptyState }) })
2382
+ /* @__PURE__ */ jsx19("div", { className: "frankie-page-canvas", children: /* @__PURE__ */ jsx19(FrankieInline, { ...panel, header: panel.header ?? false, placeholder: panel.placeholder ?? `Ask anything about your ${config?.branding.name ?? "Frankie"} workspace\u2026`, emptyState: panel.emptyState }) })
2281
2383
  ] }),
2282
- showHistory ? /* @__PURE__ */ jsx18("dialog", { ref: dialog, className: "frankie-history-dialog frankie-root", "aria-label": "Chat conversations", style: themeToCssVars(theme), onCancel: close, onClick: (event) => {
2384
+ showHistory ? /* @__PURE__ */ jsx19("dialog", { ref: dialog, className: "frankie-history-dialog frankie-root", "aria-label": "Chat conversations", style: themeToCssVars(theme), onCancel: close, onClick: (event) => {
2283
2385
  if (event.target === event.currentTarget) close();
2284
- }, children: /* @__PURE__ */ jsx18("aside", { children: history }) }) : null
2386
+ }, children: /* @__PURE__ */ jsx19("aside", { children: history }) }) : null
2285
2387
  ] });
2286
2388
  }
2287
2389
  function FrankieChatPage({ className, style, header, footer, emptyState, renderMessage, renderTool, placeholder, autoFocus, showHistory = true, navigation, fillViewport = true, ...provider }) {
@@ -2291,18 +2393,18 @@ function FrankieChatPage({ className, style, header, footer, emptyState, renderM
2291
2393
  const pageRef = useRef7(null);
2292
2394
  const stylesReady = useStylesReady(pageRef, void 0, provider.injectStyles);
2293
2395
  const fill = useViewportFill(pageRef, fillViewport);
2294
- return /* @__PURE__ */ jsx18("div", { ref: pageRef, className: ["frankie-root", "frankie-chat-page", className].filter(Boolean).join(" "), style: { height: "100%", minHeight: fill > 360 ? `${fill}px` : "min(36rem, 100dvh)", width: "100%", ...style, ...stylesReady ? null : { opacity: 0 } }, "data-frankie-styles": stylesReady ? "ready" : "pending", children: /* @__PURE__ */ jsx18(FrankieProvider, { ...provider, conversationId: id, storageNamespace: (provider.storageNamespace ?? "frankie." + provider.publishableKey) + "." + id, children: /* @__PURE__ */ jsx18(PageChrome, { showHistory, navigation, currentId: id, onSelect: setId, onNew, history, header, footer, emptyState, renderMessage, renderTool, placeholder, autoFocus }) }) });
2396
+ return /* @__PURE__ */ jsx19("div", { ref: pageRef, className: ["frankie-root", "frankie-chat-page", className].filter(Boolean).join(" "), style: { height: "100%", minHeight: fill > 360 ? `${fill}px` : "min(36rem, 100dvh)", width: "100%", ...style, ...stylesReady ? null : { opacity: 0 } }, "data-frankie-styles": stylesReady ? "ready" : "pending", children: /* @__PURE__ */ jsx19(FrankieProvider, { ...provider, conversationId: id, storageNamespace: (provider.storageNamespace ?? "frankie." + provider.publishableKey) + "." + id, children: /* @__PURE__ */ jsx19(PageChrome, { showHistory, navigation, currentId: id, onSelect: setId, onNew, history, header, footer, emptyState, renderMessage, renderTool, placeholder, autoFocus }) }) });
2295
2397
  }
2296
2398
 
2297
2399
  // src/components/chat/SuggestedPrompts.tsx
2298
- import { jsx as jsx19 } from "react/jsx-runtime";
2400
+ import { jsx as jsx20 } from "react/jsx-runtime";
2299
2401
  function SuggestedPrompts({
2300
2402
  prompts,
2301
2403
  onPick,
2302
2404
  disabled
2303
2405
  }) {
2304
2406
  if (prompts.length === 0) return null;
2305
- return /* @__PURE__ */ jsx19("div", { className: "flex flex-wrap gap-2", children: prompts.map((prompt) => /* @__PURE__ */ jsx19(
2407
+ return /* @__PURE__ */ jsx20("div", { className: "flex flex-wrap gap-2", children: prompts.map((prompt) => /* @__PURE__ */ jsx20(
2306
2408
  Button,
2307
2409
  {
2308
2410
  type: "button",
@@ -2317,11 +2419,12 @@ function SuggestedPrompts({
2317
2419
  }
2318
2420
 
2319
2421
  // src/components/ui/separator.tsx
2320
- import { jsx as jsx20 } from "react/jsx-runtime";
2422
+ import { jsx as jsx21 } from "react/jsx-runtime";
2321
2423
  function Separator({ className }) {
2322
- return /* @__PURE__ */ jsx20("div", { role: "separator", className: cn("h-px w-full bg-border", className) });
2424
+ return /* @__PURE__ */ jsx21("div", { role: "separator", className: cn("h-px w-full bg-border", className) });
2323
2425
  }
2324
2426
  export {
2427
+ ActionConfirm,
2325
2428
  Avatar,
2326
2429
  Badge,
2327
2430
  Button,