@proveanything/smartlinks-utils-ui 0.3.7 → 0.3.8

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,8 +1,9 @@
1
- import { styleInject } from '../../chunk-WFNEZQCD.js';
1
+ import { styleInject } from '../../chunk-NIAIQRFC.js';
2
2
  import { cn } from '../../chunk-L7FQ52F5.js';
3
3
  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, Box, AlertTriangle, Info, X, HelpCircle, Search, CornerDownLeft, Circle } from 'lucide-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, Box, X, AlertTriangle, Info, HelpCircle, Search, CornerDownLeft, Circle, AlertCircle, Undo2, Save } from 'lucide-react';
5
5
  import { useQueryClient, useInfiniteQuery, useQuery } from '@tanstack/react-query';
6
+ import { createPortal } from 'react-dom';
6
7
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
8
 
8
9
  var DEFAULT_ICONS = {
@@ -83,6 +84,7 @@ var DEFAULT_I18N = {
83
84
  unsavedPromptDiscard: "Discard changes",
84
85
  unsavedPromptCancel: "Stay here",
85
86
  unsavedPromptSave: "Save & continue",
87
+ unsavedBannerBody: "Unsaved changes on {name}",
86
88
  presentationList: "List",
87
89
  presentationGrid: "Grid",
88
90
  presentationGallery: "Gallery",
@@ -455,12 +457,24 @@ var resolveRecord = async (args) => {
455
457
  const editingScope = parsedRefToScope(args.target);
456
458
  const result = await matchRecords(args.ctx, target, { strategy: "all" }).catch(() => null);
457
459
  const records = result?.records ?? [];
460
+ console.info("[RecordsAdmin/resolveRecord]", {
461
+ editingScope,
462
+ target,
463
+ matchCount: records.length,
464
+ winnerScope: records[0]?.record?.scope,
465
+ winnerRef: records[0]?.record?.ref
466
+ });
458
467
  if (records.length === 0) {
459
468
  return { data: null, source: "empty" };
460
469
  }
461
470
  const winnerEntry = records[0];
462
471
  const winner = winnerEntry.record;
463
472
  const winnerIsSelf = scopesEqual(winner.scope, editingScope);
473
+ console.info("[RecordsAdmin/resolveRecord] classification", {
474
+ winnerIsSelf,
475
+ winnerScope: winner.scope,
476
+ editingScope
477
+ });
464
478
  if (winnerIsSelf) {
465
479
  const parent = records[1]?.record;
466
480
  return {
@@ -1101,6 +1115,144 @@ var useDirtyNavigation = ({
1101
1115
  );
1102
1116
  return { runWithGuard };
1103
1117
  };
1118
+ var ConfirmDialog = ({
1119
+ open,
1120
+ title,
1121
+ body,
1122
+ saveLabel,
1123
+ discardLabel,
1124
+ cancelLabel,
1125
+ onChoice
1126
+ }) => {
1127
+ const saveBtnRef = useRef(null);
1128
+ useEffect(() => {
1129
+ if (!open) return;
1130
+ const prev = document.body.style.overflow;
1131
+ document.body.style.overflow = "hidden";
1132
+ const t = window.setTimeout(() => saveBtnRef.current?.focus(), 0);
1133
+ const onKey = (e) => {
1134
+ if (e.key === "Escape") {
1135
+ e.stopPropagation();
1136
+ onChoice("cancel");
1137
+ }
1138
+ };
1139
+ window.addEventListener("keydown", onKey, true);
1140
+ return () => {
1141
+ window.clearTimeout(t);
1142
+ window.removeEventListener("keydown", onKey, true);
1143
+ document.body.style.overflow = prev;
1144
+ };
1145
+ }, [open, onChoice]);
1146
+ if (!open || typeof document === "undefined") return null;
1147
+ return createPortal(
1148
+ /* @__PURE__ */ jsxs(
1149
+ "div",
1150
+ {
1151
+ className: "ra-shell ra-confirm-root",
1152
+ role: "presentation",
1153
+ onMouseDown: (e) => e.stopPropagation(),
1154
+ onClick: (e) => e.stopPropagation(),
1155
+ children: [
1156
+ /* @__PURE__ */ jsx("div", { className: "ra-confirm-backdrop", onClick: () => onChoice("cancel") }),
1157
+ /* @__PURE__ */ jsxs(
1158
+ "div",
1159
+ {
1160
+ role: "alertdialog",
1161
+ "aria-modal": "true",
1162
+ "aria-labelledby": "ra-confirm-title",
1163
+ "aria-describedby": "ra-confirm-body",
1164
+ className: "ra-confirm-card",
1165
+ children: [
1166
+ /* @__PURE__ */ jsxs("div", { className: "ra-confirm-header", children: [
1167
+ /* @__PURE__ */ jsx("span", { className: "ra-confirm-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx(AlertTriangle, { className: "w-4 h-4" }) }),
1168
+ /* @__PURE__ */ jsx("h2", { id: "ra-confirm-title", className: "ra-confirm-title", children: title })
1169
+ ] }),
1170
+ /* @__PURE__ */ jsx("p", { id: "ra-confirm-body", className: "ra-confirm-body", children: body }),
1171
+ /* @__PURE__ */ jsxs("div", { className: "ra-confirm-actions", children: [
1172
+ /* @__PURE__ */ jsx(
1173
+ "button",
1174
+ {
1175
+ type: "button",
1176
+ className: "ra-confirm-btn ra-confirm-btn-ghost",
1177
+ onClick: () => onChoice("cancel"),
1178
+ children: cancelLabel
1179
+ }
1180
+ ),
1181
+ /* @__PURE__ */ jsx(
1182
+ "button",
1183
+ {
1184
+ type: "button",
1185
+ className: "ra-confirm-btn ra-confirm-btn-danger",
1186
+ onClick: () => onChoice("discard"),
1187
+ children: discardLabel
1188
+ }
1189
+ ),
1190
+ /* @__PURE__ */ jsx(
1191
+ "button",
1192
+ {
1193
+ type: "button",
1194
+ ref: saveBtnRef,
1195
+ className: "ra-confirm-btn ra-confirm-btn-primary",
1196
+ onClick: () => onChoice("save"),
1197
+ children: saveLabel
1198
+ }
1199
+ )
1200
+ ] })
1201
+ ]
1202
+ }
1203
+ )
1204
+ ]
1205
+ }
1206
+ ),
1207
+ document.body
1208
+ );
1209
+ };
1210
+ var DEFAULTS = {
1211
+ title: "Unsaved changes",
1212
+ body: "You have unsaved changes. Save them, discard them, or stay on this record?",
1213
+ saveLabel: "Save & continue",
1214
+ discardLabel: "Discard",
1215
+ cancelLabel: "Stay here"
1216
+ };
1217
+ var useConfirmDialog = () => {
1218
+ const [open, setOpen] = useState(false);
1219
+ const [state, setState] = useState(DEFAULTS);
1220
+ const resolverRef = useRef(null);
1221
+ const confirm = useCallback((i18n) => {
1222
+ setState({
1223
+ title: i18n?.title ?? DEFAULTS.title,
1224
+ body: i18n?.body ?? DEFAULTS.body,
1225
+ saveLabel: i18n?.save ?? DEFAULTS.saveLabel,
1226
+ discardLabel: i18n?.discard ?? DEFAULTS.discardLabel,
1227
+ cancelLabel: i18n?.cancel ?? DEFAULTS.cancelLabel
1228
+ });
1229
+ setOpen(true);
1230
+ return new Promise((resolve) => {
1231
+ resolverRef.current = resolve;
1232
+ });
1233
+ }, []);
1234
+ const handleChoice = useCallback((choice) => {
1235
+ setOpen(false);
1236
+ const r = resolverRef.current;
1237
+ resolverRef.current = null;
1238
+ r?.(choice);
1239
+ }, []);
1240
+ return {
1241
+ confirm,
1242
+ dialog: /* @__PURE__ */ jsx(
1243
+ ConfirmDialog,
1244
+ {
1245
+ open,
1246
+ title: state.title,
1247
+ body: state.body,
1248
+ saveLabel: state.saveLabel,
1249
+ discardLabel: state.discardLabel,
1250
+ cancelLabel: state.cancelLabel,
1251
+ onChoice: handleChoice
1252
+ }
1253
+ )
1254
+ };
1255
+ };
1104
1256
  var LABELS = {
1105
1257
  product: "Products",
1106
1258
  facet: "Shared",
@@ -1139,14 +1291,17 @@ var ScopeTabs = ({
1139
1291
  );
1140
1292
  }) });
1141
1293
  };
1142
- var StatusFilterPills = ({ value, onChange, counts, i18n }) => {
1294
+ var StatusFilterPills = ({ value, onChange, counts, i18n, hideZero }) => {
1143
1295
  const opts = [
1144
1296
  { key: "all", label: i18n.filterAll, count: counts.all },
1145
1297
  { key: "configured", label: i18n.filterConfigured, count: counts.configured },
1146
1298
  { key: "partial", label: i18n.filterPartial, count: counts.partial },
1147
1299
  { key: "empty", label: i18n.filterEmpty, count: counts.empty }
1148
1300
  ];
1149
- return /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5", children: opts.map((o) => {
1301
+ const visible = opts.filter(
1302
+ (o) => o.key === value || !hideZero?.includes(o.key) || o.count > 0
1303
+ );
1304
+ return /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5", children: visible.map((o) => {
1150
1305
  const active = value === o.key;
1151
1306
  return /* @__PURE__ */ jsxs(
1152
1307
  "button",
@@ -1641,25 +1796,49 @@ function RecordEditor({
1641
1796
  preview,
1642
1797
  bulkActions,
1643
1798
  footerExtra,
1644
- onBeforeDelete
1799
+ onBeforeDelete,
1800
+ headerLabel,
1801
+ headerSubtitle,
1802
+ headerMeta
1645
1803
  }) {
1646
- const sourceLabel = ctx.source === "self" ? "Own" : ctx.source === "inherited" ? "Inherited" : "New";
1804
+ const sourceLabel = ctx.source === "self" ? "Customised" : ctx.source === "inherited" ? "Inherited" : null;
1647
1805
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full", children: [
1648
1806
  /* @__PURE__ */ jsxs(
1649
1807
  "header",
1650
1808
  {
1651
- className: "sticky top-0 z-10 px-5 py-3 border-b flex items-center justify-between gap-3",
1809
+ className: "sticky top-0 z-40 px-5 py-3 border-b flex items-start justify-between gap-3",
1652
1810
  style: { borderColor: "hsl(var(--ra-border))", background: "hsl(var(--ra-surface))" },
1653
1811
  children: [
1654
1812
  /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
1655
- /* @__PURE__ */ jsx(ScopeBreadcrumb, { scope: ctx.scope }),
1656
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 mt-1", children: [
1657
- /* @__PURE__ */ jsx(StatusDot, { source: ctx.source }),
1658
- /* @__PURE__ */ jsx("span", { className: "text-[10px] uppercase tracking-wide", style: { color: "hsl(var(--ra-muted-text))" }, children: sourceLabel }),
1813
+ headerLabel ? /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
1814
+ /* @__PURE__ */ jsx(
1815
+ "div",
1816
+ {
1817
+ className: "text-sm font-medium truncate",
1818
+ style: { color: "hsl(var(--ra-text))" },
1819
+ title: headerLabel,
1820
+ children: headerLabel
1821
+ }
1822
+ ),
1823
+ headerSubtitle && /* @__PURE__ */ jsx(
1824
+ "div",
1825
+ {
1826
+ className: "text-xs truncate",
1827
+ style: { color: "hsl(var(--ra-muted-text))" },
1828
+ title: headerSubtitle,
1829
+ children: headerSubtitle
1830
+ }
1831
+ )
1832
+ ] }) : /* @__PURE__ */ jsx(ScopeBreadcrumb, { scope: ctx.scope }),
1833
+ (sourceLabel || ctx.isDirty) && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 mt-1", children: [
1834
+ sourceLabel && /* @__PURE__ */ jsxs(Fragment, { children: [
1835
+ /* @__PURE__ */ jsx(StatusDot, { source: ctx.source }),
1836
+ /* @__PURE__ */ jsx("span", { className: "text-[10px] uppercase tracking-wide", style: { color: "hsl(var(--ra-muted-text))" }, children: sourceLabel })
1837
+ ] }),
1659
1838
  ctx.isDirty && /* @__PURE__ */ jsxs(
1660
1839
  "span",
1661
1840
  {
1662
- className: "ml-2 flex items-center gap-1 text-[10px] uppercase tracking-wide",
1841
+ className: `flex items-center gap-1 text-[10px] uppercase tracking-wide ${sourceLabel ? "ml-2" : ""}`,
1663
1842
  style: { color: "hsl(var(--ra-accent))" },
1664
1843
  children: [
1665
1844
  /* @__PURE__ */ jsx("span", { className: "ra-status-dot ra-status-shared", "aria-hidden": "true" }),
@@ -1669,7 +1848,22 @@ function RecordEditor({
1669
1848
  )
1670
1849
  ] })
1671
1850
  ] }),
1672
- bulkActions && /* @__PURE__ */ jsx(BulkActionsMenu, { ...bulkActions, i18n })
1851
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2 shrink-0", children: [
1852
+ headerMeta && /* @__PURE__ */ jsx(
1853
+ "code",
1854
+ {
1855
+ className: "text-[10px] font-mono px-1.5 py-0.5 rounded truncate max-w-[14rem] mt-0.5",
1856
+ style: {
1857
+ color: "hsl(var(--ra-muted-text) / 0.85)",
1858
+ background: "hsl(var(--ra-muted) / 0.5)",
1859
+ border: "1px solid hsl(var(--ra-border) / 0.6)"
1860
+ },
1861
+ title: headerMeta,
1862
+ children: headerMeta
1863
+ }
1864
+ ),
1865
+ bulkActions && /* @__PURE__ */ jsx(BulkActionsMenu, { ...bulkActions, i18n })
1866
+ ] })
1673
1867
  ]
1674
1868
  }
1675
1869
  ),
@@ -1884,13 +2078,29 @@ var InlinePreview = ({ children, scopePicker, label = "Preview" }) => /* @__PURE
1884
2078
  ] }),
1885
2079
  children
1886
2080
  ] });
1887
- var SidePreview = ({ children, scopePicker, label = "Preview" }) => /* @__PURE__ */ jsxs("div", { className: "ra-preview-rail", children: [
2081
+ var SidePreview = ({
2082
+ children,
2083
+ scopePicker,
2084
+ label = "Preview",
2085
+ onClose
2086
+ }) => /* @__PURE__ */ jsxs("div", { className: "ra-preview-rail", children: [
1888
2087
  /* @__PURE__ */ jsxs("header", { className: "ra-preview-rail-header", children: [
1889
2088
  /* @__PURE__ */ jsxs("div", { className: "ra-preview-rail-title", children: [
1890
2089
  /* @__PURE__ */ jsx(Eye, { className: "w-3 h-3" }),
1891
2090
  label
1892
2091
  ] }),
1893
- scopePicker && /* @__PURE__ */ jsx("div", { className: "ml-auto", children: scopePicker })
2092
+ scopePicker && /* @__PURE__ */ jsx("div", { className: "ml-auto", children: scopePicker }),
2093
+ onClose && /* @__PURE__ */ jsx(
2094
+ "button",
2095
+ {
2096
+ type: "button",
2097
+ onClick: onClose,
2098
+ "aria-label": "Close preview",
2099
+ className: scopePicker ? "p-1 rounded hover:bg-[hsl(var(--ra-muted))]" : "ml-auto p-1 rounded hover:bg-[hsl(var(--ra-muted))]",
2100
+ style: { color: "hsl(var(--ra-muted-text))" },
2101
+ children: /* @__PURE__ */ jsx(X, { className: "w-3.5 h-3.5" })
2102
+ }
2103
+ )
1894
2104
  ] }),
1895
2105
  /* @__PURE__ */ jsx("div", { className: "ra-preview-rail-body", children })
1896
2106
  ] });
@@ -2004,7 +2214,13 @@ var PreviewScopePicker = ({
2004
2214
  showBatches,
2005
2215
  i18n
2006
2216
  }) => {
2007
- const products = useProductBrowse({ SL, collectionId, pageSize: 100 });
2217
+ const productPinned = !!editingScope.productId;
2218
+ const products = useProductBrowse({
2219
+ SL,
2220
+ collectionId,
2221
+ pageSize: 100,
2222
+ enabled: !productPinned
2223
+ });
2008
2224
  const variants = useProductChildren({
2009
2225
  SL,
2010
2226
  collectionId,
@@ -2021,6 +2237,27 @@ var PreviewScopePicker = ({
2021
2237
  () => value.raw === editingScope.raw,
2022
2238
  [value.raw, editingScope.raw]
2023
2239
  );
2240
+ useEffect(() => {
2241
+ if (productPinned) return;
2242
+ if (value.productId) return;
2243
+ const first = products.items[0];
2244
+ if (!first) return;
2245
+ onChange({
2246
+ ...value,
2247
+ productId: first.id,
2248
+ variantId: void 0,
2249
+ batchId: void 0,
2250
+ raw: `product:${first.id}`
2251
+ });
2252
+ }, [productPinned, value.productId, products.items]);
2253
+ const [productPickerOpen, setProductPickerOpen] = useState(false);
2254
+ const showProductPicker = !productPinned && products.items.length > 1;
2255
+ const showVariantPicker = showVariants && !!value.productId && variants.items.length > 0;
2256
+ const showBatchPicker = showBatches && !!value.productId && batches.items.length > 0;
2257
+ if (!showProductPicker && !showVariantPicker && !showBatchPicker) {
2258
+ return null;
2259
+ }
2260
+ const currentProductName = products.items.find((p) => p.id === value.productId)?.name ?? value.productId ?? "";
2024
2261
  const selectStyle = {
2025
2262
  borderColor: "hsl(var(--ra-border))",
2026
2263
  color: "hsl(var(--ra-text))"
@@ -2050,30 +2287,44 @@ var PreviewScopePicker = ({
2050
2287
  ]
2051
2288
  }
2052
2289
  ),
2053
- /* @__PURE__ */ jsxs(
2290
+ showProductPicker && !productPickerOpen && currentProductName && /* @__PURE__ */ jsxs(
2291
+ "button",
2292
+ {
2293
+ type: "button",
2294
+ onClick: () => setProductPickerOpen(true),
2295
+ className: "text-[10px] px-2 py-1 rounded-md border hover:bg-[hsl(var(--ra-muted))] inline-flex items-center gap-1 max-w-[12rem] truncate",
2296
+ style: selectStyle,
2297
+ title: `Preview as ${currentProductName} \u2014 click to change`,
2298
+ children: [
2299
+ "as ",
2300
+ /* @__PURE__ */ jsx("span", { className: "font-medium truncate", children: currentProductName }),
2301
+ /* @__PURE__ */ jsx(ChevronDown, { className: "w-3 h-3 opacity-60" })
2302
+ ]
2303
+ }
2304
+ ),
2305
+ showProductPicker && productPickerOpen && /* @__PURE__ */ jsx(
2054
2306
  "select",
2055
2307
  {
2056
2308
  className: SELECT_CLS,
2057
2309
  style: selectStyle,
2310
+ autoFocus: true,
2311
+ onBlur: () => setProductPickerOpen(false),
2058
2312
  value: value.productId ?? "",
2059
2313
  onChange: (e) => {
2060
2314
  const productId = e.target.value || void 0;
2061
2315
  onChange({
2062
2316
  ...value,
2063
2317
  productId,
2064
- // Clear variant/batch when switching products.
2065
2318
  variantId: void 0,
2066
2319
  batchId: void 0,
2067
2320
  raw: productId ? `product:${productId}` : ""
2068
2321
  });
2322
+ setProductPickerOpen(false);
2069
2323
  },
2070
- children: [
2071
- /* @__PURE__ */ jsx("option", { value: "", children: "\u2014 Any product \u2014" }),
2072
- products.items.map((p) => /* @__PURE__ */ jsx("option", { value: p.id, children: p.name }, p.id))
2073
- ]
2324
+ children: products.items.map((p) => /* @__PURE__ */ jsx("option", { value: p.id, children: p.name }, p.id))
2074
2325
  }
2075
2326
  ),
2076
- showVariants && value.productId && variants.items.length > 0 && /* @__PURE__ */ jsxs(
2327
+ showVariantPicker && /* @__PURE__ */ jsxs(
2077
2328
  "select",
2078
2329
  {
2079
2330
  className: SELECT_CLS,
@@ -2094,7 +2345,7 @@ var PreviewScopePicker = ({
2094
2345
  ]
2095
2346
  }
2096
2347
  ),
2097
- showBatches && value.productId && batches.items.length > 0 && /* @__PURE__ */ jsxs(
2348
+ showBatchPicker && /* @__PURE__ */ jsxs(
2098
2349
  "select",
2099
2350
  {
2100
2351
  className: SELECT_CLS,
@@ -2241,6 +2492,61 @@ function ShellHeader({
2241
2492
  ] })
2242
2493
  ] });
2243
2494
  }
2495
+ var UnsavedBanner = ({
2496
+ label,
2497
+ context,
2498
+ isSaving,
2499
+ saveError,
2500
+ onSave,
2501
+ onDiscard,
2502
+ saveLabel,
2503
+ discardLabel,
2504
+ bodyTemplate,
2505
+ savingLabel,
2506
+ errorLabel
2507
+ }) => {
2508
+ const name = label ?? context ?? "this record";
2509
+ const message = bodyTemplate.replace("{name}", name);
2510
+ return /* @__PURE__ */ jsxs("div", { className: "ra-unsaved-banner", role: "status", "aria-live": "polite", children: [
2511
+ /* @__PURE__ */ jsx("span", { className: "ra-unsaved-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx(AlertCircle, { className: "w-3.5 h-3.5" }) }),
2512
+ /* @__PURE__ */ jsxs("span", { className: "ra-unsaved-text", children: [
2513
+ message,
2514
+ context && label && /* @__PURE__ */ jsxs("span", { className: "ra-unsaved-context", children: [
2515
+ " \xB7 ",
2516
+ context
2517
+ ] })
2518
+ ] }),
2519
+ saveError != null && !isSaving && /* @__PURE__ */ jsx("span", { className: "ra-unsaved-error", role: "alert", children: errorLabel ?? "Save failed" }),
2520
+ /* @__PURE__ */ jsxs("div", { className: "ra-unsaved-actions", children: [
2521
+ /* @__PURE__ */ jsxs(
2522
+ "button",
2523
+ {
2524
+ type: "button",
2525
+ className: "ra-unsaved-btn ra-unsaved-btn-ghost",
2526
+ onClick: onDiscard,
2527
+ disabled: isSaving,
2528
+ children: [
2529
+ /* @__PURE__ */ jsx(Undo2, { className: "w-3 h-3" }),
2530
+ discardLabel
2531
+ ]
2532
+ }
2533
+ ),
2534
+ /* @__PURE__ */ jsxs(
2535
+ "button",
2536
+ {
2537
+ type: "button",
2538
+ className: "ra-unsaved-btn ra-unsaved-btn-primary",
2539
+ onClick: onSave,
2540
+ disabled: isSaving,
2541
+ children: [
2542
+ /* @__PURE__ */ jsx(Save, { className: "w-3 h-3" }),
2543
+ isSaving ? savingLabel ?? "Saving\u2026" : saveLabel
2544
+ ]
2545
+ }
2546
+ )
2547
+ ] })
2548
+ ] });
2549
+ };
2244
2550
 
2245
2551
  // src/components/RecordsAdmin/data/csv.ts
2246
2552
  var escapeCell = (s) => {
@@ -2350,8 +2656,8 @@ var downloadBlob = (blob, filename) => {
2350
2656
  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');
2351
2657
 
2352
2658
  // src/components/RecordsAdmin/shell/shell.css
2353
- 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: 30;\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");
2354
- var TOP_LEVEL_SCOPES = ["product", "facet"];
2659
+ 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");
2660
+ var TOP_LEVEL_SCOPES = ["facet", "product"];
2355
2661
  var defaultItemId = () => {
2356
2662
  const time = Date.now().toString(36);
2357
2663
  const rand = Math.random().toString(36).slice(2, 8);
@@ -2390,7 +2696,11 @@ function RecordsAdminShell(props) {
2390
2696
  className,
2391
2697
  previewMode = "inline",
2392
2698
  previewScopePicker = false,
2393
- dirtyStrategy = "prompt",
2699
+ // Default to `keep` — admins can tab around freely while edits are
2700
+ // preserved per editor mount, and the inline UnsavedBanner surfaces the
2701
+ // dirty state at the top of the shell with Save/Discard buttons. Hosts
2702
+ // that want the old blocking behaviour can opt back into `'prompt'`.
2703
+ dirtyStrategy = "keep",
2394
2704
  onBeforeDelete,
2395
2705
  disableBeforeUnload = false,
2396
2706
  presentations = ["list"],
@@ -2434,7 +2744,7 @@ function RecordsAdminShell(props) {
2434
2744
  );
2435
2745
  const probe = useScopeProbe({ SL, collectionId });
2436
2746
  const topLevelScopes = useMemo(
2437
- () => requestedScopes.filter((s) => TOP_LEVEL_SCOPES.includes(s)),
2747
+ () => TOP_LEVEL_SCOPES.filter((s) => requestedScopes.includes(s)),
2438
2748
  [requestedScopes]
2439
2749
  );
2440
2750
  const drillVariantsAllowed = useMemo(
@@ -2448,6 +2758,7 @@ function RecordsAdminShell(props) {
2448
2758
  const initialScope = useMemo(() => {
2449
2759
  if (contextScope?.productId && topLevelScopes.includes("product")) return "product";
2450
2760
  if (defaultScope && topLevelScopes.includes(defaultScope)) return defaultScope;
2761
+ if (topLevelScopes.includes("facet")) return "facet";
2451
2762
  return topLevelScopes[0] ?? "product";
2452
2763
  }, [contextScope?.productId, defaultScope, topLevelScopes]);
2453
2764
  const [activeScope, setActiveScope] = useState(initialScope);
@@ -2597,13 +2908,19 @@ function RecordsAdminShell(props) {
2597
2908
  useUnsavedGuard({
2598
2909
  isDirty: editorCtx.isDirty,
2599
2910
  label: recordType,
2600
- disableBeforeUnload
2911
+ disableBeforeUnload,
2912
+ // In `keep` mode we don't want the host iframe to pop its own native
2913
+ // confirm — the banner is the canonical surface. Hosts on `prompt` /
2914
+ // `autosave` opt back into platform notifications.
2915
+ disableParentMessage: dirtyStrategy === "keep"
2601
2916
  });
2917
+ const dirtyConfirm = useConfirmDialog();
2602
2918
  const { runWithGuard } = useDirtyNavigation({
2603
2919
  strategy: dirtyStrategy,
2604
2920
  isDirty: editorCtx.isDirty,
2605
2921
  save: editorCtx.save,
2606
2922
  reset: editorCtx.reset,
2923
+ confirm: dirtyConfirm.confirm,
2607
2924
  i18n: {
2608
2925
  title: i18n.unsavedPromptTitle,
2609
2926
  body: i18n.unsavedPromptBody,
@@ -2640,11 +2957,40 @@ function RecordsAdminShell(props) {
2640
2957
  const csvBulk = csvSchema ? { onImportCsv: handleImport, onExportCsv: handleExport } : {};
2641
2958
  const [previewScope, setPreviewScope] = useState(null);
2642
2959
  const [drawerOpen, setDrawerOpen] = useState(false);
2960
+ const [sidePreviewOpen, setSidePreviewOpen] = useState(true);
2643
2961
  useEffect(() => {
2644
2962
  if (!editingScope) return;
2645
2963
  setPreviewScope((cur) => cur === null ? editingScope : cur);
2646
2964
  }, [editingScope]);
2647
2965
  const effectivePreviewScope = previewScope ?? editingScope;
2966
+ const editorHeaderLabel = useMemo(() => {
2967
+ if (!editingScope) return void 0;
2968
+ if (activeScope === "facet" && selectedFacetRef) {
2969
+ const hit = facetBrowse.items.find((it) => it.ref === selectedFacetRef);
2970
+ return hit?.label;
2971
+ }
2972
+ if (activeScope === "product" && selectedProductId) {
2973
+ const hit = productBrowse.items.find((it) => it.id === selectedProductId);
2974
+ return hit?.name ?? selectedProductId;
2975
+ }
2976
+ return void 0;
2977
+ }, [activeScope, editingScope, selectedFacetRef, selectedProductId, facetBrowse.items, productBrowse.items]);
2978
+ const editorHeaderSubtitle = useMemo(() => {
2979
+ if (!editingScope) return void 0;
2980
+ if (activeScope === "facet" && selectedFacetRef) {
2981
+ const hit = facetBrowse.items.find((it) => it.ref === selectedFacetRef);
2982
+ return hit?.subtitle;
2983
+ }
2984
+ return void 0;
2985
+ }, [activeScope, editingScope, selectedFacetRef, selectedProductId, facetBrowse.items, productBrowse.items]);
2986
+ const editorHeaderMeta = useMemo(() => {
2987
+ if (!editingScope) return void 0;
2988
+ if (activeScope === "product" && selectedProductId) {
2989
+ const hit = productBrowse.items.find((it) => it.id === selectedProductId);
2990
+ return hit?.sku ?? selectedProductId;
2991
+ }
2992
+ return void 0;
2993
+ }, [activeScope, editingScope, selectedProductId, productBrowse.items]);
2648
2994
  const renderEditorWithPreview = () => {
2649
2995
  if (!editingScope) return null;
2650
2996
  const previewBody = renderPreview && effectivePreviewScope ? renderPreview({ resolved: editorCtx.value, previewScope: effectivePreviewScope }) : null;
@@ -2670,6 +3016,9 @@ function RecordsAdminShell(props) {
2670
3016
  preview: inlinePreviewBody,
2671
3017
  footerExtra: extraFooter,
2672
3018
  onBeforeDelete: onBeforeDelete && editingScope ? () => onBeforeDelete(editingScope) : void 0,
3019
+ headerLabel: editorHeaderLabel,
3020
+ headerSubtitle: editorHeaderSubtitle,
3021
+ headerMeta: editorHeaderMeta,
2673
3022
  children: renderEditor(editorCtx)
2674
3023
  }
2675
3024
  );
@@ -2681,9 +3030,28 @@ function RecordsAdminShell(props) {
2681
3030
  );
2682
3031
  }
2683
3032
  if (previewMode === "side") {
3033
+ if (!sidePreviewOpen) {
3034
+ return /* @__PURE__ */ jsx("div", { className: "relative h-full", children: baseEditor(
3035
+ /* @__PURE__ */ jsx(
3036
+ PreviewToggleButton,
3037
+ {
3038
+ onClick: () => setSidePreviewOpen(true),
3039
+ label: i18n.openPreview
3040
+ }
3041
+ )
3042
+ ) });
3043
+ }
2684
3044
  return /* @__PURE__ */ jsxs("div", { className: "grid h-full", style: { gridTemplateColumns: "minmax(0, 1fr) minmax(280px, 420px)" }, children: [
2685
3045
  /* @__PURE__ */ jsx("div", { className: "overflow-hidden", children: baseEditor() }),
2686
- /* @__PURE__ */ jsx(SidePreview, { label: i18n.preview, scopePicker, children: previewBody })
3046
+ /* @__PURE__ */ jsx(
3047
+ SidePreview,
3048
+ {
3049
+ label: i18n.preview,
3050
+ scopePicker,
3051
+ onClose: () => setSidePreviewOpen(false),
3052
+ children: previewBody
3053
+ }
3054
+ )
2687
3055
  ] });
2688
3056
  }
2689
3057
  if (previewMode === "tab") {
@@ -2715,6 +3083,18 @@ function RecordsAdminShell(props) {
2715
3083
  };
2716
3084
  const isProductTab = activeScope === "product";
2717
3085
  const productPinned = !!contextScope?.productId;
3086
+ const effectivePresentation = isProductTab ? presentation : "list";
3087
+ const showPresentationSwitcher = isProductTab && presentations.length > 1;
3088
+ const effectiveGroupBy = useMemo(() => {
3089
+ if (groupBy) return groupBy;
3090
+ if (isProductTab) return void 0;
3091
+ return (record) => {
3092
+ const key = record.scope.facetId;
3093
+ if (!key) return null;
3094
+ const label2 = record.subtitle ?? key;
3095
+ return { key, label: label2 };
3096
+ };
3097
+ }, [groupBy, isProductTab]);
2718
3098
  const productListItems = useMemo(() => {
2719
3099
  if (productPinned) {
2720
3100
  return [{
@@ -2751,6 +3131,7 @@ function RecordsAdminShell(props) {
2751
3131
  className: `ra-shell flex flex-col h-full ${className ?? ""}`,
2752
3132
  "data-density": density,
2753
3133
  children: [
3134
+ dirtyConfirm.dialog,
2754
3135
  /* @__PURE__ */ jsxs("div", { className: "px-4 pt-4 space-y-3", children: [
2755
3136
  intro && !dismissed && /* @__PURE__ */ jsx(
2756
3137
  IntroCard,
@@ -2795,6 +3176,25 @@ function RecordsAdminShell(props) {
2795
3176
  introHidden: dismissed && !!intro,
2796
3177
  onShowIntro: undismiss
2797
3178
  }
3179
+ ),
3180
+ editorCtx.isDirty && /* @__PURE__ */ jsx(
3181
+ UnsavedBanner,
3182
+ {
3183
+ label: editorHeaderLabel,
3184
+ context: editorHeaderSubtitle,
3185
+ isSaving: !!editorCtx.isSaving,
3186
+ saveError: editorCtx.saveError,
3187
+ onSave: () => {
3188
+ void editorCtx.save().catch(() => {
3189
+ });
3190
+ },
3191
+ onDiscard: editorCtx.reset,
3192
+ saveLabel: i18n.save,
3193
+ discardLabel: i18n.discard,
3194
+ savingLabel: i18n.saving,
3195
+ errorLabel: i18n.saveError,
3196
+ bodyTemplate: i18n.unsavedBannerBody
3197
+ }
2798
3198
  )
2799
3199
  ] }),
2800
3200
  /* @__PURE__ */ jsxs(
@@ -2842,14 +3242,23 @@ function RecordsAdminShell(props) {
2842
3242
  /* @__PURE__ */ jsx(
2843
3243
  PresentationSwitcher,
2844
3244
  {
2845
- options: presentations,
3245
+ options: showPresentationSwitcher ? presentations : [],
2846
3246
  value: presentation,
2847
3247
  onChange: onPresentationChange,
2848
3248
  i18n
2849
3249
  }
2850
3250
  )
2851
3251
  ] }),
2852
- !isProductTab && /* @__PURE__ */ jsx(StatusFilterPills, { value: filter, onChange: setFilter, counts: facetBrowse.counts, i18n }),
3252
+ !isProductTab && /* @__PURE__ */ jsx(
3253
+ StatusFilterPills,
3254
+ {
3255
+ value: filter,
3256
+ onChange: setFilter,
3257
+ counts: facetBrowse.counts,
3258
+ hideZero: ["partial"],
3259
+ i18n
3260
+ }
3261
+ ),
2853
3262
  cardinality === "collection" && !isProductTab && editingScope && /* @__PURE__ */ jsxs(
2854
3263
  "button",
2855
3264
  {
@@ -2891,10 +3300,10 @@ function RecordsAdminShell(props) {
2891
3300
  selectedRef: leftSelectedRef,
2892
3301
  onSelect: onLeftSelect,
2893
3302
  dirtyRef: editorCtx.isDirty ? editingScope?.raw : void 0,
2894
- presentation,
3303
+ presentation: effectivePresentation,
2895
3304
  renderListRow,
2896
3305
  renderCard,
2897
- groupBy
3306
+ groupBy: effectiveGroupBy
2898
3307
  }
2899
3308
  ),
2900
3309
  isProductTab && !productPinned && productBrowse.hasNextPage && /* @__PURE__ */ jsx("div", { className: "p-2", children: /* @__PURE__ */ jsx(