@arbidocs/blocks 0.3.119 → 0.3.121

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.cjs CHANGED
@@ -1,16 +1,17 @@
1
1
  'use strict';
2
2
 
3
- var zustand = require('zustand');
4
- var middleware = require('zustand/middleware');
3
+ var chunkAHWIZJ4M_cjs = require('./chunk-AHWIZJ4M.cjs');
5
4
  var react$1 = require('react');
6
- var lucideReact = require('lucide-react');
7
5
  var react = require('@arbidocs/react');
8
6
  var jsxRuntime = require('react/jsx-runtime');
9
7
  var reactQuery = require('@tanstack/react-query');
10
8
  var agGridReact = require('ag-grid-react');
11
9
  var agGridCommunity = require('ag-grid-community');
10
+ var lucideReact = require('lucide-react');
12
11
  var reactRouterDom = require('react-router-dom');
13
12
  var puck = require('@measured/puck');
13
+ var zustand = require('zustand');
14
+ var middleware = require('zustand/middleware');
14
15
 
15
16
  // src/prompts.ts
16
17
  function matterToContext(m) {
@@ -193,380 +194,23 @@ Lead with why the firm is the right choice, reference relevant experience at a t
193
194
  ];
194
195
  return { prompts, WORKFLOW_ACTIONS };
195
196
  }
196
-
197
- // src/theme/tokens.ts
198
- var THEME_STYLE_ID = "arbi-theme-vars";
199
- var TRIPLET_RE = /^-?\d+(?:\.\d+)?\s+-?\d+(?:\.\d+)?%\s+-?\d+(?:\.\d+)?%$/;
200
- function parseRgb(color) {
201
- if (color.startsWith("#")) {
202
- let hex = color.slice(1);
203
- if (hex.length === 3) {
204
- hex = hex.split("").map((ch) => ch + ch).join("");
205
- }
206
- if (hex.length === 6 && /^[0-9a-fA-F]{6}$/.test(hex)) {
207
- return {
208
- r: parseInt(hex.slice(0, 2), 16),
209
- g: parseInt(hex.slice(2, 4), 16),
210
- b: parseInt(hex.slice(4, 6), 16)
211
- };
212
- }
197
+ var ConnectionContext = react$1.createContext(null);
198
+ var WORKSPACE_STORAGE_PREFIX = "arbi:selectedWorkspace";
199
+ var workspaceStorageKey = (apiUrl) => `${WORKSPACE_STORAGE_PREFIX}:${apiUrl || "demo"}`;
200
+ function readPersistedWorkspace(apiUrl) {
201
+ try {
202
+ return window.localStorage.getItem(workspaceStorageKey(apiUrl));
203
+ } catch {
213
204
  return null;
214
205
  }
215
- const m = color.match(/^rgba?\(\s*([\d.]+)[\s,]+([\d.]+)[\s,]+([\d.]+)/i);
216
- if (m) return { r: Number(m[1]), g: Number(m[2]), b: Number(m[3]) };
217
- return null;
218
- }
219
- function rgbToHslTriplet(r, g, b) {
220
- const rn = r / 255;
221
- const gn = g / 255;
222
- const bn = b / 255;
223
- const max = Math.max(rn, gn, bn);
224
- const min = Math.min(rn, gn, bn);
225
- const l = (max + min) / 2;
226
- const d = max - min;
227
- let h = 0;
228
- let s = 0;
229
- if (d !== 0) {
230
- s = d / (1 - Math.abs(2 * l - 1));
231
- switch (max) {
232
- case rn:
233
- h = 60 * ((gn - bn) / d % 6);
234
- break;
235
- case gn:
236
- h = 60 * ((bn - rn) / d + 2);
237
- break;
238
- default:
239
- h = 60 * ((rn - gn) / d + 4);
240
- break;
241
- }
242
- }
243
- if (h < 0) h += 360;
244
- return `${Math.round(h)} ${Math.round(s * 100)}% ${Math.round(l * 100)}%`;
245
- }
246
- function toHslTriplet(color) {
247
- const c = color.trim();
248
- if (TRIPLET_RE.test(c)) return c;
249
- const rgb = parseRgb(c);
250
- if (!rgb) return c;
251
- return rgbToHslTriplet(rgb.r, rgb.g, rgb.b);
252
- }
253
- function renderTripletBlock(colors) {
254
- return Object.entries(colors).map(([key, value]) => ` --${key}: ${toHslTriplet(value)};`).join("\n");
255
- }
256
- function emitCssVars(theme, dark) {
257
- if (typeof document === "undefined") return;
258
- const meta = [
259
- ` --font-display: ${theme.fonts.display};`,
260
- ` --font-sans: ${theme.fonts.sans};`,
261
- ` --radius: ${theme.radius}rem;`
262
- ].join("\n");
263
- let css = `:root {
264
- ${renderTripletBlock(theme.colors)}
265
- ${meta}
266
- }`;
267
- if (dark) {
268
- css += `
269
- :root.dark {
270
- ${renderTripletBlock(dark)}
271
- }`;
272
- }
273
- let style = document.getElementById(THEME_STYLE_ID);
274
- if (!style) {
275
- style = document.createElement("style");
276
- style.id = THEME_STYLE_ID;
277
- document.head.appendChild(style);
278
- }
279
- style.textContent = css;
280
- }
281
- function removeCssVars() {
282
- if (typeof document === "undefined") return;
283
- document.getElementById(THEME_STYLE_ID)?.remove();
284
- }
285
- function normalizeOptions(optionsOrRoot) {
286
- if (typeof HTMLElement !== "undefined" && optionsOrRoot instanceof HTMLElement) {
287
- return { root: optionsOrRoot };
288
- }
289
- return optionsOrRoot;
290
- }
291
- function applyThemeVars(theme, optionsOrRoot = {}) {
292
- const { mode = "flat", dark, root = document.documentElement } = normalizeOptions(optionsOrRoot);
293
- if (mode === "cssVars") {
294
- emitCssVars(theme, dark);
295
- return;
296
- }
297
- for (const [key, value] of Object.entries(theme.colors)) {
298
- root.style.setProperty(`--color-${key}`, value);
299
- }
300
- root.style.setProperty("--font-display", theme.fonts.display);
301
- root.style.setProperty("--font-sans", theme.fonts.sans);
302
- root.style.setProperty("--radius", `${theme.radius}rem`);
303
- }
304
- function clearThemeVars(theme, optionsOrRoot = {}) {
305
- const { mode = "flat", root = document.documentElement } = normalizeOptions(optionsOrRoot);
306
- if (mode === "cssVars") {
307
- removeCssVars();
308
- return;
309
- }
310
- for (const key of Object.keys(theme.colors)) {
311
- root.style.removeProperty(`--color-${key}`);
312
- }
313
- root.style.removeProperty("--font-display");
314
- root.style.removeProperty("--font-sans");
315
- root.style.removeProperty("--radius");
316
206
  }
317
- function createThemeStore(config) {
318
- const { defaultTheme, presets, storageKey } = config;
319
- const useStore = zustand.create()(
320
- middleware.persist(
321
- (set, get) => ({
322
- ...defaultTheme,
323
- activePresetId: presets[0]?.id ?? null,
324
- setColor: (key, value) => set((s) => ({ colors: { ...s.colors, [key]: value }, activePresetId: null })),
325
- setFont: (which, value) => set((s) => ({ fonts: { ...s.fonts, [which]: value }, activePresetId: null })),
326
- setRadius: (radius) => set({ radius, activePresetId: null }),
327
- applyPreset: (presetId) => {
328
- const preset = presets.find((p) => p.id === presetId);
329
- if (!preset) return;
330
- set({
331
- colors: { ...preset.tokens.colors },
332
- fonts: { ...preset.tokens.fonts },
333
- radius: preset.tokens.radius,
334
- activePresetId: presetId
335
- });
336
- },
337
- reset: () => set({
338
- colors: { ...defaultTheme.colors },
339
- fonts: { ...defaultTheme.fonts },
340
- radius: defaultTheme.radius,
341
- activePresetId: presets[0]?.id ?? null
342
- }),
343
- snapshot: () => {
344
- const { colors, fonts, radius } = get();
345
- return { colors, fonts, radius };
346
- }
347
- }),
348
- { name: storageKey }
349
- )
350
- );
351
- return { ...config, useStore };
352
- }
353
- function applyStoredTheme(bundle) {
354
- const { colors, fonts, radius } = bundle.useStore.getState();
355
- applyThemeVars({ colors, fonts, radius }, { mode: bundle.mode, dark: bundle.darkColors });
356
- }
357
- function ThemeEditor({
358
- bundle,
359
- variant = "panel",
360
- preview,
361
- onSave,
362
- testIdPrefix = "theme"
363
- }) {
364
- const { useStore, tokens, presets, groupLabels, mode, darkColors } = bundle;
365
- const colors = useStore((s) => s.colors);
366
- const fonts = useStore((s) => s.fonts);
367
- const radius = useStore((s) => s.radius);
368
- const activePresetId = useStore((s) => s.activePresetId);
369
- const setColor = useStore((s) => s.setColor);
370
- const setFont = useStore((s) => s.setFont);
371
- const setRadius = useStore((s) => s.setRadius);
372
- const applyPreset = useStore((s) => s.applyPreset);
373
- const reset = useStore((s) => s.reset);
374
- const [saving, setSaving] = react$1.useState(false);
375
- const [savedVia, setSavedVia] = react$1.useState(null);
376
- react$1.useEffect(() => {
377
- applyThemeVars({ colors, fonts, radius }, { mode, dark: darkColors });
378
- }, [colors, fonts, radius, mode, darkColors]);
379
- const tid2 = (suffix) => `${testIdPrefix}-${suffix}`;
380
- const groups = [...new Set(tokens.map((t) => t.group))];
381
- const save = async () => {
382
- if (!onSave) return;
383
- setSaving(true);
384
- const via = await onSave();
385
- setSavedVia(typeof via === "string" ? via : "saved");
386
- setSaving(false);
387
- };
388
- const Presets = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
389
- presets.map((p) => /* @__PURE__ */ jsxRuntime.jsx(
390
- "button",
391
- {
392
- type: "button",
393
- onClick: () => applyPreset(p.id),
394
- className: `rounded-full border px-3 py-1 text-xs font-medium transition-colors ${activePresetId === p.id ? "border-primary bg-primary text-primary-foreground" : "border-border text-foreground hover:border-primary"}`,
395
- "data-testid": tid2(`preset-${p.id}`),
396
- children: p.label
397
- },
398
- p.id
399
- )),
400
- /* @__PURE__ */ jsxRuntime.jsxs(
401
- "button",
402
- {
403
- type: "button",
404
- onClick: reset,
405
- className: "ml-auto inline-flex items-center gap-1.5 text-xs font-medium text-muted-foreground hover:text-foreground",
406
- "data-testid": tid2("reset"),
407
- children: [
408
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RotateCcw, { className: "size-3" }),
409
- " Reset"
410
- ]
411
- }
412
- )
413
- ] });
414
- const colorRow = (k, label) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
415
- /* @__PURE__ */ jsxRuntime.jsx(
416
- "input",
417
- {
418
- type: "color",
419
- value: colors[k] ?? "#000000",
420
- onChange: (e) => setColor(k, e.target.value),
421
- className: "size-9 shrink-0 cursor-pointer rounded-md border border-border bg-transparent",
422
- "aria-label": label,
423
- "data-testid": tid2(`color-${k}`)
424
- }
425
- ),
426
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
427
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block text-xs text-muted-foreground", children: label }),
428
- /* @__PURE__ */ jsxRuntime.jsx(
429
- react.Input,
430
- {
431
- value: colors[k] ?? "",
432
- onChange: (e) => setColor(k, e.target.value),
433
- className: "bg-card placeholder:text-muted-foreground/70 focus-visible:border-ring/60 focus-visible:ring-2 focus-visible:ring-ring/50 h-7 font-mono text-xs",
434
- "data-testid": tid2(`hex-${k}`)
435
- }
436
- )
437
- ] })
438
- ] }, k);
439
- const Typography = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
440
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
441
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block text-xs text-muted-foreground", children: "Display font stack" }),
442
- /* @__PURE__ */ jsxRuntime.jsx(
443
- react.Input,
444
- {
445
- value: fonts.display,
446
- onChange: (e) => setFont("display", e.target.value),
447
- className: "bg-card placeholder:text-muted-foreground/70 focus-visible:border-ring/60 focus-visible:ring-2 focus-visible:ring-ring/50 mt-1 font-mono text-xs",
448
- "data-testid": tid2("font-display")
449
- }
450
- )
451
- ] }),
452
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
453
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block text-xs text-muted-foreground", children: "Body font stack" }),
454
- /* @__PURE__ */ jsxRuntime.jsx(
455
- react.Input,
456
- {
457
- value: fonts.sans,
458
- onChange: (e) => setFont("sans", e.target.value),
459
- className: "bg-card placeholder:text-muted-foreground/70 focus-visible:border-ring/60 focus-visible:ring-2 focus-visible:ring-ring/50 mt-1 font-mono text-xs",
460
- "data-testid": tid2("font-sans")
461
- }
462
- )
463
- ] }),
464
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
465
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "block text-xs text-muted-foreground", children: [
466
- "Base radius \u2014 ",
467
- radius,
468
- "rem"
469
- ] }),
470
- /* @__PURE__ */ jsxRuntime.jsx(
471
- "input",
472
- {
473
- type: "range",
474
- min: 0,
475
- max: 1.5,
476
- step: 0.125,
477
- value: radius,
478
- onChange: (e) => setRadius(Number(e.target.value)),
479
- className: "mt-2 w-full accent-[color:var(--color-primary)]",
480
- "data-testid": tid2("radius")
481
- }
482
- )
483
- ] })
484
- ] });
485
- const Preview = /* @__PURE__ */ jsxRuntime.jsxs(react.Card, { variant: "elevated", className: "rounded-xl", "data-testid": tid2("preview"), children: [
486
- /* @__PURE__ */ jsxRuntime.jsx(react.CardHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(react.CardTitle, { className: "text-base", children: "Live preview" }) }),
487
- /* @__PURE__ */ jsxRuntime.jsxs(react.CardContent, { className: "space-y-3", children: [
488
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-[var(--radius)] bg-primary p-4 text-primary-foreground", children: [
489
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-display text-lg font-semibold", children: preview?.title ?? "Preview" }),
490
- preview?.subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs opacity-80", children: preview.subtitle })
491
- ] }),
492
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-6 gap-1.5", children: tokens.map((t) => /* @__PURE__ */ jsxRuntime.jsx(
493
- "div",
494
- {
495
- title: t.label,
496
- className: "aspect-square rounded-md border border-border",
497
- style: { background: `var(--color-${t.key})` }
498
- },
499
- t.key
500
- )) }),
501
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-[var(--radius)] border border-border bg-[color:var(--color-ai-accent-soft,var(--color-accent))] p-3", children: [
502
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-[color:var(--color-ai-accent,var(--color-primary))]", children: "AI action surface" }),
503
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "Themed by the AI-kit accent tokens." })
504
- ] })
505
- ] })
506
- ] });
507
- const SaveBar = onSave && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-6 flex items-center gap-3", children: [
508
- /* @__PURE__ */ jsxRuntime.jsxs(
509
- "button",
510
- {
511
- type: "button",
512
- onClick: () => void save(),
513
- disabled: saving,
514
- className: "inline-flex items-center gap-1.5 rounded-md bg-primary px-3 py-2 text-sm font-medium text-primary-foreground hover:opacity-90 disabled:opacity-60",
515
- "data-testid": tid2("save"),
516
- children: [
517
- savedVia ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "size-4" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Save, { className: "size-4" }),
518
- saving ? "Saving\u2026" : savedVia ? "Saved" : "Save theme"
519
- ]
520
- }
521
- ),
522
- savedVia && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground", "data-testid": tid2("via"), children: [
523
- "stored via ",
524
- savedVia
525
- ] })
526
- ] });
527
- if (variant === "drawer") {
528
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full flex-col overflow-y-auto bg-card p-5", "data-testid": testIdPrefix, children: [
529
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-4 flex items-center justify-between", children: /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "font-display text-lg font-semibold text-foreground", children: "Theme" }) }),
530
- Presets,
531
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-5 mb-2 text-[10px] font-semibold uppercase tracking-[0.14em] text-muted-foreground", children: "Colours" }),
532
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-3", children: tokens.map((t) => colorRow(t.key, t.label)) }),
533
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-6 mb-2 text-[10px] font-semibold uppercase tracking-[0.14em] text-muted-foreground", children: "Typography & shape" }),
534
- Typography,
535
- SaveBar
536
- ] });
207
+ function persistWorkspace(apiUrl, id) {
208
+ try {
209
+ if (id) window.localStorage.setItem(workspaceStorageKey(apiUrl), id);
210
+ else window.localStorage.removeItem(workspaceStorageKey(apiUrl));
211
+ } catch {
537
212
  }
538
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-6 lg:grid-cols-[1fr_320px]", "data-testid": testIdPrefix, children: [
539
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
540
- /* @__PURE__ */ jsxRuntime.jsxs(react.Card, { variant: "elevated", className: "rounded-xl", children: [
541
- /* @__PURE__ */ jsxRuntime.jsx(react.CardHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(react.CardTitle, { className: "flex items-center gap-2 text-base", children: [
542
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Palette, { className: "size-4 text-[color:var(--color-primary)]" }),
543
- " Presets"
544
- ] }) }),
545
- /* @__PURE__ */ jsxRuntime.jsx(react.CardContent, { children: Presets })
546
- ] }),
547
- groups.map((group) => /* @__PURE__ */ jsxRuntime.jsxs(
548
- react.Card,
549
- {
550
- variant: "elevated",
551
- className: "rounded-xl",
552
- "data-testid": tid2(`group-${group}`),
553
- children: [
554
- /* @__PURE__ */ jsxRuntime.jsx(react.CardHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(react.CardTitle, { className: "text-base", children: groupLabels[group] ?? group }) }),
555
- /* @__PURE__ */ jsxRuntime.jsx(react.CardContent, { className: "grid gap-3 sm:grid-cols-2", children: tokens.filter((t) => t.group === group).map((t) => colorRow(t.key, t.label)) })
556
- ]
557
- },
558
- group
559
- )),
560
- /* @__PURE__ */ jsxRuntime.jsxs(react.Card, { variant: "elevated", className: "rounded-xl", children: [
561
- /* @__PURE__ */ jsxRuntime.jsx(react.CardHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(react.CardTitle, { className: "text-base", children: "Typography & shape" }) }),
562
- /* @__PURE__ */ jsxRuntime.jsx(react.CardContent, { children: Typography })
563
- ] }),
564
- SaveBar
565
- ] }),
566
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "lg:sticky lg:top-4 lg:self-start", children: Preview })
567
- ] });
568
213
  }
569
- var ConnectionContext = react$1.createContext(null);
570
214
  function ConnectionProvider({
571
215
  config,
572
216
  children
@@ -599,10 +243,12 @@ function ConnectionProvider({
599
243
  await arbi.login(email, password);
600
244
  const workspaces = await arbi.workspaces.list();
601
245
  if (workspaces?.length) {
602
- const preferred = config.workspaceId;
246
+ const persisted = readPersistedWorkspace(config.apiUrl);
247
+ const preferred = persisted ?? config.workspaceId;
603
248
  const target = (preferred ? workspaces.find((w) => w.external_id === preferred) : void 0) ?? workspaces[0];
604
249
  await arbi.selectWorkspace(target.external_id);
605
250
  setWorkspaceId(target.external_id);
251
+ persistWorkspace(config.apiUrl, target.external_id);
606
252
  }
607
253
  let resolved = { name: email.split("@")[0], email };
608
254
  try {
@@ -629,7 +275,7 @@ function ConnectionProvider({
629
275
  setStatus("error");
630
276
  }
631
277
  },
632
- [arbi, enterDemo, isLiveConfigured, config.workspaceId]
278
+ [arbi, enterDemo, isLiveConfigured, config.workspaceId, config.apiUrl]
633
279
  );
634
280
  const logout = react$1.useCallback(() => {
635
281
  if (mode === "live") {
@@ -637,10 +283,25 @@ function ConnectionProvider({
637
283
  }
638
284
  setUser(null);
639
285
  setWorkspaceId(null);
286
+ persistWorkspace(config.apiUrl, null);
640
287
  setStatus("disconnected");
641
288
  setError(null);
642
- }, [arbi, mode]);
643
- const setWorkspace = react$1.useCallback((id) => setWorkspaceId(id), []);
289
+ }, [arbi, mode, config.apiUrl]);
290
+ const setWorkspace = react$1.useCallback(
291
+ async (id) => {
292
+ if (mode === "live" && arbi.isLoggedIn) {
293
+ await arbi.selectWorkspace(id);
294
+ }
295
+ setWorkspaceId(id);
296
+ persistWorkspace(config.apiUrl, id);
297
+ },
298
+ [arbi, mode, config.apiUrl]
299
+ );
300
+ const ensureWorkspaceOpen = react$1.useCallback(async () => {
301
+ if (mode !== "live" || !arbi.isLoggedIn) return;
302
+ const id = workspaceId ?? readPersistedWorkspace(config.apiUrl) ?? config.workspaceId;
303
+ if (id) await arbi.selectWorkspace(id);
304
+ }, [arbi, mode, workspaceId, config.apiUrl, config.workspaceId]);
644
305
  const value = react$1.useMemo(
645
306
  () => ({
646
307
  mode,
@@ -655,7 +316,8 @@ function ConnectionProvider({
655
316
  login,
656
317
  enterDemo,
657
318
  logout,
658
- setWorkspace
319
+ setWorkspace,
320
+ ensureWorkspaceOpen
659
321
  }),
660
322
  [
661
323
  mode,
@@ -670,7 +332,8 @@ function ConnectionProvider({
670
332
  login,
671
333
  enterDemo,
672
334
  logout,
673
- setWorkspace
335
+ setWorkspace,
336
+ ensureWorkspaceOpen
674
337
  ]
675
338
  );
676
339
  return /* @__PURE__ */ jsxRuntime.jsx(ConnectionContext.Provider, { value, children });
@@ -715,100 +378,6 @@ function useSemanticSearch() {
715
378
  const { docIds } = useWorkspaceDocs();
716
379
  return react.useSemanticSearch(docIds);
717
380
  }
718
-
719
- // src/lib/testid.ts
720
- function tid(...parts) {
721
- return parts.filter((p) => p !== void 0 && p !== false && p !== "").map(
722
- (p) => String(p).trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "")
723
- ).join("-");
724
- }
725
-
726
- // src/lib/format.ts
727
- function gbp(value, compact = false) {
728
- return new Intl.NumberFormat("en-GB", {
729
- style: "currency",
730
- currency: "GBP",
731
- maximumFractionDigits: compact && Math.abs(value) >= 1e3 ? 1 : 0,
732
- notation: compact ? "compact" : "standard"
733
- }).format(value);
734
- }
735
- function initials(name) {
736
- const parts = name.trim().split(/\s+/);
737
- if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase();
738
- return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
739
- }
740
- function parseIso(iso) {
741
- const dateOnly = /^\d{4}-\d{2}-\d{2}$/.test(iso);
742
- const d = new Date(dateOnly ? `${iso}T00:00:00` : iso);
743
- if (Number.isNaN(d.getTime())) throw new Error(`Invalid ISO date: ${iso}`);
744
- return d;
745
- }
746
- function fmtDate(iso) {
747
- try {
748
- return new Intl.DateTimeFormat("en-GB", {
749
- day: "numeric",
750
- month: "short",
751
- year: "numeric"
752
- }).format(parseIso(iso));
753
- } catch {
754
- return iso;
755
- }
756
- }
757
- function fmtDateTime(iso) {
758
- try {
759
- return new Intl.DateTimeFormat("en-GB", {
760
- day: "numeric",
761
- month: "short",
762
- year: "numeric",
763
- hour: "2-digit",
764
- minute: "2-digit",
765
- hour12: false
766
- }).format(parseIso(iso));
767
- } catch {
768
- return iso;
769
- }
770
- }
771
- var RELATIVE_UNITS = [
772
- ["year", 31536e3],
773
- ["month", 2592e3],
774
- ["week", 604800],
775
- ["day", 86400],
776
- ["hour", 3600],
777
- ["minute", 60],
778
- ["second", 1]
779
- ];
780
- function fromNow(iso, from = /* @__PURE__ */ new Date()) {
781
- try {
782
- const diffSeconds = (parseIso(iso).getTime() - from.getTime()) / 1e3;
783
- const abs = Math.abs(diffSeconds);
784
- const rtf = new Intl.RelativeTimeFormat("en-GB", { numeric: "always" });
785
- for (const [unit, secs] of RELATIVE_UNITS) {
786
- if (abs >= secs || unit === "second") {
787
- const value = Math.round(diffSeconds / secs);
788
- return rtf.format(value, unit);
789
- }
790
- }
791
- return rtf.format(0, "second");
792
- } catch {
793
- return iso;
794
- }
795
- }
796
- function daysUntil(iso, from = /* @__PURE__ */ new Date()) {
797
- try {
798
- const target = parseIso(iso);
799
- const a = Date.UTC(target.getFullYear(), target.getMonth(), target.getDate());
800
- const b = Date.UTC(from.getFullYear(), from.getMonth(), from.getDate());
801
- return Math.round((a - b) / 864e5);
802
- } catch {
803
- return 0;
804
- }
805
- }
806
- function hrs(n) {
807
- return `${n.toFixed(1)}h`;
808
- }
809
- function pct(n) {
810
- return `${Math.round(n)}%`;
811
- }
812
381
  function EmptyState({
813
382
  icon: Icon,
814
383
  title,
@@ -846,9 +415,9 @@ function DataTable({
846
415
  className
847
416
  }) {
848
417
  if (rows.length === 0) {
849
- return /* @__PURE__ */ jsxRuntime.jsx(EmptyState, { title: emptyTitle, description: emptyDescription, testId: tid(area, "empty") });
418
+ return /* @__PURE__ */ jsxRuntime.jsx(EmptyState, { title: emptyTitle, description: emptyDescription, testId: chunkAHWIZJ4M_cjs.tid(area, "empty") });
850
419
  }
851
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: react.cn("rounded-xl border border-border bg-card", className), children: /* @__PURE__ */ jsxRuntime.jsxs(react.Table, { "data-testid": tid(area, "table"), children: [
420
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: react.cn("rounded-xl border border-border bg-card", className), children: /* @__PURE__ */ jsxRuntime.jsxs(react.Table, { "data-testid": chunkAHWIZJ4M_cjs.tid(area, "table"), children: [
852
421
  /* @__PURE__ */ jsxRuntime.jsx(react.TableHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(react.TableRow, { className: "hover:bg-transparent", children: columns.map((c) => /* @__PURE__ */ jsxRuntime.jsx(
853
422
  react.TableHead,
854
423
  {
@@ -862,7 +431,7 @@ function DataTable({
862
431
  return /* @__PURE__ */ jsxRuntime.jsx(
863
432
  react.TableRow,
864
433
  {
865
- "data-testid": tid(area, "row", id),
434
+ "data-testid": chunkAHWIZJ4M_cjs.tid(area, "row", id),
866
435
  onClick: onRowClick ? () => onRowClick(row) : void 0,
867
436
  className: react.cn(onRowClick && "cursor-pointer"),
868
437
  children: columns.map((c) => /* @__PURE__ */ jsxRuntime.jsx(
@@ -1305,6 +874,84 @@ function GridView({
1305
874
  }
1306
875
  ) });
1307
876
  }
877
+ function UploadDropzone({
878
+ onFiles,
879
+ accept,
880
+ multiple = true,
881
+ disabled = false,
882
+ uploading = false,
883
+ title = "Drag files here",
884
+ description = "or click to browse",
885
+ hint,
886
+ uploadingLabel = "Uploading\u2026",
887
+ icon: Icon = lucideReact.UploadCloud,
888
+ testId,
889
+ className
890
+ }) {
891
+ const inputRef = react$1.useRef(null);
892
+ const [dragOver, setDragOver] = react$1.useState(false);
893
+ const inert = disabled || uploading;
894
+ const pick = (files) => {
895
+ if (!files?.length) return;
896
+ onFiles(Array.from(files));
897
+ };
898
+ const onDrop = (e) => {
899
+ e.preventDefault();
900
+ setDragOver(false);
901
+ if (inert) return;
902
+ pick(e.dataTransfer.files);
903
+ };
904
+ const onDragOver = (e) => {
905
+ e.preventDefault();
906
+ if (!inert) setDragOver(true);
907
+ };
908
+ return /* @__PURE__ */ jsxRuntime.jsxs(
909
+ "button",
910
+ {
911
+ type: "button",
912
+ onClick: () => !inert && inputRef.current?.click(),
913
+ onDrop,
914
+ onDragOver,
915
+ onDragLeave: () => setDragOver(false),
916
+ disabled: inert,
917
+ "data-testid": testId,
918
+ className: react.cn(
919
+ "flex w-full flex-col items-center justify-center gap-3 rounded-xl border-2 border-dashed border-border bg-muted/30 px-6 py-12 text-center transition-colors",
920
+ "hover:border-primary/50 hover:bg-muted/50",
921
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
922
+ dragOver && "border-primary bg-primary/5",
923
+ inert && "cursor-not-allowed opacity-60 hover:border-border hover:bg-muted/30",
924
+ className
925
+ ),
926
+ children: [
927
+ /* @__PURE__ */ jsxRuntime.jsx(
928
+ "input",
929
+ {
930
+ ref: inputRef,
931
+ type: "file",
932
+ accept,
933
+ multiple,
934
+ className: "hidden",
935
+ onChange: (e) => {
936
+ pick(e.target.files);
937
+ if (inputRef.current) inputRef.current.value = "";
938
+ },
939
+ "data-testid": testId ? `${testId}-input` : void 0
940
+ }
941
+ ),
942
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex size-12 items-center justify-center rounded-full bg-primary/10 text-primary", children: uploading ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "size-6 animate-spin" }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "size-6" }) }),
943
+ uploading ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-foreground", children: uploadingLabel }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
944
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm font-medium text-foreground", children: [
945
+ title,
946
+ " ",
947
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: description })
948
+ ] }),
949
+ hint && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: hint })
950
+ ] })
951
+ ]
952
+ }
953
+ );
954
+ }
1308
955
  function PageHeader({
1309
956
  title,
1310
957
  eyebrow,
@@ -1329,48 +976,6 @@ function PageHeader({
1329
976
  }
1330
977
  );
1331
978
  }
1332
- function SectionHeading({
1333
- eyebrow,
1334
- title,
1335
- lead,
1336
- align = "left",
1337
- className,
1338
- invert,
1339
- eyebrowClassName
1340
- }) {
1341
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: react.cn("max-w-3xl", align === "center" && "mx-auto text-center", className), children: [
1342
- eyebrow && /* @__PURE__ */ jsxRuntime.jsx(
1343
- "p",
1344
- {
1345
- className: react.cn(
1346
- "mb-3 text-xs font-semibold uppercase tracking-wider",
1347
- eyebrowClassName ?? (invert ? "text-background/60" : "text-muted-foreground")
1348
- ),
1349
- children: eyebrow
1350
- }
1351
- ),
1352
- /* @__PURE__ */ jsxRuntime.jsx(
1353
- "h2",
1354
- {
1355
- className: react.cn(
1356
- "font-display text-3xl font-semibold tracking-tight text-balance sm:text-4xl",
1357
- invert ? "text-background" : "text-foreground"
1358
- ),
1359
- children: title
1360
- }
1361
- ),
1362
- lead && /* @__PURE__ */ jsxRuntime.jsx(
1363
- "p",
1364
- {
1365
- className: react.cn(
1366
- "mt-4 text-lg leading-relaxed",
1367
- invert ? "text-background/70" : "text-muted-foreground"
1368
- ),
1369
- children: lead
1370
- }
1371
- )
1372
- ] });
1373
- }
1374
979
  function Toolbar({
1375
980
  search,
1376
981
  onSearch,
@@ -1452,869 +1057,102 @@ function MetricCard({
1452
1057
  ] })
1453
1058
  ] });
1454
1059
  }
1455
- var ASSET_REF_PREFIX = "asset:";
1456
- function asAssetRef(docId) {
1457
- return `${ASSET_REF_PREFIX}${docId}`;
1458
- }
1459
- function assetRefId(src) {
1460
- return src.slice(ASSET_REF_PREFIX.length);
1461
- }
1462
- var AssetResolverContext = react$1.createContext(false);
1463
- function AssetResolverProvider({ children }) {
1464
- return /* @__PURE__ */ jsxRuntime.jsx(AssetResolverContext.Provider, { value: true, children });
1465
- }
1466
- function useAssetResolverActive() {
1467
- return react$1.useContext(AssetResolverContext);
1468
- }
1469
- function isAssetRef(src) {
1470
- return !!src && src.startsWith(ASSET_REF_PREFIX);
1471
- }
1472
- function useAssetImage(docId) {
1473
- const arbi = react.useArbi();
1474
- const { data: thumbs } = react.useThumbnails([docId]);
1475
- const thumb = thumbs?.[docId];
1476
- const { data: objectUrl } = reactQuery.useQuery({
1477
- queryKey: ["arbi", "asset-image", docId],
1478
- queryFn: async () => {
1479
- const res = await arbi.documents.download(docId);
1480
- const blob = await res.blob();
1481
- return URL.createObjectURL(blob);
1482
- },
1483
- // Only download when the thumbnail is genuinely absent (not merely loading).
1484
- enabled: !!docId && thumbs != null && !thumb && arbi.hasWorkspace,
1485
- staleTime: 10 * 6e4
1486
- });
1487
- react$1.useEffect(() => {
1488
- return () => {
1489
- if (objectUrl) URL.revokeObjectURL(objectUrl);
1490
- };
1491
- }, [objectUrl]);
1492
- return thumb ?? objectUrl;
1493
- }
1494
- function AssetThumb({
1495
- docId,
1496
- alt,
1497
- className,
1498
- testId
1499
- }) {
1500
- const src = useAssetImage(docId);
1501
- return /* @__PURE__ */ jsxRuntime.jsx("img", { src: src ?? void 0, alt: alt ?? "", className, "data-testid": testId });
1502
- }
1503
- var ASPECT = {
1504
- "16:9": "aspect-video",
1505
- "4:3": "aspect-[4/3]",
1506
- "1:1": "aspect-square",
1507
- "21:9": "aspect-[21/9]",
1508
- "4:5": "aspect-[4/5]"
1509
- };
1510
- var ROUNDED = {
1511
- none: "rounded-none",
1512
- md: "rounded-md",
1513
- lg: "rounded-xl",
1514
- full: "rounded-full"
1515
- };
1516
- function BlockImage({
1517
- src,
1518
- alt = "",
1519
- aspect = "16:9",
1520
- rounded = "lg",
1521
- framed,
1522
- className,
1523
- testId
1524
- }) {
1525
- const shape = react.cn(
1526
- ASPECT[aspect] ?? ASPECT["16:9"],
1527
- ROUNDED[rounded] ?? ROUNDED.lg,
1528
- framed && "ring-1 ring-border shadow-xl"
1529
- );
1530
- const canResolve = useAssetResolverActive();
1531
- if (canResolve && isAssetRef(src)) {
1532
- return /* @__PURE__ */ jsxRuntime.jsx(
1533
- AssetThumb,
1534
- {
1535
- docId: assetRefId(src),
1536
- alt,
1537
- className: react.cn("w-full object-cover", shape, className),
1538
- testId
1539
- }
1540
- );
1541
- }
1542
- if (src && !isAssetRef(src)) {
1543
- return /* @__PURE__ */ jsxRuntime.jsx(
1544
- "img",
1545
- {
1546
- src,
1547
- alt,
1548
- className: react.cn("w-full object-cover", shape, className),
1549
- "data-testid": testId
1550
- }
1551
- );
1552
- }
1553
- return /* @__PURE__ */ jsxRuntime.jsx(
1554
- "div",
1555
- {
1556
- className: react.cn(
1557
- "flex w-full items-center justify-center overflow-hidden border border-border",
1558
- "bg-gradient-to-br from-muted via-card to-accent text-muted-foreground",
1559
- shape,
1560
- className
1561
- ),
1562
- "data-testid": testId,
1563
- "aria-label": alt || "Image placeholder",
1564
- role: "img",
1565
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ImageIcon, { className: "size-8 opacity-60" })
1566
- }
1567
- );
1568
- }
1569
- var TONE_SURFACE = {
1570
- default: "bg-background text-foreground",
1571
- muted: "bg-muted text-foreground",
1572
- ink: "bg-foreground text-background"
1573
- };
1574
- function renderTitle(title, emphasis) {
1575
- if (!emphasis || !title.includes(emphasis)) return title;
1576
- const parts = title.split(emphasis);
1577
- return parts.map((part, i) => /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
1578
- part,
1579
- i < parts.length - 1 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-primary", children: emphasis })
1580
- ] }, i));
1581
- }
1582
- function Hero({
1583
- eyebrow,
1584
- title,
1585
- emphasis,
1586
- subtitle,
1587
- primaryCta,
1588
- secondaryCta,
1589
- align = "left",
1590
- tone = "default",
1591
- imageUrl,
1592
- backgroundImage,
1593
- overlay = true,
1594
- eyebrowClassName,
1595
- testId
1596
- }) {
1597
- const onDark = Boolean(backgroundImage) || tone === "ink";
1598
- const subtle = onDark ? "text-background/70" : "text-muted-foreground";
1599
- const eyebrowClass = eyebrowClassName ?? (onDark ? "text-background/60" : "text-muted-foreground");
1600
- const centered = align === "center" || Boolean(backgroundImage);
1601
- const heading = renderTitle(title, emphasis);
1602
- const copy = /* @__PURE__ */ jsxRuntime.jsxs(
1603
- "div",
1604
- {
1605
- className: react.cn(
1606
- "max-w-2xl",
1607
- centered && "mx-auto text-center",
1608
- backgroundImage && "text-background"
1609
- ),
1610
- children: [
1611
- eyebrow && /* @__PURE__ */ jsxRuntime.jsx("p", { className: react.cn("mb-4 text-sm font-semibold uppercase tracking-wider", eyebrowClass), children: eyebrow }),
1612
- /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-4xl font-semibold tracking-tight text-balance sm:text-5xl", children: heading }),
1613
- subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: react.cn("mt-6 text-lg leading-relaxed", subtle), children: subtitle }),
1614
- (primaryCta?.label || secondaryCta?.label) && /* @__PURE__ */ jsxRuntime.jsxs(
1615
- "div",
1616
- {
1617
- className: react.cn("mt-8 flex flex-col gap-3 sm:flex-row", centered && "sm:justify-center"),
1618
- children: [
1619
- primaryCta?.label && /* @__PURE__ */ jsxRuntime.jsx(react.Button, { asChild: true, size: "lg", children: /* @__PURE__ */ jsxRuntime.jsxs("a", { href: primaryCta.href || "#", children: [
1620
- primaryCta.label,
1621
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRight, { className: "size-4" })
1622
- ] }) }),
1623
- secondaryCta?.label && /* @__PURE__ */ jsxRuntime.jsx(react.Button, { asChild: true, size: "lg", variant: "outline", children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: secondaryCta.href || "#", children: secondaryCta.label }) })
1624
- ]
1625
- }
1626
- )
1627
- ]
1628
- }
1629
- );
1630
- if (backgroundImage) {
1631
- const bgStyle = {
1632
- backgroundImage: `url("${backgroundImage}")`,
1633
- backgroundSize: "cover",
1634
- backgroundPosition: "center"
1635
- };
1636
- return /* @__PURE__ */ jsxRuntime.jsxs(
1637
- "section",
1638
- {
1639
- className: "relative isolate overflow-hidden",
1640
- style: bgStyle,
1641
- "data-testid": testId,
1642
- "data-bg": testId && `${testId}-bg`,
1643
- children: [
1644
- overlay && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 bg-black/55", "aria-hidden": true }),
1645
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative mx-auto max-w-7xl px-5 py-28 lg:px-8 lg:py-36", children: copy })
1646
- ]
1647
- }
1648
- );
1649
- }
1650
- return /* @__PURE__ */ jsxRuntime.jsx("section", { className: react.cn(TONE_SURFACE[tone] ?? TONE_SURFACE.default), "data-testid": testId, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-auto max-w-7xl px-5 py-20 lg:px-8 lg:py-28", children: centered ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-12", children: [
1651
- copy,
1652
- imageUrl && /* @__PURE__ */ jsxRuntime.jsx(
1653
- BlockImage,
1654
- {
1655
- src: imageUrl,
1656
- aspect: "16:9",
1657
- rounded: "lg",
1658
- className: "w-full max-w-4xl",
1659
- testId: testId && `${testId}-image`
1660
- }
1661
- )
1662
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid items-center gap-12 lg:grid-cols-2", children: [
1663
- copy,
1664
- /* @__PURE__ */ jsxRuntime.jsx(
1665
- BlockImage,
1666
- {
1667
- src: imageUrl,
1668
- aspect: "4:5",
1669
- rounded: "lg",
1670
- testId: testId && `${testId}-image`
1671
- }
1672
- )
1673
- ] }) }) });
1674
- }
1675
- var COLS = {
1676
- "2": "sm:grid-cols-2",
1677
- "3": "sm:grid-cols-2 lg:grid-cols-3"
1678
- };
1679
- function FeatureGrid({ columns = "3", items, testId }) {
1680
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: react.cn("grid gap-5", COLS[columns] ?? COLS["3"]), "data-testid": testId, children: (items ?? []).map((item, i) => {
1681
- const Icon = item.icon;
1682
- return /* @__PURE__ */ jsxRuntime.jsxs(
1683
- react.Card,
1684
- {
1685
- variant: "outline",
1686
- className: "h-full p-6",
1687
- "data-testid": testId && `${testId}-item-${i}`,
1688
- children: [
1689
- Icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mb-4 inline-flex size-10 items-center justify-center rounded-lg bg-primary/10 text-primary", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "size-5" }) }),
1690
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold tracking-tight", children: item.title }),
1691
- item.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm leading-relaxed text-muted-foreground", children: item.description })
1692
- ]
1693
- },
1694
- i
1695
- );
1696
- }) });
1697
- }
1698
- var GRID = {
1699
- 1: "grid-cols-1",
1700
- 2: "grid-cols-2",
1701
- 3: "grid-cols-2 sm:grid-cols-3",
1702
- 4: "grid-cols-2 lg:grid-cols-4"
1703
- };
1704
- function StatGroup({ items, testId }) {
1705
- const list = items ?? [];
1706
- const cols = GRID[Math.min(list.length, 4)] ?? GRID[4];
1707
- return /* @__PURE__ */ jsxRuntime.jsx("dl", { className: react.cn("grid gap-8", cols), "data-testid": testId, children: list.map((item, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", "data-testid": testId && `${testId}-item-${i}`, children: [
1708
- /* @__PURE__ */ jsxRuntime.jsx("dt", { className: "sr-only", children: item.label }),
1709
- /* @__PURE__ */ jsxRuntime.jsx("dd", { className: "text-4xl font-semibold tracking-tight sm:text-5xl", children: item.value }),
1710
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: item.label })
1711
- ] }, i)) });
1712
- }
1713
- function Testimonial({ quote, author, role, avatarUrl, testId }) {
1714
- return /* @__PURE__ */ jsxRuntime.jsxs(react.Card, { variant: "outline", className: "mx-auto max-w-3xl p-8 text-center", "data-testid": testId, children: [
1715
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Quote, { className: "mx-auto size-8 text-primary/40", "aria-hidden": true }),
1716
- /* @__PURE__ */ jsxRuntime.jsx("blockquote", { className: "mt-4 text-xl font-medium leading-relaxed text-balance", children: quote }),
1717
- (author || avatarUrl) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-6 flex items-center justify-center gap-3", children: [
1718
- (avatarUrl || author) && /* @__PURE__ */ jsxRuntime.jsxs(react.Avatar, { children: [
1719
- avatarUrl && /* @__PURE__ */ jsxRuntime.jsx(react.AvatarImage, { src: avatarUrl, alt: author ?? "" }),
1720
- /* @__PURE__ */ jsxRuntime.jsx(react.AvatarFallback, { children: initials(author || "?") })
1721
- ] }),
1722
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-left", children: [
1723
- author && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold", children: author }),
1724
- role && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: role })
1725
- ] })
1726
- ] })
1727
- ] });
1728
- }
1729
- var TONE_SURFACE2 = {
1730
- default: "bg-primary text-primary-foreground",
1731
- muted: "bg-muted text-foreground",
1732
- ink: "bg-foreground text-background"
1733
- };
1734
- function CTABanner({
1735
- title,
1736
- subtitle,
1737
- cta,
1738
- tone = "default",
1739
- backgroundImage,
1740
- overlay = true,
1741
- testId
1742
- }) {
1743
- const onImage = Boolean(backgroundImage);
1744
- const subtle = onImage ? "text-white/80" : tone === "default" ? "text-primary-foreground/80" : tone === "ink" ? "text-background/70" : "text-muted-foreground";
1745
- const bgStyle = backgroundImage ? {
1746
- backgroundImage: `url("${backgroundImage}")`,
1747
- backgroundSize: "cover",
1748
- backgroundPosition: "center"
1749
- } : void 0;
1750
- return /* @__PURE__ */ jsxRuntime.jsxs(
1751
- "div",
1752
- {
1753
- className: react.cn(
1754
- "relative isolate overflow-hidden rounded-2xl px-8 py-14 text-center",
1755
- onImage ? "text-white" : TONE_SURFACE2[tone] ?? TONE_SURFACE2.default
1756
- ),
1757
- style: bgStyle,
1758
- "data-testid": testId,
1759
- children: [
1760
- onImage && overlay && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 bg-black/55", "aria-hidden": true }),
1761
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
1762
- /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-3xl font-semibold tracking-tight text-balance sm:text-4xl", children: title }),
1763
- subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: react.cn("mx-auto mt-4 max-w-2xl text-lg", subtle), children: subtitle }),
1764
- cta?.label && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-8", children: /* @__PURE__ */ jsxRuntime.jsx(
1765
- react.Button,
1766
- {
1767
- asChild: true,
1768
- size: "lg",
1769
- variant: tone === "default" && !onImage ? "secondary" : "default",
1770
- children: /* @__PURE__ */ jsxRuntime.jsxs("a", { href: cta.href || "#", children: [
1771
- cta.label,
1772
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRight, { className: "size-4" })
1773
- ] })
1774
- }
1775
- ) })
1776
- ] })
1777
- ]
1778
- }
1779
- );
1780
- }
1781
- function LogoCloud({ items, testId }) {
1782
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap items-center justify-center gap-4", "data-testid": testId, children: (items ?? []).map((item, i) => /* @__PURE__ */ jsxRuntime.jsx(
1783
- "span",
1784
- {
1785
- className: "rounded-md border border-border bg-muted px-5 py-2.5 text-sm font-semibold uppercase tracking-wide text-muted-foreground",
1786
- "data-testid": testId && `${testId}-item-${i}`,
1787
- children: item.label
1788
- },
1789
- i
1790
- )) });
1791
- }
1792
- function FAQ({ items, testId }) {
1793
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-auto max-w-3xl divide-y divide-border", "data-testid": testId, children: (items ?? []).map((item, i) => /* @__PURE__ */ jsxRuntime.jsxs("details", { className: "group py-4", "data-testid": testId && `${testId}-item-${i}`, children: [
1794
- /* @__PURE__ */ jsxRuntime.jsxs("summary", { className: "flex cursor-pointer list-none items-center justify-between gap-4 text-left text-base font-medium", children: [
1795
- item.question,
1796
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "size-4 shrink-0 text-muted-foreground transition-transform group-open:rotate-180" })
1797
- ] }),
1798
- item.answer && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-3 text-sm leading-relaxed text-muted-foreground", children: item.answer })
1799
- ] }, i)) });
1800
- }
1801
- function RichTextBlock({ content, testId }) {
1802
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-auto max-w-3xl", "data-testid": testId, children: /* @__PURE__ */ jsxRuntime.jsx(react.AiMarkdown, { children: content ?? "" }) });
1803
- }
1804
- var STYLES = {
1805
- info: { wrap: "border-primary/30 bg-primary/5", icon: "text-primary", Icon: lucideReact.Info },
1806
- success: { wrap: "border-success/30 bg-success/10", icon: "text-success", Icon: lucideReact.CheckCircle2 },
1807
- warning: { wrap: "border-warning/40 bg-warning/10", icon: "text-warning", Icon: lucideReact.AlertTriangle },
1808
- danger: {
1809
- wrap: "border-destructive/30 bg-destructive/10",
1810
- icon: "text-destructive",
1811
- Icon: lucideReact.XCircle
1812
- }
1813
- };
1814
- function Callout({ variant = "info", title, body, testId }) {
1815
- const style = STYLES[variant] ?? STYLES.info;
1816
- const Icon = style.Icon;
1817
- return /* @__PURE__ */ jsxRuntime.jsxs(
1818
- "div",
1819
- {
1820
- className: react.cn("flex gap-3 rounded-lg border p-4 text-foreground", style.wrap),
1821
- "data-testid": testId,
1822
- role: "note",
1823
- children: [
1824
- /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: react.cn("mt-0.5 size-5 shrink-0", style.icon), "aria-hidden": true }),
1825
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
1826
- title && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-semibold", children: title }),
1827
- body && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm leading-relaxed text-muted-foreground", children: body })
1828
- ] })
1829
- ]
1830
- }
1831
- );
1832
- }
1833
- var SIZE = {
1834
- sm: "size-8 text-xs",
1835
- md: "size-10 text-sm",
1836
- lg: "size-14 text-base",
1837
- xl: "size-20 text-xl"
1838
- };
1839
- function AvatarBlock({ src, name = "", size = "md", testId }) {
1840
- return /* @__PURE__ */ jsxRuntime.jsxs(react.Avatar, { className: react.cn(SIZE[size] ?? SIZE.md), "data-testid": testId, children: [
1841
- src && /* @__PURE__ */ jsxRuntime.jsx(react.AvatarImage, { src, alt: name }),
1842
- /* @__PURE__ */ jsxRuntime.jsx(react.AvatarFallback, { className: "font-semibold", children: initials(name || "?") })
1843
- ] });
1844
- }
1845
- function Navbar({ brand, links, cta, testId }) {
1846
- return /* @__PURE__ */ jsxRuntime.jsx("header", { className: "border-b border-border bg-background", "data-testid": testId, children: /* @__PURE__ */ jsxRuntime.jsxs("nav", { className: "mx-auto flex max-w-7xl items-center justify-between gap-6 px-5 py-4 lg:px-8", children: [
1847
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-lg font-semibold tracking-tight", children: brand }),
1848
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden items-center gap-6 md:flex", children: (links ?? []).map((link, i) => /* @__PURE__ */ jsxRuntime.jsx(
1849
- "a",
1850
- {
1851
- href: link.href || "#",
1852
- className: "text-sm font-medium text-muted-foreground transition-colors hover:text-foreground",
1853
- "data-testid": testId && `${testId}-link-${i}`,
1854
- children: link.label
1855
- },
1856
- i
1857
- )) }),
1858
- cta?.label && /* @__PURE__ */ jsxRuntime.jsx(react.Button, { asChild: true, size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: cta.href || "#", children: cta.label }) })
1859
- ] }) });
1860
- }
1861
- function Footer({ columns, copyright, testId }) {
1862
- return /* @__PURE__ */ jsxRuntime.jsx("footer", { className: "border-t border-border bg-muted text-foreground", "data-testid": testId, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto max-w-7xl px-5 py-14 lg:px-8", children: [
1863
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid gap-8 sm:grid-cols-2 lg:grid-cols-4", children: (columns ?? []).map((col, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-testid": testId && `${testId}-col-${i}`, children: [
1864
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-sm font-semibold tracking-tight", children: col.heading }),
1865
- /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "mt-4 space-y-2", children: (col.links ?? []).map((link, j) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(
1866
- "a",
1867
- {
1868
- href: link.href || "#",
1869
- className: "text-sm text-muted-foreground transition-colors hover:text-foreground",
1870
- children: link.label
1871
- }
1872
- ) }, j)) })
1873
- ] }, i)) }),
1874
- copyright && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-12 border-t border-border pt-6 text-sm text-muted-foreground", children: copyright })
1875
- ] }) });
1876
- }
1877
- function ListBlock({ ordered = false, items, testId }) {
1878
- const list = items ?? [];
1879
- const className = react.cn(
1880
- "mx-auto max-w-3xl space-y-2 pl-5 text-foreground",
1881
- ordered ? "list-decimal" : "list-disc"
1882
- );
1883
- const content = list.map((item, i) => /* @__PURE__ */ jsxRuntime.jsx("li", { className: "leading-relaxed marker:text-muted-foreground", children: item.text }, i));
1884
- return ordered ? /* @__PURE__ */ jsxRuntime.jsx("ol", { className, "data-testid": testId, children: content }) : /* @__PURE__ */ jsxRuntime.jsx("ul", { className, "data-testid": testId, children: content });
1885
- }
1886
- var GRID2 = {
1887
- 2: "sm:grid-cols-2",
1888
- 3: "sm:grid-cols-2 lg:grid-cols-3",
1889
- 4: "sm:grid-cols-2 lg:grid-cols-4"
1890
- };
1891
- var GAP = {
1892
- sm: "gap-3",
1893
- md: "gap-6",
1894
- lg: "gap-10"
1895
- };
1896
- function Columns({ count = 3, gap = "md", columns, testId }) {
1897
- return /* @__PURE__ */ jsxRuntime.jsx(
1898
- "div",
1899
- {
1900
- className: react.cn("grid grid-cols-1", GRID2[count] ?? GRID2[3], GAP[gap] ?? GAP.md),
1901
- "data-testid": testId,
1902
- children: columns.map((col, i) => /* @__PURE__ */ jsxRuntime.jsx("div", { "data-testid": testId && `${testId}-col-${i}`, children: col }, i))
1903
- }
1904
- );
1905
- }
1906
- var SIZE2 = {
1907
- sm: "h-4",
1908
- md: "h-8",
1909
- lg: "h-16",
1910
- xl: "h-24"
1911
- };
1912
- function Spacer({ size = "md", testId }) {
1913
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: react.cn("w-full", SIZE2[size] ?? SIZE2.md), "data-testid": testId, "aria-hidden": true });
1914
- }
1915
- var WIDTH = {
1916
- narrow: "max-w-3xl",
1917
- default: "max-w-5xl",
1918
- wide: "max-w-7xl",
1919
- full: "max-w-none"
1920
- };
1921
- var PADDING = {
1922
- none: "px-0 py-0",
1923
- sm: "px-4 py-6",
1924
- md: "px-5 py-12 lg:px-8",
1925
- lg: "px-5 py-20 lg:px-8"
1926
- };
1927
- function Container({ width = "default", padding = "md", children, testId }) {
1928
- return /* @__PURE__ */ jsxRuntime.jsx(
1929
- "div",
1930
- {
1931
- className: react.cn(
1932
- "mx-auto w-full",
1933
- WIDTH[width] ?? WIDTH.default,
1934
- PADDING[padding] ?? PADDING.md
1935
- ),
1936
- "data-testid": testId,
1937
- children
1938
- }
1939
- );
1940
- }
1941
- function PricingTable({ plans, testId }) {
1942
- return /* @__PURE__ */ jsxRuntime.jsx(
1943
- "div",
1944
- {
1945
- className: react.cn("grid gap-6", (plans?.length ?? 0) >= 3 ? "md:grid-cols-3" : "sm:grid-cols-2"),
1946
- "data-testid": testId,
1947
- children: (plans ?? []).map((plan, i) => /* @__PURE__ */ jsxRuntime.jsxs(
1948
- react.Card,
1949
- {
1950
- variant: plan.featured ? "elevated" : "outline",
1951
- className: react.cn("flex h-full flex-col p-6", plan.featured && "ring-2 ring-primary"),
1952
- "data-testid": testId && `${testId}-item-${i}`,
1953
- children: [
1954
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold tracking-tight", children: plan.name }),
1955
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 flex items-baseline gap-1", children: [
1956
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-3xl font-semibold tracking-tight", children: plan.price }),
1957
- plan.period && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-muted-foreground", children: [
1958
- "/",
1959
- plan.period
1960
- ] })
1961
- ] }),
1962
- plan.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm leading-relaxed text-muted-foreground", children: plan.description }),
1963
- plan.features && plan.features.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "mt-5 flex-1 space-y-2", children: plan.features.map((f, j) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-start gap-2 text-sm", children: [
1964
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "mt-0.5 size-4 shrink-0 text-primary" }),
1965
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: f })
1966
- ] }, j)) }),
1967
- plan.cta?.label && /* @__PURE__ */ jsxRuntime.jsx(react.Button, { asChild: true, className: "mt-6 w-full", variant: plan.featured ? "default" : "outline", children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: plan.cta.href || "#", children: plan.cta.label }) })
1968
- ]
1969
- },
1970
- i
1971
- ))
1972
- }
1973
- );
1974
- }
1975
- function Tabs({ items, testId }) {
1976
- const [active, setActive] = react$1.useState(0);
1977
- const list = items ?? [];
1978
- const current = list[Math.min(active, Math.max(list.length - 1, 0))];
1979
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-testid": testId, children: [
1980
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-1 border-b border-border", role: "tablist", children: list.map((t, i) => {
1981
- const selected = i === active;
1982
- return /* @__PURE__ */ jsxRuntime.jsx(
1983
- "button",
1984
- {
1985
- type: "button",
1986
- role: "tab",
1987
- "aria-selected": selected,
1988
- onClick: () => setActive(i),
1989
- className: react.cn(
1990
- "-mb-px border-b-2 px-4 py-2 text-sm font-medium transition-colors",
1991
- selected ? "border-primary text-foreground" : "border-transparent text-muted-foreground hover:text-foreground"
1992
- ),
1993
- "data-testid": testId && `${testId}-tab-${i}`,
1994
- children: t.label
1995
- },
1996
- i
1997
- );
1998
- }) }),
1999
- current && /* @__PURE__ */ jsxRuntime.jsx(
2000
- "div",
2001
- {
2002
- role: "tabpanel",
2003
- className: "pt-5 text-sm leading-relaxed text-muted-foreground",
2004
- "data-testid": testId && `${testId}-panel`,
2005
- children: current.content
2006
- }
2007
- )
2008
- ] });
2009
- }
2010
- function Accordion({ items, allowMultiple = false, testId }) {
2011
- const [open, setOpen] = react$1.useState([]);
2012
- const toggle2 = (i) => setOpen(
2013
- (prev) => prev.includes(i) ? prev.filter((n) => n !== i) : allowMultiple ? [...prev, i] : [i]
2014
- );
2015
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y divide-border border-y border-border", "data-testid": testId, children: (items ?? []).map((item, i) => {
2016
- const isOpen = open.includes(i);
2017
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-testid": testId && `${testId}-item-${i}`, children: [
2018
- /* @__PURE__ */ jsxRuntime.jsxs(
2019
- "button",
2020
- {
2021
- type: "button",
2022
- "aria-expanded": isOpen,
2023
- onClick: () => toggle2(i),
2024
- className: "flex w-full items-center justify-between gap-4 py-4 text-left text-base font-medium",
2025
- "data-testid": testId && `${testId}-trigger-${i}`,
2026
- children: [
2027
- item.title,
2028
- /* @__PURE__ */ jsxRuntime.jsx(
2029
- lucideReact.ChevronDown,
2030
- {
2031
- className: react.cn("size-4 shrink-0 transition-transform", isOpen && "rotate-180")
2032
- }
2033
- )
2034
- ]
2035
- }
2036
- ),
2037
- isOpen && /* @__PURE__ */ jsxRuntime.jsx(
2038
- "p",
2039
- {
2040
- className: "pb-4 text-sm leading-relaxed text-muted-foreground",
2041
- "data-testid": testId && `${testId}-content-${i}`,
2042
- children: item.content
2043
- }
2044
- )
2045
- ] }, i);
2046
- }) });
2047
- }
2048
- var COLS2 = {
2049
- "2": "grid-cols-2",
2050
- "3": "grid-cols-2 sm:grid-cols-3",
2051
- "4": "grid-cols-2 sm:grid-cols-4"
2052
- };
2053
- function Gallery({
2054
- images,
2055
- columns = "3",
2056
- aspect = "1:1",
2057
- rounded = "lg",
2058
- testId
2059
- }) {
2060
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: react.cn("grid gap-4", COLS2[columns] ?? COLS2["3"]), "data-testid": testId, children: (images ?? []).map((img, i) => /* @__PURE__ */ jsxRuntime.jsxs("figure", { "data-testid": testId && `${testId}-item-${i}`, children: [
2061
- /* @__PURE__ */ jsxRuntime.jsx(
2062
- BlockImage,
2063
- {
2064
- src: img.src,
2065
- alt: img.alt,
2066
- aspect,
2067
- rounded,
2068
- testId: testId && `${testId}-item-${i}-image`
2069
- }
2070
- ),
2071
- img.caption && /* @__PURE__ */ jsxRuntime.jsx("figcaption", { className: "mt-1.5 text-xs text-muted-foreground", children: img.caption })
2072
- ] }, i)) });
2073
- }
2074
- var ASPECT2 = {
2075
- "16:9": "aspect-video",
2076
- "4:3": "aspect-[4/3]",
2077
- "1:1": "aspect-square"
2078
- };
2079
- function toEmbedUrl(url) {
2080
- if (!url) return null;
2081
- const yt = url.match(/(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([\w-]{11})/);
2082
- if (yt) return `https://www.youtube.com/embed/${yt[1]}`;
2083
- const vimeo = url.match(/vimeo\.com\/(?:video\/)?(\d+)/);
2084
- if (vimeo) return `https://player.vimeo.com/video/${vimeo[1]}`;
2085
- const loom = url.match(/loom\.com\/(?:share|embed)\/([\w-]+)/);
2086
- if (loom) return `https://www.loom.com/embed/${loom[1]}`;
2087
- return null;
2088
- }
2089
- function VideoEmbed({
2090
- url,
2091
- title,
2092
- aspect = "16:9",
2093
- rounded = true,
2094
- testId
2095
- }) {
2096
- const embed = toEmbedUrl(url);
2097
- const frame = react.cn(
2098
- "w-full overflow-hidden border border-border bg-muted",
2099
- ASPECT2[aspect] ?? ASPECT2["16:9"],
2100
- rounded && "rounded-lg"
2101
- );
2102
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: frame, "data-testid": testId, children: embed ? /* @__PURE__ */ jsxRuntime.jsx(
2103
- "iframe",
2104
- {
2105
- src: embed,
2106
- title: title || "Embedded video",
2107
- className: "size-full",
2108
- allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",
2109
- allowFullScreen: true,
2110
- "data-testid": testId && `${testId}-iframe`
2111
- }
2112
- ) : url ? /* @__PURE__ */ jsxRuntime.jsx("video", { src: url, controls: true, className: "size-full", "data-testid": testId && `${testId}-video` }) : null });
2113
- }
2114
- function ContactForm({
2115
- fields,
2116
- submitLabel = "Send",
2117
- action,
2118
- successMessage = "Thanks \u2014 we\u2019ll be in touch shortly.",
2119
- testId
2120
- }) {
2121
- const [sent, setSent] = react$1.useState(false);
2122
- const list = fields ?? [];
2123
- const onSubmit = (e) => {
2124
- if (!action) {
2125
- e.preventDefault();
2126
- setSent(true);
2127
- }
2128
- };
2129
- if (sent) {
2130
- return /* @__PURE__ */ jsxRuntime.jsx(
2131
- "p",
2132
- {
2133
- className: "rounded-lg border border-border bg-muted p-6 text-center text-sm text-foreground",
2134
- role: "status",
2135
- "data-testid": testId && `${testId}-success`,
2136
- children: successMessage
2137
- }
2138
- );
2139
- }
2140
- return /* @__PURE__ */ jsxRuntime.jsxs(
2141
- "form",
2142
- {
2143
- action,
2144
- method: action ? "post" : void 0,
2145
- onSubmit,
2146
- className: "mx-auto flex max-w-xl flex-col gap-4",
2147
- "data-testid": testId,
2148
- children: [
2149
- list.map((f, i) => {
2150
- const inputClass = "w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground outline-none focus:border-primary";
2151
- return /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col gap-1.5 text-left", children: [
2152
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium", children: f.label }),
2153
- f.type === "textarea" ? /* @__PURE__ */ jsxRuntime.jsx(
2154
- "textarea",
2155
- {
2156
- name: f.name,
2157
- required: f.required,
2158
- rows: 4,
2159
- className: inputClass,
2160
- "data-testid": testId && `${testId}-field-${f.name}`
2161
- }
2162
- ) : /* @__PURE__ */ jsxRuntime.jsx(
2163
- "input",
2164
- {
2165
- name: f.name,
2166
- type: f.type || "text",
2167
- required: f.required,
2168
- className: inputClass,
2169
- "data-testid": testId && `${testId}-field-${f.name}`
2170
- }
2171
- )
2172
- ] }, i);
2173
- }),
2174
- /* @__PURE__ */ jsxRuntime.jsx(
2175
- react.Button,
2176
- {
2177
- type: "submit",
2178
- className: react.cn("mt-1 self-start"),
2179
- "data-testid": testId && `${testId}-submit`,
2180
- children: submitLabel
2181
- }
2182
- )
2183
- ]
2184
- }
2185
- );
2186
- }
2187
- var TONE = {
2188
- primary: "bg-primary text-primary-foreground",
2189
- muted: "bg-muted text-foreground",
2190
- ink: "bg-foreground text-background"
2191
- };
2192
- function Banner({ text, cta, tone = "primary", testId }) {
2193
- return /* @__PURE__ */ jsxRuntime.jsxs(
2194
- "div",
2195
- {
2196
- className: react.cn("w-full px-5 py-2.5 text-center text-sm", TONE[tone] ?? TONE.primary),
2197
- "data-testid": testId,
2198
- children: [
2199
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: text }),
2200
- cta?.label && /* @__PURE__ */ jsxRuntime.jsxs(
2201
- "a",
2202
- {
2203
- href: cta.href || "#",
2204
- className: "ml-2 inline-flex items-center gap-1 font-semibold underline underline-offset-4",
2205
- "data-testid": testId && `${testId}-cta`,
2206
- children: [
2207
- cta.label,
2208
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRight, { className: "size-3.5" })
2209
- ]
2210
- }
2211
- )
2212
- ]
2213
- }
2214
- );
2215
- }
2216
- function MediaText({
2217
- eyebrow,
2218
- title,
2219
- body,
2220
- imageUrl,
2221
- mediaSide = "left",
2222
- cta,
2223
- testId
2224
- }) {
2225
- const media = /* @__PURE__ */ jsxRuntime.jsx(BlockImage, { src: imageUrl, aspect: "4:3", rounded: "lg", testId: testId && `${testId}-image` });
2226
- const copy = /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2227
- eyebrow && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-3 text-xs font-semibold uppercase tracking-wider text-muted-foreground", children: eyebrow }),
2228
- /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-3xl font-semibold tracking-tight text-balance", children: title }),
2229
- body && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-4 text-lg leading-relaxed text-muted-foreground", children: body }),
2230
- cta?.label && /* @__PURE__ */ jsxRuntime.jsx(react.Button, { asChild: true, className: "mt-6", children: /* @__PURE__ */ jsxRuntime.jsxs("a", { href: cta.href || "#", children: [
2231
- cta.label,
2232
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRight, { className: "size-4" })
2233
- ] }) })
2234
- ] });
2235
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid items-center gap-10 lg:grid-cols-2", "data-testid": testId, children: mediaSide === "right" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2236
- copy,
2237
- media
2238
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2239
- media,
2240
- copy
2241
- ] }) });
2242
- }
2243
- var COLS3 = {
2244
- "2": "sm:grid-cols-2",
2245
- "3": "sm:grid-cols-2 lg:grid-cols-3",
2246
- "4": "sm:grid-cols-2 lg:grid-cols-4"
2247
- };
2248
- function TeamGrid({ members, columns = "3", testId }) {
2249
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: react.cn("grid gap-6", COLS3[columns] ?? COLS3["3"]), "data-testid": testId, children: (members ?? []).map((m, i) => /* @__PURE__ */ jsxRuntime.jsxs(
2250
- react.Card,
2251
- {
2252
- variant: "outline",
2253
- className: "flex h-full flex-col items-center p-6 text-center",
2254
- "data-testid": testId && `${testId}-item-${i}`,
2255
- children: [
2256
- /* @__PURE__ */ jsxRuntime.jsxs(react.Avatar, { className: "size-20", children: [
2257
- m.avatarUrl && /* @__PURE__ */ jsxRuntime.jsx(react.AvatarImage, { src: m.avatarUrl, alt: m.name }),
2258
- /* @__PURE__ */ jsxRuntime.jsx(react.AvatarFallback, { children: initials(m.name || "?") })
2259
- ] }),
2260
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "mt-4 text-base font-semibold tracking-tight", children: m.name }),
2261
- m.role && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-primary", children: m.role }),
2262
- m.bio && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm leading-relaxed text-muted-foreground", children: m.bio })
2263
- ]
2264
- },
2265
- i
2266
- )) });
2267
- }
2268
- function Steps({ steps, variant = "numbered", testId }) {
2269
- const list = steps ?? [];
2270
- if (variant === "timeline") {
2271
- return /* @__PURE__ */ jsxRuntime.jsx("ol", { className: "relative ml-3 border-l border-border", "data-testid": testId, children: list.map((s, i) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "mb-8 ml-6 last:mb-0", "data-testid": testId && `${testId}-item-${i}`, children: [
2272
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute -left-3 flex size-6 items-center justify-center rounded-full bg-primary text-xs font-semibold text-primary-foreground", children: i + 1 }),
2273
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-base font-semibold tracking-tight", children: s.title }),
2274
- s.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm leading-relaxed text-muted-foreground", children: s.description })
2275
- ] }, i)) });
2276
- }
2277
- return /* @__PURE__ */ jsxRuntime.jsx(
2278
- "div",
2279
- {
2280
- className: react.cn("grid gap-6", list.length >= 4 ? "md:grid-cols-4" : "sm:grid-cols-3"),
2281
- "data-testid": testId,
2282
- children: list.map((s, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-testid": testId && `${testId}-item-${i}`, children: [
2283
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex size-9 items-center justify-center rounded-full bg-primary/10 text-sm font-semibold text-primary", children: i + 1 }),
2284
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "mt-4 text-base font-semibold tracking-tight", children: s.title }),
2285
- s.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm leading-relaxed text-muted-foreground", children: s.description })
2286
- ] }, i))
2287
- }
2288
- );
2289
- }
2290
- var COLS4 = {
2291
- "2": "sm:grid-cols-2",
2292
- "3": "sm:grid-cols-2 lg:grid-cols-3"
2293
- };
2294
- function TestimonialGrid({ items, columns = "3", testId }) {
2295
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: react.cn("grid gap-6", COLS4[columns] ?? COLS4["3"]), "data-testid": testId, children: (items ?? []).map((t, i) => /* @__PURE__ */ jsxRuntime.jsxs(
1060
+ var MAX_AVATARS = 4;
1061
+ function WorkspaceCard({
1062
+ name,
1063
+ matterRef,
1064
+ description,
1065
+ docCount,
1066
+ memberCount,
1067
+ members = [],
1068
+ updatedAt,
1069
+ active = false,
1070
+ busy = false,
1071
+ onOpen,
1072
+ icon: Icon = lucideReact.FolderLock,
1073
+ testId,
1074
+ buttonTestId,
1075
+ className
1076
+ }) {
1077
+ const totalMembers = memberCount ?? members.length;
1078
+ const shownMembers = members.slice(0, MAX_AVATARS);
1079
+ const extraMembers = totalMembers - shownMembers.length;
1080
+ const btnTestId = buttonTestId ?? (testId ? `${testId}-open` : void 0);
1081
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2296
1082
  react.Card,
2297
1083
  {
2298
1084
  variant: "outline",
2299
- className: "flex h-full flex-col p-6",
2300
- "data-testid": testId && `${testId}-item-${i}`,
1085
+ className: react.cn("card-hover flex flex-col p-5", className),
1086
+ "data-testid": testId,
2301
1087
  children: [
2302
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Quote, { className: "size-6 text-primary/40", "aria-hidden": true }),
2303
- /* @__PURE__ */ jsxRuntime.jsx("blockquote", { className: "mt-3 flex-1 text-base leading-relaxed", children: t.quote }),
2304
- (t.author || t.avatarUrl) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-5 flex items-center gap-3", children: [
2305
- /* @__PURE__ */ jsxRuntime.jsxs(react.Avatar, { className: "size-9", children: [
2306
- t.avatarUrl && /* @__PURE__ */ jsxRuntime.jsx(react.AvatarImage, { src: t.avatarUrl, alt: t.author ?? "" }),
2307
- /* @__PURE__ */ jsxRuntime.jsx(react.AvatarFallback, { children: initials(t.author || "?") })
1088
+ /* @__PURE__ */ jsxRuntime.jsxs(react.CardHeader, { className: "p-0", children: [
1089
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
1090
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex size-10 shrink-0 items-center justify-center rounded-md bg-primary/10 text-primary", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "size-5" }) }),
1091
+ active ? /* @__PURE__ */ jsxRuntime.jsxs(react.Badge, { children: [
1092
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle2, { className: "mr-1 size-3" }),
1093
+ " Active"
1094
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(react.Badge, { variant: "secondary", children: "Encrypted" })
1095
+ ] }),
1096
+ /* @__PURE__ */ jsxRuntime.jsx(react.CardTitle, { className: "mt-3 text-base", children: name }),
1097
+ matterRef && /* @__PURE__ */ jsxRuntime.jsx(react.CardDescription, { className: "text-xs font-medium uppercase tracking-wide text-muted-foreground", children: matterRef })
1098
+ ] }),
1099
+ /* @__PURE__ */ jsxRuntime.jsxs(react.CardContent, { className: "mt-3 flex-1 space-y-4 p-0", children: [
1100
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "line-clamp-2 text-sm text-muted-foreground", children: description }),
1101
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4 text-sm", children: [
1102
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1.5 text-foreground", children: [
1103
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileText, { className: "size-4 text-muted-foreground" }),
1104
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: docCount.toLocaleString() }),
1105
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "docs" })
1106
+ ] }),
1107
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1.5 text-foreground", children: [
1108
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Users, { className: "size-4 text-muted-foreground" }),
1109
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: totalMembers }),
1110
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "members" })
1111
+ ] })
2308
1112
  ] }),
2309
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2310
- t.author && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold", children: t.author }),
2311
- t.role && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: t.role })
1113
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-3", children: [
1114
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex -space-x-2", children: [
1115
+ shownMembers.map((m, i) => /* @__PURE__ */ jsxRuntime.jsxs(react.Avatar, { className: "size-7 border-2 border-card", title: m.name, children: [
1116
+ m.picture && /* @__PURE__ */ jsxRuntime.jsx(react.AvatarImage, { src: m.picture, alt: m.name }),
1117
+ /* @__PURE__ */ jsxRuntime.jsx(react.AvatarFallback, { className: "bg-foreground text-[10px] font-medium text-background", children: chunkAHWIZJ4M_cjs.initials(m.name || "?") })
1118
+ ] }, i)),
1119
+ extraMembers > 0 && /* @__PURE__ */ jsxRuntime.jsx(react.Avatar, { className: "size-7 border-2 border-card", children: /* @__PURE__ */ jsxRuntime.jsxs(react.AvatarFallback, { className: "bg-accent text-[10px] font-medium text-muted-foreground", children: [
1120
+ "+",
1121
+ extraMembers
1122
+ ] }) })
1123
+ ] }),
1124
+ updatedAt && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground", title: chunkAHWIZJ4M_cjs.fmtDate(updatedAt), children: [
1125
+ "Updated ",
1126
+ chunkAHWIZJ4M_cjs.fromNow(updatedAt)
1127
+ ] })
2312
1128
  ] })
2313
- ] })
1129
+ ] }),
1130
+ /* @__PURE__ */ jsxRuntime.jsx(react.CardFooter, { className: "mt-4 p-0", children: active ? /* @__PURE__ */ jsxRuntime.jsxs(react.Button, { variant: "outline", className: "w-full", disabled: true, "data-testid": btnTestId, children: [
1131
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle2, { className: "size-4" }),
1132
+ " Current workspace"
1133
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(react.Button, { className: "w-full", onClick: onOpen, disabled: busy, "data-testid": btnTestId, children: [
1134
+ busy ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "size-4 animate-spin" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeftRight, { className: "size-4" }),
1135
+ "Open"
1136
+ ] }) })
2314
1137
  ]
2315
- },
2316
- i
2317
- )) });
1138
+ }
1139
+ );
1140
+ }
1141
+ var GRID = {
1142
+ 1: "grid-cols-1",
1143
+ 2: "grid-cols-2",
1144
+ 3: "grid-cols-2 sm:grid-cols-3",
1145
+ 4: "grid-cols-2 lg:grid-cols-4"
1146
+ };
1147
+ function StatGroup({ items, testId }) {
1148
+ const list = items ?? [];
1149
+ const cols = GRID[Math.min(list.length, 4)] ?? GRID[4];
1150
+ return /* @__PURE__ */ jsxRuntime.jsx("dl", { className: react.cn("grid gap-8", cols), "data-testid": testId, children: list.map((item, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", "data-testid": testId && `${testId}-item-${i}`, children: [
1151
+ /* @__PURE__ */ jsxRuntime.jsx("dt", { className: "sr-only", children: item.label }),
1152
+ /* @__PURE__ */ jsxRuntime.jsx("dd", { className: "text-4xl font-semibold tracking-tight sm:text-5xl", children: item.value }),
1153
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: item.label }),
1154
+ item.sub && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-xs text-muted-foreground/80", children: item.sub })
1155
+ ] }, i)) });
2318
1156
  }
2319
1157
  function NavItemLink({ item, onNavigate }) {
2320
1158
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -2323,7 +1161,7 @@ function NavItemLink({ item, onNavigate }) {
2323
1161
  to: item.to,
2324
1162
  end: item.end,
2325
1163
  onClick: onNavigate,
2326
- "data-testid": tid("sidebar-nav", item.id),
1164
+ "data-testid": chunkAHWIZJ4M_cjs.tid("sidebar-nav", item.id),
2327
1165
  className: ({ isActive }) => react.cn(
2328
1166
  "group flex items-center gap-3 rounded-md px-3 py-2 text-sm font-medium transition-colors",
2329
1167
  isActive ? "bg-sidebar-accent text-sidebar-accent-foreground" : "text-sidebar-foreground hover:bg-sidebar-accent/60 hover:text-sidebar-accent-foreground"
@@ -2387,85 +1225,90 @@ function AppShell({
2387
1225
  onNavigate
2388
1226
  }
2389
1227
  );
2390
- return /* @__PURE__ */ jsxRuntime.jsxs(
2391
- "div",
2392
- {
2393
- className: "flex h-screen overflow-hidden bg-background",
2394
- "data-testid": `${testIdPrefix}-shell`,
2395
- children: [
2396
- /* @__PURE__ */ jsxRuntime.jsx(
2397
- "aside",
2398
- {
2399
- className: "hidden h-full w-64 shrink-0 flex-col border-r border-sidebar-border bg-sidebar lg:flex",
2400
- "data-testid": `${testIdPrefix}-sidebar`,
2401
- children: body()
2402
- }
2403
- ),
2404
- open && /* @__PURE__ */ jsxRuntime.jsxs(
2405
- "div",
2406
- {
2407
- className: "fixed inset-0 z-50 lg:hidden",
2408
- "data-testid": `${testIdPrefix}-sidebar-mobile`,
2409
- children: [
2410
- /* @__PURE__ */ jsxRuntime.jsx(
2411
- "div",
2412
- {
2413
- className: "absolute inset-0 bg-black/60 backdrop-blur-sm",
2414
- onClick: () => setOpen(false),
2415
- "aria-hidden": true
2416
- }
2417
- ),
2418
- /* @__PURE__ */ jsxRuntime.jsxs("aside", { className: "absolute inset-y-0 left-0 flex w-64 max-w-[82%] flex-col border-r border-sidebar-border bg-sidebar shadow-xl", children: [
2419
- /* @__PURE__ */ jsxRuntime.jsx(
2420
- "button",
2421
- {
2422
- type: "button",
2423
- onClick: () => setOpen(false),
2424
- className: "absolute right-3 top-4 z-10 flex size-8 items-center justify-center rounded-md text-sidebar-foreground/70 hover:bg-sidebar-accent/60 hover:text-sidebar-accent-foreground",
2425
- "aria-label": "Close menu",
2426
- "data-testid": `${testIdPrefix}-sidebar-close`,
2427
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "size-5" })
2428
- }
2429
- ),
2430
- body(() => setOpen(false))
2431
- ] })
2432
- ]
2433
- }
2434
- ),
2435
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [
2436
- /* @__PURE__ */ jsxRuntime.jsxs(
2437
- "header",
1228
+ return (
1229
+ // One TooltipProvider for the whole back office: every kit component that
1230
+ // renders a tooltip (entity pills, document tiles, toolbars) inherits the
1231
+ // same hover delay, and no app has to remember to mount it.
1232
+ /* @__PURE__ */ jsxRuntime.jsx(react.TooltipProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs(
1233
+ "div",
1234
+ {
1235
+ className: "flex h-screen overflow-hidden bg-background",
1236
+ "data-testid": `${testIdPrefix}-shell`,
1237
+ children: [
1238
+ /* @__PURE__ */ jsxRuntime.jsx(
1239
+ "aside",
2438
1240
  {
2439
- className: "flex h-16 shrink-0 items-center gap-4 border-b border-border bg-card/80 px-6 backdrop-blur",
2440
- "data-testid": `${testIdPrefix}-topbar`,
1241
+ className: "hidden h-full w-64 shrink-0 flex-col border-r border-sidebar-border bg-sidebar lg:flex",
1242
+ "data-testid": `${testIdPrefix}-sidebar`,
1243
+ children: body()
1244
+ }
1245
+ ),
1246
+ open && /* @__PURE__ */ jsxRuntime.jsxs(
1247
+ "div",
1248
+ {
1249
+ className: "fixed inset-0 z-50 lg:hidden",
1250
+ "data-testid": `${testIdPrefix}-sidebar-mobile`,
2441
1251
  children: [
2442
1252
  /* @__PURE__ */ jsxRuntime.jsx(
2443
- "button",
1253
+ "div",
2444
1254
  {
2445
- type: "button",
2446
- onClick: () => setOpen(true),
2447
- className: "flex size-9 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent hover:text-foreground lg:hidden",
2448
- "data-testid": `${testIdPrefix}-nav-toggle`,
2449
- "aria-label": "Open menu",
2450
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Menu, { className: "size-5" })
1255
+ className: "absolute inset-0 bg-black/60 backdrop-blur-sm",
1256
+ onClick: () => setOpen(false),
1257
+ "aria-hidden": true
2451
1258
  }
2452
1259
  ),
2453
- topbar
1260
+ /* @__PURE__ */ jsxRuntime.jsxs("aside", { className: "absolute inset-y-0 left-0 flex w-64 max-w-[82%] flex-col border-r border-sidebar-border bg-sidebar shadow-xl", children: [
1261
+ /* @__PURE__ */ jsxRuntime.jsx(
1262
+ "button",
1263
+ {
1264
+ type: "button",
1265
+ onClick: () => setOpen(false),
1266
+ className: "absolute right-3 top-4 z-10 flex size-8 items-center justify-center rounded-md text-sidebar-foreground/70 hover:bg-sidebar-accent/60 hover:text-sidebar-accent-foreground",
1267
+ "aria-label": "Close menu",
1268
+ "data-testid": `${testIdPrefix}-sidebar-close`,
1269
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "size-5" })
1270
+ }
1271
+ ),
1272
+ body(() => setOpen(false))
1273
+ ] })
2454
1274
  ]
2455
1275
  }
2456
1276
  ),
2457
- /* @__PURE__ */ jsxRuntime.jsx(
2458
- "main",
2459
- {
2460
- className: react.cn("flex-1 overflow-y-auto", mainClassName),
2461
- "data-testid": `${testIdPrefix}-main`,
2462
- children
2463
- }
2464
- )
2465
- ] }),
2466
- rightRail
2467
- ]
2468
- }
1277
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [
1278
+ /* @__PURE__ */ jsxRuntime.jsxs(
1279
+ "header",
1280
+ {
1281
+ className: "flex h-16 shrink-0 items-center gap-4 border-b border-border bg-card/80 px-6 backdrop-blur",
1282
+ "data-testid": `${testIdPrefix}-topbar`,
1283
+ children: [
1284
+ /* @__PURE__ */ jsxRuntime.jsx(
1285
+ "button",
1286
+ {
1287
+ type: "button",
1288
+ onClick: () => setOpen(true),
1289
+ className: "flex size-9 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent hover:text-foreground lg:hidden",
1290
+ "data-testid": `${testIdPrefix}-nav-toggle`,
1291
+ "aria-label": "Open menu",
1292
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Menu, { className: "size-5" })
1293
+ }
1294
+ ),
1295
+ topbar
1296
+ ]
1297
+ }
1298
+ ),
1299
+ /* @__PURE__ */ jsxRuntime.jsx(
1300
+ "main",
1301
+ {
1302
+ className: react.cn("flex-1 overflow-y-auto", mainClassName),
1303
+ "data-testid": `${testIdPrefix}-main`,
1304
+ children
1305
+ }
1306
+ )
1307
+ ] }),
1308
+ rightRail
1309
+ ]
1310
+ }
1311
+ ) })
2469
1312
  );
2470
1313
  }
2471
1314
  function AppHeader({
@@ -2491,7 +1334,7 @@ function AppHeader({
2491
1334
  type: "button",
2492
1335
  onClick: onSearch,
2493
1336
  className: classNames?.search ?? "relative hidden max-w-md flex-1 items-center rounded-md border border-input bg-background py-2 pl-9 pr-3 text-left text-sm text-muted-foreground transition-colors hover:bg-accent md:flex",
2494
- "data-testid": tid(testIdPrefix, "global-search"),
1337
+ "data-testid": chunkAHWIZJ4M_cjs.tid(testIdPrefix, "global-search"),
2495
1338
  children: [
2496
1339
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" }),
2497
1340
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: searchPlaceholder }),
@@ -2507,7 +1350,7 @@ function AppHeader({
2507
1350
  size: "sm",
2508
1351
  onClick: onAsk ?? onSearch,
2509
1352
  className: classNames?.askButton,
2510
- "data-testid": tid(testIdPrefix, "ask-ai"),
1353
+ "data-testid": chunkAHWIZJ4M_cjs.tid(testIdPrefix, "ask-ai"),
2511
1354
  children: [
2512
1355
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "size-4" }),
2513
1356
  askLabel
@@ -2518,7 +1361,7 @@ function AppHeader({
2518
1361
  /* @__PURE__ */ jsxRuntime.jsx(
2519
1362
  react.NotificationBell,
2520
1363
  {
2521
- testId: tid(testIdPrefix, "notifications"),
1364
+ testId: chunkAHWIZJ4M_cjs.tid(testIdPrefix, "notifications"),
2522
1365
  onNavigate: onNotificationNavigate,
2523
1366
  toneClassNames: notificationTones
2524
1367
  }
@@ -2529,8 +1372,8 @@ function AppHeader({
2529
1372
  user,
2530
1373
  items: userItems,
2531
1374
  onLogout,
2532
- testId: tid(testIdPrefix, "user-menu"),
2533
- logoutTestId: tid(testIdPrefix, "logout")
1375
+ testId: chunkAHWIZJ4M_cjs.tid(testIdPrefix, "user-menu"),
1376
+ logoutTestId: chunkAHWIZJ4M_cjs.tid(testIdPrefix, "logout")
2534
1377
  }
2535
1378
  )
2536
1379
  ] })
@@ -2700,6 +1543,32 @@ function createLiveWidgets(kit) {
2700
1543
  LiveMetric: LiveMetricWidget
2701
1544
  };
2702
1545
  }
1546
+ function useAssetImage(docId) {
1547
+ const arbi = react.useArbi();
1548
+ const { data: thumbs } = react.useThumbnails([docId]);
1549
+ const thumb = thumbs?.[docId];
1550
+ const { data: objectUrl } = reactQuery.useQuery({
1551
+ queryKey: ["arbi", "asset-image", docId],
1552
+ queryFn: async () => {
1553
+ const res = await arbi.documents.download(docId);
1554
+ const blob = await res.blob();
1555
+ return URL.createObjectURL(blob);
1556
+ },
1557
+ // Only download when the thumbnail is genuinely absent (not merely loading).
1558
+ enabled: !!docId && thumbs != null && !thumb && arbi.hasWorkspace,
1559
+ staleTime: 10 * 6e4
1560
+ });
1561
+ react$1.useEffect(() => {
1562
+ return () => {
1563
+ if (objectUrl) URL.revokeObjectURL(objectUrl);
1564
+ };
1565
+ }, [objectUrl]);
1566
+ return thumb ?? objectUrl;
1567
+ }
1568
+ function AssetThumb({ docId, alt, className, testId }) {
1569
+ const src = useAssetImage(docId);
1570
+ return /* @__PURE__ */ jsxRuntime.jsx("img", { src: src ?? void 0, alt: alt ?? "", className, "data-testid": testId });
1571
+ }
2703
1572
 
2704
1573
  // src/studio/publish.ts
2705
1574
  function blobToDataUrl(blob) {
@@ -2724,7 +1593,7 @@ function createArbiMaterializer(arbi, opts = {}) {
2724
1593
  }
2725
1594
  function collectAssetRefs(node, acc) {
2726
1595
  if (typeof node === "string") {
2727
- if (isAssetRef(node)) acc.add(node);
1596
+ if (chunkAHWIZJ4M_cjs.isAssetRef(node)) acc.add(node);
2728
1597
  return;
2729
1598
  }
2730
1599
  if (Array.isArray(node)) {
@@ -2758,7 +1627,7 @@ async function materializePageData(data, materialize) {
2758
1627
  const replacements = /* @__PURE__ */ new Map();
2759
1628
  await Promise.all(
2760
1629
  [...refs].map(async (ref) => {
2761
- const src = await materialize(assetRefId(ref));
1630
+ const src = await materialize(chunkAHWIZJ4M_cjs.assetRefId(ref));
2762
1631
  if (src) replacements.set(ref, src);
2763
1632
  })
2764
1633
  );
@@ -2818,7 +1687,7 @@ function StudioEditor({
2818
1687
  delete w.__studioResetSlug;
2819
1688
  };
2820
1689
  }, [resetSeam, arbi, live, persistence]);
2821
- const persist4 = react$1.useCallback(
1690
+ const persist3 = react$1.useCallback(
2822
1691
  async (toSave) => {
2823
1692
  setSaving(true);
2824
1693
  try {
@@ -2843,7 +1712,7 @@ function StudioEditor({
2843
1712
  radius: stored.radius ?? defaultTheme.radius,
2844
1713
  activePresetId: null
2845
1714
  });
2846
- applyStoredTheme(themeBundle);
1715
+ chunkAHWIZJ4M_cjs.applyStoredTheme(themeBundle);
2847
1716
  })();
2848
1717
  return () => {
2849
1718
  cancelled = true;
@@ -2911,7 +1780,7 @@ function StudioEditor({
2911
1780
  "button",
2912
1781
  {
2913
1782
  type: "button",
2914
- onClick: () => void persist4(latest.current),
1783
+ onClick: () => void persist3(latest.current),
2915
1784
  disabled: saving || loading,
2916
1785
  className: "inline-flex items-center gap-1.5 rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-60",
2917
1786
  "data-testid": `${testIdPrefix}-publish`,
@@ -2936,7 +1805,7 @@ function StudioEditor({
2936
1805
  "\u201D\u2026"
2937
1806
  ]
2938
1807
  }
2939
- ) : /* @__PURE__ */ jsxRuntime.jsx(AssetResolverProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(
1808
+ ) : /* @__PURE__ */ jsxRuntime.jsx(chunkAHWIZJ4M_cjs.AssetResolverProvider, { render: AssetThumb, children: /* @__PURE__ */ jsxRuntime.jsx(
2940
1809
  puck.Puck,
2941
1810
  {
2942
1811
  config,
@@ -2944,7 +1813,7 @@ function StudioEditor({
2944
1813
  onChange: (d) => {
2945
1814
  latest.current = d;
2946
1815
  },
2947
- onPublish: (d) => void persist4(d)
1816
+ onPublish: (d) => void persist3(d)
2948
1817
  },
2949
1818
  `${slug}-${rev}`
2950
1819
  ) }) }),
@@ -2954,7 +1823,7 @@ function StudioEditor({
2954
1823
  className: "w-80 shrink-0 border-l border-border",
2955
1824
  "data-testid": `${testIdPrefix}-theme-drawer`,
2956
1825
  children: /* @__PURE__ */ jsxRuntime.jsx(
2957
- ThemeEditor,
1826
+ chunkAHWIZJ4M_cjs.ThemeEditor,
2958
1827
  {
2959
1828
  bundle: themeBundle,
2960
1829
  variant: "drawer",
@@ -2993,7 +1862,7 @@ function PageRenderer({
2993
1862
  const page = initialData ?? (await persistence.loadPublished(arbi, live, slug)).data ?? (await persistence.loadPage(arbi, live, slug)).data;
2994
1863
  if (cancelled) return;
2995
1864
  if (applyTheme) {
2996
- applyThemeVars(
1865
+ chunkAHWIZJ4M_cjs.applyThemeVars(
2997
1866
  theme ? { ...defaultTheme, ...theme, colors: { ...defaultTheme.colors, ...theme.colors } } : defaultTheme
2998
1867
  );
2999
1868
  }
@@ -3195,7 +2064,7 @@ function AiTextField({
3195
2064
  setActive(true);
3196
2065
  await task.run(buildPrompt({ kind, label, current: value ?? "" }), docIds);
3197
2066
  };
3198
- const inputTid = tid(`${testIdPrefix}-field`, name);
2067
+ const inputTid = chunkAHWIZJ4M_cjs.tid(`${testIdPrefix}-field`, name);
3199
2068
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "al-ai-field", children: [
3200
2069
  multiline ? /* @__PURE__ */ jsxRuntime.jsx(
3201
2070
  "textarea",
@@ -3224,7 +2093,7 @@ function AiTextField({
3224
2093
  className: "al-ai-field__btn",
3225
2094
  onClick: () => void write(),
3226
2095
  disabled: task.isRunning,
3227
- "data-testid": tid(`${testIdPrefix}-ai-write`, name),
2096
+ "data-testid": chunkAHWIZJ4M_cjs.tid(`${testIdPrefix}-ai-write`, name),
3228
2097
  title: "Draft this field with AI, grounded in the marketing workspace",
3229
2098
  children: [
3230
2099
  task.isRunning ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "size-3 animate-spin" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "size-3" }),
@@ -3287,10 +2156,10 @@ function useImageGen() {
3287
2156
  const task = useFirmAiTask();
3288
2157
  const { run } = task;
3289
2158
  const generate = react$1.useCallback(
3290
- async (prompt) => {
2159
+ async (prompt, referenceDocIds = []) => {
3291
2160
  const trimmed = prompt.trim();
3292
2161
  if (!trimmed) return null;
3293
- const result = await run(`/image ${trimmed}`, []);
2162
+ const result = await run(`/image ${trimmed}`, referenceDocIds);
3294
2163
  return latestImageDocId(result?.artifacts ?? []);
3295
2164
  },
3296
2165
  [run]
@@ -3321,13 +2190,14 @@ function ImageFieldControl({
3321
2190
  const [url, setUrl] = react$1.useState("");
3322
2191
  const [prompt, setPrompt] = react$1.useState("");
3323
2192
  const [busy, setBusy] = react$1.useState(false);
2193
+ const [refIds, setRefIds] = react$1.useState([]);
3324
2194
  const [cropSrc, setCropSrc] = react$1.useState(null);
3325
2195
  const [cropName, setCropName] = react$1.useState("image.jpg");
3326
2196
  const arbi = react.useArbi();
3327
2197
  const gen = useImageGen();
3328
2198
  const queryClient = reactQuery.useQueryClient();
3329
- const currentAssetImage = useAssetImage(isAssetRef(value) ? assetRefId(value) : "");
3330
- const tp = (...q) => tid(`${testIdPrefix}-image`, name, ...q);
2199
+ const currentAssetImage = useAssetImage(chunkAHWIZJ4M_cjs.isAssetRef(value) ? chunkAHWIZJ4M_cjs.assetRefId(value) : "");
2200
+ const tp = (...q) => chunkAHWIZJ4M_cjs.tid(`${testIdPrefix}-image`, name, ...q);
3331
2201
  const refreshAssets = () => queryClient.invalidateQueries({ queryKey: ["arbi", "documents", workspaceId] });
3332
2202
  const { data: docs } = react.useDocuments(workspaceId);
3333
2203
  const imageDocs = react$1.useMemo(
@@ -3361,7 +2231,7 @@ function ImageFieldControl({
3361
2231
  const res = await arbi.documents.uploadFile(file, name2, { folder });
3362
2232
  const id = res.doc_ext_ids?.[0];
3363
2233
  if (id) {
3364
- onChange(asAssetRef(id));
2234
+ onChange(chunkAHWIZJ4M_cjs.asAssetRef(id));
3365
2235
  void refreshAssets();
3366
2236
  }
3367
2237
  } finally {
@@ -3374,11 +2244,13 @@ function ImageFieldControl({
3374
2244
  await uploadBlobAsAsset(result.blob, cropName);
3375
2245
  if (src?.startsWith("blob:")) URL.revokeObjectURL(src);
3376
2246
  };
2247
+ const toggleRef = (id) => setRefIds((prev) => prev.includes(id) ? prev.filter((x) => x !== id) : [...prev, id]);
3377
2248
  const onGenerate = async () => {
3378
2249
  if (!prompt.trim() || gen.isGenerating) return;
3379
- const id = await gen.generate(prompt);
2250
+ const id = await gen.generate(prompt, refIds);
3380
2251
  if (id) {
3381
- onChange(asAssetRef(id));
2252
+ onChange(chunkAHWIZJ4M_cjs.asAssetRef(id));
2253
+ setRefIds([]);
3382
2254
  void refreshAssets();
3383
2255
  }
3384
2256
  };
@@ -3392,7 +2264,7 @@ function ImageFieldControl({
3392
2264
  const tabClass = (on) => `inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs font-medium ${on ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:text-foreground"}`;
3393
2265
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", "data-testid": tp(), children: [
3394
2266
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
3395
- /* @__PURE__ */ jsxRuntime.jsx(BlockImage, { src: value, aspect: "16:9", rounded: "md", testId: tp("preview") }),
2267
+ /* @__PURE__ */ jsxRuntime.jsx(chunkAHWIZJ4M_cjs.BlockImage, { src: value, aspect: "16:9", rounded: "md", testId: tp("preview") }),
3396
2268
  currentAssetImage ? /* @__PURE__ */ jsxRuntime.jsxs(
3397
2269
  "button",
3398
2270
  {
@@ -3426,12 +2298,12 @@ function ImageFieldControl({
3426
2298
  imageDocs.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "col-span-3 py-3 text-center text-xs text-muted-foreground", children: "No image assets yet \u2014 upload or generate one." }),
3427
2299
  imageDocs.map((d) => {
3428
2300
  const thumb = thumbs?.[d.external_id];
3429
- const selected = value === asAssetRef(d.external_id);
2301
+ const selected = value === chunkAHWIZJ4M_cjs.asAssetRef(d.external_id);
3430
2302
  return /* @__PURE__ */ jsxRuntime.jsx(
3431
2303
  "button",
3432
2304
  {
3433
2305
  type: "button",
3434
- onClick: () => onChange(asAssetRef(d.external_id)),
2306
+ onClick: () => onChange(chunkAHWIZJ4M_cjs.asAssetRef(d.external_id)),
3435
2307
  className: `overflow-hidden rounded border ${selected ? "border-primary ring-1 ring-primary" : "border-border"}`,
3436
2308
  title: d.file_name ?? "",
3437
2309
  "data-testid": tp("asset", d.external_id),
@@ -3487,12 +2359,57 @@ function ImageFieldControl({
3487
2359
  )
3488
2360
  ] }),
3489
2361
  mode === "generate" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5", children: [
2362
+ imageDocs.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", "data-testid": tp("refs"), children: [
2363
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
2364
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground", children: [
2365
+ "Reference images",
2366
+ refIds.length > 0 ? ` (${refIds.length})` : " (optional)"
2367
+ ] }),
2368
+ chunkAHWIZJ4M_cjs.isAssetRef(value) && /* @__PURE__ */ jsxRuntime.jsx(
2369
+ "button",
2370
+ {
2371
+ type: "button",
2372
+ className: "text-xs font-medium text-primary hover:underline",
2373
+ onClick: () => toggleRef(chunkAHWIZJ4M_cjs.assetRefId(value)),
2374
+ "data-testid": tp("vary-current"),
2375
+ children: refIds.includes(chunkAHWIZJ4M_cjs.assetRefId(value)) ? "Varying current" : "Vary current image"
2376
+ }
2377
+ )
2378
+ ] }),
2379
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid max-h-28 grid-cols-4 gap-1.5 overflow-auto", children: imageDocs.map((d) => {
2380
+ const thumb = thumbs?.[d.external_id];
2381
+ const on = refIds.includes(d.external_id);
2382
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2383
+ "button",
2384
+ {
2385
+ type: "button",
2386
+ onClick: () => toggleRef(d.external_id),
2387
+ "aria-pressed": on,
2388
+ className: `relative overflow-hidden rounded border ${on ? "border-primary ring-1 ring-primary" : "border-border"}`,
2389
+ title: d.file_name ?? "",
2390
+ "data-testid": tp("ref", d.external_id),
2391
+ children: [
2392
+ thumb ? /* @__PURE__ */ jsxRuntime.jsx(
2393
+ "img",
2394
+ {
2395
+ src: thumb,
2396
+ alt: d.file_name ?? "",
2397
+ className: "aspect-square w-full bg-muted object-contain"
2398
+ }
2399
+ ) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex aspect-square w-full items-center justify-center bg-muted text-muted-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ImagePlus, { className: "size-3.5" }) }),
2400
+ on && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute right-0.5 top-0.5 rounded-full bg-primary p-0.5 text-primary-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "size-2.5" }) })
2401
+ ]
2402
+ },
2403
+ d.external_id
2404
+ );
2405
+ }) })
2406
+ ] }),
3490
2407
  /* @__PURE__ */ jsxRuntime.jsx(
3491
2408
  "textarea",
3492
2409
  {
3493
2410
  className: inputClass,
3494
2411
  rows: 2,
3495
- placeholder: "Describe the image\u2026",
2412
+ placeholder: refIds.length > 0 ? "Describe the edit to apply\u2026" : "Describe the image\u2026",
3496
2413
  value: prompt,
3497
2414
  onChange: (e) => setPrompt(e.target.value),
3498
2415
  "data-testid": tp("prompt")
@@ -3508,7 +2425,7 @@ function ImageFieldControl({
3508
2425
  "data-testid": tp("generate"),
3509
2426
  children: [
3510
2427
  gen.isGenerating ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "size-3.5 animate-spin" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "size-3.5" }),
3511
- gen.isGenerating ? "Generating\u2026" : "Generate"
2428
+ gen.isGenerating ? "Generating\u2026" : refIds.length > 0 ? `Generate from ${refIds.length} reference${refIds.length > 1 ? "s" : ""}` : "Generate"
3512
2429
  ]
3513
2430
  }
3514
2431
  ),
@@ -3565,13 +2482,13 @@ var TEXTURE_STYLE = {
3565
2482
  backgroundSize: "4px 4px",
3566
2483
  opacity: 0.04
3567
2484
  };
3568
- var PADDING2 = {
2485
+ var PADDING = {
3569
2486
  none: "",
3570
2487
  sm: "py-8 lg:py-10",
3571
2488
  md: "py-16 lg:py-20",
3572
2489
  lg: "py-24 lg:py-28"
3573
2490
  };
3574
- var WIDTH2 = {
2491
+ var WIDTH = {
3575
2492
  narrow: "max-w-3xl",
3576
2493
  default: "max-w-7xl",
3577
2494
  wide: "max-w-[90rem]",
@@ -3603,8 +2520,8 @@ function Section({
3603
2520
  {
3604
2521
  className: react.cn(
3605
2522
  "relative mx-auto px-5 lg:px-8",
3606
- WIDTH2[maxWidth],
3607
- PADDING2[padding],
2523
+ WIDTH[maxWidth],
2524
+ PADDING[padding],
3608
2525
  className
3609
2526
  ),
3610
2527
  children
@@ -3669,7 +2586,7 @@ function createBlockKit(ai, image, eyebrowClassName) {
3669
2586
  }),
3670
2587
  iconField: (label = "Icon") => ({ type: "select", label, options: ICON_OPTIONS }),
3671
2588
  resolveIcon: (name) => name ? iconMap[name] : void 0,
3672
- blockTestId: (id) => tid("arbi-block", id)
2589
+ blockTestId: (id) => chunkAHWIZJ4M_cjs.tid("arbi-block", id)
3673
2590
  };
3674
2591
  }
3675
2592
  var emptySlot = [];
@@ -3734,7 +2651,7 @@ function createWebsiteBlocks(kit) {
3734
2651
  render: ({ id, count, gap, col1, col2, col3, col4 }) => {
3735
2652
  const n = Number(count) || 3;
3736
2653
  const columns = [col1, col2, col3, col4].slice(0, n).map(renderSlot);
3737
- return /* @__PURE__ */ jsxRuntime.jsx(Columns, { count: n, gap, columns, testId: blockTestId(id) });
2654
+ return /* @__PURE__ */ jsxRuntime.jsx(chunkAHWIZJ4M_cjs.Columns, { count: n, gap, columns, testId: blockTestId(id) });
3738
2655
  }
3739
2656
  };
3740
2657
  const SpacerBlock = {
@@ -3752,7 +2669,7 @@ function createWebsiteBlocks(kit) {
3752
2669
  }
3753
2670
  },
3754
2671
  defaultProps: { size: "md" },
3755
- render: ({ id, size }) => /* @__PURE__ */ jsxRuntime.jsx(Spacer, { size, testId: blockTestId(id) })
2672
+ render: ({ id, size }) => /* @__PURE__ */ jsxRuntime.jsx(chunkAHWIZJ4M_cjs.Spacer, { size, testId: blockTestId(id) })
3756
2673
  };
3757
2674
  const ContainerBlock = {
3758
2675
  label: "Container",
@@ -3780,7 +2697,7 @@ function createWebsiteBlocks(kit) {
3780
2697
  children: { type: "slot" }
3781
2698
  },
3782
2699
  defaultProps: { width: "default", padding: "md", children: emptySlot },
3783
- render: ({ id, width, padding, children }) => /* @__PURE__ */ jsxRuntime.jsx(Container, { width, padding, testId: blockTestId(id), children: renderSlot(children) })
2700
+ render: ({ id, width, padding, children }) => /* @__PURE__ */ jsxRuntime.jsx(chunkAHWIZJ4M_cjs.Container, { width, padding, testId: blockTestId(id), children: renderSlot(children) })
3784
2701
  };
3785
2702
  const HeroBlock = {
3786
2703
  label: "Hero",
@@ -3831,7 +2748,7 @@ function createWebsiteBlocks(kit) {
3831
2748
  backgroundImage,
3832
2749
  overlay
3833
2750
  }) => /* @__PURE__ */ jsxRuntime.jsx(
3834
- Hero,
2751
+ chunkAHWIZJ4M_cjs.Hero,
3835
2752
  {
3836
2753
  eyebrow,
3837
2754
  title,
@@ -3903,7 +2820,7 @@ function createWebsiteBlocks(kit) {
3903
2820
  icon: resolveIcon(it.icon)
3904
2821
  })
3905
2822
  );
3906
- return /* @__PURE__ */ jsxRuntime.jsx(FeatureGrid, { columns, items: list, testId: blockTestId(id) });
2823
+ return /* @__PURE__ */ jsxRuntime.jsx(chunkAHWIZJ4M_cjs.FeatureGrid, { columns, items: list, testId: blockTestId(id) });
3907
2824
  }
3908
2825
  };
3909
2826
  const StatGroupBlock = {
@@ -3945,7 +2862,7 @@ function createWebsiteBlocks(kit) {
3945
2862
  avatarUrl: ""
3946
2863
  },
3947
2864
  render: ({ id, quote, author, role, avatarUrl }) => /* @__PURE__ */ jsxRuntime.jsx(
3948
- Testimonial,
2865
+ chunkAHWIZJ4M_cjs.Testimonial,
3949
2866
  {
3950
2867
  quote,
3951
2868
  author,
@@ -3974,7 +2891,7 @@ function createWebsiteBlocks(kit) {
3974
2891
  overlay: true
3975
2892
  },
3976
2893
  render: ({ id, title, subtitle, cta, tone, backgroundImage, overlay }) => /* @__PURE__ */ jsxRuntime.jsx(
3977
- CTABanner,
2894
+ chunkAHWIZJ4M_cjs.CTABanner,
3978
2895
  {
3979
2896
  title,
3980
2897
  subtitle,
@@ -4006,7 +2923,7 @@ function createWebsiteBlocks(kit) {
4006
2923
  { label: "Umbrella" }
4007
2924
  ]
4008
2925
  },
4009
- render: ({ id, items }) => /* @__PURE__ */ jsxRuntime.jsx(LogoCloud, { items, testId: blockTestId(id) })
2926
+ render: ({ id, items }) => /* @__PURE__ */ jsxRuntime.jsx(chunkAHWIZJ4M_cjs.LogoCloud, { items, testId: blockTestId(id) })
4010
2927
  };
4011
2928
  const FAQBlock = {
4012
2929
  label: "FAQ",
@@ -4038,7 +2955,7 @@ function createWebsiteBlocks(kit) {
4038
2955
  }
4039
2956
  ]
4040
2957
  },
4041
- render: ({ id, items }) => /* @__PURE__ */ jsxRuntime.jsx(FAQ, { items, testId: blockTestId(id) })
2958
+ render: ({ id, items }) => /* @__PURE__ */ jsxRuntime.jsx(chunkAHWIZJ4M_cjs.FAQ, { items, testId: blockTestId(id) })
4042
2959
  };
4043
2960
  const RichTextBlockConfig = {
4044
2961
  label: "Rich text",
@@ -4048,7 +2965,7 @@ function createWebsiteBlocks(kit) {
4048
2965
  defaultProps: {
4049
2966
  content: "## About us\n\nWe build tools that help teams do their best work. Our platform combines **power** and _simplicity_ so you can focus on what matters.\n\n- Fast to learn\n- Easy to scale\n- Loved by teams"
4050
2967
  },
4051
- render: ({ id, content }) => /* @__PURE__ */ jsxRuntime.jsx(RichTextBlock, { content, testId: blockTestId(id) })
2968
+ render: ({ id, content }) => /* @__PURE__ */ jsxRuntime.jsx(chunkAHWIZJ4M_cjs.RichTextBlock, { content, testId: blockTestId(id) })
4052
2969
  };
4053
2970
  const CalloutBlock = {
4054
2971
  label: "Callout",
@@ -4071,7 +2988,7 @@ function createWebsiteBlocks(kit) {
4071
2988
  title: "Good to know",
4072
2989
  body: "This is a helpful note that draws attention to important information."
4073
2990
  },
4074
- render: ({ id, variant, title, body }) => /* @__PURE__ */ jsxRuntime.jsx(Callout, { variant, title, body, testId: blockTestId(id) })
2991
+ render: ({ id, variant, title, body }) => /* @__PURE__ */ jsxRuntime.jsx(chunkAHWIZJ4M_cjs.Callout, { variant, title, body, testId: blockTestId(id) })
4075
2992
  };
4076
2993
  const ImageBlock = {
4077
2994
  label: "Image",
@@ -4102,7 +3019,7 @@ function createWebsiteBlocks(kit) {
4102
3019
  },
4103
3020
  defaultProps: { src: "", alt: "Image", aspect: "16:9", rounded: "lg", framed: false },
4104
3021
  render: ({ id, src, alt, aspect, rounded, framed }) => /* @__PURE__ */ jsxRuntime.jsx(
4105
- BlockImage,
3022
+ chunkAHWIZJ4M_cjs.BlockImage,
4106
3023
  {
4107
3024
  src,
4108
3025
  alt,
@@ -4130,7 +3047,7 @@ function createWebsiteBlocks(kit) {
4130
3047
  }
4131
3048
  },
4132
3049
  defaultProps: { src: "", name: "Jane Doe", size: "md" },
4133
- render: ({ id, src, name, size }) => /* @__PURE__ */ jsxRuntime.jsx(AvatarBlock, { src, name, size, testId: blockTestId(id) })
3050
+ render: ({ id, src, name, size }) => /* @__PURE__ */ jsxRuntime.jsx(chunkAHWIZJ4M_cjs.AvatarBlock, { src, name, size, testId: blockTestId(id) })
4134
3051
  };
4135
3052
  const NavbarBlock = {
4136
3053
  label: "Navbar",
@@ -4158,7 +3075,7 @@ function createWebsiteBlocks(kit) {
4158
3075
  ],
4159
3076
  cta: { label: "Sign up", href: "#" }
4160
3077
  },
4161
- render: ({ id, brand, links, cta }) => /* @__PURE__ */ jsxRuntime.jsx(Navbar, { brand, links, cta, testId: blockTestId(id) })
3078
+ render: ({ id, brand, links, cta }) => /* @__PURE__ */ jsxRuntime.jsx(chunkAHWIZJ4M_cjs.Navbar, { brand, links, cta, testId: blockTestId(id) })
4162
3079
  };
4163
3080
  const FooterBlock = {
4164
3081
  label: "Footer",
@@ -4217,7 +3134,7 @@ function createWebsiteBlocks(kit) {
4217
3134
  ],
4218
3135
  copyright: "\xA9 2026 Acme, Inc. All rights reserved."
4219
3136
  },
4220
- render: ({ id, columns, copyright }) => /* @__PURE__ */ jsxRuntime.jsx(Footer, { columns, copyright, testId: blockTestId(id) })
3137
+ render: ({ id, columns, copyright }) => /* @__PURE__ */ jsxRuntime.jsx(chunkAHWIZJ4M_cjs.Footer, { columns, copyright, testId: blockTestId(id) })
4221
3138
  };
4222
3139
  const ListBlockConfig = {
4223
3140
  label: "List",
@@ -4235,7 +3152,7 @@ function createWebsiteBlocks(kit) {
4235
3152
  ordered: false,
4236
3153
  items: [{ text: "First item" }, { text: "Second item" }, { text: "Third item" }]
4237
3154
  },
4238
- render: ({ id, ordered, items }) => /* @__PURE__ */ jsxRuntime.jsx(ListBlock, { ordered, items, testId: blockTestId(id) })
3155
+ render: ({ id, ordered, items }) => /* @__PURE__ */ jsxRuntime.jsx(chunkAHWIZJ4M_cjs.ListBlock, { ordered, items, testId: blockTestId(id) })
4239
3156
  };
4240
3157
  return {
4241
3158
  Columns: ColumnsBlock,
@@ -4337,7 +3254,7 @@ function createSiteBlocks(kit) {
4337
3254
  ]
4338
3255
  },
4339
3256
  render: ({ id, plans }) => /* @__PURE__ */ jsxRuntime.jsx(
4340
- PricingTable,
3257
+ chunkAHWIZJ4M_cjs.PricingTable,
4341
3258
  {
4342
3259
  plans: (plans ?? []).map(
4343
3260
  (p) => ({
@@ -4375,7 +3292,7 @@ function createSiteBlocks(kit) {
4375
3292
  { label: "FAQ", content: "Answers to common questions." }
4376
3293
  ]
4377
3294
  },
4378
- render: ({ id, items }) => /* @__PURE__ */ jsxRuntime.jsx(Tabs, { items, testId: blockTestId(id) })
3295
+ render: ({ id, items }) => /* @__PURE__ */ jsxRuntime.jsx(chunkAHWIZJ4M_cjs.Tabs, { items, testId: blockTestId(id) })
4379
3296
  };
4380
3297
  const AccordionBlock = {
4381
3298
  label: "Accordion",
@@ -4399,7 +3316,7 @@ function createSiteBlocks(kit) {
4399
3316
  { title: "How does billing work?", content: "Monthly or annually, cancel anytime." }
4400
3317
  ]
4401
3318
  },
4402
- render: ({ id, allowMultiple, items }) => /* @__PURE__ */ jsxRuntime.jsx(Accordion, { allowMultiple, items, testId: blockTestId(id) })
3319
+ render: ({ id, allowMultiple, items }) => /* @__PURE__ */ jsxRuntime.jsx(chunkAHWIZJ4M_cjs.Accordion, { allowMultiple, items, testId: blockTestId(id) })
4403
3320
  };
4404
3321
  const GalleryBlock = {
4405
3322
  label: "Gallery",
@@ -4435,7 +3352,7 @@ function createSiteBlocks(kit) {
4435
3352
  { src: "", alt: "Image three", caption: "" }
4436
3353
  ]
4437
3354
  },
4438
- render: ({ id, columns, aspect, images }) => /* @__PURE__ */ jsxRuntime.jsx(Gallery, { columns, aspect, images, testId: blockTestId(id) })
3355
+ render: ({ id, columns, aspect, images }) => /* @__PURE__ */ jsxRuntime.jsx(chunkAHWIZJ4M_cjs.Gallery, { columns, aspect, images, testId: blockTestId(id) })
4439
3356
  };
4440
3357
  const VideoBlock = {
4441
3358
  label: "Video",
@@ -4455,7 +3372,7 @@ function createSiteBlocks(kit) {
4455
3372
  },
4456
3373
  defaultProps: { url: "", title: "", aspect: "16:9", rounded: true },
4457
3374
  render: ({ id, url, title, aspect, rounded }) => /* @__PURE__ */ jsxRuntime.jsx(
4458
- VideoEmbed,
3375
+ chunkAHWIZJ4M_cjs.VideoEmbed,
4459
3376
  {
4460
3377
  url,
4461
3378
  title,
@@ -4504,7 +3421,7 @@ function createSiteBlocks(kit) {
4504
3421
  ]
4505
3422
  },
4506
3423
  render: ({ id, submitLabel, action, successMessage, fields }) => /* @__PURE__ */ jsxRuntime.jsx(
4507
- ContactForm,
3424
+ chunkAHWIZJ4M_cjs.ContactForm,
4508
3425
  {
4509
3426
  submitLabel,
4510
3427
  action: action || void 0,
@@ -4534,7 +3451,7 @@ function createSiteBlocks(kit) {
4534
3451
  cta: { label: "Read more", href: "#" },
4535
3452
  tone: "primary"
4536
3453
  },
4537
- render: ({ id, text, cta, tone }) => /* @__PURE__ */ jsxRuntime.jsx(Banner, { text, cta, tone, testId: blockTestId(id) })
3454
+ render: ({ id, text, cta, tone }) => /* @__PURE__ */ jsxRuntime.jsx(chunkAHWIZJ4M_cjs.Banner, { text, cta, tone, testId: blockTestId(id) })
4538
3455
  };
4539
3456
  const MediaTextBlock = {
4540
3457
  label: "Media & text",
@@ -4562,7 +3479,7 @@ function createSiteBlocks(kit) {
4562
3479
  cta: { label: "Learn more", href: "#" }
4563
3480
  },
4564
3481
  render: ({ id, eyebrow, title, body, imageUrl, mediaSide, cta }) => /* @__PURE__ */ jsxRuntime.jsx(
4565
- MediaText,
3482
+ chunkAHWIZJ4M_cjs.MediaText,
4566
3483
  {
4567
3484
  eyebrow,
4568
3485
  title,
@@ -4599,7 +3516,7 @@ function createSiteBlocks(kit) {
4599
3516
  { name: "Jordan Lee", role: "Lead Engineer", bio: "", avatarUrl: "" }
4600
3517
  ]
4601
3518
  },
4602
- render: ({ id, columns, members }) => /* @__PURE__ */ jsxRuntime.jsx(TeamGrid, { columns, members, testId: blockTestId(id) })
3519
+ render: ({ id, columns, members }) => /* @__PURE__ */ jsxRuntime.jsx(chunkAHWIZJ4M_cjs.TeamGrid, { columns, members, testId: blockTestId(id) })
4603
3520
  };
4604
3521
  const StepsBlock = {
4605
3522
  label: "Steps",
@@ -4631,7 +3548,7 @@ function createSiteBlocks(kit) {
4631
3548
  { title: "Launch", description: "Go live and start seeing results." }
4632
3549
  ]
4633
3550
  },
4634
- render: ({ id, variant, steps }) => /* @__PURE__ */ jsxRuntime.jsx(Steps, { variant, steps, testId: blockTestId(id) })
3551
+ render: ({ id, variant, steps }) => /* @__PURE__ */ jsxRuntime.jsx(chunkAHWIZJ4M_cjs.Steps, { variant, steps, testId: blockTestId(id) })
4635
3552
  };
4636
3553
  const TestimonialGridBlock = {
4637
3554
  label: "Testimonial grid",
@@ -4673,7 +3590,7 @@ function createSiteBlocks(kit) {
4673
3590
  }
4674
3591
  ]
4675
3592
  },
4676
- render: ({ id, columns, items }) => /* @__PURE__ */ jsxRuntime.jsx(TestimonialGrid, { columns, items, testId: blockTestId(id) })
3593
+ render: ({ id, columns, items }) => /* @__PURE__ */ jsxRuntime.jsx(chunkAHWIZJ4M_cjs.TestimonialGrid, { columns, items, testId: blockTestId(id) })
4677
3594
  };
4678
3595
  return {
4679
3596
  Pricing: PricingBlock,
@@ -4717,7 +3634,7 @@ function createArbiBlocksConfig(opts = {}) {
4717
3634
  },
4718
3635
  defaultProps: { title: "Section title", align: "left", invert: false },
4719
3636
  render: ({ id, title, eyebrow, lead, align, invert }) => /* @__PURE__ */ jsxRuntime.jsx("div", { "data-testid": blockTestId(id), children: /* @__PURE__ */ jsxRuntime.jsx(
4720
- SectionHeading,
3637
+ chunkAHWIZJ4M_cjs.SectionHeading,
4721
3638
  {
4722
3639
  title,
4723
3640
  eyebrow,
@@ -5311,7 +4228,7 @@ function ModuleManager({ store, testIdPrefix = "builder" }) {
5311
4228
  {
5312
4229
  variant: "elevated",
5313
4230
  className: "rounded-xl",
5314
- "data-testid": tid(`${testIdPrefix}-modules-section`, group.section),
4231
+ "data-testid": chunkAHWIZJ4M_cjs.tid(`${testIdPrefix}-modules-section`, group.section),
5315
4232
  children: [
5316
4233
  /* @__PURE__ */ jsxRuntime.jsx(react.CardHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(react.CardTitle, { className: "text-base", children: group.section }) }),
5317
4234
  /* @__PURE__ */ jsxRuntime.jsx(react.CardContent, { className: "space-y-1.5", children: group.modules.map((m, idx) => {
@@ -5320,7 +4237,7 @@ function ModuleManager({ store, testIdPrefix = "builder" }) {
5320
4237
  "div",
5321
4238
  {
5322
4239
  className: "flex items-center gap-3 rounded-md border border-border/60 bg-card px-3 py-2",
5323
- "data-testid": tid(`${testIdPrefix}-module`, m.id),
4240
+ "data-testid": chunkAHWIZJ4M_cjs.tid(`${testIdPrefix}-module`, m.id),
5324
4241
  children: [
5325
4242
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
5326
4243
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -5332,7 +4249,7 @@ function ModuleManager({ store, testIdPrefix = "builder" }) {
5332
4249
  disabled: idx === 0,
5333
4250
  onClick: () => move(m.id, "up"),
5334
4251
  "aria-label": `Move ${m.label} up`,
5335
- "data-testid": tid(`${testIdPrefix}-module-up`, m.id),
4252
+ "data-testid": chunkAHWIZJ4M_cjs.tid(`${testIdPrefix}-module-up`, m.id),
5336
4253
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronUp, { className: "size-3.5" })
5337
4254
  }
5338
4255
  ),
@@ -5345,7 +4262,7 @@ function ModuleManager({ store, testIdPrefix = "builder" }) {
5345
4262
  disabled: idx === group.modules.length - 1,
5346
4263
  onClick: () => move(m.id, "down"),
5347
4264
  "aria-label": `Move ${m.label} down`,
5348
- "data-testid": tid(`${testIdPrefix}-module-down`, m.id),
4265
+ "data-testid": chunkAHWIZJ4M_cjs.tid(`${testIdPrefix}-module-down`, m.id),
5349
4266
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "size-3.5" })
5350
4267
  }
5351
4268
  )
@@ -5365,7 +4282,7 @@ function ModuleManager({ store, testIdPrefix = "builder" }) {
5365
4282
  checked: m.enabled,
5366
4283
  onCheckedChange: () => toggle2(m.id),
5367
4284
  "aria-label": `Enable ${m.label}`,
5368
- "data-testid": tid(`${testIdPrefix}-module-toggle`, m.id)
4285
+ "data-testid": chunkAHWIZJ4M_cjs.tid(`${testIdPrefix}-module-toggle`, m.id)
5369
4286
  }
5370
4287
  )
5371
4288
  ]
@@ -5397,7 +4314,7 @@ function ConfigModelBadge({ configId, testIdPrefix }) {
5397
4314
  react.Badge,
5398
4315
  {
5399
4316
  variant: TIER_VARIANT[tier] ?? "secondary",
5400
- "data-testid": tid(`${testIdPrefix}-agents-config-tier`, configId),
4317
+ "data-testid": chunkAHWIZJ4M_cjs.tid(`${testIdPrefix}-agents-config-tier`, configId),
5401
4318
  children: [
5402
4319
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Cpu, { className: "size-3" }),
5403
4320
  " ",
@@ -5434,14 +4351,14 @@ function AgentsPanel({ store, testIdPrefix = "builder" }) {
5434
4351
  "label",
5435
4352
  {
5436
4353
  className: "flex cursor-pointer items-center gap-3 rounded-md border border-border/60 bg-card px-3 py-2",
5437
- "data-testid": tid(`${testIdPrefix}-agents-config`, v.external_id),
4354
+ "data-testid": chunkAHWIZJ4M_cjs.tid(`${testIdPrefix}-agents-config`, v.external_id),
5438
4355
  children: [
5439
4356
  /* @__PURE__ */ jsxRuntime.jsx(
5440
4357
  react.Checkbox,
5441
4358
  {
5442
4359
  checked: configIds.includes(v.external_id),
5443
4360
  onCheckedChange: () => toggleConfig(v.external_id),
5444
- "data-testid": tid(`${testIdPrefix}-agents-config-toggle`, v.external_id)
4361
+ "data-testid": chunkAHWIZJ4M_cjs.tid(`${testIdPrefix}-agents-config-toggle`, v.external_id)
5445
4362
  }
5446
4363
  ),
5447
4364
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
@@ -5470,14 +4387,14 @@ function AgentsPanel({ store, testIdPrefix = "builder" }) {
5470
4387
  "label",
5471
4388
  {
5472
4389
  className: "flex cursor-pointer items-center gap-3 rounded-md border border-border/60 bg-card px-3 py-2",
5473
- "data-testid": tid(`${testIdPrefix}-agents-agent`, a.external_id),
4390
+ "data-testid": chunkAHWIZJ4M_cjs.tid(`${testIdPrefix}-agents-agent`, a.external_id),
5474
4391
  children: [
5475
4392
  /* @__PURE__ */ jsxRuntime.jsx(
5476
4393
  react.Checkbox,
5477
4394
  {
5478
4395
  checked: agentIds.includes(a.external_id),
5479
4396
  onCheckedChange: () => toggleAgent(a.external_id),
5480
- "data-testid": tid(`${testIdPrefix}-agents-agent-toggle`, a.external_id)
4397
+ "data-testid": chunkAHWIZJ4M_cjs.tid(`${testIdPrefix}-agents-agent-toggle`, a.external_id)
5481
4398
  }
5482
4399
  ),
5483
4400
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
@@ -5564,7 +4481,7 @@ function VerticalBuilder({
5564
4481
  ] })
5565
4482
  ] }),
5566
4483
  /* @__PURE__ */ jsxRuntime.jsx(react.TabsContent, { value: "theme", children: /* @__PURE__ */ jsxRuntime.jsx(
5567
- ThemeEditor,
4484
+ chunkAHWIZJ4M_cjs.ThemeEditor,
5568
4485
  {
5569
4486
  bundle: themeBundle,
5570
4487
  variant: "panel",
@@ -5588,6 +4505,246 @@ function VerticalBuilder({
5588
4505
  ] });
5589
4506
  }
5590
4507
 
4508
+ Object.defineProperty(exports, "ASSET_REF_PREFIX", {
4509
+ enumerable: true,
4510
+ get: function () { return chunkAHWIZJ4M_cjs.ASSET_REF_PREFIX; }
4511
+ });
4512
+ Object.defineProperty(exports, "Accordion", {
4513
+ enumerable: true,
4514
+ get: function () { return chunkAHWIZJ4M_cjs.Accordion; }
4515
+ });
4516
+ Object.defineProperty(exports, "AssetResolverProvider", {
4517
+ enumerable: true,
4518
+ get: function () { return chunkAHWIZJ4M_cjs.AssetResolverProvider; }
4519
+ });
4520
+ Object.defineProperty(exports, "AvatarBlock", {
4521
+ enumerable: true,
4522
+ get: function () { return chunkAHWIZJ4M_cjs.AvatarBlock; }
4523
+ });
4524
+ Object.defineProperty(exports, "Banner", {
4525
+ enumerable: true,
4526
+ get: function () { return chunkAHWIZJ4M_cjs.Banner; }
4527
+ });
4528
+ Object.defineProperty(exports, "BlockImage", {
4529
+ enumerable: true,
4530
+ get: function () { return chunkAHWIZJ4M_cjs.BlockImage; }
4531
+ });
4532
+ Object.defineProperty(exports, "BlockLink", {
4533
+ enumerable: true,
4534
+ get: function () { return chunkAHWIZJ4M_cjs.BlockLink; }
4535
+ });
4536
+ Object.defineProperty(exports, "CTABanner", {
4537
+ enumerable: true,
4538
+ get: function () { return chunkAHWIZJ4M_cjs.CTABanner; }
4539
+ });
4540
+ Object.defineProperty(exports, "Callout", {
4541
+ enumerable: true,
4542
+ get: function () { return chunkAHWIZJ4M_cjs.Callout; }
4543
+ });
4544
+ Object.defineProperty(exports, "Columns", {
4545
+ enumerable: true,
4546
+ get: function () { return chunkAHWIZJ4M_cjs.Columns; }
4547
+ });
4548
+ Object.defineProperty(exports, "ContactForm", {
4549
+ enumerable: true,
4550
+ get: function () { return chunkAHWIZJ4M_cjs.ContactForm; }
4551
+ });
4552
+ Object.defineProperty(exports, "Container", {
4553
+ enumerable: true,
4554
+ get: function () { return chunkAHWIZJ4M_cjs.Container; }
4555
+ });
4556
+ Object.defineProperty(exports, "FAQ", {
4557
+ enumerable: true,
4558
+ get: function () { return chunkAHWIZJ4M_cjs.FAQ; }
4559
+ });
4560
+ Object.defineProperty(exports, "FONT_PAIRINGS", {
4561
+ enumerable: true,
4562
+ get: function () { return chunkAHWIZJ4M_cjs.FONT_PAIRINGS; }
4563
+ });
4564
+ Object.defineProperty(exports, "FeatureGrid", {
4565
+ enumerable: true,
4566
+ get: function () { return chunkAHWIZJ4M_cjs.FeatureGrid; }
4567
+ });
4568
+ Object.defineProperty(exports, "Footer", {
4569
+ enumerable: true,
4570
+ get: function () { return chunkAHWIZJ4M_cjs.Footer; }
4571
+ });
4572
+ Object.defineProperty(exports, "Gallery", {
4573
+ enumerable: true,
4574
+ get: function () { return chunkAHWIZJ4M_cjs.Gallery; }
4575
+ });
4576
+ Object.defineProperty(exports, "Hero", {
4577
+ enumerable: true,
4578
+ get: function () { return chunkAHWIZJ4M_cjs.Hero; }
4579
+ });
4580
+ Object.defineProperty(exports, "ListBlock", {
4581
+ enumerable: true,
4582
+ get: function () { return chunkAHWIZJ4M_cjs.ListBlock; }
4583
+ });
4584
+ Object.defineProperty(exports, "LogoCloud", {
4585
+ enumerable: true,
4586
+ get: function () { return chunkAHWIZJ4M_cjs.LogoCloud; }
4587
+ });
4588
+ Object.defineProperty(exports, "MediaText", {
4589
+ enumerable: true,
4590
+ get: function () { return chunkAHWIZJ4M_cjs.MediaText; }
4591
+ });
4592
+ Object.defineProperty(exports, "Navbar", {
4593
+ enumerable: true,
4594
+ get: function () { return chunkAHWIZJ4M_cjs.Navbar; }
4595
+ });
4596
+ Object.defineProperty(exports, "PricingTable", {
4597
+ enumerable: true,
4598
+ get: function () { return chunkAHWIZJ4M_cjs.PricingTable; }
4599
+ });
4600
+ Object.defineProperty(exports, "RichTextBlock", {
4601
+ enumerable: true,
4602
+ get: function () { return chunkAHWIZJ4M_cjs.RichTextBlock; }
4603
+ });
4604
+ Object.defineProperty(exports, "SectionHeading", {
4605
+ enumerable: true,
4606
+ get: function () { return chunkAHWIZJ4M_cjs.SectionHeading; }
4607
+ });
4608
+ Object.defineProperty(exports, "Spacer", {
4609
+ enumerable: true,
4610
+ get: function () { return chunkAHWIZJ4M_cjs.Spacer; }
4611
+ });
4612
+ Object.defineProperty(exports, "Steps", {
4613
+ enumerable: true,
4614
+ get: function () { return chunkAHWIZJ4M_cjs.Steps; }
4615
+ });
4616
+ Object.defineProperty(exports, "THEME_STYLE_ID", {
4617
+ enumerable: true,
4618
+ get: function () { return chunkAHWIZJ4M_cjs.THEME_STYLE_ID; }
4619
+ });
4620
+ Object.defineProperty(exports, "Tabs", {
4621
+ enumerable: true,
4622
+ get: function () { return chunkAHWIZJ4M_cjs.Tabs; }
4623
+ });
4624
+ Object.defineProperty(exports, "TeamGrid", {
4625
+ enumerable: true,
4626
+ get: function () { return chunkAHWIZJ4M_cjs.TeamGrid; }
4627
+ });
4628
+ Object.defineProperty(exports, "Testimonial", {
4629
+ enumerable: true,
4630
+ get: function () { return chunkAHWIZJ4M_cjs.Testimonial; }
4631
+ });
4632
+ Object.defineProperty(exports, "TestimonialGrid", {
4633
+ enumerable: true,
4634
+ get: function () { return chunkAHWIZJ4M_cjs.TestimonialGrid; }
4635
+ });
4636
+ Object.defineProperty(exports, "ThemeEditor", {
4637
+ enumerable: true,
4638
+ get: function () { return chunkAHWIZJ4M_cjs.ThemeEditor; }
4639
+ });
4640
+ Object.defineProperty(exports, "VideoEmbed", {
4641
+ enumerable: true,
4642
+ get: function () { return chunkAHWIZJ4M_cjs.VideoEmbed; }
4643
+ });
4644
+ Object.defineProperty(exports, "applyFontVars", {
4645
+ enumerable: true,
4646
+ get: function () { return chunkAHWIZJ4M_cjs.applyFontVars; }
4647
+ });
4648
+ Object.defineProperty(exports, "applyStoredTheme", {
4649
+ enumerable: true,
4650
+ get: function () { return chunkAHWIZJ4M_cjs.applyStoredTheme; }
4651
+ });
4652
+ Object.defineProperty(exports, "applyThemeVars", {
4653
+ enumerable: true,
4654
+ get: function () { return chunkAHWIZJ4M_cjs.applyThemeVars; }
4655
+ });
4656
+ Object.defineProperty(exports, "asAssetRef", {
4657
+ enumerable: true,
4658
+ get: function () { return chunkAHWIZJ4M_cjs.asAssetRef; }
4659
+ });
4660
+ Object.defineProperty(exports, "assetRefId", {
4661
+ enumerable: true,
4662
+ get: function () { return chunkAHWIZJ4M_cjs.assetRefId; }
4663
+ });
4664
+ Object.defineProperty(exports, "clearFontVars", {
4665
+ enumerable: true,
4666
+ get: function () { return chunkAHWIZJ4M_cjs.clearFontVars; }
4667
+ });
4668
+ Object.defineProperty(exports, "clearThemeVars", {
4669
+ enumerable: true,
4670
+ get: function () { return chunkAHWIZJ4M_cjs.clearThemeVars; }
4671
+ });
4672
+ Object.defineProperty(exports, "createThemeStore", {
4673
+ enumerable: true,
4674
+ get: function () { return chunkAHWIZJ4M_cjs.createThemeStore; }
4675
+ });
4676
+ Object.defineProperty(exports, "daysUntil", {
4677
+ enumerable: true,
4678
+ get: function () { return chunkAHWIZJ4M_cjs.daysUntil; }
4679
+ });
4680
+ Object.defineProperty(exports, "fmtDate", {
4681
+ enumerable: true,
4682
+ get: function () { return chunkAHWIZJ4M_cjs.fmtDate; }
4683
+ });
4684
+ Object.defineProperty(exports, "fmtDateTime", {
4685
+ enumerable: true,
4686
+ get: function () { return chunkAHWIZJ4M_cjs.fmtDateTime; }
4687
+ });
4688
+ Object.defineProperty(exports, "fontPackages", {
4689
+ enumerable: true,
4690
+ get: function () { return chunkAHWIZJ4M_cjs.fontPackages; }
4691
+ });
4692
+ Object.defineProperty(exports, "fromNow", {
4693
+ enumerable: true,
4694
+ get: function () { return chunkAHWIZJ4M_cjs.fromNow; }
4695
+ });
4696
+ Object.defineProperty(exports, "gbp", {
4697
+ enumerable: true,
4698
+ get: function () { return chunkAHWIZJ4M_cjs.gbp; }
4699
+ });
4700
+ Object.defineProperty(exports, "getFontPairing", {
4701
+ enumerable: true,
4702
+ get: function () { return chunkAHWIZJ4M_cjs.getFontPairing; }
4703
+ });
4704
+ Object.defineProperty(exports, "hrs", {
4705
+ enumerable: true,
4706
+ get: function () { return chunkAHWIZJ4M_cjs.hrs; }
4707
+ });
4708
+ Object.defineProperty(exports, "initials", {
4709
+ enumerable: true,
4710
+ get: function () { return chunkAHWIZJ4M_cjs.initials; }
4711
+ });
4712
+ Object.defineProperty(exports, "isAssetRef", {
4713
+ enumerable: true,
4714
+ get: function () { return chunkAHWIZJ4M_cjs.isAssetRef; }
4715
+ });
4716
+ Object.defineProperty(exports, "matchFontPairing", {
4717
+ enumerable: true,
4718
+ get: function () { return chunkAHWIZJ4M_cjs.matchFontPairing; }
4719
+ });
4720
+ Object.defineProperty(exports, "pct", {
4721
+ enumerable: true,
4722
+ get: function () { return chunkAHWIZJ4M_cjs.pct; }
4723
+ });
4724
+ Object.defineProperty(exports, "tid", {
4725
+ enumerable: true,
4726
+ get: function () { return chunkAHWIZJ4M_cjs.tid; }
4727
+ });
4728
+ Object.defineProperty(exports, "toEmbedUrl", {
4729
+ enumerable: true,
4730
+ get: function () { return chunkAHWIZJ4M_cjs.toEmbedUrl; }
4731
+ });
4732
+ Object.defineProperty(exports, "toHslTriplet", {
4733
+ enumerable: true,
4734
+ get: function () { return chunkAHWIZJ4M_cjs.toHslTriplet; }
4735
+ });
4736
+ Object.defineProperty(exports, "useAssetRenderer", {
4737
+ enumerable: true,
4738
+ get: function () { return chunkAHWIZJ4M_cjs.useAssetRenderer; }
4739
+ });
4740
+ Object.defineProperty(exports, "useAssetResolverActive", {
4741
+ enumerable: true,
4742
+ get: function () { return chunkAHWIZJ4M_cjs.useAssetResolverActive; }
4743
+ });
4744
+ Object.defineProperty(exports, "DocumentCard", {
4745
+ enumerable: true,
4746
+ get: function () { return react.DocumentCard; }
4747
+ });
5591
4748
  Object.defineProperty(exports, "Table", {
5592
4749
  enumerable: true,
5593
4750
  get: function () { return react.Table; }
@@ -5612,6 +4769,22 @@ Object.defineProperty(exports, "TableRow", {
5612
4769
  enumerable: true,
5613
4770
  get: function () { return react.TableRow; }
5614
4771
  });
4772
+ Object.defineProperty(exports, "Tooltip", {
4773
+ enumerable: true,
4774
+ get: function () { return react.Tooltip; }
4775
+ });
4776
+ Object.defineProperty(exports, "TooltipContent", {
4777
+ enumerable: true,
4778
+ get: function () { return react.TooltipContent; }
4779
+ });
4780
+ Object.defineProperty(exports, "TooltipProvider", {
4781
+ enumerable: true,
4782
+ get: function () { return react.TooltipProvider; }
4783
+ });
4784
+ Object.defineProperty(exports, "TooltipTrigger", {
4785
+ enumerable: true,
4786
+ get: function () { return react.TooltipTrigger; }
4787
+ });
5615
4788
  Object.defineProperty(exports, "redlineStats", {
5616
4789
  enumerable: true,
5617
4790
  get: function () { return react.redlineStats; }
@@ -5624,63 +4797,29 @@ Object.defineProperty(exports, "toRedlineMarkdown", {
5624
4797
  enumerable: true,
5625
4798
  get: function () { return react.toRedlineMarkdown; }
5626
4799
  });
5627
- exports.ASSET_REF_PREFIX = ASSET_REF_PREFIX;
5628
- exports.Accordion = Accordion;
5629
4800
  exports.AgentsPanel = AgentsPanel;
5630
4801
  exports.AppHeader = AppHeader;
5631
4802
  exports.AppShell = AppShell;
5632
- exports.AssetResolverProvider = AssetResolverProvider;
5633
- exports.AvatarBlock = AvatarBlock;
5634
- exports.Banner = Banner;
5635
- exports.BlockImage = BlockImage;
5636
- exports.CTABanner = CTABanner;
5637
- exports.Callout = Callout;
5638
- exports.Columns = Columns;
4803
+ exports.AssetThumb = AssetThumb;
5639
4804
  exports.ConnectionProvider = ConnectionProvider;
5640
- exports.ContactForm = ContactForm;
5641
- exports.Container = Container;
5642
4805
  exports.DataTable = DataTable;
5643
4806
  exports.DataTableBlock = DataTableBlock;
5644
4807
  exports.EmptyState = EmptyState;
5645
- exports.FAQ = FAQ;
5646
- exports.FeatureGrid = FeatureGrid;
5647
- exports.Footer = Footer;
5648
- exports.Gallery = Gallery;
5649
4808
  exports.GridView = GridView;
5650
- exports.Hero = Hero;
5651
4809
  exports.LegalArbiProvider = LegalArbiProvider;
5652
- exports.ListBlock = ListBlock;
5653
4810
  exports.LiveDataProvider = LiveDataProvider;
5654
- exports.LogoCloud = LogoCloud;
5655
- exports.MediaText = MediaText;
5656
4811
  exports.MetricCard = MetricCard;
5657
4812
  exports.ModuleManager = ModuleManager;
5658
- exports.Navbar = Navbar;
5659
4813
  exports.PageHeader = PageHeader;
5660
4814
  exports.PageRenderer = PageRenderer;
5661
- exports.PricingTable = PricingTable;
5662
- exports.RichTextBlock = RichTextBlock;
5663
4815
  exports.Section = Section;
5664
- exports.SectionHeading = SectionHeading;
5665
- exports.Spacer = Spacer;
5666
4816
  exports.StatGroup = StatGroup;
5667
- exports.Steps = Steps;
5668
4817
  exports.StudioEditor = StudioEditor;
5669
- exports.THEME_STYLE_ID = THEME_STYLE_ID;
5670
- exports.Tabs = Tabs;
5671
- exports.TeamGrid = TeamGrid;
5672
- exports.Testimonial = Testimonial;
5673
- exports.TestimonialGrid = TestimonialGrid;
5674
- exports.ThemeEditor = ThemeEditor;
5675
4818
  exports.Toolbar = Toolbar;
4819
+ exports.UploadDropzone = UploadDropzone;
5676
4820
  exports.VerticalBuilder = VerticalBuilder;
5677
- exports.VideoEmbed = VideoEmbed;
5678
4821
  exports.WidgetPlaceholder = WidgetPlaceholder;
5679
- exports.applyStoredTheme = applyStoredTheme;
5680
- exports.applyThemeVars = applyThemeVars;
5681
- exports.asAssetRef = asAssetRef;
5682
- exports.assetRefId = assetRefId;
5683
- exports.clearThemeVars = clearThemeVars;
4822
+ exports.WorkspaceCard = WorkspaceCard;
5684
4823
  exports.createAgentSelectionStore = createAgentSelectionStore;
5685
4824
  exports.createAiFields = createAiFields;
5686
4825
  exports.createArbiBlocksConfig = createArbiBlocksConfig;
@@ -5693,26 +4832,13 @@ exports.createModuleStore = createModuleStore;
5693
4832
  exports.createPromptLibrary = createPromptLibrary;
5694
4833
  exports.createSiteBlocks = createSiteBlocks;
5695
4834
  exports.createStudioPersistence = createStudioPersistence;
5696
- exports.createThemeStore = createThemeStore;
5697
4835
  exports.createVerticalExport = createVerticalExport;
5698
4836
  exports.createWebsiteBlocks = createWebsiteBlocks;
5699
- exports.daysUntil = daysUntil;
5700
- exports.fmtDate = fmtDate;
5701
- exports.fmtDateTime = fmtDateTime;
5702
- exports.fromNow = fromNow;
5703
- exports.gbp = gbp;
5704
- exports.hrs = hrs;
5705
4837
  exports.iconMap = iconMap;
5706
- exports.initials = initials;
5707
- exports.isAssetRef = isAssetRef;
5708
4838
  exports.isAuthenticated = isAuthenticated;
5709
4839
  exports.materializePageData = materializePageData;
5710
4840
  exports.matterToContext = matterToContext;
5711
- exports.pct = pct;
5712
- exports.tid = tid;
5713
- exports.toEmbedUrl = toEmbedUrl;
5714
- exports.toHslTriplet = toHslTriplet;
5715
- exports.useAssetResolverActive = useAssetResolverActive;
4841
+ exports.useAssetImage = useAssetImage;
5716
4842
  exports.useConnection = useConnection;
5717
4843
  exports.useFirmAiTask = useFirmAiTask;
5718
4844
  exports.useImageGen = useImageGen;