@proveanything/smartlinks-utils-ui 0.3.12 → 0.3.14

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.
@@ -70,17 +70,26 @@ var getRecordByRef = async (ctx, ref) => {
70
70
  };
71
71
  var upsertRecord = async (ctx, write) => {
72
72
  const ref = write.ref ?? deriveRefFromScope(write.scope);
73
- const res = await ctx.SL.app.records.upsert(ctx.collectionId, ctx.appId, {
73
+ const payload = {
74
74
  ref,
75
75
  ...ctx.recordType ? { recordType: ctx.recordType } : {},
76
- scope: write.scope,
77
76
  data: write.data,
78
77
  status: write.status,
79
78
  startsAt: write.startsAt,
80
79
  expiresAt: write.expiresAt,
81
80
  customId: write.customId,
82
81
  sourceSystem: write.sourceSystem
83
- });
82
+ };
83
+ if (write.facetRule && write.facetRule.all && write.facetRule.all.length > 0) {
84
+ payload.facetRule = write.facetRule;
85
+ } else {
86
+ payload.scope = write.scope;
87
+ }
88
+ const res = await ctx.SL.app.records.upsert(
89
+ ctx.collectionId,
90
+ ctx.appId,
91
+ payload
92
+ );
84
93
  return { record: res, isCreate: !!res?.created };
85
94
  };
86
95
  var upsertRecordForScope = async (ctx, scope, data, extra = {}) => upsertRecord(ctx, {
@@ -168,5 +177,5 @@ var deriveRefFromScope = (scope) => {
168
177
  };
169
178
 
170
179
  export { bulkDelete, bulkUpsert, deleteRecord, getRecordByRef, listRecords, matchRecords, parsedRefToScope, parsedRefToTarget, restoreRecord, scopesEqual, upsertRecord, upsertRecordForScope };
171
- //# sourceMappingURL=chunk-TY2UIZ24.js.map
172
- //# sourceMappingURL=chunk-TY2UIZ24.js.map
180
+ //# sourceMappingURL=chunk-76Y4UTYQ.js.map
181
+ //# sourceMappingURL=chunk-76Y4UTYQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/RecordsAdmin/data/scopeBridge.ts","../src/components/RecordsAdmin/data/records.ts"],"names":[],"mappings":"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","file":"chunk-76Y4UTYQ.js","sourcesContent":["// =============================================================================\r\n// scopeBridge — Convert between our UI `ParsedRef` and the SDK `RecordScope`.\r\n//\r\n// Our `ParsedRef` is a UI-friendly flat object that round-trips with the\r\n// `kind:id/kind:id` URL refs. The SDK's `RecordScope` is the structured\r\n// canonical form used for server-side specificity & `match()`. Use these\r\n// helpers at every boundary so we never write a record without `scope`.\r\n// =============================================================================\r\nimport type { RecordScope, RecordTarget } from './sdkTypes';\r\nimport type { ParsedRef } from '../types';\r\n\r\nexport const parsedRefToScope = (ref: ParsedRef): RecordScope => {\r\n const scope: RecordScope = {};\r\n if (ref.productId) scope.productId = ref.productId;\r\n if (ref.variantId) scope.variantId = ref.variantId;\r\n if (ref.batchId) scope.batchId = ref.batchId;\r\n if (ref.proofId) scope.proofId = ref.proofId;\r\n if (ref.facetId) {\r\n scope.facets = [{\r\n key: ref.facetId,\r\n valueKeys: ref.facetValue ? [ref.facetValue] : [],\r\n }];\r\n }\r\n return scope;\r\n};\r\n\r\nexport const parsedRefToTarget = (ref: ParsedRef): RecordTarget => {\r\n const target: RecordTarget = {};\r\n if (ref.productId) target.productId = ref.productId;\r\n if (ref.variantId) target.variantId = ref.variantId;\r\n if (ref.batchId) target.batchId = ref.batchId;\r\n if (ref.proofId) target.proofId = ref.proofId;\r\n if (ref.facetId && ref.facetValue) {\r\n target.facets = { [ref.facetId]: [ref.facetValue] };\r\n }\r\n return target;\r\n};\r\n\r\n/**\r\n * Compare a winning record's scope against the editing scope.\r\n * Returns true when they refer to the same node — used to decide\r\n * \"self\" vs \"inherited\" when consuming `match()` results.\r\n */\r\nexport const scopesEqual = (a: RecordScope, b: RecordScope): boolean => {\r\n if ((a.productId ?? null) !== (b.productId ?? null)) return false;\r\n if ((a.variantId ?? null) !== (b.variantId ?? null)) return false;\r\n if ((a.batchId ?? null) !== (b.batchId ?? null)) return false;\r\n if ((a.proofId ?? null) !== (b.proofId ?? null)) return false;\r\n const af = a.facets ?? [];\r\n const bf = b.facets ?? [];\r\n if (af.length !== bf.length) return false;\r\n const norm = (xs: typeof af) => xs\r\n .map((f) => `${f.key}:${[...f.valueKeys].sort().join(',')}`)\r\n .sort()\r\n .join('|');\r\n return norm(af) === norm(bf);\r\n};","// =============================================================================\r\n// Thin wrappers over SL.app.records.* — always admin: true here.\r\n//\r\n// As of `@proveanything/smartlinks` 1.9.0 the records surface ships a proper\r\n// `upsert()`, server-side `match()`, and atomic `bulkUpsert` / `bulkDelete`.\r\n// We delegate to those rather than rolling our own list+update sequences,\r\n// which were racy and ignored facet AND-of-OR semantics.\r\n// =============================================================================\r\nimport type {\r\n AppRecord, RecordScope, RecordTarget, BulkUpsertItem, BulkDeleteResult,\r\n MatchResult, FacetRule,\r\n} from './sdkTypes';\r\nimport type { ParsedRef, SmartLinksSDK } from '../types';\r\nimport { parsedRefToScope } from './scopeBridge';\r\n\r\nexport interface RecordsCtx {\r\n SL: SmartLinksSDK;\r\n collectionId: string;\r\n appId: string;\r\n /** Optional — when omitted, records are stored against the app id alone\r\n * (no type qualifier). Set this only when an app uses multiple record types\r\n * and needs to query/scope by type. */\r\n recordType?: string;\r\n}\r\n\r\n/** Shape of a single record write — uses the SDK's structured `scope`. */\r\nexport interface RecordWrite<T = unknown> {\r\n /** Logical key. The server canonicalises this from `scope` if omitted. */\r\n ref?: string;\r\n /** Structured scope; required for specificity / `match()` to work. */\r\n scope: RecordScope;\r\n data: T;\r\n visibility?: 'public' | 'owner' | 'admin';\r\n productId?: string;\r\n status?: string;\r\n startsAt?: string | null;\r\n expiresAt?: string | null;\r\n customId?: string;\r\n sourceSystem?: string;\r\n /**\r\n * Optional facet rule. When set, the record is targeted via this rule and\r\n * `scope` should be empty (the SDK enforces mutual exclusion). Used by\r\n * the rule editor / Targeting section.\r\n */\r\n facetRule?: FacetRule | null;\r\n}\r\n\r\nexport const listRecords = async (\r\n ctx: RecordsCtx,\r\n params: { ref?: string; refPrefix?: string; q?: string; limit?: number; offset?: number; sort?: string } = {},\r\n): Promise<{ data: AppRecord[]; total: number; hasMore: boolean }> => {\r\n const { limit = 100, offset, ref, refPrefix, q, sort } = params;\r\n const res = await ctx.SL.app.records.list(\r\n ctx.collectionId,\r\n ctx.appId,\r\n {\r\n ...(ctx.recordType ? { recordType: ctx.recordType } : {}),\r\n limit, offset, ref, refPrefix, q, sort,\r\n },\r\n true,\r\n );\r\n return {\r\n data: res?.data ?? [],\r\n total: res?.pagination?.total ?? (res?.data?.length ?? 0),\r\n hasMore: res?.pagination?.hasMore ?? false,\r\n };\r\n};\r\n\r\n/** Look up a single record by its canonical ref. */\r\nexport const getRecordByRef = async (\r\n ctx: RecordsCtx,\r\n ref: string,\r\n): Promise<AppRecord | null> => {\r\n const res = await ctx.SL.app.records.list(\r\n ctx.collectionId,\r\n ctx.appId,\r\n { ...(ctx.recordType ? { recordType: ctx.recordType } : {}), ref, limit: 1 },\r\n true,\r\n );\r\n return res?.data?.[0] ?? null;\r\n};\r\n\r\n/**\r\n * Atomic upsert via the SDK. Always sends `scope` so the server can compute\r\n * `specificity` and derive `ref` deterministically.\r\n */\r\nexport const upsertRecord = async <T,>(\r\n ctx: RecordsCtx,\r\n write: RecordWrite<T>,\r\n): Promise<{ record: AppRecord; isCreate: boolean }> => {\r\n const ref = write.ref ?? deriveRefFromScope(write.scope);\r\n const payload: Record<string, unknown> = {\r\n ref,\r\n ...(ctx.recordType ? { recordType: ctx.recordType } : {}),\r\n data: write.data as Record<string, unknown>,\r\n status: write.status,\r\n startsAt: write.startsAt,\r\n expiresAt: write.expiresAt,\r\n customId: write.customId,\r\n sourceSystem: write.sourceSystem,\r\n };\r\n // SDK 1.10 enforces mutual exclusion between `scope` and `facetRule`. Send\r\n // exactly one. When a rule is supplied the server resolves matches against\r\n // it; otherwise the structured scope drives specificity.\r\n if (write.facetRule && write.facetRule.all && write.facetRule.all.length > 0) {\r\n payload.facetRule = write.facetRule;\r\n } else {\r\n payload.scope = write.scope;\r\n }\r\n const res = await ctx.SL.app.records.upsert(\r\n ctx.collectionId, ctx.appId, payload as Parameters<typeof ctx.SL.app.records.upsert>[2],\r\n );\r\n return { record: res, isCreate: !!res?.created };\r\n};\r\n\r\n/**\r\n * Convenience wrapper for callers that only have a `ParsedRef` and a payload —\r\n * matches the previous (`ref`, `data`) call shape used by the editor hook.\r\n */\r\nexport const upsertRecordForScope = async <T,>(\r\n ctx: RecordsCtx,\r\n scope: ParsedRef,\r\n data: T,\r\n extra: { visibility?: 'public' | 'owner' | 'admin' } = {},\r\n) => upsertRecord<T>(ctx, {\r\n ref: scope.raw || undefined,\r\n scope: parsedRefToScope(scope),\r\n data,\r\n visibility: extra.visibility,\r\n});\r\n\r\nexport const deleteRecord = async (\r\n ctx: RecordsCtx,\r\n ref: string,\r\n): Promise<boolean> => {\r\n const existing = await getRecordByRef(ctx, ref).catch(() => null);\r\n if (!existing) return false;\r\n await ctx.SL.app.records.remove(ctx.collectionId, ctx.appId, existing.id, true);\r\n return true;\r\n};\r\n\r\n/** Restore a soft-deleted record by ID (admin only). */\r\nexport const restoreRecord = async (\r\n ctx: RecordsCtx,\r\n recordId: string,\r\n): Promise<AppRecord> => ctx.SL.app.records.restore(ctx.collectionId, ctx.appId, recordId);\r\n\r\n/**\r\n * Server-side match — single round trip that returns every record whose\r\n * `scope` is satisfied by `target`, ordered by descending `specificity`.\r\n * Replaces the per-scope N+1 chain walk we used pre-1.9.\r\n */\r\nexport const matchRecords = async (\r\n ctx: RecordsCtx,\r\n target: RecordTarget,\r\n opts: {\r\n strategy?: 'all' | 'best';\r\n at?: string;\r\n includeScheduled?: boolean;\r\n includeExpired?: boolean;\r\n limit?: number;\r\n } = {},\r\n): Promise<MatchResult> => ctx.SL.app.records.match(\r\n ctx.collectionId,\r\n ctx.appId,\r\n {\r\n target,\r\n ...(ctx.recordType ? { recordType: ctx.recordType } : {}),\r\n strategy: opts.strategy ?? 'all',\r\n at: opts.at,\r\n includeScheduled: opts.includeScheduled,\r\n includeExpired: opts.includeExpired,\r\n limit: opts.limit,\r\n },\r\n true,\r\n);\r\n\r\n/**\r\n * Server-side bulk upsert. Up to 500 rows per call; any leftover is chunked.\r\n * Each row is error-isolated by the server.\r\n */\r\nexport const bulkUpsert = async <T,>(\r\n ctx: RecordsCtx,\r\n entries: Array<{ ref?: string; scope: RecordScope; data: T; status?: string }>,\r\n): Promise<{ saved: number; failed: number }> => {\r\n const CHUNK = 500;\r\n let saved = 0;\r\n let failed = 0;\r\n for (let i = 0; i < entries.length; i += CHUNK) {\r\n const slice = entries.slice(i, i + CHUNK);\r\n const items: BulkUpsertItem[] = slice.map((e) => ({\r\n ref: e.ref ?? deriveRefFromScope(e.scope),\r\n ...(ctx.recordType ? { recordType: ctx.recordType } : {}),\r\n scope: e.scope,\r\n data: e.data as Record<string, unknown>,\r\n status: e.status,\r\n }));\r\n const res = await ctx.SL.app.records.bulkUpsert(ctx.collectionId, ctx.appId, items)\r\n .catch((): { saved: number; failed: number } => ({ saved: 0, failed: items.length }));\r\n saved += res.saved ?? 0;\r\n failed += res.failed ?? 0;\r\n }\r\n return { saved, failed };\r\n};\r\n\r\n/**\r\n * Server-side bulk delete. Accepts an explicit ref list (max 1000 per call,\r\n * chunked here) or a scope anchor (single call).\r\n */\r\nexport const bulkDelete = async (\r\n ctx: RecordsCtx,\r\n input: { refs: string[] } | { scope: Omit<RecordScope, 'facets'> },\r\n): Promise<{ removed: number }> => {\r\n if ('scope' in input) {\r\n const res: BulkDeleteResult = await ctx.SL.app.records.bulkDelete(\r\n ctx.collectionId, ctx.appId,\r\n { scope: input.scope, ...(ctx.recordType ? { recordType: ctx.recordType } : {}) },\r\n );\r\n return { removed: res.deleted ?? 0 };\r\n }\r\n\r\n const CHUNK = 1000;\r\n let removed = 0;\r\n for (let i = 0; i < input.refs.length; i += CHUNK) {\r\n const slice = input.refs.slice(i, i + CHUNK);\r\n const res: BulkDeleteResult = await ctx.SL.app.records.bulkDelete(\r\n ctx.collectionId, ctx.appId,\r\n { refs: slice, ...(ctx.recordType ? { recordType: ctx.recordType } : {}) },\r\n );\r\n removed += res.deleted ?? 0;\r\n }\r\n return { removed };\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// Internal — derive a stable ref string from a structured scope. The server\r\n// re-derives this canonically on write; we send our best guess so callers\r\n// (and our own list/lookup helpers) can find the record by ref afterwards.\r\n// ---------------------------------------------------------------------------\r\nconst deriveRefFromScope = (scope: RecordScope): string => {\r\n const parts: string[] = [];\r\n if (scope.facets && scope.facets.length > 0) {\r\n // Sort for determinism.\r\n const sorted = [...scope.facets].sort((a, b) => a.key.localeCompare(b.key));\r\n for (const f of sorted) {\r\n const vals = [...f.valueKeys].sort().join(',');\r\n parts.push(vals ? `facet:${f.key}=${vals}` : `facet:${f.key}`);\r\n }\r\n }\r\n if (scope.productId) parts.push(`product:${scope.productId}`);\r\n if (scope.variantId) parts.push(`variant:${scope.variantId}`);\r\n if (scope.batchId) parts.push(`batch:${scope.batchId}`);\r\n if (scope.proofId) parts.push(`proof:${scope.proofId}`);\r\n return parts.join('/');\r\n};"]}
@@ -243,5 +243,5 @@ var FacetRuleEditor = ({
243
243
  };
244
244
 
245
245
  export { FacetRuleEditor };
246
- //# sourceMappingURL=chunk-MZ6JSCXO.js.map
247
- //# sourceMappingURL=chunk-MZ6JSCXO.js.map
246
+ //# sourceMappingURL=chunk-JMCV6FOW.js.map
247
+ //# sourceMappingURL=chunk-JMCV6FOW.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/FacetRuleEditor/FacetRuleEditor.tsx"],"names":[],"mappings":"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","file":"chunk-MZ6JSCXO.js","sourcesContent":["// =============================================================================\r\n// FacetRuleEditor — Friendly AND-of-OR rule builder for facet-targeted records.\r\n//\r\n// Model: `{ all: [{ facetKey, anyOf: [valueKey, ...] }, ...] }`.\r\n// - Each clause picks ONE facet key and one or more values (OR within).\r\n// - Multiple clauses are ANDed.\r\n// - Facet keys cannot repeat across clauses (server enforces; we hide already-\r\n// chosen keys from the picker).\r\n// - No NOTs, no nesting, no free-text — by design. This is the public-side\r\n// rule shape; richer logic belongs in `ConditionsEditor` (client-side only).\r\n//\r\n// UX notes:\r\n// - Empty state: a single inviting \"Pick a facet to start\" card.\r\n// - Each clause renders as a labelled row of value chips that toggle on click.\r\n// - Bottom bar shows live \"matches N products\" feedback when `preview` is set.\r\n// =============================================================================\r\nimport React, { useMemo } from 'react';\r\nimport { Plus, X, Trash2, Loader2, Check, AlertCircle } from 'lucide-react';\r\nimport { cn } from '../../utils/cn';\r\nimport { useFacets } from '../ConditionsEditor/useFacets';\r\nimport type { FacetRuleEditorProps, FacetRule, FacetRuleClause, FacetOption } from './types';\r\n\r\n// ---------------------------------------------------------------------------\r\n// Helpers\r\n// ---------------------------------------------------------------------------\r\nconst cloneRule = (rule: FacetRule | null): FacetRule => ({\r\n all: (rule?.all ?? []).map((c: FacetRuleClause) => ({ facetKey: c.facetKey, anyOf: [...c.anyOf] })),\r\n});\r\n\r\nconst updateClause = (\r\n rule: FacetRule | null,\r\n index: number,\r\n next: FacetRuleClause | null,\r\n): FacetRule | null => {\r\n const draft = cloneRule(rule);\r\n if (next === null) draft.all.splice(index, 1);\r\n else draft.all[index] = next;\r\n return draft.all.length === 0 ? null : draft;\r\n};\r\n\r\nconst findFacet = (facets: FacetOption[], key: string) =>\r\n facets.find((f) => f.key === key);\r\n\r\n// ---------------------------------------------------------------------------\r\n// Single-clause editor: facet header + chip-grid of values.\r\n// ---------------------------------------------------------------------------\r\ninterface ClauseEditorProps {\r\n clause: FacetRuleClause;\r\n facet: FacetOption | undefined;\r\n onChange: (next: FacetRuleClause | null) => void;\r\n readOnly?: boolean;\r\n}\r\n\r\nconst ClauseEditor: React.FC<ClauseEditorProps> = ({ clause, facet, onChange, readOnly }) => {\r\n const selected = useMemo(() => new Set(clause.anyOf), [clause.anyOf]);\r\n const toggle = (valueKey: string) => {\r\n if (readOnly) return;\r\n const next = new Set(selected);\r\n if (next.has(valueKey)) next.delete(valueKey);\r\n else next.add(valueKey);\r\n onChange({ facetKey: clause.facetKey, anyOf: Array.from(next) });\r\n };\r\n\r\n const facetName = facet?.name ?? clause.facetKey;\r\n const values = facet?.values ?? [];\r\n\r\n return (\r\n <div className=\"rounded-xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 overflow-hidden\">\r\n {/* Header */}\r\n <div className=\"flex items-center gap-2 px-4 py-2.5 bg-gray-50 dark:bg-gray-800/50 border-b border-gray-200 dark:border-gray-700\">\r\n <div className=\"flex flex-col flex-1 min-w-0\">\r\n <span className=\"text-[11px] font-medium uppercase tracking-wide text-gray-500 dark:text-gray-400\">\r\n Where\r\n </span>\r\n <span className=\"text-sm font-semibold text-gray-900 dark:text-gray-100 truncate\">\r\n {facetName}\r\n </span>\r\n </div>\r\n <span className=\"text-xs text-gray-500 dark:text-gray-400 px-2 py-0.5 rounded-full bg-gray-100 dark:bg-gray-700\">\r\n {clause.anyOf.length} selected\r\n </span>\r\n {!readOnly && (\r\n <button\r\n type=\"button\"\r\n onClick={() => onChange(null)}\r\n className=\"p-1.5 rounded-md text-gray-400 hover:text-red-600 hover:bg-red-50 dark:hover:bg-red-900/20 transition-colors\"\r\n aria-label={`Remove ${facetName} clause`}\r\n >\r\n <Trash2 className=\"w-3.5 h-3.5\" />\r\n </button>\r\n )}\r\n </div>\r\n\r\n {/* Body */}\r\n <div className=\"p-3\">\r\n {!facet ? (\r\n <div className=\"flex items-center gap-2 text-xs text-amber-600 dark:text-amber-400 px-2 py-1.5\">\r\n <AlertCircle className=\"w-3.5 h-3.5\" />\r\n <span>Facet \"{clause.facetKey}\" no longer exists in this collection.</span>\r\n </div>\r\n ) : values.length === 0 ? (\r\n <div className=\"text-xs text-gray-500 dark:text-gray-400 px-2 py-1.5\">\r\n No values defined for this facet yet.\r\n </div>\r\n ) : (\r\n <div className=\"flex flex-wrap gap-1.5\">\r\n {values.map((v) => {\r\n const isSel = selected.has(v.key);\r\n return (\r\n <button\r\n key={v.key}\r\n type=\"button\"\r\n disabled={readOnly}\r\n onClick={() => toggle(v.key)}\r\n className={cn(\r\n 'inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-medium transition-all',\r\n 'border',\r\n isSel\r\n ? 'bg-blue-600 text-white border-blue-600 hover:bg-blue-700'\r\n : 'bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-300 border-gray-200 dark:border-gray-700 hover:border-blue-400 hover:text-blue-600 dark:hover:text-blue-400',\r\n readOnly && 'cursor-not-allowed opacity-60'\r\n )}\r\n aria-pressed={isSel}\r\n >\r\n {v.color && (\r\n <span\r\n className=\"inline-block w-2 h-2 rounded-full\"\r\n style={{ backgroundColor: v.color }}\r\n />\r\n )}\r\n {v.name}\r\n {isSel && <Check className=\"w-3 h-3\" />}\r\n </button>\r\n );\r\n })}\r\n </div>\r\n )}\r\n {clause.anyOf.length > 1 && (\r\n <p className=\"mt-2 text-[11px] text-gray-500 dark:text-gray-400 px-1\">\r\n Matches when any of the selected values is present.\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// \"Add facet\" picker — lists facets not already used by another clause.\r\n// ---------------------------------------------------------------------------\r\ninterface AddFacetPickerProps {\r\n available: FacetOption[];\r\n onPick: (facetKey: string) => void;\r\n isFirst: boolean;\r\n}\r\n\r\nconst AddFacetPicker: React.FC<AddFacetPickerProps> = ({ available, onPick, isFirst }) => {\r\n const [open, setOpen] = React.useState(false);\r\n\r\n if (available.length === 0 && !isFirst) {\r\n return (\r\n <p className=\"text-xs text-gray-500 dark:text-gray-400 px-2 py-1\">\r\n All available facets are in use.\r\n </p>\r\n );\r\n }\r\n\r\n if (isFirst) {\r\n // Empty state — friendly inviting card\r\n return (\r\n <div className=\"rounded-xl border-2 border-dashed border-gray-300 dark:border-gray-700 p-6 text-center\">\r\n <p className=\"text-sm font-medium text-gray-700 dark:text-gray-200 mb-1\">\r\n Pick a facet to target\r\n </p>\r\n <p className=\"text-xs text-gray-500 dark:text-gray-400 mb-4\">\r\n Records matching this rule will be applied to every product whose facets satisfy it.\r\n </p>\r\n <div className=\"flex flex-wrap gap-1.5 justify-center\">\r\n {available.map((f) => (\r\n <button\r\n key={f.key}\r\n type=\"button\"\r\n onClick={() => onPick(f.key)}\r\n className=\"inline-flex items-center gap-1 px-3 py-1.5 rounded-full text-xs font-medium bg-blue-50 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300 hover:bg-blue-100 dark:hover:bg-blue-900/50 transition-colors\"\r\n >\r\n <Plus className=\"w-3 h-3\" />\r\n {f.name}\r\n </button>\r\n ))}\r\n {available.length === 0 && (\r\n <span className=\"text-xs text-gray-500 dark:text-gray-400\">\r\n No facets defined for this collection yet.\r\n </span>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"relative\">\r\n <button\r\n type=\"button\"\r\n onClick={() => setOpen((o) => !o)}\r\n className=\"inline-flex items-center gap-1.5 px-3 py-1.5 rounded-full text-xs font-medium bg-gray-100 dark:bg-gray-800 text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors\"\r\n >\r\n <Plus className=\"w-3.5 h-3.5\" />\r\n AND another facet\r\n </button>\r\n {open && (\r\n <>\r\n <div className=\"fixed inset-0 z-40\" onClick={() => setOpen(false)} />\r\n <div className=\"absolute z-50 mt-1 left-0 min-w-[200px] rounded-lg border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 shadow-lg overflow-hidden\">\r\n {available.map((f) => (\r\n <button\r\n key={f.key}\r\n type=\"button\"\r\n onClick={() => { onPick(f.key); setOpen(false); }}\r\n className=\"w-full text-left px-3 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors\"\r\n >\r\n {f.name}\r\n </button>\r\n ))}\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// Live preview chip — wired through the optional `preview` prop.\r\n// ---------------------------------------------------------------------------\r\nconst PreviewChip: React.FC<{ preview: NonNullable<FacetRuleEditorProps['preview']> }> = ({ preview }) => {\r\n const { totalMatches, isLoading, isStale, error } = preview;\r\n\r\n if (error) {\r\n return (\r\n <div className=\"inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-medium bg-red-50 dark:bg-red-900/30 text-red-700 dark:text-red-300\">\r\n <AlertCircle className=\"w-3 h-3\" />\r\n Preview failed\r\n </div>\r\n );\r\n }\r\n\r\n if (isLoading || isStale || totalMatches === null) {\r\n return (\r\n <div className=\"inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-medium bg-gray-100 dark:bg-gray-800 text-gray-500 dark:text-gray-400\">\r\n <Loader2 className=\"w-3 h-3 animate-spin\" />\r\n Counting…\r\n </div>\r\n );\r\n }\r\n\r\n const tone = totalMatches === 0\r\n ? 'bg-amber-50 dark:bg-amber-900/30 text-amber-700 dark:text-amber-300'\r\n : 'bg-emerald-50 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-300';\r\n\r\n return (\r\n <div className={cn('inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-medium', tone)}>\r\n <Check className=\"w-3 h-3\" />\r\n {totalMatches === 0\r\n ? 'Matches no products yet'\r\n : `Matches ${totalMatches} product${totalMatches === 1 ? '' : 's'}`}\r\n </div>\r\n );\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// Top-level component\r\n// ---------------------------------------------------------------------------\r\nexport const FacetRuleEditor: React.FC<FacetRuleEditorProps> = ({\r\n value, onChange,\r\n facets: providedFacets, collectionId, getFacets,\r\n preview, readOnly,\r\n onClear,\r\n title,\r\n description,\r\n className,\r\n}) => {\r\n const facets = useFacets(collectionId, providedFacets, getFacets);\r\n\r\n const usedKeys = useMemo(\r\n () => new Set((value?.all ?? []).map((c: FacetRuleClause) => c.facetKey)),\r\n [value],\r\n );\r\n const availableFacets = useMemo(\r\n () => facets.filter((f) => !usedKeys.has(f.key)),\r\n [facets, usedKeys],\r\n );\r\n\r\n const addClause = (facetKey: string) => {\r\n const next: FacetRule = cloneRule(value);\r\n next.all.push({ facetKey, anyOf: [] });\r\n onChange(next);\r\n };\r\n\r\n const updateAt = (i: number, next: FacetRuleClause | null) => {\r\n onChange(updateClause(value, i, next));\r\n };\r\n\r\n const hasClauses = (value?.all?.length ?? 0) > 0;\r\n\r\n return (\r\n <div className={cn('smartlinks-ui-facet-rule-editor space-y-3', className)}>\r\n {(title || description || (hasClauses && onClear) || preview) && (\r\n <div className=\"flex items-start gap-2\">\r\n <div className=\"flex-1 min-w-0\">\r\n {title && (\r\n <h3 className=\"text-sm font-semibold text-gray-900 dark:text-gray-100\">{title}</h3>\r\n )}\r\n {description && (\r\n <p className=\"mt-0.5 text-xs text-gray-500 dark:text-gray-400\">{description}</p>\r\n )}\r\n </div>\r\n {preview && hasClauses && <PreviewChip preview={preview} />}\r\n {onClear && hasClauses && !readOnly && (\r\n <button\r\n type=\"button\"\r\n onClick={onClear}\r\n className=\"inline-flex items-center gap-1 px-2 py-1 rounded-md text-xs text-gray-500 hover:text-red-600 hover:bg-red-50 dark:hover:bg-red-900/20 transition-colors\"\r\n >\r\n <X className=\"w-3 h-3\" />\r\n Remove rule\r\n </button>\r\n )}\r\n </div>\r\n )}\r\n\r\n {!hasClauses ? (\r\n <AddFacetPicker available={facets} onPick={addClause} isFirst />\r\n ) : (\r\n <>\r\n {value!.all.map((clause: FacetRuleClause, i: number) => (\r\n <React.Fragment key={`${clause.facetKey}-${i}`}>\r\n {i > 0 && (\r\n <div className=\"flex items-center justify-center\">\r\n <span className=\"px-2 py-0.5 rounded-full text-[10px] font-bold uppercase tracking-wider bg-gray-100 dark:bg-gray-800 text-gray-500 dark:text-gray-400\">\r\n AND\r\n </span>\r\n </div>\r\n )}\r\n <ClauseEditor\r\n clause={clause}\r\n facet={findFacet(facets, clause.facetKey)}\r\n onChange={(next) => updateAt(i, next)}\r\n readOnly={readOnly}\r\n />\r\n </React.Fragment>\r\n ))}\r\n {!readOnly && (\r\n <div className=\"pt-1\">\r\n <AddFacetPicker\r\n available={availableFacets}\r\n onPick={addClause}\r\n isFirst={false}\r\n />\r\n </div>\r\n )}\r\n </>\r\n )}\r\n </div>\r\n );\r\n};"]}
1
+ {"version":3,"sources":["../src/components/FacetRuleEditor/FacetRuleEditor.tsx"],"names":[],"mappings":"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","file":"chunk-JMCV6FOW.js","sourcesContent":["// =============================================================================\r\n// FacetRuleEditor — Friendly AND-of-OR rule builder for facet-targeted records.\r\n//\r\n// Model: `{ all: [{ facetKey, anyOf: [valueKey, ...] }, ...] }`.\r\n// - Each clause picks ONE facet key and one or more values (OR within).\r\n// - Multiple clauses are ANDed.\r\n// - Facet keys cannot repeat across clauses (server enforces; we hide already-\r\n// chosen keys from the picker).\r\n// - No NOTs, no nesting, no free-text — by design. This is the public-side\r\n// rule shape; richer logic belongs in `ConditionsEditor` (client-side only).\r\n//\r\n// UX notes:\r\n// - Empty state: a single inviting \"Pick a facet to start\" card.\r\n// - Each clause renders as a labelled row of value chips that toggle on click.\r\n// - Bottom bar shows live \"matches N products\" feedback when `preview` is set.\r\n// =============================================================================\r\nimport React, { useMemo } from 'react';\r\nimport { Plus, X, Trash2, Loader2, Check, AlertCircle } from 'lucide-react';\r\nimport { cn } from '../../utils/cn';\r\nimport { useFacets } from '../ConditionsEditor/useFacets';\r\nimport type { FacetRuleEditorProps, FacetRule, FacetRuleClause, FacetOption } from './types';\r\n\r\n// ---------------------------------------------------------------------------\r\n// Helpers\r\n// ---------------------------------------------------------------------------\r\nconst cloneRule = (rule: FacetRule | null): FacetRule => ({\r\n all: (rule?.all ?? []).map((c: FacetRuleClause) => ({ facetKey: c.facetKey, anyOf: [...c.anyOf] })),\r\n});\r\n\r\nconst updateClause = (\r\n rule: FacetRule | null,\r\n index: number,\r\n next: FacetRuleClause | null,\r\n): FacetRule | null => {\r\n const draft = cloneRule(rule);\r\n if (next === null) draft.all.splice(index, 1);\r\n else draft.all[index] = next;\r\n return draft.all.length === 0 ? null : draft;\r\n};\r\n\r\nconst findFacet = (facets: FacetOption[], key: string) =>\r\n facets.find((f) => f.key === key);\r\n\r\n// ---------------------------------------------------------------------------\r\n// Single-clause editor: facet header + chip-grid of values.\r\n// ---------------------------------------------------------------------------\r\ninterface ClauseEditorProps {\r\n clause: FacetRuleClause;\r\n facet: FacetOption | undefined;\r\n onChange: (next: FacetRuleClause | null) => void;\r\n readOnly?: boolean;\r\n}\r\n\r\nconst ClauseEditor: React.FC<ClauseEditorProps> = ({ clause, facet, onChange, readOnly }) => {\r\n const selected = useMemo(() => new Set(clause.anyOf), [clause.anyOf]);\r\n const toggle = (valueKey: string) => {\r\n if (readOnly) return;\r\n const next = new Set(selected);\r\n if (next.has(valueKey)) next.delete(valueKey);\r\n else next.add(valueKey);\r\n onChange({ facetKey: clause.facetKey, anyOf: Array.from(next) });\r\n };\r\n\r\n const facetName = facet?.name ?? clause.facetKey;\r\n const values = facet?.values ?? [];\r\n\r\n return (\r\n <div className=\"rounded-xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 overflow-hidden\">\r\n {/* Header */}\r\n <div className=\"flex items-center gap-2 px-4 py-2.5 bg-gray-50 dark:bg-gray-800/50 border-b border-gray-200 dark:border-gray-700\">\r\n <div className=\"flex flex-col flex-1 min-w-0\">\r\n <span className=\"text-[11px] font-medium uppercase tracking-wide text-gray-500 dark:text-gray-400\">\r\n Where\r\n </span>\r\n <span className=\"text-sm font-semibold text-gray-900 dark:text-gray-100 truncate\">\r\n {facetName}\r\n </span>\r\n </div>\r\n <span className=\"text-xs text-gray-500 dark:text-gray-400 px-2 py-0.5 rounded-full bg-gray-100 dark:bg-gray-700\">\r\n {clause.anyOf.length} selected\r\n </span>\r\n {!readOnly && (\r\n <button\r\n type=\"button\"\r\n onClick={() => onChange(null)}\r\n className=\"p-1.5 rounded-md text-gray-400 hover:text-red-600 hover:bg-red-50 dark:hover:bg-red-900/20 transition-colors\"\r\n aria-label={`Remove ${facetName} clause`}\r\n >\r\n <Trash2 className=\"w-3.5 h-3.5\" />\r\n </button>\r\n )}\r\n </div>\r\n\r\n {/* Body */}\r\n <div className=\"p-3\">\r\n {!facet ? (\r\n <div className=\"flex items-center gap-2 text-xs text-amber-600 dark:text-amber-400 px-2 py-1.5\">\r\n <AlertCircle className=\"w-3.5 h-3.5\" />\r\n <span>Facet \"{clause.facetKey}\" no longer exists in this collection.</span>\r\n </div>\r\n ) : values.length === 0 ? (\r\n <div className=\"text-xs text-gray-500 dark:text-gray-400 px-2 py-1.5\">\r\n No values defined for this facet yet.\r\n </div>\r\n ) : (\r\n <div className=\"flex flex-wrap gap-1.5\">\r\n {values.map((v) => {\r\n const isSel = selected.has(v.key);\r\n return (\r\n <button\r\n key={v.key}\r\n type=\"button\"\r\n disabled={readOnly}\r\n onClick={() => toggle(v.key)}\r\n className={cn(\r\n 'inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-medium transition-all',\r\n 'border',\r\n isSel\r\n ? 'bg-blue-600 text-white border-blue-600 hover:bg-blue-700'\r\n : 'bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-300 border-gray-200 dark:border-gray-700 hover:border-blue-400 hover:text-blue-600 dark:hover:text-blue-400',\r\n readOnly && 'cursor-not-allowed opacity-60'\r\n )}\r\n aria-pressed={isSel}\r\n >\r\n {v.color && (\r\n <span\r\n className=\"inline-block w-2 h-2 rounded-full\"\r\n style={{ backgroundColor: v.color }}\r\n />\r\n )}\r\n {v.name}\r\n {isSel && <Check className=\"w-3 h-3\" />}\r\n </button>\r\n );\r\n })}\r\n </div>\r\n )}\r\n {clause.anyOf.length > 1 && (\r\n <p className=\"mt-2 text-[11px] text-gray-500 dark:text-gray-400 px-1\">\r\n Matches when any of the selected values is present.\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// \"Add facet\" picker — lists facets not already used by another clause.\r\n// ---------------------------------------------------------------------------\r\ninterface AddFacetPickerProps {\r\n available: FacetOption[];\r\n onPick: (facetKey: string) => void;\r\n isFirst: boolean;\r\n}\r\n\r\nconst AddFacetPicker: React.FC<AddFacetPickerProps> = ({ available, onPick, isFirst }) => {\r\n const [open, setOpen] = React.useState(false);\r\n\r\n if (available.length === 0 && !isFirst) {\r\n return (\r\n <p className=\"text-xs text-gray-500 dark:text-gray-400 px-2 py-1\">\r\n All available facets are in use.\r\n </p>\r\n );\r\n }\r\n\r\n if (isFirst) {\r\n // Empty state — friendly inviting card\r\n return (\r\n <div className=\"rounded-xl border-2 border-dashed border-gray-300 dark:border-gray-700 p-6 text-center\">\r\n <p className=\"text-sm font-medium text-gray-700 dark:text-gray-200 mb-1\">\r\n Pick a facet to target\r\n </p>\r\n <p className=\"text-xs text-gray-500 dark:text-gray-400 mb-4\">\r\n Records matching this rule will be applied to every product whose facets satisfy it.\r\n </p>\r\n <div className=\"flex flex-wrap gap-1.5 justify-center\">\r\n {available.map((f) => (\r\n <button\r\n key={f.key}\r\n type=\"button\"\r\n onClick={() => onPick(f.key)}\r\n className=\"inline-flex items-center gap-1 px-3 py-1.5 rounded-full text-xs font-medium bg-blue-50 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300 hover:bg-blue-100 dark:hover:bg-blue-900/50 transition-colors\"\r\n >\r\n <Plus className=\"w-3 h-3\" />\r\n {f.name}\r\n </button>\r\n ))}\r\n {available.length === 0 && (\r\n <span className=\"text-xs text-gray-500 dark:text-gray-400\">\r\n No facets defined for this collection yet.\r\n </span>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"relative\">\r\n <button\r\n type=\"button\"\r\n onClick={() => setOpen((o) => !o)}\r\n className=\"inline-flex items-center gap-1.5 px-3 py-1.5 rounded-full text-xs font-medium bg-gray-100 dark:bg-gray-800 text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors\"\r\n >\r\n <Plus className=\"w-3.5 h-3.5\" />\r\n AND another facet\r\n </button>\r\n {open && (\r\n <>\r\n <div className=\"fixed inset-0 z-40\" onClick={() => setOpen(false)} />\r\n <div className=\"absolute z-50 mt-1 left-0 min-w-[200px] rounded-lg border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 shadow-lg overflow-hidden\">\r\n {available.map((f) => (\r\n <button\r\n key={f.key}\r\n type=\"button\"\r\n onClick={() => { onPick(f.key); setOpen(false); }}\r\n className=\"w-full text-left px-3 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors\"\r\n >\r\n {f.name}\r\n </button>\r\n ))}\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// Live preview chip — wired through the optional `preview` prop.\r\n// ---------------------------------------------------------------------------\r\nconst PreviewChip: React.FC<{ preview: NonNullable<FacetRuleEditorProps['preview']> }> = ({ preview }) => {\r\n const { totalMatches, isLoading, isStale, error } = preview;\r\n\r\n if (error) {\r\n return (\r\n <div className=\"inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-medium bg-red-50 dark:bg-red-900/30 text-red-700 dark:text-red-300\">\r\n <AlertCircle className=\"w-3 h-3\" />\r\n Preview failed\r\n </div>\r\n );\r\n }\r\n\r\n if (isLoading || isStale || totalMatches === null) {\r\n return (\r\n <div className=\"inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-medium bg-gray-100 dark:bg-gray-800 text-gray-500 dark:text-gray-400\">\r\n <Loader2 className=\"w-3 h-3 animate-spin\" />\r\n Counting…\r\n </div>\r\n );\r\n }\r\n\r\n const tone = totalMatches === 0\r\n ? 'bg-amber-50 dark:bg-amber-900/30 text-amber-700 dark:text-amber-300'\r\n : 'bg-emerald-50 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-300';\r\n\r\n return (\r\n <div className={cn('inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-medium', tone)}>\r\n <Check className=\"w-3 h-3\" />\r\n {totalMatches === 0\r\n ? 'Matches no products yet'\r\n : `Matches ${totalMatches} product${totalMatches === 1 ? '' : 's'}`}\r\n </div>\r\n );\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// Top-level component\r\n// ---------------------------------------------------------------------------\r\nexport const FacetRuleEditor: React.FC<FacetRuleEditorProps> = ({\r\n value, onChange,\r\n facets: providedFacets, collectionId, getFacets,\r\n preview, readOnly,\r\n onClear,\r\n title,\r\n description,\r\n className,\r\n}) => {\r\n const facets = useFacets(collectionId, providedFacets, getFacets);\r\n\r\n const usedKeys = useMemo(\r\n () => new Set((value?.all ?? []).map((c: FacetRuleClause) => c.facetKey)),\r\n [value],\r\n );\r\n const availableFacets = useMemo(\r\n () => facets.filter((f) => !usedKeys.has(f.key)),\r\n [facets, usedKeys],\r\n );\r\n\r\n const addClause = (facetKey: string) => {\r\n const next: FacetRule = cloneRule(value);\r\n next.all.push({ facetKey, anyOf: [] });\r\n onChange(next);\r\n };\r\n\r\n const updateAt = (i: number, next: FacetRuleClause | null) => {\r\n onChange(updateClause(value, i, next));\r\n };\r\n\r\n const hasClauses = (value?.all?.length ?? 0) > 0;\r\n\r\n return (\r\n <div className={cn('smartlinks-ui-facet-rule-editor space-y-3', className)}>\r\n {(title || description || (hasClauses && onClear) || preview) && (\r\n <div className=\"flex items-start gap-2\">\r\n <div className=\"flex-1 min-w-0\">\r\n {title && (\r\n <h3 className=\"text-sm font-semibold text-gray-900 dark:text-gray-100\">{title}</h3>\r\n )}\r\n {description && (\r\n <p className=\"mt-0.5 text-xs text-gray-500 dark:text-gray-400\">{description}</p>\r\n )}\r\n </div>\r\n {preview && hasClauses && <PreviewChip preview={preview} />}\r\n {onClear && hasClauses && !readOnly && (\r\n <button\r\n type=\"button\"\r\n onClick={onClear}\r\n className=\"inline-flex items-center gap-1 px-2 py-1 rounded-md text-xs text-gray-500 hover:text-red-600 hover:bg-red-50 dark:hover:bg-red-900/20 transition-colors\"\r\n >\r\n <X className=\"w-3 h-3\" />\r\n Remove rule\r\n </button>\r\n )}\r\n </div>\r\n )}\r\n\r\n {!hasClauses ? (\r\n <AddFacetPicker available={facets} onPick={addClause} isFirst />\r\n ) : (\r\n <>\r\n {value!.all.map((clause: FacetRuleClause, i: number) => (\r\n <React.Fragment key={`${clause.facetKey}-${i}`}>\r\n {i > 0 && (\r\n <div className=\"flex items-center justify-center\">\r\n <span className=\"px-2 py-0.5 rounded-full text-[10px] font-bold uppercase tracking-wider bg-gray-100 dark:bg-gray-800 text-gray-500 dark:text-gray-400\">\r\n AND\r\n </span>\r\n </div>\r\n )}\r\n <ClauseEditor\r\n clause={clause}\r\n facet={findFacet(facets, clause.facetKey)}\r\n onChange={(next) => updateAt(i, next)}\r\n readOnly={readOnly}\r\n />\r\n </React.Fragment>\r\n ))}\r\n {!readOnly && (\r\n <div className=\"pt-1\">\r\n <AddFacetPicker\r\n available={availableFacets}\r\n onPick={addClause}\r\n isFirst={false}\r\n />\r\n </div>\r\n )}\r\n </>\r\n )}\r\n </div>\r\n );\r\n};"]}
@@ -0,0 +1,28 @@
1
+ // #style-inject:#style-inject
2
+ function styleInject(css, { insertAt } = {}) {
3
+ if (!css || typeof document === "undefined") return;
4
+ const head = document.head || document.getElementsByTagName("head")[0];
5
+ const style = document.createElement("style");
6
+ style.type = "text/css";
7
+ if (insertAt === "top") {
8
+ if (head.firstChild) {
9
+ head.insertBefore(style, head.firstChild);
10
+ } else {
11
+ head.appendChild(style);
12
+ }
13
+ } else {
14
+ head.appendChild(style);
15
+ }
16
+ if (style.styleSheet) {
17
+ style.styleSheet.cssText = css;
18
+ } else {
19
+ style.appendChild(document.createTextNode(css));
20
+ }
21
+ }
22
+
23
+ // src/styles.css
24
+ styleInject('.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border-width: 0;\n}\n.pointer-events-none {\n pointer-events: none;\n}\n.visible {\n visibility: visible;\n}\n.collapse {\n visibility: collapse;\n}\n.fixed {\n position: fixed;\n}\n.absolute {\n position: absolute;\n}\n.relative {\n position: relative;\n}\n.sticky {\n position: sticky;\n}\n.inset-0 {\n inset: 0px;\n}\n.inset-x-0 {\n left: 0px;\n right: 0px;\n}\n.bottom-0 {\n bottom: 0px;\n}\n.left-0 {\n left: 0px;\n}\n.left-1\\.5 {\n left: 0.375rem;\n}\n.left-2 {\n left: 0.5rem;\n}\n.left-2\\.5 {\n left: 0.625rem;\n}\n.left-3 {\n left: 0.75rem;\n}\n.right-0 {\n right: 0px;\n}\n.right-1\\.5 {\n right: 0.375rem;\n}\n.right-2 {\n right: 0.5rem;\n}\n.right-3 {\n right: 0.75rem;\n}\n.top-0 {\n top: 0px;\n}\n.top-0\\.5 {\n top: 0.125rem;\n}\n.top-1\\.5 {\n top: 0.375rem;\n}\n.top-1\\/2 {\n top: 50%;\n}\n.top-2 {\n top: 0.5rem;\n}\n.z-10 {\n z-index: 10;\n}\n.z-20 {\n z-index: 20;\n}\n.z-40 {\n z-index: 40;\n}\n.z-50 {\n z-index: 50;\n}\n.col-span-2 {\n grid-column: span 2 / span 2;\n}\n.mx-4 {\n margin-left: 1rem;\n margin-right: 1rem;\n}\n.mx-auto {\n margin-left: auto;\n margin-right: auto;\n}\n.-mb-px {\n margin-bottom: -1px;\n}\n.mb-1 {\n margin-bottom: 0.25rem;\n}\n.mb-2 {\n margin-bottom: 0.5rem;\n}\n.mb-3 {\n margin-bottom: 0.75rem;\n}\n.mb-4 {\n margin-bottom: 1rem;\n}\n.ml-1 {\n margin-left: 0.25rem;\n}\n.ml-1\\.5 {\n margin-left: 0.375rem;\n}\n.ml-2 {\n margin-left: 0.5rem;\n}\n.ml-auto {\n margin-left: auto;\n}\n.mt-0\\.5 {\n margin-top: 0.125rem;\n}\n.mt-1 {\n margin-top: 0.25rem;\n}\n.mt-1\\.5 {\n margin-top: 0.375rem;\n}\n.mt-2 {\n margin-top: 0.5rem;\n}\n.mt-4 {\n margin-top: 1rem;\n}\n.block {\n display: block;\n}\n.inline-block {\n display: inline-block;\n}\n.inline {\n display: inline;\n}\n.flex {\n display: flex;\n}\n.inline-flex {\n display: inline-flex;\n}\n.table {\n display: table;\n}\n.grid {\n display: grid;\n}\n.contents {\n display: contents;\n}\n.hidden {\n display: none;\n}\n.aspect-square {\n aspect-ratio: 1 / 1;\n}\n.aspect-video {\n aspect-ratio: 16 / 9;\n}\n.h-1\\.5 {\n height: 0.375rem;\n}\n.h-10 {\n height: 2.5rem;\n}\n.h-11 {\n height: 2.75rem;\n}\n.h-16 {\n height: 4rem;\n}\n.h-2 {\n height: 0.5rem;\n}\n.h-2\\.5 {\n height: 0.625rem;\n}\n.h-3 {\n height: 0.75rem;\n}\n.h-3\\.5 {\n height: 0.875rem;\n}\n.h-4 {\n height: 1rem;\n}\n.h-5 {\n height: 1.25rem;\n}\n.h-6 {\n height: 1.5rem;\n}\n.h-7 {\n height: 1.75rem;\n}\n.h-8 {\n height: 2rem;\n}\n.h-9 {\n height: 2.25rem;\n}\n.h-full {\n height: 100%;\n}\n.max-h-32 {\n max-height: 8rem;\n}\n.max-h-80 {\n max-height: 20rem;\n}\n.max-h-\\[300px\\] {\n max-height: 300px;\n}\n.max-h-\\[400px\\] {\n max-height: 400px;\n}\n.max-h-\\[80vh\\] {\n max-height: 80vh;\n}\n.max-h-\\[85vh\\] {\n max-height: 85vh;\n}\n.min-h-0 {\n min-height: 0px;\n}\n.w-1\\.5 {\n width: 0.375rem;\n}\n.w-10 {\n width: 2.5rem;\n}\n.w-16 {\n width: 4rem;\n}\n.w-2 {\n width: 0.5rem;\n}\n.w-2\\.5 {\n width: 0.625rem;\n}\n.w-3 {\n width: 0.75rem;\n}\n.w-3\\.5 {\n width: 0.875rem;\n}\n.w-36 {\n width: 9rem;\n}\n.w-4 {\n width: 1rem;\n}\n.w-5 {\n width: 1.25rem;\n}\n.w-6 {\n width: 1.5rem;\n}\n.w-7 {\n width: 1.75rem;\n}\n.w-8 {\n width: 2rem;\n}\n.w-9 {\n width: 2.25rem;\n}\n.w-full {\n width: 100%;\n}\n.min-w-0 {\n min-width: 0px;\n}\n.min-w-\\[12rem\\] {\n min-width: 12rem;\n}\n.min-w-\\[200px\\] {\n min-width: 200px;\n}\n.max-w-2xl {\n max-width: 42rem;\n}\n.max-w-4xl {\n max-width: 56rem;\n}\n.max-w-\\[12rem\\] {\n max-width: 12rem;\n}\n.max-w-\\[14rem\\] {\n max-width: 14rem;\n}\n.max-w-\\[160px\\] {\n max-width: 160px;\n}\n.max-w-\\[200px\\] {\n max-width: 200px;\n}\n.max-w-full {\n max-width: 100%;\n}\n.max-w-lg {\n max-width: 32rem;\n}\n.max-w-xl {\n max-width: 36rem;\n}\n.max-w-xs {\n max-width: 20rem;\n}\n.flex-1 {\n flex: 1 1 0%;\n}\n.flex-shrink-0 {\n flex-shrink: 0;\n}\n.shrink-0 {\n flex-shrink: 0;\n}\n.-translate-y-1\\/2 {\n --tw-translate-y: -50%;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.translate-x-0\\.5 {\n --tw-translate-x: 0.125rem;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.translate-x-4 {\n --tw-translate-x: 1rem;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.scale-110 {\n --tw-scale-x: 1.1;\n --tw-scale-y: 1.1;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.transform {\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n@keyframes pulse {\n 50% {\n opacity: .5;\n }\n}\n.animate-pulse {\n animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;\n}\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n.animate-spin {\n animation: spin 1s linear infinite;\n}\n.cursor-not-allowed {\n cursor: not-allowed;\n}\n.cursor-pointer {\n cursor: pointer;\n}\n.select-none {\n -webkit-user-select: none;\n -moz-user-select: none;\n user-select: none;\n}\n.resize-none {\n resize: none;\n}\n.appearance-none {\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n}\n.grid-cols-2 {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n}\n.grid-cols-3 {\n grid-template-columns: repeat(3, minmax(0, 1fr));\n}\n.grid-cols-8 {\n grid-template-columns: repeat(8, minmax(0, 1fr));\n}\n.flex-col {\n flex-direction: column;\n}\n.flex-wrap {\n flex-wrap: wrap;\n}\n.items-start {\n align-items: flex-start;\n}\n.items-end {\n align-items: flex-end;\n}\n.items-center {\n align-items: center;\n}\n.justify-end {\n justify-content: flex-end;\n}\n.justify-center {\n justify-content: center;\n}\n.justify-between {\n justify-content: space-between;\n}\n.gap-0\\.5 {\n gap: 0.125rem;\n}\n.gap-1 {\n gap: 0.25rem;\n}\n.gap-1\\.5 {\n gap: 0.375rem;\n}\n.gap-2 {\n gap: 0.5rem;\n}\n.gap-3 {\n gap: 0.75rem;\n}\n.space-y-0\\.5 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(0.125rem * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(0.125rem * var(--tw-space-y-reverse));\n}\n.space-y-1 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(0.25rem * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(0.25rem * var(--tw-space-y-reverse));\n}\n.space-y-1\\.5 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(0.375rem * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(0.375rem * var(--tw-space-y-reverse));\n}\n.space-y-2 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(0.5rem * var(--tw-space-y-reverse));\n}\n.space-y-2\\.5 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(0.625rem * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(0.625rem * var(--tw-space-y-reverse));\n}\n.space-y-3 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(0.75rem * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(0.75rem * var(--tw-space-y-reverse));\n}\n.space-y-4 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(1rem * var(--tw-space-y-reverse));\n}\n.divide-y > :not([hidden]) ~ :not([hidden]) {\n --tw-divide-y-reverse: 0;\n border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse)));\n border-bottom-width: calc(1px * var(--tw-divide-y-reverse));\n}\n.self-start {\n align-self: flex-start;\n}\n.overflow-hidden {\n overflow: hidden;\n}\n.overflow-y-auto {\n overflow-y: auto;\n}\n.truncate {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.rounded {\n border-radius: 0.25rem;\n}\n.rounded-full {\n border-radius: 9999px;\n}\n.rounded-lg {\n border-radius: var(--radius);\n}\n.rounded-md {\n border-radius: calc(var(--radius) - 2px);\n}\n.rounded-xl {\n border-radius: 0.75rem;\n}\n.border {\n border-width: 1px;\n}\n.border-2 {\n border-width: 2px;\n}\n.border-b {\n border-bottom-width: 1px;\n}\n.border-b-2 {\n border-bottom-width: 2px;\n}\n.border-r {\n border-right-width: 1px;\n}\n.border-t {\n border-top-width: 1px;\n}\n.border-solid {\n border-style: solid;\n}\n.border-dashed {\n border-style: dashed;\n}\n.border-blue-600 {\n --tw-border-opacity: 1;\n border-color: rgb(37 99 235 / var(--tw-border-opacity, 1));\n}\n.border-border {\n border-color: hsl(var(--border));\n}\n.border-destructive {\n border-color: hsl(var(--destructive));\n}\n.border-destructive\\/50 {\n border-color: hsl(var(--destructive) / 0.5);\n}\n.border-gray-100 {\n --tw-border-opacity: 1;\n border-color: rgb(243 244 246 / var(--tw-border-opacity, 1));\n}\n.border-gray-200 {\n --tw-border-opacity: 1;\n border-color: rgb(229 231 235 / var(--tw-border-opacity, 1));\n}\n.border-gray-300 {\n --tw-border-opacity: 1;\n border-color: rgb(209 213 219 / var(--tw-border-opacity, 1));\n}\n.border-primary {\n border-color: hsl(var(--primary));\n}\n.border-primary\\/50 {\n border-color: hsl(var(--primary) / 0.5);\n}\n.border-transparent {\n border-color: transparent;\n}\n.bg-\\[hsl\\(var\\(--ra-text\\)\\)\\] {\n background-color: hsl(var(--ra-text));\n}\n.bg-accent {\n background-color: hsl(var(--accent));\n}\n.bg-amber-50 {\n --tw-bg-opacity: 1;\n background-color: rgb(255 251 235 / var(--tw-bg-opacity, 1));\n}\n.bg-background {\n background-color: hsl(var(--background));\n}\n.bg-background\\/80 {\n background-color: hsl(var(--background) / 0.8);\n}\n.bg-black\\/50 {\n background-color: rgb(0 0 0 / 0.5);\n}\n.bg-blue-100 {\n --tw-bg-opacity: 1;\n background-color: rgb(219 234 254 / var(--tw-bg-opacity, 1));\n}\n.bg-blue-50 {\n --tw-bg-opacity: 1;\n background-color: rgb(239 246 255 / var(--tw-bg-opacity, 1));\n}\n.bg-blue-500 {\n --tw-bg-opacity: 1;\n background-color: rgb(59 130 246 / var(--tw-bg-opacity, 1));\n}\n.bg-blue-600 {\n --tw-bg-opacity: 1;\n background-color: rgb(37 99 235 / var(--tw-bg-opacity, 1));\n}\n.bg-card {\n background-color: hsl(var(--card));\n}\n.bg-destructive {\n background-color: hsl(var(--destructive));\n}\n.bg-destructive\\/10 {\n background-color: hsl(var(--destructive) / 0.1);\n}\n.bg-destructive\\/5 {\n background-color: hsl(var(--destructive) / 0.05);\n}\n.bg-destructive\\/80 {\n background-color: hsl(var(--destructive) / 0.8);\n}\n.bg-emerald-50 {\n --tw-bg-opacity: 1;\n background-color: rgb(236 253 245 / var(--tw-bg-opacity, 1));\n}\n.bg-foreground {\n background-color: hsl(var(--foreground));\n}\n.bg-foreground\\/60 {\n background-color: hsl(var(--foreground) / 0.6);\n}\n.bg-gray-100 {\n --tw-bg-opacity: 1;\n background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));\n}\n.bg-gray-300 {\n --tw-bg-opacity: 1;\n background-color: rgb(209 213 219 / var(--tw-bg-opacity, 1));\n}\n.bg-gray-50 {\n --tw-bg-opacity: 1;\n background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1));\n}\n.bg-muted {\n background-color: hsl(var(--muted));\n}\n.bg-muted\\/20 {\n background-color: hsl(var(--muted) / 0.2);\n}\n.bg-muted\\/30 {\n background-color: hsl(var(--muted) / 0.3);\n}\n.bg-primary {\n background-color: hsl(var(--primary));\n}\n.bg-primary\\/10 {\n background-color: hsl(var(--primary) / 0.1);\n}\n.bg-primary\\/5 {\n background-color: hsl(var(--primary) / 0.05);\n}\n.bg-red-50 {\n --tw-bg-opacity: 1;\n background-color: rgb(254 242 242 / var(--tw-bg-opacity, 1));\n}\n.bg-transparent {\n background-color: transparent;\n}\n.bg-white {\n --tw-bg-opacity: 1;\n background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));\n}\n.fill-current {\n fill: currentColor;\n}\n.object-contain {\n -o-object-fit: contain;\n object-fit: contain;\n}\n.object-cover {\n -o-object-fit: cover;\n object-fit: cover;\n}\n.p-0\\.5 {\n padding: 0.125rem;\n}\n.p-1 {\n padding: 0.25rem;\n}\n.p-1\\.5 {\n padding: 0.375rem;\n}\n.p-2 {\n padding: 0.5rem;\n}\n.p-2\\.5 {\n padding: 0.625rem;\n}\n.p-3 {\n padding: 0.75rem;\n}\n.p-4 {\n padding: 1rem;\n}\n.p-6 {\n padding: 1.5rem;\n}\n.px-1 {\n padding-left: 0.25rem;\n padding-right: 0.25rem;\n}\n.px-1\\.5 {\n padding-left: 0.375rem;\n padding-right: 0.375rem;\n}\n.px-2 {\n padding-left: 0.5rem;\n padding-right: 0.5rem;\n}\n.px-2\\.5 {\n padding-left: 0.625rem;\n padding-right: 0.625rem;\n}\n.px-3 {\n padding-left: 0.75rem;\n padding-right: 0.75rem;\n}\n.px-4 {\n padding-left: 1rem;\n padding-right: 1rem;\n}\n.px-5 {\n padding-left: 1.25rem;\n padding-right: 1.25rem;\n}\n.py-0 {\n padding-top: 0px;\n padding-bottom: 0px;\n}\n.py-0\\.5 {\n padding-top: 0.125rem;\n padding-bottom: 0.125rem;\n}\n.py-1 {\n padding-top: 0.25rem;\n padding-bottom: 0.25rem;\n}\n.py-1\\.5 {\n padding-top: 0.375rem;\n padding-bottom: 0.375rem;\n}\n.py-10 {\n padding-top: 2.5rem;\n padding-bottom: 2.5rem;\n}\n.py-12 {\n padding-top: 3rem;\n padding-bottom: 3rem;\n}\n.py-2 {\n padding-top: 0.5rem;\n padding-bottom: 0.5rem;\n}\n.py-2\\.5 {\n padding-top: 0.625rem;\n padding-bottom: 0.625rem;\n}\n.py-3 {\n padding-top: 0.75rem;\n padding-bottom: 0.75rem;\n}\n.py-4 {\n padding-top: 1rem;\n padding-bottom: 1rem;\n}\n.pb-1 {\n padding-bottom: 0.25rem;\n}\n.pb-2 {\n padding-bottom: 0.5rem;\n}\n.pb-3 {\n padding-bottom: 0.75rem;\n}\n.pl-1 {\n padding-left: 0.25rem;\n}\n.pl-7 {\n padding-left: 1.75rem;\n}\n.pl-8 {\n padding-left: 2rem;\n}\n.pl-9 {\n padding-left: 2.25rem;\n}\n.pr-2 {\n padding-right: 0.5rem;\n}\n.pr-3 {\n padding-right: 0.75rem;\n}\n.pr-5 {\n padding-right: 1.25rem;\n}\n.pr-9 {\n padding-right: 2.25rem;\n}\n.pt-1 {\n padding-top: 0.25rem;\n}\n.pt-2 {\n padding-top: 0.5rem;\n}\n.pt-3 {\n padding-top: 0.75rem;\n}\n.pt-4 {\n padding-top: 1rem;\n}\n.text-left {\n text-align: left;\n}\n.text-center {\n text-align: center;\n}\n.font-mono {\n font-family:\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Monaco,\n Consolas,\n "Liberation Mono",\n "Courier New",\n monospace;\n}\n.text-2xl {\n font-size: 1.5rem;\n line-height: 2rem;\n}\n.text-\\[10px\\] {\n font-size: 10px;\n}\n.text-\\[11px\\] {\n font-size: 11px;\n}\n.text-\\[9px\\] {\n font-size: 9px;\n}\n.text-base {\n font-size: 1rem;\n line-height: 1.5rem;\n}\n.text-sm {\n font-size: 0.875rem;\n line-height: 1.25rem;\n}\n.text-xs {\n font-size: 0.75rem;\n line-height: 1rem;\n}\n.font-bold {\n font-weight: 700;\n}\n.font-medium {\n font-weight: 500;\n}\n.font-semibold {\n font-weight: 600;\n}\n.uppercase {\n text-transform: uppercase;\n}\n.capitalize {\n text-transform: capitalize;\n}\n.\\!italic {\n font-style: italic !important;\n}\n.italic {\n font-style: italic;\n}\n.tracking-wide {\n letter-spacing: 0.025em;\n}\n.tracking-wider {\n letter-spacing: 0.05em;\n}\n.text-\\[hsl\\(var\\(--ra-surface\\)\\)\\] {\n color: hsl(var(--ra-surface));\n}\n.text-accent-foreground {\n color: hsl(var(--accent-foreground));\n}\n.text-amber-600 {\n --tw-text-opacity: 1;\n color: rgb(217 119 6 / var(--tw-text-opacity, 1));\n}\n.text-amber-700 {\n --tw-text-opacity: 1;\n color: rgb(180 83 9 / var(--tw-text-opacity, 1));\n}\n.text-background {\n color: hsl(var(--background));\n}\n.text-blue-700 {\n --tw-text-opacity: 1;\n color: rgb(29 78 216 / var(--tw-text-opacity, 1));\n}\n.text-destructive {\n color: hsl(var(--destructive));\n}\n.text-destructive-foreground {\n color: hsl(var(--destructive-foreground));\n}\n.text-emerald-700 {\n --tw-text-opacity: 1;\n color: rgb(4 120 87 / var(--tw-text-opacity, 1));\n}\n.text-foreground {\n color: hsl(var(--foreground));\n}\n.text-gray-400 {\n --tw-text-opacity: 1;\n color: rgb(156 163 175 / var(--tw-text-opacity, 1));\n}\n.text-gray-500 {\n --tw-text-opacity: 1;\n color: rgb(107 114 128 / var(--tw-text-opacity, 1));\n}\n.text-gray-600 {\n --tw-text-opacity: 1;\n color: rgb(75 85 99 / var(--tw-text-opacity, 1));\n}\n.text-gray-700 {\n --tw-text-opacity: 1;\n color: rgb(55 65 81 / var(--tw-text-opacity, 1));\n}\n.text-gray-800 {\n --tw-text-opacity: 1;\n color: rgb(31 41 55 / var(--tw-text-opacity, 1));\n}\n.text-gray-900 {\n --tw-text-opacity: 1;\n color: rgb(17 24 39 / var(--tw-text-opacity, 1));\n}\n.text-muted-foreground {\n color: hsl(var(--muted-foreground));\n}\n.text-muted-foreground\\/40 {\n color: hsl(var(--muted-foreground) / 0.4);\n}\n.text-primary {\n color: hsl(var(--primary));\n}\n.text-primary-foreground {\n color: hsl(var(--primary-foreground));\n}\n.text-red-400 {\n --tw-text-opacity: 1;\n color: rgb(248 113 113 / var(--tw-text-opacity, 1));\n}\n.text-red-700 {\n --tw-text-opacity: 1;\n color: rgb(185 28 28 / var(--tw-text-opacity, 1));\n}\n.text-white {\n --tw-text-opacity: 1;\n color: rgb(255 255 255 / var(--tw-text-opacity, 1));\n}\n.underline {\n text-decoration-line: underline;\n}\n.opacity-0 {\n opacity: 0;\n}\n.opacity-100 {\n opacity: 1;\n}\n.opacity-50 {\n opacity: 0.5;\n}\n.opacity-60 {\n opacity: 0.6;\n}\n.opacity-70 {\n opacity: 0.7;\n}\n.opacity-80 {\n opacity: 0.8;\n}\n.shadow {\n --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);\n --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);\n box-shadow:\n var(--tw-ring-offset-shadow, 0 0 #0000),\n var(--tw-ring-shadow, 0 0 #0000),\n var(--tw-shadow);\n}\n.shadow-2xl {\n --tw-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25);\n --tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);\n box-shadow:\n var(--tw-ring-offset-shadow, 0 0 #0000),\n var(--tw-ring-shadow, 0 0 #0000),\n var(--tw-shadow);\n}\n.shadow-lg {\n --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);\n --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);\n box-shadow:\n var(--tw-ring-offset-shadow, 0 0 #0000),\n var(--tw-ring-shadow, 0 0 #0000),\n var(--tw-shadow);\n}\n.shadow-sm {\n --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);\n --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);\n box-shadow:\n var(--tw-ring-offset-shadow, 0 0 #0000),\n var(--tw-ring-shadow, 0 0 #0000),\n var(--tw-shadow);\n}\n.shadow-xl {\n --tw-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);\n --tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);\n box-shadow:\n var(--tw-ring-offset-shadow, 0 0 #0000),\n var(--tw-ring-shadow, 0 0 #0000),\n var(--tw-shadow);\n}\n.outline {\n outline-style: solid;\n}\n.ring-1 {\n --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);\n box-shadow:\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow, 0 0 #0000);\n}\n.ring-2 {\n --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);\n box-shadow:\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow, 0 0 #0000);\n}\n.ring-primary {\n --tw-ring-color: hsl(var(--primary)) ;\n}\n.filter {\n filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);\n}\n.backdrop-blur-sm {\n --tw-backdrop-blur: blur(4px);\n backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);\n}\n.transition {\n transition-property:\n color,\n background-color,\n border-color,\n text-decoration-color,\n fill,\n stroke,\n opacity,\n box-shadow,\n transform,\n filter,\n backdrop-filter;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.transition-all {\n transition-property: all;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.transition-colors {\n transition-property:\n color,\n background-color,\n border-color,\n text-decoration-color,\n fill,\n stroke;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.transition-opacity {\n transition-property: opacity;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.transition-shadow {\n transition-property: box-shadow;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.transition-transform {\n transition-property: transform;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.duration-300 {\n transition-duration: 300ms;\n}\n.placeholder\\:text-muted-foreground::-moz-placeholder {\n color: hsl(var(--muted-foreground));\n}\n.placeholder\\:text-muted-foreground::placeholder {\n color: hsl(var(--muted-foreground));\n}\n.hover\\:border-blue-400:hover {\n --tw-border-opacity: 1;\n border-color: rgb(96 165 250 / var(--tw-border-opacity, 1));\n}\n.hover\\:border-gray-300:hover {\n --tw-border-opacity: 1;\n border-color: rgb(209 213 219 / var(--tw-border-opacity, 1));\n}\n.hover\\:border-muted-foreground:hover {\n border-color: hsl(var(--muted-foreground));\n}\n.hover\\:border-muted-foreground\\/40:hover {\n border-color: hsl(var(--muted-foreground) / 0.4);\n}\n.hover\\:border-ring:hover {\n border-color: hsl(var(--ring));\n}\n.hover\\:bg-\\[hsl\\(var\\(--ra-muted\\)\\)\\]:hover {\n background-color: hsl(var(--ra-muted));\n}\n.hover\\:bg-\\[hsl\\(var\\(--ra-muted\\)\\/0\\.5\\)\\]:hover {\n background-color: hsl(var(--ra-muted)/0.5);\n}\n.hover\\:bg-accent:hover {\n background-color: hsl(var(--accent));\n}\n.hover\\:bg-accent\\/30:hover {\n background-color: hsl(var(--accent) / 0.3);\n}\n.hover\\:bg-accent\\/50:hover {\n background-color: hsl(var(--accent) / 0.5);\n}\n.hover\\:bg-blue-100:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(219 234 254 / var(--tw-bg-opacity, 1));\n}\n.hover\\:bg-blue-50\\/50:hover {\n background-color: rgb(239 246 255 / 0.5);\n}\n.hover\\:bg-blue-700:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(29 78 216 / var(--tw-bg-opacity, 1));\n}\n.hover\\:bg-destructive:hover {\n background-color: hsl(var(--destructive));\n}\n.hover\\:bg-destructive\\/10:hover {\n background-color: hsl(var(--destructive) / 0.1);\n}\n.hover\\:bg-gray-100:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));\n}\n.hover\\:bg-gray-200:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(229 231 235 / var(--tw-bg-opacity, 1));\n}\n.hover\\:bg-gray-50:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1));\n}\n.hover\\:bg-muted:hover {\n background-color: hsl(var(--muted));\n}\n.hover\\:bg-primary\\/90:hover {\n background-color: hsl(var(--primary) / 0.9);\n}\n.hover\\:bg-red-100:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(254 226 226 / var(--tw-bg-opacity, 1));\n}\n.hover\\:bg-red-50:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(254 242 242 / var(--tw-bg-opacity, 1));\n}\n.hover\\:text-accent-foreground:hover {\n color: hsl(var(--accent-foreground));\n}\n.hover\\:text-blue-500:hover {\n --tw-text-opacity: 1;\n color: rgb(59 130 246 / var(--tw-text-opacity, 1));\n}\n.hover\\:text-blue-600:hover {\n --tw-text-opacity: 1;\n color: rgb(37 99 235 / var(--tw-text-opacity, 1));\n}\n.hover\\:text-destructive:hover {\n color: hsl(var(--destructive));\n}\n.hover\\:text-destructive\\/80:hover {\n color: hsl(var(--destructive) / 0.8);\n}\n.hover\\:text-foreground:hover {\n color: hsl(var(--foreground));\n}\n.hover\\:text-red-600:hover {\n --tw-text-opacity: 1;\n color: rgb(220 38 38 / var(--tw-text-opacity, 1));\n}\n.hover\\:underline:hover {\n text-decoration-line: underline;\n}\n.hover\\:opacity-100:hover {\n opacity: 1;\n}\n.hover\\:shadow-md:hover {\n --tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);\n --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);\n box-shadow:\n var(--tw-ring-offset-shadow, 0 0 #0000),\n var(--tw-ring-shadow, 0 0 #0000),\n var(--tw-shadow);\n}\n.hover\\:shadow-sm:hover {\n --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);\n --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);\n box-shadow:\n var(--tw-ring-offset-shadow, 0 0 #0000),\n var(--tw-ring-shadow, 0 0 #0000),\n var(--tw-shadow);\n}\n.focus\\:outline-none:focus {\n outline: 2px solid transparent;\n outline-offset: 2px;\n}\n.focus\\:ring-1:focus {\n --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);\n box-shadow:\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow, 0 0 #0000);\n}\n.focus\\:ring-2:focus {\n --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);\n box-shadow:\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow, 0 0 #0000);\n}\n.focus\\:ring-blue-500:focus {\n --tw-ring-opacity: 1;\n --tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1)) ;\n}\n.focus\\:ring-ring:focus {\n --tw-ring-color: hsl(var(--ring)) ;\n}\n.disabled\\:cursor-not-allowed:disabled {\n cursor: not-allowed;\n}\n.disabled\\:opacity-30:disabled {\n opacity: 0.3;\n}\n.disabled\\:opacity-40:disabled {\n opacity: 0.4;\n}\n.disabled\\:opacity-50:disabled {\n opacity: 0.5;\n}\n.disabled\\:opacity-60:disabled {\n opacity: 0.6;\n}\n.disabled\\:opacity-70:disabled {\n opacity: 0.7;\n}\n.group:hover .group-hover\\:opacity-100 {\n opacity: 1;\n}\n@media (min-width: 640px) {\n .sm\\:grid-cols-10 {\n grid-template-columns: repeat(10, minmax(0, 1fr));\n }\n .sm\\:grid-cols-3 {\n grid-template-columns: repeat(3, minmax(0, 1fr));\n }\n .sm\\:grid-cols-4 {\n grid-template-columns: repeat(4, minmax(0, 1fr));\n }\n}\n@media (min-width: 768px) {\n .md\\:grid-cols-12 {\n grid-template-columns: repeat(12, minmax(0, 1fr));\n }\n .md\\:grid-cols-4 {\n grid-template-columns: repeat(4, minmax(0, 1fr));\n }\n .md\\:grid-cols-5 {\n grid-template-columns: repeat(5, minmax(0, 1fr));\n }\n}\n@media (min-width: 1024px) {\n .lg\\:grid-cols-6 {\n grid-template-columns: repeat(6, minmax(0, 1fr));\n }\n}\n@media (prefers-color-scheme: dark) {\n .dark\\:border-gray-600 {\n --tw-border-opacity: 1;\n border-color: rgb(75 85 99 / var(--tw-border-opacity, 1));\n }\n .dark\\:border-gray-700 {\n --tw-border-opacity: 1;\n border-color: rgb(55 65 81 / var(--tw-border-opacity, 1));\n }\n .dark\\:border-gray-800 {\n --tw-border-opacity: 1;\n border-color: rgb(31 41 55 / var(--tw-border-opacity, 1));\n }\n .dark\\:bg-amber-900\\/30 {\n background-color: rgb(120 53 15 / 0.3);\n }\n .dark\\:bg-blue-900\\/30 {\n background-color: rgb(30 58 138 / 0.3);\n }\n .dark\\:bg-blue-900\\/40 {\n background-color: rgb(30 58 138 / 0.4);\n }\n .dark\\:bg-emerald-900\\/30 {\n background-color: rgb(6 78 59 / 0.3);\n }\n .dark\\:bg-gray-600 {\n --tw-bg-opacity: 1;\n background-color: rgb(75 85 99 / var(--tw-bg-opacity, 1));\n }\n .dark\\:bg-gray-700 {\n --tw-bg-opacity: 1;\n background-color: rgb(55 65 81 / var(--tw-bg-opacity, 1));\n }\n .dark\\:bg-gray-800 {\n --tw-bg-opacity: 1;\n background-color: rgb(31 41 55 / var(--tw-bg-opacity, 1));\n }\n .dark\\:bg-gray-800\\/50 {\n background-color: rgb(31 41 55 / 0.5);\n }\n .dark\\:bg-gray-900 {\n --tw-bg-opacity: 1;\n background-color: rgb(17 24 39 / var(--tw-bg-opacity, 1));\n }\n .dark\\:bg-red-900\\/30 {\n background-color: rgb(127 29 29 / 0.3);\n }\n .dark\\:text-amber-300 {\n --tw-text-opacity: 1;\n color: rgb(252 211 77 / var(--tw-text-opacity, 1));\n }\n .dark\\:text-amber-400 {\n --tw-text-opacity: 1;\n color: rgb(251 191 36 / var(--tw-text-opacity, 1));\n }\n .dark\\:text-blue-300 {\n --tw-text-opacity: 1;\n color: rgb(147 197 253 / var(--tw-text-opacity, 1));\n }\n .dark\\:text-emerald-300 {\n --tw-text-opacity: 1;\n color: rgb(110 231 183 / var(--tw-text-opacity, 1));\n }\n .dark\\:text-gray-100 {\n --tw-text-opacity: 1;\n color: rgb(243 244 246 / var(--tw-text-opacity, 1));\n }\n .dark\\:text-gray-200 {\n --tw-text-opacity: 1;\n color: rgb(229 231 235 / var(--tw-text-opacity, 1));\n }\n .dark\\:text-gray-300 {\n --tw-text-opacity: 1;\n color: rgb(209 213 219 / var(--tw-text-opacity, 1));\n }\n .dark\\:text-gray-400 {\n --tw-text-opacity: 1;\n color: rgb(156 163 175 / var(--tw-text-opacity, 1));\n }\n .dark\\:text-gray-500 {\n --tw-text-opacity: 1;\n color: rgb(107 114 128 / var(--tw-text-opacity, 1));\n }\n .dark\\:text-red-300 {\n --tw-text-opacity: 1;\n color: rgb(252 165 165 / var(--tw-text-opacity, 1));\n }\n .dark\\:hover\\:border-blue-500:hover {\n --tw-border-opacity: 1;\n border-color: rgb(59 130 246 / var(--tw-border-opacity, 1));\n }\n .dark\\:hover\\:border-gray-600:hover {\n --tw-border-opacity: 1;\n border-color: rgb(75 85 99 / var(--tw-border-opacity, 1));\n }\n .dark\\:hover\\:bg-blue-900\\/50:hover {\n background-color: rgb(30 58 138 / 0.5);\n }\n .dark\\:hover\\:bg-blue-950\\/20:hover {\n background-color: rgb(23 37 84 / 0.2);\n }\n .dark\\:hover\\:bg-gray-700:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(55 65 81 / var(--tw-bg-opacity, 1));\n }\n .dark\\:hover\\:bg-gray-800:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(31 41 55 / var(--tw-bg-opacity, 1));\n }\n .dark\\:hover\\:bg-gray-800\\/50:hover {\n background-color: rgb(31 41 55 / 0.5);\n }\n .dark\\:hover\\:bg-red-900\\/20:hover {\n background-color: rgb(127 29 29 / 0.2);\n }\n .dark\\:hover\\:bg-red-900\\/30:hover {\n background-color: rgb(127 29 29 / 0.3);\n }\n .dark\\:hover\\:text-blue-400:hover {\n --tw-text-opacity: 1;\n color: rgb(96 165 250 / var(--tw-text-opacity, 1));\n }\n}\n');
25
+
26
+ export { styleInject };
27
+ //# sourceMappingURL=chunk-LLSIDR6U.js.map
28
+ //# sourceMappingURL=chunk-LLSIDR6U.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["#style-inject:#style-inject","../src/styles.css"],"names":[],"mappings":";AACyB,SAAR,YAA6B,GAAA,EAAK,EAAE,QAAA,EAAS,GAAI,EAAC,EAAG;AAC1D,EAAA,IAAI,CAAC,GAAA,IAAO,OAAO,QAAA,KAAa,WAAA,EAAa;AAE7C,EAAA,MAAM,OAAO,QAAA,CAAS,IAAA,IAAQ,SAAS,oBAAA,CAAqB,MAAM,EAAE,CAAC,CAAA;AACrE,EAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,aAAA,CAAc,OAAO,CAAA;AAC5C,EAAA,KAAA,CAAM,IAAA,GAAO,UAAA;AAEb,EAAA,IAAI,aAAa,KAAA,EAAO;AACtB,IAAA,IAAI,KAAK,UAAA,EAAY;AACnB,MAAA,IAAA,CAAK,YAAA,CAAa,KAAA,EAAO,IAAA,CAAK,UAAU,CAAA;AAAA,IAC1C,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,YAAY,KAAK,CAAA;AAAA,IACxB;AAAA,EACF,CAAA,MAAO;AACL,IAAA,IAAA,CAAK,YAAY,KAAK,CAAA;AAAA,EACxB;AAEA,EAAA,IAAI,MAAM,UAAA,EAAY;AACpB,IAAA,KAAA,CAAM,WAAW,OAAA,GAAU,GAAA;AAAA,EAC7B,CAAA,MAAO;AACL,IAAA,KAAA,CAAM,WAAA,CAAY,QAAA,CAAS,cAAA,CAAe,GAAG,CAAC,CAAA;AAAA,EAChD;AACF;;;ACvB8B,WAAA,CAAY,gv9BAAov9B,CAAA","file":"chunk-LLSIDR6U.js","sourcesContent":["\n export default function styleInject(css, { insertAt } = {}) {\n if (!css || typeof document === 'undefined') return\n \n const head = document.head || document.getElementsByTagName('head')[0]\n const style = document.createElement('style')\n style.type = 'text/css'\n \n if (insertAt === 'top') {\n if (head.firstChild) {\n head.insertBefore(style, head.firstChild)\n } else {\n head.appendChild(style)\n }\n } else {\n head.appendChild(style)\n }\n \n if (style.styleSheet) {\n style.styleSheet.cssText = css\n } else {\n style.appendChild(document.createTextNode(css))\n }\n }\n ","import styleInject from '#style-inject';styleInject(\".sr-only {\\n position: absolute;\\n width: 1px;\\n height: 1px;\\n padding: 0;\\n margin: -1px;\\n overflow: hidden;\\n clip: rect(0, 0, 0, 0);\\n white-space: nowrap;\\n border-width: 0;\\n}\\n.pointer-events-none {\\n pointer-events: none;\\n}\\n.visible {\\n visibility: visible;\\n}\\n.collapse {\\n visibility: collapse;\\n}\\n.fixed {\\n position: fixed;\\n}\\n.absolute {\\n position: absolute;\\n}\\n.relative {\\n position: relative;\\n}\\n.sticky {\\n position: sticky;\\n}\\n.inset-0 {\\n inset: 0px;\\n}\\n.inset-x-0 {\\n left: 0px;\\n right: 0px;\\n}\\n.bottom-0 {\\n bottom: 0px;\\n}\\n.left-0 {\\n left: 0px;\\n}\\n.left-1\\\\.5 {\\n left: 0.375rem;\\n}\\n.left-2 {\\n left: 0.5rem;\\n}\\n.left-2\\\\.5 {\\n left: 0.625rem;\\n}\\n.left-3 {\\n left: 0.75rem;\\n}\\n.right-0 {\\n right: 0px;\\n}\\n.right-1\\\\.5 {\\n right: 0.375rem;\\n}\\n.right-2 {\\n right: 0.5rem;\\n}\\n.right-3 {\\n right: 0.75rem;\\n}\\n.top-0 {\\n top: 0px;\\n}\\n.top-0\\\\.5 {\\n top: 0.125rem;\\n}\\n.top-1\\\\.5 {\\n top: 0.375rem;\\n}\\n.top-1\\\\/2 {\\n top: 50%;\\n}\\n.top-2 {\\n top: 0.5rem;\\n}\\n.z-10 {\\n z-index: 10;\\n}\\n.z-20 {\\n z-index: 20;\\n}\\n.z-40 {\\n z-index: 40;\\n}\\n.z-50 {\\n z-index: 50;\\n}\\n.col-span-2 {\\n grid-column: span 2 / span 2;\\n}\\n.mx-4 {\\n margin-left: 1rem;\\n margin-right: 1rem;\\n}\\n.mx-auto {\\n margin-left: auto;\\n margin-right: auto;\\n}\\n.-mb-px {\\n margin-bottom: -1px;\\n}\\n.mb-1 {\\n margin-bottom: 0.25rem;\\n}\\n.mb-2 {\\n margin-bottom: 0.5rem;\\n}\\n.mb-3 {\\n margin-bottom: 0.75rem;\\n}\\n.mb-4 {\\n margin-bottom: 1rem;\\n}\\n.ml-1 {\\n margin-left: 0.25rem;\\n}\\n.ml-1\\\\.5 {\\n margin-left: 0.375rem;\\n}\\n.ml-2 {\\n margin-left: 0.5rem;\\n}\\n.ml-auto {\\n margin-left: auto;\\n}\\n.mt-0\\\\.5 {\\n margin-top: 0.125rem;\\n}\\n.mt-1 {\\n margin-top: 0.25rem;\\n}\\n.mt-1\\\\.5 {\\n margin-top: 0.375rem;\\n}\\n.mt-2 {\\n margin-top: 0.5rem;\\n}\\n.mt-4 {\\n margin-top: 1rem;\\n}\\n.block {\\n display: block;\\n}\\n.inline-block {\\n display: inline-block;\\n}\\n.inline {\\n display: inline;\\n}\\n.flex {\\n display: flex;\\n}\\n.inline-flex {\\n display: inline-flex;\\n}\\n.table {\\n display: table;\\n}\\n.grid {\\n display: grid;\\n}\\n.contents {\\n display: contents;\\n}\\n.hidden {\\n display: none;\\n}\\n.aspect-square {\\n aspect-ratio: 1 / 1;\\n}\\n.aspect-video {\\n aspect-ratio: 16 / 9;\\n}\\n.h-1\\\\.5 {\\n height: 0.375rem;\\n}\\n.h-10 {\\n height: 2.5rem;\\n}\\n.h-11 {\\n height: 2.75rem;\\n}\\n.h-16 {\\n height: 4rem;\\n}\\n.h-2 {\\n height: 0.5rem;\\n}\\n.h-2\\\\.5 {\\n height: 0.625rem;\\n}\\n.h-3 {\\n height: 0.75rem;\\n}\\n.h-3\\\\.5 {\\n height: 0.875rem;\\n}\\n.h-4 {\\n height: 1rem;\\n}\\n.h-5 {\\n height: 1.25rem;\\n}\\n.h-6 {\\n height: 1.5rem;\\n}\\n.h-7 {\\n height: 1.75rem;\\n}\\n.h-8 {\\n height: 2rem;\\n}\\n.h-9 {\\n height: 2.25rem;\\n}\\n.h-full {\\n height: 100%;\\n}\\n.max-h-32 {\\n max-height: 8rem;\\n}\\n.max-h-80 {\\n max-height: 20rem;\\n}\\n.max-h-\\\\[300px\\\\] {\\n max-height: 300px;\\n}\\n.max-h-\\\\[400px\\\\] {\\n max-height: 400px;\\n}\\n.max-h-\\\\[80vh\\\\] {\\n max-height: 80vh;\\n}\\n.max-h-\\\\[85vh\\\\] {\\n max-height: 85vh;\\n}\\n.min-h-0 {\\n min-height: 0px;\\n}\\n.w-1\\\\.5 {\\n width: 0.375rem;\\n}\\n.w-10 {\\n width: 2.5rem;\\n}\\n.w-16 {\\n width: 4rem;\\n}\\n.w-2 {\\n width: 0.5rem;\\n}\\n.w-2\\\\.5 {\\n width: 0.625rem;\\n}\\n.w-3 {\\n width: 0.75rem;\\n}\\n.w-3\\\\.5 {\\n width: 0.875rem;\\n}\\n.w-36 {\\n width: 9rem;\\n}\\n.w-4 {\\n width: 1rem;\\n}\\n.w-5 {\\n width: 1.25rem;\\n}\\n.w-6 {\\n width: 1.5rem;\\n}\\n.w-7 {\\n width: 1.75rem;\\n}\\n.w-8 {\\n width: 2rem;\\n}\\n.w-9 {\\n width: 2.25rem;\\n}\\n.w-full {\\n width: 100%;\\n}\\n.min-w-0 {\\n min-width: 0px;\\n}\\n.min-w-\\\\[12rem\\\\] {\\n min-width: 12rem;\\n}\\n.min-w-\\\\[200px\\\\] {\\n min-width: 200px;\\n}\\n.max-w-2xl {\\n max-width: 42rem;\\n}\\n.max-w-4xl {\\n max-width: 56rem;\\n}\\n.max-w-\\\\[12rem\\\\] {\\n max-width: 12rem;\\n}\\n.max-w-\\\\[14rem\\\\] {\\n max-width: 14rem;\\n}\\n.max-w-\\\\[160px\\\\] {\\n max-width: 160px;\\n}\\n.max-w-\\\\[200px\\\\] {\\n max-width: 200px;\\n}\\n.max-w-full {\\n max-width: 100%;\\n}\\n.max-w-lg {\\n max-width: 32rem;\\n}\\n.max-w-xl {\\n max-width: 36rem;\\n}\\n.max-w-xs {\\n max-width: 20rem;\\n}\\n.flex-1 {\\n flex: 1 1 0%;\\n}\\n.flex-shrink-0 {\\n flex-shrink: 0;\\n}\\n.shrink-0 {\\n flex-shrink: 0;\\n}\\n.-translate-y-1\\\\/2 {\\n --tw-translate-y: -50%;\\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\\n}\\n.translate-x-0\\\\.5 {\\n --tw-translate-x: 0.125rem;\\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\\n}\\n.translate-x-4 {\\n --tw-translate-x: 1rem;\\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\\n}\\n.scale-110 {\\n --tw-scale-x: 1.1;\\n --tw-scale-y: 1.1;\\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\\n}\\n.transform {\\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\\n}\\n@keyframes pulse {\\n 50% {\\n opacity: .5;\\n }\\n}\\n.animate-pulse {\\n animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;\\n}\\n@keyframes spin {\\n to {\\n transform: rotate(360deg);\\n }\\n}\\n.animate-spin {\\n animation: spin 1s linear infinite;\\n}\\n.cursor-not-allowed {\\n cursor: not-allowed;\\n}\\n.cursor-pointer {\\n cursor: pointer;\\n}\\n.select-none {\\n -webkit-user-select: none;\\n -moz-user-select: none;\\n user-select: none;\\n}\\n.resize-none {\\n resize: none;\\n}\\n.appearance-none {\\n -webkit-appearance: none;\\n -moz-appearance: none;\\n appearance: none;\\n}\\n.grid-cols-2 {\\n grid-template-columns: repeat(2, minmax(0, 1fr));\\n}\\n.grid-cols-3 {\\n grid-template-columns: repeat(3, minmax(0, 1fr));\\n}\\n.grid-cols-8 {\\n grid-template-columns: repeat(8, minmax(0, 1fr));\\n}\\n.flex-col {\\n flex-direction: column;\\n}\\n.flex-wrap {\\n flex-wrap: wrap;\\n}\\n.items-start {\\n align-items: flex-start;\\n}\\n.items-end {\\n align-items: flex-end;\\n}\\n.items-center {\\n align-items: center;\\n}\\n.justify-end {\\n justify-content: flex-end;\\n}\\n.justify-center {\\n justify-content: center;\\n}\\n.justify-between {\\n justify-content: space-between;\\n}\\n.gap-0\\\\.5 {\\n gap: 0.125rem;\\n}\\n.gap-1 {\\n gap: 0.25rem;\\n}\\n.gap-1\\\\.5 {\\n gap: 0.375rem;\\n}\\n.gap-2 {\\n gap: 0.5rem;\\n}\\n.gap-3 {\\n gap: 0.75rem;\\n}\\n.space-y-0\\\\.5 > :not([hidden]) ~ :not([hidden]) {\\n --tw-space-y-reverse: 0;\\n margin-top: calc(0.125rem * calc(1 - var(--tw-space-y-reverse)));\\n margin-bottom: calc(0.125rem * var(--tw-space-y-reverse));\\n}\\n.space-y-1 > :not([hidden]) ~ :not([hidden]) {\\n --tw-space-y-reverse: 0;\\n margin-top: calc(0.25rem * calc(1 - var(--tw-space-y-reverse)));\\n margin-bottom: calc(0.25rem * var(--tw-space-y-reverse));\\n}\\n.space-y-1\\\\.5 > :not([hidden]) ~ :not([hidden]) {\\n --tw-space-y-reverse: 0;\\n margin-top: calc(0.375rem * calc(1 - var(--tw-space-y-reverse)));\\n margin-bottom: calc(0.375rem * var(--tw-space-y-reverse));\\n}\\n.space-y-2 > :not([hidden]) ~ :not([hidden]) {\\n --tw-space-y-reverse: 0;\\n margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));\\n margin-bottom: calc(0.5rem * var(--tw-space-y-reverse));\\n}\\n.space-y-2\\\\.5 > :not([hidden]) ~ :not([hidden]) {\\n --tw-space-y-reverse: 0;\\n margin-top: calc(0.625rem * calc(1 - var(--tw-space-y-reverse)));\\n margin-bottom: calc(0.625rem * var(--tw-space-y-reverse));\\n}\\n.space-y-3 > :not([hidden]) ~ :not([hidden]) {\\n --tw-space-y-reverse: 0;\\n margin-top: calc(0.75rem * calc(1 - var(--tw-space-y-reverse)));\\n margin-bottom: calc(0.75rem * var(--tw-space-y-reverse));\\n}\\n.space-y-4 > :not([hidden]) ~ :not([hidden]) {\\n --tw-space-y-reverse: 0;\\n margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));\\n margin-bottom: calc(1rem * var(--tw-space-y-reverse));\\n}\\n.divide-y > :not([hidden]) ~ :not([hidden]) {\\n --tw-divide-y-reverse: 0;\\n border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse)));\\n border-bottom-width: calc(1px * var(--tw-divide-y-reverse));\\n}\\n.self-start {\\n align-self: flex-start;\\n}\\n.overflow-hidden {\\n overflow: hidden;\\n}\\n.overflow-y-auto {\\n overflow-y: auto;\\n}\\n.truncate {\\n overflow: hidden;\\n text-overflow: ellipsis;\\n white-space: nowrap;\\n}\\n.rounded {\\n border-radius: 0.25rem;\\n}\\n.rounded-full {\\n border-radius: 9999px;\\n}\\n.rounded-lg {\\n border-radius: var(--radius);\\n}\\n.rounded-md {\\n border-radius: calc(var(--radius) - 2px);\\n}\\n.rounded-xl {\\n border-radius: 0.75rem;\\n}\\n.border {\\n border-width: 1px;\\n}\\n.border-2 {\\n border-width: 2px;\\n}\\n.border-b {\\n border-bottom-width: 1px;\\n}\\n.border-b-2 {\\n border-bottom-width: 2px;\\n}\\n.border-r {\\n border-right-width: 1px;\\n}\\n.border-t {\\n border-top-width: 1px;\\n}\\n.border-solid {\\n border-style: solid;\\n}\\n.border-dashed {\\n border-style: dashed;\\n}\\n.border-blue-600 {\\n --tw-border-opacity: 1;\\n border-color: rgb(37 99 235 / var(--tw-border-opacity, 1));\\n}\\n.border-border {\\n border-color: hsl(var(--border));\\n}\\n.border-destructive {\\n border-color: hsl(var(--destructive));\\n}\\n.border-destructive\\\\/50 {\\n border-color: hsl(var(--destructive) / 0.5);\\n}\\n.border-gray-100 {\\n --tw-border-opacity: 1;\\n border-color: rgb(243 244 246 / var(--tw-border-opacity, 1));\\n}\\n.border-gray-200 {\\n --tw-border-opacity: 1;\\n border-color: rgb(229 231 235 / var(--tw-border-opacity, 1));\\n}\\n.border-gray-300 {\\n --tw-border-opacity: 1;\\n border-color: rgb(209 213 219 / var(--tw-border-opacity, 1));\\n}\\n.border-primary {\\n border-color: hsl(var(--primary));\\n}\\n.border-primary\\\\/50 {\\n border-color: hsl(var(--primary) / 0.5);\\n}\\n.border-transparent {\\n border-color: transparent;\\n}\\n.bg-\\\\[hsl\\\\(var\\\\(--ra-text\\\\)\\\\)\\\\] {\\n background-color: hsl(var(--ra-text));\\n}\\n.bg-accent {\\n background-color: hsl(var(--accent));\\n}\\n.bg-amber-50 {\\n --tw-bg-opacity: 1;\\n background-color: rgb(255 251 235 / var(--tw-bg-opacity, 1));\\n}\\n.bg-background {\\n background-color: hsl(var(--background));\\n}\\n.bg-background\\\\/80 {\\n background-color: hsl(var(--background) / 0.8);\\n}\\n.bg-black\\\\/50 {\\n background-color: rgb(0 0 0 / 0.5);\\n}\\n.bg-blue-100 {\\n --tw-bg-opacity: 1;\\n background-color: rgb(219 234 254 / var(--tw-bg-opacity, 1));\\n}\\n.bg-blue-50 {\\n --tw-bg-opacity: 1;\\n background-color: rgb(239 246 255 / var(--tw-bg-opacity, 1));\\n}\\n.bg-blue-500 {\\n --tw-bg-opacity: 1;\\n background-color: rgb(59 130 246 / var(--tw-bg-opacity, 1));\\n}\\n.bg-blue-600 {\\n --tw-bg-opacity: 1;\\n background-color: rgb(37 99 235 / var(--tw-bg-opacity, 1));\\n}\\n.bg-card {\\n background-color: hsl(var(--card));\\n}\\n.bg-destructive {\\n background-color: hsl(var(--destructive));\\n}\\n.bg-destructive\\\\/10 {\\n background-color: hsl(var(--destructive) / 0.1);\\n}\\n.bg-destructive\\\\/5 {\\n background-color: hsl(var(--destructive) / 0.05);\\n}\\n.bg-destructive\\\\/80 {\\n background-color: hsl(var(--destructive) / 0.8);\\n}\\n.bg-emerald-50 {\\n --tw-bg-opacity: 1;\\n background-color: rgb(236 253 245 / var(--tw-bg-opacity, 1));\\n}\\n.bg-foreground {\\n background-color: hsl(var(--foreground));\\n}\\n.bg-foreground\\\\/60 {\\n background-color: hsl(var(--foreground) / 0.6);\\n}\\n.bg-gray-100 {\\n --tw-bg-opacity: 1;\\n background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));\\n}\\n.bg-gray-300 {\\n --tw-bg-opacity: 1;\\n background-color: rgb(209 213 219 / var(--tw-bg-opacity, 1));\\n}\\n.bg-gray-50 {\\n --tw-bg-opacity: 1;\\n background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1));\\n}\\n.bg-muted {\\n background-color: hsl(var(--muted));\\n}\\n.bg-muted\\\\/20 {\\n background-color: hsl(var(--muted) / 0.2);\\n}\\n.bg-muted\\\\/30 {\\n background-color: hsl(var(--muted) / 0.3);\\n}\\n.bg-primary {\\n background-color: hsl(var(--primary));\\n}\\n.bg-primary\\\\/10 {\\n background-color: hsl(var(--primary) / 0.1);\\n}\\n.bg-primary\\\\/5 {\\n background-color: hsl(var(--primary) / 0.05);\\n}\\n.bg-red-50 {\\n --tw-bg-opacity: 1;\\n background-color: rgb(254 242 242 / var(--tw-bg-opacity, 1));\\n}\\n.bg-transparent {\\n background-color: transparent;\\n}\\n.bg-white {\\n --tw-bg-opacity: 1;\\n background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));\\n}\\n.fill-current {\\n fill: currentColor;\\n}\\n.object-contain {\\n -o-object-fit: contain;\\n object-fit: contain;\\n}\\n.object-cover {\\n -o-object-fit: cover;\\n object-fit: cover;\\n}\\n.p-0\\\\.5 {\\n padding: 0.125rem;\\n}\\n.p-1 {\\n padding: 0.25rem;\\n}\\n.p-1\\\\.5 {\\n padding: 0.375rem;\\n}\\n.p-2 {\\n padding: 0.5rem;\\n}\\n.p-2\\\\.5 {\\n padding: 0.625rem;\\n}\\n.p-3 {\\n padding: 0.75rem;\\n}\\n.p-4 {\\n padding: 1rem;\\n}\\n.p-6 {\\n padding: 1.5rem;\\n}\\n.px-1 {\\n padding-left: 0.25rem;\\n padding-right: 0.25rem;\\n}\\n.px-1\\\\.5 {\\n padding-left: 0.375rem;\\n padding-right: 0.375rem;\\n}\\n.px-2 {\\n padding-left: 0.5rem;\\n padding-right: 0.5rem;\\n}\\n.px-2\\\\.5 {\\n padding-left: 0.625rem;\\n padding-right: 0.625rem;\\n}\\n.px-3 {\\n padding-left: 0.75rem;\\n padding-right: 0.75rem;\\n}\\n.px-4 {\\n padding-left: 1rem;\\n padding-right: 1rem;\\n}\\n.px-5 {\\n padding-left: 1.25rem;\\n padding-right: 1.25rem;\\n}\\n.py-0 {\\n padding-top: 0px;\\n padding-bottom: 0px;\\n}\\n.py-0\\\\.5 {\\n padding-top: 0.125rem;\\n padding-bottom: 0.125rem;\\n}\\n.py-1 {\\n padding-top: 0.25rem;\\n padding-bottom: 0.25rem;\\n}\\n.py-1\\\\.5 {\\n padding-top: 0.375rem;\\n padding-bottom: 0.375rem;\\n}\\n.py-10 {\\n padding-top: 2.5rem;\\n padding-bottom: 2.5rem;\\n}\\n.py-12 {\\n padding-top: 3rem;\\n padding-bottom: 3rem;\\n}\\n.py-2 {\\n padding-top: 0.5rem;\\n padding-bottom: 0.5rem;\\n}\\n.py-2\\\\.5 {\\n padding-top: 0.625rem;\\n padding-bottom: 0.625rem;\\n}\\n.py-3 {\\n padding-top: 0.75rem;\\n padding-bottom: 0.75rem;\\n}\\n.py-4 {\\n padding-top: 1rem;\\n padding-bottom: 1rem;\\n}\\n.pb-1 {\\n padding-bottom: 0.25rem;\\n}\\n.pb-2 {\\n padding-bottom: 0.5rem;\\n}\\n.pb-3 {\\n padding-bottom: 0.75rem;\\n}\\n.pl-1 {\\n padding-left: 0.25rem;\\n}\\n.pl-7 {\\n padding-left: 1.75rem;\\n}\\n.pl-8 {\\n padding-left: 2rem;\\n}\\n.pl-9 {\\n padding-left: 2.25rem;\\n}\\n.pr-2 {\\n padding-right: 0.5rem;\\n}\\n.pr-3 {\\n padding-right: 0.75rem;\\n}\\n.pr-5 {\\n padding-right: 1.25rem;\\n}\\n.pr-9 {\\n padding-right: 2.25rem;\\n}\\n.pt-1 {\\n padding-top: 0.25rem;\\n}\\n.pt-2 {\\n padding-top: 0.5rem;\\n}\\n.pt-3 {\\n padding-top: 0.75rem;\\n}\\n.pt-4 {\\n padding-top: 1rem;\\n}\\n.text-left {\\n text-align: left;\\n}\\n.text-center {\\n text-align: center;\\n}\\n.font-mono {\\n font-family:\\n ui-monospace,\\n SFMono-Regular,\\n Menlo,\\n Monaco,\\n Consolas,\\n \\\"Liberation Mono\\\",\\n \\\"Courier New\\\",\\n monospace;\\n}\\n.text-2xl {\\n font-size: 1.5rem;\\n line-height: 2rem;\\n}\\n.text-\\\\[10px\\\\] {\\n font-size: 10px;\\n}\\n.text-\\\\[11px\\\\] {\\n font-size: 11px;\\n}\\n.text-\\\\[9px\\\\] {\\n font-size: 9px;\\n}\\n.text-base {\\n font-size: 1rem;\\n line-height: 1.5rem;\\n}\\n.text-sm {\\n font-size: 0.875rem;\\n line-height: 1.25rem;\\n}\\n.text-xs {\\n font-size: 0.75rem;\\n line-height: 1rem;\\n}\\n.font-bold {\\n font-weight: 700;\\n}\\n.font-medium {\\n font-weight: 500;\\n}\\n.font-semibold {\\n font-weight: 600;\\n}\\n.uppercase {\\n text-transform: uppercase;\\n}\\n.capitalize {\\n text-transform: capitalize;\\n}\\n.\\\\!italic {\\n font-style: italic !important;\\n}\\n.italic {\\n font-style: italic;\\n}\\n.tracking-wide {\\n letter-spacing: 0.025em;\\n}\\n.tracking-wider {\\n letter-spacing: 0.05em;\\n}\\n.text-\\\\[hsl\\\\(var\\\\(--ra-surface\\\\)\\\\)\\\\] {\\n color: hsl(var(--ra-surface));\\n}\\n.text-accent-foreground {\\n color: hsl(var(--accent-foreground));\\n}\\n.text-amber-600 {\\n --tw-text-opacity: 1;\\n color: rgb(217 119 6 / var(--tw-text-opacity, 1));\\n}\\n.text-amber-700 {\\n --tw-text-opacity: 1;\\n color: rgb(180 83 9 / var(--tw-text-opacity, 1));\\n}\\n.text-background {\\n color: hsl(var(--background));\\n}\\n.text-blue-700 {\\n --tw-text-opacity: 1;\\n color: rgb(29 78 216 / var(--tw-text-opacity, 1));\\n}\\n.text-destructive {\\n color: hsl(var(--destructive));\\n}\\n.text-destructive-foreground {\\n color: hsl(var(--destructive-foreground));\\n}\\n.text-emerald-700 {\\n --tw-text-opacity: 1;\\n color: rgb(4 120 87 / var(--tw-text-opacity, 1));\\n}\\n.text-foreground {\\n color: hsl(var(--foreground));\\n}\\n.text-gray-400 {\\n --tw-text-opacity: 1;\\n color: rgb(156 163 175 / var(--tw-text-opacity, 1));\\n}\\n.text-gray-500 {\\n --tw-text-opacity: 1;\\n color: rgb(107 114 128 / var(--tw-text-opacity, 1));\\n}\\n.text-gray-600 {\\n --tw-text-opacity: 1;\\n color: rgb(75 85 99 / var(--tw-text-opacity, 1));\\n}\\n.text-gray-700 {\\n --tw-text-opacity: 1;\\n color: rgb(55 65 81 / var(--tw-text-opacity, 1));\\n}\\n.text-gray-800 {\\n --tw-text-opacity: 1;\\n color: rgb(31 41 55 / var(--tw-text-opacity, 1));\\n}\\n.text-gray-900 {\\n --tw-text-opacity: 1;\\n color: rgb(17 24 39 / var(--tw-text-opacity, 1));\\n}\\n.text-muted-foreground {\\n color: hsl(var(--muted-foreground));\\n}\\n.text-muted-foreground\\\\/40 {\\n color: hsl(var(--muted-foreground) / 0.4);\\n}\\n.text-primary {\\n color: hsl(var(--primary));\\n}\\n.text-primary-foreground {\\n color: hsl(var(--primary-foreground));\\n}\\n.text-red-400 {\\n --tw-text-opacity: 1;\\n color: rgb(248 113 113 / var(--tw-text-opacity, 1));\\n}\\n.text-red-700 {\\n --tw-text-opacity: 1;\\n color: rgb(185 28 28 / var(--tw-text-opacity, 1));\\n}\\n.text-white {\\n --tw-text-opacity: 1;\\n color: rgb(255 255 255 / var(--tw-text-opacity, 1));\\n}\\n.underline {\\n text-decoration-line: underline;\\n}\\n.opacity-0 {\\n opacity: 0;\\n}\\n.opacity-100 {\\n opacity: 1;\\n}\\n.opacity-50 {\\n opacity: 0.5;\\n}\\n.opacity-60 {\\n opacity: 0.6;\\n}\\n.opacity-70 {\\n opacity: 0.7;\\n}\\n.opacity-80 {\\n opacity: 0.8;\\n}\\n.shadow {\\n --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);\\n --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);\\n box-shadow:\\n var(--tw-ring-offset-shadow, 0 0 #0000),\\n var(--tw-ring-shadow, 0 0 #0000),\\n var(--tw-shadow);\\n}\\n.shadow-2xl {\\n --tw-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25);\\n --tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);\\n box-shadow:\\n var(--tw-ring-offset-shadow, 0 0 #0000),\\n var(--tw-ring-shadow, 0 0 #0000),\\n var(--tw-shadow);\\n}\\n.shadow-lg {\\n --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);\\n --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);\\n box-shadow:\\n var(--tw-ring-offset-shadow, 0 0 #0000),\\n var(--tw-ring-shadow, 0 0 #0000),\\n var(--tw-shadow);\\n}\\n.shadow-sm {\\n --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);\\n --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);\\n box-shadow:\\n var(--tw-ring-offset-shadow, 0 0 #0000),\\n var(--tw-ring-shadow, 0 0 #0000),\\n var(--tw-shadow);\\n}\\n.shadow-xl {\\n --tw-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);\\n --tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);\\n box-shadow:\\n var(--tw-ring-offset-shadow, 0 0 #0000),\\n var(--tw-ring-shadow, 0 0 #0000),\\n var(--tw-shadow);\\n}\\n.outline {\\n outline-style: solid;\\n}\\n.ring-1 {\\n --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\\n --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);\\n box-shadow:\\n var(--tw-ring-offset-shadow),\\n var(--tw-ring-shadow),\\n var(--tw-shadow, 0 0 #0000);\\n}\\n.ring-2 {\\n --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\\n --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);\\n box-shadow:\\n var(--tw-ring-offset-shadow),\\n var(--tw-ring-shadow),\\n var(--tw-shadow, 0 0 #0000);\\n}\\n.ring-primary {\\n --tw-ring-color: hsl(var(--primary)) ;\\n}\\n.filter {\\n filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);\\n}\\n.backdrop-blur-sm {\\n --tw-backdrop-blur: blur(4px);\\n backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);\\n}\\n.transition {\\n transition-property:\\n color,\\n background-color,\\n border-color,\\n text-decoration-color,\\n fill,\\n stroke,\\n opacity,\\n box-shadow,\\n transform,\\n filter,\\n backdrop-filter;\\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\\n transition-duration: 150ms;\\n}\\n.transition-all {\\n transition-property: all;\\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\\n transition-duration: 150ms;\\n}\\n.transition-colors {\\n transition-property:\\n color,\\n background-color,\\n border-color,\\n text-decoration-color,\\n fill,\\n stroke;\\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\\n transition-duration: 150ms;\\n}\\n.transition-opacity {\\n transition-property: opacity;\\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\\n transition-duration: 150ms;\\n}\\n.transition-shadow {\\n transition-property: box-shadow;\\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\\n transition-duration: 150ms;\\n}\\n.transition-transform {\\n transition-property: transform;\\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\\n transition-duration: 150ms;\\n}\\n.duration-300 {\\n transition-duration: 300ms;\\n}\\n.placeholder\\\\:text-muted-foreground::-moz-placeholder {\\n color: hsl(var(--muted-foreground));\\n}\\n.placeholder\\\\:text-muted-foreground::placeholder {\\n color: hsl(var(--muted-foreground));\\n}\\n.hover\\\\:border-blue-400:hover {\\n --tw-border-opacity: 1;\\n border-color: rgb(96 165 250 / var(--tw-border-opacity, 1));\\n}\\n.hover\\\\:border-gray-300:hover {\\n --tw-border-opacity: 1;\\n border-color: rgb(209 213 219 / var(--tw-border-opacity, 1));\\n}\\n.hover\\\\:border-muted-foreground:hover {\\n border-color: hsl(var(--muted-foreground));\\n}\\n.hover\\\\:border-muted-foreground\\\\/40:hover {\\n border-color: hsl(var(--muted-foreground) / 0.4);\\n}\\n.hover\\\\:border-ring:hover {\\n border-color: hsl(var(--ring));\\n}\\n.hover\\\\:bg-\\\\[hsl\\\\(var\\\\(--ra-muted\\\\)\\\\)\\\\]:hover {\\n background-color: hsl(var(--ra-muted));\\n}\\n.hover\\\\:bg-\\\\[hsl\\\\(var\\\\(--ra-muted\\\\)\\\\/0\\\\.5\\\\)\\\\]:hover {\\n background-color: hsl(var(--ra-muted)/0.5);\\n}\\n.hover\\\\:bg-accent:hover {\\n background-color: hsl(var(--accent));\\n}\\n.hover\\\\:bg-accent\\\\/30:hover {\\n background-color: hsl(var(--accent) / 0.3);\\n}\\n.hover\\\\:bg-accent\\\\/50:hover {\\n background-color: hsl(var(--accent) / 0.5);\\n}\\n.hover\\\\:bg-blue-100:hover {\\n --tw-bg-opacity: 1;\\n background-color: rgb(219 234 254 / var(--tw-bg-opacity, 1));\\n}\\n.hover\\\\:bg-blue-50\\\\/50:hover {\\n background-color: rgb(239 246 255 / 0.5);\\n}\\n.hover\\\\:bg-blue-700:hover {\\n --tw-bg-opacity: 1;\\n background-color: rgb(29 78 216 / var(--tw-bg-opacity, 1));\\n}\\n.hover\\\\:bg-destructive:hover {\\n background-color: hsl(var(--destructive));\\n}\\n.hover\\\\:bg-destructive\\\\/10:hover {\\n background-color: hsl(var(--destructive) / 0.1);\\n}\\n.hover\\\\:bg-gray-100:hover {\\n --tw-bg-opacity: 1;\\n background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));\\n}\\n.hover\\\\:bg-gray-200:hover {\\n --tw-bg-opacity: 1;\\n background-color: rgb(229 231 235 / var(--tw-bg-opacity, 1));\\n}\\n.hover\\\\:bg-gray-50:hover {\\n --tw-bg-opacity: 1;\\n background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1));\\n}\\n.hover\\\\:bg-muted:hover {\\n background-color: hsl(var(--muted));\\n}\\n.hover\\\\:bg-primary\\\\/90:hover {\\n background-color: hsl(var(--primary) / 0.9);\\n}\\n.hover\\\\:bg-red-100:hover {\\n --tw-bg-opacity: 1;\\n background-color: rgb(254 226 226 / var(--tw-bg-opacity, 1));\\n}\\n.hover\\\\:bg-red-50:hover {\\n --tw-bg-opacity: 1;\\n background-color: rgb(254 242 242 / var(--tw-bg-opacity, 1));\\n}\\n.hover\\\\:text-accent-foreground:hover {\\n color: hsl(var(--accent-foreground));\\n}\\n.hover\\\\:text-blue-500:hover {\\n --tw-text-opacity: 1;\\n color: rgb(59 130 246 / var(--tw-text-opacity, 1));\\n}\\n.hover\\\\:text-blue-600:hover {\\n --tw-text-opacity: 1;\\n color: rgb(37 99 235 / var(--tw-text-opacity, 1));\\n}\\n.hover\\\\:text-destructive:hover {\\n color: hsl(var(--destructive));\\n}\\n.hover\\\\:text-destructive\\\\/80:hover {\\n color: hsl(var(--destructive) / 0.8);\\n}\\n.hover\\\\:text-foreground:hover {\\n color: hsl(var(--foreground));\\n}\\n.hover\\\\:text-red-600:hover {\\n --tw-text-opacity: 1;\\n color: rgb(220 38 38 / var(--tw-text-opacity, 1));\\n}\\n.hover\\\\:underline:hover {\\n text-decoration-line: underline;\\n}\\n.hover\\\\:opacity-100:hover {\\n opacity: 1;\\n}\\n.hover\\\\:shadow-md:hover {\\n --tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);\\n --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);\\n box-shadow:\\n var(--tw-ring-offset-shadow, 0 0 #0000),\\n var(--tw-ring-shadow, 0 0 #0000),\\n var(--tw-shadow);\\n}\\n.hover\\\\:shadow-sm:hover {\\n --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);\\n --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);\\n box-shadow:\\n var(--tw-ring-offset-shadow, 0 0 #0000),\\n var(--tw-ring-shadow, 0 0 #0000),\\n var(--tw-shadow);\\n}\\n.focus\\\\:outline-none:focus {\\n outline: 2px solid transparent;\\n outline-offset: 2px;\\n}\\n.focus\\\\:ring-1:focus {\\n --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\\n --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);\\n box-shadow:\\n var(--tw-ring-offset-shadow),\\n var(--tw-ring-shadow),\\n var(--tw-shadow, 0 0 #0000);\\n}\\n.focus\\\\:ring-2:focus {\\n --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\\n --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);\\n box-shadow:\\n var(--tw-ring-offset-shadow),\\n var(--tw-ring-shadow),\\n var(--tw-shadow, 0 0 #0000);\\n}\\n.focus\\\\:ring-blue-500:focus {\\n --tw-ring-opacity: 1;\\n --tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1)) ;\\n}\\n.focus\\\\:ring-ring:focus {\\n --tw-ring-color: hsl(var(--ring)) ;\\n}\\n.disabled\\\\:cursor-not-allowed:disabled {\\n cursor: not-allowed;\\n}\\n.disabled\\\\:opacity-30:disabled {\\n opacity: 0.3;\\n}\\n.disabled\\\\:opacity-40:disabled {\\n opacity: 0.4;\\n}\\n.disabled\\\\:opacity-50:disabled {\\n opacity: 0.5;\\n}\\n.disabled\\\\:opacity-60:disabled {\\n opacity: 0.6;\\n}\\n.disabled\\\\:opacity-70:disabled {\\n opacity: 0.7;\\n}\\n.group:hover .group-hover\\\\:opacity-100 {\\n opacity: 1;\\n}\\n@media (min-width: 640px) {\\n .sm\\\\:grid-cols-10 {\\n grid-template-columns: repeat(10, minmax(0, 1fr));\\n }\\n .sm\\\\:grid-cols-3 {\\n grid-template-columns: repeat(3, minmax(0, 1fr));\\n }\\n .sm\\\\:grid-cols-4 {\\n grid-template-columns: repeat(4, minmax(0, 1fr));\\n }\\n}\\n@media (min-width: 768px) {\\n .md\\\\:grid-cols-12 {\\n grid-template-columns: repeat(12, minmax(0, 1fr));\\n }\\n .md\\\\:grid-cols-4 {\\n grid-template-columns: repeat(4, minmax(0, 1fr));\\n }\\n .md\\\\:grid-cols-5 {\\n grid-template-columns: repeat(5, minmax(0, 1fr));\\n }\\n}\\n@media (min-width: 1024px) {\\n .lg\\\\:grid-cols-6 {\\n grid-template-columns: repeat(6, minmax(0, 1fr));\\n }\\n}\\n@media (prefers-color-scheme: dark) {\\n .dark\\\\:border-gray-600 {\\n --tw-border-opacity: 1;\\n border-color: rgb(75 85 99 / var(--tw-border-opacity, 1));\\n }\\n .dark\\\\:border-gray-700 {\\n --tw-border-opacity: 1;\\n border-color: rgb(55 65 81 / var(--tw-border-opacity, 1));\\n }\\n .dark\\\\:border-gray-800 {\\n --tw-border-opacity: 1;\\n border-color: rgb(31 41 55 / var(--tw-border-opacity, 1));\\n }\\n .dark\\\\:bg-amber-900\\\\/30 {\\n background-color: rgb(120 53 15 / 0.3);\\n }\\n .dark\\\\:bg-blue-900\\\\/30 {\\n background-color: rgb(30 58 138 / 0.3);\\n }\\n .dark\\\\:bg-blue-900\\\\/40 {\\n background-color: rgb(30 58 138 / 0.4);\\n }\\n .dark\\\\:bg-emerald-900\\\\/30 {\\n background-color: rgb(6 78 59 / 0.3);\\n }\\n .dark\\\\:bg-gray-600 {\\n --tw-bg-opacity: 1;\\n background-color: rgb(75 85 99 / var(--tw-bg-opacity, 1));\\n }\\n .dark\\\\:bg-gray-700 {\\n --tw-bg-opacity: 1;\\n background-color: rgb(55 65 81 / var(--tw-bg-opacity, 1));\\n }\\n .dark\\\\:bg-gray-800 {\\n --tw-bg-opacity: 1;\\n background-color: rgb(31 41 55 / var(--tw-bg-opacity, 1));\\n }\\n .dark\\\\:bg-gray-800\\\\/50 {\\n background-color: rgb(31 41 55 / 0.5);\\n }\\n .dark\\\\:bg-gray-900 {\\n --tw-bg-opacity: 1;\\n background-color: rgb(17 24 39 / var(--tw-bg-opacity, 1));\\n }\\n .dark\\\\:bg-red-900\\\\/30 {\\n background-color: rgb(127 29 29 / 0.3);\\n }\\n .dark\\\\:text-amber-300 {\\n --tw-text-opacity: 1;\\n color: rgb(252 211 77 / var(--tw-text-opacity, 1));\\n }\\n .dark\\\\:text-amber-400 {\\n --tw-text-opacity: 1;\\n color: rgb(251 191 36 / var(--tw-text-opacity, 1));\\n }\\n .dark\\\\:text-blue-300 {\\n --tw-text-opacity: 1;\\n color: rgb(147 197 253 / var(--tw-text-opacity, 1));\\n }\\n .dark\\\\:text-emerald-300 {\\n --tw-text-opacity: 1;\\n color: rgb(110 231 183 / var(--tw-text-opacity, 1));\\n }\\n .dark\\\\:text-gray-100 {\\n --tw-text-opacity: 1;\\n color: rgb(243 244 246 / var(--tw-text-opacity, 1));\\n }\\n .dark\\\\:text-gray-200 {\\n --tw-text-opacity: 1;\\n color: rgb(229 231 235 / var(--tw-text-opacity, 1));\\n }\\n .dark\\\\:text-gray-300 {\\n --tw-text-opacity: 1;\\n color: rgb(209 213 219 / var(--tw-text-opacity, 1));\\n }\\n .dark\\\\:text-gray-400 {\\n --tw-text-opacity: 1;\\n color: rgb(156 163 175 / var(--tw-text-opacity, 1));\\n }\\n .dark\\\\:text-gray-500 {\\n --tw-text-opacity: 1;\\n color: rgb(107 114 128 / var(--tw-text-opacity, 1));\\n }\\n .dark\\\\:text-red-300 {\\n --tw-text-opacity: 1;\\n color: rgb(252 165 165 / var(--tw-text-opacity, 1));\\n }\\n .dark\\\\:hover\\\\:border-blue-500:hover {\\n --tw-border-opacity: 1;\\n border-color: rgb(59 130 246 / var(--tw-border-opacity, 1));\\n }\\n .dark\\\\:hover\\\\:border-gray-600:hover {\\n --tw-border-opacity: 1;\\n border-color: rgb(75 85 99 / var(--tw-border-opacity, 1));\\n }\\n .dark\\\\:hover\\\\:bg-blue-900\\\\/50:hover {\\n background-color: rgb(30 58 138 / 0.5);\\n }\\n .dark\\\\:hover\\\\:bg-blue-950\\\\/20:hover {\\n background-color: rgb(23 37 84 / 0.2);\\n }\\n .dark\\\\:hover\\\\:bg-gray-700:hover {\\n --tw-bg-opacity: 1;\\n background-color: rgb(55 65 81 / var(--tw-bg-opacity, 1));\\n }\\n .dark\\\\:hover\\\\:bg-gray-800:hover {\\n --tw-bg-opacity: 1;\\n background-color: rgb(31 41 55 / var(--tw-bg-opacity, 1));\\n }\\n .dark\\\\:hover\\\\:bg-gray-800\\\\/50:hover {\\n background-color: rgb(31 41 55 / 0.5);\\n }\\n .dark\\\\:hover\\\\:bg-red-900\\\\/20:hover {\\n background-color: rgb(127 29 29 / 0.2);\\n }\\n .dark\\\\:hover\\\\:bg-red-900\\\\/30:hover {\\n background-color: rgb(127 29 29 / 0.3);\\n }\\n .dark\\\\:hover\\\\:text-blue-400:hover {\\n --tw-text-opacity: 1;\\n color: rgb(96 165 250 / var(--tw-text-opacity, 1));\\n }\\n}\\n\")"]}
@@ -0,0 +1,3 @@
1
+
2
+ //# sourceMappingURL=chunk-S27GIYV7.js.map
3
+ //# sourceMappingURL=chunk-S27GIYV7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-S27GIYV7.js"}
@@ -1,5 +1,5 @@
1
1
  export { AssetPicker, useAppRegistry, useAssets } from '../../chunk-UDYVH7QF.js';
2
- import '../../chunk-3BLWNYM4.js';
2
+ import '../../chunk-LLSIDR6U.js';
3
3
  import '../../chunk-L7FQ52F5.js';
4
4
  //# sourceMappingURL=index.js.map
5
5
  //# sourceMappingURL=index.js.map
@@ -1,5 +1,5 @@
1
1
  export { ConditionsEditor } from '../../chunk-7UBXTFZQ.js';
2
- import '../../chunk-3BLWNYM4.js';
2
+ import '../../chunk-LLSIDR6U.js';
3
3
  import '../../chunk-4LHF5JB7.js';
4
4
  import '../../chunk-L7FQ52F5.js';
5
5
  //# sourceMappingURL=index.js.map
@@ -1,4 +1,5 @@
1
- export { FacetRuleEditor } from '../../chunk-MZ6JSCXO.js';
1
+ import '../../chunk-S27GIYV7.js';
2
+ export { FacetRuleEditor } from '../../chunk-JMCV6FOW.js';
2
3
  import '../../chunk-4LHF5JB7.js';
3
4
  import '../../chunk-L7FQ52F5.js';
4
5
  //# sourceMappingURL=index.js.map
@@ -1,5 +1,5 @@
1
1
  export { CATEGORY_FALLBACKS, CATEGORY_LABELS, FontPicker, GOOGLE_FONTS_CATALOG, getGoogleFontUrl } from '../../chunk-OTJV62XV.js';
2
- import '../../chunk-3BLWNYM4.js';
2
+ import '../../chunk-LLSIDR6U.js';
3
3
  import '../../chunk-L7FQ52F5.js';
4
4
  //# sourceMappingURL=index.js.map
5
5
  //# sourceMappingURL=index.js.map
@@ -1,5 +1,5 @@
1
1
  export { IconPicker, parseFaClass, toFaClass } from '../../chunk-JQPS5XPJ.js';
2
- import '../../chunk-3BLWNYM4.js';
2
+ import '../../chunk-LLSIDR6U.js';
3
3
  import '../../chunk-L7FQ52F5.js';
4
4
  //# sourceMappingURL=index.js.map
5
5
  //# sourceMappingURL=index.js.map
@@ -1,9 +1,9 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode, ComponentType } from 'react';
3
- import * as _proveanything_smartlinks_dist_types_appObjects from '@proveanything/smartlinks/dist/types/appObjects';
4
3
  import { FacetRule, MatchedAt, RecordScope, AppRecord, RecordTarget, MatchResult, MatchEntry } from '@proveanything/smartlinks/dist/types/appObjects';
5
4
  import { LucideIcon } from 'lucide-react';
6
5
  import * as _tanstack_query_core from '@tanstack/query-core';
6
+ import * as _proveanything_smartlinks from '@proveanything/smartlinks';
7
7
  import { InfiniteData } from '@tanstack/react-query';
8
8
 
9
9
  /**
@@ -104,6 +104,13 @@ interface ResolvedRecord<TData = unknown> {
104
104
  matchedAt?: MatchedAt;
105
105
  /** The rule that fired. Present only when `matchedAt === 'rule'`. */
106
106
  matchedRule?: FacetRule;
107
+ /**
108
+ * The `facetRule` attached to the winning record itself, if any. Distinct
109
+ * from `matchedRule` (which is set when the resolver classified the match
110
+ * as rule-based). For rule-targeted records (`source: 'self'` on a
111
+ * `rule:{id}` ref) this is the rule the editor authors against.
112
+ */
113
+ facetRule?: FacetRule | null;
107
114
  }
108
115
 
109
116
  interface EditorContext<TData = unknown> {
@@ -120,10 +127,29 @@ interface EditorContext<TData = unknown> {
120
127
  remove: () => Promise<void>;
121
128
  /** True when a saved-own record exists that can be removed. */
122
129
  canRemove: boolean;
130
+ /**
131
+ * True when the editor's current state is structurally valid for save.
132
+ * Defaults to `true`; the shell flips this to `false` for rule-targeted
133
+ * scopes whose `facetRule` is empty / has clauses with no selected values.
134
+ * Save buttons should disable on `!canSave` to avoid server 500s on
135
+ * empty-rule upserts.
136
+ */
137
+ canSave?: boolean;
138
+ /** Human-readable reason `canSave` is false (used as a tooltip). */
139
+ cannotSaveReason?: string;
123
140
  /** True while an optimistic save is in flight (request not yet acknowledged). */
124
141
  isSaving?: boolean;
125
142
  /** Last save error, if any. Cleared when the next save attempt starts. */
126
143
  saveError?: unknown | null;
144
+ /**
145
+ * Current facet rule attached to this record, if any. Always defined for
146
+ * rule-targeted scopes (`scope.kind === 'rule'`) — starts as `{ all: [] }`
147
+ * for a freshly created rule and is updated via `onFacetRuleChange`.
148
+ * Mutually exclusive with the structured `scope` on save.
149
+ */
150
+ facetRule?: FacetRule | null;
151
+ /** Update the in-progress facet rule. Marks the editor dirty. */
152
+ onFacetRuleChange?: (next: FacetRule | null) => void;
127
153
  }
128
154
 
129
155
  interface CsvSchemaColumn<TData> {
@@ -1044,6 +1070,13 @@ interface Props$a<T> {
1044
1070
  i18n: RecordsAdminI18n;
1045
1071
  children: ReactNode;
1046
1072
  preview?: ReactNode;
1073
+ /**
1074
+ * Optional Targeting section rendered above `children`. The shell mounts
1075
+ * this for rule-targeted records (`scope.kind === 'rule'`) so admins can
1076
+ * author the facet rule alongside the record's data. Plain record types
1077
+ * leave it `undefined` and nothing renders.
1078
+ */
1079
+ targeting?: ReactNode;
1047
1080
  bulkActions?: React.ComponentProps<typeof BulkActionsMenu>;
1048
1081
  /** Extra slot rendered in the footer between the danger actions and Save. */
1049
1082
  footerExtra?: ReactNode;
@@ -1082,7 +1115,7 @@ interface Props$a<T> {
1082
1115
  /** Host-provided icons rendered before save / discard / delete labels. */
1083
1116
  actionIcons?: Partial<Record<RecordsAdminActionKey, RecordsAdminActionIcon>>;
1084
1117
  }
1085
- declare function RecordEditor<T>({ ctx, i18n, children, preview, bulkActions, footerExtra, onBeforeDelete, headerLabel, headerSubtitle, headerMeta, clipboard, actionLabels, actionIcons, }: Props$a<T>): react_jsx_runtime.JSX.Element;
1118
+ declare function RecordEditor<T>({ ctx, i18n, children, preview, targeting, bulkActions, footerExtra, onBeforeDelete, headerLabel, headerSubtitle, headerMeta, clipboard, actionLabels, actionIcons, }: Props$a<T>): react_jsx_runtime.JSX.Element;
1086
1119
 
1087
1120
  interface InheritanceCtx {
1088
1121
  parentValue?: Record<string, unknown> | null;
@@ -1269,6 +1302,12 @@ interface RecordWrite<T = unknown> {
1269
1302
  expiresAt?: string | null;
1270
1303
  customId?: string;
1271
1304
  sourceSystem?: string;
1305
+ /**
1306
+ * Optional facet rule. When set, the record is targeted via this rule and
1307
+ * `scope` should be empty (the SDK enforces mutual exclusion). Used by
1308
+ * the rule editor / Targeting section.
1309
+ */
1310
+ facetRule?: FacetRule | null;
1272
1311
  }
1273
1312
  declare const listRecords: (ctx: RecordsCtx, params?: {
1274
1313
  ref?: string;
@@ -1391,6 +1430,13 @@ interface UseRecordEditorArgs<T> {
1391
1430
  * (used by the shell when `dirtyStrategy === 'keep'`).
1392
1431
  */
1393
1432
  reseed?: 'always' | 'preserve-dirty';
1433
+ /**
1434
+ * Initial facet rule for the record. Required for rule-targeted scopes —
1435
+ * pass `null` (or `{ all: [] }`) for a freshly minted `rule:{id}` ref so
1436
+ * the Targeting section has somewhere to author into. Ignored for pinned
1437
+ * scopes unless the host explicitly opts a record into rule targeting.
1438
+ */
1439
+ initialFacetRule?: FacetRule | null;
1394
1440
  }
1395
1441
  declare function useRecordEditor<T>(args: UseRecordEditorArgs<T>): EditorContext<T>;
1396
1442
 
@@ -1406,6 +1452,13 @@ interface UseResolvedRecordArgs {
1406
1452
  facetId?: string;
1407
1453
  facetValue?: string;
1408
1454
  proofId?: string;
1455
+ /**
1456
+ * Optional raw ref. Required for rule-targeted records (`rule:{id}`) so the
1457
+ * resolver can look them up by ref instead of running an inheritance chain.
1458
+ * For pinned scopes this can be left empty — the structured scope ids are
1459
+ * sufficient.
1460
+ */
1461
+ ref?: string;
1409
1462
  supportedScopes?: ScopeKind[];
1410
1463
  enabled?: boolean;
1411
1464
  withParent?: boolean;
@@ -1417,8 +1470,9 @@ declare function useResolvedRecord<T = unknown>(args: UseResolvedRecordArgs): {
1417
1470
  source: RecordSource;
1418
1471
  sourceRef?: string;
1419
1472
  parentValue?: T | null | undefined;
1420
- matchedAt?: _proveanything_smartlinks_dist_types_appObjects.MatchedAt;
1421
- matchedRule?: _proveanything_smartlinks_dist_types_appObjects.FacetRule;
1473
+ matchedAt?: _proveanything_smartlinks.MatchedAt;
1474
+ matchedRule?: _proveanything_smartlinks.FacetRule;
1475
+ facetRule?: _proveanything_smartlinks.FacetRule | null;
1422
1476
  };
1423
1477
 
1424
1478
  interface UseCollectionItemsArgs {