@proveanything/smartlinks-utils-ui 0.3.9 → 0.3.12

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,23 @@
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, SlidersHorizontal, 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
+ rule: SlidersHorizontal
20
+ },
11
21
  status: { own: CheckCircle2, inherited: ArrowDownLeft, missing: CircleDashed },
12
22
  action: {
13
23
  add: Plus,
@@ -86,12 +96,22 @@ var DEFAULT_I18N = {
86
96
  unsavedPromptSave: "Save & continue",
87
97
  unsavedBannerBody: "Unsaved changes on {name}",
88
98
  presentationList: "List",
89
- presentationGrid: "Grid",
90
- presentationGallery: "Gallery",
91
99
  presentationCompact: "Compact",
100
+ itemViewTable: "Table",
101
+ itemViewCards: "Cards",
102
+ itemViewGallery: "Gallery",
92
103
  newItem: "New item",
93
104
  noItemsTitle: "No items yet",
94
105
  noItemsBody: "Create your first item to get started.",
106
+ backToList: "Back to list",
107
+ prevItem: "Previous",
108
+ nextItem: "Next",
109
+ itemListTitle: "Items",
110
+ itemColumnLabel: "Name",
111
+ itemColumnUpdated: "Updated",
112
+ itemActions: "Actions",
113
+ backToScopes: "\u2190 All scopes",
114
+ siblingsHeading: "Items in this scope",
95
115
  railEmptyTitle: "No records yet",
96
116
  railEmptyBody: "Records you create will appear here.",
97
117
  copy: "Copy",
@@ -110,7 +130,15 @@ var DEFAULT_I18N = {
110
130
  };
111
131
 
112
132
  // src/components/RecordsAdmin/types/presentation.ts
113
- var ALL_PRESENTATIONS = ["list", "grid", "gallery", "compact"];
133
+ var ALL_PRESENTATIONS = ["list", "compact"];
134
+ var ALL_ITEM_VIEWS = ["table", "cards", "gallery"];
135
+
136
+ // src/components/RecordsAdmin/types/deepLink.ts
137
+ var DEFAULT_DEEP_LINK_PARAM_NAMES = {
138
+ item: "item",
139
+ scope: "scope",
140
+ view: "view"
141
+ };
114
142
 
115
143
  // src/components/RecordsAdmin/data/refs.ts
116
144
  var KIND_KEYS = {
@@ -119,7 +147,11 @@ var KIND_KEYS = {
119
147
  variant: "variantId",
120
148
  batch: "batchId",
121
149
  proof: "proofId",
122
- collection: "collectionId"
150
+ collection: "collectionId",
151
+ // `rule` records carry an opaque id under the `rule:` prefix; we expose
152
+ // the id via `productId`-equivalent slot to keep ParsedRef flat. Resolved
153
+ // refs use the `ruleId` field (added below) so callers can disambiguate.
154
+ rule: "ruleId"
123
155
  };
124
156
  var parseRef = (raw) => {
125
157
  const parsed = { kind: "collection", raw };
@@ -139,6 +171,9 @@ var parseRef = (raw) => {
139
171
  } else {
140
172
  parsed.facetId = id;
141
173
  }
174
+ } else if (k === "item") {
175
+ parsed.itemId = id;
176
+ continue;
142
177
  } else if (k in KIND_KEYS) {
143
178
  parsed[KIND_KEYS[k]] = id;
144
179
  }
@@ -156,6 +191,7 @@ var buildRef = (a) => {
156
191
  if (a.variantId) parts.push(`variant:${a.variantId}`);
157
192
  if (a.batchId) parts.push(`batch:${a.batchId}`);
158
193
  if (a.proofId) parts.push(`proof:${a.proofId}`);
194
+ if (a.itemId) parts.push(`item:${a.itemId}`);
159
195
  return parts.join("/");
160
196
  };
161
197
  var resolutionChain = (target, supportedScopes) => {
@@ -172,180 +208,36 @@ var resolutionChain = (target, supportedScopes) => {
172
208
  if (supportedScopes.includes("facet") && target.facetId) {
173
209
  chain.push(buildRef({ facetId: target.facetId, facetValue: target.facetValue }));
174
210
  }
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;
211
+ if (supportedScopes.includes("collection")) {
212
+ chain.push("");
300
213
  }
301
- return { saved, failed };
214
+ return Array.from(new Set(chain));
302
215
  };
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;
216
+ var splitItemRef = (raw) => {
217
+ if (!raw) return { scopeRef: "" };
218
+ const segs = raw.split("/").filter(Boolean);
219
+ const last = segs[segs.length - 1];
220
+ if (last && last.startsWith("item:")) {
221
+ return { scopeRef: segs.slice(0, -1).join("/"), itemId: last.slice("item:".length) };
322
222
  }
323
- return { removed };
223
+ return { scopeRef: raw };
324
224
  };
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("/");
225
+ var buildItemRef = (scopeRef, itemId) => {
226
+ return scopeRef ? `${scopeRef}/item:${itemId}` : `item:${itemId}`;
339
227
  };
340
-
341
- // src/components/RecordsAdmin/hooks/useRecordList.ts
342
228
  var defaultClassify = (r) => {
343
229
  if (!r.data) return "empty";
344
230
  const keys = Object.keys(r.data);
345
231
  if (keys.length === 0) return "empty";
346
232
  return "configured";
347
233
  };
348
- var matchesScope = (kind, p) => {
234
+ var matchesScope = (kind, rec, p) => {
235
+ const hasRule = !!rec.facetRule || (rec.ref ?? "").startsWith("rule:");
236
+ if (kind === "rule") return hasRule;
237
+ if (hasRule) return false;
238
+ if (kind === "collection") {
239
+ return !p.productId && !p.facetId && !p.variantId && !p.batchId && !p.proofId;
240
+ }
349
241
  if (kind === "product") return !!p.productId && !p.variantId && !p.batchId;
350
242
  if (kind === "facet") return !!p.facetId;
351
243
  if (kind === "variant") return !!p.variantId;
@@ -362,14 +254,17 @@ var matchesContext = (p, ctx) => {
362
254
  var toSummary = (rec) => {
363
255
  const ref = rec.ref ?? "";
364
256
  const scope = parseRef(ref);
257
+ const facetRule = rec.facetRule ?? null;
258
+ const fallbackLabel = scope.batchId ?? scope.variantId ?? scope.productId ?? scope.facetValue ?? scope.facetId ?? (facetRule ? "Rule-targeted record" : ref || "Global record");
365
259
  return {
366
260
  id: rec.id,
367
261
  ref,
368
262
  scope,
369
263
  data: rec.data ?? null,
370
264
  status: "configured",
371
- label: scope.batchId ?? scope.variantId ?? scope.productId ?? scope.facetValue ?? scope.facetId ?? ref,
372
- updatedAt: rec.updatedAt
265
+ label: fallbackLabel,
266
+ updatedAt: rec.updatedAt,
267
+ facetRule
373
268
  };
374
269
  };
375
270
  var QK_BASE = ["records-admin", "list"];
@@ -379,7 +274,7 @@ var useRecordList = (args) => {
379
274
  scopeKind,
380
275
  search = "",
381
276
  filter = "all",
382
- classify,
277
+ classify: classify2,
383
278
  enabled = true,
384
279
  scaffolder,
385
280
  contextScope,
@@ -414,9 +309,9 @@ var useRecordList = (args) => {
414
309
  const [scaffolded, setScaffolded] = useState(null);
415
310
  const rawItems = useMemo(() => {
416
311
  const all = query.data?.pages.flatMap((p) => p.data) ?? [];
417
- const cls = classify ?? defaultClassify;
418
- 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]);
312
+ const cls = classify2 ?? defaultClassify;
313
+ return all.map((rec) => ({ rec, summary: toSummary(rec) })).filter(({ rec, summary }) => matchesScope(scopeKind, rec, summary.scope)).filter(({ summary }) => matchesContext(summary.scope, contextScope)).map(({ summary }) => ({ ...summary, status: cls(summary) }));
314
+ }, [query.data, scopeKind, classify2, contextScope]);
420
315
  useEffect(() => {
421
316
  if (!scaffolder) {
422
317
  setScaffolded(null);
@@ -1383,10 +1278,12 @@ function cloneValue(value) {
1383
1278
  }
1384
1279
  }
1385
1280
  var LABELS = {
1281
+ collection: "Global",
1386
1282
  product: "Products",
1387
1283
  facet: "Shared",
1388
1284
  variant: "Variants",
1389
- batch: "Batches"
1285
+ batch: "Batches",
1286
+ rule: "Rules"
1390
1287
  };
1391
1288
  var ScopeTabs = ({
1392
1289
  scopes,
@@ -1455,11 +1352,30 @@ var StatusFilterPills = ({ value, onChange, counts, i18n, hideZero }) => {
1455
1352
  );
1456
1353
  }) });
1457
1354
  };
1458
- var StatusDot = ({ source, status, className }) => {
1459
- let cls = "ra-status-missing";
1460
- if (source === "self" || status === "configured") cls = "ra-status-own";
1461
- else if (source === "inherited" || status === "partial") cls = "ra-status-shared";
1462
- return /* @__PURE__ */ jsx("span", { className: cn("ra-status-dot", cls, className), "aria-hidden": "true" });
1355
+ var resolveTone = (source, status) => {
1356
+ if (source === "self" || status === "configured") return "own";
1357
+ if (source === "inherited" || status === "partial") return "shared";
1358
+ return "missing";
1359
+ };
1360
+ var StatusIcon = ({ source, status, className, size = "1.05rem", label }) => {
1361
+ const tone = resolveTone(source, status);
1362
+ const Icon = DEFAULT_ICONS.status[tone === "own" ? "own" : tone === "shared" ? "inherited" : "missing"];
1363
+ return /* @__PURE__ */ jsx(
1364
+ "span",
1365
+ {
1366
+ className: cn("ra-status-icon", `ra-status-icon--${tone}`, className),
1367
+ style: { width: size, height: size },
1368
+ role: label ? "img" : void 0,
1369
+ "aria-label": label,
1370
+ "aria-hidden": label ? void 0 : "true",
1371
+ children: /* @__PURE__ */ jsx(Icon, { className: "w-full h-full" })
1372
+ }
1373
+ );
1374
+ };
1375
+ var statusToneLabel = (tone) => {
1376
+ if (tone === "own") return "Configured";
1377
+ if (tone === "shared") return "Inherited";
1378
+ return "Empty";
1463
1379
  };
1464
1380
  var RowContextMenu = ({
1465
1381
  onCopy,
@@ -1543,31 +1459,54 @@ var RowContextMenu = ({
1543
1459
  ] })
1544
1460
  ] });
1545
1461
  };
1462
+
1463
+ // src/components/RecordsAdmin/browser/formatFacetRule.ts
1464
+ function formatFacetRule(rule) {
1465
+ if (!rule || !rule.all || rule.all.length === 0) return null;
1466
+ const parts = rule.all.map((c) => {
1467
+ const vals = (c.anyOf ?? []).filter(Boolean);
1468
+ if (vals.length === 0) return `${c.facetKey} (no values)`;
1469
+ if (vals.length === 1) return `${c.facetKey} = ${vals[0]}`;
1470
+ return `${c.facetKey} \u2208 {${vals.join(", ")}}`;
1471
+ });
1472
+ return parts.join(" AND ");
1473
+ }
1546
1474
  var DefaultRecordRow = ({ record, ctx, compact = false }) => {
1547
1475
  const { selected, onSelect, isDirty, onCopy, onPaste, canPaste, pasteWillReplace, clipboardSourceLabel } = ctx;
1548
1476
  const ScopeIcon = record.scope.kind && record.scope.kind !== "collection" ? DEFAULT_ICONS.scope[record.scope.kind] : DEFAULT_ICONS.scope.product;
1477
+ const tone = resolveTone(void 0, record.status);
1478
+ const ruleSummary = formatFacetRule(record.facetRule);
1479
+ const subtitle = record.subtitle ?? ruleSummary ?? (tone === "missing" ? "Empty \u2014 needs values" : tone === "own" ? "Configured" : "Inherited");
1549
1480
  return /* @__PURE__ */ jsxs(
1550
1481
  "button",
1551
1482
  {
1552
1483
  type: "button",
1553
1484
  onClick: onSelect,
1554
1485
  "data-selected": selected ? "true" : "false",
1486
+ "data-tone": tone,
1555
1487
  className: cn("ra-row", compact && "ra-row-compact"),
1556
1488
  style: compact ? { paddingTop: "0.4rem", paddingBottom: "0.4rem" } : void 0,
1557
1489
  children: [
1558
- !compact && /* @__PURE__ */ jsx("span", { className: "ra-row-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx(ScopeIcon, { className: "w-3.5 h-3.5" }) }),
1490
+ !compact && /* @__PURE__ */ jsx("span", { className: "ra-row-status", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
1491
+ StatusIcon,
1492
+ {
1493
+ status: record.status,
1494
+ label: statusToneLabel(tone)
1495
+ }
1496
+ ) }),
1559
1497
  /* @__PURE__ */ jsxs("div", { className: "ra-row-body", children: [
1560
1498
  /* @__PURE__ */ jsx("div", { className: "ra-row-title", children: record.label }),
1561
- !compact && record.subtitle && /* @__PURE__ */ jsx("div", { className: "ra-row-sub", children: record.subtitle })
1499
+ !compact && /* @__PURE__ */ jsx("div", { className: "ra-row-sub", children: subtitle })
1562
1500
  ] }),
1563
- /* @__PURE__ */ jsx(StatusDot, { status: record.status }),
1501
+ compact && /* @__PURE__ */ jsx(StatusIcon, { status: record.status, size: "0.85rem" }),
1502
+ !compact && record.scope.kind && record.scope.kind !== "collection" && /* @__PURE__ */ jsx("span", { className: "ra-row-scope", "aria-hidden": "true", children: /* @__PURE__ */ jsx(ScopeIcon, { className: "w-3 h-3" }) }),
1564
1503
  record.badges?.slice(0, 1).map((b, i) => /* @__PURE__ */ jsx("span", { className: "ra-chip", "data-tone": "muted", children: b.label }, `${b.label}-${i}`)),
1565
1504
  isDirty && /* @__PURE__ */ jsx(
1566
1505
  "span",
1567
1506
  {
1568
1507
  title: "Unsaved changes",
1569
1508
  "aria-label": "Unsaved changes",
1570
- className: "ra-status-dot ra-status-shared shrink-0"
1509
+ className: "ra-dirty-pip"
1571
1510
  }
1572
1511
  ),
1573
1512
  (onCopy || onPaste) && /* @__PURE__ */ jsx(
@@ -1591,87 +1530,6 @@ var DefaultRecordRow = ({ record, ctx, compact = false }) => {
1591
1530
  }
1592
1531
  );
1593
1532
  };
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
1533
  var RecordList = ({
1676
1534
  items,
1677
1535
  selectedRef,
@@ -1679,7 +1537,6 @@ var RecordList = ({
1679
1537
  dirtyRef,
1680
1538
  presentation = "list",
1681
1539
  renderListRow,
1682
- renderCard,
1683
1540
  groupBy,
1684
1541
  rowClipboard
1685
1542
  }) => {
@@ -1707,20 +1564,6 @@ var RecordList = ({
1707
1564
  return orderedKeys.map((k) => buckets.get(k));
1708
1565
  }, [items, groupBy]);
1709
1566
  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
1567
  const compact = presentation === "compact";
1725
1568
  return /* @__PURE__ */ jsx("ul", { children: rows.map((item) => {
1726
1569
  const ctx = buildCtx(item);
@@ -1803,18 +1646,12 @@ var ErrorState = ({ error }) => /* @__PURE__ */ jsxs("div", { className: "ra-emp
1803
1646
  ] });
1804
1647
  var ICONS = {
1805
1648
  list: List,
1806
- grid: LayoutGrid,
1807
- gallery: Image,
1808
1649
  compact: Rows3
1809
1650
  };
1810
1651
  var labelFor = (p, i18n) => {
1811
1652
  switch (p) {
1812
1653
  case "list":
1813
1654
  return i18n.presentationList;
1814
- case "grid":
1815
- return i18n.presentationGrid;
1816
- case "gallery":
1817
- return i18n.presentationGallery;
1818
1655
  case "compact":
1819
1656
  return i18n.presentationCompact;
1820
1657
  }
@@ -1853,6 +1690,7 @@ var PresentationSwitcher = ({ options, value, onChange, i18n }) => {
1853
1690
  );
1854
1691
  };
1855
1692
  var KEY_PREFIX = "smartlinks-ui:records-admin:presentation";
1693
+ var ITEM_VIEW_KEY_PREFIX = "smartlinks-ui:records-admin:item-view";
1856
1694
  var safeRead = (key) => {
1857
1695
  try {
1858
1696
  return typeof window === "undefined" ? null : window.localStorage.getItem(key);
@@ -1884,6 +1722,195 @@ function usePresentationPref(args) {
1884
1722
  }, [key]);
1885
1723
  return [value, set];
1886
1724
  }
1725
+ function useItemViewPref(args) {
1726
+ const { appId, recordType, options, defaultValue } = args;
1727
+ const key = `${ITEM_VIEW_KEY_PREFIX}:${appId}:${recordType ?? "_default"}`;
1728
+ const initial = () => {
1729
+ const stored = safeRead(key);
1730
+ if (stored && options.includes(stored)) return stored;
1731
+ return options.includes(defaultValue) ? defaultValue : options[0];
1732
+ };
1733
+ const [value, setValue] = useState(initial);
1734
+ useEffect(() => {
1735
+ if (!options.includes(value)) setValue(options[0]);
1736
+ }, [options, value]);
1737
+ const set = useCallback((next) => {
1738
+ setValue(next);
1739
+ safeWrite(key, next);
1740
+ }, [key]);
1741
+ return [value, set];
1742
+ }
1743
+ var QK_BASE2 = ["records-admin", "collection-items"];
1744
+ var defaultToSummary = (rec, base) => {
1745
+ const data = rec.data;
1746
+ if (!data) return base;
1747
+ const label = data.title ?? data.name ?? data.label ?? data.question ?? base.label;
1748
+ const subtitle = data.subtitle ?? data.summary ?? data.description ?? base.subtitle;
1749
+ const thumbnail = data.thumbnail ?? data.image ?? data.cover ?? base.thumbnail;
1750
+ return { ...base, label, subtitle, thumbnail };
1751
+ };
1752
+ function useCollectionItems(args) {
1753
+ const {
1754
+ ctx,
1755
+ scope,
1756
+ pageSize = 100,
1757
+ toSummary: toSummary2 = defaultToSummary,
1758
+ enabled = true
1759
+ } = args;
1760
+ const queryClient = useQueryClient();
1761
+ const scopeRef = scope?.raw ?? "";
1762
+ const refPrefix = scopeRef ? `${scopeRef}/item:` : "item:";
1763
+ const queryKey = useMemo(
1764
+ () => [...QK_BASE2, ctx.collectionId, ctx.appId, ctx.recordType, scopeRef],
1765
+ [ctx.collectionId, ctx.appId, ctx.recordType, scopeRef]
1766
+ );
1767
+ const query = useInfiniteQuery({
1768
+ queryKey,
1769
+ enabled: enabled && !!scope,
1770
+ initialPageParam: 0,
1771
+ queryFn: async ({ pageParam }) => {
1772
+ const offset = pageParam;
1773
+ const { data, total, hasMore } = await listRecords(ctx, {
1774
+ limit: pageSize,
1775
+ offset,
1776
+ refPrefix
1777
+ });
1778
+ return { data, total, hasMore, nextOffset: offset + data.length };
1779
+ },
1780
+ getNextPageParam: (last) => last.hasMore ? last.nextOffset : void 0,
1781
+ staleTime: 15e3
1782
+ });
1783
+ const items = useMemo(() => {
1784
+ const all = query.data?.pages.flatMap((p) => p.data) ?? [];
1785
+ return all.map((rec) => {
1786
+ const ref = rec.ref ?? "";
1787
+ const parsed = parseRef(ref);
1788
+ const { itemId } = splitItemRef(ref);
1789
+ if (!itemId) return null;
1790
+ const base = {
1791
+ id: rec.id,
1792
+ ref,
1793
+ scope: parsed,
1794
+ data: rec.data ?? null,
1795
+ status: rec.data ? "configured" : "empty",
1796
+ label: itemId,
1797
+ updatedAt: rec.updatedAt,
1798
+ itemId
1799
+ };
1800
+ return toSummary2(rec, base);
1801
+ }).filter((x) => x !== null);
1802
+ }, [query.data, toSummary2]);
1803
+ const refetch = useCallback(() => {
1804
+ queryClient.invalidateQueries({ queryKey });
1805
+ }, [queryClient, queryKey]);
1806
+ return {
1807
+ items,
1808
+ total: query.data?.pages[query.data.pages.length - 1]?.total ?? items.length,
1809
+ isLoading: query.isLoading,
1810
+ error: query.error ?? null,
1811
+ hasNextPage: query.hasNextPage,
1812
+ isFetchingNextPage: query.isFetchingNextPage,
1813
+ fetchNextPage: query.fetchNextPage,
1814
+ refetch
1815
+ };
1816
+ }
1817
+
1818
+ // src/components/RecordsAdmin/data/deepLinkAdapter.ts
1819
+ var findQueryHost = (loc) => {
1820
+ if (loc.search && loc.search.length > 1) return "search";
1821
+ if (loc.hash && loc.hash.includes("?")) return "hash";
1822
+ return "search";
1823
+ };
1824
+ var getQueryString = (loc) => {
1825
+ const host = findQueryHost(loc);
1826
+ if (host === "search") return loc.search.startsWith("?") ? loc.search.slice(1) : loc.search;
1827
+ const idx = loc.hash.indexOf("?");
1828
+ return idx >= 0 ? loc.hash.slice(idx + 1) : "";
1829
+ };
1830
+ var buildUrl = (loc, nextQuery) => {
1831
+ const host = findQueryHost(loc);
1832
+ const qs = nextQuery ? `?${nextQuery}` : "";
1833
+ if (host === "search") {
1834
+ return `${loc.pathname}${qs}${loc.hash}`;
1835
+ }
1836
+ const hashPath = loc.hash.includes("?") ? loc.hash.slice(0, loc.hash.indexOf("?")) : loc.hash;
1837
+ return `${loc.pathname}${loc.search}${hashPath}${qs}`;
1838
+ };
1839
+ var createDefaultDeepLinkAdapter = (paramNames) => ({
1840
+ read() {
1841
+ if (typeof window === "undefined") return {};
1842
+ const params = new URLSearchParams(getQueryString(window.location));
1843
+ return {
1844
+ item: params.get(paramNames.item),
1845
+ scope: params.get(paramNames.scope),
1846
+ view: params.get(paramNames.view)
1847
+ };
1848
+ },
1849
+ write(partial, mode) {
1850
+ if (typeof window === "undefined") return;
1851
+ const params = new URLSearchParams(getQueryString(window.location));
1852
+ const apply = (key, value) => {
1853
+ if (value == null || value === "") params.delete(key);
1854
+ else params.set(key, value);
1855
+ };
1856
+ if ("item" in partial) apply(paramNames.item, partial.item);
1857
+ if ("scope" in partial) apply(paramNames.scope, partial.scope);
1858
+ if ("view" in partial) apply(paramNames.view, partial.view);
1859
+ const nextUrl = buildUrl(window.location, params.toString());
1860
+ if (mode === "push") window.history.pushState({}, "", nextUrl);
1861
+ else window.history.replaceState({}, "", nextUrl);
1862
+ },
1863
+ subscribe(listener) {
1864
+ if (typeof window === "undefined") return () => {
1865
+ };
1866
+ window.addEventListener("popstate", listener);
1867
+ window.addEventListener("hashchange", listener);
1868
+ return () => {
1869
+ window.removeEventListener("popstate", listener);
1870
+ window.removeEventListener("hashchange", listener);
1871
+ };
1872
+ }
1873
+ });
1874
+
1875
+ // src/components/RecordsAdmin/hooks/useDeepLinkState.ts
1876
+ var SMART_PUSH = ["item.open", "item.close", "scope"];
1877
+ var classify = (mode, kind) => {
1878
+ if (mode === "push") return "push";
1879
+ if (mode === "replace") return "replace";
1880
+ return SMART_PUSH.includes(kind) ? "push" : "replace";
1881
+ };
1882
+ function useDeepLinkState(options) {
1883
+ const enabled = !!options?.enabled;
1884
+ const history = options?.history ?? "smart";
1885
+ const paramNames = useMemo(() => ({
1886
+ ...DEFAULT_DEEP_LINK_PARAM_NAMES,
1887
+ ...options?.paramNames ?? {}
1888
+ }), [options?.paramNames]);
1889
+ const defaultAdapterRef = useRef(null);
1890
+ const adapter = useMemo(() => {
1891
+ if (!enabled) return null;
1892
+ if (options?.adapter) return options.adapter;
1893
+ if (!defaultAdapterRef.current) {
1894
+ defaultAdapterRef.current = createDefaultDeepLinkAdapter(paramNames);
1895
+ }
1896
+ return defaultAdapterRef.current;
1897
+ }, [enabled, options?.adapter, paramNames]);
1898
+ const [urlState, setUrlState] = useState(
1899
+ () => adapter ? adapter.read() : {}
1900
+ );
1901
+ useEffect(() => {
1902
+ if (!adapter) return;
1903
+ setUrlState(adapter.read());
1904
+ return adapter.subscribe(() => setUrlState(adapter.read()));
1905
+ }, [adapter]);
1906
+ const emit = useCallback((partial, kind) => {
1907
+ if (!adapter) return;
1908
+ const mode = classify(history, kind);
1909
+ adapter.write(partial, mode);
1910
+ setUrlState((prev) => ({ ...prev, ...partial }));
1911
+ }, [adapter, history]);
1912
+ return { urlState, emit, paramNames, enabled };
1913
+ }
1887
1914
  var segmentsFor = (s) => {
1888
1915
  const out = [];
1889
1916
  if (s.facetId) out.push({ label: s.facetValue ? `${s.facetId}: ${s.facetValue}` : `Facet: ${s.facetId}`, key: "facet" });
@@ -1967,6 +1994,12 @@ var BulkActionsMenu = ({
1967
1994
  }) })
1968
1995
  ] });
1969
1996
  };
1997
+ var StatusDot = ({ source, status, className }) => {
1998
+ let cls = "ra-status-missing";
1999
+ if (source === "self" || status === "configured") cls = "ra-status-own";
2000
+ else if (source === "inherited" || status === "partial") cls = "ra-status-shared";
2001
+ return /* @__PURE__ */ jsx("span", { className: cn("ra-status-dot", cls, className), "aria-hidden": "true" });
2002
+ };
1970
2003
  var DeleteButton = ({
1971
2004
  onConfirm,
1972
2005
  onBeforeDelete,
@@ -2673,36 +2706,425 @@ var PreviewScopePicker = ({
2673
2706
  )
2674
2707
  ] });
2675
2708
  };
2676
- var TONE_ICON = {
2677
- info: Lightbulb,
2678
- success: CheckCircle2,
2679
- warning: AlertTriangle
2709
+ var ICONS2 = {
2710
+ table: Table,
2711
+ cards: LayoutGrid,
2712
+ gallery: Image
2680
2713
  };
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(
2714
+ var labelFor2 = (v, i18n) => {
2715
+ if (v === "table") return i18n.itemViewTable;
2716
+ if (v === "cards") return i18n.itemViewCards;
2717
+ return i18n.itemViewGallery;
2718
+ };
2719
+ var ItemViewSwitcher = ({ options, value, onChange, i18n }) => {
2720
+ if (options.length < 2) return null;
2721
+ return /* @__PURE__ */ jsx("div", { role: "tablist", className: "ra-tabs", "aria-label": "Item view", style: { padding: "0.15rem" }, children: options.map((opt) => {
2722
+ const Icon = ICONS2[opt];
2723
+ const active = value === opt;
2724
+ return /* @__PURE__ */ jsxs(
2693
2725
  "button",
2694
2726
  {
2695
2727
  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
- ] });
2728
+ role: "tab",
2729
+ "aria-selected": active,
2730
+ onClick: () => onChange(opt),
2731
+ className: "ra-tab",
2732
+ title: labelFor2(opt, i18n),
2733
+ style: { padding: "0.3rem 0.55rem" },
2734
+ children: [
2735
+ /* @__PURE__ */ jsx(Icon, { className: cn("ra-tab-icon w-3.5 h-3.5") }),
2736
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: labelFor2(opt, i18n) })
2737
+ ]
2738
+ },
2739
+ opt
2740
+ );
2741
+ }) });
2703
2742
  };
2704
- var UtilityRow = ({ label, introHidden, onShowIntro }) => {
2705
- if (!introHidden || !onShowIntro) return null;
2743
+ var formatDate = (iso) => {
2744
+ if (!iso) return "\u2014";
2745
+ try {
2746
+ const d = new Date(iso);
2747
+ return d.toLocaleDateString(void 0, { year: "numeric", month: "short", day: "numeric" });
2748
+ } catch {
2749
+ return iso;
2750
+ }
2751
+ };
2752
+ function DefaultItemTable({
2753
+ items,
2754
+ columns,
2755
+ selectedId,
2756
+ onOpen,
2757
+ onDelete,
2758
+ i18n
2759
+ }) {
2760
+ const cols = columns ?? [];
2761
+ const useFallback = cols.length === 0;
2762
+ return /* @__PURE__ */ jsx("div", { className: "ra-item-table-wrap", children: /* @__PURE__ */ jsxs("table", { className: "ra-item-table", children: [
2763
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
2764
+ useFallback ? /* @__PURE__ */ jsxs(Fragment, { children: [
2765
+ /* @__PURE__ */ jsx("th", { children: i18n.itemColumnLabel }),
2766
+ /* @__PURE__ */ jsx("th", { style: { width: "12rem" }, children: i18n.itemColumnUpdated })
2767
+ ] }) : cols.map((c) => /* @__PURE__ */ jsx("th", { style: { width: c.width, textAlign: c.align ?? "left" }, children: c.header }, c.key)),
2768
+ /* @__PURE__ */ jsx(
2769
+ "th",
2770
+ {
2771
+ style: { width: "6.5rem", textAlign: "right" },
2772
+ "aria-label": i18n.itemActions
2773
+ }
2774
+ )
2775
+ ] }) }),
2776
+ /* @__PURE__ */ jsx("tbody", { children: items.map((item) => {
2777
+ const id = item.itemId ?? "";
2778
+ const isSelected = !!selectedId && selectedId === id;
2779
+ return /* @__PURE__ */ jsxs(
2780
+ "tr",
2781
+ {
2782
+ "data-selected": isSelected,
2783
+ onClick: () => onOpen(id),
2784
+ className: "ra-item-row",
2785
+ children: [
2786
+ useFallback ? /* @__PURE__ */ jsxs(Fragment, { children: [
2787
+ /* @__PURE__ */ jsxs("td", { children: [
2788
+ /* @__PURE__ */ jsx("div", { className: "ra-item-row-title", children: item.label }),
2789
+ item.subtitle && /* @__PURE__ */ jsx("div", { className: "ra-item-row-sub", children: item.subtitle })
2790
+ ] }),
2791
+ /* @__PURE__ */ jsx("td", { className: "ra-item-row-meta", children: formatDate(item.updatedAt) })
2792
+ ] }) : cols.map((c) => /* @__PURE__ */ jsx("td", { style: { textAlign: c.align ?? "left" }, children: c.render(item) }, c.key)),
2793
+ /* @__PURE__ */ jsxs("td", { className: "ra-item-row-actions", children: [
2794
+ /* @__PURE__ */ jsx(
2795
+ "button",
2796
+ {
2797
+ type: "button",
2798
+ className: "ra-row-action",
2799
+ onClick: (e) => {
2800
+ e.stopPropagation();
2801
+ onOpen(id);
2802
+ },
2803
+ "aria-label": "Edit",
2804
+ children: /* @__PURE__ */ jsx(Pencil, { className: "w-3.5 h-3.5" })
2805
+ }
2806
+ ),
2807
+ /* @__PURE__ */ jsx(
2808
+ "button",
2809
+ {
2810
+ type: "button",
2811
+ className: "ra-row-action",
2812
+ "data-tone": "danger",
2813
+ onClick: (e) => {
2814
+ e.stopPropagation();
2815
+ 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
+ },
2824
+ item.ref
2825
+ );
2826
+ }) })
2827
+ ] }) });
2828
+ }
2829
+ var initials = (label) => label.split(/\s+/).slice(0, 2).map((s) => s[0]?.toUpperCase() ?? "").join("") || "?";
2830
+ function DefaultItemCards({
2831
+ items,
2832
+ variant,
2833
+ selectedId,
2834
+ ctx,
2835
+ renderCard,
2836
+ i18n
2837
+ }) {
2838
+ const isGallery = variant === "gallery";
2839
+ return /* @__PURE__ */ jsx("div", { className: isGallery ? "ra-item-gallery" : "ra-item-cards", children: items.map((item) => {
2840
+ const id = item.itemId ?? "";
2841
+ const slotCtx = {
2842
+ ...ctx,
2843
+ selected: selectedId === id
2844
+ };
2845
+ if (renderCard) {
2846
+ return /* @__PURE__ */ jsx(
2847
+ "div",
2848
+ {
2849
+ onClick: () => ctx.onOpen(id),
2850
+ className: "ra-item-card-wrap",
2851
+ "data-selected": slotCtx.selected,
2852
+ children: renderCard(item, slotCtx)
2853
+ },
2854
+ item.ref
2855
+ );
2856
+ }
2857
+ return /* @__PURE__ */ jsxs(
2858
+ "button",
2859
+ {
2860
+ type: "button",
2861
+ onClick: () => ctx.onOpen(id),
2862
+ className: `ra-item-card ${isGallery ? "ra-item-card--gallery" : ""}`,
2863
+ "data-selected": slotCtx.selected,
2864
+ children: [
2865
+ /* @__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) }) }),
2866
+ /* @__PURE__ */ jsxs("div", { className: "ra-item-card-body", children: [
2867
+ /* @__PURE__ */ jsx("div", { className: "ra-item-card-title", children: item.label }),
2868
+ item.subtitle && /* @__PURE__ */ jsx("div", { className: "ra-item-card-sub", children: item.subtitle })
2869
+ ] }),
2870
+ /* @__PURE__ */ jsx(
2871
+ "button",
2872
+ {
2873
+ type: "button",
2874
+ className: "ra-row-action ra-item-card-delete",
2875
+ "data-tone": "danger",
2876
+ onClick: (e) => {
2877
+ e.stopPropagation();
2878
+ ctx.onDelete(id);
2879
+ },
2880
+ "aria-label": i18n.delete,
2881
+ children: /* @__PURE__ */ jsx(Trash2, { className: "w-3.5 h-3.5" })
2882
+ }
2883
+ )
2884
+ ]
2885
+ },
2886
+ item.ref
2887
+ );
2888
+ }) });
2889
+ }
2890
+ function ItemListView({
2891
+ items,
2892
+ isLoading,
2893
+ error,
2894
+ ctx,
2895
+ itemNoun,
2896
+ view,
2897
+ views,
2898
+ onViewChange,
2899
+ renderItemList,
2900
+ renderItemCard,
2901
+ renderItemEmpty,
2902
+ itemColumns,
2903
+ i18n
2904
+ }) {
2905
+ const newLabel = i18n.newItem.includes("{noun}") ? i18n.newItem.replace("{noun}", itemNoun) : i18n.newItem;
2906
+ const toolbar = /* @__PURE__ */ jsxs("div", { className: "ra-item-toolbar", children: [
2907
+ /* @__PURE__ */ jsxs("div", { className: "ra-item-toolbar-title", children: [
2908
+ /* @__PURE__ */ jsx("h2", { className: "ra-display", style: { fontSize: "0.95rem", margin: 0 }, children: i18n.itemListTitle }),
2909
+ /* @__PURE__ */ jsx("span", { className: "ra-item-toolbar-count", children: items.length })
2910
+ ] }),
2911
+ /* @__PURE__ */ jsxs("div", { className: "ra-item-toolbar-actions", children: [
2912
+ !renderItemList && /* @__PURE__ */ jsx(
2913
+ ItemViewSwitcher,
2914
+ {
2915
+ options: views,
2916
+ value: view,
2917
+ onChange: onViewChange,
2918
+ i18n
2919
+ }
2920
+ ),
2921
+ /* @__PURE__ */ jsxs(
2922
+ "button",
2923
+ {
2924
+ type: "button",
2925
+ onClick: ctx.onCreate,
2926
+ className: "ra-btn",
2927
+ "data-variant": "primary",
2928
+ children: [
2929
+ /* @__PURE__ */ jsx(Plus, { className: "w-3.5 h-3.5" }),
2930
+ newLabel
2931
+ ]
2932
+ }
2933
+ )
2934
+ ] })
2935
+ ] });
2936
+ let body;
2937
+ if (isLoading) {
2938
+ body = /* @__PURE__ */ jsx(LoadingState, {});
2939
+ } else if (error) {
2940
+ body = /* @__PURE__ */ jsx(ErrorState, { error });
2941
+ } else if (items.length === 0) {
2942
+ body = renderItemEmpty ? renderItemEmpty(ctx) : /* @__PURE__ */ jsx(
2943
+ EmptyState,
2944
+ {
2945
+ title: i18n.noItemsTitle,
2946
+ body: i18n.noItemsBody,
2947
+ action: /* @__PURE__ */ jsxs(
2948
+ "button",
2949
+ {
2950
+ type: "button",
2951
+ onClick: ctx.onCreate,
2952
+ className: "ra-btn",
2953
+ "data-variant": "primary",
2954
+ children: [
2955
+ /* @__PURE__ */ jsx(Plus, { className: "w-3.5 h-3.5" }),
2956
+ newLabel
2957
+ ]
2958
+ }
2959
+ )
2960
+ }
2961
+ );
2962
+ } else if (renderItemList) {
2963
+ body = renderItemList(items, ctx);
2964
+ } else if (view === "table") {
2965
+ body = /* @__PURE__ */ jsx(
2966
+ DefaultItemTable,
2967
+ {
2968
+ items,
2969
+ columns: itemColumns,
2970
+ selectedId: ctx.selectedId,
2971
+ onOpen: ctx.onOpen,
2972
+ onDelete: ctx.onDelete,
2973
+ i18n
2974
+ }
2975
+ );
2976
+ } else {
2977
+ body = /* @__PURE__ */ jsx(
2978
+ DefaultItemCards,
2979
+ {
2980
+ items,
2981
+ variant: view,
2982
+ selectedId: ctx.selectedId,
2983
+ ctx,
2984
+ renderCard: renderItemCard,
2985
+ i18n
2986
+ }
2987
+ );
2988
+ }
2989
+ return /* @__PURE__ */ jsxs("div", { className: "ra-item-list", children: [
2990
+ toolbar,
2991
+ /* @__PURE__ */ jsx("div", { className: "ra-item-list-body", children: body })
2992
+ ] });
2993
+ }
2994
+ var EditorItemNav = ({
2995
+ label,
2996
+ position,
2997
+ total,
2998
+ onBack,
2999
+ onPrev,
3000
+ onNext,
3001
+ canPrev,
3002
+ canNext,
3003
+ i18n
3004
+ }) => /* @__PURE__ */ jsxs("div", { className: "ra-item-nav", children: [
3005
+ /* @__PURE__ */ jsxs(
3006
+ "button",
3007
+ {
3008
+ type: "button",
3009
+ onClick: onBack,
3010
+ className: "ra-btn",
3011
+ "data-variant": "ghost",
3012
+ children: [
3013
+ /* @__PURE__ */ jsx(ArrowLeft, { className: "w-3.5 h-3.5" }),
3014
+ i18n.backToList
3015
+ ]
3016
+ }
3017
+ ),
3018
+ typeof position === "number" && typeof total === "number" && total > 0 && /* @__PURE__ */ jsxs("span", { className: "ra-item-nav-position", "aria-label": label, children: [
3019
+ position,
3020
+ " / ",
3021
+ total
3022
+ ] }),
3023
+ /* @__PURE__ */ jsxs("div", { className: "ra-item-nav-arrows", children: [
3024
+ /* @__PURE__ */ jsx(
3025
+ "button",
3026
+ {
3027
+ type: "button",
3028
+ onClick: onPrev,
3029
+ disabled: !canPrev,
3030
+ className: "ra-row-action",
3031
+ "aria-label": i18n.prevItem,
3032
+ title: i18n.prevItem,
3033
+ children: /* @__PURE__ */ jsx(ChevronLeft, { className: "w-4 h-4" })
3034
+ }
3035
+ ),
3036
+ /* @__PURE__ */ jsx(
3037
+ "button",
3038
+ {
3039
+ type: "button",
3040
+ onClick: onNext,
3041
+ disabled: !canNext,
3042
+ className: "ra-row-action",
3043
+ "aria-label": i18n.nextItem,
3044
+ title: i18n.nextItem,
3045
+ children: /* @__PURE__ */ jsx(ChevronRight, { className: "w-4 h-4" })
3046
+ }
3047
+ )
3048
+ ] })
3049
+ ] });
3050
+ function SiblingRail({
3051
+ items,
3052
+ selectedItemId,
3053
+ isLoading,
3054
+ error,
3055
+ onBack,
3056
+ onSelect,
3057
+ i18n
3058
+ }) {
3059
+ return /* @__PURE__ */ jsxs("div", { className: "ra-sibling-rail", children: [
3060
+ /* @__PURE__ */ jsxs(
3061
+ "button",
3062
+ {
3063
+ type: "button",
3064
+ onClick: onBack,
3065
+ className: "ra-sibling-back",
3066
+ children: [
3067
+ /* @__PURE__ */ jsx(ArrowLeft, { className: "w-3.5 h-3.5" }),
3068
+ i18n.backToScopes
3069
+ ]
3070
+ }
3071
+ ),
3072
+ /* @__PURE__ */ jsx("div", { className: "ra-sibling-heading", children: i18n.siblingsHeading }),
3073
+ /* @__PURE__ */ jsxs("div", { className: "ra-sibling-body", children: [
3074
+ isLoading && /* @__PURE__ */ jsx(LoadingState, {}),
3075
+ !isLoading && error && /* @__PURE__ */ jsx(ErrorState, { error }),
3076
+ !isLoading && !error && items.length === 0 && /* @__PURE__ */ jsx(EmptyState, { title: i18n.noItemsTitle, body: i18n.noItemsBody }),
3077
+ !isLoading && !error && items.length > 0 && /* @__PURE__ */ jsx("ul", { className: "ra-sibling-list", children: items.map((item) => {
3078
+ const id = item.itemId ?? "";
3079
+ const selected = selectedItemId === id;
3080
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
3081
+ "button",
3082
+ {
3083
+ type: "button",
3084
+ onClick: () => onSelect(id),
3085
+ className: "ra-row",
3086
+ "data-selected": selected,
3087
+ children: /* @__PURE__ */ jsxs("div", { className: "ra-row-body", children: [
3088
+ /* @__PURE__ */ jsx("div", { className: "ra-row-title", children: item.label }),
3089
+ item.subtitle && /* @__PURE__ */ jsx("div", { className: "ra-row-sub", children: item.subtitle })
3090
+ ] })
3091
+ }
3092
+ ) }, item.ref);
3093
+ }) })
3094
+ ] })
3095
+ ] });
3096
+ }
3097
+ var TONE_ICON = {
3098
+ info: Lightbulb,
3099
+ success: CheckCircle2,
3100
+ warning: AlertTriangle
3101
+ };
3102
+ var IntroCard = ({ title, body, onDismiss, tone = "info", action }) => {
3103
+ const Icon = TONE_ICON[tone] ?? Info;
3104
+ return /* @__PURE__ */ jsxs("div", { className: "ra-intro", "data-tone": tone, role: "note", children: [
3105
+ /* @__PURE__ */ jsx("div", { className: "ra-intro-icon", children: /* @__PURE__ */ jsx(Icon, { className: "w-4 h-4" }) }),
3106
+ /* @__PURE__ */ jsxs("div", { className: "ra-intro-body", children: [
3107
+ /* @__PURE__ */ jsx("h4", { className: "ra-intro-title", children: title }),
3108
+ /* @__PURE__ */ jsxs("div", { className: "ra-intro-text", children: [
3109
+ body,
3110
+ action && /* @__PURE__ */ jsx("span", { className: "ml-1.5", children: action })
3111
+ ] })
3112
+ ] }),
3113
+ /* @__PURE__ */ jsx(
3114
+ "button",
3115
+ {
3116
+ type: "button",
3117
+ onClick: onDismiss,
3118
+ "aria-label": "Dismiss",
3119
+ className: "ra-intro-dismiss",
3120
+ children: /* @__PURE__ */ jsx(X, { className: "w-3.5 h-3.5" })
3121
+ }
3122
+ )
3123
+ ] });
3124
+ };
3125
+ var UtilityRow = ({ label, customLabel, introHidden, onShowIntro }) => {
3126
+ if (!introHidden || !onShowIntro) return null;
3127
+ const text = customLabel ?? `How ${label.toLowerCase()} works`;
2706
3128
  return /* @__PURE__ */ jsx(
2707
3129
  "div",
2708
3130
  {
@@ -2718,9 +3140,7 @@ var UtilityRow = ({ label, introHidden, onShowIntro }) => {
2718
3140
  style: { padding: "0.25rem 0.55rem", fontSize: "0.7rem" },
2719
3141
  children: [
2720
3142
  /* @__PURE__ */ jsx(HelpCircle, { className: "w-3 h-3" }),
2721
- "How ",
2722
- label.toLowerCase(),
2723
- " works"
3143
+ text
2724
3144
  ]
2725
3145
  }
2726
3146
  )
@@ -2739,7 +3159,8 @@ function ShellHeader({
2739
3159
  stats,
2740
3160
  statsItems,
2741
3161
  statsTitle,
2742
- statsIcon
3162
+ statsIcon,
3163
+ trailingSlot
2743
3164
  }) {
2744
3165
  let iconNode = null;
2745
3166
  if (showHeaderIcon) {
@@ -2794,7 +3215,10 @@ function ShellHeader({
2794
3215
  ]
2795
3216
  }
2796
3217
  ) : null,
2797
- headerActions ? /* @__PURE__ */ jsx("div", { className: "ra-header-actions", children: headerActions }) : null
3218
+ headerActions || trailingSlot ? /* @__PURE__ */ jsxs("div", { className: "ra-header-actions", children: [
3219
+ headerActions,
3220
+ trailingSlot
3221
+ ] }) : null
2798
3222
  ] })
2799
3223
  ] });
2800
3224
  }
@@ -2985,8 +3409,8 @@ var downloadBlob = (blob, filename) => {
2985
3409
  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
3410
 
2987
3411
  // 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");
2989
- var TOP_LEVEL_SCOPES = ["facet", "product"];
3412
+ 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.55rem;\n width: 100%;\n text-align: left;\n padding: 0.45rem 0.75rem;\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-compact {\n padding-block: 0.3rem;\n}\n.ra-shell .ra-row-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1.5rem;\n height: 1.5rem;\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.8125rem;\n line-height: 1.2;\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.6875rem;\n color: hsl(var(--ra-muted-text));\n margin-top: 0.05rem;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ra-shell[data-density=compact] .ra-row {\n padding-block: 0.3rem;\n gap: 0.45rem;\n}\n.ra-shell[data-density=compact] .ra-row-title {\n font-size: 0.78125rem;\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.ra-shell .ra-status-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n border-radius: 9999px;\n}\n.ra-shell .ra-status-icon > svg {\n width: 100%;\n height: 100%;\n display: block;\n}\n.ra-shell .ra-status-icon--own {\n color: hsl(var(--ra-status-own));\n}\n.ra-shell .ra-status-icon--shared {\n color: hsl(var(--ra-status-shared));\n}\n.ra-shell .ra-status-icon--missing {\n color: hsl(var(--ra-status-missing) / 0.7);\n}\n.ra-shell .ra-row-status {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1.5rem;\n height: 1.5rem;\n flex-shrink: 0;\n}\n.ra-shell .ra-row-scope {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1.25rem;\n height: 1.25rem;\n border-radius: calc(var(--ra-radius) * 0.5);\n background: hsl(var(--ra-muted));\n color: hsl(var(--ra-muted-text));\n flex-shrink: 0;\n margin-left: auto;\n opacity: 0.55;\n transition:\n opacity .12s ease,\n color .12s ease,\n background .12s ease;\n}\n.ra-shell .ra-row:hover .ra-row-scope {\n opacity: 0.85;\n}\n.ra-shell .ra-row[data-selected=true] .ra-row-scope {\n opacity: 1;\n background: hsl(var(--ra-accent) / 0.12);\n color: hsl(var(--ra-accent));\n}\n.ra-shell .ra-row[data-tone=own] .ra-row-sub {\n color: hsl(var(--ra-status-own));\n}\n.ra-shell .ra-row[data-tone=shared] .ra-row-sub {\n color: hsl(var(--ra-status-shared));\n}\n.ra-shell .ra-row[data-selected=true] {\n background:\n linear-gradient(\n 90deg,\n hsl(var(--ra-accent) / 0.10) 0%,\n hsl(var(--ra-accent) / 0.04) 100%);\n border-left-width: 3px;\n border-left-color: hsl(var(--ra-accent));\n}\n.ra-shell .ra-dirty-pip {\n display: inline-block;\n width: 0.45rem;\n height: 0.45rem;\n border-radius: 9999px;\n background: hsl(var(--ra-warning));\n box-shadow: 0 0 0 2px hsl(var(--ra-warning) / 0.18);\n flex-shrink: 0;\n}\n.ra-shell .ra-group-summary {\n background: transparent;\n}\n.ra-shell {\n position: relative;\n}\n.ra-shell .ra-help-float {\n position: absolute;\n top: 0.65rem;\n right: 0.85rem;\n z-index: 5;\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n padding: 0.3rem 0.6rem;\n font-size: 0.7rem;\n font-weight: 500;\n color: hsl(var(--ra-muted-text));\n background: hsl(var(--ra-surface) / 0.85);\n backdrop-filter: blur(6px);\n border: 1px solid hsl(var(--ra-border));\n border-radius: 999px;\n cursor: pointer;\n transition:\n color .12s ease,\n background .12s ease,\n border-color .12s ease;\n}\n.ra-shell .ra-help-float:hover {\n color: hsl(var(--ra-accent));\n border-color: hsl(var(--ra-accent) / 0.4);\n background: hsl(var(--ra-surface));\n}\n.ra-shell .ra-help-float svg {\n width: 0.85rem;\n height: 0.85rem;\n}\n.ra-shell .ra-preview-reopen {\n position: absolute;\n top: 50%;\n right: 0;\n transform: translateY(-50%);\n z-index: 4;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.4rem;\n padding: 0.65rem 0.45rem;\n background: hsl(var(--ra-surface));\n color: hsl(var(--ra-muted-text));\n border: 1px solid hsl(var(--ra-border));\n border-right: 0;\n border-radius: calc(var(--ra-radius) * 0.85) 0 0 calc(var(--ra-radius) * 0.85);\n box-shadow: var(--ra-card-shadow);\n cursor: pointer;\n transition:\n color .12s ease,\n background .12s ease,\n padding-right .15s ease;\n writing-mode: vertical-rl;\n font-size: 0.7rem;\n font-weight: 600;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n}\n.ra-shell .ra-preview-reopen:hover {\n color: hsl(var(--ra-accent));\n background: hsl(var(--ra-accent) / 0.04);\n padding-right: 0.6rem;\n}\n.ra-shell .ra-preview-reopen svg {\n width: 0.85rem;\n height: 0.85rem;\n writing-mode: horizontal-tb;\n}\n");
3413
+ var TOP_LEVEL_SCOPES = ["rule", "collection", "product", "facet"];
2990
3414
  var defaultItemId = () => {
2991
3415
  const time = Date.now().toString(36);
2992
3416
  const rand = Math.random().toString(36).slice(2, 8);
@@ -3018,7 +3442,7 @@ function RecordsAdminShell(props) {
3018
3442
  renderPreview,
3019
3443
  intro,
3020
3444
  csvSchema,
3021
- classify,
3445
+ classify: classify2,
3022
3446
  defaultData,
3023
3447
  i18n: i18nOverride,
3024
3448
  onTelemetry,
@@ -3034,7 +3458,6 @@ function RecordsAdminShell(props) {
3034
3458
  disableBeforeUnload = false,
3035
3459
  presentations = ["list"],
3036
3460
  defaultPresentation,
3037
- renderCard,
3038
3461
  renderListRow,
3039
3462
  renderEmpty,
3040
3463
  cardinality = "singleton",
@@ -3059,10 +3482,22 @@ function RecordsAdminShell(props) {
3059
3482
  onPaste: onPasteOverride,
3060
3483
  actionLabels,
3061
3484
  actionIcons,
3062
- editorTabs = "off"
3485
+ editorTabs = "off",
3486
+ // Right-pane item view (collection cardinality)
3487
+ itemViews = ["table"],
3488
+ defaultItemView,
3489
+ itemColumns,
3490
+ renderItemList,
3491
+ renderItemCard,
3492
+ renderItemEmpty,
3493
+ collectionRailMode = "siblings",
3494
+ // Deep linking
3495
+ deepLink
3063
3496
  } = props;
3064
3497
  const i18n = { ...DEFAULT_I18N, ...i18nOverride ?? {} };
3065
3498
  const icons = useMemo(() => mergeIcons(iconsOverride), [iconsOverride]);
3499
+ const deepLinkState = useDeepLinkState(deepLink);
3500
+ const lastAppliedDLRef = useRef("");
3066
3501
  const multiOpenWarnedRef = useRef(false);
3067
3502
  if (editorTabs === "multi" && !multiOpenWarnedRef.current) {
3068
3503
  multiOpenWarnedRef.current = true;
@@ -3080,6 +3515,25 @@ function RecordsAdminShell(props) {
3080
3515
  onTelemetry?.({ type: "presentation.change", recordType, from: presentation, to: next });
3081
3516
  setPresentation(next);
3082
3517
  }, [onTelemetry, recordType, presentation, setPresentation]);
3518
+ const [itemView, setItemView] = useItemViewPref({
3519
+ appId,
3520
+ recordType,
3521
+ options: itemViews,
3522
+ defaultValue: defaultItemView ?? itemViews[0] ?? "table"
3523
+ });
3524
+ const onItemViewChange = useCallback((next) => {
3525
+ onTelemetry?.({
3526
+ type: "item.view.change",
3527
+ recordType,
3528
+ scopeRef: "",
3529
+ // populated below if a scope is active
3530
+ from: itemView,
3531
+ to: next
3532
+ });
3533
+ setItemView(next);
3534
+ deepLinkState.emit({ view: next }, "view");
3535
+ }, [onTelemetry, recordType, itemView, setItemView, deepLinkState]);
3536
+ const [selectedItemId, setSelectedItemId] = useState(null);
3083
3537
  const ctx = useMemo(
3084
3538
  () => ({ SL, collectionId, appId, recordType }),
3085
3539
  [SL, collectionId, appId, recordType]
@@ -3138,20 +3592,30 @@ function RecordsAdminShell(props) {
3138
3592
  }
3139
3593
  }, [contextScope?.batchId]);
3140
3594
  const { dismissed, dismiss, undismiss } = useIntroDismissed(SL, collectionId, appId, recordType);
3595
+ const headerWillRender = useMemo(() => {
3596
+ const headerCustomised = !!title || !!subtitle || !!headerIcon || !!headerActions || showStats || !!statsItems || !!statsTitle || !!statsIcon;
3597
+ return showHeader === true || showHeader !== false && headerCustomised;
3598
+ }, [showHeader, title, subtitle, headerIcon, headerActions, showStats, statsItems, statsTitle, statsIcon]);
3599
+ const resolvedReopenAffordance = useMemo(() => {
3600
+ const requested = intro?.reopenAffordance ?? "header";
3601
+ if (requested === "header" && !headerWillRender) return "footer";
3602
+ return requested;
3603
+ }, [intro?.reopenAffordance, headerWillRender]);
3141
3604
  const productBrowse = useProductBrowse({
3142
3605
  SL,
3143
3606
  collectionId,
3144
3607
  search: activeScope === "product" ? search : "",
3145
3608
  enabled: activeScope === "product" && !contextScope?.productId
3146
3609
  });
3610
+ const recordListEnabled = (activeScope === "facet" || activeScope === "rule" || activeScope === "collection") && !probe.isLoading;
3147
3611
  const recordList = useRecordList({
3148
3612
  ctx,
3149
3613
  scopeKind: activeScope,
3150
3614
  search,
3151
3615
  filter,
3152
- classify,
3616
+ classify: classify2,
3153
3617
  contextScope,
3154
- enabled: activeScope === "facet" && !probe.isLoading
3618
+ enabled: recordListEnabled
3155
3619
  });
3156
3620
  const facetBrowse = useFacetBrowse({
3157
3621
  SL,
@@ -3204,19 +3668,82 @@ function RecordsAdminShell(props) {
3204
3668
  }
3205
3669
  return parseRef(buildRef({ productId: selectedProductId }));
3206
3670
  }, [activeScope, selectedFacetRef, selectedProductId, drillTab, selectedVariantId, selectedBatchId]);
3671
+ const isCollection = cardinality === "collection";
3672
+ const editingItemRef = useMemo(() => {
3673
+ if (!isCollection) return null;
3674
+ if (!selectedItemId) return null;
3675
+ const baseRef = editingScope?.raw ?? "";
3676
+ return buildItemRef(baseRef, selectedItemId);
3677
+ }, [isCollection, selectedItemId, editingScope]);
3678
+ const editingTargetScope = useMemo(() => {
3679
+ if (!isCollection) return editingScope;
3680
+ if (!editingItemRef) return null;
3681
+ return parseRef(editingItemRef);
3682
+ }, [isCollection, editingScope, editingItemRef]);
3683
+ const skipNextItemResetRef = useRef(false);
3684
+ useEffect(() => {
3685
+ if (skipNextItemResetRef.current) {
3686
+ skipNextItemResetRef.current = false;
3687
+ return;
3688
+ }
3689
+ setSelectedItemId(null);
3690
+ }, [editingScope?.raw]);
3691
+ const collectionItems = useCollectionItems({
3692
+ ctx,
3693
+ scope: isCollection ? editingScope : null,
3694
+ enabled: isCollection
3695
+ });
3696
+ useEffect(() => {
3697
+ if (!deepLinkState.enabled) return;
3698
+ if (selectedItemId) return;
3699
+ deepLinkState.emit({ scope: editingScope?.raw ?? null, item: null }, "scope");
3700
+ lastAppliedDLRef.current = `${""}|${editingScope?.raw ?? ""}|${itemView}`;
3701
+ }, [deepLinkState.enabled, editingScope?.raw, selectedItemId, itemView]);
3702
+ useEffect(() => {
3703
+ if (!deepLinkState.enabled) return;
3704
+ const { item, scope, view } = deepLinkState.urlState;
3705
+ const sig = `${item ?? ""}|${scope ?? ""}|${view ?? ""}`;
3706
+ if (sig === lastAppliedDLRef.current) return;
3707
+ lastAppliedDLRef.current = sig;
3708
+ if (view && itemViews.includes(view) && view !== itemView) {
3709
+ setItemView(view);
3710
+ }
3711
+ const railRef = item ? item.includes("item:") ? item.slice(0, item.lastIndexOf("item:")).replace(/\/$/, "") : "" : scope ?? "";
3712
+ const itemId = item ? item.includes("item:") ? item.slice(item.lastIndexOf("item:") + "item:".length) : item : null;
3713
+ const parsed = railRef ? parseRef(railRef) : null;
3714
+ if (parsed?.productId) {
3715
+ if (activeScope !== "product") setActiveScope("product");
3716
+ if (selectedProductId !== parsed.productId) setSelectedProductId(parsed.productId);
3717
+ const nextDrill = parsed.batchId ? "batch" : parsed.variantId ? "variant" : "product";
3718
+ if (drillTab !== nextDrill) setDrillTab(nextDrill);
3719
+ if (parsed.variantId && selectedVariantId !== parsed.variantId) setSelectedVariantId(parsed.variantId);
3720
+ if (parsed.batchId && selectedBatchId !== parsed.batchId) setSelectedBatchId(parsed.batchId);
3721
+ } else if (parsed?.facetId) {
3722
+ if (activeScope !== "facet") setActiveScope("facet");
3723
+ if (selectedFacetRef !== railRef) setSelectedFacetRef(railRef);
3724
+ } else {
3725
+ if (selectedFacetRef) setSelectedFacetRef(void 0);
3726
+ }
3727
+ if (itemId !== selectedItemId) {
3728
+ if (railRef && railRef !== editingScope?.raw) {
3729
+ skipNextItemResetRef.current = true;
3730
+ }
3731
+ setSelectedItemId(itemId);
3732
+ }
3733
+ }, [deepLinkState.enabled, deepLinkState.urlState]);
3207
3734
  const supportedForResolution = useMemo(() => requestedScopes, [requestedScopes]);
3208
3735
  const resolved = useResolvedRecord({
3209
3736
  SL,
3210
3737
  appId,
3211
3738
  recordType,
3212
3739
  collectionId,
3213
- productId: editingScope?.productId,
3214
- variantId: editingScope?.variantId,
3215
- batchId: editingScope?.batchId,
3216
- facetId: editingScope?.facetId,
3217
- facetValue: editingScope?.facetValue,
3740
+ productId: editingTargetScope?.productId,
3741
+ variantId: editingTargetScope?.variantId,
3742
+ batchId: editingTargetScope?.batchId,
3743
+ facetId: editingTargetScope?.facetId,
3744
+ facetValue: editingTargetScope?.facetValue,
3218
3745
  supportedScopes: supportedForResolution,
3219
- enabled: !!editingScope
3746
+ enabled: !!editingTargetScope
3220
3747
  });
3221
3748
  const refetchAll = useCallback(() => {
3222
3749
  productBrowse.refetch();
@@ -3224,20 +3751,23 @@ function RecordsAdminShell(props) {
3224
3751
  facetBrowse.refetch();
3225
3752
  variantChildren.refetch();
3226
3753
  batchChildren.refetch();
3227
- }, [productBrowse, recordList, facetBrowse, variantChildren, batchChildren]);
3754
+ if (isCollection) collectionItems.refetch();
3755
+ }, [productBrowse, recordList, facetBrowse, variantChildren, batchChildren, isCollection, collectionItems]);
3228
3756
  const editorCtx = useRecordEditor({
3229
3757
  ctx,
3230
- scope: editingScope ?? parseRef(""),
3758
+ scope: editingTargetScope ?? parseRef(""),
3231
3759
  resolved: { data: resolved.data, source: resolved.source, sourceRef: resolved.sourceRef, parentValue: resolved.parentValue },
3232
3760
  defaultData,
3233
3761
  reseed: dirtyStrategy === "keep" ? "preserve-dirty" : "always",
3234
3762
  onSaved: () => {
3235
- onTelemetry?.({ type: "record.save", recordType, ref: editingScope?.raw ?? "", isCreate: resolved.source !== "self" });
3763
+ onTelemetry?.({ type: "record.save", recordType, ref: editingTargetScope?.raw ?? "", isCreate: resolved.source !== "self" });
3236
3764
  refetchAll();
3237
3765
  },
3238
3766
  onDeleted: () => {
3239
- onTelemetry?.({ type: "record.delete", recordType, ref: editingScope?.raw ?? "" });
3240
- if (activeScope === "facet") {
3767
+ onTelemetry?.({ type: "record.delete", recordType, ref: editingTargetScope?.raw ?? "" });
3768
+ if (isCollection && selectedItemId) {
3769
+ setSelectedItemId(null);
3770
+ } else if (activeScope === "facet") {
3241
3771
  setSelectedFacetRef(void 0);
3242
3772
  } else if (drillTab === "variant") {
3243
3773
  setSelectedVariantId(void 0);
@@ -3494,15 +4024,104 @@ function RecordsAdminShell(props) {
3494
4024
  };
3495
4025
  } : void 0;
3496
4026
  const onLeftSelectRef = useRef(null);
4027
+ const baseScopeRef = editingScope?.raw ?? "";
4028
+ const itemNounLabel = itemNoun || "item";
4029
+ const buildItemUrlValue = useCallback((id) => {
4030
+ return baseScopeRef ? `${baseScopeRef}/item:${id}` : id;
4031
+ }, [baseScopeRef]);
4032
+ const onItemOpen = useCallback((itemId) => {
4033
+ if (!isCollection) return;
4034
+ void runWithGuard(() => {
4035
+ setSelectedItemId(itemId);
4036
+ onTelemetry?.({ type: "item.open", recordType, scopeRef: baseScopeRef, itemId });
4037
+ deepLinkState.emit({ item: buildItemUrlValue(itemId) }, "item.open");
4038
+ });
4039
+ }, [isCollection, runWithGuard, onTelemetry, recordType, baseScopeRef, deepLinkState, buildItemUrlValue]);
4040
+ const onItemCreate = useCallback(() => {
4041
+ if (!isCollection) return;
4042
+ void runWithGuard(() => {
4043
+ const id = generateItemId ? generateItemId() : defaultItemId();
4044
+ setSelectedItemId(id);
4045
+ onTelemetry?.({ type: "item.create", recordType, scopeRef: baseScopeRef });
4046
+ deepLinkState.emit({ item: buildItemUrlValue(id) }, "item.open");
4047
+ });
4048
+ }, [isCollection, runWithGuard, generateItemId, onTelemetry, recordType, baseScopeRef, deepLinkState, buildItemUrlValue]);
4049
+ const onItemDelete = useCallback(async (itemId) => {
4050
+ if (!isCollection) return;
4051
+ const ref = buildItemRef(baseScopeRef, itemId);
4052
+ if (onBeforeDelete) {
4053
+ const ok = await onBeforeDelete(parseRef(ref));
4054
+ if (!ok) return;
4055
+ }
4056
+ try {
4057
+ const { deleteRecord: deleteRecord2 } = await import('../../records-66QWR67J.js');
4058
+ await deleteRecord2(ctx, ref);
4059
+ onTelemetry?.({ type: "item.delete", recordType, scopeRef: baseScopeRef, itemId });
4060
+ if (selectedItemId === itemId) setSelectedItemId(null);
4061
+ if (selectedItemId === itemId) deepLinkState.emit({ item: null }, "item.close");
4062
+ collectionItems.refetch();
4063
+ } catch (err) {
4064
+ console.error("[RecordsAdminShell] item delete failed", err);
4065
+ }
4066
+ }, [
4067
+ isCollection,
4068
+ baseScopeRef,
4069
+ ctx,
4070
+ onBeforeDelete,
4071
+ onTelemetry,
4072
+ recordType,
4073
+ selectedItemId,
4074
+ collectionItems,
4075
+ deepLinkState
4076
+ ]);
4077
+ const itemViewCtx = useMemo(() => ({
4078
+ onOpen: onItemOpen,
4079
+ onCreate: onItemCreate,
4080
+ onDelete: (id) => {
4081
+ void onItemDelete(id);
4082
+ },
4083
+ scope: editingScope ?? parseRef(""),
4084
+ selectedId: selectedItemId ?? void 0,
4085
+ isLoading: collectionItems.isLoading
4086
+ }), [onItemOpen, onItemCreate, onItemDelete, editingScope, selectedItemId, collectionItems.isLoading]);
4087
+ const itemPosition = useMemo(() => {
4088
+ if (!isCollection || !selectedItemId) return null;
4089
+ const idx = collectionItems.items.findIndex((it) => it.itemId === selectedItemId);
4090
+ if (idx < 0) return null;
4091
+ return { index: idx, total: collectionItems.items.length };
4092
+ }, [isCollection, selectedItemId, collectionItems.items]);
4093
+ const onItemBack = useCallback(() => {
4094
+ void runWithGuard(() => {
4095
+ setSelectedItemId(null);
4096
+ deepLinkState.emit({ item: null }, "item.close");
4097
+ });
4098
+ }, [runWithGuard, deepLinkState]);
4099
+ const stepToItem = useCallback((id) => {
4100
+ void runWithGuard(() => {
4101
+ setSelectedItemId(id);
4102
+ onTelemetry?.({ type: "item.open", recordType, scopeRef: baseScopeRef, itemId: id });
4103
+ deepLinkState.emit({ item: buildItemUrlValue(id) }, "item.step");
4104
+ });
4105
+ }, [runWithGuard, onTelemetry, recordType, baseScopeRef, deepLinkState, buildItemUrlValue]);
4106
+ const onItemPrev = useCallback(() => {
4107
+ if (!itemPosition || itemPosition.index <= 0) return;
4108
+ const next = collectionItems.items[itemPosition.index - 1];
4109
+ if (next?.itemId) stepToItem(next.itemId);
4110
+ }, [itemPosition, collectionItems.items, stepToItem]);
4111
+ const onItemNext = useCallback(() => {
4112
+ if (!itemPosition || itemPosition.index >= itemPosition.total - 1) return;
4113
+ const next = collectionItems.items[itemPosition.index + 1];
4114
+ if (next?.itemId) stepToItem(next.itemId);
4115
+ }, [itemPosition, collectionItems.items, stepToItem]);
3497
4116
  const renderEditorWithPreview = () => {
3498
- if (!editingScope) return null;
4117
+ if (!editingTargetScope) return null;
3499
4118
  const previewBody = renderPreview && effectivePreviewScope ? renderPreview({ resolved: editorCtx.value, previewScope: effectivePreviewScope }) : null;
3500
4119
  const scopePicker = previewScopePicker && effectivePreviewScope ? /* @__PURE__ */ jsx(
3501
4120
  PreviewScopePicker,
3502
4121
  {
3503
4122
  SL,
3504
4123
  collectionId,
3505
- editingScope,
4124
+ editingScope: editingTargetScope,
3506
4125
  value: effectivePreviewScope,
3507
4126
  onChange: setPreviewScope,
3508
4127
  showVariants: drillVariantsAllowed,
@@ -3510,6 +4129,20 @@ function RecordsAdminShell(props) {
3510
4129
  i18n: { previewAs: i18n.previewAs, previewAsDefault: i18n.previewAsDefault }
3511
4130
  }
3512
4131
  ) : null;
4132
+ const itemNav = isCollection && selectedItemId && itemPosition ? /* @__PURE__ */ jsx(
4133
+ EditorItemNav,
4134
+ {
4135
+ label: editorHeaderLabel,
4136
+ position: itemPosition.index + 1,
4137
+ total: itemPosition.total,
4138
+ onBack: onItemBack,
4139
+ onPrev: onItemPrev,
4140
+ onNext: onItemNext,
4141
+ canPrev: itemPosition.index > 0,
4142
+ canNext: itemPosition.index < itemPosition.total - 1,
4143
+ i18n
4144
+ }
4145
+ ) : null;
3513
4146
  const baseEditor = (extraFooter, inlinePreviewBody) => /* @__PURE__ */ jsx(
3514
4147
  RecordEditor,
3515
4148
  {
@@ -3518,7 +4151,7 @@ function RecordsAdminShell(props) {
3518
4151
  bulkActions: { ...csvBulk, i18n },
3519
4152
  preview: inlinePreviewBody,
3520
4153
  footerExtra: extraFooter,
3521
- onBeforeDelete: onBeforeDelete && editingScope ? () => onBeforeDelete(editingScope) : void 0,
4154
+ onBeforeDelete: onBeforeDelete && editingTargetScope ? () => onBeforeDelete(editingTargetScope) : void 0,
3522
4155
  headerLabel: editorHeaderLabel,
3523
4156
  headerSubtitle: editorHeaderSubtitle,
3524
4157
  headerMeta: editorHeaderMeta,
@@ -3528,64 +4161,84 @@ function RecordsAdminShell(props) {
3528
4161
  children: renderEditor(editorCtx)
3529
4162
  }
3530
4163
  );
3531
- if (!previewBody) return baseEditor();
4164
+ const withNav = (node) => itemNav ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full min-h-0", children: [
4165
+ itemNav,
4166
+ /* @__PURE__ */ jsx("div", { className: "flex-1 min-h-0 overflow-hidden", children: node })
4167
+ ] }) : node;
4168
+ if (!previewBody) return withNav(baseEditor());
3532
4169
  if (previewMode === "inline") {
3533
- return baseEditor(
4170
+ return withNav(baseEditor(
3534
4171
  void 0,
3535
4172
  /* @__PURE__ */ jsx(InlinePreview, { label: i18n.preview, scopePicker, children: previewBody })
3536
- );
4173
+ ));
3537
4174
  }
3538
4175
  if (previewMode === "side") {
3539
4176
  if (!sidePreviewOpen) {
3540
- return /* @__PURE__ */ jsx("div", { className: "relative h-full", children: baseEditor(
4177
+ return withNav(
4178
+ /* @__PURE__ */ jsxs("div", { className: "relative h-full", children: [
4179
+ baseEditor(),
4180
+ /* @__PURE__ */ jsxs(
4181
+ "button",
4182
+ {
4183
+ type: "button",
4184
+ className: "ra-preview-reopen",
4185
+ onClick: () => setSidePreviewOpen(true),
4186
+ "aria-label": i18n.openPreview,
4187
+ title: i18n.openPreview,
4188
+ children: [
4189
+ /* @__PURE__ */ jsx(Eye, { "aria-hidden": "true" }),
4190
+ i18n.preview
4191
+ ]
4192
+ }
4193
+ )
4194
+ ] })
4195
+ );
4196
+ }
4197
+ return withNav(
4198
+ /* @__PURE__ */ jsxs("div", { className: "grid h-full", style: { gridTemplateColumns: "minmax(0, 1fr) minmax(280px, 420px)" }, children: [
4199
+ /* @__PURE__ */ jsx("div", { className: "overflow-hidden", children: baseEditor() }),
3541
4200
  /* @__PURE__ */ jsx(
3542
- PreviewToggleButton,
4201
+ SidePreview,
3543
4202
  {
3544
- onClick: () => setSidePreviewOpen(true),
3545
- label: i18n.openPreview
4203
+ label: i18n.preview,
4204
+ scopePicker,
4205
+ onClose: () => setSidePreviewOpen(false),
4206
+ children: previewBody
3546
4207
  }
3547
4208
  )
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() }),
4209
+ ] })
4210
+ );
4211
+ }
4212
+ if (previewMode === "tab") {
4213
+ return withNav(
3552
4214
  /* @__PURE__ */ jsx(
3553
- SidePreview,
4215
+ TabbedPreview,
3554
4216
  {
3555
- label: i18n.preview,
4217
+ editor: baseEditor(),
4218
+ preview: previewBody,
3556
4219
  scopePicker,
3557
- onClose: () => setSidePreviewOpen(false),
3558
- children: previewBody
4220
+ i18n: { editor: i18n.editor, preview: i18n.preview }
3559
4221
  }
3560
4222
  )
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
4223
  );
3573
4224
  }
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
- ] });
4225
+ return withNav(
4226
+ /* @__PURE__ */ jsxs("div", { className: "relative h-full", children: [
4227
+ baseEditor(
4228
+ /* @__PURE__ */ jsx(PreviewToggleButton, { onClick: () => setDrawerOpen(true), label: i18n.openPreview })
4229
+ ),
4230
+ /* @__PURE__ */ jsx(
4231
+ DrawerPreview,
4232
+ {
4233
+ open: drawerOpen,
4234
+ onClose: () => setDrawerOpen(false),
4235
+ label: i18n.preview,
4236
+ scopePicker,
4237
+ children: previewBody
4238
+ }
4239
+ )
4240
+ ] })
4241
+ );
3589
4242
  };
3590
4243
  const isProductTab = activeScope === "product";
3591
4244
  const productPinned = !!contextScope?.productId;
@@ -3615,9 +4268,12 @@ function RecordsAdminShell(props) {
3615
4268
  }
3616
4269
  return productBrowse.items.map(productItemToSummary);
3617
4270
  }, [productPinned, contextScope, productBrowse.items]);
3618
- const leftItems = isProductTab ? productListItems : facetBrowse.items;
3619
- const leftLoading = isProductTab ? !productPinned && productBrowse.isLoading : facetBrowse.isLoading || recordList.isLoading || probe.isLoading;
3620
- const leftError = isProductTab ? productBrowse.error : facetBrowse.error ?? recordList.error;
4271
+ const isRuleTab = activeScope === "rule";
4272
+ const isGlobalTab = activeScope === "collection";
4273
+ const isRecordsTab = isRuleTab || isGlobalTab;
4274
+ const leftItems = isProductTab ? productListItems : isRecordsTab ? recordList.items : facetBrowse.items;
4275
+ const leftLoading = isProductTab ? !productPinned && productBrowse.isLoading : isRecordsTab ? recordList.isLoading || probe.isLoading : facetBrowse.isLoading || recordList.isLoading || probe.isLoading;
4276
+ const leftError = isProductTab ? productBrowse.error : isRecordsTab ? recordList.error : facetBrowse.error ?? recordList.error;
3621
4277
  const leftSelectedRef = isProductTab ? selectedProductId ? buildRef({ productId: selectedProductId }) : void 0 : selectedFacetRef;
3622
4278
  const onLeftSelect = (item) => {
3623
4279
  void runWithGuard(() => {
@@ -3648,6 +4304,25 @@ function RecordsAdminShell(props) {
3648
4304
  onDismiss: () => setClipboardNotice(null)
3649
4305
  }
3650
4306
  ),
4307
+ (() => {
4308
+ const showFloatHelp = !!intro && dismissed && resolvedReopenAffordance === "footer" && !headerWillRender;
4309
+ if (!showFloatHelp) return null;
4310
+ const reopenLabel = intro?.reopenLabel ?? `How ${label.toLowerCase()} works`;
4311
+ return /* @__PURE__ */ jsxs(
4312
+ "button",
4313
+ {
4314
+ type: "button",
4315
+ className: "ra-help-float",
4316
+ onClick: undismiss,
4317
+ "aria-label": reopenLabel,
4318
+ title: reopenLabel,
4319
+ children: [
4320
+ /* @__PURE__ */ jsx(HelpCircle, { "aria-hidden": "true" }),
4321
+ /* @__PURE__ */ jsx("span", { children: reopenLabel })
4322
+ ]
4323
+ }
4324
+ );
4325
+ })(),
3651
4326
  /* @__PURE__ */ jsxs("div", { className: "px-4 pt-4 space-y-3", children: [
3652
4327
  intro && !dismissed && /* @__PURE__ */ jsx(
3653
4328
  IntroCard,
@@ -3661,9 +4336,9 @@ function RecordsAdminShell(props) {
3661
4336
  }
3662
4337
  ),
3663
4338
  (() => {
3664
- const headerCustomised = !!title || !!subtitle || !!headerIcon || !!headerActions || showStats || !!statsItems || !!statsTitle || !!statsIcon;
3665
- const renderHeader = showHeader === true || showHeader !== false && headerCustomised;
3666
- if (!renderHeader) return null;
4339
+ if (!headerWillRender) return null;
4340
+ const showHeaderReopen = !!intro && dismissed && resolvedReopenAffordance === "header";
4341
+ const reopenLabel = intro?.reopenLabel ?? `How ${label.toLowerCase()} works`;
3667
4342
  return /* @__PURE__ */ jsx(
3668
4343
  ShellHeader,
3669
4344
  {
@@ -3681,18 +4356,32 @@ function RecordsAdminShell(props) {
3681
4356
  },
3682
4357
  statsItems,
3683
4358
  statsTitle,
3684
- statsIcon
4359
+ statsIcon,
4360
+ trailingSlot: showHeaderReopen ? /* @__PURE__ */ jsx(
4361
+ "button",
4362
+ {
4363
+ type: "button",
4364
+ onClick: undismiss,
4365
+ className: "ra-btn",
4366
+ "data-variant": "ghost",
4367
+ "aria-label": reopenLabel,
4368
+ title: reopenLabel,
4369
+ style: { width: "2rem", height: "2rem", padding: 0, justifyContent: "center" },
4370
+ children: /* @__PURE__ */ jsx(HelpCircle, { className: "w-4 h-4" })
4371
+ }
4372
+ ) : void 0
3685
4373
  }
3686
4374
  );
3687
4375
  })(),
3688
- /* @__PURE__ */ jsx(
4376
+ resolvedReopenAffordance === "inline" ? /* @__PURE__ */ jsx(
3689
4377
  UtilityRow,
3690
4378
  {
3691
- label,
4379
+ label: intro?.reopenLabel ? "" : label,
4380
+ customLabel: intro?.reopenLabel,
3692
4381
  introHidden: dismissed && !!intro,
3693
4382
  onShowIntro: undismiss
3694
4383
  }
3695
- ),
4384
+ ) : null,
3696
4385
  editorCtx.isDirty && /* @__PURE__ */ jsx(
3697
4386
  UnsavedBanner,
3698
4387
  {
@@ -3721,7 +4410,18 @@ function RecordsAdminShell(props) {
3721
4410
  className: "flex-1 grid border-t overflow-hidden",
3722
4411
  style: { gridTemplateColumns: "minmax(260px, 320px) 1fr", borderColor: "hsl(var(--ra-border))", marginTop: "0.75rem" },
3723
4412
  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: [
4413
+ /* @__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(
4414
+ SiblingRail,
4415
+ {
4416
+ items: collectionItems.items,
4417
+ selectedItemId,
4418
+ isLoading: collectionItems.isLoading,
4419
+ error: collectionItems.error,
4420
+ onBack: onItemBack,
4421
+ onSelect: onItemOpen,
4422
+ i18n
4423
+ }
4424
+ ) : /* @__PURE__ */ jsxs(Fragment, { children: [
3725
4425
  /* @__PURE__ */ jsx("div", { className: "p-2", children: /* @__PURE__ */ jsx(
3726
4426
  ScopeTabs,
3727
4427
  {
@@ -3776,27 +4476,6 @@ function RecordsAdminShell(props) {
3776
4476
  hideZero: ["partial"],
3777
4477
  i18n
3778
4478
  }
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
4479
  )
3801
4480
  ] }),
3802
4481
  /* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto", children: [
@@ -3820,7 +4499,6 @@ function RecordsAdminShell(props) {
3820
4499
  dirtyRef: editorCtx.isDirty ? editingScope?.raw : void 0,
3821
4500
  presentation: effectivePresentation,
3822
4501
  renderListRow,
3823
- renderCard,
3824
4502
  groupBy: effectiveGroupBy,
3825
4503
  rowClipboard
3826
4504
  }
@@ -3840,11 +4518,29 @@ function RecordsAdminShell(props) {
3840
4518
  ) })
3841
4519
  ] })
3842
4520
  ] })
3843
- ] }),
4521
+ ] }) }),
3844
4522
  /* @__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(
4523
+ isCollection && editingScope && !selectedItemId && /* @__PURE__ */ jsx(
4524
+ ItemListView,
4525
+ {
4526
+ items: collectionItems.items,
4527
+ isLoading: collectionItems.isLoading,
4528
+ error: collectionItems.error,
4529
+ ctx: itemViewCtx,
4530
+ itemNoun: itemNounLabel,
4531
+ view: itemView,
4532
+ views: itemViews,
4533
+ onViewChange: onItemViewChange,
4534
+ renderItemList,
4535
+ renderItemCard,
4536
+ renderItemEmpty,
4537
+ itemColumns,
4538
+ i18n
4539
+ }
4540
+ ),
4541
+ !isCollection && !editingScope && activeScope === "product" && !selectedProductId && /* @__PURE__ */ jsx(EmptyState, { title: i18n.emptyTitle, body: i18n.emptyBody }),
4542
+ !isCollection && !editingScope && activeScope === "facet" && /* @__PURE__ */ jsx(EmptyState, { title: i18n.emptyTitle, body: i18n.emptyBody }),
4543
+ isProductTab && selectedProductId && (!isCollection || selectedItemId) && /* @__PURE__ */ jsx(
3848
4544
  ProductDrillDown,
3849
4545
  {
3850
4546
  productLabel: productBrowse.items.find((p) => p.id === selectedProductId)?.name ?? selectedProductId,
@@ -3872,7 +4568,7 @@ function RecordsAdminShell(props) {
3872
4568
  batches: batchChildren.items,
3873
4569
  variantsLoading: variantChildren.isLoading,
3874
4570
  batchesLoading: batchChildren.isLoading,
3875
- children: editingScope ? renderEditorWithPreview() : /* @__PURE__ */ jsx(
4571
+ children: editingTargetScope ? renderEditorWithPreview() : /* @__PURE__ */ jsx(
3876
4572
  EmptyState,
3877
4573
  {
3878
4574
  title: drillTab === "variant" ? "Pick a variant" : "Pick a batch",
@@ -3881,7 +4577,7 @@ function RecordsAdminShell(props) {
3881
4577
  )
3882
4578
  }
3883
4579
  ),
3884
- !isProductTab && editingScope && renderEditorWithPreview()
4580
+ !isProductTab && editingTargetScope && (!isCollection || selectedItemId) && renderEditorWithPreview()
3885
4581
  ] })
3886
4582
  ]
3887
4583
  }
@@ -3953,6 +4649,87 @@ var RecordBrowser = ({
3953
4649
  ] })
3954
4650
  ] });
3955
4651
  };
4652
+ var initials2 = (s) => s.split(/\s+/).filter(Boolean).slice(0, 2).map((p) => p[0]?.toUpperCase() ?? "").join("") || "?";
4653
+ var DefaultRecordCard = ({ record, ctx, variant = "grid" }) => {
4654
+ const { selected, onSelect, isDirty, onCopy, onPaste, canPaste, pasteWillReplace, clipboardSourceLabel } = ctx;
4655
+ const aspect = variant === "gallery" ? "aspect-video" : "aspect-square";
4656
+ return /* @__PURE__ */ jsxs(
4657
+ "button",
4658
+ {
4659
+ type: "button",
4660
+ onClick: onSelect,
4661
+ className: cn(
4662
+ "group flex flex-col text-left rounded-md overflow-hidden border ra-card-hover",
4663
+ selected && "ring-2"
4664
+ ),
4665
+ style: {
4666
+ background: "hsl(var(--ra-surface))",
4667
+ borderColor: selected ? "var(--ra-row-active-bd)" : "hsl(var(--ra-border))",
4668
+ boxShadow: selected ? `0 0 0 2px hsl(var(--ra-accent) / 0.45), var(--ra-card-shadow)` : "var(--ra-card-shadow)"
4669
+ },
4670
+ children: [
4671
+ /* @__PURE__ */ jsxs(
4672
+ "div",
4673
+ {
4674
+ className: cn(aspect, "relative w-full flex items-center justify-center overflow-hidden"),
4675
+ style: { background: "hsl(var(--ra-muted))" },
4676
+ children: [
4677
+ record.thumbnail ? /* @__PURE__ */ jsx(
4678
+ "img",
4679
+ {
4680
+ src: record.thumbnail,
4681
+ alt: "",
4682
+ loading: "lazy",
4683
+ className: "w-full h-full object-cover"
4684
+ }
4685
+ ) : /* @__PURE__ */ jsx(
4686
+ "span",
4687
+ {
4688
+ className: "text-2xl ra-display",
4689
+ style: { color: "hsl(var(--ra-muted-text))" },
4690
+ children: initials2(record.label)
4691
+ }
4692
+ ),
4693
+ /* @__PURE__ */ jsx("div", { className: "absolute top-1.5 left-1.5", children: /* @__PURE__ */ jsx(StatusDot, { status: record.status }) }),
4694
+ isDirty && /* @__PURE__ */ jsx(
4695
+ "span",
4696
+ {
4697
+ title: "Unsaved changes",
4698
+ "aria-label": "Unsaved changes",
4699
+ className: "ra-status-dot ra-status-shared absolute top-1.5 right-1.5"
4700
+ }
4701
+ )
4702
+ ]
4703
+ }
4704
+ ),
4705
+ /* @__PURE__ */ jsxs("div", { className: "p-2.5 min-w-0", children: [
4706
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-1.5 min-w-0", children: [
4707
+ /* @__PURE__ */ jsx("div", { className: "ra-row-title flex-1 min-w-0", children: record.label }),
4708
+ (onCopy || onPaste) && /* @__PURE__ */ jsx(
4709
+ RowContextMenu,
4710
+ {
4711
+ onCopy,
4712
+ onPaste,
4713
+ canPaste,
4714
+ pasteWillReplace,
4715
+ pasteSourceLabel: clipboardSourceLabel,
4716
+ i18n: {
4717
+ copy: DEFAULT_I18N.copy,
4718
+ paste: DEFAULT_I18N.paste,
4719
+ pasteFrom: DEFAULT_I18N.pasteFrom,
4720
+ pasteReplace: DEFAULT_I18N.pasteReplace,
4721
+ clipboardEmpty: DEFAULT_I18N.clipboardEmpty
4722
+ }
4723
+ }
4724
+ )
4725
+ ] }),
4726
+ variant === "gallery" && record.subtitle && /* @__PURE__ */ jsx("div", { className: "ra-row-sub", children: record.subtitle }),
4727
+ 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}`)) })
4728
+ ] })
4729
+ ]
4730
+ }
4731
+ );
4732
+ };
3956
4733
  var Ctx = createContext({});
3957
4734
  var InheritanceProvider = ({
3958
4735
  parentValue,
@@ -4283,6 +5060,6 @@ function useMergedRecord(args) {
4283
5060
  };
4284
5061
  }
4285
5062
 
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 };
5063
+ 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, StatusIcon, TabbedPreview, UtilityRow, VariantList, buildItemRef, buildRef, checkPasteCompatibility, cloneValue, createDefaultDeepLinkAdapter, downloadBlob, exportCsv, importCsv, mergeIcons, parseRef, pickHeaderIcon, resolutionChain, resolveRecord, splitItemRef, statusToneLabel, useCollectedRecords, useCollectionItems, useDeepLinkState, useDirtyNavigation, useFacetBrowse, useIntroDismissed, useItemViewPref, useMergedRecord, usePresentationPref, useProductBrowse, useProductChildren, useRecordClipboard, useRecordEditor, useRecordList, useResolveAllRecords, useResolvedRecord, useRulePreview, useScopeProbe, useUnsavedGuard };
4287
5064
  //# sourceMappingURL=index.js.map
4288
5065
  //# sourceMappingURL=index.js.map