@proveanything/smartlinks-utils-ui 0.3.9 → 0.3.11

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.
@@ -1,13 +1,22 @@
1
- import { styleInject } from '../../chunk-IGFYMNKL.js';
1
+ import { styleInject } from '../../chunk-3BLWNYM4.js';
2
2
  import { cn } from '../../chunk-L7FQ52F5.js';
3
+ import { listRecords, parsedRefToTarget, parsedRefToScope, matchRecords, scopesEqual, upsertRecord, deleteRecord } from '../../chunk-TY2UIZ24.js';
4
+ export { bulkDelete, bulkUpsert, deleteRecord, getRecordByRef, listRecords, matchRecords, parsedRefToScope, parsedRefToTarget, restoreRecord, scopesEqual, upsertRecord } from '../../chunk-TY2UIZ24.js';
3
5
  import { createContext, useMemo, useState, useEffect, useCallback, useRef, useContext, createElement } from 'react';
4
- import { ChevronDown, Database, Lightbulb, SearchX, Inbox, LayoutGrid, Eye, MoreHorizontal, Download, Upload, Trash2, Copy, Pencil, Plus, CircleDashed, ArrowDownLeft, CheckCircle2, Globe, Tag, Boxes, Layers, Package, Rows3, Image, List, ChevronRight, Eraser, ClipboardPaste, Box, X, AlertTriangle, Info, HelpCircle, Search, CornerDownLeft, Circle, AlertCircle, Undo2, Save } from 'lucide-react';
6
+ import { ChevronDown, Database, Lightbulb, SearchX, Inbox, LayoutGrid, Eye, MoreHorizontal, Download, Upload, Trash2, Copy, Pencil, Plus, CircleDashed, ArrowDownLeft, CheckCircle2, Globe, Tag, Boxes, Layers, Package, Rows3, List, ChevronRight, Eraser, ClipboardPaste, Box, X, Image, Table, ArrowLeft, ChevronLeft, AlertTriangle, Info, HelpCircle, Search, CornerDownLeft, Circle, AlertCircle, Undo2, Save } from 'lucide-react';
5
7
  import { useQueryClient, useInfiniteQuery, useQuery } from '@tanstack/react-query';
6
8
  import { createPortal } from 'react-dom';
7
9
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
8
10
 
9
11
  var DEFAULT_ICONS = {
10
- scope: { product: Package, variant: Layers, batch: Boxes, facet: Tag, universal: Globe },
12
+ scope: {
13
+ collection: Globe,
14
+ product: Package,
15
+ variant: Layers,
16
+ batch: Boxes,
17
+ facet: Tag,
18
+ universal: Globe
19
+ },
11
20
  status: { own: CheckCircle2, inherited: ArrowDownLeft, missing: CircleDashed },
12
21
  action: {
13
22
  add: Plus,
@@ -86,12 +95,22 @@ var DEFAULT_I18N = {
86
95
  unsavedPromptSave: "Save & continue",
87
96
  unsavedBannerBody: "Unsaved changes on {name}",
88
97
  presentationList: "List",
89
- presentationGrid: "Grid",
90
- presentationGallery: "Gallery",
91
98
  presentationCompact: "Compact",
99
+ itemViewTable: "Table",
100
+ itemViewCards: "Cards",
101
+ itemViewGallery: "Gallery",
92
102
  newItem: "New item",
93
103
  noItemsTitle: "No items yet",
94
104
  noItemsBody: "Create your first item to get started.",
105
+ backToList: "Back to list",
106
+ prevItem: "Previous",
107
+ nextItem: "Next",
108
+ itemListTitle: "Items",
109
+ itemColumnLabel: "Name",
110
+ itemColumnUpdated: "Updated",
111
+ itemActions: "Actions",
112
+ backToScopes: "\u2190 All scopes",
113
+ siblingsHeading: "Items in this scope",
95
114
  railEmptyTitle: "No records yet",
96
115
  railEmptyBody: "Records you create will appear here.",
97
116
  copy: "Copy",
@@ -110,7 +129,15 @@ var DEFAULT_I18N = {
110
129
  };
111
130
 
112
131
  // src/components/RecordsAdmin/types/presentation.ts
113
- var ALL_PRESENTATIONS = ["list", "grid", "gallery", "compact"];
132
+ var ALL_PRESENTATIONS = ["list", "compact"];
133
+ var ALL_ITEM_VIEWS = ["table", "cards", "gallery"];
134
+
135
+ // src/components/RecordsAdmin/types/deepLink.ts
136
+ var DEFAULT_DEEP_LINK_PARAM_NAMES = {
137
+ item: "item",
138
+ scope: "scope",
139
+ view: "view"
140
+ };
114
141
 
115
142
  // src/components/RecordsAdmin/data/refs.ts
116
143
  var KIND_KEYS = {
@@ -139,6 +166,9 @@ var parseRef = (raw) => {
139
166
  } else {
140
167
  parsed.facetId = id;
141
168
  }
169
+ } else if (k === "item") {
170
+ parsed.itemId = id;
171
+ continue;
142
172
  } else if (k in KIND_KEYS) {
143
173
  parsed[KIND_KEYS[k]] = id;
144
174
  }
@@ -156,6 +186,7 @@ var buildRef = (a) => {
156
186
  if (a.variantId) parts.push(`variant:${a.variantId}`);
157
187
  if (a.batchId) parts.push(`batch:${a.batchId}`);
158
188
  if (a.proofId) parts.push(`proof:${a.proofId}`);
189
+ if (a.itemId) parts.push(`item:${a.itemId}`);
159
190
  return parts.join("/");
160
191
  };
161
192
  var resolutionChain = (target, supportedScopes) => {
@@ -172,173 +203,23 @@ var resolutionChain = (target, supportedScopes) => {
172
203
  if (supportedScopes.includes("facet") && target.facetId) {
173
204
  chain.push(buildRef({ facetId: target.facetId, facetValue: target.facetValue }));
174
205
  }
175
- return Array.from(new Set(chain));
176
- };
177
-
178
- // src/components/RecordsAdmin/data/scopeBridge.ts
179
- var parsedRefToScope = (ref) => {
180
- const scope = {};
181
- if (ref.productId) scope.productId = ref.productId;
182
- if (ref.variantId) scope.variantId = ref.variantId;
183
- if (ref.batchId) scope.batchId = ref.batchId;
184
- if (ref.proofId) scope.proofId = ref.proofId;
185
- if (ref.facetId) {
186
- scope.facets = [{
187
- key: ref.facetId,
188
- valueKeys: ref.facetValue ? [ref.facetValue] : []
189
- }];
190
- }
191
- return scope;
192
- };
193
- var parsedRefToTarget = (ref) => {
194
- const target = {};
195
- if (ref.productId) target.productId = ref.productId;
196
- if (ref.variantId) target.variantId = ref.variantId;
197
- if (ref.batchId) target.batchId = ref.batchId;
198
- if (ref.proofId) target.proofId = ref.proofId;
199
- if (ref.facetId && ref.facetValue) {
200
- target.facets = { [ref.facetId]: [ref.facetValue] };
201
- }
202
- return target;
203
- };
204
- var scopesEqual = (a, b) => {
205
- if ((a.productId ?? null) !== (b.productId ?? null)) return false;
206
- if ((a.variantId ?? null) !== (b.variantId ?? null)) return false;
207
- if ((a.batchId ?? null) !== (b.batchId ?? null)) return false;
208
- if ((a.proofId ?? null) !== (b.proofId ?? null)) return false;
209
- const af = a.facets ?? [];
210
- const bf = b.facets ?? [];
211
- if (af.length !== bf.length) return false;
212
- const norm = (xs) => xs.map((f) => `${f.key}:${[...f.valueKeys].sort().join(",")}`).sort().join("|");
213
- return norm(af) === norm(bf);
214
- };
215
-
216
- // src/components/RecordsAdmin/data/records.ts
217
- var listRecords = async (ctx, params = {}) => {
218
- const { limit = 100, offset, ref, refPrefix, q, sort } = params;
219
- const res = await ctx.SL.app.records.list(
220
- ctx.collectionId,
221
- ctx.appId,
222
- {
223
- ...ctx.recordType ? { recordType: ctx.recordType } : {},
224
- limit,
225
- offset,
226
- ref,
227
- refPrefix,
228
- q,
229
- sort
230
- },
231
- true
232
- );
233
- return {
234
- data: res?.data ?? [],
235
- total: res?.pagination?.total ?? (res?.data?.length ?? 0),
236
- hasMore: res?.pagination?.hasMore ?? false
237
- };
238
- };
239
- var getRecordByRef = async (ctx, ref) => {
240
- const res = await ctx.SL.app.records.list(
241
- ctx.collectionId,
242
- ctx.appId,
243
- { ...ctx.recordType ? { recordType: ctx.recordType } : {}, ref, limit: 1 },
244
- true
245
- );
246
- return res?.data?.[0] ?? null;
247
- };
248
- var upsertRecord = async (ctx, write) => {
249
- const ref = write.ref ?? deriveRefFromScope(write.scope);
250
- const res = await ctx.SL.app.records.upsert(ctx.collectionId, ctx.appId, {
251
- ref,
252
- ...ctx.recordType ? { recordType: ctx.recordType } : {},
253
- scope: write.scope,
254
- data: write.data,
255
- status: write.status,
256
- startsAt: write.startsAt,
257
- expiresAt: write.expiresAt,
258
- customId: write.customId,
259
- sourceSystem: write.sourceSystem
260
- });
261
- return { record: res, isCreate: !!res?.created };
262
- };
263
- var deleteRecord = async (ctx, ref) => {
264
- const existing = await getRecordByRef(ctx, ref).catch(() => null);
265
- if (!existing) return false;
266
- await ctx.SL.app.records.remove(ctx.collectionId, ctx.appId, existing.id, true);
267
- return true;
268
- };
269
- var restoreRecord = async (ctx, recordId) => ctx.SL.app.records.restore(ctx.collectionId, ctx.appId, recordId);
270
- var matchRecords = async (ctx, target, opts = {}) => ctx.SL.app.records.match(
271
- ctx.collectionId,
272
- ctx.appId,
273
- {
274
- target,
275
- ...ctx.recordType ? { recordType: ctx.recordType } : {},
276
- strategy: opts.strategy ?? "all",
277
- at: opts.at,
278
- includeScheduled: opts.includeScheduled,
279
- includeExpired: opts.includeExpired,
280
- limit: opts.limit
281
- },
282
- true
283
- );
284
- var bulkUpsert = async (ctx, entries) => {
285
- const CHUNK = 500;
286
- let saved = 0;
287
- let failed = 0;
288
- for (let i = 0; i < entries.length; i += CHUNK) {
289
- const slice = entries.slice(i, i + CHUNK);
290
- const items = slice.map((e) => ({
291
- ref: e.ref ?? deriveRefFromScope(e.scope),
292
- ...ctx.recordType ? { recordType: ctx.recordType } : {},
293
- scope: e.scope,
294
- data: e.data,
295
- status: e.status
296
- }));
297
- const res = await ctx.SL.app.records.bulkUpsert(ctx.collectionId, ctx.appId, items).catch(() => ({ saved: 0, failed: items.length }));
298
- saved += res.saved ?? 0;
299
- failed += res.failed ?? 0;
206
+ if (supportedScopes.includes("collection")) {
207
+ chain.push("");
300
208
  }
301
- return { saved, failed };
209
+ return Array.from(new Set(chain));
302
210
  };
303
- var bulkDelete = async (ctx, input) => {
304
- if ("scope" in input) {
305
- const res = await ctx.SL.app.records.bulkDelete(
306
- ctx.collectionId,
307
- ctx.appId,
308
- { scope: input.scope, ...ctx.recordType ? { recordType: ctx.recordType } : {} }
309
- );
310
- return { removed: res.deleted ?? 0 };
311
- }
312
- const CHUNK = 1e3;
313
- let removed = 0;
314
- for (let i = 0; i < input.refs.length; i += CHUNK) {
315
- const slice = input.refs.slice(i, i + CHUNK);
316
- const res = await ctx.SL.app.records.bulkDelete(
317
- ctx.collectionId,
318
- ctx.appId,
319
- { refs: slice, ...ctx.recordType ? { recordType: ctx.recordType } : {} }
320
- );
321
- removed += res.deleted ?? 0;
211
+ var splitItemRef = (raw) => {
212
+ if (!raw) return { scopeRef: "" };
213
+ const segs = raw.split("/").filter(Boolean);
214
+ const last = segs[segs.length - 1];
215
+ if (last && last.startsWith("item:")) {
216
+ return { scopeRef: segs.slice(0, -1).join("/"), itemId: last.slice("item:".length) };
322
217
  }
323
- return { removed };
218
+ return { scopeRef: raw };
324
219
  };
325
- var deriveRefFromScope = (scope) => {
326
- const parts = [];
327
- if (scope.facets && scope.facets.length > 0) {
328
- const sorted = [...scope.facets].sort((a, b) => a.key.localeCompare(b.key));
329
- for (const f of sorted) {
330
- const vals = [...f.valueKeys].sort().join(",");
331
- parts.push(vals ? `facet:${f.key}=${vals}` : `facet:${f.key}`);
332
- }
333
- }
334
- if (scope.productId) parts.push(`product:${scope.productId}`);
335
- if (scope.variantId) parts.push(`variant:${scope.variantId}`);
336
- if (scope.batchId) parts.push(`batch:${scope.batchId}`);
337
- if (scope.proofId) parts.push(`proof:${scope.proofId}`);
338
- return parts.join("/");
220
+ var buildItemRef = (scopeRef, itemId) => {
221
+ return scopeRef ? `${scopeRef}/item:${itemId}` : `item:${itemId}`;
339
222
  };
340
-
341
- // src/components/RecordsAdmin/hooks/useRecordList.ts
342
223
  var defaultClassify = (r) => {
343
224
  if (!r.data) return "empty";
344
225
  const keys = Object.keys(r.data);
@@ -379,7 +260,7 @@ var useRecordList = (args) => {
379
260
  scopeKind,
380
261
  search = "",
381
262
  filter = "all",
382
- classify,
263
+ classify: classify2,
383
264
  enabled = true,
384
265
  scaffolder,
385
266
  contextScope,
@@ -414,9 +295,9 @@ var useRecordList = (args) => {
414
295
  const [scaffolded, setScaffolded] = useState(null);
415
296
  const rawItems = useMemo(() => {
416
297
  const all = query.data?.pages.flatMap((p) => p.data) ?? [];
417
- const cls = classify ?? defaultClassify;
298
+ const cls = classify2 ?? defaultClassify;
418
299
  return all.map(toSummary).filter((s) => matchesScope(scopeKind, s.scope)).filter((s) => matchesContext(s.scope, contextScope)).map((s) => ({ ...s, status: cls(s) }));
419
- }, [query.data, scopeKind, classify, contextScope]);
300
+ }, [query.data, scopeKind, classify2, contextScope]);
420
301
  useEffect(() => {
421
302
  if (!scaffolder) {
422
303
  setScaffolded(null);
@@ -1383,6 +1264,7 @@ function cloneValue(value) {
1383
1264
  }
1384
1265
  }
1385
1266
  var LABELS = {
1267
+ collection: "Global",
1386
1268
  product: "Products",
1387
1269
  facet: "Shared",
1388
1270
  variant: "Variants",
@@ -1591,87 +1473,6 @@ var DefaultRecordRow = ({ record, ctx, compact = false }) => {
1591
1473
  }
1592
1474
  );
1593
1475
  };
1594
- var initials = (s) => s.split(/\s+/).filter(Boolean).slice(0, 2).map((p) => p[0]?.toUpperCase() ?? "").join("") || "?";
1595
- var DefaultRecordCard = ({ record, ctx, variant = "grid" }) => {
1596
- const { selected, onSelect, isDirty, onCopy, onPaste, canPaste, pasteWillReplace, clipboardSourceLabel } = ctx;
1597
- const aspect = variant === "gallery" ? "aspect-video" : "aspect-square";
1598
- return /* @__PURE__ */ jsxs(
1599
- "button",
1600
- {
1601
- type: "button",
1602
- onClick: onSelect,
1603
- className: cn(
1604
- "group flex flex-col text-left rounded-md overflow-hidden border ra-card-hover",
1605
- selected && "ring-2"
1606
- ),
1607
- style: {
1608
- background: "hsl(var(--ra-surface))",
1609
- borderColor: selected ? "var(--ra-row-active-bd)" : "hsl(var(--ra-border))",
1610
- boxShadow: selected ? `0 0 0 2px hsl(var(--ra-accent) / 0.45), var(--ra-card-shadow)` : "var(--ra-card-shadow)"
1611
- },
1612
- children: [
1613
- /* @__PURE__ */ jsxs(
1614
- "div",
1615
- {
1616
- className: cn(aspect, "relative w-full flex items-center justify-center overflow-hidden"),
1617
- style: { background: "hsl(var(--ra-muted))" },
1618
- children: [
1619
- record.thumbnail ? /* @__PURE__ */ jsx(
1620
- "img",
1621
- {
1622
- src: record.thumbnail,
1623
- alt: "",
1624
- loading: "lazy",
1625
- className: "w-full h-full object-cover"
1626
- }
1627
- ) : /* @__PURE__ */ jsx(
1628
- "span",
1629
- {
1630
- className: "text-2xl ra-display",
1631
- style: { color: "hsl(var(--ra-muted-text))" },
1632
- children: initials(record.label)
1633
- }
1634
- ),
1635
- /* @__PURE__ */ jsx("div", { className: "absolute top-1.5 left-1.5", children: /* @__PURE__ */ jsx(StatusDot, { status: record.status }) }),
1636
- isDirty && /* @__PURE__ */ jsx(
1637
- "span",
1638
- {
1639
- title: "Unsaved changes",
1640
- "aria-label": "Unsaved changes",
1641
- className: "ra-status-dot ra-status-shared absolute top-1.5 right-1.5"
1642
- }
1643
- )
1644
- ]
1645
- }
1646
- ),
1647
- /* @__PURE__ */ jsxs("div", { className: "p-2.5 min-w-0", children: [
1648
- /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-1.5 min-w-0", children: [
1649
- /* @__PURE__ */ jsx("div", { className: "ra-row-title flex-1 min-w-0", children: record.label }),
1650
- (onCopy || onPaste) && /* @__PURE__ */ jsx(
1651
- RowContextMenu,
1652
- {
1653
- onCopy,
1654
- onPaste,
1655
- canPaste,
1656
- pasteWillReplace,
1657
- pasteSourceLabel: clipboardSourceLabel,
1658
- i18n: {
1659
- copy: DEFAULT_I18N.copy,
1660
- paste: DEFAULT_I18N.paste,
1661
- pasteFrom: DEFAULT_I18N.pasteFrom,
1662
- pasteReplace: DEFAULT_I18N.pasteReplace,
1663
- clipboardEmpty: DEFAULT_I18N.clipboardEmpty
1664
- }
1665
- }
1666
- )
1667
- ] }),
1668
- variant === "gallery" && record.subtitle && /* @__PURE__ */ jsx("div", { className: "ra-row-sub", children: record.subtitle }),
1669
- record.badges && record.badges.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex gap-1 mt-1.5 flex-wrap", children: record.badges.slice(0, 3).map((b, i) => /* @__PURE__ */ jsx("span", { className: "ra-chip", "data-tone": "muted", children: b.label }, `${b.label}-${i}`)) })
1670
- ] })
1671
- ]
1672
- }
1673
- );
1674
- };
1675
1476
  var RecordList = ({
1676
1477
  items,
1677
1478
  selectedRef,
@@ -1679,7 +1480,6 @@ var RecordList = ({
1679
1480
  dirtyRef,
1680
1481
  presentation = "list",
1681
1482
  renderListRow,
1682
- renderCard,
1683
1483
  groupBy,
1684
1484
  rowClipboard
1685
1485
  }) => {
@@ -1707,20 +1507,6 @@ var RecordList = ({
1707
1507
  return orderedKeys.map((k) => buckets.get(k));
1708
1508
  }, [items, groupBy]);
1709
1509
  const renderItems = (rows) => {
1710
- if (presentation === "grid" || presentation === "gallery") {
1711
- const minColPx = presentation === "gallery" ? 200 : 120;
1712
- return /* @__PURE__ */ jsx(
1713
- "div",
1714
- {
1715
- className: "grid gap-2 p-2",
1716
- style: { gridTemplateColumns: `repeat(auto-fill, minmax(${minColPx}px, 1fr))` },
1717
- children: rows.map((item) => {
1718
- const ctx = buildCtx(item);
1719
- return /* @__PURE__ */ jsx("div", { children: renderCard ? renderCard(item, ctx) : /* @__PURE__ */ jsx(DefaultRecordCard, { record: item, ctx, variant: presentation }) }, item.ref);
1720
- })
1721
- }
1722
- );
1723
- }
1724
1510
  const compact = presentation === "compact";
1725
1511
  return /* @__PURE__ */ jsx("ul", { children: rows.map((item) => {
1726
1512
  const ctx = buildCtx(item);
@@ -1803,18 +1589,12 @@ var ErrorState = ({ error }) => /* @__PURE__ */ jsxs("div", { className: "ra-emp
1803
1589
  ] });
1804
1590
  var ICONS = {
1805
1591
  list: List,
1806
- grid: LayoutGrid,
1807
- gallery: Image,
1808
1592
  compact: Rows3
1809
1593
  };
1810
1594
  var labelFor = (p, i18n) => {
1811
1595
  switch (p) {
1812
1596
  case "list":
1813
1597
  return i18n.presentationList;
1814
- case "grid":
1815
- return i18n.presentationGrid;
1816
- case "gallery":
1817
- return i18n.presentationGallery;
1818
1598
  case "compact":
1819
1599
  return i18n.presentationCompact;
1820
1600
  }
@@ -1853,6 +1633,7 @@ var PresentationSwitcher = ({ options, value, onChange, i18n }) => {
1853
1633
  );
1854
1634
  };
1855
1635
  var KEY_PREFIX = "smartlinks-ui:records-admin:presentation";
1636
+ var ITEM_VIEW_KEY_PREFIX = "smartlinks-ui:records-admin:item-view";
1856
1637
  var safeRead = (key) => {
1857
1638
  try {
1858
1639
  return typeof window === "undefined" ? null : window.localStorage.getItem(key);
@@ -1884,6 +1665,195 @@ function usePresentationPref(args) {
1884
1665
  }, [key]);
1885
1666
  return [value, set];
1886
1667
  }
1668
+ function useItemViewPref(args) {
1669
+ const { appId, recordType, options, defaultValue } = args;
1670
+ const key = `${ITEM_VIEW_KEY_PREFIX}:${appId}:${recordType ?? "_default"}`;
1671
+ const initial = () => {
1672
+ const stored = safeRead(key);
1673
+ if (stored && options.includes(stored)) return stored;
1674
+ return options.includes(defaultValue) ? defaultValue : options[0];
1675
+ };
1676
+ const [value, setValue] = useState(initial);
1677
+ useEffect(() => {
1678
+ if (!options.includes(value)) setValue(options[0]);
1679
+ }, [options, value]);
1680
+ const set = useCallback((next) => {
1681
+ setValue(next);
1682
+ safeWrite(key, next);
1683
+ }, [key]);
1684
+ return [value, set];
1685
+ }
1686
+ var QK_BASE2 = ["records-admin", "collection-items"];
1687
+ var defaultToSummary = (rec, base) => {
1688
+ const data = rec.data;
1689
+ if (!data) return base;
1690
+ const label = data.title ?? data.name ?? data.label ?? data.question ?? base.label;
1691
+ const subtitle = data.subtitle ?? data.summary ?? data.description ?? base.subtitle;
1692
+ const thumbnail = data.thumbnail ?? data.image ?? data.cover ?? base.thumbnail;
1693
+ return { ...base, label, subtitle, thumbnail };
1694
+ };
1695
+ function useCollectionItems(args) {
1696
+ const {
1697
+ ctx,
1698
+ scope,
1699
+ pageSize = 100,
1700
+ toSummary: toSummary2 = defaultToSummary,
1701
+ enabled = true
1702
+ } = args;
1703
+ const queryClient = useQueryClient();
1704
+ const scopeRef = scope?.raw ?? "";
1705
+ const refPrefix = scopeRef ? `${scopeRef}/item:` : "item:";
1706
+ const queryKey = useMemo(
1707
+ () => [...QK_BASE2, ctx.collectionId, ctx.appId, ctx.recordType, scopeRef],
1708
+ [ctx.collectionId, ctx.appId, ctx.recordType, scopeRef]
1709
+ );
1710
+ const query = useInfiniteQuery({
1711
+ queryKey,
1712
+ enabled: enabled && !!scope,
1713
+ initialPageParam: 0,
1714
+ queryFn: async ({ pageParam }) => {
1715
+ const offset = pageParam;
1716
+ const { data, total, hasMore } = await listRecords(ctx, {
1717
+ limit: pageSize,
1718
+ offset,
1719
+ refPrefix
1720
+ });
1721
+ return { data, total, hasMore, nextOffset: offset + data.length };
1722
+ },
1723
+ getNextPageParam: (last) => last.hasMore ? last.nextOffset : void 0,
1724
+ staleTime: 15e3
1725
+ });
1726
+ const items = useMemo(() => {
1727
+ const all = query.data?.pages.flatMap((p) => p.data) ?? [];
1728
+ return all.map((rec) => {
1729
+ const ref = rec.ref ?? "";
1730
+ const parsed = parseRef(ref);
1731
+ const { itemId } = splitItemRef(ref);
1732
+ if (!itemId) return null;
1733
+ const base = {
1734
+ id: rec.id,
1735
+ ref,
1736
+ scope: parsed,
1737
+ data: rec.data ?? null,
1738
+ status: rec.data ? "configured" : "empty",
1739
+ label: itemId,
1740
+ updatedAt: rec.updatedAt,
1741
+ itemId
1742
+ };
1743
+ return toSummary2(rec, base);
1744
+ }).filter((x) => x !== null);
1745
+ }, [query.data, toSummary2]);
1746
+ const refetch = useCallback(() => {
1747
+ queryClient.invalidateQueries({ queryKey });
1748
+ }, [queryClient, queryKey]);
1749
+ return {
1750
+ items,
1751
+ total: query.data?.pages[query.data.pages.length - 1]?.total ?? items.length,
1752
+ isLoading: query.isLoading,
1753
+ error: query.error ?? null,
1754
+ hasNextPage: query.hasNextPage,
1755
+ isFetchingNextPage: query.isFetchingNextPage,
1756
+ fetchNextPage: query.fetchNextPage,
1757
+ refetch
1758
+ };
1759
+ }
1760
+
1761
+ // src/components/RecordsAdmin/data/deepLinkAdapter.ts
1762
+ var findQueryHost = (loc) => {
1763
+ if (loc.search && loc.search.length > 1) return "search";
1764
+ if (loc.hash && loc.hash.includes("?")) return "hash";
1765
+ return "search";
1766
+ };
1767
+ var getQueryString = (loc) => {
1768
+ const host = findQueryHost(loc);
1769
+ if (host === "search") return loc.search.startsWith("?") ? loc.search.slice(1) : loc.search;
1770
+ const idx = loc.hash.indexOf("?");
1771
+ return idx >= 0 ? loc.hash.slice(idx + 1) : "";
1772
+ };
1773
+ var buildUrl = (loc, nextQuery) => {
1774
+ const host = findQueryHost(loc);
1775
+ const qs = nextQuery ? `?${nextQuery}` : "";
1776
+ if (host === "search") {
1777
+ return `${loc.pathname}${qs}${loc.hash}`;
1778
+ }
1779
+ const hashPath = loc.hash.includes("?") ? loc.hash.slice(0, loc.hash.indexOf("?")) : loc.hash;
1780
+ return `${loc.pathname}${loc.search}${hashPath}${qs}`;
1781
+ };
1782
+ var createDefaultDeepLinkAdapter = (paramNames) => ({
1783
+ read() {
1784
+ if (typeof window === "undefined") return {};
1785
+ const params = new URLSearchParams(getQueryString(window.location));
1786
+ return {
1787
+ item: params.get(paramNames.item),
1788
+ scope: params.get(paramNames.scope),
1789
+ view: params.get(paramNames.view)
1790
+ };
1791
+ },
1792
+ write(partial, mode) {
1793
+ if (typeof window === "undefined") return;
1794
+ const params = new URLSearchParams(getQueryString(window.location));
1795
+ const apply = (key, value) => {
1796
+ if (value == null || value === "") params.delete(key);
1797
+ else params.set(key, value);
1798
+ };
1799
+ if ("item" in partial) apply(paramNames.item, partial.item);
1800
+ if ("scope" in partial) apply(paramNames.scope, partial.scope);
1801
+ if ("view" in partial) apply(paramNames.view, partial.view);
1802
+ const nextUrl = buildUrl(window.location, params.toString());
1803
+ if (mode === "push") window.history.pushState({}, "", nextUrl);
1804
+ else window.history.replaceState({}, "", nextUrl);
1805
+ },
1806
+ subscribe(listener) {
1807
+ if (typeof window === "undefined") return () => {
1808
+ };
1809
+ window.addEventListener("popstate", listener);
1810
+ window.addEventListener("hashchange", listener);
1811
+ return () => {
1812
+ window.removeEventListener("popstate", listener);
1813
+ window.removeEventListener("hashchange", listener);
1814
+ };
1815
+ }
1816
+ });
1817
+
1818
+ // src/components/RecordsAdmin/hooks/useDeepLinkState.ts
1819
+ var SMART_PUSH = ["item.open", "item.close", "scope"];
1820
+ var classify = (mode, kind) => {
1821
+ if (mode === "push") return "push";
1822
+ if (mode === "replace") return "replace";
1823
+ return SMART_PUSH.includes(kind) ? "push" : "replace";
1824
+ };
1825
+ function useDeepLinkState(options) {
1826
+ const enabled = !!options?.enabled;
1827
+ const history = options?.history ?? "smart";
1828
+ const paramNames = useMemo(() => ({
1829
+ ...DEFAULT_DEEP_LINK_PARAM_NAMES,
1830
+ ...options?.paramNames ?? {}
1831
+ }), [options?.paramNames]);
1832
+ const defaultAdapterRef = useRef(null);
1833
+ const adapter = useMemo(() => {
1834
+ if (!enabled) return null;
1835
+ if (options?.adapter) return options.adapter;
1836
+ if (!defaultAdapterRef.current) {
1837
+ defaultAdapterRef.current = createDefaultDeepLinkAdapter(paramNames);
1838
+ }
1839
+ return defaultAdapterRef.current;
1840
+ }, [enabled, options?.adapter, paramNames]);
1841
+ const [urlState, setUrlState] = useState(
1842
+ () => adapter ? adapter.read() : {}
1843
+ );
1844
+ useEffect(() => {
1845
+ if (!adapter) return;
1846
+ setUrlState(adapter.read());
1847
+ return adapter.subscribe(() => setUrlState(adapter.read()));
1848
+ }, [adapter]);
1849
+ const emit = useCallback((partial, kind) => {
1850
+ if (!adapter) return;
1851
+ const mode = classify(history, kind);
1852
+ adapter.write(partial, mode);
1853
+ setUrlState((prev) => ({ ...prev, ...partial }));
1854
+ }, [adapter, history]);
1855
+ return { urlState, emit, paramNames, enabled };
1856
+ }
1887
1857
  var segmentsFor = (s) => {
1888
1858
  const out = [];
1889
1859
  if (s.facetId) out.push({ label: s.facetValue ? `${s.facetId}: ${s.facetValue}` : `Facet: ${s.facetId}`, key: "facet" });
@@ -2673,55 +2643,442 @@ var PreviewScopePicker = ({
2673
2643
  )
2674
2644
  ] });
2675
2645
  };
2676
- var TONE_ICON = {
2677
- info: Lightbulb,
2678
- success: CheckCircle2,
2679
- warning: AlertTriangle
2646
+ var ICONS2 = {
2647
+ table: Table,
2648
+ cards: LayoutGrid,
2649
+ gallery: Image
2680
2650
  };
2681
- var IntroCard = ({ title, body, onDismiss, tone = "info", action }) => {
2682
- const Icon = TONE_ICON[tone] ?? Info;
2683
- return /* @__PURE__ */ jsxs("div", { className: "ra-intro", "data-tone": tone, role: "note", children: [
2684
- /* @__PURE__ */ jsx("div", { className: "ra-intro-icon", children: /* @__PURE__ */ jsx(Icon, { className: "w-4 h-4" }) }),
2685
- /* @__PURE__ */ jsxs("div", { className: "ra-intro-body", children: [
2686
- /* @__PURE__ */ jsx("h4", { className: "ra-intro-title", children: title }),
2687
- /* @__PURE__ */ jsxs("div", { className: "ra-intro-text", children: [
2688
- body,
2689
- action && /* @__PURE__ */ jsx("span", { className: "ml-1.5", children: action })
2690
- ] })
2691
- ] }),
2692
- /* @__PURE__ */ jsx(
2651
+ var labelFor2 = (v, i18n) => {
2652
+ if (v === "table") return i18n.itemViewTable;
2653
+ if (v === "cards") return i18n.itemViewCards;
2654
+ return i18n.itemViewGallery;
2655
+ };
2656
+ var ItemViewSwitcher = ({ options, value, onChange, i18n }) => {
2657
+ if (options.length < 2) return null;
2658
+ return /* @__PURE__ */ jsx("div", { role: "tablist", className: "ra-tabs", "aria-label": "Item view", style: { padding: "0.15rem" }, children: options.map((opt) => {
2659
+ const Icon = ICONS2[opt];
2660
+ const active = value === opt;
2661
+ return /* @__PURE__ */ jsxs(
2693
2662
  "button",
2694
2663
  {
2695
2664
  type: "button",
2696
- onClick: onDismiss,
2697
- "aria-label": "Dismiss",
2698
- className: "ra-intro-dismiss",
2699
- children: /* @__PURE__ */ jsx(X, { className: "w-3.5 h-3.5" })
2700
- }
2701
- )
2702
- ] });
2665
+ role: "tab",
2666
+ "aria-selected": active,
2667
+ onClick: () => onChange(opt),
2668
+ className: "ra-tab",
2669
+ title: labelFor2(opt, i18n),
2670
+ style: { padding: "0.3rem 0.55rem" },
2671
+ children: [
2672
+ /* @__PURE__ */ jsx(Icon, { className: cn("ra-tab-icon w-3.5 h-3.5") }),
2673
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: labelFor2(opt, i18n) })
2674
+ ]
2675
+ },
2676
+ opt
2677
+ );
2678
+ }) });
2703
2679
  };
2704
- var UtilityRow = ({ label, introHidden, onShowIntro }) => {
2705
- if (!introHidden || !onShowIntro) return null;
2706
- return /* @__PURE__ */ jsx(
2707
- "div",
2708
- {
2709
- className: "flex items-center justify-end gap-2 text-xs",
2710
- style: { color: "hsl(var(--ra-muted-text))" },
2711
- children: /* @__PURE__ */ jsxs(
2712
- "button",
2680
+ var formatDate = (iso) => {
2681
+ if (!iso) return "\u2014";
2682
+ try {
2683
+ const d = new Date(iso);
2684
+ return d.toLocaleDateString(void 0, { year: "numeric", month: "short", day: "numeric" });
2685
+ } catch {
2686
+ return iso;
2687
+ }
2688
+ };
2689
+ function DefaultItemTable({
2690
+ items,
2691
+ columns,
2692
+ selectedId,
2693
+ onOpen,
2694
+ onDelete,
2695
+ i18n
2696
+ }) {
2697
+ const cols = columns ?? [];
2698
+ const useFallback = cols.length === 0;
2699
+ return /* @__PURE__ */ jsx("div", { className: "ra-item-table-wrap", children: /* @__PURE__ */ jsxs("table", { className: "ra-item-table", children: [
2700
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
2701
+ useFallback ? /* @__PURE__ */ jsxs(Fragment, { children: [
2702
+ /* @__PURE__ */ jsx("th", { children: i18n.itemColumnLabel }),
2703
+ /* @__PURE__ */ jsx("th", { style: { width: "12rem" }, children: i18n.itemColumnUpdated })
2704
+ ] }) : cols.map((c) => /* @__PURE__ */ jsx("th", { style: { width: c.width, textAlign: c.align ?? "left" }, children: c.header }, c.key)),
2705
+ /* @__PURE__ */ jsx(
2706
+ "th",
2713
2707
  {
2714
- type: "button",
2715
- onClick: onShowIntro,
2716
- className: "ra-btn",
2717
- "data-variant": "ghost",
2718
- style: { padding: "0.25rem 0.55rem", fontSize: "0.7rem" },
2719
- children: [
2720
- /* @__PURE__ */ jsx(HelpCircle, { className: "w-3 h-3" }),
2721
- "How ",
2722
- label.toLowerCase(),
2723
- " works"
2724
- ]
2708
+ style: { width: "6.5rem", textAlign: "right" },
2709
+ "aria-label": i18n.itemActions
2710
+ }
2711
+ )
2712
+ ] }) }),
2713
+ /* @__PURE__ */ jsx("tbody", { children: items.map((item) => {
2714
+ const id = item.itemId ?? "";
2715
+ const isSelected = !!selectedId && selectedId === id;
2716
+ return /* @__PURE__ */ jsxs(
2717
+ "tr",
2718
+ {
2719
+ "data-selected": isSelected,
2720
+ onClick: () => onOpen(id),
2721
+ className: "ra-item-row",
2722
+ children: [
2723
+ useFallback ? /* @__PURE__ */ jsxs(Fragment, { children: [
2724
+ /* @__PURE__ */ jsxs("td", { children: [
2725
+ /* @__PURE__ */ jsx("div", { className: "ra-item-row-title", children: item.label }),
2726
+ item.subtitle && /* @__PURE__ */ jsx("div", { className: "ra-item-row-sub", children: item.subtitle })
2727
+ ] }),
2728
+ /* @__PURE__ */ jsx("td", { className: "ra-item-row-meta", children: formatDate(item.updatedAt) })
2729
+ ] }) : cols.map((c) => /* @__PURE__ */ jsx("td", { style: { textAlign: c.align ?? "left" }, children: c.render(item) }, c.key)),
2730
+ /* @__PURE__ */ jsxs("td", { className: "ra-item-row-actions", children: [
2731
+ /* @__PURE__ */ jsx(
2732
+ "button",
2733
+ {
2734
+ type: "button",
2735
+ className: "ra-row-action",
2736
+ onClick: (e) => {
2737
+ e.stopPropagation();
2738
+ onOpen(id);
2739
+ },
2740
+ "aria-label": "Edit",
2741
+ children: /* @__PURE__ */ jsx(Pencil, { className: "w-3.5 h-3.5" })
2742
+ }
2743
+ ),
2744
+ /* @__PURE__ */ jsx(
2745
+ "button",
2746
+ {
2747
+ type: "button",
2748
+ className: "ra-row-action",
2749
+ "data-tone": "danger",
2750
+ onClick: (e) => {
2751
+ e.stopPropagation();
2752
+ onDelete(id);
2753
+ },
2754
+ "aria-label": i18n.delete,
2755
+ children: /* @__PURE__ */ jsx(Trash2, { className: "w-3.5 h-3.5" })
2756
+ }
2757
+ )
2758
+ ] })
2759
+ ]
2760
+ },
2761
+ item.ref
2762
+ );
2763
+ }) })
2764
+ ] }) });
2765
+ }
2766
+ var initials = (label) => label.split(/\s+/).slice(0, 2).map((s) => s[0]?.toUpperCase() ?? "").join("") || "?";
2767
+ function DefaultItemCards({
2768
+ items,
2769
+ variant,
2770
+ selectedId,
2771
+ ctx,
2772
+ renderCard,
2773
+ i18n
2774
+ }) {
2775
+ const isGallery = variant === "gallery";
2776
+ return /* @__PURE__ */ jsx("div", { className: isGallery ? "ra-item-gallery" : "ra-item-cards", children: items.map((item) => {
2777
+ const id = item.itemId ?? "";
2778
+ const slotCtx = {
2779
+ ...ctx,
2780
+ selected: selectedId === id
2781
+ };
2782
+ if (renderCard) {
2783
+ return /* @__PURE__ */ jsx(
2784
+ "div",
2785
+ {
2786
+ onClick: () => ctx.onOpen(id),
2787
+ className: "ra-item-card-wrap",
2788
+ "data-selected": slotCtx.selected,
2789
+ children: renderCard(item, slotCtx)
2790
+ },
2791
+ item.ref
2792
+ );
2793
+ }
2794
+ return /* @__PURE__ */ jsxs(
2795
+ "button",
2796
+ {
2797
+ type: "button",
2798
+ onClick: () => ctx.onOpen(id),
2799
+ className: `ra-item-card ${isGallery ? "ra-item-card--gallery" : ""}`,
2800
+ "data-selected": slotCtx.selected,
2801
+ children: [
2802
+ /* @__PURE__ */ jsx("div", { className: `ra-item-card-thumb ${isGallery ? "ra-item-card-thumb--gallery" : ""}`, children: item.thumbnail ? /* @__PURE__ */ jsx("img", { src: item.thumbnail, alt: "", loading: "lazy" }) : /* @__PURE__ */ jsx("span", { className: "ra-item-card-initials", children: initials(item.label) }) }),
2803
+ /* @__PURE__ */ jsxs("div", { className: "ra-item-card-body", children: [
2804
+ /* @__PURE__ */ jsx("div", { className: "ra-item-card-title", children: item.label }),
2805
+ item.subtitle && /* @__PURE__ */ jsx("div", { className: "ra-item-card-sub", children: item.subtitle })
2806
+ ] }),
2807
+ /* @__PURE__ */ jsx(
2808
+ "button",
2809
+ {
2810
+ type: "button",
2811
+ className: "ra-row-action ra-item-card-delete",
2812
+ "data-tone": "danger",
2813
+ onClick: (e) => {
2814
+ e.stopPropagation();
2815
+ ctx.onDelete(id);
2816
+ },
2817
+ "aria-label": i18n.delete,
2818
+ children: /* @__PURE__ */ jsx(Trash2, { className: "w-3.5 h-3.5" })
2819
+ }
2820
+ )
2821
+ ]
2822
+ },
2823
+ item.ref
2824
+ );
2825
+ }) });
2826
+ }
2827
+ function ItemListView({
2828
+ items,
2829
+ isLoading,
2830
+ error,
2831
+ ctx,
2832
+ itemNoun,
2833
+ view,
2834
+ views,
2835
+ onViewChange,
2836
+ renderItemList,
2837
+ renderItemCard,
2838
+ renderItemEmpty,
2839
+ itemColumns,
2840
+ i18n
2841
+ }) {
2842
+ const newLabel = i18n.newItem.includes("{noun}") ? i18n.newItem.replace("{noun}", itemNoun) : i18n.newItem;
2843
+ const toolbar = /* @__PURE__ */ jsxs("div", { className: "ra-item-toolbar", children: [
2844
+ /* @__PURE__ */ jsxs("div", { className: "ra-item-toolbar-title", children: [
2845
+ /* @__PURE__ */ jsx("h2", { className: "ra-display", style: { fontSize: "0.95rem", margin: 0 }, children: i18n.itemListTitle }),
2846
+ /* @__PURE__ */ jsx("span", { className: "ra-item-toolbar-count", children: items.length })
2847
+ ] }),
2848
+ /* @__PURE__ */ jsxs("div", { className: "ra-item-toolbar-actions", children: [
2849
+ !renderItemList && /* @__PURE__ */ jsx(
2850
+ ItemViewSwitcher,
2851
+ {
2852
+ options: views,
2853
+ value: view,
2854
+ onChange: onViewChange,
2855
+ i18n
2856
+ }
2857
+ ),
2858
+ /* @__PURE__ */ jsxs(
2859
+ "button",
2860
+ {
2861
+ type: "button",
2862
+ onClick: ctx.onCreate,
2863
+ className: "ra-btn",
2864
+ "data-variant": "primary",
2865
+ children: [
2866
+ /* @__PURE__ */ jsx(Plus, { className: "w-3.5 h-3.5" }),
2867
+ newLabel
2868
+ ]
2869
+ }
2870
+ )
2871
+ ] })
2872
+ ] });
2873
+ let body;
2874
+ if (isLoading) {
2875
+ body = /* @__PURE__ */ jsx(LoadingState, {});
2876
+ } else if (error) {
2877
+ body = /* @__PURE__ */ jsx(ErrorState, { error });
2878
+ } else if (items.length === 0) {
2879
+ body = renderItemEmpty ? renderItemEmpty(ctx) : /* @__PURE__ */ jsx(
2880
+ EmptyState,
2881
+ {
2882
+ title: i18n.noItemsTitle,
2883
+ body: i18n.noItemsBody,
2884
+ action: /* @__PURE__ */ jsxs(
2885
+ "button",
2886
+ {
2887
+ type: "button",
2888
+ onClick: ctx.onCreate,
2889
+ className: "ra-btn",
2890
+ "data-variant": "primary",
2891
+ children: [
2892
+ /* @__PURE__ */ jsx(Plus, { className: "w-3.5 h-3.5" }),
2893
+ newLabel
2894
+ ]
2895
+ }
2896
+ )
2897
+ }
2898
+ );
2899
+ } else if (renderItemList) {
2900
+ body = renderItemList(items, ctx);
2901
+ } else if (view === "table") {
2902
+ body = /* @__PURE__ */ jsx(
2903
+ DefaultItemTable,
2904
+ {
2905
+ items,
2906
+ columns: itemColumns,
2907
+ selectedId: ctx.selectedId,
2908
+ onOpen: ctx.onOpen,
2909
+ onDelete: ctx.onDelete,
2910
+ i18n
2911
+ }
2912
+ );
2913
+ } else {
2914
+ body = /* @__PURE__ */ jsx(
2915
+ DefaultItemCards,
2916
+ {
2917
+ items,
2918
+ variant: view,
2919
+ selectedId: ctx.selectedId,
2920
+ ctx,
2921
+ renderCard: renderItemCard,
2922
+ i18n
2923
+ }
2924
+ );
2925
+ }
2926
+ return /* @__PURE__ */ jsxs("div", { className: "ra-item-list", children: [
2927
+ toolbar,
2928
+ /* @__PURE__ */ jsx("div", { className: "ra-item-list-body", children: body })
2929
+ ] });
2930
+ }
2931
+ var EditorItemNav = ({
2932
+ label,
2933
+ position,
2934
+ total,
2935
+ onBack,
2936
+ onPrev,
2937
+ onNext,
2938
+ canPrev,
2939
+ canNext,
2940
+ i18n
2941
+ }) => /* @__PURE__ */ jsxs("div", { className: "ra-item-nav", children: [
2942
+ /* @__PURE__ */ jsxs(
2943
+ "button",
2944
+ {
2945
+ type: "button",
2946
+ onClick: onBack,
2947
+ className: "ra-btn",
2948
+ "data-variant": "ghost",
2949
+ children: [
2950
+ /* @__PURE__ */ jsx(ArrowLeft, { className: "w-3.5 h-3.5" }),
2951
+ i18n.backToList
2952
+ ]
2953
+ }
2954
+ ),
2955
+ typeof position === "number" && typeof total === "number" && total > 0 && /* @__PURE__ */ jsxs("span", { className: "ra-item-nav-position", "aria-label": label, children: [
2956
+ position,
2957
+ " / ",
2958
+ total
2959
+ ] }),
2960
+ /* @__PURE__ */ jsxs("div", { className: "ra-item-nav-arrows", children: [
2961
+ /* @__PURE__ */ jsx(
2962
+ "button",
2963
+ {
2964
+ type: "button",
2965
+ onClick: onPrev,
2966
+ disabled: !canPrev,
2967
+ className: "ra-row-action",
2968
+ "aria-label": i18n.prevItem,
2969
+ title: i18n.prevItem,
2970
+ children: /* @__PURE__ */ jsx(ChevronLeft, { className: "w-4 h-4" })
2971
+ }
2972
+ ),
2973
+ /* @__PURE__ */ jsx(
2974
+ "button",
2975
+ {
2976
+ type: "button",
2977
+ onClick: onNext,
2978
+ disabled: !canNext,
2979
+ className: "ra-row-action",
2980
+ "aria-label": i18n.nextItem,
2981
+ title: i18n.nextItem,
2982
+ children: /* @__PURE__ */ jsx(ChevronRight, { className: "w-4 h-4" })
2983
+ }
2984
+ )
2985
+ ] })
2986
+ ] });
2987
+ function SiblingRail({
2988
+ items,
2989
+ selectedItemId,
2990
+ isLoading,
2991
+ error,
2992
+ onBack,
2993
+ onSelect,
2994
+ i18n
2995
+ }) {
2996
+ return /* @__PURE__ */ jsxs("div", { className: "ra-sibling-rail", children: [
2997
+ /* @__PURE__ */ jsxs(
2998
+ "button",
2999
+ {
3000
+ type: "button",
3001
+ onClick: onBack,
3002
+ className: "ra-sibling-back",
3003
+ children: [
3004
+ /* @__PURE__ */ jsx(ArrowLeft, { className: "w-3.5 h-3.5" }),
3005
+ i18n.backToScopes
3006
+ ]
3007
+ }
3008
+ ),
3009
+ /* @__PURE__ */ jsx("div", { className: "ra-sibling-heading", children: i18n.siblingsHeading }),
3010
+ /* @__PURE__ */ jsxs("div", { className: "ra-sibling-body", children: [
3011
+ isLoading && /* @__PURE__ */ jsx(LoadingState, {}),
3012
+ !isLoading && error && /* @__PURE__ */ jsx(ErrorState, { error }),
3013
+ !isLoading && !error && items.length === 0 && /* @__PURE__ */ jsx(EmptyState, { title: i18n.noItemsTitle, body: i18n.noItemsBody }),
3014
+ !isLoading && !error && items.length > 0 && /* @__PURE__ */ jsx("ul", { className: "ra-sibling-list", children: items.map((item) => {
3015
+ const id = item.itemId ?? "";
3016
+ const selected = selectedItemId === id;
3017
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
3018
+ "button",
3019
+ {
3020
+ type: "button",
3021
+ onClick: () => onSelect(id),
3022
+ className: "ra-row",
3023
+ "data-selected": selected,
3024
+ children: /* @__PURE__ */ jsxs("div", { className: "ra-row-body", children: [
3025
+ /* @__PURE__ */ jsx("div", { className: "ra-row-title", children: item.label }),
3026
+ item.subtitle && /* @__PURE__ */ jsx("div", { className: "ra-row-sub", children: item.subtitle })
3027
+ ] })
3028
+ }
3029
+ ) }, item.ref);
3030
+ }) })
3031
+ ] })
3032
+ ] });
3033
+ }
3034
+ var TONE_ICON = {
3035
+ info: Lightbulb,
3036
+ success: CheckCircle2,
3037
+ warning: AlertTriangle
3038
+ };
3039
+ var IntroCard = ({ title, body, onDismiss, tone = "info", action }) => {
3040
+ const Icon = TONE_ICON[tone] ?? Info;
3041
+ return /* @__PURE__ */ jsxs("div", { className: "ra-intro", "data-tone": tone, role: "note", children: [
3042
+ /* @__PURE__ */ jsx("div", { className: "ra-intro-icon", children: /* @__PURE__ */ jsx(Icon, { className: "w-4 h-4" }) }),
3043
+ /* @__PURE__ */ jsxs("div", { className: "ra-intro-body", children: [
3044
+ /* @__PURE__ */ jsx("h4", { className: "ra-intro-title", children: title }),
3045
+ /* @__PURE__ */ jsxs("div", { className: "ra-intro-text", children: [
3046
+ body,
3047
+ action && /* @__PURE__ */ jsx("span", { className: "ml-1.5", children: action })
3048
+ ] })
3049
+ ] }),
3050
+ /* @__PURE__ */ jsx(
3051
+ "button",
3052
+ {
3053
+ type: "button",
3054
+ onClick: onDismiss,
3055
+ "aria-label": "Dismiss",
3056
+ className: "ra-intro-dismiss",
3057
+ children: /* @__PURE__ */ jsx(X, { className: "w-3.5 h-3.5" })
3058
+ }
3059
+ )
3060
+ ] });
3061
+ };
3062
+ var UtilityRow = ({ label, customLabel, introHidden, onShowIntro }) => {
3063
+ if (!introHidden || !onShowIntro) return null;
3064
+ const text = customLabel ?? `How ${label.toLowerCase()} works`;
3065
+ return /* @__PURE__ */ jsx(
3066
+ "div",
3067
+ {
3068
+ className: "flex items-center justify-end gap-2 text-xs",
3069
+ style: { color: "hsl(var(--ra-muted-text))" },
3070
+ children: /* @__PURE__ */ jsxs(
3071
+ "button",
3072
+ {
3073
+ type: "button",
3074
+ onClick: onShowIntro,
3075
+ className: "ra-btn",
3076
+ "data-variant": "ghost",
3077
+ style: { padding: "0.25rem 0.55rem", fontSize: "0.7rem" },
3078
+ children: [
3079
+ /* @__PURE__ */ jsx(HelpCircle, { className: "w-3 h-3" }),
3080
+ text
3081
+ ]
2725
3082
  }
2726
3083
  )
2727
3084
  }
@@ -2739,7 +3096,8 @@ function ShellHeader({
2739
3096
  stats,
2740
3097
  statsItems,
2741
3098
  statsTitle,
2742
- statsIcon
3099
+ statsIcon,
3100
+ trailingSlot
2743
3101
  }) {
2744
3102
  let iconNode = null;
2745
3103
  if (showHeaderIcon) {
@@ -2794,7 +3152,10 @@ function ShellHeader({
2794
3152
  ]
2795
3153
  }
2796
3154
  ) : null,
2797
- headerActions ? /* @__PURE__ */ jsx("div", { className: "ra-header-actions", children: headerActions }) : null
3155
+ headerActions || trailingSlot ? /* @__PURE__ */ jsxs("div", { className: "ra-header-actions", children: [
3156
+ headerActions,
3157
+ trailingSlot
3158
+ ] }) : null
2798
3159
  ] })
2799
3160
  ] });
2800
3161
  }
@@ -2985,7 +3346,7 @@ var downloadBlob = (blob, filename) => {
2985
3346
  styleInject(':root {\n --ra-status-own: var(--ra-emerald, 142 71% 45%);\n --ra-status-shared: var(--ra-amber, 38 92% 50%);\n --ra-status-missing: var(--muted-foreground, 220 9% 46%);\n --ra-accent: var(--primary, 222 47% 11%);\n --ra-surface: var(--card, 0 0% 100%);\n --ra-border: var(--border, 220 13% 91%);\n --ra-text: var(--foreground, 222 47% 11%);\n --ra-muted: var(--muted, 220 14% 96%);\n --ra-muted-text: var(--muted-foreground, 220 9% 46%);\n --ra-radius: var(--radius, 0.625rem);\n --ra-dot-size: 0.5rem;\n --ra-page-bg: var(--background, 220 14% 98%);\n --ra-card-shadow: 0 1px 2px hsl(var(--ra-accent) / 0.04), 0 4px 12px hsl(var(--ra-accent) / 0.05);\n --ra-card-shadow-hover: 0 2px 4px hsl(var(--ra-accent) / 0.06), 0 8px 24px hsl(var(--ra-accent) / 0.08);\n --ra-row-hover: hsl(var(--ra-accent) / 0.05);\n --ra-row-active-bg: hsl(var(--ra-accent) / 0.10);\n --ra-row-active-bd: hsl(var(--ra-accent) / 0.45);\n --ra-focus-ring: hsl(var(--ra-accent) / 0.35);\n --ra-font-display: var(--font-display, var(--font-sans, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif));\n --ra-font-ui: var(--font-sans, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif);\n --ra-title-weight: 600;\n --ra-display-weight: 700;\n --ra-info: var(--ra-blue, 214 95% 55%);\n --ra-success: var(--ra-emerald, 142 71% 45%);\n --ra-warning: var(--ra-amber, 38 92% 50%);\n --ra-danger: var(--destructive, 0 72% 51%);\n}\n.ra-status-dot {\n display: inline-block;\n width: var(--ra-dot-size);\n height: var(--ra-dot-size);\n border-radius: 9999px;\n flex-shrink: 0;\n}\n.ra-status-own {\n background: hsl(var(--ra-status-own));\n}\n.ra-status-shared {\n background: hsl(var(--ra-status-shared));\n}\n.ra-status-missing {\n background: hsl(var(--ra-status-missing) / 0.4);\n border: 1px solid hsl(var(--ra-status-missing) / 0.6);\n}\n.ra-row-active {\n background: var(--ra-row-active-bg);\n border-color: var(--ra-row-active-bd) !important;\n}\n');
2986
3347
 
2987
3348
  // src/components/RecordsAdmin/shell/shell.css
2988
- styleInject(".ra-shell {\n color: hsl(var(--ra-text));\n background: hsl(var(--ra-page-bg));\n font-family: var(--ra-font-ui);\n}\n.ra-shell *,\n.ra-shell *::before,\n.ra-shell *::after {\n box-sizing: border-box;\n}\n.ra-shell .ra-card {\n background: hsl(var(--ra-surface));\n border: 1px solid hsl(var(--ra-border));\n border-radius: var(--ra-radius);\n box-shadow: var(--ra-card-shadow);\n}\n.ra-shell .ra-card-hover {\n transition:\n box-shadow .18s ease,\n transform .18s ease,\n border-color .18s ease;\n}\n.ra-shell .ra-card-hover:hover {\n box-shadow: var(--ra-card-shadow-hover);\n}\n.ra-shell .ra-display {\n font-family: var(--ra-font-display);\n font-weight: var(--ra-display-weight);\n letter-spacing: -0.01em;\n}\n.ra-shell .ra-title {\n font-weight: var(--ra-title-weight);\n}\n.ra-shell :where(button, [role=button], input, select, textarea, a):focus-visible {\n outline: none;\n box-shadow: 0 0 0 3px var(--ra-focus-ring);\n border-radius: calc(var(--ra-radius) * 0.6);\n}\n.ra-shell .ra-header {\n position: relative;\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: 0.65rem 0.9rem;\n border-radius: var(--ra-radius);\n border: 1px solid hsl(var(--ra-accent) / 0.12);\n background:\n linear-gradient(\n 135deg,\n hsl(var(--ra-accent) / 0.08),\n hsl(var(--ra-accent) / 0.02) 60%,\n hsl(var(--ra-surface)) 100%);\n box-shadow: var(--ra-card-shadow);\n}\n.ra-shell .ra-header__main {\n flex: 1;\n min-width: 0;\n display: flex;\n align-items: center;\n gap: 0.625rem;\n}\n.ra-shell .ra-header-aside {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n flex-shrink: 0;\n}\n.ra-shell .ra-header-icon {\n flex-shrink: 0;\n width: 2rem;\n height: 2rem;\n border-radius: calc(var(--ra-radius) * 0.9);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: hsl(var(--ra-accent) / 0.12);\n color: hsl(var(--ra-accent));\n border: 1px solid hsl(var(--ra-accent) / 0.18);\n}\n.ra-shell .ra-header-text {\n flex: 1;\n min-width: 0;\n}\n.ra-shell .ra-header-title {\n font-family: var(--ra-font-display);\n font-weight: var(--ra-display-weight);\n font-size: 1rem;\n line-height: 1.2;\n color: hsl(var(--ra-text));\n letter-spacing: -0.01em;\n margin: 0;\n}\n.ra-shell .ra-header-subtitle {\n font-size: 0.75rem;\n color: hsl(var(--ra-muted-text));\n margin-top: 0.125rem;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ra-shell .ra-header-stats {\n display: flex;\n align-items: stretch;\n gap: 0.15rem;\n padding: 0.15rem 0.4rem;\n border-radius: calc(var(--ra-radius) * 0.75);\n background: hsl(var(--ra-surface) / 0.7);\n border: 1px solid hsl(var(--ra-border));\n}\n.ra-shell .ra-header-stats--titled {\n flex-direction: column;\n align-items: stretch;\n padding: 0.4rem 0.55rem;\n gap: 0.3rem;\n}\n.ra-shell .ra-header-stats .ra-stats-items {\n display: flex;\n align-items: stretch;\n gap: 0.15rem;\n}\n.ra-shell .ra-header-stats .ra-stats-heading {\n display: flex;\n align-items: center;\n gap: 0.35rem;\n color: hsl(var(--ra-muted-text));\n font-size: 0.65rem;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n}\n.ra-shell .ra-header-stats .ra-stats-heading-icon {\n display: inline-flex;\n align-items: center;\n color: hsl(var(--ra-text));\n opacity: 0.75;\n}\n.ra-shell .ra-header-stats .ra-stats-heading-icon > svg {\n width: 0.85rem;\n height: 0.85rem;\n}\n.ra-shell .ra-stat {\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 0.15rem 0.45rem;\n min-width: 2.5rem;\n}\n.ra-shell .ra-stat-value {\n font-family: var(--ra-font-display);\n font-weight: var(--ra-display-weight);\n font-size: 0.85rem;\n color: hsl(var(--ra-text));\n line-height: 1;\n}\n.ra-shell .ra-stat-label {\n font-size: 0.6rem;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: hsl(var(--ra-muted-text));\n margin-top: 0.15rem;\n}\n.ra-shell .ra-stat-divider {\n width: 1px;\n background: hsl(var(--ra-border));\n margin: 0.25rem 0;\n}\n.ra-shell .ra-header-actions {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n.ra-shell .ra-tabs {\n display: flex;\n gap: 0.25rem;\n padding: 0.25rem;\n background: hsl(var(--ra-muted));\n border-radius: calc(var(--ra-radius) * 0.85);\n border: 1px solid hsl(var(--ra-border));\n}\n.ra-shell .ra-tab {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n padding: 0.4rem 0.7rem;\n border-radius: calc(var(--ra-radius) * 0.65);\n font-size: 0.78rem;\n font-weight: 500;\n color: hsl(var(--ra-muted-text));\n background: transparent;\n border: 0;\n cursor: pointer;\n transition:\n background .15s ease,\n color .15s ease,\n transform .15s ease;\n white-space: nowrap;\n}\n.ra-shell .ra-tab:hover {\n background: hsl(var(--ra-surface));\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-tab[aria-selected=true] {\n background: hsl(var(--ra-surface));\n color: hsl(var(--ra-text));\n box-shadow: var(--ra-card-shadow);\n font-weight: var(--ra-title-weight);\n}\n.ra-shell .ra-tab[aria-selected=true] .ra-tab-icon {\n color: hsl(var(--ra-accent));\n}\n.ra-shell .ra-tab[disabled] {\n opacity: .5;\n cursor: not-allowed;\n}\n.ra-shell .ra-tab-count {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 1.25rem;\n padding: 0 0.35rem;\n height: 1.1rem;\n border-radius: 999px;\n background: hsl(var(--ra-accent) / 0.12);\n color: hsl(var(--ra-accent));\n font-size: 0.625rem;\n font-weight: 600;\n line-height: 1;\n}\n.ra-shell .ra-tab[aria-selected=false] .ra-tab-count {\n background: hsl(var(--ra-muted-text) / 0.15);\n color: hsl(var(--ra-muted-text));\n}\n.ra-shell[data-density=compact] .ra-row {\n padding-block: 0.4rem;\n}\n.ra-shell[data-density=compact] .ra-header {\n padding: 0.75rem 1rem;\n}\n.ra-shell[data-density=compact] .ra-header-icon {\n width: 2.25rem;\n height: 2.25rem;\n}\n.ra-shell .ra-row {\n display: flex;\n align-items: center;\n gap: 0.65rem;\n width: 100%;\n text-align: left;\n padding: 0.65rem 0.85rem;\n border-left: 3px solid transparent;\n background: transparent;\n border-bottom: 1px solid transparent;\n transition: background .12s ease, border-color .12s ease;\n cursor: pointer;\n color: hsl(var(--ra-text));\n font-family: inherit;\n}\n.ra-shell .ra-row + .ra-row {\n border-top: 1px solid hsl(var(--ra-border) / 0.6);\n}\n.ra-shell .ra-row:hover {\n background: var(--ra-row-hover);\n}\n.ra-shell .ra-row[data-selected=true] {\n background: var(--ra-row-active-bg);\n border-left-color: var(--ra-row-active-bd);\n}\n.ra-shell .ra-row-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1.75rem;\n height: 1.75rem;\n border-radius: calc(var(--ra-radius) * 0.6);\n background: hsl(var(--ra-muted));\n color: hsl(var(--ra-muted-text));\n flex-shrink: 0;\n}\n.ra-shell .ra-row[data-selected=true] .ra-row-icon {\n background: hsl(var(--ra-accent) / 0.15);\n color: hsl(var(--ra-accent));\n}\n.ra-shell .ra-row-body {\n flex: 1;\n min-width: 0;\n}\n.ra-shell .ra-row-title {\n font-weight: var(--ra-title-weight);\n font-size: 0.875rem;\n line-height: 1.25;\n color: hsl(var(--ra-text));\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ra-shell .ra-row-sub {\n font-size: 0.75rem;\n color: hsl(var(--ra-muted-text));\n margin-top: 0.15rem;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ra-shell .ra-row-actions {\n display: inline-flex;\n align-items: center;\n gap: 0.15rem;\n margin-left: auto;\n opacity: 0;\n transition: opacity .15s ease;\n}\n.ra-shell .ra-row:hover .ra-row-actions,\n.ra-shell .ra-row:focus-within .ra-row-actions {\n opacity: 1;\n}\n.ra-shell .ra-row-action {\n width: 1.6rem;\n height: 1.6rem;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: 999px;\n background: transparent;\n color: hsl(var(--ra-muted-text));\n border: 0;\n cursor: pointer;\n transition: background .15s ease, color .15s ease;\n}\n.ra-shell .ra-row-action:hover {\n background: hsl(var(--ra-accent) / 0.10);\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-row-action[data-tone=danger]:hover {\n background: hsl(var(--ra-danger) / 0.12);\n color: hsl(var(--ra-danger));\n}\n.ra-shell .ra-chip {\n display: inline-flex;\n align-items: center;\n gap: 0.3rem;\n padding: 0.15rem 0.5rem;\n border-radius: 999px;\n font-size: 0.6875rem;\n font-weight: 500;\n background: hsl(var(--ra-muted));\n color: hsl(var(--ra-muted-text));\n border: 1px solid hsl(var(--ra-border));\n white-space: nowrap;\n max-width: 14rem;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ra-shell .ra-chip[data-tone=success] {\n background: hsl(var(--ra-success) / 0.12);\n color: hsl(var(--ra-success));\n border-color: hsl(var(--ra-success) / 0.30);\n}\n.ra-shell .ra-chip[data-tone=warning] {\n background: hsl(var(--ra-warning) / 0.14);\n color: hsl(var(--ra-warning));\n border-color: hsl(var(--ra-warning) / 0.35);\n}\n.ra-shell .ra-chip[data-tone=info] {\n background: hsl(var(--ra-info) / 0.10);\n color: hsl(var(--ra-info));\n border-color: hsl(var(--ra-info) / 0.30);\n}\n.ra-shell .ra-chip[data-tone=danger] {\n background: hsl(var(--ra-danger) / 0.10);\n color: hsl(var(--ra-danger));\n border-color: hsl(var(--ra-danger) / 0.30);\n}\n.ra-shell .ra-chip[data-tone=muted] {\n background: transparent;\n color: hsl(var(--ra-muted-text));\n border-style: dashed;\n}\n.ra-shell .ra-group {\n border-bottom: 1px solid hsl(var(--ra-border));\n}\n.ra-shell .ra-group:last-child {\n border-bottom: 0;\n}\n.ra-shell .ra-group-summary {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n width: 100%;\n padding: 0.5rem 0.85rem;\n background: hsl(var(--ra-muted) / 0.6);\n font-size: 0.7rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: hsl(var(--ra-muted-text));\n border: 0;\n cursor: pointer;\n transition: background .12s ease;\n}\n.ra-shell .ra-group-summary:hover {\n background: hsl(var(--ra-muted));\n}\n.ra-shell .ra-group-summary .ra-group-chevron {\n transition: transform .15s ease;\n}\n.ra-shell .ra-group[data-open=false] .ra-group-chevron {\n transform: rotate(-90deg);\n}\n.ra-shell .ra-group-name {\n flex: 1;\n text-align: left;\n}\n.ra-shell .ra-group-count {\n font-size: 0.65rem;\n font-weight: 600;\n color: hsl(var(--ra-muted-text));\n background: hsl(var(--ra-surface));\n border: 1px solid hsl(var(--ra-border));\n border-radius: 999px;\n padding: 0.05rem 0.4rem;\n}\n.ra-shell .ra-group[data-open=false] .ra-group-body {\n display: none;\n}\n.ra-shell .ra-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n padding: 2.5rem 1.5rem;\n gap: 0.75rem;\n}\n.ra-shell .ra-empty-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 3.25rem;\n height: 3.25rem;\n border-radius: 999px;\n background: hsl(var(--ra-accent) / 0.08);\n color: hsl(var(--ra-accent));\n margin-bottom: 0.25rem;\n}\n.ra-shell .ra-empty-title {\n font-family: var(--ra-font-display);\n font-weight: var(--ra-display-weight);\n font-size: 1rem;\n color: hsl(var(--ra-text));\n margin: 0;\n letter-spacing: -0.01em;\n}\n.ra-shell .ra-empty-body {\n font-size: 0.8125rem;\n color: hsl(var(--ra-muted-text));\n max-width: 22rem;\n line-height: 1.45;\n}\n.ra-shell .ra-empty-actions {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n margin-top: 0.25rem;\n flex-wrap: wrap;\n justify-content: center;\n}\n.ra-shell .ra-btn {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n padding: 0.45rem 0.85rem;\n border-radius: calc(var(--ra-radius) * 0.7);\n font-size: 0.8125rem;\n font-weight: 500;\n border: 1px solid hsl(var(--ra-border));\n background: hsl(var(--ra-surface));\n color: hsl(var(--ra-text));\n cursor: pointer;\n transition:\n background .15s ease,\n border-color .15s ease,\n box-shadow .15s ease,\n transform .1s ease;\n}\n.ra-shell .ra-btn:hover {\n background: hsl(var(--ra-muted));\n box-shadow: var(--ra-card-shadow);\n}\n.ra-shell .ra-btn:active {\n transform: translateY(1px);\n}\n.ra-shell .ra-btn[data-variant=primary] {\n background: hsl(var(--ra-accent));\n color: hsl(var(--ra-surface));\n border-color: hsl(var(--ra-accent));\n}\n.ra-shell .ra-btn[data-variant=primary]:hover {\n background: hsl(var(--ra-accent) / 0.92);\n}\n.ra-shell .ra-btn[data-variant=ghost] {\n background: transparent;\n border-color: transparent;\n color: hsl(var(--ra-muted-text));\n}\n.ra-shell .ra-btn[data-variant=ghost]:hover {\n background: hsl(var(--ra-muted));\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-btn[data-variant=danger] {\n color: hsl(var(--ra-danger));\n}\n.ra-shell .ra-btn[data-variant=danger]:hover {\n background: hsl(var(--ra-danger) / 0.10);\n border-color: hsl(var(--ra-danger) / 0.40);\n}\n.ra-shell .ra-intro {\n position: relative;\n display: flex;\n gap: 0.85rem;\n padding: 0.9rem 1rem;\n border-radius: var(--ra-radius);\n border: 1px solid hsl(var(--ra-info) / 0.30);\n background: hsl(var(--ra-info) / 0.08);\n margin-bottom: 1rem;\n}\n.ra-shell .ra-intro[data-tone=success] {\n border-color: hsl(var(--ra-success) / 0.30);\n background: hsl(var(--ra-success) / 0.08);\n}\n.ra-shell .ra-intro[data-tone=warning] {\n border-color: hsl(var(--ra-warning) / 0.35);\n background: hsl(var(--ra-warning) / 0.10);\n}\n.ra-shell .ra-intro-icon {\n flex-shrink: 0;\n width: 2rem;\n height: 2rem;\n border-radius: 999px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: hsl(var(--ra-info) / 0.18);\n color: hsl(var(--ra-info));\n}\n.ra-shell .ra-intro[data-tone=success] .ra-intro-icon {\n background: hsl(var(--ra-success) / 0.18);\n color: hsl(var(--ra-success));\n}\n.ra-shell .ra-intro[data-tone=warning] .ra-intro-icon {\n background: hsl(var(--ra-warning) / 0.20);\n color: hsl(var(--ra-warning));\n}\n.ra-shell .ra-intro-body {\n flex: 1;\n min-width: 0;\n}\n.ra-shell .ra-intro-title {\n font-family: var(--ra-font-display);\n font-weight: var(--ra-title-weight);\n font-size: 0.875rem;\n color: hsl(var(--ra-text));\n margin: 0 0 0.2rem 0;\n}\n.ra-shell .ra-intro-text {\n font-size: 0.8125rem;\n color: hsl(var(--ra-text) / 0.85);\n line-height: 1.45;\n}\n.ra-shell .ra-intro-dismiss {\n position: absolute;\n top: 0.5rem;\n right: 0.5rem;\n width: 1.6rem;\n height: 1.6rem;\n border-radius: 999px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: 0;\n color: hsl(var(--ra-muted-text));\n cursor: pointer;\n}\n.ra-shell .ra-intro-dismiss:hover {\n background: hsl(var(--ra-text) / 0.06);\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-bulk-menu {\n min-width: 12rem;\n background: hsl(var(--ra-surface));\n border: 1px solid hsl(var(--ra-border));\n border-radius: calc(var(--ra-radius) * 0.85);\n box-shadow: var(--ra-card-shadow-hover);\n padding: 0.3rem;\n z-index: 60;\n}\n.ra-shell .ra-bulk-item {\n display: flex;\n align-items: center;\n gap: 0.55rem;\n width: 100%;\n padding: 0.45rem 0.6rem;\n border-radius: calc(var(--ra-radius) * 0.6);\n font-size: 0.8125rem;\n color: hsl(var(--ra-text));\n background: transparent;\n border: 0;\n cursor: pointer;\n text-align: left;\n transition: background .12s ease, color .12s ease;\n}\n.ra-shell .ra-bulk-item:hover {\n background: hsl(var(--ra-muted));\n}\n.ra-shell .ra-bulk-item[data-tone=danger] {\n color: hsl(var(--ra-danger));\n}\n.ra-shell .ra-bulk-item[data-tone=danger]:hover {\n background: hsl(var(--ra-danger) / 0.10);\n}\n.ra-shell .ra-bulk-divider {\n height: 1px;\n background: hsl(var(--ra-border));\n margin: 0.25rem 0;\n}\n.ra-shell .ra-preview-rail {\n background: hsl(var(--ra-surface));\n border-left: 1px solid hsl(var(--ra-border));\n box-shadow: -4px 0 16px hsl(var(--ra-accent) / 0.04);\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n}\n.ra-shell .ra-preview-rail-header {\n position: sticky;\n top: 0;\n z-index: 1;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.75rem 1rem;\n background:\n linear-gradient(\n 180deg,\n hsl(var(--ra-surface)) 0%,\n hsl(var(--ra-surface) / 0.92) 100%);\n border-bottom: 1px solid hsl(var(--ra-border));\n backdrop-filter: blur(6px);\n}\n.ra-shell .ra-preview-rail-title {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n font-size: 0.7rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: hsl(var(--ra-muted-text));\n}\n.ra-shell .ra-preview-rail-body {\n flex: 1;\n overflow-y: auto;\n padding: 1rem;\n}\n.ra-confirm-root {\n position: fixed;\n inset: 0;\n z-index: 2147483000;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 1rem;\n}\n.ra-confirm-root .ra-confirm-backdrop {\n position: absolute;\n inset: 0;\n background: hsl(0 0% 0% / 0.45);\n backdrop-filter: blur(2px);\n animation: ra-confirm-fade .12s ease-out;\n}\n.ra-confirm-root .ra-confirm-card {\n position: relative;\n width: min(440px, 100%);\n background: hsl(var(--ra-surface));\n color: hsl(var(--ra-text));\n border: 1px solid hsl(var(--ra-border));\n border-radius: var(--ra-radius);\n box-shadow: 0 1px 2px hsl(0 0% 0% / 0.08), 0 24px 48px -12px hsl(0 0% 0% / 0.32);\n padding: 1.25rem;\n animation: ra-confirm-pop .14s ease-out;\n}\n.ra-confirm-root .ra-confirm-header {\n display: flex;\n align-items: center;\n gap: 0.6rem;\n margin-bottom: 0.5rem;\n}\n.ra-confirm-root .ra-confirm-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1.75rem;\n height: 1.75rem;\n border-radius: 999px;\n background: hsl(var(--ra-warning, 38 92% 50%) / 0.12);\n color: hsl(var(--ra-warning, 38 92% 50%));\n}\n.ra-confirm-root .ra-confirm-title {\n font-family: var(--ra-font-display);\n font-weight: 600;\n font-size: 1rem;\n margin: 0;\n}\n.ra-confirm-root .ra-confirm-body {\n font-size: 0.875rem;\n color: hsl(var(--ra-muted-text));\n margin: 0 0 1.1rem;\n line-height: 1.45;\n}\n.ra-confirm-root .ra-confirm-actions {\n display: flex;\n justify-content: flex-end;\n gap: 0.5rem;\n flex-wrap: wrap;\n}\n.ra-confirm-root .ra-confirm-btn {\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n border: 1px solid transparent;\n border-radius: calc(var(--ra-radius) - 2px);\n padding: 0.45rem 0.85rem;\n font-size: 0.8125rem;\n font-weight: 500;\n cursor: pointer;\n transition:\n background-color .12s ease,\n border-color .12s ease,\n color .12s ease;\n}\n.ra-confirm-root .ra-confirm-btn:focus-visible {\n outline: none;\n box-shadow: 0 0 0 3px var(--ra-focus-ring);\n}\n.ra-confirm-root .ra-confirm-btn-ghost {\n background: transparent;\n color: hsl(var(--ra-muted-text));\n border-color: hsl(var(--ra-border));\n}\n.ra-confirm-root .ra-confirm-btn-ghost:hover {\n background: hsl(var(--ra-muted));\n color: hsl(var(--ra-text));\n}\n.ra-confirm-root .ra-confirm-btn-danger {\n background: transparent;\n color: hsl(var(--ra-danger, 0 72% 51%));\n border-color: hsl(var(--ra-danger, 0 72% 51%) / 0.45);\n}\n.ra-confirm-root .ra-confirm-btn-danger:hover {\n background: hsl(var(--ra-danger, 0 72% 51%) / 0.08);\n border-color: hsl(var(--ra-danger, 0 72% 51%));\n}\n.ra-confirm-root .ra-confirm-btn-primary {\n background: hsl(var(--ra-accent));\n color: hsl(var(--ra-accent-fg, 0 0% 100%));\n border-color: hsl(var(--ra-accent));\n}\n.ra-confirm-root .ra-confirm-btn-primary:hover {\n filter: brightness(0.95);\n}\n@keyframes ra-confirm-fade {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n@keyframes ra-confirm-pop {\n from {\n opacity: 0;\n transform: translateY(4px) scale(.98);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n}\n.ra-shell .ra-unsaved-banner {\n display: flex;\n align-items: center;\n gap: 0.6rem;\n padding: 0.5rem 0.75rem;\n border: 1px solid hsl(var(--ra-warning, 38 92% 50%) / 0.35);\n background: hsl(var(--ra-warning, 38 92% 50%) / 0.08);\n border-radius: var(--ra-radius);\n font-size: 0.8125rem;\n color: hsl(var(--ra-text));\n animation: ra-unsaved-slide .14s ease-out;\n}\n.ra-shell .ra-unsaved-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: hsl(var(--ra-warning, 38 92% 50%));\n flex-shrink: 0;\n}\n.ra-shell .ra-unsaved-text {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.ra-shell .ra-unsaved-context {\n color: hsl(var(--ra-muted-text));\n font-weight: 400;\n}\n.ra-shell .ra-unsaved-error {\n color: hsl(var(--ra-danger, 0 72% 51%));\n font-size: 0.75rem;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n font-weight: 500;\n}\n.ra-shell .ra-unsaved-actions {\n display: inline-flex;\n gap: 0.4rem;\n flex-shrink: 0;\n}\n.ra-shell .ra-unsaved-btn {\n display: inline-flex;\n align-items: center;\n gap: 0.3rem;\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n border: 1px solid transparent;\n border-radius: calc(var(--ra-radius) - 2px);\n padding: 0.3rem 0.6rem;\n font-size: 0.75rem;\n font-weight: 500;\n cursor: pointer;\n transition:\n background-color .12s ease,\n border-color .12s ease,\n color .12s ease,\n opacity .12s ease;\n}\n.ra-shell .ra-unsaved-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.ra-shell .ra-unsaved-btn:focus-visible {\n outline: none;\n box-shadow: 0 0 0 3px var(--ra-focus-ring);\n}\n.ra-shell .ra-unsaved-btn-ghost {\n background: transparent;\n color: hsl(var(--ra-muted-text));\n border-color: hsl(var(--ra-border));\n}\n.ra-shell .ra-unsaved-btn-ghost:hover:not(:disabled) {\n background: hsl(var(--ra-muted));\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-unsaved-btn-primary {\n background: hsl(var(--ra-accent));\n color: hsl(var(--ra-accent-fg, 0 0% 100%));\n border-color: hsl(var(--ra-accent));\n}\n.ra-shell .ra-unsaved-btn-primary:hover:not(:disabled) {\n filter: brightness(0.95);\n}\n@keyframes ra-unsaved-slide {\n from {\n opacity: 0;\n transform: translateY(-3px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n.ra-shell .ra-clipboard-toast {\n position: fixed;\n bottom: 1.25rem;\n left: 50%;\n transform: translateX(-50%);\n z-index: 90;\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n max-width: min(28rem, calc(100vw - 2rem));\n padding: 0.55rem 0.85rem;\n border-radius: 999px;\n background: hsl(var(--ra-text));\n color: hsl(var(--ra-surface));\n font-size: 0.75rem;\n line-height: 1;\n box-shadow: 0 8px 24px -10px hsl(0 0% 0% / 0.45);\n animation: ra-clipboard-pop 0.18s ease-out both;\n pointer-events: none;\n}\n@keyframes ra-clipboard-pop {\n from {\n opacity: 0;\n transform: translate(-50%, 6px);\n }\n to {\n opacity: 1;\n transform: translate(-50%, 0);\n }\n}\n.ra-shell .ra-row-menu-wrap {\n display: inline-flex;\n align-items: center;\n margin-left: 0.25rem;\n}\n.ra-shell .ra-row-menu-trigger {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1.5rem;\n height: 1.5rem;\n border-radius: 0.35rem;\n background: transparent;\n color: hsl(var(--ra-muted-text));\n opacity: 0;\n transition:\n opacity .15s ease,\n background .15s ease,\n color .15s ease;\n border: 1px solid transparent;\n}\n.ra-shell .ra-row:hover .ra-row-menu-trigger,\n.ra-shell .ra-card-hover:hover .ra-row-menu-trigger,\n.ra-shell .ra-row-menu-trigger:focus-visible,\n.ra-shell .ra-row-menu-trigger[aria-expanded=true] {\n opacity: 1;\n}\n.ra-shell .ra-row-menu-trigger:hover {\n background: hsl(var(--ra-muted));\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-row-menu {\n position: absolute;\n right: 0;\n top: calc(100% + 4px);\n z-index: 50;\n min-width: 11rem;\n padding: 0.25rem;\n border-radius: 0.5rem;\n background: hsl(var(--ra-surface));\n border: 1px solid hsl(var(--ra-border));\n box-shadow: 0 12px 28px -10px hsl(0 0% 0% / 0.25);\n display: flex;\n flex-direction: column;\n gap: 0.125rem;\n}\n.ra-shell .ra-row-menu-item {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.4rem 0.55rem;\n border-radius: 0.35rem;\n font-size: 0.75rem;\n color: hsl(var(--ra-text));\n background: transparent;\n border: 0;\n text-align: left;\n width: 100%;\n cursor: pointer;\n}\n.ra-shell .ra-row-menu-item:hover:not(:disabled) {\n background: hsl(var(--ra-muted));\n}\n.ra-shell .ra-row-menu-item:disabled {\n opacity: 0.45;\n cursor: not-allowed;\n}\n");
3349
+ styleInject(".ra-shell {\n color: hsl(var(--ra-text));\n background: hsl(var(--ra-page-bg));\n font-family: var(--ra-font-ui);\n}\n.ra-shell *,\n.ra-shell *::before,\n.ra-shell *::after {\n box-sizing: border-box;\n}\n.ra-shell .ra-card {\n background: hsl(var(--ra-surface));\n border: 1px solid hsl(var(--ra-border));\n border-radius: var(--ra-radius);\n box-shadow: var(--ra-card-shadow);\n}\n.ra-shell .ra-card-hover {\n transition:\n box-shadow .18s ease,\n transform .18s ease,\n border-color .18s ease;\n}\n.ra-shell .ra-card-hover:hover {\n box-shadow: var(--ra-card-shadow-hover);\n}\n.ra-shell .ra-display {\n font-family: var(--ra-font-display);\n font-weight: var(--ra-display-weight);\n letter-spacing: -0.01em;\n}\n.ra-shell .ra-title {\n font-weight: var(--ra-title-weight);\n}\n.ra-shell :where(button, [role=button], input, select, textarea, a):focus-visible {\n outline: none;\n box-shadow: 0 0 0 3px var(--ra-focus-ring);\n border-radius: calc(var(--ra-radius) * 0.6);\n}\n.ra-shell .ra-header {\n position: relative;\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: 0.65rem 0.9rem;\n border-radius: var(--ra-radius);\n border: 1px solid hsl(var(--ra-accent) / 0.12);\n background:\n linear-gradient(\n 135deg,\n hsl(var(--ra-accent) / 0.08),\n hsl(var(--ra-accent) / 0.02) 60%,\n hsl(var(--ra-surface)) 100%);\n box-shadow: var(--ra-card-shadow);\n}\n.ra-shell .ra-header__main {\n flex: 1;\n min-width: 0;\n display: flex;\n align-items: center;\n gap: 0.625rem;\n}\n.ra-shell .ra-header-aside {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n flex-shrink: 0;\n}\n.ra-shell .ra-header-icon {\n flex-shrink: 0;\n width: 2rem;\n height: 2rem;\n border-radius: calc(var(--ra-radius) * 0.9);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: hsl(var(--ra-accent) / 0.12);\n color: hsl(var(--ra-accent));\n border: 1px solid hsl(var(--ra-accent) / 0.18);\n}\n.ra-shell .ra-header-text {\n flex: 1;\n min-width: 0;\n}\n.ra-shell .ra-header-title {\n font-family: var(--ra-font-display);\n font-weight: var(--ra-display-weight);\n font-size: 1rem;\n line-height: 1.2;\n color: hsl(var(--ra-text));\n letter-spacing: -0.01em;\n margin: 0;\n}\n.ra-shell .ra-header-subtitle {\n font-size: 0.75rem;\n color: hsl(var(--ra-muted-text));\n margin-top: 0.125rem;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ra-shell .ra-header-stats {\n display: flex;\n align-items: stretch;\n gap: 0.15rem;\n padding: 0.15rem 0.4rem;\n border-radius: calc(var(--ra-radius) * 0.75);\n background: hsl(var(--ra-surface) / 0.7);\n border: 1px solid hsl(var(--ra-border));\n}\n.ra-shell .ra-header-stats--titled {\n flex-direction: column;\n align-items: stretch;\n padding: 0.4rem 0.55rem;\n gap: 0.3rem;\n}\n.ra-shell .ra-header-stats .ra-stats-items {\n display: flex;\n align-items: stretch;\n gap: 0.15rem;\n}\n.ra-shell .ra-header-stats .ra-stats-heading {\n display: flex;\n align-items: center;\n gap: 0.35rem;\n color: hsl(var(--ra-muted-text));\n font-size: 0.65rem;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n}\n.ra-shell .ra-header-stats .ra-stats-heading-icon {\n display: inline-flex;\n align-items: center;\n color: hsl(var(--ra-text));\n opacity: 0.75;\n}\n.ra-shell .ra-header-stats .ra-stats-heading-icon > svg {\n width: 0.85rem;\n height: 0.85rem;\n}\n.ra-shell .ra-stat {\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 0.15rem 0.45rem;\n min-width: 2.5rem;\n}\n.ra-shell .ra-stat-value {\n font-family: var(--ra-font-display);\n font-weight: var(--ra-display-weight);\n font-size: 0.85rem;\n color: hsl(var(--ra-text));\n line-height: 1;\n}\n.ra-shell .ra-stat-label {\n font-size: 0.6rem;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: hsl(var(--ra-muted-text));\n margin-top: 0.15rem;\n}\n.ra-shell .ra-stat-divider {\n width: 1px;\n background: hsl(var(--ra-border));\n margin: 0.25rem 0;\n}\n.ra-shell .ra-header-actions {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n.ra-shell .ra-tabs {\n display: flex;\n gap: 0.25rem;\n padding: 0.25rem;\n background: hsl(var(--ra-muted));\n border-radius: calc(var(--ra-radius) * 0.85);\n border: 1px solid hsl(var(--ra-border));\n}\n.ra-shell .ra-tab {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n padding: 0.4rem 0.7rem;\n border-radius: calc(var(--ra-radius) * 0.65);\n font-size: 0.78rem;\n font-weight: 500;\n color: hsl(var(--ra-muted-text));\n background: transparent;\n border: 0;\n cursor: pointer;\n transition:\n background .15s ease,\n color .15s ease,\n transform .15s ease;\n white-space: nowrap;\n}\n.ra-shell .ra-tab:hover {\n background: hsl(var(--ra-surface));\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-tab[aria-selected=true] {\n background: hsl(var(--ra-surface));\n color: hsl(var(--ra-text));\n box-shadow: var(--ra-card-shadow);\n font-weight: var(--ra-title-weight);\n}\n.ra-shell .ra-tab[aria-selected=true] .ra-tab-icon {\n color: hsl(var(--ra-accent));\n}\n.ra-shell .ra-tab[disabled] {\n opacity: .5;\n cursor: not-allowed;\n}\n.ra-shell .ra-tab-count {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 1.25rem;\n padding: 0 0.35rem;\n height: 1.1rem;\n border-radius: 999px;\n background: hsl(var(--ra-accent) / 0.12);\n color: hsl(var(--ra-accent));\n font-size: 0.625rem;\n font-weight: 600;\n line-height: 1;\n}\n.ra-shell .ra-tab[aria-selected=false] .ra-tab-count {\n background: hsl(var(--ra-muted-text) / 0.15);\n color: hsl(var(--ra-muted-text));\n}\n.ra-shell[data-density=compact] .ra-row {\n padding-block: 0.4rem;\n}\n.ra-shell[data-density=compact] .ra-header {\n padding: 0.75rem 1rem;\n}\n.ra-shell[data-density=compact] .ra-header-icon {\n width: 2.25rem;\n height: 2.25rem;\n}\n.ra-shell .ra-row {\n display: flex;\n align-items: center;\n gap: 0.65rem;\n width: 100%;\n text-align: left;\n padding: 0.65rem 0.85rem;\n border-left: 3px solid transparent;\n background: transparent;\n border-bottom: 1px solid transparent;\n transition: background .12s ease, border-color .12s ease;\n cursor: pointer;\n color: hsl(var(--ra-text));\n font-family: inherit;\n}\n.ra-shell .ra-row + .ra-row {\n border-top: 1px solid hsl(var(--ra-border) / 0.6);\n}\n.ra-shell .ra-row:hover {\n background: var(--ra-row-hover);\n}\n.ra-shell .ra-row[data-selected=true] {\n background: var(--ra-row-active-bg);\n border-left-color: var(--ra-row-active-bd);\n}\n.ra-shell .ra-row-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1.75rem;\n height: 1.75rem;\n border-radius: calc(var(--ra-radius) * 0.6);\n background: hsl(var(--ra-muted));\n color: hsl(var(--ra-muted-text));\n flex-shrink: 0;\n}\n.ra-shell .ra-row[data-selected=true] .ra-row-icon {\n background: hsl(var(--ra-accent) / 0.15);\n color: hsl(var(--ra-accent));\n}\n.ra-shell .ra-row-body {\n flex: 1;\n min-width: 0;\n}\n.ra-shell .ra-row-title {\n font-weight: var(--ra-title-weight);\n font-size: 0.875rem;\n line-height: 1.25;\n color: hsl(var(--ra-text));\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ra-shell .ra-row-sub {\n font-size: 0.75rem;\n color: hsl(var(--ra-muted-text));\n margin-top: 0.15rem;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ra-shell .ra-row-actions {\n display: inline-flex;\n align-items: center;\n gap: 0.15rem;\n margin-left: auto;\n opacity: 0;\n transition: opacity .15s ease;\n}\n.ra-shell .ra-row:hover .ra-row-actions,\n.ra-shell .ra-row:focus-within .ra-row-actions {\n opacity: 1;\n}\n.ra-shell .ra-row-action {\n width: 1.6rem;\n height: 1.6rem;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: 999px;\n background: transparent;\n color: hsl(var(--ra-muted-text));\n border: 0;\n cursor: pointer;\n transition: background .15s ease, color .15s ease;\n}\n.ra-shell .ra-row-action:hover {\n background: hsl(var(--ra-accent) / 0.10);\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-row-action[data-tone=danger]:hover {\n background: hsl(var(--ra-danger) / 0.12);\n color: hsl(var(--ra-danger));\n}\n.ra-shell .ra-chip {\n display: inline-flex;\n align-items: center;\n gap: 0.3rem;\n padding: 0.15rem 0.5rem;\n border-radius: 999px;\n font-size: 0.6875rem;\n font-weight: 500;\n background: hsl(var(--ra-muted));\n color: hsl(var(--ra-muted-text));\n border: 1px solid hsl(var(--ra-border));\n white-space: nowrap;\n max-width: 14rem;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ra-shell .ra-chip[data-tone=success] {\n background: hsl(var(--ra-success) / 0.12);\n color: hsl(var(--ra-success));\n border-color: hsl(var(--ra-success) / 0.30);\n}\n.ra-shell .ra-chip[data-tone=warning] {\n background: hsl(var(--ra-warning) / 0.14);\n color: hsl(var(--ra-warning));\n border-color: hsl(var(--ra-warning) / 0.35);\n}\n.ra-shell .ra-chip[data-tone=info] {\n background: hsl(var(--ra-info) / 0.10);\n color: hsl(var(--ra-info));\n border-color: hsl(var(--ra-info) / 0.30);\n}\n.ra-shell .ra-chip[data-tone=danger] {\n background: hsl(var(--ra-danger) / 0.10);\n color: hsl(var(--ra-danger));\n border-color: hsl(var(--ra-danger) / 0.30);\n}\n.ra-shell .ra-chip[data-tone=muted] {\n background: transparent;\n color: hsl(var(--ra-muted-text));\n border-style: dashed;\n}\n.ra-shell .ra-group {\n border-bottom: 1px solid hsl(var(--ra-border));\n}\n.ra-shell .ra-group:last-child {\n border-bottom: 0;\n}\n.ra-shell .ra-group-summary {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n width: 100%;\n padding: 0.5rem 0.85rem;\n background: hsl(var(--ra-muted) / 0.6);\n font-size: 0.7rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: hsl(var(--ra-muted-text));\n border: 0;\n cursor: pointer;\n transition: background .12s ease;\n}\n.ra-shell .ra-group-summary:hover {\n background: hsl(var(--ra-muted));\n}\n.ra-shell .ra-group-summary .ra-group-chevron {\n transition: transform .15s ease;\n}\n.ra-shell .ra-group[data-open=false] .ra-group-chevron {\n transform: rotate(-90deg);\n}\n.ra-shell .ra-group-name {\n flex: 1;\n text-align: left;\n}\n.ra-shell .ra-group-count {\n font-size: 0.65rem;\n font-weight: 600;\n color: hsl(var(--ra-muted-text));\n background: hsl(var(--ra-surface));\n border: 1px solid hsl(var(--ra-border));\n border-radius: 999px;\n padding: 0.05rem 0.4rem;\n}\n.ra-shell .ra-group[data-open=false] .ra-group-body {\n display: none;\n}\n.ra-shell .ra-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n padding: 2.5rem 1.5rem;\n gap: 0.75rem;\n}\n.ra-shell .ra-empty-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 3.25rem;\n height: 3.25rem;\n border-radius: 999px;\n background: hsl(var(--ra-accent) / 0.08);\n color: hsl(var(--ra-accent));\n margin-bottom: 0.25rem;\n}\n.ra-shell .ra-empty-title {\n font-family: var(--ra-font-display);\n font-weight: var(--ra-display-weight);\n font-size: 1rem;\n color: hsl(var(--ra-text));\n margin: 0;\n letter-spacing: -0.01em;\n}\n.ra-shell .ra-empty-body {\n font-size: 0.8125rem;\n color: hsl(var(--ra-muted-text));\n max-width: 22rem;\n line-height: 1.45;\n}\n.ra-shell .ra-empty-actions {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n margin-top: 0.25rem;\n flex-wrap: wrap;\n justify-content: center;\n}\n.ra-shell .ra-btn {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n padding: 0.45rem 0.85rem;\n border-radius: calc(var(--ra-radius) * 0.7);\n font-size: 0.8125rem;\n font-weight: 500;\n border: 1px solid hsl(var(--ra-border));\n background: hsl(var(--ra-surface));\n color: hsl(var(--ra-text));\n cursor: pointer;\n transition:\n background .15s ease,\n border-color .15s ease,\n box-shadow .15s ease,\n transform .1s ease;\n}\n.ra-shell .ra-btn:hover {\n background: hsl(var(--ra-muted));\n box-shadow: var(--ra-card-shadow);\n}\n.ra-shell .ra-btn:active {\n transform: translateY(1px);\n}\n.ra-shell .ra-btn[data-variant=primary] {\n background: hsl(var(--ra-accent));\n color: hsl(var(--ra-surface));\n border-color: hsl(var(--ra-accent));\n}\n.ra-shell .ra-btn[data-variant=primary]:hover {\n background: hsl(var(--ra-accent) / 0.92);\n}\n.ra-shell .ra-btn[data-variant=ghost] {\n background: transparent;\n border-color: transparent;\n color: hsl(var(--ra-muted-text));\n}\n.ra-shell .ra-btn[data-variant=ghost]:hover {\n background: hsl(var(--ra-muted));\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-btn[data-variant=danger] {\n color: hsl(var(--ra-danger));\n}\n.ra-shell .ra-btn[data-variant=danger]:hover {\n background: hsl(var(--ra-danger) / 0.10);\n border-color: hsl(var(--ra-danger) / 0.40);\n}\n.ra-shell .ra-intro {\n position: relative;\n display: flex;\n gap: 0.85rem;\n padding: 0.9rem 1rem;\n border-radius: var(--ra-radius);\n border: 1px solid hsl(var(--ra-info) / 0.30);\n background: hsl(var(--ra-info) / 0.08);\n margin-bottom: 1rem;\n}\n.ra-shell .ra-intro[data-tone=success] {\n border-color: hsl(var(--ra-success) / 0.30);\n background: hsl(var(--ra-success) / 0.08);\n}\n.ra-shell .ra-intro[data-tone=warning] {\n border-color: hsl(var(--ra-warning) / 0.35);\n background: hsl(var(--ra-warning) / 0.10);\n}\n.ra-shell .ra-intro-icon {\n flex-shrink: 0;\n width: 2rem;\n height: 2rem;\n border-radius: 999px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: hsl(var(--ra-info) / 0.18);\n color: hsl(var(--ra-info));\n}\n.ra-shell .ra-intro[data-tone=success] .ra-intro-icon {\n background: hsl(var(--ra-success) / 0.18);\n color: hsl(var(--ra-success));\n}\n.ra-shell .ra-intro[data-tone=warning] .ra-intro-icon {\n background: hsl(var(--ra-warning) / 0.20);\n color: hsl(var(--ra-warning));\n}\n.ra-shell .ra-intro-body {\n flex: 1;\n min-width: 0;\n}\n.ra-shell .ra-intro-title {\n font-family: var(--ra-font-display);\n font-weight: var(--ra-title-weight);\n font-size: 0.875rem;\n color: hsl(var(--ra-text));\n margin: 0 0 0.2rem 0;\n}\n.ra-shell .ra-intro-text {\n font-size: 0.8125rem;\n color: hsl(var(--ra-text) / 0.85);\n line-height: 1.45;\n}\n.ra-shell .ra-intro-dismiss {\n position: absolute;\n top: 0.5rem;\n right: 0.5rem;\n width: 1.6rem;\n height: 1.6rem;\n border-radius: 999px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: 0;\n color: hsl(var(--ra-muted-text));\n cursor: pointer;\n}\n.ra-shell .ra-intro-dismiss:hover {\n background: hsl(var(--ra-text) / 0.06);\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-bulk-menu {\n min-width: 12rem;\n background: hsl(var(--ra-surface));\n border: 1px solid hsl(var(--ra-border));\n border-radius: calc(var(--ra-radius) * 0.85);\n box-shadow: var(--ra-card-shadow-hover);\n padding: 0.3rem;\n z-index: 60;\n}\n.ra-shell .ra-bulk-item {\n display: flex;\n align-items: center;\n gap: 0.55rem;\n width: 100%;\n padding: 0.45rem 0.6rem;\n border-radius: calc(var(--ra-radius) * 0.6);\n font-size: 0.8125rem;\n color: hsl(var(--ra-text));\n background: transparent;\n border: 0;\n cursor: pointer;\n text-align: left;\n transition: background .12s ease, color .12s ease;\n}\n.ra-shell .ra-bulk-item:hover {\n background: hsl(var(--ra-muted));\n}\n.ra-shell .ra-bulk-item[data-tone=danger] {\n color: hsl(var(--ra-danger));\n}\n.ra-shell .ra-bulk-item[data-tone=danger]:hover {\n background: hsl(var(--ra-danger) / 0.10);\n}\n.ra-shell .ra-bulk-divider {\n height: 1px;\n background: hsl(var(--ra-border));\n margin: 0.25rem 0;\n}\n.ra-shell .ra-preview-rail {\n background: hsl(var(--ra-surface));\n border-left: 1px solid hsl(var(--ra-border));\n box-shadow: -4px 0 16px hsl(var(--ra-accent) / 0.04);\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n}\n.ra-shell .ra-preview-rail-header {\n position: sticky;\n top: 0;\n z-index: 1;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.75rem 1rem;\n background:\n linear-gradient(\n 180deg,\n hsl(var(--ra-surface)) 0%,\n hsl(var(--ra-surface) / 0.92) 100%);\n border-bottom: 1px solid hsl(var(--ra-border));\n backdrop-filter: blur(6px);\n}\n.ra-shell .ra-preview-rail-title {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n font-size: 0.7rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: hsl(var(--ra-muted-text));\n}\n.ra-shell .ra-preview-rail-body {\n flex: 1;\n overflow-y: auto;\n padding: 1rem;\n}\n.ra-confirm-root {\n position: fixed;\n inset: 0;\n z-index: 2147483000;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 1rem;\n}\n.ra-confirm-root .ra-confirm-backdrop {\n position: absolute;\n inset: 0;\n background: hsl(0 0% 0% / 0.45);\n backdrop-filter: blur(2px);\n animation: ra-confirm-fade .12s ease-out;\n}\n.ra-confirm-root .ra-confirm-card {\n position: relative;\n width: min(440px, 100%);\n background: hsl(var(--ra-surface));\n color: hsl(var(--ra-text));\n border: 1px solid hsl(var(--ra-border));\n border-radius: var(--ra-radius);\n box-shadow: 0 1px 2px hsl(0 0% 0% / 0.08), 0 24px 48px -12px hsl(0 0% 0% / 0.32);\n padding: 1.25rem;\n animation: ra-confirm-pop .14s ease-out;\n}\n.ra-confirm-root .ra-confirm-header {\n display: flex;\n align-items: center;\n gap: 0.6rem;\n margin-bottom: 0.5rem;\n}\n.ra-confirm-root .ra-confirm-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1.75rem;\n height: 1.75rem;\n border-radius: 999px;\n background: hsl(var(--ra-warning, 38 92% 50%) / 0.12);\n color: hsl(var(--ra-warning, 38 92% 50%));\n}\n.ra-confirm-root .ra-confirm-title {\n font-family: var(--ra-font-display);\n font-weight: 600;\n font-size: 1rem;\n margin: 0;\n}\n.ra-confirm-root .ra-confirm-body {\n font-size: 0.875rem;\n color: hsl(var(--ra-muted-text));\n margin: 0 0 1.1rem;\n line-height: 1.45;\n}\n.ra-confirm-root .ra-confirm-actions {\n display: flex;\n justify-content: flex-end;\n gap: 0.5rem;\n flex-wrap: wrap;\n}\n.ra-confirm-root .ra-confirm-btn {\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n border: 1px solid transparent;\n border-radius: calc(var(--ra-radius) - 2px);\n padding: 0.45rem 0.85rem;\n font-size: 0.8125rem;\n font-weight: 500;\n cursor: pointer;\n transition:\n background-color .12s ease,\n border-color .12s ease,\n color .12s ease;\n}\n.ra-confirm-root .ra-confirm-btn:focus-visible {\n outline: none;\n box-shadow: 0 0 0 3px var(--ra-focus-ring);\n}\n.ra-confirm-root .ra-confirm-btn-ghost {\n background: transparent;\n color: hsl(var(--ra-muted-text));\n border-color: hsl(var(--ra-border));\n}\n.ra-confirm-root .ra-confirm-btn-ghost:hover {\n background: hsl(var(--ra-muted));\n color: hsl(var(--ra-text));\n}\n.ra-confirm-root .ra-confirm-btn-danger {\n background: transparent;\n color: hsl(var(--ra-danger, 0 72% 51%));\n border-color: hsl(var(--ra-danger, 0 72% 51%) / 0.45);\n}\n.ra-confirm-root .ra-confirm-btn-danger:hover {\n background: hsl(var(--ra-danger, 0 72% 51%) / 0.08);\n border-color: hsl(var(--ra-danger, 0 72% 51%));\n}\n.ra-confirm-root .ra-confirm-btn-primary {\n background: hsl(var(--ra-accent));\n color: hsl(var(--ra-accent-fg, 0 0% 100%));\n border-color: hsl(var(--ra-accent));\n}\n.ra-confirm-root .ra-confirm-btn-primary:hover {\n filter: brightness(0.95);\n}\n@keyframes ra-confirm-fade {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n@keyframes ra-confirm-pop {\n from {\n opacity: 0;\n transform: translateY(4px) scale(.98);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n}\n.ra-shell .ra-unsaved-banner {\n display: flex;\n align-items: center;\n gap: 0.6rem;\n padding: 0.5rem 0.75rem;\n border: 1px solid hsl(var(--ra-warning, 38 92% 50%) / 0.35);\n background: hsl(var(--ra-warning, 38 92% 50%) / 0.08);\n border-radius: var(--ra-radius);\n font-size: 0.8125rem;\n color: hsl(var(--ra-text));\n animation: ra-unsaved-slide .14s ease-out;\n}\n.ra-shell .ra-unsaved-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: hsl(var(--ra-warning, 38 92% 50%));\n flex-shrink: 0;\n}\n.ra-shell .ra-unsaved-text {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.ra-shell .ra-unsaved-context {\n color: hsl(var(--ra-muted-text));\n font-weight: 400;\n}\n.ra-shell .ra-unsaved-error {\n color: hsl(var(--ra-danger, 0 72% 51%));\n font-size: 0.75rem;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n font-weight: 500;\n}\n.ra-shell .ra-unsaved-actions {\n display: inline-flex;\n gap: 0.4rem;\n flex-shrink: 0;\n}\n.ra-shell .ra-unsaved-btn {\n display: inline-flex;\n align-items: center;\n gap: 0.3rem;\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n border: 1px solid transparent;\n border-radius: calc(var(--ra-radius) - 2px);\n padding: 0.3rem 0.6rem;\n font-size: 0.75rem;\n font-weight: 500;\n cursor: pointer;\n transition:\n background-color .12s ease,\n border-color .12s ease,\n color .12s ease,\n opacity .12s ease;\n}\n.ra-shell .ra-unsaved-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.ra-shell .ra-unsaved-btn:focus-visible {\n outline: none;\n box-shadow: 0 0 0 3px var(--ra-focus-ring);\n}\n.ra-shell .ra-unsaved-btn-ghost {\n background: transparent;\n color: hsl(var(--ra-muted-text));\n border-color: hsl(var(--ra-border));\n}\n.ra-shell .ra-unsaved-btn-ghost:hover:not(:disabled) {\n background: hsl(var(--ra-muted));\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-unsaved-btn-primary {\n background: hsl(var(--ra-accent));\n color: hsl(var(--ra-accent-fg, 0 0% 100%));\n border-color: hsl(var(--ra-accent));\n}\n.ra-shell .ra-unsaved-btn-primary:hover:not(:disabled) {\n filter: brightness(0.95);\n}\n@keyframes ra-unsaved-slide {\n from {\n opacity: 0;\n transform: translateY(-3px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n.ra-shell .ra-clipboard-toast {\n position: fixed;\n bottom: 1.25rem;\n left: 50%;\n transform: translateX(-50%);\n z-index: 90;\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n max-width: min(28rem, calc(100vw - 2rem));\n padding: 0.55rem 0.85rem;\n border-radius: 999px;\n background: hsl(var(--ra-text));\n color: hsl(var(--ra-surface));\n font-size: 0.75rem;\n line-height: 1;\n box-shadow: 0 8px 24px -10px hsl(0 0% 0% / 0.45);\n animation: ra-clipboard-pop 0.18s ease-out both;\n pointer-events: none;\n}\n@keyframes ra-clipboard-pop {\n from {\n opacity: 0;\n transform: translate(-50%, 6px);\n }\n to {\n opacity: 1;\n transform: translate(-50%, 0);\n }\n}\n.ra-shell .ra-row-menu-wrap {\n display: inline-flex;\n align-items: center;\n margin-left: 0.25rem;\n}\n.ra-shell .ra-row-menu-trigger {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1.5rem;\n height: 1.5rem;\n border-radius: 0.35rem;\n background: transparent;\n color: hsl(var(--ra-muted-text));\n opacity: 0;\n transition:\n opacity .15s ease,\n background .15s ease,\n color .15s ease;\n border: 1px solid transparent;\n}\n.ra-shell .ra-row:hover .ra-row-menu-trigger,\n.ra-shell .ra-card-hover:hover .ra-row-menu-trigger,\n.ra-shell .ra-row-menu-trigger:focus-visible,\n.ra-shell .ra-row-menu-trigger[aria-expanded=true] {\n opacity: 1;\n}\n.ra-shell .ra-row-menu-trigger:hover {\n background: hsl(var(--ra-muted));\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-row-menu {\n position: absolute;\n right: 0;\n top: calc(100% + 4px);\n z-index: 50;\n min-width: 11rem;\n padding: 0.25rem;\n border-radius: 0.5rem;\n background: hsl(var(--ra-surface));\n border: 1px solid hsl(var(--ra-border));\n box-shadow: 0 12px 28px -10px hsl(0 0% 0% / 0.25);\n display: flex;\n flex-direction: column;\n gap: 0.125rem;\n}\n.ra-shell .ra-row-menu-item {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.4rem 0.55rem;\n border-radius: 0.35rem;\n font-size: 0.75rem;\n color: hsl(var(--ra-text));\n background: transparent;\n border: 0;\n text-align: left;\n width: 100%;\n cursor: pointer;\n}\n.ra-shell .ra-row-menu-item:hover:not(:disabled) {\n background: hsl(var(--ra-muted));\n}\n.ra-shell .ra-row-menu-item:disabled {\n opacity: 0.45;\n cursor: not-allowed;\n}\n.ra-shell .ra-item-list {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n}\n.ra-shell .ra-item-list-body {\n flex: 1;\n min-height: 0;\n overflow: auto;\n padding: 1rem 1.25rem 1.5rem;\n}\n.ra-shell .ra-item-toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 0.75rem;\n padding: 0.75rem 1.25rem;\n border-bottom: 1px solid hsl(var(--ra-border));\n background: hsl(var(--ra-surface));\n}\n.ra-shell .ra-item-toolbar-title {\n display: flex;\n align-items: baseline;\n gap: 0.5rem;\n min-width: 0;\n}\n.ra-shell .ra-item-toolbar-count {\n font-size: 0.7rem;\n font-weight: 600;\n color: hsl(var(--ra-muted-text));\n background: hsl(var(--ra-muted));\n border: 1px solid hsl(var(--ra-border));\n border-radius: 999px;\n padding: 0.05rem 0.45rem;\n}\n.ra-shell .ra-item-toolbar-actions {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n flex-shrink: 0;\n}\n.ra-shell .ra-item-table-wrap {\n border: 1px solid hsl(var(--ra-border));\n border-radius: var(--ra-radius);\n background: hsl(var(--ra-surface));\n overflow: hidden;\n box-shadow: var(--ra-card-shadow);\n}\n.ra-shell .ra-item-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 0.85rem;\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-item-table thead th {\n text-align: left;\n font-size: 0.7rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: hsl(var(--ra-muted-text));\n padding: 0.65rem 0.85rem;\n background: hsl(var(--ra-muted) / 0.55);\n border-bottom: 1px solid hsl(var(--ra-border));\n}\n.ra-shell .ra-item-table tbody td {\n padding: 0.65rem 0.85rem;\n border-bottom: 1px solid hsl(var(--ra-border) / 0.7);\n vertical-align: middle;\n}\n.ra-shell .ra-item-table tbody tr:last-child td {\n border-bottom: 0;\n}\n.ra-shell .ra-item-row {\n cursor: pointer;\n transition: background .12s ease;\n}\n.ra-shell .ra-item-row:hover {\n background: var(--ra-row-hover);\n}\n.ra-shell .ra-item-row[data-selected=true] {\n background: var(--ra-row-active-bg);\n}\n.ra-shell .ra-item-row-title {\n font-weight: var(--ra-title-weight);\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-item-row-sub {\n font-size: 0.75rem;\n color: hsl(var(--ra-muted-text));\n margin-top: 0.15rem;\n}\n.ra-shell .ra-item-row-meta {\n font-size: 0.78rem;\n color: hsl(var(--ra-muted-text));\n}\n.ra-shell .ra-item-row-actions {\n text-align: right;\n white-space: nowrap;\n}\n.ra-shell .ra-item-row-actions .ra-row-action + .ra-row-action {\n margin-left: 0.15rem;\n}\n.ra-shell .ra-item-cards {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));\n gap: 0.85rem;\n}\n.ra-shell .ra-item-gallery {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));\n gap: 1rem;\n}\n.ra-shell .ra-item-card {\n position: relative;\n display: flex;\n flex-direction: column;\n align-items: stretch;\n text-align: left;\n padding: 0;\n background: hsl(var(--ra-surface));\n border: 1px solid hsl(var(--ra-border));\n border-radius: var(--ra-radius);\n overflow: hidden;\n cursor: pointer;\n transition:\n box-shadow .18s ease,\n transform .12s ease,\n border-color .15s ease;\n box-shadow: var(--ra-card-shadow);\n font-family: inherit;\n color: inherit;\n}\n.ra-shell .ra-item-card:hover {\n box-shadow: var(--ra-card-shadow-hover);\n border-color: hsl(var(--ra-accent) / 0.30);\n}\n.ra-shell .ra-item-card[data-selected=true] {\n border-color: hsl(var(--ra-accent) / 0.55);\n box-shadow: var(--ra-card-shadow-hover);\n}\n.ra-shell .ra-item-card-thumb {\n width: 100%;\n aspect-ratio: 1 / 1;\n background:\n linear-gradient(\n 135deg,\n hsl(var(--ra-accent) / 0.12),\n hsl(var(--ra-accent) / 0.04));\n display: flex;\n align-items: center;\n justify-content: center;\n color: hsl(var(--ra-accent));\n overflow: hidden;\n}\n.ra-shell .ra-item-card-thumb--gallery {\n aspect-ratio: 16 / 9;\n}\n.ra-shell .ra-item-card-thumb img {\n width: 100%;\n height: 100%;\n -o-object-fit: cover;\n object-fit: cover;\n}\n.ra-shell .ra-item-card-initials {\n font-family: var(--ra-font-display);\n font-weight: var(--ra-display-weight);\n font-size: 1.5rem;\n letter-spacing: 0.02em;\n}\n.ra-shell .ra-item-card-body {\n padding: 0.65rem 0.8rem 0.85rem;\n min-width: 0;\n}\n.ra-shell .ra-item-card-title {\n font-weight: var(--ra-title-weight);\n font-size: 0.85rem;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ra-shell .ra-item-card-sub {\n font-size: 0.75rem;\n color: hsl(var(--ra-muted-text));\n margin-top: 0.15rem;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ra-shell .ra-item-card-delete {\n position: absolute;\n top: 0.4rem;\n right: 0.4rem;\n background: hsl(var(--ra-surface) / 0.85);\n backdrop-filter: blur(4px);\n opacity: 0;\n transition: opacity .15s ease;\n}\n.ra-shell .ra-item-card:hover .ra-item-card-delete,\n.ra-shell .ra-item-card:focus-within .ra-item-card-delete {\n opacity: 1;\n}\n.ra-shell .ra-item-nav {\n display: flex;\n align-items: center;\n gap: 0.6rem;\n padding: 0.5rem 1.25rem;\n border-bottom: 1px solid hsl(var(--ra-border));\n background: hsl(var(--ra-surface));\n}\n.ra-shell .ra-item-nav-position {\n font-size: 0.72rem;\n color: hsl(var(--ra-muted-text));\n font-variant-numeric: tabular-nums;\n}\n.ra-shell .ra-item-nav-arrows {\n margin-left: auto;\n display: inline-flex;\n align-items: center;\n gap: 0.15rem;\n}\n.ra-shell .ra-item-nav-arrows .ra-row-action[disabled] {\n opacity: 0.35;\n cursor: not-allowed;\n}\n.ra-shell .ra-sibling-rail {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n}\n.ra-shell .ra-sibling-back {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n padding: 0.6rem 0.85rem;\n font-size: 0.75rem;\n font-weight: 500;\n color: hsl(var(--ra-muted-text));\n background: hsl(var(--ra-muted) / 0.5);\n border: 0;\n border-bottom: 1px solid hsl(var(--ra-border));\n cursor: pointer;\n text-align: left;\n transition: background .12s ease, color .12s ease;\n}\n.ra-shell .ra-sibling-back:hover {\n background: hsl(var(--ra-muted));\n color: hsl(var(--ra-text));\n}\n.ra-shell .ra-sibling-heading {\n padding: 0.6rem 0.85rem 0.4rem;\n font-size: 0.65rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: hsl(var(--ra-muted-text));\n}\n.ra-shell .ra-sibling-body {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n}\n.ra-shell .ra-sibling-list {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n");
2989
3350
  var TOP_LEVEL_SCOPES = ["facet", "product"];
2990
3351
  var defaultItemId = () => {
2991
3352
  const time = Date.now().toString(36);
@@ -3018,7 +3379,7 @@ function RecordsAdminShell(props) {
3018
3379
  renderPreview,
3019
3380
  intro,
3020
3381
  csvSchema,
3021
- classify,
3382
+ classify: classify2,
3022
3383
  defaultData,
3023
3384
  i18n: i18nOverride,
3024
3385
  onTelemetry,
@@ -3034,7 +3395,6 @@ function RecordsAdminShell(props) {
3034
3395
  disableBeforeUnload = false,
3035
3396
  presentations = ["list"],
3036
3397
  defaultPresentation,
3037
- renderCard,
3038
3398
  renderListRow,
3039
3399
  renderEmpty,
3040
3400
  cardinality = "singleton",
@@ -3059,10 +3419,22 @@ function RecordsAdminShell(props) {
3059
3419
  onPaste: onPasteOverride,
3060
3420
  actionLabels,
3061
3421
  actionIcons,
3062
- editorTabs = "off"
3422
+ editorTabs = "off",
3423
+ // Right-pane item view (collection cardinality)
3424
+ itemViews = ["table"],
3425
+ defaultItemView,
3426
+ itemColumns,
3427
+ renderItemList,
3428
+ renderItemCard,
3429
+ renderItemEmpty,
3430
+ collectionRailMode = "siblings",
3431
+ // Deep linking
3432
+ deepLink
3063
3433
  } = props;
3064
3434
  const i18n = { ...DEFAULT_I18N, ...i18nOverride ?? {} };
3065
3435
  const icons = useMemo(() => mergeIcons(iconsOverride), [iconsOverride]);
3436
+ const deepLinkState = useDeepLinkState(deepLink);
3437
+ const lastAppliedDLRef = useRef("");
3066
3438
  const multiOpenWarnedRef = useRef(false);
3067
3439
  if (editorTabs === "multi" && !multiOpenWarnedRef.current) {
3068
3440
  multiOpenWarnedRef.current = true;
@@ -3080,6 +3452,25 @@ function RecordsAdminShell(props) {
3080
3452
  onTelemetry?.({ type: "presentation.change", recordType, from: presentation, to: next });
3081
3453
  setPresentation(next);
3082
3454
  }, [onTelemetry, recordType, presentation, setPresentation]);
3455
+ const [itemView, setItemView] = useItemViewPref({
3456
+ appId,
3457
+ recordType,
3458
+ options: itemViews,
3459
+ defaultValue: defaultItemView ?? itemViews[0] ?? "table"
3460
+ });
3461
+ const onItemViewChange = useCallback((next) => {
3462
+ onTelemetry?.({
3463
+ type: "item.view.change",
3464
+ recordType,
3465
+ scopeRef: "",
3466
+ // populated below if a scope is active
3467
+ from: itemView,
3468
+ to: next
3469
+ });
3470
+ setItemView(next);
3471
+ deepLinkState.emit({ view: next }, "view");
3472
+ }, [onTelemetry, recordType, itemView, setItemView, deepLinkState]);
3473
+ const [selectedItemId, setSelectedItemId] = useState(null);
3083
3474
  const ctx = useMemo(
3084
3475
  () => ({ SL, collectionId, appId, recordType }),
3085
3476
  [SL, collectionId, appId, recordType]
@@ -3138,6 +3529,15 @@ function RecordsAdminShell(props) {
3138
3529
  }
3139
3530
  }, [contextScope?.batchId]);
3140
3531
  const { dismissed, dismiss, undismiss } = useIntroDismissed(SL, collectionId, appId, recordType);
3532
+ const headerWillRender = useMemo(() => {
3533
+ const headerCustomised = !!title || !!subtitle || !!headerIcon || !!headerActions || showStats || !!statsItems || !!statsTitle || !!statsIcon;
3534
+ return showHeader === true || showHeader !== false && headerCustomised;
3535
+ }, [showHeader, title, subtitle, headerIcon, headerActions, showStats, statsItems, statsTitle, statsIcon]);
3536
+ const resolvedReopenAffordance = useMemo(() => {
3537
+ const requested = intro?.reopenAffordance ?? "header";
3538
+ if (requested === "header" && !headerWillRender) return "footer";
3539
+ return requested;
3540
+ }, [intro?.reopenAffordance, headerWillRender]);
3141
3541
  const productBrowse = useProductBrowse({
3142
3542
  SL,
3143
3543
  collectionId,
@@ -3149,7 +3549,7 @@ function RecordsAdminShell(props) {
3149
3549
  scopeKind: activeScope,
3150
3550
  search,
3151
3551
  filter,
3152
- classify,
3552
+ classify: classify2,
3153
3553
  contextScope,
3154
3554
  enabled: activeScope === "facet" && !probe.isLoading
3155
3555
  });
@@ -3204,19 +3604,82 @@ function RecordsAdminShell(props) {
3204
3604
  }
3205
3605
  return parseRef(buildRef({ productId: selectedProductId }));
3206
3606
  }, [activeScope, selectedFacetRef, selectedProductId, drillTab, selectedVariantId, selectedBatchId]);
3607
+ const isCollection = cardinality === "collection";
3608
+ const editingItemRef = useMemo(() => {
3609
+ if (!isCollection) return null;
3610
+ if (!selectedItemId) return null;
3611
+ const baseRef = editingScope?.raw ?? "";
3612
+ return buildItemRef(baseRef, selectedItemId);
3613
+ }, [isCollection, selectedItemId, editingScope]);
3614
+ const editingTargetScope = useMemo(() => {
3615
+ if (!isCollection) return editingScope;
3616
+ if (!editingItemRef) return null;
3617
+ return parseRef(editingItemRef);
3618
+ }, [isCollection, editingScope, editingItemRef]);
3619
+ const skipNextItemResetRef = useRef(false);
3620
+ useEffect(() => {
3621
+ if (skipNextItemResetRef.current) {
3622
+ skipNextItemResetRef.current = false;
3623
+ return;
3624
+ }
3625
+ setSelectedItemId(null);
3626
+ }, [editingScope?.raw]);
3627
+ const collectionItems = useCollectionItems({
3628
+ ctx,
3629
+ scope: isCollection ? editingScope : null,
3630
+ enabled: isCollection
3631
+ });
3632
+ useEffect(() => {
3633
+ if (!deepLinkState.enabled) return;
3634
+ if (selectedItemId) return;
3635
+ deepLinkState.emit({ scope: editingScope?.raw ?? null, item: null }, "scope");
3636
+ lastAppliedDLRef.current = `${""}|${editingScope?.raw ?? ""}|${itemView}`;
3637
+ }, [deepLinkState.enabled, editingScope?.raw, selectedItemId, itemView]);
3638
+ useEffect(() => {
3639
+ if (!deepLinkState.enabled) return;
3640
+ const { item, scope, view } = deepLinkState.urlState;
3641
+ const sig = `${item ?? ""}|${scope ?? ""}|${view ?? ""}`;
3642
+ if (sig === lastAppliedDLRef.current) return;
3643
+ lastAppliedDLRef.current = sig;
3644
+ if (view && itemViews.includes(view) && view !== itemView) {
3645
+ setItemView(view);
3646
+ }
3647
+ const railRef = item ? item.includes("item:") ? item.slice(0, item.lastIndexOf("item:")).replace(/\/$/, "") : "" : scope ?? "";
3648
+ const itemId = item ? item.includes("item:") ? item.slice(item.lastIndexOf("item:") + "item:".length) : item : null;
3649
+ const parsed = railRef ? parseRef(railRef) : null;
3650
+ if (parsed?.productId) {
3651
+ if (activeScope !== "product") setActiveScope("product");
3652
+ if (selectedProductId !== parsed.productId) setSelectedProductId(parsed.productId);
3653
+ const nextDrill = parsed.batchId ? "batch" : parsed.variantId ? "variant" : "product";
3654
+ if (drillTab !== nextDrill) setDrillTab(nextDrill);
3655
+ if (parsed.variantId && selectedVariantId !== parsed.variantId) setSelectedVariantId(parsed.variantId);
3656
+ if (parsed.batchId && selectedBatchId !== parsed.batchId) setSelectedBatchId(parsed.batchId);
3657
+ } else if (parsed?.facetId) {
3658
+ if (activeScope !== "facet") setActiveScope("facet");
3659
+ if (selectedFacetRef !== railRef) setSelectedFacetRef(railRef);
3660
+ } else {
3661
+ if (selectedFacetRef) setSelectedFacetRef(void 0);
3662
+ }
3663
+ if (itemId !== selectedItemId) {
3664
+ if (railRef && railRef !== editingScope?.raw) {
3665
+ skipNextItemResetRef.current = true;
3666
+ }
3667
+ setSelectedItemId(itemId);
3668
+ }
3669
+ }, [deepLinkState.enabled, deepLinkState.urlState]);
3207
3670
  const supportedForResolution = useMemo(() => requestedScopes, [requestedScopes]);
3208
3671
  const resolved = useResolvedRecord({
3209
3672
  SL,
3210
3673
  appId,
3211
3674
  recordType,
3212
3675
  collectionId,
3213
- productId: editingScope?.productId,
3214
- variantId: editingScope?.variantId,
3215
- batchId: editingScope?.batchId,
3216
- facetId: editingScope?.facetId,
3217
- facetValue: editingScope?.facetValue,
3676
+ productId: editingTargetScope?.productId,
3677
+ variantId: editingTargetScope?.variantId,
3678
+ batchId: editingTargetScope?.batchId,
3679
+ facetId: editingTargetScope?.facetId,
3680
+ facetValue: editingTargetScope?.facetValue,
3218
3681
  supportedScopes: supportedForResolution,
3219
- enabled: !!editingScope
3682
+ enabled: !!editingTargetScope
3220
3683
  });
3221
3684
  const refetchAll = useCallback(() => {
3222
3685
  productBrowse.refetch();
@@ -3224,20 +3687,23 @@ function RecordsAdminShell(props) {
3224
3687
  facetBrowse.refetch();
3225
3688
  variantChildren.refetch();
3226
3689
  batchChildren.refetch();
3227
- }, [productBrowse, recordList, facetBrowse, variantChildren, batchChildren]);
3690
+ if (isCollection) collectionItems.refetch();
3691
+ }, [productBrowse, recordList, facetBrowse, variantChildren, batchChildren, isCollection, collectionItems]);
3228
3692
  const editorCtx = useRecordEditor({
3229
3693
  ctx,
3230
- scope: editingScope ?? parseRef(""),
3694
+ scope: editingTargetScope ?? parseRef(""),
3231
3695
  resolved: { data: resolved.data, source: resolved.source, sourceRef: resolved.sourceRef, parentValue: resolved.parentValue },
3232
3696
  defaultData,
3233
3697
  reseed: dirtyStrategy === "keep" ? "preserve-dirty" : "always",
3234
3698
  onSaved: () => {
3235
- onTelemetry?.({ type: "record.save", recordType, ref: editingScope?.raw ?? "", isCreate: resolved.source !== "self" });
3699
+ onTelemetry?.({ type: "record.save", recordType, ref: editingTargetScope?.raw ?? "", isCreate: resolved.source !== "self" });
3236
3700
  refetchAll();
3237
3701
  },
3238
3702
  onDeleted: () => {
3239
- onTelemetry?.({ type: "record.delete", recordType, ref: editingScope?.raw ?? "" });
3240
- if (activeScope === "facet") {
3703
+ onTelemetry?.({ type: "record.delete", recordType, ref: editingTargetScope?.raw ?? "" });
3704
+ if (isCollection && selectedItemId) {
3705
+ setSelectedItemId(null);
3706
+ } else if (activeScope === "facet") {
3241
3707
  setSelectedFacetRef(void 0);
3242
3708
  } else if (drillTab === "variant") {
3243
3709
  setSelectedVariantId(void 0);
@@ -3494,15 +3960,104 @@ function RecordsAdminShell(props) {
3494
3960
  };
3495
3961
  } : void 0;
3496
3962
  const onLeftSelectRef = useRef(null);
3963
+ const baseScopeRef = editingScope?.raw ?? "";
3964
+ const itemNounLabel = itemNoun || "item";
3965
+ const buildItemUrlValue = useCallback((id) => {
3966
+ return baseScopeRef ? `${baseScopeRef}/item:${id}` : id;
3967
+ }, [baseScopeRef]);
3968
+ const onItemOpen = useCallback((itemId) => {
3969
+ if (!isCollection) return;
3970
+ void runWithGuard(() => {
3971
+ setSelectedItemId(itemId);
3972
+ onTelemetry?.({ type: "item.open", recordType, scopeRef: baseScopeRef, itemId });
3973
+ deepLinkState.emit({ item: buildItemUrlValue(itemId) }, "item.open");
3974
+ });
3975
+ }, [isCollection, runWithGuard, onTelemetry, recordType, baseScopeRef, deepLinkState, buildItemUrlValue]);
3976
+ const onItemCreate = useCallback(() => {
3977
+ if (!isCollection) return;
3978
+ void runWithGuard(() => {
3979
+ const id = generateItemId ? generateItemId() : defaultItemId();
3980
+ setSelectedItemId(id);
3981
+ onTelemetry?.({ type: "item.create", recordType, scopeRef: baseScopeRef });
3982
+ deepLinkState.emit({ item: buildItemUrlValue(id) }, "item.open");
3983
+ });
3984
+ }, [isCollection, runWithGuard, generateItemId, onTelemetry, recordType, baseScopeRef, deepLinkState, buildItemUrlValue]);
3985
+ const onItemDelete = useCallback(async (itemId) => {
3986
+ if (!isCollection) return;
3987
+ const ref = buildItemRef(baseScopeRef, itemId);
3988
+ if (onBeforeDelete) {
3989
+ const ok = await onBeforeDelete(parseRef(ref));
3990
+ if (!ok) return;
3991
+ }
3992
+ try {
3993
+ const { deleteRecord: deleteRecord2 } = await import('../../records-66QWR67J.js');
3994
+ await deleteRecord2(ctx, ref);
3995
+ onTelemetry?.({ type: "item.delete", recordType, scopeRef: baseScopeRef, itemId });
3996
+ if (selectedItemId === itemId) setSelectedItemId(null);
3997
+ if (selectedItemId === itemId) deepLinkState.emit({ item: null }, "item.close");
3998
+ collectionItems.refetch();
3999
+ } catch (err) {
4000
+ console.error("[RecordsAdminShell] item delete failed", err);
4001
+ }
4002
+ }, [
4003
+ isCollection,
4004
+ baseScopeRef,
4005
+ ctx,
4006
+ onBeforeDelete,
4007
+ onTelemetry,
4008
+ recordType,
4009
+ selectedItemId,
4010
+ collectionItems,
4011
+ deepLinkState
4012
+ ]);
4013
+ const itemViewCtx = useMemo(() => ({
4014
+ onOpen: onItemOpen,
4015
+ onCreate: onItemCreate,
4016
+ onDelete: (id) => {
4017
+ void onItemDelete(id);
4018
+ },
4019
+ scope: editingScope ?? parseRef(""),
4020
+ selectedId: selectedItemId ?? void 0,
4021
+ isLoading: collectionItems.isLoading
4022
+ }), [onItemOpen, onItemCreate, onItemDelete, editingScope, selectedItemId, collectionItems.isLoading]);
4023
+ const itemPosition = useMemo(() => {
4024
+ if (!isCollection || !selectedItemId) return null;
4025
+ const idx = collectionItems.items.findIndex((it) => it.itemId === selectedItemId);
4026
+ if (idx < 0) return null;
4027
+ return { index: idx, total: collectionItems.items.length };
4028
+ }, [isCollection, selectedItemId, collectionItems.items]);
4029
+ const onItemBack = useCallback(() => {
4030
+ void runWithGuard(() => {
4031
+ setSelectedItemId(null);
4032
+ deepLinkState.emit({ item: null }, "item.close");
4033
+ });
4034
+ }, [runWithGuard, deepLinkState]);
4035
+ const stepToItem = useCallback((id) => {
4036
+ void runWithGuard(() => {
4037
+ setSelectedItemId(id);
4038
+ onTelemetry?.({ type: "item.open", recordType, scopeRef: baseScopeRef, itemId: id });
4039
+ deepLinkState.emit({ item: buildItemUrlValue(id) }, "item.step");
4040
+ });
4041
+ }, [runWithGuard, onTelemetry, recordType, baseScopeRef, deepLinkState, buildItemUrlValue]);
4042
+ const onItemPrev = useCallback(() => {
4043
+ if (!itemPosition || itemPosition.index <= 0) return;
4044
+ const next = collectionItems.items[itemPosition.index - 1];
4045
+ if (next?.itemId) stepToItem(next.itemId);
4046
+ }, [itemPosition, collectionItems.items, stepToItem]);
4047
+ const onItemNext = useCallback(() => {
4048
+ if (!itemPosition || itemPosition.index >= itemPosition.total - 1) return;
4049
+ const next = collectionItems.items[itemPosition.index + 1];
4050
+ if (next?.itemId) stepToItem(next.itemId);
4051
+ }, [itemPosition, collectionItems.items, stepToItem]);
3497
4052
  const renderEditorWithPreview = () => {
3498
- if (!editingScope) return null;
4053
+ if (!editingTargetScope) return null;
3499
4054
  const previewBody = renderPreview && effectivePreviewScope ? renderPreview({ resolved: editorCtx.value, previewScope: effectivePreviewScope }) : null;
3500
4055
  const scopePicker = previewScopePicker && effectivePreviewScope ? /* @__PURE__ */ jsx(
3501
4056
  PreviewScopePicker,
3502
4057
  {
3503
4058
  SL,
3504
4059
  collectionId,
3505
- editingScope,
4060
+ editingScope: editingTargetScope,
3506
4061
  value: effectivePreviewScope,
3507
4062
  onChange: setPreviewScope,
3508
4063
  showVariants: drillVariantsAllowed,
@@ -3510,6 +4065,20 @@ function RecordsAdminShell(props) {
3510
4065
  i18n: { previewAs: i18n.previewAs, previewAsDefault: i18n.previewAsDefault }
3511
4066
  }
3512
4067
  ) : null;
4068
+ const itemNav = isCollection && selectedItemId && itemPosition ? /* @__PURE__ */ jsx(
4069
+ EditorItemNav,
4070
+ {
4071
+ label: editorHeaderLabel,
4072
+ position: itemPosition.index + 1,
4073
+ total: itemPosition.total,
4074
+ onBack: onItemBack,
4075
+ onPrev: onItemPrev,
4076
+ onNext: onItemNext,
4077
+ canPrev: itemPosition.index > 0,
4078
+ canNext: itemPosition.index < itemPosition.total - 1,
4079
+ i18n
4080
+ }
4081
+ ) : null;
3513
4082
  const baseEditor = (extraFooter, inlinePreviewBody) => /* @__PURE__ */ jsx(
3514
4083
  RecordEditor,
3515
4084
  {
@@ -3518,7 +4087,7 @@ function RecordsAdminShell(props) {
3518
4087
  bulkActions: { ...csvBulk, i18n },
3519
4088
  preview: inlinePreviewBody,
3520
4089
  footerExtra: extraFooter,
3521
- onBeforeDelete: onBeforeDelete && editingScope ? () => onBeforeDelete(editingScope) : void 0,
4090
+ onBeforeDelete: onBeforeDelete && editingTargetScope ? () => onBeforeDelete(editingTargetScope) : void 0,
3522
4091
  headerLabel: editorHeaderLabel,
3523
4092
  headerSubtitle: editorHeaderSubtitle,
3524
4093
  headerMeta: editorHeaderMeta,
@@ -3528,64 +4097,76 @@ function RecordsAdminShell(props) {
3528
4097
  children: renderEditor(editorCtx)
3529
4098
  }
3530
4099
  );
3531
- if (!previewBody) return baseEditor();
4100
+ const withNav = (node) => itemNav ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full min-h-0", children: [
4101
+ itemNav,
4102
+ /* @__PURE__ */ jsx("div", { className: "flex-1 min-h-0 overflow-hidden", children: node })
4103
+ ] }) : node;
4104
+ if (!previewBody) return withNav(baseEditor());
3532
4105
  if (previewMode === "inline") {
3533
- return baseEditor(
4106
+ return withNav(baseEditor(
3534
4107
  void 0,
3535
4108
  /* @__PURE__ */ jsx(InlinePreview, { label: i18n.preview, scopePicker, children: previewBody })
3536
- );
4109
+ ));
3537
4110
  }
3538
4111
  if (previewMode === "side") {
3539
4112
  if (!sidePreviewOpen) {
3540
- return /* @__PURE__ */ jsx("div", { className: "relative h-full", children: baseEditor(
4113
+ return withNav(
4114
+ /* @__PURE__ */ jsx("div", { className: "relative h-full", children: baseEditor(
4115
+ /* @__PURE__ */ jsx(
4116
+ PreviewToggleButton,
4117
+ {
4118
+ onClick: () => setSidePreviewOpen(true),
4119
+ label: i18n.openPreview
4120
+ }
4121
+ )
4122
+ ) })
4123
+ );
4124
+ }
4125
+ return withNav(
4126
+ /* @__PURE__ */ jsxs("div", { className: "grid h-full", style: { gridTemplateColumns: "minmax(0, 1fr) minmax(280px, 420px)" }, children: [
4127
+ /* @__PURE__ */ jsx("div", { className: "overflow-hidden", children: baseEditor() }),
3541
4128
  /* @__PURE__ */ jsx(
3542
- PreviewToggleButton,
4129
+ SidePreview,
3543
4130
  {
3544
- onClick: () => setSidePreviewOpen(true),
3545
- label: i18n.openPreview
4131
+ label: i18n.preview,
4132
+ scopePicker,
4133
+ onClose: () => setSidePreviewOpen(false),
4134
+ children: previewBody
3546
4135
  }
3547
4136
  )
3548
- ) });
3549
- }
3550
- return /* @__PURE__ */ jsxs("div", { className: "grid h-full", style: { gridTemplateColumns: "minmax(0, 1fr) minmax(280px, 420px)" }, children: [
3551
- /* @__PURE__ */ jsx("div", { className: "overflow-hidden", children: baseEditor() }),
4137
+ ] })
4138
+ );
4139
+ }
4140
+ if (previewMode === "tab") {
4141
+ return withNav(
3552
4142
  /* @__PURE__ */ jsx(
3553
- SidePreview,
4143
+ TabbedPreview,
3554
4144
  {
3555
- label: i18n.preview,
4145
+ editor: baseEditor(),
4146
+ preview: previewBody,
3556
4147
  scopePicker,
3557
- onClose: () => setSidePreviewOpen(false),
3558
- children: previewBody
4148
+ i18n: { editor: i18n.editor, preview: i18n.preview }
3559
4149
  }
3560
4150
  )
3561
- ] });
3562
- }
3563
- if (previewMode === "tab") {
3564
- return /* @__PURE__ */ jsx(
3565
- TabbedPreview,
3566
- {
3567
- editor: baseEditor(),
3568
- preview: previewBody,
3569
- scopePicker,
3570
- i18n: { editor: i18n.editor, preview: i18n.preview }
3571
- }
3572
4151
  );
3573
4152
  }
3574
- return /* @__PURE__ */ jsxs("div", { className: "relative h-full", children: [
3575
- baseEditor(
3576
- /* @__PURE__ */ jsx(PreviewToggleButton, { onClick: () => setDrawerOpen(true), label: i18n.openPreview })
3577
- ),
3578
- /* @__PURE__ */ jsx(
3579
- DrawerPreview,
3580
- {
3581
- open: drawerOpen,
3582
- onClose: () => setDrawerOpen(false),
3583
- label: i18n.preview,
3584
- scopePicker,
3585
- children: previewBody
3586
- }
3587
- )
3588
- ] });
4153
+ return withNav(
4154
+ /* @__PURE__ */ jsxs("div", { className: "relative h-full", children: [
4155
+ baseEditor(
4156
+ /* @__PURE__ */ jsx(PreviewToggleButton, { onClick: () => setDrawerOpen(true), label: i18n.openPreview })
4157
+ ),
4158
+ /* @__PURE__ */ jsx(
4159
+ DrawerPreview,
4160
+ {
4161
+ open: drawerOpen,
4162
+ onClose: () => setDrawerOpen(false),
4163
+ label: i18n.preview,
4164
+ scopePicker,
4165
+ children: previewBody
4166
+ }
4167
+ )
4168
+ ] })
4169
+ );
3589
4170
  };
3590
4171
  const isProductTab = activeScope === "product";
3591
4172
  const productPinned = !!contextScope?.productId;
@@ -3661,9 +4242,9 @@ function RecordsAdminShell(props) {
3661
4242
  }
3662
4243
  ),
3663
4244
  (() => {
3664
- const headerCustomised = !!title || !!subtitle || !!headerIcon || !!headerActions || showStats || !!statsItems || !!statsTitle || !!statsIcon;
3665
- const renderHeader = showHeader === true || showHeader !== false && headerCustomised;
3666
- if (!renderHeader) return null;
4245
+ if (!headerWillRender) return null;
4246
+ const showHeaderReopen = !!intro && dismissed && resolvedReopenAffordance === "header";
4247
+ const reopenLabel = intro?.reopenLabel ?? `How ${label.toLowerCase()} works`;
3667
4248
  return /* @__PURE__ */ jsx(
3668
4249
  ShellHeader,
3669
4250
  {
@@ -3681,18 +4262,32 @@ function RecordsAdminShell(props) {
3681
4262
  },
3682
4263
  statsItems,
3683
4264
  statsTitle,
3684
- statsIcon
4265
+ statsIcon,
4266
+ trailingSlot: showHeaderReopen ? /* @__PURE__ */ jsx(
4267
+ "button",
4268
+ {
4269
+ type: "button",
4270
+ onClick: undismiss,
4271
+ className: "ra-btn",
4272
+ "data-variant": "ghost",
4273
+ "aria-label": reopenLabel,
4274
+ title: reopenLabel,
4275
+ style: { width: "2rem", height: "2rem", padding: 0, justifyContent: "center" },
4276
+ children: /* @__PURE__ */ jsx(HelpCircle, { className: "w-4 h-4" })
4277
+ }
4278
+ ) : void 0
3685
4279
  }
3686
4280
  );
3687
4281
  })(),
3688
- /* @__PURE__ */ jsx(
4282
+ resolvedReopenAffordance === "inline" || resolvedReopenAffordance === "footer" ? /* @__PURE__ */ jsx(
3689
4283
  UtilityRow,
3690
4284
  {
3691
- label,
4285
+ label: intro?.reopenLabel ? "" : label,
4286
+ customLabel: intro?.reopenLabel,
3692
4287
  introHidden: dismissed && !!intro,
3693
4288
  onShowIntro: undismiss
3694
4289
  }
3695
- ),
4290
+ ) : null,
3696
4291
  editorCtx.isDirty && /* @__PURE__ */ jsx(
3697
4292
  UnsavedBanner,
3698
4293
  {
@@ -3721,7 +4316,18 @@ function RecordsAdminShell(props) {
3721
4316
  className: "flex-1 grid border-t overflow-hidden",
3722
4317
  style: { gridTemplateColumns: "minmax(260px, 320px) 1fr", borderColor: "hsl(var(--ra-border))", marginTop: "0.75rem" },
3723
4318
  children: [
3724
- /* @__PURE__ */ jsxs("aside", { className: "border-r overflow-hidden flex flex-col", style: { borderColor: "hsl(var(--ra-border))", background: "hsl(var(--ra-surface))" }, children: [
4319
+ /* @__PURE__ */ jsx("aside", { className: "border-r overflow-hidden flex flex-col", style: { borderColor: "hsl(var(--ra-border))", background: "hsl(var(--ra-surface))" }, children: isCollection && selectedItemId && collectionRailMode === "siblings" ? /* @__PURE__ */ jsx(
4320
+ SiblingRail,
4321
+ {
4322
+ items: collectionItems.items,
4323
+ selectedItemId,
4324
+ isLoading: collectionItems.isLoading,
4325
+ error: collectionItems.error,
4326
+ onBack: onItemBack,
4327
+ onSelect: onItemOpen,
4328
+ i18n
4329
+ }
4330
+ ) : /* @__PURE__ */ jsxs(Fragment, { children: [
3725
4331
  /* @__PURE__ */ jsx("div", { className: "p-2", children: /* @__PURE__ */ jsx(
3726
4332
  ScopeTabs,
3727
4333
  {
@@ -3776,27 +4382,6 @@ function RecordsAdminShell(props) {
3776
4382
  hideZero: ["partial"],
3777
4383
  i18n
3778
4384
  }
3779
- ),
3780
- cardinality === "collection" && !isProductTab && editingScope && /* @__PURE__ */ jsxs(
3781
- "button",
3782
- {
3783
- type: "button",
3784
- onClick: () => {
3785
- void runWithGuard(() => {
3786
- const id = generateItemId ? generateItemId() : defaultItemId();
3787
- const baseRef = editingScope.raw;
3788
- const itemRef = baseRef ? `${baseRef}/item:${id}` : `item:${id}`;
3789
- setSelectedFacetRef(itemRef);
3790
- onTelemetry?.({ type: "item.create", recordType, scopeRef: baseRef });
3791
- });
3792
- },
3793
- className: "w-full inline-flex items-center justify-center gap-1.5 text-xs py-1.5 rounded-md border transition-colors hover:bg-[hsl(var(--ra-muted))]",
3794
- style: { borderColor: "hsl(var(--ra-border))", color: "hsl(var(--ra-text))" },
3795
- children: [
3796
- /* @__PURE__ */ jsx(Plus, { className: "w-3.5 h-3.5" }),
3797
- i18n.newItem || `New ${itemNoun}`
3798
- ]
3799
- }
3800
4385
  )
3801
4386
  ] }),
3802
4387
  /* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto", children: [
@@ -3820,7 +4405,6 @@ function RecordsAdminShell(props) {
3820
4405
  dirtyRef: editorCtx.isDirty ? editingScope?.raw : void 0,
3821
4406
  presentation: effectivePresentation,
3822
4407
  renderListRow,
3823
- renderCard,
3824
4408
  groupBy: effectiveGroupBy,
3825
4409
  rowClipboard
3826
4410
  }
@@ -3840,11 +4424,29 @@ function RecordsAdminShell(props) {
3840
4424
  ) })
3841
4425
  ] })
3842
4426
  ] })
3843
- ] }),
4427
+ ] }) }),
3844
4428
  /* @__PURE__ */ jsxs("main", { className: "overflow-hidden", children: [
3845
- !editingScope && activeScope === "product" && !selectedProductId && /* @__PURE__ */ jsx(EmptyState, { title: i18n.emptyTitle, body: i18n.emptyBody }),
3846
- !editingScope && activeScope === "facet" && /* @__PURE__ */ jsx(EmptyState, { title: i18n.emptyTitle, body: i18n.emptyBody }),
3847
- isProductTab && selectedProductId && /* @__PURE__ */ jsx(
4429
+ isCollection && editingScope && !selectedItemId && /* @__PURE__ */ jsx(
4430
+ ItemListView,
4431
+ {
4432
+ items: collectionItems.items,
4433
+ isLoading: collectionItems.isLoading,
4434
+ error: collectionItems.error,
4435
+ ctx: itemViewCtx,
4436
+ itemNoun: itemNounLabel,
4437
+ view: itemView,
4438
+ views: itemViews,
4439
+ onViewChange: onItemViewChange,
4440
+ renderItemList,
4441
+ renderItemCard,
4442
+ renderItemEmpty,
4443
+ itemColumns,
4444
+ i18n
4445
+ }
4446
+ ),
4447
+ !isCollection && !editingScope && activeScope === "product" && !selectedProductId && /* @__PURE__ */ jsx(EmptyState, { title: i18n.emptyTitle, body: i18n.emptyBody }),
4448
+ !isCollection && !editingScope && activeScope === "facet" && /* @__PURE__ */ jsx(EmptyState, { title: i18n.emptyTitle, body: i18n.emptyBody }),
4449
+ isProductTab && selectedProductId && (!isCollection || selectedItemId) && /* @__PURE__ */ jsx(
3848
4450
  ProductDrillDown,
3849
4451
  {
3850
4452
  productLabel: productBrowse.items.find((p) => p.id === selectedProductId)?.name ?? selectedProductId,
@@ -3872,7 +4474,7 @@ function RecordsAdminShell(props) {
3872
4474
  batches: batchChildren.items,
3873
4475
  variantsLoading: variantChildren.isLoading,
3874
4476
  batchesLoading: batchChildren.isLoading,
3875
- children: editingScope ? renderEditorWithPreview() : /* @__PURE__ */ jsx(
4477
+ children: editingTargetScope ? renderEditorWithPreview() : /* @__PURE__ */ jsx(
3876
4478
  EmptyState,
3877
4479
  {
3878
4480
  title: drillTab === "variant" ? "Pick a variant" : "Pick a batch",
@@ -3881,7 +4483,7 @@ function RecordsAdminShell(props) {
3881
4483
  )
3882
4484
  }
3883
4485
  ),
3884
- !isProductTab && editingScope && renderEditorWithPreview()
4486
+ !isProductTab && editingTargetScope && (!isCollection || selectedItemId) && renderEditorWithPreview()
3885
4487
  ] })
3886
4488
  ]
3887
4489
  }
@@ -3953,6 +4555,87 @@ var RecordBrowser = ({
3953
4555
  ] })
3954
4556
  ] });
3955
4557
  };
4558
+ var initials2 = (s) => s.split(/\s+/).filter(Boolean).slice(0, 2).map((p) => p[0]?.toUpperCase() ?? "").join("") || "?";
4559
+ var DefaultRecordCard = ({ record, ctx, variant = "grid" }) => {
4560
+ const { selected, onSelect, isDirty, onCopy, onPaste, canPaste, pasteWillReplace, clipboardSourceLabel } = ctx;
4561
+ const aspect = variant === "gallery" ? "aspect-video" : "aspect-square";
4562
+ return /* @__PURE__ */ jsxs(
4563
+ "button",
4564
+ {
4565
+ type: "button",
4566
+ onClick: onSelect,
4567
+ className: cn(
4568
+ "group flex flex-col text-left rounded-md overflow-hidden border ra-card-hover",
4569
+ selected && "ring-2"
4570
+ ),
4571
+ style: {
4572
+ background: "hsl(var(--ra-surface))",
4573
+ borderColor: selected ? "var(--ra-row-active-bd)" : "hsl(var(--ra-border))",
4574
+ boxShadow: selected ? `0 0 0 2px hsl(var(--ra-accent) / 0.45), var(--ra-card-shadow)` : "var(--ra-card-shadow)"
4575
+ },
4576
+ children: [
4577
+ /* @__PURE__ */ jsxs(
4578
+ "div",
4579
+ {
4580
+ className: cn(aspect, "relative w-full flex items-center justify-center overflow-hidden"),
4581
+ style: { background: "hsl(var(--ra-muted))" },
4582
+ children: [
4583
+ record.thumbnail ? /* @__PURE__ */ jsx(
4584
+ "img",
4585
+ {
4586
+ src: record.thumbnail,
4587
+ alt: "",
4588
+ loading: "lazy",
4589
+ className: "w-full h-full object-cover"
4590
+ }
4591
+ ) : /* @__PURE__ */ jsx(
4592
+ "span",
4593
+ {
4594
+ className: "text-2xl ra-display",
4595
+ style: { color: "hsl(var(--ra-muted-text))" },
4596
+ children: initials2(record.label)
4597
+ }
4598
+ ),
4599
+ /* @__PURE__ */ jsx("div", { className: "absolute top-1.5 left-1.5", children: /* @__PURE__ */ jsx(StatusDot, { status: record.status }) }),
4600
+ isDirty && /* @__PURE__ */ jsx(
4601
+ "span",
4602
+ {
4603
+ title: "Unsaved changes",
4604
+ "aria-label": "Unsaved changes",
4605
+ className: "ra-status-dot ra-status-shared absolute top-1.5 right-1.5"
4606
+ }
4607
+ )
4608
+ ]
4609
+ }
4610
+ ),
4611
+ /* @__PURE__ */ jsxs("div", { className: "p-2.5 min-w-0", children: [
4612
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-1.5 min-w-0", children: [
4613
+ /* @__PURE__ */ jsx("div", { className: "ra-row-title flex-1 min-w-0", children: record.label }),
4614
+ (onCopy || onPaste) && /* @__PURE__ */ jsx(
4615
+ RowContextMenu,
4616
+ {
4617
+ onCopy,
4618
+ onPaste,
4619
+ canPaste,
4620
+ pasteWillReplace,
4621
+ pasteSourceLabel: clipboardSourceLabel,
4622
+ i18n: {
4623
+ copy: DEFAULT_I18N.copy,
4624
+ paste: DEFAULT_I18N.paste,
4625
+ pasteFrom: DEFAULT_I18N.pasteFrom,
4626
+ pasteReplace: DEFAULT_I18N.pasteReplace,
4627
+ clipboardEmpty: DEFAULT_I18N.clipboardEmpty
4628
+ }
4629
+ }
4630
+ )
4631
+ ] }),
4632
+ variant === "gallery" && record.subtitle && /* @__PURE__ */ jsx("div", { className: "ra-row-sub", children: record.subtitle }),
4633
+ record.badges && record.badges.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex gap-1 mt-1.5 flex-wrap", children: record.badges.slice(0, 3).map((b, i) => /* @__PURE__ */ jsx("span", { className: "ra-chip", "data-tone": "muted", children: b.label }, `${b.label}-${i}`)) })
4634
+ ] })
4635
+ ]
4636
+ }
4637
+ );
4638
+ };
3956
4639
  var Ctx = createContext({});
3957
4640
  var InheritanceProvider = ({
3958
4641
  parentValue,
@@ -4283,6 +4966,6 @@ function useMergedRecord(args) {
4283
4966
  };
4284
4967
  }
4285
4968
 
4286
- export { ALL_PRESENTATIONS, BatchList, BulkActionsMenu, DEFAULT_I18N, DEFAULT_ICONS, DefaultRecordCard, DefaultRecordRow, DeleteButton, DrawerPreview, EmptyState, ErrorState, FacetList, InheritanceMarker, InheritanceProvider, InlinePreview, IntroCard, LoadingState, PresentationSwitcher, PreviewScopePicker, PreviewToggleButton, ProductDrillDown, ProductList, RecordBrowser, RecordEditor, RecordList, RecordsAdminShell, ResolvedPreview, ScopeBreadcrumb, ScopeTabs, SidePreview, StatusDot, StatusFilterPills, TabbedPreview, UtilityRow, VariantList, buildRef, bulkDelete, bulkUpsert, checkPasteCompatibility, cloneValue, deleteRecord, downloadBlob, exportCsv, getRecordByRef, importCsv, listRecords, matchRecords, mergeIcons, parseRef, parsedRefToScope, parsedRefToTarget, pickHeaderIcon, resolutionChain, resolveRecord, restoreRecord, scopesEqual, upsertRecord, useCollectedRecords, useDirtyNavigation, useFacetBrowse, useIntroDismissed, useMergedRecord, usePresentationPref, useProductBrowse, useProductChildren, useRecordClipboard, useRecordEditor, useRecordList, useResolveAllRecords, useResolvedRecord, useRulePreview, useScopeProbe, useUnsavedGuard };
4969
+ export { ALL_ITEM_VIEWS, ALL_PRESENTATIONS, BatchList, BulkActionsMenu, DEFAULT_DEEP_LINK_PARAM_NAMES, DEFAULT_I18N, DEFAULT_ICONS, DefaultItemCards, DefaultItemTable, DefaultRecordCard, DefaultRecordRow, DeleteButton, DrawerPreview, EditorItemNav, EmptyState, ErrorState, FacetList, InheritanceMarker, InheritanceProvider, InlinePreview, IntroCard, ItemListView, ItemViewSwitcher, LoadingState, PresentationSwitcher, PreviewScopePicker, PreviewToggleButton, ProductDrillDown, ProductList, RecordBrowser, RecordEditor, RecordList, RecordsAdminShell, ResolvedPreview, ScopeBreadcrumb, ScopeTabs, SiblingRail, SidePreview, StatusDot, StatusFilterPills, TabbedPreview, UtilityRow, VariantList, buildItemRef, buildRef, checkPasteCompatibility, cloneValue, createDefaultDeepLinkAdapter, downloadBlob, exportCsv, importCsv, mergeIcons, parseRef, pickHeaderIcon, resolutionChain, resolveRecord, splitItemRef, useCollectedRecords, useCollectionItems, useDeepLinkState, useDirtyNavigation, useFacetBrowse, useIntroDismissed, useItemViewPref, useMergedRecord, usePresentationPref, useProductBrowse, useProductChildren, useRecordClipboard, useRecordEditor, useRecordList, useResolveAllRecords, useResolvedRecord, useRulePreview, useScopeProbe, useUnsavedGuard };
4287
4970
  //# sourceMappingURL=index.js.map
4288
4971
  //# sourceMappingURL=index.js.map