@stonecrop/stonecrop 0.10.16 → 0.11.1

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.
Files changed (71) hide show
  1. package/README.md +72 -29
  2. package/dist/composables/lazy-link.js +125 -0
  3. package/dist/composables/stonecrop.js +123 -68
  4. package/dist/doctype.js +10 -2
  5. package/dist/field-triggers.js +15 -3
  6. package/dist/index.js +4 -3
  7. package/dist/registry.js +261 -101
  8. package/dist/schema-validator.js +105 -1
  9. package/dist/src/composables/lazy-link.d.ts +25 -0
  10. package/dist/src/composables/lazy-link.d.ts.map +1 -0
  11. package/dist/src/composables/operation-log.d.ts +5 -5
  12. package/dist/src/composables/operation-log.d.ts.map +1 -1
  13. package/dist/src/composables/stonecrop.d.ts +11 -1
  14. package/dist/src/composables/stonecrop.d.ts.map +1 -1
  15. package/dist/src/doctype.d.ts +9 -1
  16. package/dist/src/doctype.d.ts.map +1 -1
  17. package/dist/src/field-triggers.d.ts +6 -0
  18. package/dist/src/field-triggers.d.ts.map +1 -1
  19. package/dist/src/index.d.ts +3 -2
  20. package/dist/src/index.d.ts.map +1 -1
  21. package/dist/src/registry.d.ts +102 -23
  22. package/dist/src/registry.d.ts.map +1 -1
  23. package/dist/src/schema-validator.d.ts +8 -1
  24. package/dist/src/schema-validator.d.ts.map +1 -1
  25. package/dist/src/stonecrop.d.ts +73 -28
  26. package/dist/src/stonecrop.d.ts.map +1 -1
  27. package/dist/src/stores/hst.d.ts +5 -75
  28. package/dist/src/stores/hst.d.ts.map +1 -1
  29. package/dist/src/stores/operation-log.d.ts +14 -14
  30. package/dist/src/stores/operation-log.d.ts.map +1 -1
  31. package/dist/src/types/composable.d.ts +50 -12
  32. package/dist/src/types/composable.d.ts.map +1 -1
  33. package/dist/src/types/doctype.d.ts +6 -7
  34. package/dist/src/types/doctype.d.ts.map +1 -1
  35. package/dist/src/types/field-triggers.d.ts +1 -1
  36. package/dist/src/types/field-triggers.d.ts.map +1 -1
  37. package/dist/src/types/hst.d.ts +70 -0
  38. package/dist/src/types/hst.d.ts.map +1 -0
  39. package/dist/src/types/index.d.ts +1 -0
  40. package/dist/src/types/index.d.ts.map +1 -1
  41. package/dist/src/types/operation-log.d.ts +4 -4
  42. package/dist/src/types/operation-log.d.ts.map +1 -1
  43. package/dist/src/types/schema-validator.d.ts +2 -0
  44. package/dist/src/types/schema-validator.d.ts.map +1 -1
  45. package/dist/stonecrop.d.ts +317 -99
  46. package/dist/stonecrop.js +2191 -1897
  47. package/dist/stonecrop.js.map +1 -1
  48. package/dist/stores/hst.js +27 -25
  49. package/dist/stores/operation-log.js +59 -47
  50. package/dist/types/hst.js +0 -0
  51. package/dist/types/index.js +1 -0
  52. package/package.json +5 -5
  53. package/src/composables/lazy-link.ts +146 -0
  54. package/src/composables/operation-log.ts +1 -1
  55. package/src/composables/stonecrop.ts +142 -73
  56. package/src/doctype.ts +13 -4
  57. package/src/field-triggers.ts +18 -4
  58. package/src/index.ts +4 -2
  59. package/src/registry.ts +289 -111
  60. package/src/schema-validator.ts +120 -1
  61. package/src/stonecrop.ts +230 -106
  62. package/src/stores/hst.ts +29 -104
  63. package/src/stores/operation-log.ts +64 -50
  64. package/src/types/composable.ts +55 -12
  65. package/src/types/doctype.ts +6 -7
  66. package/src/types/field-triggers.ts +1 -1
  67. package/src/types/hst.ts +77 -0
  68. package/src/types/index.ts +1 -0
  69. package/src/types/operation-log.ts +4 -4
  70. package/src/types/schema-validator.ts +2 -0
  71. package/dist/stonecrop.css +0 -1
@@ -1,16 +1,17 @@
1
1
  import { defineStore } from 'pinia'
2
2
  import { ref, computed, watch } from 'vue'
3
3
  import { useLocalStorage } from '@vueuse/core'
4
+
5
+ import type { HSTNode } from './hst'
4
6
  import type {
7
+ CrossTabMessage,
5
8
  HSTOperation,
6
9
  HSTOperationInput,
7
10
  OperationLogConfig,
8
- UndoRedoState,
9
11
  OperationLogSnapshot,
10
- CrossTabMessage,
11
12
  OperationSource,
13
+ UndoRedoState,
12
14
  } from '../types/operation-log'
13
- import type { HSTNode } from './hst'
14
15
 
15
16
  /**
16
17
  * Generate a UUID using crypto API or fallback
@@ -107,8 +108,7 @@ export const useOperationLogStore = defineStore('hst-operation-log', () => {
107
108
  const currentIndex = ref(-1) // Points to the last applied operation
108
109
  const clientId = ref(generateId())
109
110
  const batchMode = ref(false)
110
- const currentBatch = ref<HSTOperation[]>([])
111
- const currentBatchId = ref<string | null>(null)
111
+ const batchStack = ref<{ id: string; operations: HSTOperation[] }[]>([])
112
112
 
113
113
  // Computed
114
114
  const canUndo = computed(() => {
@@ -183,9 +183,9 @@ export const useOperationLogStore = defineStore('hst-operation-log', () => {
183
183
  return fullOperation.id
184
184
  }
185
185
 
186
- // If in batch mode, collect operations
187
- if (batchMode.value) {
188
- currentBatch.value.push(fullOperation)
186
+ // If in batch mode, collect operations in current batch
187
+ if (batchMode.value && batchStack.value.length > 0) {
188
+ batchStack.value[batchStack.value.length - 1].operations.push(fullOperation)
189
189
  return fullOperation.id
190
190
  }
191
191
 
@@ -218,25 +218,35 @@ export const useOperationLogStore = defineStore('hst-operation-log', () => {
218
218
  */
219
219
  function startBatch() {
220
220
  batchMode.value = true
221
- currentBatch.value = []
222
- currentBatchId.value = generateId()
221
+ batchStack.value.push({
222
+ id: generateId(),
223
+ operations: [],
224
+ })
223
225
  }
224
226
 
225
227
  /**
226
228
  * Commit batch - create a single batch operation
227
229
  */
228
230
  function commitBatch(description?: string): string | null {
229
- if (!batchMode.value || currentBatch.value.length === 0) {
230
- batchMode.value = false
231
- currentBatch.value = []
232
- currentBatchId.value = null
231
+ if (!batchMode.value || batchStack.value.length === 0) {
233
232
  return null
234
233
  }
235
234
 
236
- const batchId = currentBatchId.value!
237
- const allReversible = currentBatch.value.every(op => op.reversible)
235
+ const currentBatchData = batchStack.value.pop()!
236
+ const batchOperations = currentBatchData.operations
238
237
 
239
- // Create parent batch operation
238
+ if (batchOperations.length === 0) {
239
+ // Empty batch - just pop and continue if there are outer batches
240
+ if (batchStack.value.length === 0) {
241
+ batchMode.value = false
242
+ }
243
+ return null
244
+ }
245
+
246
+ const batchId = currentBatchData.id
247
+ const allReversible = batchOperations.every(op => op.reversible)
248
+
249
+ // Create ancestor batch operation
240
250
  const batchOperation: HSTOperation = {
241
251
  id: batchId,
242
252
  type: 'batch',
@@ -244,45 +254,49 @@ export const useOperationLogStore = defineStore('hst-operation-log', () => {
244
254
  fieldname: '',
245
255
  beforeValue: null,
246
256
  afterValue: null,
247
- doctype: currentBatch.value[0]?.doctype || '',
257
+ doctype: batchOperations[0]?.doctype || '',
248
258
  timestamp: new Date(),
249
259
  source: 'user',
250
260
  reversible: allReversible,
251
261
  irreversibleReason: allReversible ? undefined : 'Contains irreversible operations',
252
- childOperationIds: currentBatch.value.map(op => op.id),
262
+ descendantOperationIds: batchOperations.map(op => op.id),
253
263
  metadata: { description },
254
264
  }
255
265
 
256
- // Add parent operation ID to all children
257
- currentBatch.value.forEach(op => {
258
- op.parentOperationId = batchId
266
+ // Add ancestor operation ID to all descendants
267
+ batchOperations.forEach(op => {
268
+ op.ancestorOperationId = batchId
259
269
  })
260
270
 
261
- // Add all operations to the log
262
- operations.value.push(...currentBatch.value, batchOperation)
263
- currentIndex.value = operations.value.length - 1
271
+ // If we're inside a ancestor batch, add this batch as a descendant of the ancestor
272
+ if (batchStack.value.length > 0) {
273
+ // Nested batch - add the batch operation to the ancestor batch
274
+ batchStack.value[batchStack.value.length - 1].operations.push(batchOperation)
275
+ } else {
276
+ // Top-level batch - add to the operations log
277
+ operations.value.push(...batchOperations, batchOperation)
278
+ currentIndex.value = operations.value.length - 1
279
+ }
264
280
 
265
281
  // Broadcast batch
266
282
  if (config.value.enableCrossTabSync) {
267
- broadcastBatch(currentBatch.value, batchOperation)
283
+ broadcastBatch(batchOperations, batchOperation)
268
284
  }
269
285
 
270
- // Reset batch state
271
- const result = batchId
272
- batchMode.value = false
273
- currentBatch.value = []
274
- currentBatchId.value = null
286
+ // If no more batches on stack, exit batch mode
287
+ if (batchStack.value.length === 0) {
288
+ batchMode.value = false
289
+ }
275
290
 
276
- return result
291
+ return batchId
277
292
  }
278
293
 
279
294
  /**
280
295
  * Cancel batch mode without committing
281
296
  */
282
297
  function cancelBatch() {
298
+ batchStack.value = []
283
299
  batchMode.value = false
284
- currentBatch.value = []
285
- currentBatchId.value = null
286
300
  }
287
301
 
288
302
  /**
@@ -304,13 +318,13 @@ export const useOperationLogStore = defineStore('hst-operation-log', () => {
304
318
 
305
319
  try {
306
320
  // Handle batch operations
307
- if (operation.type === 'batch' && operation.childOperationIds) {
308
- // Undo all child operations in reverse order
309
- for (let i = operation.childOperationIds.length - 1; i >= 0; i--) {
310
- const childId = operation.childOperationIds[i]
311
- const childOp = operations.value.find(op => op.id === childId)
312
- if (childOp) {
313
- revertOperation(childOp, store)
321
+ if (operation.type === 'batch' && operation.descendantOperationIds) {
322
+ // Undo all descendant operations in reverse order
323
+ for (let i = operation.descendantOperationIds.length - 1; i >= 0; i--) {
324
+ const descendantId = operation.descendantOperationIds[i]
325
+ const descendantOp = operations.value.find(op => op.id === descendantId)
326
+ if (descendantOp) {
327
+ revertOperation(descendantOp, store)
314
328
  }
315
329
  }
316
330
  } else {
@@ -346,12 +360,12 @@ export const useOperationLogStore = defineStore('hst-operation-log', () => {
346
360
 
347
361
  try {
348
362
  // Handle batch operations
349
- if (operation.type === 'batch' && operation.childOperationIds) {
350
- // Redo all child operations in order
351
- for (const childId of operation.childOperationIds) {
352
- const childOp = operations.value.find(op => op.id === childId)
353
- if (childOp) {
354
- applyOperation(childOp, store)
363
+ if (operation.type === 'batch' && operation.descendantOperationIds) {
364
+ // Redo all descendant operations in order
365
+ for (const descendantId of operation.descendantOperationIds) {
366
+ const descendantOp = operations.value.find(op => op.id === descendantId)
367
+ if (descendantOp) {
368
+ applyOperation(descendantOp, store)
355
369
  }
356
370
  }
357
371
  } else {
@@ -525,12 +539,12 @@ export const useOperationLogStore = defineStore('hst-operation-log', () => {
525
539
  broadcastChannel.postMessage(serializeForBroadcast(message))
526
540
  }
527
541
 
528
- function broadcastBatch(childOps: HSTOperation[], batchOp: HSTOperation) {
542
+ function broadcastBatch(descendantOps: HSTOperation[], batchOp: HSTOperation) {
529
543
  if (!broadcastChannel) return
530
544
 
531
545
  const message: CrossTabMessage = {
532
546
  type: 'operation',
533
- operations: [...childOps, batchOp],
547
+ operations: [...descendantOps, batchOp],
534
548
  clientId: clientId.value,
535
549
  timestamp: new Date(),
536
550
  }
@@ -567,7 +581,7 @@ export const useOperationLogStore = defineStore('hst-operation-log', () => {
567
581
  currentIndex: number
568
582
  }
569
583
 
570
- const persistedData = useLocalStorage<PersistedData | null>('stonecrop-ops-operations', null, {
584
+ const persistedData = useLocalStorage<PersistedData | null>('stonecrop-operations', null, {
571
585
  serializer: {
572
586
  read: (v: string) => {
573
587
  try {
@@ -1,8 +1,8 @@
1
- import { SchemaTypes } from '@stonecrop/aform'
1
+ import type { SchemaTypes } from '@stonecrop/aform'
2
2
  import type { Ref, ComputedRef } from 'vue'
3
3
 
4
4
  import type Doctype from '../doctype'
5
- import type { HSTNode } from '../stores/hst'
5
+ import type { HSTNode } from './hst'
6
6
  import type { HSTOperation, OperationLogConfig, OperationLogSnapshot } from './operation-log'
7
7
 
8
8
  /**
@@ -179,14 +179,28 @@ export type HSTStonecropReturn = BaseStonecropReturn & {
179
179
  */
180
180
  resolvedSchema: Ref<SchemaTypes[]>
181
181
  /**
182
- * Loads or initializes nested doctype data.
183
- * Use this when rendering a nested form component. Checks HST first, then initializes defaults.
184
- * @param parentPath - The HST path to check for existing data
185
- * @param childDoctype - The nested doctype metadata
186
- * @param recordId - Optional record ID (reserved for future API fetch)
187
- * @returns The loaded or initialized data object
182
+ * Scaffold empty descendant records from defaults for all descendant links.
183
+ * @param path - The HST path where initialized data should be stored
184
+ * @param doctype - The doctype to initialize
188
185
  */
189
- loadNestedData: (parentPath: string, childDoctype: Doctype, recordId?: string) => Record<string, any>
186
+ initializeNestedData: (path: string, doctype: Doctype) => void
187
+
188
+ /**
189
+ * Fetch a record and its nested data from the server.
190
+ * Stores each field at its own HST path per the field-level convention.
191
+ * @param path - The HST path (e.g., "recipe.r1")
192
+ * @param doctype - The doctype to fetch
193
+ * @param recordId - Record ID to fetch
194
+ * @param options - Query options (includeNested to control which links are fetched)
195
+ * @throws Error with code "CLIENT_REQUIRED" if no data client is configured
196
+ * @throws Error with code "RECORD_NOT_FOUND" if the server returns null
197
+ */
198
+ fetchNestedData: (
199
+ path: string,
200
+ doctype: Doctype,
201
+ recordId: string,
202
+ options?: { includeNested?: boolean | string[] }
203
+ ) => Promise<void>
190
204
  /**
191
205
  * Collects a complete record payload with all nested data from HST.
192
206
  * Use this before submitting to an API. Recursively includes 1:1 and 1:many nested records.
@@ -196,15 +210,15 @@ export type HSTStonecropReturn = BaseStonecropReturn & {
196
210
  */
197
211
  collectRecordPayload: (doctype: Doctype, recordId: string) => Record<string, any>
198
212
  /**
199
- * Creates a nested context for a child doctype component.
213
+ * Creates a nested context for a descendant doctype component.
200
214
  * Use this in parent components to pass scoped handlers to child components.
201
215
  * @param basePath - The parent HST path prefix
202
- * @param childDoctype - The child doctype metadata
216
+ * @param descendantDoctype - The descendant doctype metadata
203
217
  * @returns Scoped provideHSTPath and handleHSTChange functions
204
218
  */
205
219
  createNestedContext: (
206
220
  basePath: string,
207
- childDoctype: Doctype
221
+ descendantDoctype: Doctype
208
222
  ) => {
209
223
  provideHSTPath: (fieldname: string) => string
210
224
  handleHSTChange: (changeData: HSTChangeData) => void
@@ -224,6 +238,17 @@ export type HSTStonecropReturn = BaseStonecropReturn & {
224
238
  * Available immediately if Doctype instance passed, after async resolution if slug string passed.
225
239
  */
226
240
  resolvedDoctype: Ref<Doctype | undefined>
241
+ /**
242
+ * Computed ref indicating whether workflow actions are ready to run.
243
+ * True when all links with blockWorkflows are loaded in HST.
244
+ * Use with v-bind:disabled="!isWorkflowReady" on action buttons.
245
+ */
246
+ isWorkflowReady: ComputedRef<boolean>
247
+ /**
248
+ * List of link fieldnames that are blocking workflow execution.
249
+ * Empty array when isWorkflowReady is true.
250
+ */
251
+ blockedLinks: ComputedRef<string[]>
227
252
  }
228
253
 
229
254
  // Import Stonecrop class for the BaseStonecropReturn type (circular reference handled via import)
@@ -243,3 +268,21 @@ export type HSTChangeData = {
243
268
  /** Optional record ID */
244
269
  recordId?: string
245
270
  }
271
+
272
+ /**
273
+ * Lazy link state for a single link field.
274
+ * Provides reactive state and reload capability for lazy-loaded links.
275
+ * @public
276
+ */
277
+ export type LazyLink = {
278
+ /** True while fetching data */
279
+ loading: Ref<boolean>
280
+ /** True after successful fetch (permanent until reload) */
281
+ loaded: Ref<boolean>
282
+ /** Error state, if any */
283
+ error: Ref<Error | null>
284
+ /** Explicitly trigger a fetch for this link */
285
+ reload: () => Promise<void>
286
+ /** The loaded data from HST, or undefined if not loaded */
287
+ data: ComputedRef<any>
288
+ }
@@ -1,5 +1,5 @@
1
1
  import type { SchemaTypes } from '@stonecrop/aform'
2
- import type { WorkflowMeta } from '@stonecrop/schema'
2
+ import type { LinkDeclaration, WorkflowMeta } from '@stonecrop/schema'
3
3
  import { List, Map } from 'immutable'
4
4
  import type { AnyStateNodeConfig, UnknownMachineConfig } from 'xstate'
5
5
 
@@ -11,6 +11,7 @@ export type ImmutableDoctype = {
11
11
  readonly schema?: List<SchemaTypes>
12
12
  readonly workflow?: UnknownMachineConfig | AnyStateNodeConfig | WorkflowMeta
13
13
  readonly actions?: Map<string, string[]>
14
+ readonly links?: Record<string, LinkDeclaration>
14
15
  }
15
16
 
16
17
  /**
@@ -45,16 +46,14 @@ export type DoctypeConfig = {
45
46
  slug?: string
46
47
  /** Database table name */
47
48
  tableName?: string
48
- /** Field definitions */
49
+ /** Field definitions (including link fields with fieldtype: 'Link') */
49
50
  fields?: SchemaTypes[]
51
+ /** Relationship links to other doctypes */
52
+ links?: Record<string, LinkDeclaration>
50
53
  /** Workflow configuration (XState format or simple WorkflowMeta) */
51
54
  workflow?: UnknownMachineConfig | WorkflowMeta
52
55
  /** Actions and their field triggers */
53
56
  actions?: Record<string, string[]>
54
- /** Parent doctype for inheritance */
57
+ /** Ancestor doctype for inheritance */
55
58
  inherits?: string
56
- /** Doctype to use for list views */
57
- listDoctype?: string
58
- /** Parent doctype for child tables */
59
- parentDoctype?: string
60
59
  }
@@ -3,7 +3,7 @@
3
3
  * @public
4
4
  */
5
5
 
6
- import { HSTNode } from '../stores/hst'
6
+ import type { HSTNode } from './hst'
7
7
 
8
8
  /**
9
9
  * Context provided to action functions when field changes occur
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Core HST Interface - enhanced with tree navigation
3
+ * Provides a hierarchical state tree interface for navigating and manipulating nested data structures.
4
+ *
5
+ * @public
6
+ */
7
+ export interface HSTNode {
8
+ /**
9
+ * Gets a value at the specified path
10
+ * @param path - The dot-separated path to the value
11
+ * @returns The value at the specified path
12
+ */
13
+ get(path: string): any
14
+
15
+ /**
16
+ * Sets a value at the specified path
17
+ * @param path - The dot-separated path where to set the value
18
+ * @param value - The value to set
19
+ * @param source - Optional source of the operation (user, system, sync, undo, redo)
20
+ */
21
+ set(path: string, value: any, source?: 'user' | 'system' | 'sync' | 'undo' | 'redo'): void
22
+
23
+ /**
24
+ * Checks if a value exists at the specified path
25
+ * @param path - The dot-separated path to check
26
+ * @returns True if the path exists, false otherwise
27
+ */
28
+ has(path: string): boolean
29
+
30
+ /**
31
+ * Gets the ancestor node in the tree hierarchy (immediate predecessor)
32
+ * @returns The ancestor HSTNode or null if this is the root
33
+ */
34
+ getAncestor(): HSTNode | null
35
+
36
+ /**
37
+ * Gets the root node of the tree
38
+ * @returns The root HSTNode
39
+ */
40
+ getRoot(): HSTNode
41
+
42
+ /**
43
+ * Gets the full path from root to this node
44
+ * @returns The dot-separated path string
45
+ */
46
+ getPath(): string
47
+
48
+ /**
49
+ * Gets the depth level of this node in the tree
50
+ * @returns The depth as a number (0 for root)
51
+ */
52
+ getDepth(): number
53
+
54
+ /**
55
+ * Gets an array of path segments from root to this node
56
+ * @returns Array of path segments representing breadcrumbs
57
+ */
58
+ getBreadcrumbs(): string[]
59
+
60
+ /**
61
+ * Gets a child node at the specified relative path
62
+ * @param path - The relative path to the child node
63
+ * @returns The child HSTNode
64
+ */
65
+ getNode(path: string): HSTNode
66
+
67
+ /**
68
+ * Trigger an XState transition with optional context data
69
+ * @param transition - The transition name (should be uppercase per convention)
70
+ * @param context - Optional additional FSM context data
71
+ * @returns Promise resolving to the transition execution results
72
+ */
73
+ triggerTransition(
74
+ transition: string,
75
+ context?: { currentState?: string; targetState?: string; fsmContext?: Record<string, any> }
76
+ ): Promise<any>
77
+ }
@@ -2,6 +2,7 @@
2
2
  export * from './composable'
3
3
  export * from './doctype'
4
4
  export * from './field-triggers'
5
+ export * from './hst'
5
6
  export * from './operation-log'
6
7
  export * from './plugin'
7
8
  export * from './registry'
@@ -79,11 +79,11 @@ export interface HSTOperation {
79
79
  /** Additional metadata for custom use cases */
80
80
  metadata?: Record<string, any>
81
81
 
82
- /** Parent operation ID for batch operations */
83
- parentOperationId?: string
82
+ /** Ancestor operation ID for batch operations */
83
+ ancestorOperationId?: string
84
84
 
85
- /** Child operation IDs for batch operations */
86
- childOperationIds?: string[]
85
+ /** Descendant operation IDs for batch operations */
86
+ descendantOperationIds?: string[]
87
87
  }
88
88
 
89
89
  /**
@@ -58,6 +58,8 @@ export interface ValidatorOptions {
58
58
  registry?: Registry
59
59
  /** Whether to validate Link field targets */
60
60
  validateLinkTargets?: boolean
61
+ /** Whether to validate links object (target resolution, backlink consistency, Link field correspondence) */
62
+ validateLinks?: boolean
61
63
  /** Whether to validate workflow reachability */
62
64
  validateWorkflows?: boolean
63
65
  /** Whether to validate action registration */
@@ -1 +0,0 @@
1
- @import"https://fonts.googleapis.com/css2?family=Arimo:ital,wght@0,400..700;1,400..700&display=swap";.atable-cell{border-radius:0;box-sizing:border-box;outline:none;box-shadow:none;color:var(--sc-cell-text-color);padding-left:.5ch!important;padding-right:.5ch;padding-top:var(--sc-atable-row-padding);padding-bottom:var(--sc-atable-row-padding);border-spacing:0px;border-collapse:collapse;overflow:hidden;text-overflow:ellipsis;order:1;white-space:nowrap;max-width:40ch;border-top:1px solid var(--sc-row-border-color);margin:0 0 0 1px}.atable-cell a{color:var(--sc-cell-text-color);text-decoration:none}.atable-cell:focus,.atable-cell:focus-within{background-color:var(--sc-focus-cell-background);outline-width:var(--sc-atable-cell-border-width);outline-style:solid;outline-offset:calc(var(--sc-atable-cell-border-width) * -1);outline-color:var(--sc-focus-cell-outline);box-shadow:none;overflow:hidden;text-wrap:nowrap;box-sizing:border-box}.cell-modified{font-weight:700;font-style:italic}.cell-modified-highlight{background-color:var(--sc-cell-changed-color)}.row-index{color:var(--sc-header-text-color);font-weight:700;text-align:center;-webkit-user-select:none;user-select:none;width:2ch;display:flex;align-items:center;justify-content:center}.expandable-row{border-top:1px solid var(--sc-row-border-color);height:var(--sc-atable-row-height)}.expandable-row>td:first-child{border-left:4px solid var(--sc-row-border-color)}.expanded-row{border-left:2px solid var(--sc-row-border-color)}.expandable-row:last-child{border-bottom:1px solid var(--sc-row-border-color)}.expanded-row-content{border-top:1px solid var(--sc-row-border-color);padding:1.5rem}.expandable-row.changed-row-gradient[data-v-a42297c7]:has(td.cell-modified){--cell-color-start: color-mix(in srgb, var(--sc-cell-changed-color), #fff 20%);--cell-color-end: color-mix(in srgb, var(--sc-cell-changed-color), #fff 60%);background:linear-gradient(90deg,var(--cell-color-start),var(--cell-color-end))}.aganttcell[data-v-c2df3f52]{background-color:#f9f9f9;width:100%;padding:0;height:100%}.gantt-container[data-v-c2df3f52]{position:relative;height:100%;background-color:#f0f0f0;border-radius:4px;overflow:visible}.gantt-bar[data-v-c2df3f52]{position:absolute;border-radius:4px;display:flex;align-items:center;justify-content:space-between;cursor:grab;box-sizing:border-box;border:1px solid rgba(0,0,0,.5);transition:left .1s ease-out,width .1s ease-out;height:80%;top:50%;z-index:0;transform:translateY(-50%)}.gantt-bar[data-v-c2df3f52]:active{cursor:grabbing}.gantt-bar.is-dragging[data-v-c2df3f52]{z-index:10}.gantt-label[data-v-c2df3f52]{flex:1;text-align:center;font-size:12px;color:#aaa;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding:0 8px;-webkit-user-select:none;user-select:none}.resize-handle[data-v-c2df3f52]{position:relative;width:12px;height:100%;cursor:ew-resize;display:flex;align-items:center;justify-content:center;z-index:0;background:#00000040}.left-resize-handle[data-v-c2df3f52]{border-right:1px solid rgba(0,0,0,.5)}.right-resize-handle[data-v-c2df3f52]{border-left:1px solid rgba(0,0,0,.5)}.handle-grip[data-v-c2df3f52]{width:4px;height:12px;border-radius:2px;background:#000c}.resize-handle[data-v-c2df3f52]:hover{background-color:#ffffff80}.vertical-indicator[data-v-c2df3f52]{position:absolute;width:2px;opacity:0;pointer-events:none;transition:opacity .2s ease;top:-100vh;height:100vh;z-index:5;background-color:var(--v737862e7)}.left-indicator[data-v-c2df3f52]{left:50%;transform:translate(-50%)}.right-indicator[data-v-c2df3f52]{right:50%;transform:translate(50%)}.resize-handle.is-dragging .vertical-indicator[data-v-c2df3f52]{opacity:.7}.gantt-container[data-v-c2df3f52]:after{content:"";position:absolute;inset:0;background-size:calc(100% / var(--v05f25613)) 100%;background-image:linear-gradient(to right,rgba(0,0,0,.1) 1px,transparent 1px);pointer-events:none;z-index:1}.connection-handle[data-v-c2df3f52]{position:absolute;top:50%;transform:translateY(-50%);width:16px;height:16px;opacity:0;transition:opacity .2s ease;cursor:crosshair;z-index:2;display:flex;align-items:center;justify-content:center}.connection-handle.visible[data-v-c2df3f52]{opacity:1}.left-connection-handle[data-v-c2df3f52]{left:-16px}.right-connection-handle[data-v-c2df3f52]{right:-16px}.connection-dot[data-v-c2df3f52]{width:8px;height:8px;border-radius:50%;background-color:#2196f3;border:2px solid white;box-shadow:0 1px 3px #0000004d}.connection-handle:hover .connection-dot[data-v-c2df3f52]{background-color:#1976d2;transform:scale(1.2)}.connection-handle.is-dragging[data-v-c2df3f52]{opacity:1!important}.connection-handle.is-dragging .connection-dot[data-v-c2df3f52]{background-color:#1976d2;transform:scale(1.3);box-shadow:0 2px 8px #2196f366}.atable-row-actions{width:2rem;min-width:2rem;padding:0 .25rem;vertical-align:middle;white-space:nowrap;border-top:1px solid var(--sc-row-border-color);background:#fff;-webkit-user-select:none;user-select:none;position:relative}.atable-row-actions.dropdown-active{z-index:101}.row-actions-icons{display:flex;gap:.25rem;align-items:center;justify-content:center}.row-action-btn{display:inline-flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;padding:.125rem;border:none;background:transparent;cursor:pointer;border-radius:.25rem;transition:background-color .15s ease}.row-action-btn:hover{background-color:var(--sc-gray-10, #e5e5e5)}.row-action-btn:focus{outline:2px solid var(--sc-focus-cell-outline, #3b82f6);outline-offset:1px}.row-action-btn .action-icon{display:flex;align-items:center;justify-content:center;width:1rem;height:1rem}.row-action-btn .action-icon :deep(svg){width:100%;height:100%}.row-actions-dropdown{position:relative;display:inline-block}.row-actions-dropdown:has(button:focus){outline:2px solid var(--sc-focus-cell-outline);outline-offset:-2px}.row-actions-toggle{display:inline-flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;padding:0;border:none;background:transparent;cursor:pointer;border-radius:.25rem;font-size:1rem;font-weight:700;transition:background-color .15s ease}.row-actions-toggle:hover{background-color:var(--sc-gray-10, #e5e5e5)}.dropdown-icon{line-height:1}.row-actions-menu{position:fixed;z-index:100;min-width:10rem;padding:.25rem 0;background:#fff;border:1px solid var(--sc-row-border-color);border-left:4px solid var(--sc-row-border-color);border-radius:0}.row-actions-menu.menu-flipped{box-shadow:0 -4px 6px -1px #0000001a,0 -2px 4px -2px #0000001a}.row-action-menu-item{display:flex;align-items:center;gap:.5rem;width:100%;padding:.5rem .75rem;border:none;background:transparent;cursor:pointer;text-align:left;font-size:.875rem;transition:background-color .15s ease}.row-action-menu-item:hover{background-color:var(--sc-gray-10, #f5f5f5)}.row-action-menu-item:focus{outline:none;background-color:var(--sc-gray-10, #f5f5f5)}.row-action-menu-item .action-icon{display:flex;align-items:center;justify-content:center;width:1rem;height:1rem;flex-shrink:0}.row-action-menu-item .action-icon :deep(svg){width:100%;height:100%}.row-action-menu-item .action-label{flex:1}.atable-row{background-color:#fff}.atable-row:last-child>td{border-bottom:1px solid var(--sc-row-border-color)}.atable-row>td:first-child{border-left:4px solid var(--sc-row-border-color)}.atable-row>td:last-child{border-right:1px solid var(--sc-row-border-color)}.list-index{color:var(--sc-header-text-color);font-weight:700;padding-left:var(--sc-atable-row-padding);padding-right:.5em;text-align:left;-webkit-user-select:none;user-select:none;border-top:1px solid var(--sc-row-border-color);text-overflow:ellipsis;overflow:hidden;box-sizing:border-box;padding-top:var(--sc-atable-row-padding);padding-bottom:var(--sc-atable-row-padding)}.tree-index{color:var(--sc-header-text-color);font-weight:700;text-align:center;-webkit-user-select:none;user-select:none;width:2ch;box-sizing:border-box;padding-top:var(--sc-atable-row-padding);padding-bottom:var(--sc-atable-row-padding)}.atable-row:has(td.cell-modified)>td.sticky-column,.atable-row:has(td.cell-modified)>th.sticky-column,.atable-row:has(td.cell-modified)>td.sticky-index,.atable-row:has(td.cell-modified)>th.sticky-index{background:var(--sc-cell-changed-color)}.atable-row.changed-row-gradient[data-v-2e038a9c]:has(td.cell-modified){--cell-color-start: color-mix(in srgb, var(--sc-cell-changed-color), #fff 20%);--cell-color-end: color-mix(in srgb, var(--sc-cell-changed-color), #fff 60%);background:linear-gradient(90deg,var(--cell-color-start),var(--cell-color-end))}.gantt-connection-overlay[data-v-d5929c98]{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:15}.connection-path[data-v-d5929c98]{transition:stroke-width .2s ease;pointer-events:auto;cursor:pointer;stroke-dasharray:5px;stroke:var(--sc-cell-text-color)}#arrowhead-marker polygon[data-v-d5929c98]{fill:var(--sc-cell-text-color)}.animated-path[data-v-d5929c98]{animation:animated-dash-d5929c98 infinite 1.5s linear}.connection-path[data-v-d5929c98]:hover{stroke-width:3px}.connection-hitbox[data-v-d5929c98]{pointer-events:auto;cursor:pointer}@keyframes animated-dash-d5929c98{0%{stroke-dashoffset:0px}to{stroke-dashoffset:-10px}}.column-filter[data-v-8487462d]{display:flex;align-items:center;gap:.25rem;width:100%}.filter-input[data-v-8487462d],.filter-select[data-v-8487462d]{background-color:var(--sc-form-background)!important;padding:.15rem .2rem;border:1px solid var(--sc-form-border);border-radius:3px;font-size:.875rem;color:var(--sc-text-color);width:100%;box-sizing:border-box}.filter-input[data-v-8487462d]:focus,.filter-select[data-v-8487462d]:focus{outline:none;border-color:var(--sc-input-active-border-color)}.checkbox-filter[data-v-8487462d]{display:flex;align-items:center;gap:.25rem;font-size:.875rem;color:var(--sc-text-color);cursor:pointer}.filter-checkbox[data-v-8487462d]{margin:0}.date-range-filter[data-v-8487462d]{display:flex;gap:.25rem;align-items:center;width:100%}.date-range-filter .filter-input[data-v-8487462d]{flex:1;min-width:0}.date-separator[data-v-8487462d]{color:var(--sc-gray-50);font-weight:500;padding:0 .25rem;flex-shrink:0}.clear-btn[data-v-8487462d]{background:var(--sc-gray-10, #f0f0f0);border:1px solid var(--sc-form-border);border-radius:3px;color:var(--sc-gray-70);cursor:pointer;font-size:1rem;padding:.15rem .4rem;line-height:1;flex-shrink:0}.atable-header-row th{padding-left:.5ch!important;font-weight:700;min-width:3ch;padding-top:var(--sc-atable-row-padding);padding-bottom:var(--sc-atable-row-padding);box-sizing:border-box;color:var(--sc-header-text-color);position:relative}#header-index{padding-left:var(--sc-atable-row-padding);box-sizing:border-box;border-top:none}.tree-index{padding-right:0}th{order:1}.list-expansion-index{width:2ch;margin-left:5px}.cursor-pointer{cursor:pointer}.atable-filters-row th{padding:.25rem .5ch;vertical-align:top}.row-actions-header{width:2rem;min-width:2rem;padding:0 .25rem}:root{--sc-primary-color: #0098c9;--sc-primary-text-color: #ffffff;--sc-brand-color: #202a44;--sc-gray-5: #f2f2f2;--sc-gray-10: #e6e6e6;--sc-gray-20: #cccccc;--sc-gray-50: #808080;--sc-gray-60: #666666;--sc-gray-80: #333333;--sc-brand-danger: #e63c28;--sc-brand-success: #155724;--sc-brand-warning: #b99d3e;--sc-active-cell-background: #ffffff;--sc-active-cell-outline: #e6a92d;--sc-cell-border-color: #ffffff;--sc-cell-text-color: #3a3c41;--sc-focus-cell-background: #ffffff;--sc-focus-cell-outline: #000000;--sc-header-border-color: #ffffff;--sc-header-text-color: var(--sc-gray-20);--sc-row-border-color: var(--sc-gray-20);--sc-row-color-zebra-dark: #dddddd;--sc-row-color-zebra-light: #eeeeee;--sc-row-number-background-color: #ffffff;--sc-input-active-border-color: #000000;--sc-input-active-label-color: #000000;--sc-input-border-color: var(--sc-gray-20);--sc-input-label-color: var(--sc-gray-60);--sc-required-border: #e63c28;--sc-cell-changed-color: #d8edff;--sc-form-border: var(--sc-gray-5);--sc-form-background: #ffffff;--sc-input-field-background: #ffffff;--sc-input-field-disabled-background: var(--sc-gray-5);--sc-font-size: 10px;--sc-font-family: Arimo, Arial, sans-serif;--sc-table-font-size: 16px;--sc-atable-font-family: "Arimo", sans-serif;--sc-atable-row-padding: .125rem;--sc-atable-row-height: 1.5em;--sc-atable-cell-border-width: 2px;--sc-table-loading-color: 204, 204, 204;--sc-btn-border: #cccccc;--sc-btn-color: white;--sc-btn-hover: #f2f2f2;--sc-btn-label-color: black}.amodal{position:absolute;background-color:var(--sc-row-color-zebra-dark);z-index:200}.atable-container{position:relative}.sticky-index{position:sticky;left:0;z-index:100;order:0}.sticky-column,th.sticky-column,td.sticky-column,th.sticky-index,td.sticky-index{position:sticky;z-index:100;order:0;background:#fff}.sticky-column-edge,.atable th.sticky-column-edge{border-right:1px solid var(--sc-row-border-color)}[data-v-56d7171c]:root{--sc-primary-color: #0098c9;--sc-primary-text-color: #ffffff;--sc-brand-color: #202a44;--sc-gray-5: #f2f2f2;--sc-gray-10: #e6e6e6;--sc-gray-20: #cccccc;--sc-gray-50: #808080;--sc-gray-60: #666666;--sc-gray-80: #333333;--sc-brand-danger: #e63c28;--sc-brand-success: #155724;--sc-brand-warning: #b99d3e;--sc-active-cell-background: #ffffff;--sc-active-cell-outline: #e6a92d;--sc-cell-border-color: #ffffff;--sc-cell-text-color: #3a3c41;--sc-focus-cell-background: #ffffff;--sc-focus-cell-outline: #000000;--sc-header-border-color: #ffffff;--sc-header-text-color: var(--sc-gray-20);--sc-row-border-color: var(--sc-gray-20);--sc-row-color-zebra-dark: #dddddd;--sc-row-color-zebra-light: #eeeeee;--sc-row-number-background-color: #ffffff;--sc-input-active-border-color: #000000;--sc-input-active-label-color: #000000;--sc-input-border-color: var(--sc-gray-20);--sc-input-label-color: var(--sc-gray-60);--sc-required-border: #e63c28;--sc-cell-changed-color: #d8edff;--sc-form-border: var(--sc-gray-5);--sc-form-background: #ffffff;--sc-input-field-background: #ffffff;--sc-input-field-disabled-background: var(--sc-gray-5);--sc-font-size: 10px;--sc-font-family: Arimo, Arial, sans-serif;--sc-table-font-size: 16px;--sc-atable-font-family: "Arimo", sans-serif;--sc-atable-row-padding: .125rem;--sc-atable-row-height: 1.5em;--sc-atable-cell-border-width: 2px;--sc-table-loading-color: 204, 204, 204;--sc-btn-border: #cccccc;--sc-btn-color: white;--sc-btn-hover: #f2f2f2;--sc-btn-label-color: black}.atable[data-v-56d7171c]{position:relative;font-family:var(--sc-atable-font-family);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:var(--sc-table-font-size);border-collapse:collapse;box-sizing:border-box;table-layout:auto;width:auto;overflow:clip;height:1px}.atable th[data-v-56d7171c]{border-width:0px;border-style:solid;border-radius:0;padding-left:.5ch;padding-right:.5ch;padding-top:var(--sc-atable-row-padding);padding-bottom:var(--sc-atable-row-padding);color:var(--sc-gray-60);height:var(--sc-atable-row-height);font-weight:300;letter-spacing:.05rem;order:1;box-sizing:border-box}.atable th[data-v-56d7171c]:focus{outline:none}.atable[data-v-56d7171c]:tbody{overflow:hidden;position:relative}.atable[data-v-56d7171c]:tbody:before{content:"";position:absolute;top:0;left:0;right:0;height:1px;background-color:transparent;z-index:100}.aloading[data-v-a930a25b]{width:100%;border-top:1px solid var(--sc-row-border-color);border-bottom:1px solid var(--sc-row-border-color);display:flex;background-color:#fff;border-left:4px solid var(--sc-row-border-color);padding-left:.5ch!important;padding-right:.5ch;padding-top:var(--sc-atable-row-padding);padding-bottom:var(--sc-atable-row-padding);align-items:center;box-sizing:border-box;background:var(--sc-focus-cell-background);overflow:hidden;position:relative}.aloading-bar[data-v-a930a25b]{width:100%;height:100%;position:absolute;left:-100%;top:0;background:linear-gradient(90deg,rgba(var(--sc-table-loading-color),0),rgba(var(--sc-table-loading-color),1),rgba(var(--sc-table-loading-color),0));animation:gradient-a930a25b infinite 2s;z-index:0}.aloading-header[data-v-a930a25b]{color:var(--sc-cell-text-color);font-family:var(--sc-atable-font-family);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:var(--sc-table-font-size);padding:0;margin:0;font-weight:400;z-index:1}.aloading-header[data-v-a930a25b]:after{content:"...";animation:ellipse-a930a25b 2s;animation-iteration-count:infinite}@keyframes gradient-a930a25b{0%{left:-100%}to{left:100%}}@keyframes ellipse-a930a25b{0%{content:""}20%{content:""}40%{content:"."}60%{content:".."}80%{content:"..."}}.aloading[data-v-e1165876]{width:100%;border-top:1px solid var(--sc-row-border-color);border-bottom:1px solid var(--sc-row-border-color);display:flex;background-color:#fff;border-left:4px solid var(--sc-row-border-color);padding-left:.5ch!important;padding-right:.5ch;padding-top:var(--sc-atable-row-padding);padding-bottom:var(--sc-atable-row-padding);align-items:center;box-sizing:border-box;background:var(--sc-focus-cell-background);overflow:hidden;position:relative}.aloading-bar[data-v-e1165876]{width:50%;height:3px;position:absolute;left:-100%;bottom:0;background:var(--sc-row-border-color);animation:bar-left-e1165876 infinite 2s;z-index:0}.aloading-header[data-v-e1165876]{color:var(--sc-cell-text-color);font-family:var(--sc-atable-font-family);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:var(--sc-table-font-size);padding:0;margin:0;font-weight:400;z-index:1}.aloading-header[data-v-e1165876]:after{content:"...";animation:ellipse-e1165876 2s;animation-iteration-count:infinite}@keyframes bar-left-e1165876{0%{left:-50%}to{left:100%}}@keyframes ellipse-e1165876{0%{content:""}20%{content:""}40%{content:"."}60%{content:".."}80%{content:"..."}}.aform_checkbox[data-v-cc185b72]{cursor:pointer;width:auto;margin-top:0;display:block}.aform_checkbox[data-v-cc185b72]:checked{accent-color:var(--sc-primary-color);border:1px solid black}.aform_checkbox-container[data-v-cc185b72]{width:100%;display:inline-block;text-align:left}.aform_checkbox-container input[data-v-cc185b72]{width:auto}.aform_checkbox-container:hover+.aform_field-label[data-v-cc185b72]{color:var(--sc-input-active-label-color)}div[data-v-8e467bb3]{min-width:40ch;width:100%;box-sizing:border-box;border:1px solid transparent;padding:0rem;margin:0rem;margin-right:1ch}input[data-v-8e467bb3]{width:calc(100% - 1ch);box-sizing:border-box;outline:1px solid transparent;border:1px solid var(--sc-input-border-color);padding:1ch .5ch .5ch 1ch;margin:.575rem 0 0;min-height:1.15rem;border-radius:.25rem}p[data-v-8e467bb3],label[data-v-8e467bb3]{color:var(--sc-input-label-color);display:block;min-height:1.15rem;padding:0rem;margin:0rem 0rem .25rem;border:1px solid transparent;box-sizing:border-box}p[data-v-8e467bb3]{width:100%;color:red;font-size:85%;box-sizing:border-box}label[data-v-8e467bb3]{z-index:0;font-size:80%;position:absolute;background:#fff;margin:-2.575rem 0 0 1ch;padding:0 .25ch;box-sizing:border-box}input[data-v-8e467bb3]:focus{border:1px solid var(--sc-input-active-border-color)}input:focus+label[data-v-8e467bb3]{color:var(--sc-input-active-label-color)}.autocomplete[data-v-c823d475]{position:relative}.input-wrapper[data-v-c823d475]{border:1px solid transparent;padding:0rem;margin:0rem;margin-right:1ch}input[data-v-c823d475]{width:calc(100% - 1ch);outline:1px solid transparent;border:1px solid var(--sc-input-border-color);padding:1ch .5ch .5ch 1ch;margin:.575rem 0 0;min-height:1.15rem;border-radius:.25rem}input[data-v-c823d475]:focus{border:1px solid var(--sc-input-active-border-color);border-radius:.25rem .25rem 0 0;border-bottom:none}label[data-v-c823d475]{display:block;min-height:1.15rem;padding:0rem;margin:0rem 0rem .25rem;border:1px solid transparent;z-index:0;font-size:80%;position:absolute;background:#fff;margin:-2.575rem 0 0 1ch;padding:0 .25ch}.autocomplete-results[data-v-c823d475]{position:absolute;width:calc(100% - 1ch + 1.5px);z-index:100;padding:0;margin:0;color:var(--sc-input-active-border-color);border:1px solid var(--sc-input-active-border-color);border-radius:0 0 .25rem .25rem;border-top:none;background-color:#fff}.autocomplete-result[data-v-c823d475]{list-style:none;text-align:left;padding:4px 6px;cursor:pointer;border-bottom:.5px solid lightgray}.autocomplete-result.is-active[data-v-c823d475],.autocomplete-result[data-v-c823d475]:hover{background-color:var(--sc-row-color-zebra-light);color:var(--sc-input-active-border-color)}.adatepicker[data-v-9da05d06]{font-size:var(--sc-table-font-size);display:inline-table;color:var(--sc-cell-text-color);outline:none;border-collapse:collapse}.adatepicker tr[data-v-9da05d06]{height:1.15rem;text-align:center;vertical-align:middle}.adatepicker td[data-v-9da05d06]{border:2px solid transparent;outline:2px solid transparent;min-width:3ch;max-width:3ch}.adatepicker td[data-v-9da05d06]:focus,.adatepicker td[data-v-9da05d06]:focus-within{outline:1px dashed black;box-shadow:none;min-height:1.15em;max-height:1.15em;overflow:hidden}.adatepicker .selectedDate[data-v-9da05d06]{outline:1px solid black;background:var(--sc-gray-20);font-weight:bolder}.adatepicker .todaysDate[data-v-9da05d06]{font-weight:bolder;text-decoration:underline;color:#000}.days-header>td[data-v-9da05d06]{font-weight:700}.prev-date[data-v-9da05d06]{color:var(--sc-gray-20)}.collapse-button[data-v-6f1c1b45]{width:2ch;min-width:calc(66px - 4ch);background-color:transparent;font-size:150%;text-align:center;border:none;margin-top:-.5rem}.rotated[data-v-6f1c1b45]{transform:rotate(45deg);-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg);transition:transform .25s;transform-origin:center center}.unrotated[data-v-6f1c1b45]{transform:rotate(0);-webkit-transform:rotate(0deg);-moz-transform:rotate(0deg);-ms-transform:rotate(0deg);-o-transform:rotate(0deg);transition:transform .25s}.aform_form-element{padding:0;margin:0;position:relative;box-sizing:border-box;flex-grow:1;min-width:20ch;margin-bottom:1rem}.aform_input-field{outline:1px solid var(--sc-input-border-color);outline-offset:-1px;font-size:1rem;padding:.5rem;margin:0;border-radius:0;box-sizing:border-box;width:100%;min-height:auto;position:relative;color:var(--sc-cell-text-color);background:var(--sc-input-field-background)}.aform_input-field:focus{outline:1px solid var(--sc-input-active-border-color)}.aform_display-value{display:block;padding:.5rem;min-height:2rem;color:var(--sc-cell-text-color);word-break:break-word}.aform_input-field:focus+.aform_field-label{color:var(--sc-input-active-label-color)}.aform_field-label{color:var(--sc-input-label-color);display:inline-block;position:absolute;padding:0 .25rem;margin:0rem;z-index:1;font-size:.7rem;font-weight:300;letter-spacing:.05rem;background:linear-gradient(var(--sc-form-background) 50%,var(--sc-input-field-background) 50%);width:auto;box-sizing:border-box;background:#fff;margin:0;grid-row:1;top:0;left:10px;border:none;line-height:0;transform:translateY(-50%)}.aform_input-field:disabled{background:var(--sc-input-field-disabled-background)}.aform_input-field:disabled+.aform_field-label{background:linear-gradient(var(--sc-form-background) 50%,var(--sc-input-field-disabled-background) 50%)}.aform_input-field:disabled~p.aform_error{background:linear-gradient(var(--sc-form-background) 50%,var(--sc-input-field-disabled-background) 50%)}.aform_field-label:after{margin:0;padding:0;box-sizing:border-box;content:"";line-height:normal}p.aform_error{display:block;display:inline-block;display:none;background:linear-gradient(var(--sc-form-background) 50%,var(--sc-input-field-background) 50%);padding:0 .25rem;margin:0rem;width:auto;color:var(--sc-brand-danger);font-size:.7rem;position:absolute;right:0;top:0;line-height:0;background:#fff;padding:.25rem;transform:translate(-1rem,-50%);margin:0}.aform[data-v-969d8869]{display:flex;flex-wrap:wrap;gap:1rem;padding:1rem;border:1px solid var(--sc-form-border);border-left:4px solid var(--sc-form-border);margin-bottom:1rem;max-width:100%}@media screen and (max-width:400px){.aform[data-v-969d8869]{flex-direction:column}}.aform-nested-section[data-v-969d8869]{width:100%;padding:.5rem 0}.aform-nested-label[data-v-969d8869]{font-size:.9rem;font-weight:600;margin:0 0 .5rem;color:var(--sc-input-label-color, #666)}.aform-nested-section .aform[data-v-969d8869]{border-left-width:2px;margin-left:.5rem}fieldset[data-v-a3606386]{max-width:100%;width:100%;margin-right:2ch;border:1px solid transparent;border-bottom:1px solid var(--sc-gray-50)}legend[data-v-a3606386]{width:100%;height:1.15rem;border:1px solid transparent;padding-bottom:.5rem;font-size:110%;font-weight:600;-webkit-user-select:none;user-select:none}.collapse-button[data-v-a3606386]{float:right}.aform_file-attach[data-v-6543d39a]{padding:1rem;display:flex;flex-wrap:wrap;gap:1rem;flex-direction:row;justify-content:center;align-items:center;border:1px dashed var(--sc-input-border-color);width:100%}@media screen and (max-width:400px){.aform_file-attach>.aform_form-btn[data-v-6543d39a]{width:100%}}.aform_file-attach-feedback[data-v-6543d39a]{color:var(--sc-input-label-color);width:100%;padding:.5rem;text-align:center;align-self:center}.aform_file-attach-feedback>li[data-v-6543d39a]{list-style:none;font-style:italic}.aform_file-attach-feedback>p[data-v-6543d39a]{margin-top:0}.aform_form-btn[data-v-6543d39a]{padding:.5rem 2rem;width:auto;border:1px solid var(--sc-input-border-color);color:var(--sc-input-label-color);cursor:pointer;background-color:#fff}.aform_form-btn[data-v-6543d39a]:disabled{background-color:var(--sc-gray-5)}.login-container[data-v-d9ffd0a7]{width:100%;position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;font-family:var(--sc-font-family)}.account-container[data-v-d9ffd0a7]{width:100%;margin-left:auto;margin-top:.5rem;margin-right:auto;display:flex;flex-direction:column;justify-content:center}.account-header[data-v-d9ffd0a7]{display:flex;flex-direction:column;text-align:center;margin-top:.5rem}#account-title[data-v-d9ffd0a7]{font-size:1.5rem;line-height:2rem;font-weight:600;letter-spacing:-.025em;margin:0}#account-subtitle[data-v-d9ffd0a7]{font-size:.875rem;line-height:1.25rem;margin:1rem}.login-form-container[data-v-d9ffd0a7]{display:grid;gap:.5rem}.login-form-element[data-v-d9ffd0a7]{display:grid;margin:.5rem 0;position:relative}.login-field[data-v-d9ffd0a7]{padding:.5rem .25rem .25rem .5rem;outline:1px solid transparent;border:1px solid var(--sc-input-border-color);border-radius:.25rem}.login-field[data-v-d9ffd0a7]:focus{border:1px solid black}.btn[data-v-d9ffd0a7]{background-color:var(--sc-btn-color);color:var(--sc-btn-label-color);border:1px solid var(--sc-btn-border);margin:.5rem 0;padding:.25rem;position:relative;cursor:pointer}.btn[data-v-d9ffd0a7]:hover{background-color:var(--sc-btn-hover)}.btn[data-v-d9ffd0a7]:disabled{background-color:var(--sc-input-field-disabled-background)}.disabled[data-v-d9ffd0a7]{opacity:.5}.loading-icon[data-v-d9ffd0a7]{animation:spin-d9ffd0a7 1s linear infinite forwards;display:inline-block;margin-right:.2rem;line-height:0;font-size:1rem;position:relative;top:.2rem}@keyframes spin-d9ffd0a7{0%{transform:rotate(0)}to{transform:rotate(360deg)}}