@dskripchenko/laravel-admin 1.1.0

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 (163) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +226 -0
  3. package/dist/.gitkeep +0 -0
  4. package/dist/api/bootstrap.d.ts +38 -0
  5. package/dist/api/bootstrap.test.d.ts +1 -0
  6. package/dist/api/client.d.ts +30 -0
  7. package/dist/api/client.test.d.ts +1 -0
  8. package/dist/api/envelope.d.ts +24 -0
  9. package/dist/api/envelope.test.d.ts +1 -0
  10. package/dist/api/errors.d.ts +40 -0
  11. package/dist/api/errors.test.d.ts +1 -0
  12. package/dist/components/AdminApp.vue.d.ts +2 -0
  13. package/dist/components/ForbiddenPage.vue.d.ts +2 -0
  14. package/dist/components/HomePage.vue.d.ts +2 -0
  15. package/dist/components/NotFoundPage.vue.d.ts +2 -0
  16. package/dist/components/SettingsPage.vue.d.ts +2 -0
  17. package/dist/components/UnknownScreenPage.vue.d.ts +2 -0
  18. package/dist/components/auth/LoginForm.test.d.ts +1 -0
  19. package/dist/components/auth/LoginForm.vue.d.ts +17 -0
  20. package/dist/components/auth/LoginPage.test.d.ts +1 -0
  21. package/dist/components/auth/LoginPage.vue.d.ts +26 -0
  22. package/dist/components/auth/TwoFactorForm.test.d.ts +1 -0
  23. package/dist/components/auth/TwoFactorForm.vue.d.ts +8 -0
  24. package/dist/components/auth/index.d.ts +6 -0
  25. package/dist/components/createComponentRegistry.d.ts +22 -0
  26. package/dist/components/dashboard/BarChartWidget.vue.d.ts +18 -0
  27. package/dist/components/dashboard/DashboardPage.test.d.ts +1 -0
  28. package/dist/components/dashboard/DashboardPage.vue.d.ts +28 -0
  29. package/dist/components/dashboard/DonutChartWidget.vue.d.ts +13 -0
  30. package/dist/components/dashboard/GaugeWidget.vue.d.ts +29 -0
  31. package/dist/components/dashboard/HeatmapWidget.vue.d.ts +18 -0
  32. package/dist/components/dashboard/MarkdownWidget.vue.d.ts +8 -0
  33. package/dist/components/dashboard/RecentTableWidget.vue.d.ts +12 -0
  34. package/dist/components/dashboard/StatWidget.vue.d.ts +22 -0
  35. package/dist/components/dashboard/UnknownWidget.vue.d.ts +5 -0
  36. package/dist/components/dashboard/WidgetRenderer.vue.d.ts +10 -0
  37. package/dist/components/dashboard/builtin.d.ts +4 -0
  38. package/dist/components/dashboard/index.d.ts +16 -0
  39. package/dist/components/dashboard/registry.d.ts +25 -0
  40. package/dist/components/dashboard/registry.test.d.ts +1 -0
  41. package/dist/components/fields/CheckboxField.vue.d.ts +16 -0
  42. package/dist/components/fields/DateField.vue.d.ts +25 -0
  43. package/dist/components/fields/NumberField.vue.d.ts +24 -0
  44. package/dist/components/fields/SelectField.vue.d.ts +28 -0
  45. package/dist/components/fields/TextAreaField.vue.d.ts +20 -0
  46. package/dist/components/fields/TextField.vue.d.ts +22 -0
  47. package/dist/components/fields/UnknownField.vue.d.ts +6 -0
  48. package/dist/components/fields/fields.test.d.ts +1 -0
  49. package/dist/components/fields/wysiwyg/quill/QuillField.vue.d.ts +26 -0
  50. package/dist/components/fields/wysiwyg/quill/index.d.ts +12 -0
  51. package/dist/components/fields/wysiwyg/tinymce/TinymceField.vue.d.ts +31 -0
  52. package/dist/components/fields/wysiwyg/tinymce/index.d.ts +12 -0
  53. package/dist/components/gallery/FieldGalleryPage.test.d.ts +1 -0
  54. package/dist/components/gallery/FieldGalleryPage.vue.d.ts +2 -0
  55. package/dist/components/gallery/index.d.ts +1 -0
  56. package/dist/components/import/ImportWizardPage.test.d.ts +1 -0
  57. package/dist/components/import/ImportWizardPage.vue.d.ts +59 -0
  58. package/dist/components/import/index.d.ts +1 -0
  59. package/dist/components/infolist/BadgeEntry.vue.d.ts +18 -0
  60. package/dist/components/infolist/IconEntry.vue.d.ts +22 -0
  61. package/dist/components/infolist/InfolistRenderer.test.d.ts +1 -0
  62. package/dist/components/infolist/InfolistRenderer.vue.d.ts +11 -0
  63. package/dist/components/infolist/KeyValueEntry.vue.d.ts +11 -0
  64. package/dist/components/infolist/TextEntry.vue.d.ts +17 -0
  65. package/dist/components/infolist/UnknownEntry.vue.d.ts +6 -0
  66. package/dist/components/infolist/builtin.d.ts +4 -0
  67. package/dist/components/infolist/index.d.ts +13 -0
  68. package/dist/components/infolist/recordContext.d.ts +9 -0
  69. package/dist/components/infolist/registry.d.ts +19 -0
  70. package/dist/components/infolist/registry.test.d.ts +1 -0
  71. package/dist/components/layouts/ColumnsLayout.vue.d.ts +13 -0
  72. package/dist/components/layouts/RowsLayout.vue.d.ts +10 -0
  73. package/dist/components/layouts/SectionLayout.vue.d.ts +11 -0
  74. package/dist/components/layouts/TabsLayout.vue.d.ts +22 -0
  75. package/dist/components/notifications/NotificationsDrawer.test.d.ts +1 -0
  76. package/dist/components/notifications/NotificationsDrawer.vue.d.ts +13 -0
  77. package/dist/components/notifications/index.d.ts +1 -0
  78. package/dist/components/profile/ProfilePage.test.d.ts +1 -0
  79. package/dist/components/profile/ProfilePage.vue.d.ts +50 -0
  80. package/dist/components/profile/index.d.ts +1 -0
  81. package/dist/components/render/FieldRenderer.test.d.ts +1 -0
  82. package/dist/components/render/FieldRenderer.vue.d.ts +9 -0
  83. package/dist/components/render/LayoutRenderer.test.d.ts +1 -0
  84. package/dist/components/render/LayoutRenderer.vue.d.ts +10 -0
  85. package/dist/components/render/builtin.d.ts +9 -0
  86. package/dist/components/render/formState.d.ts +36 -0
  87. package/dist/components/render/formState.test.d.ts +1 -0
  88. package/dist/components/render/index.d.ts +23 -0
  89. package/dist/components/render/registry.d.ts +35 -0
  90. package/dist/components/render/registry.test.d.ts +1 -0
  91. package/dist/components/resource/ResourceFormPage.test.d.ts +1 -0
  92. package/dist/components/resource/ResourceFormPage.vue.d.ts +13 -0
  93. package/dist/components/resource/ResourceIndexPage.test.d.ts +1 -0
  94. package/dist/components/resource/ResourceIndexPage.vue.d.ts +44 -0
  95. package/dist/components/resource/ResourceViewPage.test.d.ts +1 -0
  96. package/dist/components/resource/ResourceViewPage.vue.d.ts +13 -0
  97. package/dist/components/resource/index.d.ts +6 -0
  98. package/dist/components/shell/AdminShell.vue.d.ts +35 -0
  99. package/dist/components/shell/AdminSidebar.test.d.ts +1 -0
  100. package/dist/components/shell/AdminSidebar.vue.d.ts +27 -0
  101. package/dist/components/shell/AdminTopBar.test.d.ts +1 -0
  102. package/dist/components/shell/AdminTopBar.vue.d.ts +33 -0
  103. package/dist/components/shell/index.d.ts +18 -0
  104. package/dist/components/shell/widgets/LocaleSwitcher.test.d.ts +1 -0
  105. package/dist/components/shell/widgets/LocaleSwitcher.vue.d.ts +2 -0
  106. package/dist/components/shell/widgets/NotificationBell.vue.d.ts +2 -0
  107. package/dist/components/shell/widgets/ThemeToggle.test.d.ts +1 -0
  108. package/dist/components/shell/widgets/ThemeToggle.vue.d.ts +2 -0
  109. package/dist/components/shell/widgets/UserMenu.test.d.ts +1 -0
  110. package/dist/components/shell/widgets/UserMenu.vue.d.ts +2 -0
  111. package/dist/createAdminApp.d.ts +85 -0
  112. package/dist/createAdminApp.test.d.ts +1 -0
  113. package/dist/formState-DGNcH1XQ.js +40 -0
  114. package/dist/formState-DGNcH1XQ.js.map +1 -0
  115. package/dist/formState-GlJBphEn.cjs +2 -0
  116. package/dist/formState-GlJBphEn.cjs.map +1 -0
  117. package/dist/index.cjs +2 -0
  118. package/dist/index.cjs.map +1 -0
  119. package/dist/index.d.ts +62 -0
  120. package/dist/index.mjs +4345 -0
  121. package/dist/index.mjs.map +1 -0
  122. package/dist/quill.cjs +2 -0
  123. package/dist/quill.cjs.map +1 -0
  124. package/dist/quill.mjs +71 -0
  125. package/dist/quill.mjs.map +1 -0
  126. package/dist/router/builder.d.ts +52 -0
  127. package/dist/router/builder.test.d.ts +1 -0
  128. package/dist/router/guards.d.ts +56 -0
  129. package/dist/router/guards.test.d.ts +1 -0
  130. package/dist/router/index.d.ts +63 -0
  131. package/dist/router/index.test.d.ts +1 -0
  132. package/dist/stores/auth.d.ts +142 -0
  133. package/dist/stores/auth.test.d.ts +1 -0
  134. package/dist/stores/index.d.ts +21 -0
  135. package/dist/stores/locale.d.ts +29 -0
  136. package/dist/stores/locale.test.d.ts +1 -0
  137. package/dist/stores/manifest.d.ts +515 -0
  138. package/dist/stores/manifest.test.d.ts +1 -0
  139. package/dist/stores/menu.d.ts +215 -0
  140. package/dist/stores/menu.test.d.ts +1 -0
  141. package/dist/stores/notifications.d.ts +137 -0
  142. package/dist/stores/notifications.test.d.ts +1 -0
  143. package/dist/stores/registry.d.ts +16 -0
  144. package/dist/stores/registry.test.d.ts +1 -0
  145. package/dist/stores/resourceForm.d.ts +91 -0
  146. package/dist/stores/resourceForm.test.d.ts +1 -0
  147. package/dist/stores/resourceIndex.d.ts +149 -0
  148. package/dist/stores/resourceIndex.test.d.ts +1 -0
  149. package/dist/stores/theme.d.ts +29 -0
  150. package/dist/stores/theme.test.d.ts +1 -0
  151. package/dist/style.css +1 -0
  152. package/dist/tinymce.cjs +2 -0
  153. package/dist/tinymce.cjs.map +1 -0
  154. package/dist/tinymce.mjs +80 -0
  155. package/dist/tinymce.mjs.map +1 -0
  156. package/dist/types/bootstrap.d.ts +50 -0
  157. package/package.json +162 -0
  158. package/resources/fonts/InterDisplay-Bold.woff2 +0 -0
  159. package/resources/fonts/InterDisplay-ExtraBold.woff2 +0 -0
  160. package/resources/fonts/InterDisplay-SemiBold.woff2 +0 -0
  161. package/resources/fonts/InterVariable-Italic.woff2 +0 -0
  162. package/resources/fonts/InterVariable.woff2 +0 -0
  163. package/resources/fonts/fonts.css +69 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":["../resources/ts/stores/registry.ts","../resources/ts/stores/theme.ts","../resources/ts/components/shell/widgets/ThemeToggle.vue","../resources/ts/stores/locale.ts","../resources/ts/components/shell/widgets/LocaleSwitcher.vue","../resources/ts/stores/notifications.ts","../resources/ts/components/shell/widgets/NotificationBell.vue","../resources/ts/api/errors.ts","../resources/ts/stores/auth.ts","../resources/ts/components/shell/widgets/UserMenu.vue","../resources/ts/components/shell/AdminTopBar.vue","../resources/ts/stores/menu.ts","../resources/ts/components/shell/AdminSidebar.vue","../resources/ts/components/shell/AdminShell.vue","../resources/ts/components/AdminApp.vue","../resources/ts/stores/manifest.ts","../resources/ts/components/HomePage.vue","../resources/ts/components/ForbiddenPage.vue","../resources/ts/components/NotFoundPage.vue","../resources/ts/components/SettingsPage.vue","../resources/ts/components/UnknownScreenPage.vue","../resources/ts/components/auth/LoginForm.vue","../resources/ts/components/auth/TwoFactorForm.vue","../resources/ts/components/auth/LoginPage.vue","../resources/ts/stores/resourceIndex.ts","../resources/ts/components/resource/ResourceIndexPage.vue","../resources/ts/stores/resourceForm.ts","../resources/ts/components/createComponentRegistry.ts","../resources/ts/components/render/registry.ts","../resources/ts/components/fields/UnknownField.vue","../resources/ts/components/render/FieldRenderer.vue","../resources/ts/components/render/LayoutRenderer.vue","../resources/ts/components/resource/ResourceFormPage.vue","../resources/ts/components/infolist/registry.ts","../resources/ts/components/infolist/UnknownEntry.vue","../resources/ts/components/infolist/InfolistRenderer.vue","../resources/ts/components/infolist/recordContext.ts","../resources/ts/components/resource/ResourceViewPage.vue","../resources/ts/components/profile/ProfilePage.vue","../resources/ts/components/dashboard/registry.ts","../resources/ts/components/dashboard/UnknownWidget.vue","../resources/ts/components/dashboard/WidgetRenderer.vue","../resources/ts/components/dashboard/DashboardPage.vue","../resources/ts/components/dashboard/StatWidget.vue","../resources/ts/components/dashboard/BarChartWidget.vue","../resources/ts/components/dashboard/DonutChartWidget.vue","../resources/ts/components/dashboard/RecentTableWidget.vue","../resources/ts/components/dashboard/HeatmapWidget.vue","../resources/ts/components/dashboard/GaugeWidget.vue","../resources/ts/components/dashboard/MarkdownWidget.vue","../resources/ts/components/dashboard/builtin.ts","../resources/ts/api/envelope.ts","../resources/ts/api/client.ts","../resources/ts/router/builder.ts","../resources/ts/router/guards.ts","../resources/ts/router/index.ts","../resources/ts/components/fields/TextField.vue","../resources/ts/components/fields/TextAreaField.vue","../resources/ts/components/fields/NumberField.vue","../resources/ts/components/fields/SelectField.vue","../resources/ts/components/fields/CheckboxField.vue","../resources/ts/components/fields/DateField.vue","../resources/ts/components/layouts/RowsLayout.vue","../resources/ts/components/layouts/ColumnsLayout.vue","../resources/ts/components/layouts/SectionLayout.vue","../resources/ts/components/layouts/TabsLayout.vue","../resources/ts/components/render/builtin.ts","../resources/ts/components/infolist/TextEntry.vue","../resources/ts/components/infolist/BadgeEntry.vue","../resources/ts/components/infolist/IconEntry.vue","../resources/ts/components/infolist/KeyValueEntry.vue","../resources/ts/components/infolist/builtin.ts","../resources/ts/createAdminApp.ts","../resources/ts/api/bootstrap.ts","../resources/ts/components/notifications/NotificationsDrawer.vue","../resources/ts/components/import/ImportWizardPage.vue","../resources/ts/components/gallery/FieldGalleryPage.vue"],"sourcesContent":["/**\n * Глобальный registry AdminClient'а для Pinia stores.\n *\n * Stores не получают client через параметры — это сильно усложняет API\n * (`useAuthStore(client)` каждый раз). Вместо этого client регистрируется\n * один раз при bootstrap'е приложения через `setAdminClient()`, и stores\n * читают его через `getAdminClient()`.\n *\n * Это singleton-pattern — допустим в случае admin-SPA, потому что\n * client всегда один на весь жизненный цикл.\n */\n\nimport type { AdminClient } from '../api/client'\n\nlet _client: AdminClient | null = null\n\nexport function setAdminClient(client: AdminClient): void {\n _client = client\n}\n\nexport function getAdminClient(): AdminClient {\n if (_client === null) {\n throw new Error(\n '[admin] AdminClient is not registered. Call setAdminClient(...) before using stores.',\n )\n }\n return _client\n}\n\nexport function clearAdminClient(): void {\n _client = null\n}\n\nexport function hasAdminClient(): boolean {\n return _client !== null\n}\n","/**\n * Theme store: текущая тема + список доступных + persist через API.\n *\n * Side effect: применяет `<html data-theme=\"...\">` при изменении.\n * SPA рассчитывает на это для CSS-vars overrides.\n */\n\nimport { defineStore } from 'pinia'\nimport { computed, ref } from 'vue'\nimport { getAdminClient } from './registry'\nimport type { AdminBootstrap } from '../types/bootstrap'\n\nexport const useThemeStore = defineStore('admin-theme', () => {\n const current = ref<string>('light')\n const available = ref<string[]>(['light', 'dark'])\n\n const isDark = computed(() => current.value === 'dark')\n\n function hydrate(bootstrap: AdminBootstrap): void {\n current.value = bootstrap.theme\n available.value = bootstrap.availableThemes\n applyHtmlAttr(bootstrap.theme)\n }\n\n /**\n * Локальное переключение без round-trip'а. Используется когда нужно\n * мгновенно применить тему до получения ответа от сервера.\n */\n function applyLocal(theme: string): void {\n if (!available.value.includes(theme)) {\n throw new Error(`Theme \"${theme}\" is not available`)\n }\n current.value = theme\n applyHtmlAttr(theme)\n }\n\n /**\n * POST /system/setTheme — persist в user.theme + cookie.\n * Применяет тему к DOM немедленно (optimistic update).\n */\n async function setTheme(theme: string): Promise<void> {\n if (!available.value.includes(theme)) {\n throw new Error(`Theme \"${theme}\" is not available`)\n }\n\n const previous = current.value\n applyLocal(theme)\n\n try {\n const client = getAdminClient()\n await client.post('/system/setTheme', { theme })\n } catch (err) {\n // Откатываем optimistic update.\n applyLocal(previous)\n throw err\n }\n }\n\n function applyHtmlAttr(theme: string): void {\n if (typeof document !== 'undefined' && document.documentElement) {\n document.documentElement.setAttribute('data-theme', theme)\n }\n }\n\n return {\n current,\n available,\n isDark,\n hydrate,\n applyLocal,\n setTheme,\n }\n})\n","<script setup lang=\"ts\">\n/**\n * Toggle между light/dark поверх @dskripchenko/ui. Использует topbar\n * icon-button-стиль (.admin-topbar__icon-btn) для визуальной согласованности\n * с остальными widget'ами в баре.\n */\nimport { computed } from 'vue'\nimport { useThemeStore } from '../../../stores/theme'\n\nconst theme = useThemeStore()\n\nconst isDark = computed(() => theme.current === 'dark')\nconst iconName = computed(() => (isDark.value ? 'sun' : 'moon'))\nconst ariaLabel = computed(() =>\n isDark.value ? 'Переключить на светлую тему' : 'Переключить на тёмную тему',\n)\n\nasync function toggle(): Promise<void> {\n const next = isDark.value ? 'light' : 'dark'\n await theme.setTheme(next)\n}\n</script>\n\n<template>\n <button\n type=\"button\"\n class=\"admin-topbar__icon-btn\"\n :aria-label=\"ariaLabel\"\n :aria-pressed=\"isDark\"\n @click=\"toggle\"\n >\n <span class=\"admin-topbar__icon\" :data-icon=\"iconName\" />\n </button>\n</template>\n","/**\n * Locale store: текущая локаль + persist + sync с AdminClient.\n *\n * Side effects при смене:\n * - `<html lang=\"...\">` обновляется\n * - AdminClient.setLocale() — все следующие запросы получат правильный\n * X-Admin-Locale header\n * - POST /system/setLocale → persist в user.locale + cookie\n */\n\nimport { defineStore } from 'pinia'\nimport { ref } from 'vue'\nimport { getAdminClient } from './registry'\nimport type { AdminBootstrap } from '../types/bootstrap'\n\nexport const useLocaleStore = defineStore('admin-locale', () => {\n const current = ref<string>('ru')\n const available = ref<string[]>(['ru', 'en'])\n\n function hydrate(bootstrap: AdminBootstrap): void {\n current.value = bootstrap.locale\n available.value = bootstrap.availableLocales\n applySideEffects(bootstrap.locale)\n }\n\n function applyLocal(locale: string): void {\n if (!available.value.includes(locale)) {\n throw new Error(`Locale \"${locale}\" is not available`)\n }\n current.value = locale\n applySideEffects(locale)\n }\n\n async function setLocale(locale: string): Promise<void> {\n if (!available.value.includes(locale)) {\n throw new Error(`Locale \"${locale}\" is not available`)\n }\n\n const previous = current.value\n applyLocal(locale)\n\n try {\n const client = getAdminClient()\n await client.post('/system/setLocale', { locale })\n } catch (err) {\n applyLocal(previous)\n throw err\n }\n }\n\n function applySideEffects(locale: string): void {\n if (typeof document !== 'undefined' && document.documentElement) {\n document.documentElement.setAttribute('lang', locale)\n }\n // Try-catch потому что в test-окружении registry может быть пуст.\n try {\n getAdminClient().setLocale(locale)\n } catch {\n // ignore — клиент ещё не зарегистрирован\n }\n }\n\n return {\n current,\n available,\n hydrate,\n applyLocal,\n setLocale,\n }\n})\n","<script setup lang=\"ts\">\n/**\n * Переключение локали через UidMenu. В topbar показываем компактно\n * (icon + uppercase-код), под ним выпадает список доступных локалей.\n */\nimport { UidMenu, UidMenuItem } from '@dskripchenko/ui'\nimport { useLocaleStore } from '../../../stores/locale'\n\nconst locale = useLocaleStore()\n\nasync function pick(loc: string): Promise<void> {\n if (loc === locale.current) return\n await locale.setLocale(loc)\n}\n</script>\n\n<template>\n <UidMenu>\n <template #trigger>\n <button\n type=\"button\"\n class=\"admin-topbar__icon-btn\"\n style=\"width: auto; padding: 0 8px; gap: 4px; font-size: 12px;\"\n aria-label=\"Сменить локаль\"\n >\n <span class=\"admin-topbar__icon\" data-icon=\"globe\" />\n <span>{{ (locale.current ?? '').toUpperCase() }}</span>\n </button>\n </template>\n\n <UidMenuItem\n v-for=\"loc in locale.available\"\n :key=\"loc\"\n @click=\"pick(loc)\"\n >\n {{ loc.toUpperCase() }}\n </UidMenuItem>\n </UidMenu>\n</template>\n","/**\n * Notifications store: список + unread count + read/delete actions.\n *\n * Bell-badge polling реализуется на уровне UI через setInterval +\n * вызов loadUnread() — store сам не polling'ит, чтобы не дублировать\n * SetInterval'ы между tab'ами.\n */\n\nimport { defineStore } from 'pinia'\nimport { computed, ref } from 'vue'\nimport { getAdminClient } from './registry'\nimport type { AdminBootstrap } from '../types/bootstrap'\n\nexport interface NotificationItem {\n id: string\n type: string\n data: Record<string, unknown>\n read_at: string | null\n created_at: string | null\n}\n\nexport type NotificationFilter = 'all' | 'unread' | 'read'\n\nexport const useNotificationsStore = defineStore('admin-notifications', () => {\n const items = ref<NotificationItem[]>([])\n const unreadCount = ref(0)\n const loading = ref(false)\n const lastFilter = ref<NotificationFilter>('all')\n const meta = ref<{ page: number; per_page: number; total: number; last_page: number } | null>(null)\n\n const hasUnread = computed(() => unreadCount.value > 0)\n\n function hydrate(bootstrap: AdminBootstrap): void {\n unreadCount.value = bootstrap.unread_notifications_count\n }\n\n async function load(filter: NotificationFilter = 'all', page = 1): Promise<void> {\n loading.value = true\n try {\n const client = getAdminClient()\n const result = await client.get<{\n data: NotificationItem[]\n meta: { page: number; per_page: number; total: number; last_page: number; unread_count: number }\n }>(`/notifications/list?type=${filter}&page=${page}`)\n items.value = result.data\n unreadCount.value = result.meta.unread_count\n meta.value = {\n page: result.meta.page,\n per_page: result.meta.per_page,\n total: result.meta.total,\n last_page: result.meta.last_page,\n }\n lastFilter.value = filter\n } finally {\n loading.value = false\n }\n }\n\n /**\n * Лёгкий polling-endpoint — только count + последние 20.\n * Для bell-badge.\n */\n async function loadUnread(): Promise<void> {\n const client = getAdminClient()\n const result = await client.get<{ count: number; data: NotificationItem[] }>(\n '/notifications/unread',\n )\n unreadCount.value = result.count\n // Не подменяем items если в данный момент open'нут другой filter.\n if (lastFilter.value === 'unread') {\n items.value = result.data\n }\n }\n\n async function markAsRead(id: string): Promise<void> {\n const client = getAdminClient()\n await client.post('/notifications/markAsRead', { id })\n // Optimistic update в локальном state.\n const item = items.value.find((n) => n.id === id)\n if (item && item.read_at === null) {\n item.read_at = new Date().toISOString()\n unreadCount.value = Math.max(0, unreadCount.value - 1)\n }\n }\n\n async function markAllAsRead(): Promise<void> {\n const client = getAdminClient()\n await client.post('/notifications/markAllAsRead')\n const now = new Date().toISOString()\n for (const item of items.value) {\n if (item.read_at === null) item.read_at = now\n }\n unreadCount.value = 0\n }\n\n async function destroy(id: string): Promise<void> {\n const client = getAdminClient()\n await client.post('/notifications/destroy', { id })\n const index = items.value.findIndex((n) => n.id === id)\n if (index !== -1) {\n const wasUnread = items.value[index].read_at === null\n items.value.splice(index, 1)\n if (wasUnread) {\n unreadCount.value = Math.max(0, unreadCount.value - 1)\n }\n }\n }\n\n return {\n items,\n unreadCount,\n loading,\n meta,\n lastFilter,\n hasUnread,\n hydrate,\n load,\n loadUnread,\n markAsRead,\n markAllAsRead,\n destroy,\n }\n})\n","<script setup lang=\"ts\">\n/**\n * Bell с unread-badge. По эталону handoff'а — badge `.admin-topbar__bell-badge`\n * (округлая красная пилюля 14×14 + tabular-nums + max '99+').\n */\nimport { computed } from 'vue'\nimport { RouterLink } from 'vue-router'\nimport { useNotificationsStore } from '../../../stores/notifications'\n\nconst notifications = useNotificationsStore()\n\nconst display = computed(() => {\n const n = notifications.unreadCount\n if (n <= 0) return null\n return n > 99 ? '99+' : String(n)\n})\n</script>\n\n<template>\n <RouterLink\n to=\"/notifications\"\n class=\"admin-topbar__icon-btn\"\n aria-label=\"Уведомления\"\n >\n <span class=\"admin-topbar__icon\" data-icon=\"bell\" />\n <span\n v-if=\"display !== null\"\n class=\"admin-topbar__bell-badge\"\n :title=\"`Непрочитанных: ${notifications.unreadCount}`\"\n >\n {{ display }}\n </span>\n </RouterLink>\n</template>\n","/**\n * Кастомные Error-классы для admin API.\n *\n * Все API-ошибки бросаются как ApiError или его подклассы. Потребители\n * могут делать `instanceof ValidationError` для специфичной обработки.\n */\n\nimport type { ErrorEnvelope } from './envelope'\n\nexport class ApiError extends Error {\n public readonly status: number\n public readonly errorKey: string\n public readonly payload: ErrorEnvelope['payload']\n\n constructor(status: number, payload: ErrorEnvelope['payload']) {\n super(payload.message ?? `API error ${status}`)\n this.name = 'ApiError'\n this.status = status\n this.errorKey = payload.errorKey ?? 'unknown'\n this.payload = payload\n }\n}\n\nexport class UnauthenticatedError extends ApiError {\n constructor(payload: ErrorEnvelope['payload']) {\n super(401, payload)\n this.name = 'UnauthenticatedError'\n }\n}\n\nexport class ForbiddenError extends ApiError {\n constructor(payload: ErrorEnvelope['payload']) {\n super(403, payload)\n this.name = 'ForbiddenError'\n }\n}\n\nexport class NotFoundError extends ApiError {\n constructor(payload: ErrorEnvelope['payload']) {\n super(404, payload)\n this.name = 'NotFoundError'\n }\n}\n\nexport class ValidationError extends ApiError {\n /** Field-keyed map of error messages. */\n public readonly fields: Record<string, string[]>\n\n constructor(payload: ErrorEnvelope['payload']) {\n super(422, payload)\n this.name = 'ValidationError'\n this.fields = payload.messages ?? {}\n }\n\n /** Первое сообщение из field'а — удобно для toast. */\n firstFieldMessage(): string | null {\n for (const messages of Object.values(this.fields)) {\n if (messages.length > 0) {\n return messages[0]\n }\n }\n return null\n }\n}\n\n/**\n * Network-failure (не дошли до сервера). Отдельный класс чтобы UI мог\n * показать «Нет соединения» вместо «500 Server Error».\n */\nexport class NetworkError extends Error {\n constructor(message = 'Network error') {\n super(message)\n this.name = 'NetworkError'\n }\n}\n\n/**\n * Превращает HTTP-status + envelope в правильный подкласс ApiError.\n */\nexport function toApiError(status: number, payload: ErrorEnvelope['payload']): ApiError {\n switch (status) {\n case 401: return new UnauthenticatedError(payload)\n case 403: return new ForbiddenError(payload)\n case 404: return new NotFoundError(payload)\n case 422: return new ValidationError(payload)\n default: return new ApiError(status, payload)\n }\n}\n","/**\n * Auth store: текущий user, permissions, login/logout/2FA flow.\n *\n * Wildcard в permissions:\n * - `*` — полный доступ ко всему.\n * - `admin.users.*` — доступ ко всем admin.users.{view,create,update,delete}.\n *\n * 2FA flow:\n * 1. login() с верными creds + 2FA включена → success: false +\n * errorKey: 'two_factor_required' + challenge_token. State переходит в\n * `pendingChallenge`.\n * 2. UI показывает 2FA-форму. twoFactorChallenge(code) или\n * twoFactorRecovery(recovery_code) → success login flow.\n */\n\nimport { defineStore } from 'pinia'\nimport { computed, ref } from 'vue'\nimport { getAdminClient } from './registry'\nimport { ApiError } from '../api/errors'\nimport type { AdminUser, AdminBootstrap } from '../types/bootstrap'\n\nexport interface PendingChallenge {\n challengeToken: string\n remember: boolean\n}\n\nexport interface LoginPayload {\n email: string\n password: string\n remember?: boolean\n}\n\nexport const useAuthStore = defineStore('admin-auth', () => {\n const user = ref<AdminUser | null>(null)\n const permissions = ref<string[]>([])\n const pendingChallenge = ref<PendingChallenge | null>(null)\n\n const isAuthenticated = computed(() => user.value !== null)\n const isChallengePending = computed(() => pendingChallenge.value !== null)\n\n /** Заполнить store из bootstrap-payload'а (стартовая инициализация). */\n function hydrate(bootstrap: AdminBootstrap): void {\n user.value = bootstrap.user\n permissions.value = bootstrap.permissions\n }\n\n /**\n * Проверить permission. Поддерживает wildcards:\n * - `*` — даёт доступ всем.\n * - `admin.users.*` — даёт доступ ко всем admin.users.X.\n */\n function hasPermission(key: string): boolean {\n if (permissions.value.includes('*')) return true\n if (permissions.value.includes(key)) return true\n return permissions.value.some((permission) => {\n if (!permission.endsWith('.*')) return false\n const prefix = permission.slice(0, -1) // 'admin.users.'\n return key.startsWith(prefix)\n })\n }\n\n function hasAnyPermission(keys: string[]): boolean {\n return keys.some(hasPermission)\n }\n\n function hasAllPermissions(keys: string[]): boolean {\n return keys.every(hasPermission)\n }\n\n /**\n * POST /auth/login. При 2FA-required envelope success:false +\n * errorKey:'two_factor_required' конвертируется interceptor'ом в ApiError;\n * мы ловим его, переходим в challenge-mode и возвращаем 'two_factor_required'.\n * На полный success — заполняем user и возвращаем 'authenticated'.\n * На реальную ошибку — throw'ит ApiError выше.\n */\n async function login(payload: LoginPayload): Promise<'authenticated' | 'two_factor_required'> {\n const client = getAdminClient()\n try {\n const result = await client.post<{ user?: AdminUser; permissions?: string[] }>(\n '/auth/login',\n payload,\n )\n if (result?.user) {\n user.value = result.user\n }\n if (Array.isArray(result?.permissions)) {\n permissions.value = result.permissions\n }\n pendingChallenge.value = null\n return 'authenticated'\n } catch (err) {\n if (err instanceof ApiError && err.errorKey === 'two_factor_required') {\n const challengeToken = (err.payload as Record<string, unknown>).challenge_token\n pendingChallenge.value = {\n challengeToken: typeof challengeToken === 'string' ? challengeToken : '',\n remember: payload.remember ?? false,\n }\n return 'two_factor_required'\n }\n throw err\n }\n }\n\n /** POST /auth/twoFactorChallenge. Завершает login. */\n async function twoFactorChallenge(code: string): Promise<void> {\n if (pendingChallenge.value === null) {\n throw new Error('No pending 2FA challenge')\n }\n const client = getAdminClient()\n const result = await client.post<{ user: AdminUser }>('/auth/twoFactorChallenge', {\n challenge_token: pendingChallenge.value.challengeToken,\n code,\n })\n user.value = result.user\n pendingChallenge.value = null\n }\n\n /** POST /auth/twoFactorRecovery. Использует recovery-код вместо TOTP. */\n async function twoFactorRecovery(recoveryCode: string): Promise<{ remaining: number }> {\n if (pendingChallenge.value === null) {\n throw new Error('No pending 2FA challenge')\n }\n const client = getAdminClient()\n const result = await client.post<{\n user: AdminUser\n recovery_codes_remaining: number\n }>('/auth/twoFactorRecovery', {\n challenge_token: pendingChallenge.value.challengeToken,\n recovery_code: recoveryCode,\n })\n user.value = result.user\n pendingChallenge.value = null\n return { remaining: result.recovery_codes_remaining }\n }\n\n /** Сбросить pending challenge — для возврата на login-форму. */\n function cancelChallenge(): void {\n pendingChallenge.value = null\n }\n\n /** POST /auth/logout. Чистит store. */\n async function logout(): Promise<void> {\n const client = getAdminClient()\n try {\n await client.post('/auth/logout')\n } finally {\n user.value = null\n permissions.value = []\n pendingChallenge.value = null\n }\n }\n\n return {\n // state\n user,\n permissions,\n pendingChallenge,\n // getters\n isAuthenticated,\n isChallengePending,\n // actions\n hydrate,\n hasPermission,\n hasAnyPermission,\n hasAllPermissions,\n login,\n twoFactorChallenge,\n twoFactorRecovery,\n cancelChallenge,\n logout,\n }\n})\n","<script setup lang=\"ts\">\n/**\n * UserMenu с avatar + dropdown через UidMenu из @dskripchenko/ui.\n * В trigger'е — UidAvatar (с инициалами либо src, размер sm).\n */\nimport { UidAvatar, UidMenu, UidMenuItem, UidMenuSeparator } from '@dskripchenko/ui'\nimport { useRouter } from 'vue-router'\nimport { useAuthStore } from '../../../stores/auth'\n\nconst auth = useAuthStore()\nconst router = useRouter()\n\nasync function logout(): Promise<void> {\n try {\n await auth.logout()\n } finally {\n await router.push({ name: 'admin.login' })\n }\n}\n\nfunction goProfile(): void {\n void router.push({ name: 'admin.profile' })\n}\n</script>\n\n<template>\n <UidMenu>\n <template #trigger>\n <button\n type=\"button\"\n class=\"admin-topbar__icon-btn admin-user-menu__trigger\"\n aria-label=\"Меню пользователя\"\n aria-haspopup=\"menu\"\n style=\"width: auto; padding: 0 4px; gap: 8px;\"\n >\n <UidAvatar\n :src=\"auth.user?.avatar ?? undefined\"\n :name=\"auth.user?.name ?? '?'\"\n :alt=\"auth.user?.name ?? 'User'\"\n size=\"sm\"\n />\n </button>\n </template>\n\n <UidMenuItem @click=\"goProfile\">Профиль</UidMenuItem>\n <UidMenuSeparator />\n <UidMenuItem variant=\"danger\" @click=\"logout\">Выйти</UidMenuItem>\n </UidMenu>\n</template>\n","<script setup lang=\"ts\">\n/**\n * Admin top bar поверх UID-токенов. Структура из docs/design_handoff_laravel_admin/\n * screens-shell.jsx (Topbar): collapse-toggle / breadcrumbs / spacer /\n * search-pill / bell / theme / locale / avatar.\n *\n * Slots:\n * - actions — host может вставить дополнительные actions перед widget'ами\n * - search — кастомизация ⌘K command-palette pill (по умолчанию — статичный\n * placeholder; host сверху поднимет UidCommand или свой)\n * - breadcrumbs — переопределить хлебные крошки\n */\nimport { computed } from 'vue'\nimport ThemeToggle from './widgets/ThemeToggle.vue'\nimport LocaleSwitcher from './widgets/LocaleSwitcher.vue'\nimport NotificationBell from './widgets/NotificationBell.vue'\nimport UserMenu from './widgets/UserMenu.vue'\n\ninterface Crumb {\n label: string\n to?: string | Record<string, unknown> | null\n}\n\ninterface Props {\n /** Хлебные крошки. Последний элемент — текущая страница (без to). */\n breadcrumbs?: Crumb[]\n /** Показывать кнопку collapse сайдбара (только в shell-layout'е). */\n showCollapseToggle?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n breadcrumbs: () => [],\n showCollapseToggle: true,\n})\n\nconst emit = defineEmits<{\n 'toggle-sidebar': []\n}>()\n\nconst lastIdx = computed(() => props.breadcrumbs.length - 1)\n</script>\n\n<template>\n <header class=\"admin-topbar\">\n <button\n v-if=\"showCollapseToggle\"\n type=\"button\"\n class=\"admin-topbar__icon-btn\"\n aria-label=\"Свернуть меню\"\n @click=\"emit('toggle-sidebar')\"\n >\n <span class=\"admin-topbar__icon\" data-icon=\"panel-left\" />\n </button>\n\n <div class=\"admin-topbar__breadcrumbs\">\n <slot name=\"breadcrumbs\">\n <template v-for=\"(crumb, idx) in breadcrumbs\" :key=\"idx\">\n <span v-if=\"idx > 0\" class=\"sep\">›</span>\n <component\n :is=\"crumb.to ? 'a' : 'span'\"\n :href=\"typeof crumb.to === 'string' ? crumb.to : undefined\"\n :class=\"idx === lastIdx ? 'cur' : ''\"\n >\n {{ crumb.label }}\n </component>\n </template>\n </slot>\n </div>\n\n <div class=\"admin-topbar__spacer\" />\n\n <slot name=\"search\">\n <div class=\"admin-topbar__search\" role=\"button\" tabindex=\"0\">\n <span class=\"admin-topbar__icon\" data-icon=\"search\" />\n <span>Поиск везде…</span>\n <kbd>⌘K</kbd>\n </div>\n </slot>\n\n <slot name=\"actions\" />\n <NotificationBell />\n <ThemeToggle />\n <LocaleSwitcher />\n <UserMenu />\n </header>\n</template>\n","/**\n * Menu store: дерево пунктов сайдбара.\n *\n * Источник — /system/menu (backend строит из ResourceRegistry/ScreenRegistry/\n * Settings + plugin-вкладов). Фронт фильтрует по permission'ам залогиненного\n * пользователя через auth-store.\n */\n\nimport { defineStore } from 'pinia'\nimport { computed, ref } from 'vue'\nimport { getAdminClient } from './registry'\nimport { useAuthStore } from './auth'\n\nexport interface MenuItem {\n /** Уникальный идентификатор. */\n key: string\n /** Текст пункта. */\n label: string\n /** Имя icon'а (опционально — host-проект сам резолвит icon-set). */\n icon?: string | null\n /** URL (внутренний router-target) либо null для группы. */\n url?: string | null\n /** Имя router-route (если задано — приоритет над url). */\n routeName?: string | null\n /** Бейдж справа (число unread, ярлык вроде \"new\"). */\n badge?: string | number | null\n /** Группа (header в sidebar). */\n group?: string | null\n /** Сортировочный вес. */\n order?: number\n /** Permission-keys; если заданы — пункт виден только при hasAnyPermission. */\n permissions?: string[]\n /** Вложенные пункты. */\n children?: MenuItem[]\n}\n\nexport interface MenuGroup {\n /** Заголовок группы (null = пункты без группы). */\n group: string | null\n items: MenuItem[]\n}\n\ninterface MenuResponse {\n items: MenuItem[]\n}\n\nexport const useMenuStore = defineStore('admin-menu', () => {\n const items = ref<MenuItem[]>([])\n const loading = ref(false)\n const error = ref<Error | null>(null)\n const isLoaded = ref(false)\n\n /**\n * Видимые пункты — отфильтрованные по permission'ам через auth-store.\n * Поддерживает wildcards (`*`, `admin.users.*`) через auth.hasAnyPermission.\n * Items без permissions считаются открытыми всем.\n */\n const visibleItems = computed<MenuItem[]>(() => {\n const auth = useAuthStore()\n const filter = (it: MenuItem): MenuItem | null => {\n if (Array.isArray(it.permissions) && it.permissions.length > 0) {\n if (!auth.hasAnyPermission(it.permissions)) return null\n }\n const filteredChildren = (it.children ?? [])\n .map(filter)\n .filter((c): c is MenuItem => c !== null)\n return { ...it, children: filteredChildren }\n }\n return items.value.map(filter).filter((i): i is MenuItem => i !== null)\n })\n\n /**\n * Группированный список — для рендера в sidebar по секциям.\n * Сортировка: order по возрастанию, затем label по алфавиту.\n */\n const groupedItems = computed<MenuGroup[]>(() => {\n const groups = new Map<string | null, MenuItem[]>()\n for (const item of visibleItems.value) {\n const groupKey = item.group ?? null\n if (!groups.has(groupKey)) groups.set(groupKey, [])\n groups.get(groupKey)!.push(item)\n }\n const result: MenuGroup[] = []\n for (const [group, list] of groups) {\n list.sort((a, b) => {\n const orderDiff = (a.order ?? 0) - (b.order ?? 0)\n if (orderDiff !== 0) return orderDiff\n return a.label.localeCompare(b.label)\n })\n result.push({ group, items: list })\n }\n return result\n })\n\n /** Загрузить меню с backend'а. Кэшируется до reset()/force=true. */\n async function load(force = false): Promise<MenuItem[]> {\n if (isLoaded.value && !force) return items.value\n loading.value = true\n error.value = null\n try {\n const client = getAdminClient()\n const response = await client.get<MenuResponse>('/system/menu')\n items.value = Array.isArray(response.items) ? response.items : []\n isLoaded.value = true\n return items.value\n } catch (err) {\n error.value = err instanceof Error ? err : new Error(String(err))\n throw err\n } finally {\n loading.value = false\n }\n }\n\n /** Установить items напрямую (например, host-проект построил из manifest'а). */\n function setItems(next: MenuItem[]): void {\n items.value = next\n isLoaded.value = true\n error.value = null\n }\n\n function reset(): void {\n items.value = []\n isLoaded.value = false\n error.value = null\n loading.value = false\n }\n\n return {\n items,\n loading,\n error,\n isLoaded,\n visibleItems,\n groupedItems,\n load,\n setItems,\n reset,\n }\n})\n","<script setup lang=\"ts\">\n/**\n * Sidebar admin-каркаса поверх UidSidebar/UidSidebarGroup/UidSidebarItem.\n *\n * Источник данных — useMenuStore (groupedItems, отфильтрованные по permission'ам\n * через auth.hasAnyPermission). UidSidebarItem поддерживает вложенный icon-slot\n * + active + badge — маппим прямо из MenuItem.\n *\n * Brand-row сверху + опциональный tenant-block + footer с версией/docs —\n * по эталону docs/design_handoff_laravel_admin/screens-shell.jsx (Sidebar).\n */\nimport { computed, h, type Component } from 'vue'\nimport { useRoute } from 'vue-router'\nimport { UidSidebar, UidSidebarGroup, UidSidebarItem } from '@dskripchenko/ui'\nimport { useMenuStore, type MenuItem } from '../../stores/menu'\n\ninterface Props {\n collapsed?: boolean\n /** Заголовок бренда. */\n brandName?: string\n /** Logo-mark (буква/инициалы) — отображается вместо логотипа. */\n brandMark?: string\n /** Тенант / workspace — опционально показывается под брендом. */\n tenant?: { label: string; name: string } | null\n /** Версия + ссылка на docs в footer'е. */\n version?: string | null\n docsUrl?: string | null\n}\n\nwithDefaults(defineProps<Props>(), {\n collapsed: false,\n brandName: 'Laravel Admin',\n brandMark: 'L',\n tenant: null,\n version: null,\n docsUrl: null,\n})\n\nconst menu = useMenuStore()\nconst route = useRoute()\n\nconst groups = computed(() => menu.groupedItems)\n\nfunction isActive(item: MenuItem): boolean {\n if (item.routeName && route.name === item.routeName) return true\n if (item.url && route.path === item.url) return true\n return false\n}\n\n/**\n * UidSidebarItem ожидает icon-slot. MenuItem.icon — строка (имя lucide-икoнки),\n * host-проект может зарегистрировать свой icon-resolver. Здесь возвращаем\n * простой <span data-icon> placeholder — host'у достаточно css-rule по\n * `[data-icon='users']` чтобы подставить SVG.\n */\nfunction iconSlot(name?: string | null): Component | undefined {\n if (!name) return undefined\n // Functional component возвращающий <span data-icon> placeholder.\n // Host-проект может перебить через css-rule по `[data-icon='users']`.\n return () => h('span', { class: 'admin-sidebar__icon', 'data-icon': name })\n}\n\n/** UidSidebarItem.to принимает string | object; routeName маппим через route-object. */\nfunction itemTarget(item: MenuItem): string | Record<string, unknown> | undefined {\n if (item.routeName) return { name: item.routeName }\n if (item.url) return item.url\n return undefined\n}\n</script>\n\n<template>\n <UidSidebar :collapsed=\"collapsed\">\n <template #header>\n <div class=\"admin-sidebar-brand\">\n <div class=\"admin-sidebar-brand__mark\">{{ brandMark }}</div>\n <div v-if=\"!collapsed\" class=\"admin-sidebar-brand__name\">{{ brandName }}</div>\n </div>\n <div v-if=\"tenant && !collapsed\" class=\"admin-sidebar-tenant\">\n <span>{{ tenant.label }}</span>\n <b>{{ tenant.name }}</b>\n </div>\n </template>\n\n <template #nav>\n <UidSidebarGroup\n v-for=\"(grp, idx) in groups\"\n :key=\"`grp-${idx}`\"\n :title=\"grp.group ?? undefined\"\n >\n <UidSidebarItem\n v-for=\"item in grp.items\"\n :key=\"item.key\"\n :to=\"itemTarget(item)\"\n :active=\"isActive(item)\"\n :badge=\"item.badge ?? undefined\"\n >\n <template v-if=\"item.icon\" #icon>\n <component :is=\"iconSlot(item.icon)\" />\n </template>\n {{ item.label }}\n </UidSidebarItem>\n </UidSidebarGroup>\n </template>\n\n <template v-if=\"version || docsUrl\" #footer>\n <div class=\"admin-sidebar-foot\">\n <span v-if=\"version\" class=\"admin-sidebar-foot__text\">{{ version }}</span>\n <a v-if=\"docsUrl\" :href=\"docsUrl\" class=\"admin-sidebar-foot__text admin-sidebar-foot__link\">\n Docs\n </a>\n </div>\n </template>\n </UidSidebar>\n</template>\n\n<style>\n.admin-sidebar-brand {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 14px 16px;\n border-bottom: 1px solid var(--uid-border-subtle);\n}\n.admin-sidebar-brand__mark {\n width: 28px;\n height: 28px;\n border-radius: 7px;\n flex: none;\n background: var(--uid-text-primary);\n color: var(--uid-surface-raised);\n display: grid;\n place-items: center;\n font-family: var(--uid-font-family-display);\n font-weight: var(--uid-font-weight-bold);\n font-size: 14px;\n letter-spacing: -0.02em;\n}\n.admin-sidebar-brand__name {\n font-family: var(--uid-font-family-display);\n font-size: 14px;\n font-weight: var(--uid-font-weight-semibold);\n letter-spacing: -0.01em;\n white-space: nowrap;\n overflow: hidden;\n color: var(--uid-text-primary);\n}\n.admin-sidebar-tenant {\n margin: 8px;\n display: flex;\n align-items: center;\n gap: 8px;\n height: 32px;\n padding: 0 8px;\n border: 1px solid var(--uid-border-subtle);\n border-radius: var(--uid-radius-md);\n font-size: var(--uid-font-size-xs);\n color: var(--uid-text-secondary);\n background: var(--uid-surface-base);\n}\n.admin-sidebar-tenant b { color: var(--uid-text-primary); font-weight: 500; }\n.admin-sidebar-foot {\n padding: 10px 16px;\n border-top: 1px solid var(--uid-border-subtle);\n display: flex;\n align-items: center;\n justify-content: space-between;\n font-size: 11px;\n color: var(--uid-text-tertiary);\n}\n.admin-sidebar-foot__link { cursor: pointer; }\n.admin-sidebar-foot__link:hover { color: var(--uid-text-primary); }\n\n.admin-sidebar__icon {\n width: 16px;\n height: 16px;\n display: inline-block;\n flex: none;\n color: currentColor;\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * Корневой layout admin-панели поверх UidSidebarLayout из @dskripchenko/ui.\n *\n * Slots:\n * - sidebar — обычно AdminSidebar (default)\n * - header — AdminTopBar (default)\n * - default — main-area (host рендерит <RouterView/>)\n *\n * v-model — boolean флаг сворачивания сайдбара (240→56 px, transition в uid).\n *\n * Impersonation: prop `impersonation` показывает 32-px amber бейдж над shell'ом\n * с кнопкой выхода — стиль из docs/design_handoff_laravel_admin/app.css:159\n * (.imp-banner). На <html> ставим data-impersonating='true' чтобы корректно\n * сместить sticky-элементы вниз.\n */\nimport { onBeforeUnmount, watch } from 'vue'\nimport { UidSidebarLayout } from '@dskripchenko/ui'\nimport AdminTopBar from './AdminTopBar.vue'\nimport AdminSidebar from './AdminSidebar.vue'\n\ninterface ImpersonationData {\n /** Имя того, в кого вошли. */\n asName: string\n}\n\ninterface Props {\n /** Сворачивание сайдбара. */\n collapsed?: boolean\n /** Если задано — показывает amber-banner и сдвигает контент. */\n impersonation?: ImpersonationData | null\n}\nconst props = withDefaults(defineProps<Props>(), {\n collapsed: false,\n impersonation: null,\n})\n\nconst emit = defineEmits<{\n 'update:collapsed': [value: boolean]\n 'exit-impersonation': []\n}>()\n\nfunction onCollapseChange(value: boolean): void {\n emit('update:collapsed', value)\n}\n\nfunction exitImpersonation(): void {\n emit('exit-impersonation')\n}\n\n// Маркер на <html> — для shell-classes которые делают paddding-top + sticky-offset.\nconst HTML_ATTR = 'data-admin-impersonating'\n\nwatch(\n () => props.impersonation,\n (val) => {\n if (typeof document === 'undefined') return\n if (val !== null) document.documentElement.setAttribute(HTML_ATTR, 'true')\n else document.documentElement.removeAttribute(HTML_ATTR)\n },\n { immediate: true },\n)\n\nonBeforeUnmount(() => {\n if (typeof document !== 'undefined') {\n document.documentElement.removeAttribute(HTML_ATTR)\n }\n})\n</script>\n\n<template>\n <div class=\"admin-shell-root\">\n <div v-if=\"impersonation\" class=\"admin-impersonation-banner\" role=\"status\">\n <span>\n Вы вошли как <b>{{ impersonation.asName }}</b> · режим имперсонации\n </span>\n <button\n type=\"button\"\n class=\"admin-impersonation-banner__exit\"\n @click=\"exitImpersonation\"\n >\n Выйти из режима\n </button>\n </div>\n <UidSidebarLayout\n :model-value=\"collapsed\"\n @update:model-value=\"onCollapseChange\"\n >\n <template #sidebar>\n <slot name=\"sidebar\">\n <AdminSidebar :collapsed=\"collapsed\" />\n </slot>\n </template>\n <template #header>\n <slot name=\"topbar\">\n <AdminTopBar @toggle-sidebar=\"onCollapseChange(!collapsed)\" />\n </slot>\n </template>\n <slot />\n </UidSidebarLayout>\n </div>\n</template>\n\n<style>\n.admin-shell-root[data-admin-impersonating='true'] {\n /* Sidebar/topbar sticky уже учтут `--admin-page-pad` и offset через CSS-классы. */\n padding-top: 32px;\n}\n:root[data-admin-impersonating='true'] {\n scroll-padding-top: 32px;\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * Root компонент SPA admin'а — рендерит router-view, оборачивая его в\n * AdminShell layout (TopBar + Sidebar + content) для аутентифицированных\n * роутов. Auth-роуты (login, 403, 404) и роуты с meta.fullscreen рендерятся\n * без shell.\n *\n * Используется createAdminApp() как root-component. Host'ы редко\n * переопределяют — обычно достаточно настроить отдельные pages через опции.\n */\nimport { computed } from 'vue'\nimport { useRoute } from 'vue-router'\nimport AdminShell from './shell/AdminShell.vue'\n\nconst route = useRoute()\n\nconst useShell = computed<boolean>(() => {\n if (route.meta?.fullscreen === true) return false\n // Auth-routes (login) рендерятся без shell.\n if (route.meta?.kind === 'auth') return false\n // Catch-all 404 без shell — чтобы пользователь не \"застрял\" в shell для невалидных URL.\n if (route.name === 'admin.notFound') return false\n return true\n})\n</script>\n\n<template>\n <AdminShell v-if=\"useShell\">\n <router-view />\n </AdminShell>\n <router-view v-else />\n</template>\n","/**\n * Manifest store: lazy-load JSON-манифеста админки + кеширование по version.\n *\n * Manifest содержит описание всех Resource'ов, Screen'ов, Settings'ов,\n * Plugin'ов. SPA загружает один раз на старте и переиспользует.\n *\n * ETag-based 304 Not Modified backend-side — фронт ничего особенного не\n * делает (axios + browser handle If-None-Match). Свежий version записывается\n * в lastVersion для cheap-сравнения.\n */\n\nimport { defineStore } from 'pinia'\nimport { computed, ref } from 'vue'\nimport { getAdminClient } from './registry'\n\n/**\n * Узел manifest'а с обязательным `type`. Совместим с LayoutNode/FieldNode/\n * InfolistNode — позволяет передавать массив прямо в renderer без cast'а.\n */\nexport interface ManifestNode extends Record<string, unknown> {\n type: string\n}\n\nexport interface ManifestResourceMeta {\n slug: string\n label: string\n icon?: string\n group?: string | null\n permissions: Record<string, string>\n fields: ManifestNode[]\n columns: ManifestNode[]\n filters: ManifestNode[]\n actions: ManifestNode[]\n searchable: string[]\n with: string[]\n features: Record<string, unknown>\n screens?: Record<string, unknown>\n}\n\nexport interface ManifestScreenMeta {\n slug: string\n name: string\n description: string | null\n permission: string[] | string | null\n}\n\nexport interface ManifestSettingsMeta {\n kind: 'settings'\n slug: string\n label: string\n permissions: Record<string, string>\n fields: ManifestNode[]\n}\n\nexport interface AdminManifest {\n version: string\n locale: string\n resources: ManifestResourceMeta[]\n screens: ManifestScreenMeta[]\n settings: ManifestSettingsMeta[]\n dashboards: unknown[]\n plugins: string[]\n permissions: unknown[]\n}\n\nexport const useManifestStore = defineStore('admin-manifest', () => {\n const manifest = ref<AdminManifest | null>(null)\n const loading = ref(false)\n const error = ref<Error | null>(null)\n\n const isLoaded = computed(() => manifest.value !== null)\n const version = computed(() => manifest.value?.version ?? null)\n const resources = computed(() => manifest.value?.resources ?? [])\n const screens = computed(() => manifest.value?.screens ?? [])\n const settings = computed(() => manifest.value?.settings ?? [])\n const plugins = computed(() => manifest.value?.plugins ?? [])\n\n function getResource(slug: string): ManifestResourceMeta | null {\n return resources.value.find((r) => r.slug === slug) ?? null\n }\n\n function getScreen(slug: string): ManifestScreenMeta | null {\n return screens.value.find((s) => s.slug === slug) ?? null\n }\n\n function getSettings(slug: string): ManifestSettingsMeta | null {\n return settings.value.find((s) => s.slug === slug) ?? null\n }\n\n /**\n * Загрузить manifest. Если уже загружен — возвращает cached.\n * Force=true принудительно обновит с сервера.\n */\n async function load(force = false): Promise<AdminManifest> {\n if (manifest.value !== null && !force) {\n return manifest.value\n }\n\n loading.value = true\n error.value = null\n try {\n const client = getAdminClient()\n const result = await client.get<AdminManifest>('/system/manifest')\n manifest.value = result\n return result\n } catch (err) {\n error.value = err instanceof Error ? err : new Error(String(err))\n throw err\n } finally {\n loading.value = false\n }\n }\n\n function reset(): void {\n manifest.value = null\n error.value = null\n loading.value = false\n }\n\n return {\n // state\n manifest,\n loading,\n error,\n // getters\n isLoaded,\n version,\n resources,\n screens,\n settings,\n plugins,\n // actions\n getResource,\n getScreen,\n getSettings,\n load,\n reset,\n }\n})\n","<script setup lang=\"ts\">\n/**\n * Default home-страница admin'а. Host'ы перебивают через\n * createAdminApp({ pages: { home: MyHome } }).\n *\n * Показывает welcome-карточку + список зарегистрированных Resource'ов из\n * manifest store (быстрая навигация для свежепоставленной админки).\n */\nimport { computed } from 'vue'\nimport { useRouter } from 'vue-router'\nimport { UidCard } from '@dskripchenko/ui'\nimport { useManifestStore } from '../stores/manifest'\nimport { useAuthStore } from '../stores/auth'\n\nconst manifest = useManifestStore()\nconst auth = useAuthStore()\nconst router = useRouter()\n\nconst userName = computed(() => auth.user?.name ?? '')\nconst resources = computed(() => manifest.manifest?.resources ?? [])\n</script>\n\n<template>\n <div class=\"admin-home\">\n <UidCard padding=\"lg\" class=\"admin-home__hero\">\n <h1 class=\"admin-home__title\">Добро пожаловать{{ userName ? ', ' + userName : '' }}</h1>\n <p class=\"admin-home__lead\">\n Админ-панель готова. Воспользуйтесь сайдбаром или переходите к ресурсам ниже.\n </p>\n </UidCard>\n\n <section v-if=\"resources.length\" class=\"admin-home__resources\">\n <h2 class=\"admin-home__heading\">Ресурсы</h2>\n <ul class=\"admin-home__grid\">\n <li v-for=\"r in resources\" :key=\"r.slug\">\n <button\n type=\"button\"\n class=\"admin-home__card\"\n @click=\"router.push({ name: `admin.resource.${r.slug}.index` })\"\n >\n <span class=\"admin-home__card-label\">{{ r.label }}</span>\n <span class=\"admin-home__card-slug\">{{ r.slug }}</span>\n </button>\n </li>\n </ul>\n </section>\n </div>\n</template>\n\n<style>\n.admin-home {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-lg);\n padding: var(--uid-space-md);\n}\n.admin-home__title {\n font-size: var(--uid-font-size-2xl);\n font-weight: var(--uid-font-weight-bold);\n margin: 0 0 var(--uid-space-sm);\n}\n.admin-home__lead {\n color: var(--uid-text-secondary);\n margin: 0;\n}\n.admin-home__heading {\n font-size: var(--uid-font-size-lg);\n font-weight: var(--uid-font-weight-semibold);\n margin: 0 0 var(--uid-space-sm);\n}\n.admin-home__grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));\n gap: var(--uid-space-sm);\n list-style: none;\n padding: 0;\n margin: 0;\n}\n.admin-home__card {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-2xs);\n padding: var(--uid-space-md);\n border: 1px solid var(--uid-border-subtle);\n border-radius: var(--uid-radius-md);\n background: var(--uid-surface-raised);\n text-align: left;\n cursor: pointer;\n transition: border-color 0.15s ease, transform 0.15s ease;\n}\n.admin-home__card:hover {\n border-color: var(--uid-accent);\n transform: translateY(-1px);\n}\n.admin-home__card-label {\n font-weight: var(--uid-font-weight-medium);\n}\n.admin-home__card-slug {\n font-size: var(--uid-font-size-xs);\n color: var(--uid-text-tertiary);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * 403 fallback. Host может переопределить через createAdminApp({ pages: { forbidden } }).\n */\nimport { UidCard, UidButton } from '@dskripchenko/ui'\nimport { useRouter } from 'vue-router'\n\nconst router = useRouter()\n</script>\n\n<template>\n <div class=\"admin-status-page\">\n <UidCard padding=\"lg\" class=\"admin-status-page__card\">\n <h1 class=\"admin-status-page__code\">403</h1>\n <p class=\"admin-status-page__message\">Доступ запрещён.</p>\n <UidButton variant=\"ghost\" @click=\"router.replace({ name: 'admin.home' })\">\n На главную\n </UidButton>\n </UidCard>\n </div>\n</template>\n\n<style>\n.admin-status-page {\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 60vh;\n padding: var(--uid-space-lg);\n}\n.admin-status-page__card {\n text-align: center;\n max-width: 480px;\n}\n.admin-status-page__code {\n font-size: 64px;\n font-weight: var(--uid-font-weight-bold);\n margin: 0 0 var(--uid-space-sm);\n color: var(--uid-text-secondary);\n}\n.admin-status-page__message {\n margin: 0 0 var(--uid-space-md);\n color: var(--uid-text-secondary);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * 404 fallback. Host может переопределить через createAdminApp({ pages: { notFound } }).\n */\nimport { UidCard, UidButton } from '@dskripchenko/ui'\nimport { useRouter } from 'vue-router'\n\nconst router = useRouter()\n</script>\n\n<template>\n <div class=\"admin-status-page\">\n <UidCard padding=\"lg\" class=\"admin-status-page__card\">\n <h1 class=\"admin-status-page__code\">404</h1>\n <p class=\"admin-status-page__message\">Страница не найдена.</p>\n <UidButton variant=\"ghost\" @click=\"router.replace({ name: 'admin.home' })\">\n На главную\n </UidButton>\n </UidCard>\n </div>\n</template>\n","<script setup lang=\"ts\">\n/**\n * Default страница для admin.settings.{slug} роутов.\n *\n * Загружает settings-meta из manifest'а и рендерит fields через LayoutRenderer\n * с form-state поверх SettingsApiClient. Host'ы переопределяют через\n * createAdminApp({ pages: { settings: MySettings } }) если нужна более\n * специфичная UX (например, side-tab навигация по Settings-классам).\n */\nimport { computed } from 'vue'\nimport { useRoute } from 'vue-router'\nimport { UidCard } from '@dskripchenko/ui'\nimport { useManifestStore } from '../stores/manifest'\n\nconst route = useRoute()\nconst manifest = useManifestStore()\n\nconst slug = computed(() => String(route.params.slug ?? ''))\nconst meta = computed(() => manifest.manifest?.settings?.find((s) => s.slug === slug.value) ?? null)\n</script>\n\n<template>\n <div class=\"admin-settings-page\">\n <UidCard padding=\"lg\">\n <h1 class=\"admin-settings-page__title\">{{ meta?.label ?? slug }}</h1>\n <p v-if=\"!meta\" class=\"admin-settings-page__hint\">\n Settings «{{ slug }}» не найдено в manifest'е.\n </p>\n <pre v-else class=\"admin-settings-page__debug\">{{ JSON.stringify(meta.fields, null, 2) }}</pre>\n </UidCard>\n </div>\n</template>\n\n<style>\n.admin-settings-page {\n padding: var(--uid-space-md);\n}\n.admin-settings-page__title {\n font-size: var(--uid-font-size-xl);\n font-weight: var(--uid-font-weight-semibold);\n margin: 0 0 var(--uid-space-sm);\n}\n.admin-settings-page__debug {\n background: var(--uid-surface-raised);\n border: 1px solid var(--uid-border-subtle);\n padding: var(--uid-space-sm);\n border-radius: var(--uid-radius-sm);\n font-family: var(--uid-font-mono);\n font-size: var(--uid-font-size-xs);\n overflow: auto;\n max-height: 60vh;\n}\n.admin-settings-page__hint {\n color: var(--uid-text-secondary);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * Заглушка для произвольных Screen-роутов из manifest'а.\n * Host'ы переопределяют через createAdminApp({ pages: { screen: MyScreen } })\n * и кастомным компонентом рендерят `route.params.slug` через любой template.\n */\nimport { computed } from 'vue'\nimport { useRoute } from 'vue-router'\nimport { UidCard } from '@dskripchenko/ui'\n\nconst route = useRoute()\nconst slug = computed(() => String(route.params.slug ?? ''))\nconst title = computed(() => String(route.meta?.title ?? slug.value))\n</script>\n\n<template>\n <div class=\"admin-status-page\">\n <UidCard padding=\"lg\" class=\"admin-status-page__card\">\n <h1 class=\"admin-status-page__title\">{{ title }}</h1>\n <p class=\"admin-status-page__hint\">\n Это заглушка для screen «{{ slug }}». Передайте свой компонент через\n <code>createAdminApp({{ '{' }} pages: {{ '{' }} screen: MyScreen {{ '}' }} {{ '}' }})</code>.\n </p>\n </UidCard>\n </div>\n</template>\n\n<style>\n.admin-status-page__title {\n font-size: var(--uid-font-size-xl);\n font-weight: var(--uid-font-weight-semibold);\n margin: 0 0 var(--uid-space-sm);\n}\n.admin-status-page__hint {\n margin: 0;\n color: var(--uid-text-secondary);\n font-size: var(--uid-font-size-sm);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * LoginForm — email/password/remember поверх UidInput/UidButton/UidCheckbox/\n * UidAlert. Архитектура auth-card по docs/design_handoff_laravel_admin/\n * screens-secondary.jsx (LoginScreen).\n */\nimport { computed, ref } from 'vue'\nimport { UidAlert, UidButton, UidCheckbox, UidInput } from '@dskripchenko/ui'\nimport { useAuthStore } from '../../stores/auth'\nimport { ApiError, NetworkError, ValidationError } from '../../api/errors'\n\ninterface Props {\n /** URL «Забыли пароль?» — если задан, показывается link справа от remember. */\n forgotUrl?: string | null\n /** Текст SSO-ссылки или null чтобы скрыть. */\n ssoLinkLabel?: string | null\n ssoUrl?: string | null\n}\n\nwithDefaults(defineProps<Props>(), {\n forgotUrl: null,\n ssoLinkLabel: null,\n ssoUrl: null,\n})\n\nconst emit = defineEmits<{\n success: [result: 'authenticated' | 'two_factor_required']\n}>()\n\nconst auth = useAuthStore()\n\nconst email = ref('')\nconst password = ref('')\nconst remember = ref(false)\n\nconst submitting = ref(false)\nconst generalError = ref<string | null>(null)\nconst fieldErrors = ref<Record<string, string[]>>({})\n\nconst emailError = computed<string | undefined>(() => fieldErrors.value.email?.[0])\nconst passwordError = computed<string | undefined>(() => fieldErrors.value.password?.[0])\n\nasync function submit(): Promise<void> {\n if (submitting.value) return\n submitting.value = true\n generalError.value = null\n fieldErrors.value = {}\n\n try {\n const result = await auth.login({\n email: email.value,\n password: password.value,\n remember: remember.value,\n })\n emit('success', result)\n } catch (err) {\n if (err instanceof ValidationError) {\n fieldErrors.value = err.fields\n generalError.value = err.firstFieldMessage()\n } else if (err instanceof NetworkError) {\n generalError.value = 'Нет соединения с сервером'\n } else if (err instanceof ApiError) {\n generalError.value = err.message || 'Не удалось войти'\n } else {\n generalError.value = (err as Error).message\n }\n } finally {\n submitting.value = false\n }\n}\n</script>\n\n<template>\n <form class=\"admin-auth-card__bd\" novalidate @submit.prevent=\"submit\">\n <UidAlert\n v-if=\"generalError\"\n variant=\"danger\"\n class=\"admin-auth-card__alert\"\n role=\"alert\"\n >\n {{ generalError }}\n </UidAlert>\n\n <UidInput\n v-model=\"email\"\n type=\"email\"\n label=\"Email\"\n placeholder=\"you@company.com\"\n autocomplete=\"username\"\n :required=\"true\"\n :disabled=\"submitting\"\n :error=\"emailError\"\n name=\"email\"\n />\n\n <UidInput\n v-model=\"password\"\n type=\"password\"\n label=\"Пароль\"\n autocomplete=\"current-password\"\n :required=\"true\"\n :disabled=\"submitting\"\n :error=\"passwordError\"\n name=\"password\"\n />\n\n <div class=\"admin-auth-card__row\">\n <UidCheckbox v-model=\"remember\" :disabled=\"submitting\">\n Запомнить меня\n </UidCheckbox>\n <a v-if=\"forgotUrl\" :href=\"forgotUrl\" class=\"admin-auth-card__link\">\n Забыли пароль?\n </a>\n </div>\n\n <UidButton\n type=\"submit\"\n variant=\"primary\"\n size=\"lg\"\n :loading=\"submitting\"\n :disabled=\"submitting\"\n >\n {{ submitting ? 'Вход…' : 'Войти' }}\n </UidButton>\n\n <div\n v-if=\"ssoLinkLabel && ssoUrl\"\n style=\"text-align: center; font-size: var(--uid-font-size-xs); color: var(--uid-text-secondary); padding-top: 4px;\"\n >\n или войдите через\n <a :href=\"ssoUrl\" class=\"admin-auth-card__link\">{{ ssoLinkLabel }}</a>\n </div>\n </form>\n</template>\n","<script setup lang=\"ts\">\n/**\n * 2FA-форма: 6-cell mono TOTP-input + alt recovery-code.\n *\n * Эталон — docs/design_handoff_laravel_admin/screens-secondary.jsx (TwoFactor):\n * 6 input'ов 44×52, IBM Plex Mono 22px, при заполнении одного — фокус\n * автопереходит на следующий, paste-event раскладывает 6 цифр сразу.\n */\nimport { computed, nextTick, ref } from 'vue'\nimport { UidAlert, UidButton, UidInput } from '@dskripchenko/ui'\nimport { useAuthStore } from '../../stores/auth'\nimport { ApiError, NetworkError, ValidationError } from '../../api/errors'\n\nconst emit = defineEmits<{\n success: []\n cancel: []\n}>()\n\nconst auth = useAuthStore()\n\nconst mode = ref<'totp' | 'recovery'>('totp')\nconst cells = ref<string[]>(['', '', '', '', '', ''])\nconst recoveryCode = ref('')\nconst cellRefs = ref<HTMLInputElement[]>([])\n\nconst submitting = ref(false)\nconst generalError = ref<string | null>(null)\nconst remaining = ref<number | null>(null)\n\nconst totpCode = computed(() => cells.value.join(''))\nconst isValid = computed(() => {\n if (mode.value === 'totp') return totpCode.value.length === 6\n return recoveryCode.value.trim().length > 0\n})\n\nfunction setCellRef(idx: number, el: Element | null): void {\n if (el instanceof HTMLInputElement) cellRefs.value[idx] = el\n}\n\nfunction onCellInput(idx: number, event: Event): void {\n const target = event.target as HTMLInputElement\n // Только цифры; обрезаем до 1 символа.\n const digit = target.value.replace(/\\D/g, '').slice(-1)\n cells.value[idx] = digit\n target.value = digit\n if (digit && idx < cells.value.length - 1) {\n void nextTick(() => cellRefs.value[idx + 1]?.focus())\n }\n if (totpCode.value.length === cells.value.length) {\n void submit()\n }\n}\n\nfunction onCellKeydown(idx: number, event: KeyboardEvent): void {\n if (event.key === 'Backspace' && !cells.value[idx] && idx > 0) {\n void nextTick(() => cellRefs.value[idx - 1]?.focus())\n } else if (event.key === 'ArrowLeft' && idx > 0) {\n cellRefs.value[idx - 1]?.focus()\n event.preventDefault()\n } else if (event.key === 'ArrowRight' && idx < cells.value.length - 1) {\n cellRefs.value[idx + 1]?.focus()\n event.preventDefault()\n }\n}\n\nfunction onPaste(event: ClipboardEvent): void {\n const pasted = event.clipboardData?.getData('text') ?? ''\n const digits = pasted.replace(/\\D/g, '').slice(0, cells.value.length)\n if (digits.length === 0) return\n event.preventDefault()\n for (let i = 0; i < cells.value.length; i++) {\n cells.value[i] = digits[i] ?? ''\n }\n void nextTick(() => {\n cellRefs.value[Math.min(digits.length, cells.value.length - 1)]?.focus()\n if (digits.length === cells.value.length) void submit()\n })\n}\n\nasync function submit(): Promise<void> {\n if (submitting.value || !isValid.value) return\n submitting.value = true\n generalError.value = null\n\n try {\n if (mode.value === 'totp') {\n await auth.twoFactorChallenge(totpCode.value)\n } else {\n const res = await auth.twoFactorRecovery(recoveryCode.value.trim())\n remaining.value = res.remaining\n }\n emit('success')\n } catch (err) {\n if (err instanceof ValidationError) {\n generalError.value = err.firstFieldMessage() ?? 'Неверный код'\n } else if (err instanceof NetworkError) {\n generalError.value = 'Нет соединения с сервером'\n } else if (err instanceof ApiError) {\n generalError.value = err.message || 'Не удалось проверить код'\n } else {\n generalError.value = (err as Error).message\n }\n } finally {\n submitting.value = false\n }\n}\n\nfunction cancel(): void {\n auth.cancelChallenge()\n emit('cancel')\n}\n\nfunction switchMode(): void {\n mode.value = mode.value === 'totp' ? 'recovery' : 'totp'\n generalError.value = null\n}\n</script>\n\n<template>\n <form class=\"admin-auth-card__bd\" novalidate @submit.prevent=\"submit\">\n <UidAlert\n v-if=\"generalError\"\n variant=\"danger\"\n class=\"admin-auth-card__alert\"\n role=\"alert\"\n >\n {{ generalError }}\n </UidAlert>\n <UidAlert\n v-if=\"remaining !== null\"\n variant=\"info\"\n class=\"admin-auth-card__alert\"\n role=\"status\"\n >\n Использован recovery-код. Осталось: {{ remaining }}\n </UidAlert>\n\n <div v-if=\"mode === 'totp'\" class=\"admin-code-input\" @paste=\"onPaste\">\n <input\n v-for=\"(_, idx) in cells\"\n :key=\"idx\"\n :ref=\"(el) => setCellRef(idx, el as Element | null)\"\n :value=\"cells[idx]\"\n type=\"text\"\n inputmode=\"numeric\"\n autocomplete=\"one-time-code\"\n maxlength=\"1\"\n :disabled=\"submitting\"\n :aria-label=\"`Цифра ${idx + 1}`\"\n @input=\"onCellInput(idx, $event)\"\n @keydown=\"onCellKeydown(idx, $event)\"\n />\n </div>\n\n <UidInput\n v-else\n v-model=\"recoveryCode\"\n type=\"text\"\n label=\"Recovery-код\"\n autocomplete=\"one-time-code\"\n :disabled=\"submitting\"\n name=\"recovery-code\"\n />\n\n <UidButton\n type=\"submit\"\n variant=\"primary\"\n size=\"lg\"\n :loading=\"submitting\"\n :disabled=\"submitting || !isValid\"\n >\n {{ submitting ? 'Проверка…' : 'Подтвердить' }}\n </UidButton>\n\n <div class=\"admin-auth-card__row\">\n <button type=\"button\" class=\"admin-auth-card__link\" @click=\"switchMode\">\n <template v-if=\"mode === 'totp'\">Использовать recovery-код</template>\n <template v-else>Вернуться к коду из приложения</template>\n </button>\n <button type=\"button\" class=\"admin-auth-card__link\" @click=\"cancel\">\n Отмена\n </button>\n </div>\n </form>\n</template>\n","<script setup lang=\"ts\">\n/**\n * LoginPage поверх UID design handoff: centered auth-card 400/440 px на\n * `--uid-surface-base`-фоне с corner-actions (theme + locale toggles).\n *\n * Композиция: LoginForm либо TwoFactorForm в зависимости от\n * auth.isChallengePending. Редирект на main завязан на watch\n * (auth.isAuthenticated) — это переживает unmount форм при смене ветки.\n *\n * `?redirect`-query учитывает только относительные пути (защита от\n * open-redirect).\n */\nimport { onMounted, watch } from 'vue'\nimport { useRouter, useRoute } from 'vue-router'\nimport { UidCard } from '@dskripchenko/ui'\nimport { useAuthStore } from '../../stores/auth'\nimport LoginForm from './LoginForm.vue'\nimport TwoFactorForm from './TwoFactorForm.vue'\nimport ThemeToggle from '../shell/widgets/ThemeToggle.vue'\nimport LocaleSwitcher from '../shell/widgets/LocaleSwitcher.vue'\n\ninterface Props {\n brandName?: string\n brandMark?: string\n brandLogo?: string | null\n homeRouteName?: string\n redirectQueryKey?: string\n /** URL «Забыли пароль?» — пробрасывается в LoginForm. */\n forgotUrl?: string | null\n /** SSO-link (label + url) — пробрасывается в LoginForm. */\n ssoLinkLabel?: string | null\n ssoUrl?: string | null\n /** Показывать ли theme/locale toggle'ы в углу. */\n showCornerActions?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n brandName: 'Laravel Admin',\n brandMark: 'L',\n brandLogo: null,\n homeRouteName: 'admin.home',\n redirectQueryKey: 'redirect',\n forgotUrl: null,\n ssoLinkLabel: null,\n ssoUrl: null,\n showCornerActions: true,\n})\n\nconst auth = useAuthStore()\nconst router = useRouter()\nconst route = useRoute()\n\nasync function redirectToHome(): Promise<void> {\n const target = route.query[props.redirectQueryKey]\n if (typeof target === 'string' && target.length > 0 && target.startsWith('/')) {\n await router.push(target)\n return\n }\n await router.push({ name: props.homeRouteName })\n}\n\nwatch(\n () => auth.isAuthenticated,\n (next) => {\n if (next) void redirectToHome()\n },\n)\nonMounted(() => {\n if (auth.isAuthenticated) void redirectToHome()\n})\n</script>\n\n<template>\n <div class=\"admin-auth-page\">\n <div v-if=\"showCornerActions\" class=\"admin-auth-page__corner\">\n <ThemeToggle />\n <LocaleSwitcher />\n </div>\n\n <UidCard\n :class=\"['admin-auth-card', auth.isChallengePending ? 'admin-auth-card--wide' : '']\"\n padding=\"none\"\n >\n <div class=\"admin-auth-card__hd\">\n <div\n :class=\"['admin-auth-card__logo', auth.isChallengePending ? 'admin-auth-card__logo--accent' : '']\"\n >\n <img v-if=\"brandLogo && !auth.isChallengePending\" :src=\"brandLogo\" :alt=\"brandName\" />\n <span v-else-if=\"auth.isChallengePending\" aria-hidden=\"true\">🛡</span>\n <span v-else>{{ brandMark }}</span>\n </div>\n <div class=\"admin-auth-card__title\">\n <template v-if=\"auth.isChallengePending\">Двухфакторная проверка</template>\n <template v-else>{{ brandName }}</template>\n </div>\n <div class=\"admin-auth-card__sub\">\n <template v-if=\"auth.isChallengePending\">\n Введите 6-значный код из приложения-аутентификатора\n </template>\n <template v-else>Войдите, чтобы продолжить работу</template>\n </div>\n </div>\n\n <TwoFactorForm\n v-if=\"auth.isChallengePending\"\n @success=\"() => undefined\"\n @cancel=\"() => undefined\"\n />\n <LoginForm\n v-else\n :forgot-url=\"forgotUrl\"\n :sso-link-label=\"ssoLinkLabel\"\n :sso-url=\"ssoUrl\"\n @success=\"() => undefined\"\n />\n </UidCard>\n </div>\n</template>\n","/**\n * useResourceIndexStore — list-page state для одного Resource'а.\n *\n * Поддерживает:\n * - items + pagination meta из envelope payload\n * - filters (typed Record<string, unknown>) — отправляются как query\n * - sort (key + direction)\n * - selection (Set<row-id>) для bulk-actions; tri-state header-checkbox\n * - loading/error состояния (UI рендерит UidSkeleton/UidErrorState)\n *\n * Один store-instance переиспользуется на разных Resource-страницах через\n * `useResourceIndexStore(slug)` с явным `setSlug` — это даёт чистый reset\n * между resource'ами.\n */\n\nimport { defineStore } from 'pinia'\nimport { computed, ref } from 'vue'\nimport { getAdminClient } from './registry'\n\nexport interface IndexMeta {\n page: number\n per_page: number\n total: number\n last_page: number\n}\n\nexport interface IndexParams {\n page?: number\n per_page?: number\n sort?: string | null\n direction?: 'asc' | 'desc' | null\n search?: string | null\n filters?: Record<string, unknown>\n}\n\ninterface ListResponse {\n data: Array<Record<string, unknown>>\n meta: IndexMeta\n}\n\nconst DEFAULT_META: IndexMeta = { page: 1, per_page: 20, total: 0, last_page: 1 }\n\nexport const useResourceIndexStore = defineStore('admin-resource-index', () => {\n /** Текущий resource-slug (urls/users/posts/etc). */\n const slug = ref<string | null>(null)\n\n const items = ref<Array<Record<string, unknown>>>([])\n const meta = ref<IndexMeta>({ ...DEFAULT_META })\n\n const loading = ref(false)\n const error = ref<Error | null>(null)\n\n const search = ref<string>('')\n const filters = ref<Record<string, unknown>>({})\n const sortKey = ref<string | null>(null)\n const sortDirection = ref<'asc' | 'desc'>('asc')\n\n /** Set ID-шников выбранных строк (bulk-actions). */\n const selection = ref<Set<string | number>>(new Set())\n\n const isEmpty = computed(() => !loading.value && error.value === null && items.value.length === 0)\n const selectedCount = computed(() => selection.value.size)\n const hasSelection = computed(() => selection.value.size > 0)\n const hasError = computed(() => error.value !== null)\n\n /** Tri-state: 'all' / 'mixed' / 'none' для header-checkbox. */\n const selectionState = computed<'all' | 'mixed' | 'none'>(() => {\n if (selection.value.size === 0) return 'none'\n if (items.value.length === 0) return 'none'\n const allSelected = items.value.every((row) => selection.value.has(rowId(row)))\n return allSelected ? 'all' : 'mixed'\n })\n\n /** Извлекает ID строки. По умолчанию — поле `id`; host может переопределить. */\n function rowId(row: Record<string, unknown>): string | number {\n return (row.id ?? row.key ?? '') as string | number\n }\n\n /** Сменить ресурс — сброс state'а. */\n function setSlug(next: string | null): void {\n if (slug.value === next) return\n slug.value = next\n reset()\n }\n\n function reset(): void {\n items.value = []\n meta.value = { ...DEFAULT_META }\n loading.value = false\n error.value = null\n search.value = ''\n filters.value = {}\n sortKey.value = null\n sortDirection.value = 'asc'\n selection.value = new Set()\n }\n\n function buildParams(override: IndexParams = {}): Record<string, unknown> {\n const params: Record<string, unknown> = {\n page: override.page ?? meta.value.page,\n per_page: override.per_page ?? meta.value.per_page,\n }\n const ss = override.search ?? search.value\n if (ss) params.search = ss\n\n const sk = override.sort ?? sortKey.value\n if (sk) {\n params.sort = sk\n params.direction = override.direction ?? sortDirection.value\n }\n\n const f = override.filters ?? filters.value\n for (const [k, v] of Object.entries(f)) {\n if (v === null || v === undefined || v === '') continue\n params[`filter[${k}]`] = Array.isArray(v) ? v.join(',') : String(v)\n }\n\n return params\n }\n\n /** Загрузить страницу. Без аргументов — текущие фильтры/сортировка/page. */\n async function load(override: IndexParams = {}): Promise<void> {\n if (!slug.value) {\n throw new Error('useResourceIndexStore.load() called before setSlug()')\n }\n loading.value = true\n error.value = null\n try {\n const client = getAdminClient()\n const params = buildParams(override)\n const res = await client.get<ListResponse>(`/resources/${slug.value}/list`, { params })\n items.value = res.data\n meta.value = res.meta\n } catch (err) {\n error.value = err instanceof Error ? err : new Error(String(err))\n throw err\n } finally {\n loading.value = false\n }\n }\n\n async function setSearch(value: string): Promise<void> {\n search.value = value\n meta.value.page = 1\n await load()\n }\n\n async function setFilter(key: string, value: unknown): Promise<void> {\n if (value === null || value === undefined || value === '') {\n delete filters.value[key]\n } else {\n filters.value[key] = value\n }\n meta.value.page = 1\n await load()\n }\n\n async function clearFilters(): Promise<void> {\n filters.value = {}\n meta.value.page = 1\n await load()\n }\n\n async function setSort(key: string, direction: 'asc' | 'desc' = 'asc'): Promise<void> {\n sortKey.value = key\n sortDirection.value = direction\n await load()\n }\n\n async function toggleSort(key: string): Promise<void> {\n if (sortKey.value === key) {\n sortDirection.value = sortDirection.value === 'asc' ? 'desc' : 'asc'\n } else {\n sortKey.value = key\n sortDirection.value = 'asc'\n }\n await load()\n }\n\n async function setPage(page: number): Promise<void> {\n meta.value.page = page\n await load()\n }\n\n function toggleRow(id: string | number): void {\n const next = new Set(selection.value)\n if (next.has(id)) next.delete(id)\n else next.add(id)\n selection.value = next\n }\n\n /** Toggle: выделить все на странице если что-то не выбрано, иначе очистить. */\n function toggleAllOnPage(): void {\n if (selectionState.value === 'all') {\n selection.value = new Set()\n return\n }\n const next = new Set(selection.value)\n for (const row of items.value) next.add(rowId(row))\n selection.value = next\n }\n\n function clearSelection(): void {\n selection.value = new Set()\n }\n\n /** Проверить выбор конкретной строки. */\n function isSelected(id: string | number): boolean {\n return selection.value.has(id)\n }\n\n return {\n // state\n slug,\n items,\n meta,\n loading,\n error,\n search,\n filters,\n sortKey,\n sortDirection,\n selection,\n // getters\n isEmpty,\n hasError,\n hasSelection,\n selectedCount,\n selectionState,\n // actions\n setSlug,\n reset,\n load,\n setSearch,\n setFilter,\n clearFilters,\n setSort,\n toggleSort,\n setPage,\n toggleRow,\n toggleAllOnPage,\n clearSelection,\n isSelected,\n rowId,\n }\n})\n","<script setup lang=\"ts\">\n/**\n * ResourceIndexPage — list-screen для одного Resource'а из manifest'а.\n * Архитектура по docs/design_handoff_laravel_admin/screens-shell.jsx (Resource List).\n *\n * Композиция:\n * - Page header (title + count + actions cluster)\n * - Filter bar с search + chips\n * - Bulk toolbar (заменяет filter bar при selectedCount > 0)\n * - UidTable с manifest.columns\n * - States: loading (UidSkeleton ×8) / empty (UidEmptyState) / error (UidErrorState)\n * - UidPagination внизу\n *\n * Host рендерит page через router. resource-slug приходит из props (либо\n * из route.params).\n */\nimport { computed, onMounted, watch } from 'vue'\nimport {\n UidButton,\n UidCheckbox,\n UidEmptyState,\n UidErrorState,\n UidPagination,\n UidSkeleton,\n UidTable,\n type UidTableColumn,\n} from '@dskripchenko/ui'\nimport { useResourceIndexStore } from '../../stores/resourceIndex'\nimport { useManifestStore } from '../../stores/manifest'\n\ninterface Props {\n /** Slug ресурса (users/articles/etc). */\n slug: string\n /** Заголовок страницы. Если не задан — берётся из manifest'а. */\n title?: string | null\n /** Подпись под заголовком (например \"Аналитика контента\"). */\n subtitle?: string | null\n /** Текст primary-кнопки «Создать». */\n createLabel?: string\n /** Имя router-route для action «Создать». */\n createRouteName?: string | null\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n title: null,\n subtitle: null,\n createLabel: 'Создать',\n createRouteName: null,\n})\n\nconst emit = defineEmits<{\n /** Bulk-action triggered с текущим Set'ом id. */\n 'bulk-action': [action: string, ids: Array<string | number>]\n /** Click на row — host решает (push edit / open view). */\n 'row-click': [row: Record<string, unknown>]\n}>()\n\nconst index = useResourceIndexStore()\nconst manifest = useManifestStore()\n\nconst resourceMeta = computed(() => manifest.getResource(props.slug))\n\nconst displayTitle = computed(\n () => props.title ?? resourceMeta.value?.label ?? props.slug,\n)\n\nconst columns = computed<UidTableColumn[]>(() => {\n const cols = resourceMeta.value?.columns ?? []\n return cols.map((c) => {\n const col = c as Record<string, unknown>\n return {\n key: String(col.key ?? col.name ?? ''),\n label: String(col.label ?? col.name ?? ''),\n sortable: Boolean(col.sortable),\n align: (col.align as 'left' | 'center' | 'right' | undefined) ?? 'left',\n width: typeof col.width === 'string' ? col.width : undefined,\n }\n }).filter((c) => c.key)\n})\n\nconst totalLabel = computed(() => {\n const t = index.meta.total\n if (t === 0) return ''\n return `${index.items.length} из ${t}`\n})\n\nonMounted(async () => {\n index.setSlug(props.slug)\n if (manifest.manifest === null) {\n await manifest.load().catch(() => undefined)\n }\n await index.load().catch(() => undefined)\n})\n\nwatch(\n () => props.slug,\n async (next, prev) => {\n if (next === prev) return\n index.setSlug(next)\n await index.load().catch(() => undefined)\n },\n)\n\nasync function onSortUpdate(key: string): Promise<void> {\n await index.toggleSort(key)\n}\n\nasync function onPageChange(page: number): Promise<void> {\n await index.setPage(page)\n}\n\nfunction onHeaderCheckbox(): void {\n index.toggleAllOnPage()\n}\n\nfunction onRowCheckbox(id: string | number): void {\n index.toggleRow(id)\n}\n\nfunction onRowClick(row: Record<string, unknown>): void {\n emit('row-click', row)\n}\n\nfunction bulkAction(action: string): void {\n emit('bulk-action', action, [...index.selection])\n}\n\nasync function retryLoad(): Promise<void> {\n await index.load().catch(() => undefined)\n}\n</script>\n\n<template>\n <section class=\"admin-page admin-resource-index\">\n <!-- Header -->\n <header class=\"admin-page__hd\">\n <div class=\"admin-page__title-wrap\">\n <h1 class=\"admin-page__title\">{{ displayTitle }}</h1>\n <div v-if=\"subtitle || totalLabel\" class=\"admin-page__count\">\n <template v-if=\"subtitle\">{{ subtitle }}</template>\n <template v-if=\"subtitle && totalLabel\"> · </template>\n <template v-if=\"totalLabel\">{{ totalLabel }}</template>\n </div>\n </div>\n <div class=\"admin-page__actions\">\n <slot name=\"actions\" />\n <UidButton\n v-if=\"createRouteName\"\n variant=\"primary\"\n @click=\"$router.push({ name: createRouteName })\"\n >\n {{ createLabel }}\n </UidButton>\n </div>\n </header>\n\n <!-- Bulk toolbar (selection > 0) ИЛИ filter bar -->\n <div v-if=\"index.hasSelection\" class=\"admin-bulk-toolbar\" role=\"toolbar\">\n <span class=\"admin-bulk-toolbar__count\">\n Выбрано <b>{{ index.selectedCount }}</b>\n </span>\n <span class=\"admin-bulk-toolbar__divider\" />\n <UidButton size=\"sm\" variant=\"ghost\" @click=\"bulkAction('publish')\">Опубликовать</UidButton>\n <UidButton size=\"sm\" variant=\"ghost\" @click=\"bulkAction('archive')\">Архивировать</UidButton>\n <UidButton size=\"sm\" variant=\"ghost\" @click=\"bulkAction('export')\">Экспорт</UidButton>\n <UidButton size=\"sm\" variant=\"danger\" @click=\"bulkAction('delete')\">Удалить</UidButton>\n <span class=\"admin-bulk-toolbar__spacer\" />\n <UidButton size=\"sm\" variant=\"ghost\" @click=\"index.clearSelection\">\n Снять выделение\n </UidButton>\n </div>\n\n <div v-else class=\"admin-filter-bar\">\n <input\n :value=\"index.search\"\n type=\"search\"\n placeholder=\"Поиск…\"\n class=\"admin-filter-bar__search\"\n @keydown.enter=\"(e) => index.setSearch((e.target as HTMLInputElement).value)\"\n />\n <slot name=\"filters\" :filters=\"index.filters\" :set-filter=\"index.setFilter\" />\n <span class=\"admin-filter-bar__spacer\" />\n <UidButton\n v-if=\"Object.keys(index.filters).length > 0\"\n size=\"sm\"\n variant=\"ghost\"\n @click=\"index.clearFilters\"\n >\n Сброс\n </UidButton>\n </div>\n\n <!-- States -->\n <div v-if=\"index.loading\" class=\"admin-resource-index__loading\">\n <UidSkeleton v-for=\"i in 8\" :key=\"i\" height=\"40px\" />\n </div>\n <UidErrorState\n v-else-if=\"index.hasError\"\n title=\"Не удалось загрузить данные\"\n :description=\"index.error?.message ?? 'Попробуйте обновить страницу.'\"\n class=\"admin-resource-index__state\"\n >\n <template #actions>\n <UidButton variant=\"primary\" @click=\"retryLoad\">Обновить</UidButton>\n </template>\n </UidErrorState>\n <UidEmptyState\n v-else-if=\"index.isEmpty\"\n title=\"Пока пусто\"\n description=\"Создайте первую запись или измените фильтры.\"\n class=\"admin-resource-index__state\"\n >\n <template #actions>\n <UidButton\n v-if=\"createRouteName\"\n variant=\"primary\"\n @click=\"$router.push({ name: createRouteName })\"\n >\n {{ createLabel }}\n </UidButton>\n </template>\n </UidEmptyState>\n\n <!-- Таблица -->\n <div v-else class=\"admin-resource-index__table\">\n <!-- Custom checkbox-column перед UidTable (uid-table сам не умеет selection). -->\n <div class=\"admin-resource-index__select-header\">\n <UidCheckbox\n :model-value=\"index.selectionState === 'all'\"\n :indeterminate=\"index.selectionState === 'mixed'\"\n aria-label=\"Выделить всё\"\n @update:model-value=\"onHeaderCheckbox\"\n />\n </div>\n <UidTable\n :columns=\"columns\"\n :data=\"index.items\"\n :sort-key=\"index.sortKey ?? ''\"\n :sort-direction=\"index.sortDirection\"\n @update:sort-key=\"onSortUpdate\"\n >\n <template\n v-for=\"col in columns\"\n #[`cell-${col.key}`]=\"row\"\n :key=\"col.key\"\n >\n <slot :name=\"`cell-${col.key}`\" :row=\"row\">{{ row?.[col.key] }}</slot>\n </template>\n </UidTable>\n\n <!-- Per-row checkbox + click row-area: рендерится в overlay'е -->\n <div class=\"admin-resource-index__select-overlay\">\n <div\n v-for=\"row in index.items\"\n :key=\"String(index.rowId(row))\"\n :class=\"[\n 'admin-resource-index__row',\n { 'admin-resource-index__row--selected': index.isSelected(index.rowId(row)) },\n ]\"\n @click=\"onRowClick(row)\"\n >\n <UidCheckbox\n :model-value=\"index.isSelected(index.rowId(row))\"\n :aria-label=\"`Строка ${index.rowId(row)}`\"\n @update:model-value=\"onRowCheckbox(index.rowId(row))\"\n @click.stop\n />\n </div>\n </div>\n </div>\n\n <!-- Pagination -->\n <footer\n v-if=\"!index.loading && !index.hasError && !index.isEmpty\"\n class=\"admin-resource-index__footer\"\n >\n <UidPagination\n :model-value=\"index.meta.page\"\n :total=\"index.meta.total\"\n :per-page=\"index.meta.per_page\"\n @update:model-value=\"onPageChange\"\n />\n </footer>\n </section>\n</template>\n\n<style>\n.admin-resource-index__loading {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-sm);\n margin-top: var(--uid-space-md);\n}\n.admin-resource-index__state {\n margin-top: var(--uid-space-xl);\n}\n.admin-resource-index__table {\n position: relative;\n margin-top: var(--uid-space-md);\n}\n.admin-resource-index__select-header {\n position: absolute;\n top: 8px;\n left: 12px;\n z-index: 1;\n pointer-events: auto;\n}\n.admin-resource-index__select-overlay {\n position: absolute;\n top: 36px;\n left: 12px;\n pointer-events: auto;\n display: flex;\n flex-direction: column;\n}\n.admin-resource-index__row {\n height: var(--admin-row-h, 40px);\n display: flex;\n align-items: center;\n}\n.admin-resource-index__footer {\n display: flex;\n justify-content: flex-end;\n padding: var(--uid-space-md) 0;\n}\n\n/* Filter bar */\n.admin-filter-bar {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--uid-space-sm);\n padding: var(--uid-space-sm) var(--uid-space-md);\n border: 1px solid var(--uid-border-subtle);\n background: var(--uid-surface-raised);\n border-radius: var(--uid-radius-lg) var(--uid-radius-lg) 0 0;\n border-bottom: 0;\n margin-top: var(--uid-space-md);\n}\n.admin-filter-bar__search {\n flex: 1;\n min-width: 200px;\n max-width: 320px;\n height: 28px;\n padding: 0 var(--uid-space-sm);\n border: 1px solid var(--uid-border-subtle);\n background: var(--uid-surface-base);\n border-radius: var(--uid-radius-md);\n color: var(--uid-text-primary);\n font-size: 13px;\n outline: none;\n}\n.admin-filter-bar__search:focus {\n border-color: var(--uid-accent);\n outline: 2px solid color-mix(in srgb, var(--uid-accent) 18%, transparent);\n}\n.admin-filter-bar__spacer { flex: 1; }\n\n/* Bulk toolbar — dark zinc-900 surface, заменяет filter bar */\n.admin-bulk-toolbar {\n display: flex;\n align-items: center;\n gap: var(--uid-space-sm);\n padding: var(--uid-space-sm) var(--uid-space-md);\n background: var(--uid-color-zinc-900, #18181b);\n color: var(--uid-color-zinc-100, #f4f4f5);\n border-radius: var(--uid-radius-lg) var(--uid-radius-lg) 0 0;\n border: 1px solid var(--uid-color-zinc-900, #18181b);\n border-bottom: 0;\n margin-top: var(--uid-space-md);\n}\n.admin-bulk-toolbar__count { font-size: 13px; }\n.admin-bulk-toolbar__count b { font-weight: var(--uid-font-weight-semibold); }\n.admin-bulk-toolbar__divider {\n width: 1px;\n height: 20px;\n background: rgba(255, 255, 255, 0.15);\n}\n.admin-bulk-toolbar__spacer { flex: 1; }\n.admin-bulk-toolbar .uid-button {\n background: transparent;\n border-color: rgba(255, 255, 255, 0.15);\n color: var(--uid-color-zinc-100, #f4f4f5);\n}\n.admin-bulk-toolbar .uid-button:hover:not([disabled]) {\n background: rgba(255, 255, 255, 0.08);\n}\n.admin-bulk-toolbar .uid-button--danger {\n color: var(--uid-color-rose-400, #fb7185);\n}\n\n/* Selected row tint */\n.admin-resource-index__row--selected {\n background: color-mix(in srgb, var(--uid-accent) 8%, transparent);\n}\n</style>\n","/**\n * useResourceFormStore — state для Resource Create/Edit/View screens.\n *\n * Управляет:\n * - mode ('create' | 'edit' | 'view')\n * - record (raw из API), state (working copy в form-state, но мы держим\n * reference на initial для unsaved-changes detection)\n * - errors (field-keyed) — устанавливаются при ValidationError\n * - loading/saving/deleting — для disable submit / show spinner\n * - dirty (computed) — есть ли несохранённые изменения\n *\n * Endpoints (laravel-admin contract):\n * GET /resources/{slug}/read — fetch one (id в filter[id])\n * POST /resources/{slug}/create\n * POST /resources/{slug}/update\n * POST /resources/{slug}/destroy\n */\n\nimport { defineStore } from 'pinia'\nimport { computed, ref } from 'vue'\nimport { getAdminClient } from './registry'\nimport { ApiError, ValidationError } from '../api/errors'\n\nexport type FormMode = 'create' | 'edit' | 'view'\n\ninterface ReadResponse {\n data: Record<string, unknown>\n}\n\ninterface SaveResponse {\n id: string | number\n data?: Record<string, unknown>\n redirect_url?: string\n}\n\nexport const useResourceFormStore = defineStore('admin-resource-form', () => {\n const slug = ref<string | null>(null)\n const mode = ref<FormMode>('create')\n const recordId = ref<string | number | null>(null)\n\n /** Текущее состояние формы — мутируется через setField. */\n const state = ref<Record<string, unknown>>({})\n /** Snapshot изначальных значений (после load) — для dirty-detection. */\n const initial = ref<Record<string, unknown>>({})\n\n /** Field-keyed errors. Очищаются при successful save. */\n const errors = ref<Record<string, string[]>>({})\n\n const loading = ref(false)\n const saving = ref(false)\n const deleting = ref(false)\n const error = ref<Error | null>(null)\n\n const isCreate = computed(() => mode.value === 'create')\n const isEdit = computed(() => mode.value === 'edit')\n const isView = computed(() => mode.value === 'view')\n const hasError = computed(() => error.value !== null)\n\n /** Dirty: state отличается от initial хотя бы по одному ключу. */\n const isDirty = computed(() => {\n const a = state.value\n const b = initial.value\n const keys = new Set([...Object.keys(a), ...Object.keys(b)])\n for (const k of keys) {\n if (!Object.is(a[k], b[k])) {\n // Простое сравнение скаляров; объекты/массивы сравниваем JSON-сериализацией.\n if (typeof a[k] === 'object' || typeof b[k] === 'object') {\n if (JSON.stringify(a[k]) !== JSON.stringify(b[k])) return true\n } else {\n return true\n }\n }\n }\n return false\n })\n\n /** In-place мутация reactive-объекта — сохраняет identity для provide/inject. */\n function replaceObject(target: Record<string, unknown>, next: Record<string, unknown>): void {\n for (const k of Object.keys(target)) delete target[k]\n Object.assign(target, next)\n }\n\n function reset(): void {\n replaceObject(state.value, {})\n replaceObject(initial.value, {})\n errors.value = {}\n loading.value = false\n saving.value = false\n deleting.value = false\n error.value = null\n recordId.value = null\n }\n\n /** Подготовить store для create-mode на ресурсе. */\n function prepareCreate(resourceSlug: string, defaults: Record<string, unknown> = {}): void {\n slug.value = resourceSlug\n mode.value = 'create'\n recordId.value = null\n replaceObject(state.value, defaults)\n replaceObject(initial.value, defaults)\n errors.value = {}\n error.value = null\n }\n\n /** Загрузить запись для edit либо view-режима. */\n async function load(\n resourceSlug: string,\n id: string | number,\n targetMode: 'edit' | 'view' = 'edit',\n ): Promise<void> {\n slug.value = resourceSlug\n mode.value = targetMode\n recordId.value = id\n loading.value = true\n error.value = null\n errors.value = {}\n\n try {\n const client = getAdminClient()\n const res = await client.get<ReadResponse>(`/resources/${resourceSlug}/read`, {\n params: { 'filter[id]': id },\n })\n replaceObject(state.value, res.data)\n replaceObject(initial.value, res.data)\n } catch (err) {\n error.value = err instanceof Error ? err : new Error(String(err))\n throw err\n } finally {\n loading.value = false\n }\n }\n\n /** Установить значение поля (через FormState composable обычно). */\n function setField(name: string, value: unknown): void {\n state.value[name] = value\n if (errors.value[name]) {\n // Очищаем ошибку конкретного поля при изменении (стандартный UX).\n const next = { ...errors.value }\n delete next[name]\n errors.value = next\n }\n }\n\n function setErrors(next: Record<string, string[]>): void {\n errors.value = { ...next }\n }\n\n function clearErrors(): void {\n errors.value = {}\n }\n\n /**\n * Сохранить. На create — POST /create; на edit — POST /update с id.\n * Возвращает new id (для post-create редиректа).\n */\n async function save(): Promise<string | number> {\n if (!slug.value) throw new Error('useResourceFormStore.save() before slug set')\n if (saving.value) throw new Error('Already saving')\n\n saving.value = true\n error.value = null\n errors.value = {}\n\n try {\n const client = getAdminClient()\n const url =\n mode.value === 'create'\n ? `/resources/${slug.value}/create`\n : `/resources/${slug.value}/update`\n\n const payload =\n mode.value === 'create'\n ? state.value\n : { id: recordId.value, ...state.value }\n\n const res = await client.post<SaveResponse>(url, payload)\n const newId = res.id\n recordId.value = newId\n // После успешного save обновим initial = state, чтобы dirty=false.\n replaceObject(initial.value, { ...state.value })\n mode.value = 'edit'\n return newId\n } catch (err) {\n if (err instanceof ValidationError) {\n errors.value = { ...err.fields }\n } else if (err instanceof ApiError) {\n error.value = err\n } else if (err instanceof Error) {\n error.value = err\n }\n throw err\n } finally {\n saving.value = false\n }\n }\n\n /** Удалить текущую запись (только в edit-mode). */\n async function destroy(): Promise<void> {\n if (!slug.value || recordId.value === null) {\n throw new Error('Nothing to delete')\n }\n if (deleting.value) throw new Error('Already deleting')\n\n deleting.value = true\n error.value = null\n try {\n const client = getAdminClient()\n await client.post(`/resources/${slug.value}/destroy`, { id: recordId.value })\n } catch (err) {\n if (err instanceof Error) error.value = err\n throw err\n } finally {\n deleting.value = false\n }\n }\n\n return {\n // state\n slug,\n mode,\n recordId,\n state,\n initial,\n errors,\n loading,\n saving,\n deleting,\n error,\n // getters\n isCreate,\n isEdit,\n isView,\n isDirty,\n hasError,\n // actions\n reset,\n prepareCreate,\n load,\n setField,\n setErrors,\n clearErrors,\n save,\n destroy,\n }\n})\n","/**\n * Generic factory для component-registry'ов (fields, layouts, widgets,\n * infolist entries и т.п.).\n *\n * Все component-registry в admin'е по сути одинаковы: keyed Map<string, Component>\n * + register/get/has/list/clear/registerBundle. Этот factory вытаскивает паттерн\n * один раз; конкретные модули просто переименовывают экспорты.\n *\n * const reg = createComponentRegistry<Component>()\n * export const registerWidget = reg.register\n * export const getWidget = reg.get\n * // ...\n */\n\nexport interface ComponentRegistry<T> {\n register(type: string, value: T): void\n get(type: string): T | null\n has(type: string): boolean\n list(): string[]\n clear(): void\n registerBundle(bundle: Record<string, T>): void\n}\n\nexport function createComponentRegistry<T>(): ComponentRegistry<T> {\n const store = new Map<string, T>()\n\n return {\n register(type, value) {\n store.set(type, value)\n },\n get(type) {\n return store.get(type) ?? null\n },\n has(type) {\n return store.has(type)\n },\n list() {\n return [...store.keys()]\n },\n clear() {\n store.clear()\n },\n registerBundle(bundle) {\n for (const [type, value] of Object.entries(bundle)) {\n store.set(type, value)\n }\n },\n }\n}\n","/**\n * Реестр Vue-компонентов для JSON-driven рендеринга.\n *\n * Содержит две Map'ы — для `field`-типов (input'ы, контролы) и для\n * `layout`-типов (контейнеры). LayoutRenderer и FieldRenderer резолвят тип\n * через эти реестры; host-проект может зарегистрировать кастомные компоненты\n * через `registerField()` / `registerLayout()`.\n *\n * Singleton — один регистр на admin-instance. Тестовый сценарий —\n * `clearRegistry()` + `registerField()` в `beforeEach`.\n */\n\nimport type { Component } from 'vue'\nimport { createComponentRegistry } from '../createComponentRegistry'\n\nconst fields = createComponentRegistry<Component>()\nconst layouts = createComponentRegistry<Component>()\n\nexport const registerField = fields.register\nexport const getField = fields.get\nexport const hasField = fields.has\nexport const listFields = fields.list\n\nexport const registerLayout = layouts.register\nexport const getLayout = layouts.get\nexport const hasLayout = layouts.has\nexport const listLayouts = layouts.list\n\n/** Очистить оба реестра. Используется в тестах. */\nexport function clearRegistry(): void {\n fields.clear()\n layouts.clear()\n}\n\n/**\n * Зарегистрировать сразу несколько компонентов.\n *\n * registerComponents({\n * fields: { text: TextField, select: SelectField },\n * layouts: { rows: RowsLayout, tabs: TabsLayout },\n * })\n */\nexport interface ComponentBundle {\n fields?: Record<string, Component>\n layouts?: Record<string, Component>\n}\n\nexport function registerComponents(bundle: ComponentBundle): void {\n if (bundle.fields) fields.registerBundle(bundle.fields)\n if (bundle.layouts) layouts.registerBundle(bundle.layouts)\n}\n","<script setup lang=\"ts\">\n/**\n * Fallback на missing field-registration. Видимый dev-warn вместо silent fail —\n * host-проект сразу замечает unregistered field-type.\n */\nimport { UidAlert } from '@dskripchenko/ui'\n\ninterface Props {\n type: string\n name?: string\n}\ndefineProps<Props>()\n</script>\n\n<template>\n <UidAlert variant=\"warning\">\n <template #title>Неизвестный тип поля: {{ type }}</template>\n <template v-if=\"name\">\n <code>{{ name }}</code> — зарегистрируйте field-компонент через\n <code>registerField('{{ type }}', YourComponent)</code>.\n </template>\n </UidAlert>\n</template>\n","<script setup lang=\"ts\">\n/**\n * FieldRenderer резолвит конкретный field-компонент по `node.type` из реестра\n * и forwards остальные props через v-bind.\n *\n * Узлы манифеста имеют форму:\n * { type: 'text', name: 'title', label: 'Заголовок', required: true, ... }\n *\n * Field хранит value через provide/inject form-state — узлу не передаётся\n * `modelValue` напрямую. Это позволяет строить произвольно-глубокие layout'ы\n * без явного proppin'га state'а.\n */\nimport { computed } from 'vue'\nimport { getField } from './registry'\nimport UnknownField from '../fields/UnknownField.vue'\n\nexport interface FieldNode extends Record<string, unknown> {\n type: string\n name: string\n}\n\ninterface Props {\n node: FieldNode\n}\n\nconst props = defineProps<Props>()\nconst component = computed(() => getField(props.node.type))\nconst fieldProps = computed(() => {\n const { type: _type, ...rest } = props.node\n return rest\n})\n</script>\n\n<template>\n <component :is=\"component\" v-if=\"component\" v-bind=\"fieldProps\" />\n <UnknownField v-else :type=\"node.type\" :name=\"node.name\" />\n</template>\n","<script setup lang=\"ts\">\n/**\n * Универсальный рекурсивный renderer manifest-узлов.\n *\n * Узел вида `{ kind: 'field', type: 'text', name: 'title', ... }` рендерится\n * через FieldRenderer. Узел вида `{ kind: 'layout', type: 'rows', items: [...] }`\n * — через зарегистрированный layout-компонент с children-списком.\n *\n * Для совместимости со старыми JSON'ами без `kind` — если type есть в\n * field-registry, считаем field; если в layout-registry — считаем layout;\n * иначе — UnknownField fallback.\n */\nimport { computed } from 'vue'\nimport { getField, getLayout } from './registry'\nimport FieldRenderer, { type FieldNode } from './FieldRenderer.vue'\nimport UnknownField from '../fields/UnknownField.vue'\n\nexport interface LayoutNode extends Record<string, unknown> {\n type: string\n kind?: 'field' | 'layout'\n items?: LayoutNode[]\n}\n\ninterface Props {\n node: LayoutNode\n}\nconst props = defineProps<Props>()\n\ntype Resolved =\n | { kind: 'field' }\n | { kind: 'layout'; component: ReturnType<typeof getLayout> }\n | { kind: 'unknown' }\n\nconst resolved = computed<Resolved>(() => {\n // Явный hint через `kind` всегда приоритетнее.\n if (props.node.kind === 'field') {\n return { kind: 'field' }\n }\n if (props.node.kind === 'layout') {\n const component = getLayout(props.node.type)\n return component ? { kind: 'layout', component } : { kind: 'unknown' }\n }\n // Auto-detect.\n const layoutComponent = getLayout(props.node.type)\n if (layoutComponent) return { kind: 'layout', component: layoutComponent }\n if (getField(props.node.type)) return { kind: 'field' }\n return { kind: 'unknown' }\n})\n\nconst layoutProps = computed(() => {\n const { type: _type, kind: _kind, ...rest } = props.node\n return rest\n})\n\nconst fieldNode = computed<FieldNode>(() => props.node as unknown as FieldNode)\n</script>\n\n<template>\n <component\n :is=\"resolved.component\"\n v-if=\"resolved.kind === 'layout' && resolved.component\"\n v-bind=\"layoutProps\"\n />\n <FieldRenderer v-else-if=\"resolved.kind === 'field'\" :node=\"fieldNode\" />\n <UnknownField v-else :type=\"node.type\" :name=\"(node.name as string | undefined)\" />\n</template>\n","<script setup lang=\"ts\">\n/**\n * ResourceFormPage — unified create/edit page для Resource'а.\n *\n * Архитектура по docs/design_handoff_laravel_admin/screens-shell.jsx\n * (Resource Form):\n * - Header: back-breadcrumb + title + status-badge + actions\n * (Preview / Удалить / Сохранить-primary)\n * - Body: layout из manifest.fields (LayoutRenderer + provideFormState)\n * - Sticky save-bar внизу с unsaved-changes hint\n *\n * Mode определяется наличием `id`-prop'а: id=null → create, иначе → edit.\n *\n * Form-state предоставляется через provideFormState из useResourceFormStore.state.\n * FieldRenderer'ы внутри форм автоматически подхватывают через useFormState.\n */\nimport { computed, onMounted, watch } from 'vue'\nimport { useRouter } from 'vue-router'\nimport {\n UidAlert,\n UidBadge,\n UidButton,\n UidCard,\n UidSkeleton,\n} from '@dskripchenko/ui'\nimport { useResourceFormStore } from '../../stores/resourceForm'\nimport { useManifestStore } from '../../stores/manifest'\nimport { provideFormState } from '../render/formState'\nimport LayoutRenderer from '../render/LayoutRenderer.vue'\nimport type { LayoutNode } from '../render/LayoutRenderer.vue'\n\ninterface Props {\n /** Slug ресурса (articles/users/etc). */\n slug: string\n /** ID записи. null/undefined → create-mode; число/строка → edit. */\n id?: string | number | null\n /** Имя router-route на index page (для back-redirect после save/delete). */\n indexRouteName?: string\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n id: null,\n indexRouteName: 'admin.home',\n})\n\nconst form = useResourceFormStore()\nconst manifest = useManifestStore()\nconst router = useRouter()\n\n// provideFormState ОБЯЗАН вызываться в setup() — связываем со store.state.\n// Сам form-context форвардит setField → store.setField (с auto-clear errors).\nconst ctx = provideFormState(form.state, form.errors)\n\n// Watcher: при изменениях через ctx.setField (обёртка которой) — синхронизируем\n// в store, чтобы isDirty работало. Поскольку state.value === ctx.state (тот же\n// reactive object — provideFormState не делает копию), мутации видны напрямую\n// в store. setField'у в ctx достаточно.\nwatch(\n () => form.errors,\n (next) => {\n // При обновлении store.errors — выкидываем в form-context.\n ctx.setErrors({ ...next })\n },\n)\n\nconst resourceMeta = computed(() => manifest.getResource(props.slug))\n\nconst layoutNodes = computed<LayoutNode[]>(\n () => resourceMeta.value?.fields ?? [],\n)\n\nconst titleLabel = computed(() => {\n if (form.isCreate) return `Создать: ${resourceMeta.value?.label ?? props.slug}`\n return `${resourceMeta.value?.label ?? props.slug}: запись #${props.id}`\n})\n\nconst statusValue = computed<string | null>(() => {\n const v = form.state.status\n return typeof v === 'string' ? v : null\n})\n\nconst statusBadgeVariant = computed<'success' | 'warning' | 'danger' | 'default'>(() => {\n switch (statusValue.value) {\n case 'published': return 'success'\n case 'review':\n case 'draft': return 'warning'\n case 'archived': return 'danger'\n default: return 'default'\n }\n})\n\nonMounted(async () => {\n if (manifest.manifest === null) {\n await manifest.load().catch(() => undefined)\n }\n if (props.id !== null && props.id !== undefined) {\n await form.load(props.slug, props.id, 'edit').catch(() => undefined)\n } else {\n form.prepareCreate(props.slug)\n }\n})\n\nwatch(\n () => [props.slug, props.id] as const,\n async ([nextSlug, nextId]) => {\n if (nextId !== null && nextId !== undefined) {\n await form.load(nextSlug, nextId, 'edit').catch(() => undefined)\n } else {\n form.prepareCreate(nextSlug)\n }\n },\n)\n\nasync function onSave(): Promise<void> {\n try {\n const newId = await form.save()\n if (form.isCreate) {\n // create → редирект на edit с новым id (host route'ит).\n void router.push({\n name: `admin.resource.${props.slug}.edit`,\n params: { id: newId },\n }).catch(() => undefined)\n }\n } catch {\n // ValidationError уже превратился в form.errors через store; остальные\n // ошибки попали в form.error и отрисуются как UidAlert ниже.\n }\n}\n\nasync function onDelete(): Promise<void> {\n if (!confirm('Удалить запись?')) return\n await form.destroy().catch(() => undefined)\n if (!form.hasError) {\n void router.push({ name: props.indexRouteName }).catch(() => undefined)\n }\n}\n\nfunction onCancel(): void {\n if (form.isDirty && !confirm('Несохранённые изменения будут потеряны. Продолжить?')) {\n return\n }\n void router.push({ name: props.indexRouteName }).catch(() => undefined)\n}\n</script>\n\n<template>\n <section class=\"admin-page admin-resource-form\">\n <header class=\"admin-page__hd\">\n <div class=\"admin-page__title-wrap\">\n <a class=\"admin-resource-form__back\" @click=\"onCancel\">← Назад</a>\n <h1 class=\"admin-page__title\">{{ titleLabel }}</h1>\n <UidBadge v-if=\"statusValue\" :variant=\"statusBadgeVariant\">\n {{ statusValue }}\n </UidBadge>\n </div>\n <div class=\"admin-page__actions\">\n <UidButton\n variant=\"ghost\"\n :disabled=\"form.saving || form.deleting\"\n @click=\"onCancel\"\n >\n Отмена\n </UidButton>\n <UidButton\n v-if=\"form.isEdit\"\n variant=\"danger\"\n :disabled=\"form.saving || form.deleting\"\n :loading=\"form.deleting\"\n @click=\"onDelete\"\n >\n Удалить\n </UidButton>\n <UidButton\n variant=\"primary\"\n :disabled=\"form.saving || form.loading\"\n :loading=\"form.saving\"\n @click=\"onSave\"\n >\n {{ form.isCreate ? 'Создать' : 'Сохранить' }}\n </UidButton>\n </div>\n </header>\n\n <UidAlert\n v-if=\"form.hasError\"\n variant=\"danger\"\n class=\"admin-resource-form__alert\"\n role=\"alert\"\n >\n {{ form.error?.message ?? 'Не удалось сохранить запись' }}\n </UidAlert>\n\n <!-- Loading state — UidSkeleton imitates form-rows -->\n <div v-if=\"form.loading\" class=\"admin-resource-form__loading\">\n <UidSkeleton v-for=\"i in 6\" :key=\"i\" height=\"40px\" />\n </div>\n\n <!-- Body: layout из manifest -->\n <UidCard v-else padding=\"md\" class=\"admin-resource-form__body\">\n <LayoutRenderer\n v-for=\"(node, idx) in layoutNodes\"\n :key=\"idx\"\n :node=\"node\"\n />\n </UidCard>\n\n <!-- Sticky save-bar — показывается при unsaved-changes -->\n <div v-if=\"form.isDirty && !form.loading\" class=\"admin-resource-form__savebar\">\n <span class=\"admin-resource-form__savebar-hint\">\n Есть несохранённые изменения\n </span>\n <UidButton variant=\"ghost\" size=\"sm\" @click=\"onCancel\">Отмена</UidButton>\n <UidButton\n variant=\"primary\"\n size=\"sm\"\n :loading=\"form.saving\"\n :disabled=\"form.saving\"\n @click=\"onSave\"\n >\n Сохранить\n </UidButton>\n </div>\n </section>\n</template>\n\n<style>\n.admin-resource-form__back {\n font-size: var(--uid-font-size-xs);\n color: var(--uid-text-secondary);\n cursor: pointer;\n text-decoration: none;\n display: inline-block;\n margin-bottom: 4px;\n}\n.admin-resource-form__back:hover { color: var(--uid-text-primary); }\n\n.admin-resource-form__alert {\n margin-bottom: var(--uid-space-md);\n}\n.admin-resource-form__loading {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-sm);\n}\n.admin-resource-form__body { margin-bottom: var(--uid-space-2xl); }\n\n.admin-resource-form__savebar {\n position: sticky;\n bottom: 0;\n display: flex;\n align-items: center;\n gap: var(--uid-space-sm);\n padding: var(--uid-space-sm) var(--uid-space-md);\n background: var(--uid-surface-raised);\n border-top: 1px solid var(--uid-border-default);\n border-radius: var(--uid-radius-md);\n box-shadow: var(--uid-shadow-md);\n margin-top: var(--uid-space-md);\n}\n.admin-resource-form__savebar-hint {\n flex: 1;\n font-size: 13px;\n color: var(--uid-warning);\n}\n</style>\n","/**\n * Реестр infolist-entry-компонентов.\n *\n * Аналог field-registry, но для read-only display'я. Узлы манифеста имеют\n * форму:\n * { type: 'text', name: 'title', label: 'Заголовок', value?: '...' }\n * либо без явного `value` — тогда entry извлекает `record[name]` из\n * provide'нутого `record`.\n *\n * Host регистрирует кастомные entry через `registerInfolistEntry()` /\n * `registerInfolistEntries()` bundle.\n */\n\nimport type { Component } from 'vue'\nimport { createComponentRegistry } from '../createComponentRegistry'\n\nconst entries = createComponentRegistry<Component>()\n\nexport const registerInfolistEntry = entries.register\nexport const getInfolistEntry = entries.get\nexport const hasInfolistEntry = entries.has\nexport const listInfolistEntries = entries.list\nexport const clearInfolistRegistry = entries.clear\nexport const registerInfolistEntries = entries.registerBundle\n","<script setup lang=\"ts\">\nimport { UidAlert } from '@dskripchenko/ui'\n\ninterface Props {\n type: string\n name?: string\n}\ndefineProps<Props>()\n</script>\n\n<template>\n <UidAlert variant=\"warning\">\n <template #title>Неизвестный тип infolist-entry: {{ type }}</template>\n Зарегистрируйте через <code>registerInfolistEntry('{{ type }}', YourComponent)</code>.\n </UidAlert>\n</template>\n","<script setup lang=\"ts\">\n/**\n * InfolistRenderer — read-only аналог LayoutRenderer для view-страниц.\n *\n * Узлы:\n * { type: 'text', name: 'title', label: 'Заголовок' } — entry (leaf)\n * { type: 'rows', items: [ ... ] } — layout (recurse)\n * { type: 'section', title: 'X', items: [ ... ] } — layout\n * { type: 'columns', items: [ ... ] } — layout\n *\n * Внимание: layout-узлы рендерятся СВОИМ внутренним wrapper'ом, а не\n * registered uid-layouts из render/registry, потому что те делегируют детей\n * в LayoutRenderer (field-registry → useFormState ОБЯЗАТЕЛЕН). Здесь record-\n * read-only режим — детей рендерим через сам InfolistRenderer.\n */\nimport { computed } from 'vue'\nimport { getInfolistEntry } from './registry'\nimport UnknownEntry from './UnknownEntry.vue'\n\nexport interface InfolistNode extends Record<string, unknown> {\n type: string\n /** Hint: 'entry' либо 'layout'. */\n kind?: 'entry' | 'layout'\n items?: InfolistNode[]\n}\n\ninterface Props {\n node: InfolistNode\n}\nconst props = defineProps<Props>()\n\nconst KNOWN_LAYOUTS = new Set(['rows', 'columns', 'section', 'block', 'tabs'])\n\ntype Resolved =\n | { kind: 'entry'; component: NonNullable<ReturnType<typeof getInfolistEntry>> }\n | { kind: 'layout'; layoutType: string }\n | { kind: 'unknown' }\n\nconst resolved = computed<Resolved>(() => {\n if (props.node.kind === 'entry') {\n const c = getInfolistEntry(props.node.type)\n return c ? { kind: 'entry', component: c } : { kind: 'unknown' }\n }\n if (props.node.kind === 'layout') {\n return KNOWN_LAYOUTS.has(props.node.type)\n ? { kind: 'layout', layoutType: props.node.type }\n : { kind: 'unknown' }\n }\n // Auto-detect: layouts по имени, entries по registry.\n if (KNOWN_LAYOUTS.has(props.node.type)) {\n return { kind: 'layout', layoutType: props.node.type }\n }\n const entry = getInfolistEntry(props.node.type)\n if (entry) return { kind: 'entry', component: entry }\n return { kind: 'unknown' }\n})\n\nconst entryProps = computed(() => {\n const { type: _t, kind: _k, items: _i, ...rest } = props.node\n return rest\n})\n\nconst items = computed<InfolistNode[]>(\n () => (props.node.items ?? []) as InfolistNode[],\n)\n\nconst sectionTitle = computed(() => (props.node.title as string | undefined) ?? null)\nconst sectionDescription = computed(\n () => (props.node.description as string | undefined) ?? null,\n)\nconst tabsActive = computed<number>(() => {\n const a = props.node.active\n return typeof a === 'number' ? a : 0\n})\n\ninterface InfolistTab {\n key?: string\n label: string\n items: InfolistNode[]\n}\nconst tabsList = computed<InfolistTab[]>(() => {\n return (props.node.items ?? []) as unknown as InfolistTab[]\n})\n</script>\n\n<template>\n <!-- Entry -->\n <component\n :is=\"resolved.component\"\n v-if=\"resolved.kind === 'entry'\"\n v-bind=\"entryProps\"\n />\n\n <!-- Layout: rows -->\n <div\n v-else-if=\"resolved.kind === 'layout' && resolved.layoutType === 'rows'\"\n class=\"admin-infolist-rows\"\n >\n <InfolistRenderer\n v-for=\"(child, idx) in items\"\n :key=\"idx\"\n :node=\"child\"\n />\n </div>\n\n <!-- Layout: columns (12-grid с per-item span) -->\n <div\n v-else-if=\"resolved.kind === 'layout' && resolved.layoutType === 'columns'\"\n class=\"admin-infolist-cols\"\n >\n <div\n v-for=\"(child, idx) in items\"\n :key=\"idx\"\n class=\"admin-infolist-cols__item\"\n :style=\"{\n gridColumn: `span ${\n typeof (child as Record<string, unknown>).span === 'number'\n ? (child as Record<string, unknown>).span\n : Math.max(1, Math.floor(12 / items.length))\n }`,\n }\"\n >\n <InfolistRenderer :node=\"child\" />\n </div>\n </div>\n\n <!-- Layout: section / block -->\n <section\n v-else-if=\"resolved.kind === 'layout' && (resolved.layoutType === 'section' || resolved.layoutType === 'block')\"\n class=\"admin-infolist-section\"\n >\n <header v-if=\"sectionTitle || sectionDescription\" class=\"admin-infolist-section__hd\">\n <h3 v-if=\"sectionTitle\" class=\"admin-infolist-section__title\">{{ sectionTitle }}</h3>\n <p v-if=\"sectionDescription\" class=\"admin-infolist-section__description\">\n {{ sectionDescription }}\n </p>\n </header>\n <div class=\"admin-infolist-section__body\">\n <InfolistRenderer\n v-for=\"(child, idx) in items\"\n :key=\"idx\"\n :node=\"child\"\n />\n </div>\n </section>\n\n <!-- Layout: tabs (минимальные — без переключения, показываем active по prop'у) -->\n <div\n v-else-if=\"resolved.kind === 'layout' && resolved.layoutType === 'tabs'\"\n class=\"admin-infolist-tabs\"\n >\n <ul class=\"admin-infolist-tabs__list\" role=\"tablist\">\n <li\n v-for=\"(tab, idx) in tabsList\"\n :key=\"tab.key ?? idx\"\n :class=\"[\n 'admin-infolist-tabs__tab',\n { 'admin-infolist-tabs__tab--active': idx === tabsActive },\n ]\"\n >\n {{ tab.label }}\n </li>\n </ul>\n <div class=\"admin-infolist-tabs__panel\">\n <InfolistRenderer\n v-for=\"(child, idx) in tabsList[tabsActive]?.items ?? []\"\n :key=\"idx\"\n :node=\"child\"\n />\n </div>\n </div>\n\n <UnknownEntry v-else :type=\"node.type\" :name=\"(node.name as string | undefined)\" />\n</template>\n\n<style>\n.admin-infolist-rows {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-sm);\n}\n.admin-infolist-cols {\n display: grid;\n grid-template-columns: repeat(12, minmax(0, 1fr));\n gap: var(--uid-space-md);\n}\n.admin-infolist-section {\n margin-bottom: var(--uid-space-md);\n padding: var(--uid-space-md);\n border: 1px solid var(--uid-border-subtle);\n border-radius: var(--uid-radius-lg);\n background: var(--uid-surface-raised);\n}\n.admin-infolist-section__hd { margin-bottom: var(--uid-space-sm); }\n.admin-infolist-section__title {\n margin: 0;\n font-size: var(--uid-font-size-sm);\n font-weight: var(--uid-font-weight-semibold);\n}\n.admin-infolist-section__description {\n margin: var(--uid-space-2xs) 0 0;\n font-size: var(--uid-font-size-xs);\n color: var(--uid-text-tertiary);\n}\n.admin-infolist-section__body {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-sm);\n}\n.admin-infolist-tabs__list {\n list-style: none;\n margin: 0 0 var(--uid-space-sm);\n padding: 0;\n display: flex;\n gap: var(--uid-space-xs);\n border-bottom: 1px solid var(--uid-border-subtle);\n}\n.admin-infolist-tabs__tab {\n padding: var(--uid-space-sm) var(--uid-space-sm);\n font-size: 13px;\n color: var(--uid-text-secondary);\n border-bottom: 2px solid transparent;\n}\n.admin-infolist-tabs__tab--active {\n color: var(--uid-text-primary);\n border-bottom-color: var(--uid-accent);\n font-weight: var(--uid-font-weight-medium);\n}\n</style>\n","/**\n * Composable для read-only record-контекста, передаваемого Infolist'ом.\n *\n * Контейнер (ResourceViewPage) вызывает `provideRecord(record)`, entry-\n * компоненты — `useRecord()` для чтения значения.\n */\n\nimport { inject, provide, type InjectionKey } from 'vue'\n\nconst RecordKey: InjectionKey<Record<string, unknown>> = Symbol('admin.infolist-record')\n\nexport function provideRecord(record: Record<string, unknown>): void {\n provide(RecordKey, record)\n}\n\nexport function useRecord(): Record<string, unknown> {\n const r = inject(RecordKey)\n if (!r) {\n throw new Error('useRecord() called outside of provideRecord() scope')\n }\n return r\n}\n\nexport function tryUseRecord(): Record<string, unknown> | null {\n return inject(RecordKey, null) as Record<string, unknown> | null\n}\n","<script setup lang=\"ts\">\n/**\n * ResourceViewPage — read-only зеркало form-страницы.\n *\n * Архитектура по docs/design_handoff_laravel_admin (ResourceView):\n * - Header: title + actions (Edit / Удалить)\n * - Body: 2-col grid (1fr Infolist + 320px side card с метриками)\n * - InfolistRenderer бежит по manifest.fields (тот же layout, но\n * leaf-узлы резолвятся через infolist-registry, не field-registry)\n */\nimport { computed, onMounted, watch } from 'vue'\nimport { useRouter } from 'vue-router'\nimport {\n UidAlert,\n UidButton,\n UidCard,\n UidSkeleton,\n} from '@dskripchenko/ui'\nimport { useResourceFormStore } from '../../stores/resourceForm'\nimport { useManifestStore } from '../../stores/manifest'\nimport InfolistRenderer from '../infolist/InfolistRenderer.vue'\nimport type { InfolistNode } from '../infolist/InfolistRenderer.vue'\nimport { provideRecord } from '../infolist/recordContext'\n\ninterface Props {\n slug: string\n id: string | number\n /** Имя router-route для перехода в edit. */\n editRouteName?: string\n /** Имя router-route для возврата на index. */\n indexRouteName?: string\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n editRouteName: undefined,\n indexRouteName: 'admin.home',\n})\n\nconst form = useResourceFormStore()\nconst manifest = useManifestStore()\nconst router = useRouter()\n\n// provideRecord даёт infolist-entry'ям читать record[name] через useRecord.\nprovideRecord(form.state)\n\nconst resourceMeta = computed(() => manifest.getResource(props.slug))\nconst layoutNodes = computed<InfolistNode[]>(\n () => resourceMeta.value?.fields ?? [],\n)\nconst titleLabel = computed(\n () => `${resourceMeta.value?.label ?? props.slug}: запись #${props.id}`,\n)\n\nonMounted(async () => {\n if (manifest.manifest === null) {\n await manifest.load().catch(() => undefined)\n }\n await form.load(props.slug, props.id, 'view').catch(() => undefined)\n})\n\nwatch(\n () => [props.slug, props.id] as const,\n async ([s, id]) => {\n await form.load(s, id, 'view').catch(() => undefined)\n },\n)\n\nfunction onEdit(): void {\n if (!props.editRouteName) {\n router\n .push(`/r/${props.slug}/${props.id}/edit`)\n .catch(() => undefined)\n return\n }\n router\n .push({ name: props.editRouteName, params: { id: props.id } })\n .catch(() => undefined)\n}\n\nasync function onDelete(): Promise<void> {\n if (!confirm('Удалить запись?')) return\n await form.destroy().catch(() => undefined)\n if (!form.hasError) {\n router.push({ name: props.indexRouteName }).catch(() => undefined)\n }\n}\n</script>\n\n<template>\n <section class=\"admin-page admin-resource-view\">\n <header class=\"admin-page__hd\">\n <div class=\"admin-page__title-wrap\">\n <h1 class=\"admin-page__title\">{{ titleLabel }}</h1>\n </div>\n <div class=\"admin-page__actions\">\n <UidButton variant=\"ghost\" @click=\"onEdit\">Редактировать</UidButton>\n <UidButton\n variant=\"danger\"\n :loading=\"form.deleting\"\n :disabled=\"form.deleting\"\n @click=\"onDelete\"\n >\n Удалить\n </UidButton>\n </div>\n </header>\n\n <UidAlert\n v-if=\"form.hasError\"\n variant=\"danger\"\n class=\"admin-resource-view__alert\"\n role=\"alert\"\n >\n {{ form.error?.message ?? 'Не удалось загрузить запись' }}\n </UidAlert>\n\n <div v-if=\"form.loading\" class=\"admin-resource-view__loading\">\n <UidSkeleton v-for=\"i in 8\" :key=\"i\" height=\"24px\" />\n </div>\n\n <UidCard v-else padding=\"md\" class=\"admin-resource-view__body\">\n <InfolistRenderer\n v-for=\"(node, idx) in layoutNodes\"\n :key=\"idx\"\n :node=\"node\"\n />\n </UidCard>\n </section>\n</template>\n\n<style>\n.admin-resource-view__alert {\n margin-bottom: var(--uid-space-md);\n}\n.admin-resource-view__loading {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-sm);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * ProfilePage — профильный экран по эталону handoff'а (screens-secondary.jsx\n * → Profile). Layout 200px nav / 1fr cards.\n *\n * Slot model: каждая section экспонирует свою карточку. По умолчанию\n * library рендерит общие \"Основное\" + \"Безопасность\" (на existing-данных\n * auth.user). Host подмешивает свои \"API токены\" и \"Сессии\" через slot'ы.\n */\nimport { computed, ref } from 'vue'\nimport {\n UidAvatar,\n UidBadge,\n UidButton,\n UidCard,\n UidInput,\n UidSelect,\n} from '@dskripchenko/ui'\nimport { useAuthStore } from '../../stores/auth'\nimport { useThemeStore } from '../../stores/theme'\nimport { useLocaleStore } from '../../stores/locale'\n\ninterface Props {\n /** Заголовок страницы (по умолчанию «Profile»). */\n title?: string\n /** Подзаголовок (по умолчанию из handoff'а). */\n subtitle?: string\n /** Какая section активна. */\n section?: 'general' | 'security' | 'tokens' | 'sessions' | string\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n title: 'Profile',\n subtitle: 'Личные данные, безопасность, токены',\n section: 'general',\n})\n\nconst emit = defineEmits<{\n 'update:section': [value: string]\n /** Host реагирует — например запросом /me/uploadAvatar. */\n 'avatar-replace': []\n /** 2FA disable triggered — host показывает confirmation modal. */\n 'two-factor-disable': []\n /** 2FA recovery-codes regenerate. */\n 'two-factor-regenerate': []\n /** Save profile fields. */\n save: [payload: { name: string; email: string; locale: string; theme: string }]\n}>()\n\nconst auth = useAuthStore()\nconst theme = useThemeStore()\nconst locale = useLocaleStore()\n\nconst navItems = [\n { id: 'general', label: 'Основное', icon: 'user' },\n { id: 'security', label: 'Безопасность', icon: 'shield' },\n { id: 'tokens', label: 'API токены', icon: 'key' },\n { id: 'sessions', label: 'Сессии', icon: 'monitor' },\n]\n\nconst localSection = ref(props.section)\nfunction selectSection(id: string): void {\n localSection.value = id\n emit('update:section', id)\n}\n\n// Form-state для general-tab.\nconst profile = ref({\n name: auth.user?.name ?? '',\n email: auth.user?.email ?? '',\n locale: locale.current,\n theme: theme.current,\n})\n\nconst localeOptions = computed(() =>\n locale.available.map((l) => ({ value: l, label: l.toUpperCase() })),\n)\nconst themeOptions = computed(() =>\n theme.available.map((t) => ({ value: t, label: t === 'dark' ? 'Тёмная' : t === 'light' ? 'Светлая' : t })),\n)\n\nfunction onSave(): void {\n emit('save', { ...profile.value })\n}\n\nfunction onAvatarReplace(): void {\n emit('avatar-replace')\n}\n\nfunction on2FADisable(): void {\n emit('two-factor-disable')\n}\n\nfunction on2FARegenerate(): void {\n emit('two-factor-regenerate')\n}\n\nconst has2FA = computed(() => Boolean(auth.user?.twoFactorEnabled))\n</script>\n\n<template>\n <section class=\"admin-page admin-profile\">\n <header class=\"admin-page__hd\">\n <div class=\"admin-page__title-wrap\">\n <h1 class=\"admin-page__title\">{{ title }}</h1>\n <div class=\"admin-page__count\">{{ subtitle }}</div>\n </div>\n </header>\n\n <div class=\"admin-profile__layout\">\n <nav class=\"admin-profile__nav\" aria-label=\"Profile sections\">\n <button\n v-for=\"item in navItems\"\n :key=\"item.id\"\n type=\"button\"\n :class=\"[\n 'admin-profile__nav-item',\n { 'admin-profile__nav-item--active': localSection === item.id },\n ]\"\n @click=\"selectSection(item.id)\"\n >\n <span class=\"admin-profile__nav-icon\" :data-icon=\"item.icon\" />\n <span>{{ item.label }}</span>\n </button>\n </nav>\n\n <div class=\"admin-profile__content\">\n <!-- General -->\n <UidCard v-if=\"localSection === 'general'\" padding=\"md\">\n <header class=\"admin-profile__card-hd\">\n <h3 class=\"admin-profile__card-title\">Профиль</h3>\n </header>\n\n <div class=\"admin-profile__hero\">\n <UidAvatar\n :src=\"auth.user?.avatar ?? undefined\"\n :name=\"auth.user?.name ?? '?'\"\n size=\"lg\"\n />\n <div class=\"admin-profile__hero-text\">\n <div class=\"admin-profile__hero-name\">{{ auth.user?.name ?? '—' }}</div>\n <div class=\"admin-profile__hero-meta\">\n {{ auth.user?.email ?? '—' }}\n </div>\n </div>\n <div style=\"flex:1\" />\n <UidButton variant=\"ghost\" size=\"sm\" @click=\"onAvatarReplace\">\n Заменить\n </UidButton>\n </div>\n\n <div class=\"admin-profile__form\">\n <UidInput\n v-model=\"profile.name\"\n label=\"Имя\"\n name=\"name\"\n />\n <UidInput\n v-model=\"profile.email\"\n label=\"Email\"\n type=\"email\"\n name=\"email\"\n />\n <UidSelect\n v-model=\"profile.locale\"\n :options=\"localeOptions\"\n label=\"Язык\"\n />\n <UidSelect\n v-model=\"profile.theme\"\n :options=\"themeOptions\"\n label=\"Тема\"\n />\n </div>\n\n <footer class=\"admin-profile__card-ft\">\n <UidButton variant=\"primary\" @click=\"onSave\">Сохранить</UidButton>\n </footer>\n </UidCard>\n\n <!-- Security -->\n <UidCard v-else-if=\"localSection === 'security'\" padding=\"md\">\n <header class=\"admin-profile__card-hd\">\n <h3 class=\"admin-profile__card-title\">Двухфакторная аутентификация</h3>\n <UidBadge :variant=\"has2FA ? 'success' : 'default'\">\n {{ has2FA ? 'Включена' : 'Отключена' }}\n </UidBadge>\n </header>\n\n <p v-if=\"has2FA\" class=\"admin-profile__hint\">\n 2FA включена. У вас остались recovery-коды на случай потери устройства.\n </p>\n <p v-else class=\"admin-profile__hint\">\n Включите 2FA для дополнительной защиты аккаунта.\n </p>\n\n <footer class=\"admin-profile__card-ft\">\n <template v-if=\"has2FA\">\n <UidButton variant=\"ghost\" size=\"sm\" @click=\"on2FARegenerate\">\n Перегенерировать коды\n </UidButton>\n <UidButton variant=\"danger\" size=\"sm\" @click=\"on2FADisable\">\n Отключить 2FA\n </UidButton>\n </template>\n <template v-else>\n <slot name=\"enable-2fa\">\n <UidButton variant=\"primary\" disabled>\n Включить 2FA (host customize)\n </UidButton>\n </slot>\n </template>\n </footer>\n </UidCard>\n\n <!-- Tokens / Sessions / другое — host рендерит через slot -->\n <slot v-else :name=\"localSection\" :section=\"localSection\">\n <UidCard padding=\"md\">\n <p class=\"admin-profile__hint\">\n Section «{{ localSection }}» не реализована библиотекой —\n host-проект подключает её через slot {{ localSection }}.\n </p>\n </UidCard>\n </slot>\n </div>\n </div>\n </section>\n</template>\n\n<style>\n.admin-profile__layout {\n display: grid;\n grid-template-columns: 200px 1fr;\n gap: var(--uid-space-lg);\n align-items: start;\n}\n.admin-profile__nav {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n.admin-profile__nav-item {\n appearance: none;\n border: 0;\n background: transparent;\n text-align: left;\n display: flex;\n align-items: center;\n gap: var(--uid-space-sm);\n padding: var(--uid-space-sm) var(--uid-space-sm);\n border-radius: var(--uid-radius-md);\n font-size: 13px;\n color: var(--uid-text-secondary);\n cursor: pointer;\n}\n.admin-profile__nav-item:hover {\n background: var(--uid-surface-hover);\n color: var(--uid-text-primary);\n}\n.admin-profile__nav-item--active {\n background: var(--uid-surface-base);\n color: var(--uid-text-primary);\n font-weight: var(--uid-font-weight-medium);\n}\n.admin-profile__nav-icon {\n width: 14px;\n height: 14px;\n flex: none;\n}\n.admin-profile__content {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-md);\n}\n\n.admin-profile__card-hd {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: var(--uid-space-md);\n}\n.admin-profile__card-title {\n margin: 0;\n font-size: var(--uid-font-size-sm);\n font-weight: var(--uid-font-weight-semibold);\n}\n.admin-profile__card-ft {\n margin-top: var(--uid-space-md);\n display: flex;\n gap: var(--uid-space-sm);\n}\n.admin-profile__hint {\n margin: 0;\n font-size: var(--uid-font-size-sm);\n color: var(--uid-text-secondary);\n}\n\n.admin-profile__hero {\n display: flex;\n align-items: center;\n gap: var(--uid-space-md);\n margin-bottom: var(--uid-space-md);\n}\n.admin-profile__hero-text { display: flex; flex-direction: column; gap: 4px; }\n.admin-profile__hero-name {\n font-weight: var(--uid-font-weight-semibold);\n color: var(--uid-text-primary);\n}\n.admin-profile__hero-meta {\n font-size: var(--uid-font-size-xs);\n color: var(--uid-text-tertiary);\n}\n\n.admin-profile__form {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: var(--uid-space-md);\n}\n@media (max-width: 720px) {\n .admin-profile__form { grid-template-columns: 1fr; }\n}\n</style>\n","/**\n * Реестр dashboard widget-компонентов.\n *\n * Manifest узлы dashboard выглядят так:\n * {\n * slug: 'main',\n * label: 'Главный',\n * widgets: [\n * { type: 'stat', name: 'total', title: 'Всего', value: 1284,\n * span: 3, trend: 12 },\n * { type: 'bar-chart', span: 8, ... },\n * { type: 'recent-table', span: 8, columns: [...], rows: [...] },\n * ]\n * }\n *\n * Host регистрирует кастомные widget'ы через `registerWidget()` /\n * `registerWidgets()` bundle.\n */\n\nimport type { Component } from 'vue'\nimport { createComponentRegistry } from '../createComponentRegistry'\n\nconst widgets = createComponentRegistry<Component>()\n\nexport const registerWidget = widgets.register\nexport const getWidget = widgets.get\nexport const hasWidget = widgets.has\nexport const listWidgets = widgets.list\nexport const clearWidgetRegistry = widgets.clear\nexport const registerWidgets = widgets.registerBundle\n","<script setup lang=\"ts\">\nimport { UidAlert } from '@dskripchenko/ui'\n\ninterface Props {\n type: string\n}\ndefineProps<Props>()\n</script>\n\n<template>\n <UidAlert variant=\"warning\">\n <template #title>Неизвестный widget-тип: {{ type }}</template>\n Зарегистрируйте через <code>registerWidget('{{ type }}', YourComponent)</code>.\n </UidAlert>\n</template>\n","<script setup lang=\"ts\">\n/**\n * Резолвит widget-компонент по `node.type` и forwards остальные props.\n */\nimport { computed } from 'vue'\nimport { getWidget } from './registry'\nimport UnknownWidget from './UnknownWidget.vue'\n\nexport interface WidgetNode extends Record<string, unknown> {\n type: string\n /** Сколько колонок занимает в 12-grid (1..12). */\n span?: number\n}\n\ninterface Props {\n node: WidgetNode\n}\nconst props = defineProps<Props>()\n\nconst component = computed(() => getWidget(props.node.type))\nconst widgetProps = computed(() => {\n const { type: _type, span: _span, ...rest } = props.node\n return rest\n})\n</script>\n\n<template>\n <component :is=\"component\" v-if=\"component\" v-bind=\"widgetProps\" />\n <UnknownWidget v-else :type=\"node.type\" />\n</template>\n","<script setup lang=\"ts\">\n/**\n * DashboardPage — 12-col grid из widget'ов по эталону handoff'а\n * (docs/design_handoff_laravel_admin/screens-secondary.jsx → Dashboard).\n *\n * Источник widget'ов:\n * - Если задан `slug` — берём dashboard из manifest.dashboards по slug\n * - Если задан `widgets` prop — рендерим переданные узлы напрямую\n *\n * Каждый widget — `{ type: 'stat', span: 3, title: '...', value: 1284 }`,\n * span — колонки в 12-grid (1..12), default 12 (full width).\n */\nimport { computed } from 'vue'\nimport { useManifestStore } from '../../stores/manifest'\nimport WidgetRenderer, { type WidgetNode } from './WidgetRenderer.vue'\n\ninterface DashboardManifest {\n slug: string\n label?: string\n description?: string | null\n widgets: WidgetNode[]\n}\n\ninterface Props {\n /** Slug dashboard'а в manifest.dashboards. */\n slug?: string\n /** Прямой override widget'ов (если slug не задан или не нашёлся). */\n widgets?: WidgetNode[]\n /** Заголовок страницы. */\n title?: string\n /** Подзаголовок (description). */\n subtitle?: string\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n slug: undefined,\n widgets: undefined,\n title: undefined,\n subtitle: undefined,\n})\n\nconst manifest = useManifestStore()\n\nconst dashboard = computed<DashboardManifest | null>(() => {\n if (!props.slug || !manifest.manifest) return null\n const dashboards = manifest.manifest.dashboards as DashboardManifest[] | undefined\n return dashboards?.find((d) => d.slug === props.slug) ?? null\n})\n\nconst resolvedWidgets = computed<WidgetNode[]>(() => {\n if (props.widgets) return props.widgets\n if (dashboard.value) return dashboard.value.widgets ?? []\n return []\n})\n\nconst resolvedTitle = computed(\n () => props.title ?? dashboard.value?.label ?? 'Dashboard',\n)\nconst resolvedSubtitle = computed(\n () => props.subtitle ?? dashboard.value?.description ?? null,\n)\n\nfunction spanFor(w: WidgetNode): number {\n const s = typeof w.span === 'number' ? w.span : 12\n return Math.max(1, Math.min(12, s))\n}\n</script>\n\n<template>\n <section class=\"admin-page admin-dashboard\">\n <header class=\"admin-page__hd\">\n <div class=\"admin-page__title-wrap\">\n <h1 class=\"admin-page__title\">{{ resolvedTitle }}</h1>\n <div v-if=\"resolvedSubtitle\" class=\"admin-page__count\">\n {{ resolvedSubtitle }}\n </div>\n </div>\n <div class=\"admin-page__actions\">\n <slot name=\"actions\" />\n </div>\n </header>\n\n <div class=\"admin-dashboard__grid\">\n <div\n v-for=\"(w, idx) in resolvedWidgets\"\n :key=\"idx\"\n class=\"admin-dashboard__cell\"\n :style=\"{ gridColumn: `span ${spanFor(w)} / span ${spanFor(w)}` }\"\n >\n <WidgetRenderer :node=\"w\" />\n </div>\n </div>\n </section>\n</template>\n\n<style>\n.admin-dashboard__grid {\n display: grid;\n grid-template-columns: repeat(12, minmax(0, 1fr));\n gap: var(--uid-space-md);\n}\n.admin-dashboard__cell {\n min-width: 0;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { UidStat } from '@dskripchenko/ui'\nimport type { StatTone } from '@dskripchenko/ui'\n\ntype SemanticTone = 'neutral' | 'positive' | 'negative' | 'warning' | 'info'\n\ninterface Props {\n title?: string\n value?: number | string\n prefix?: string\n suffix?: string\n trend?: number\n precision?: number\n tone?: SemanticTone\n loading?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n title: '',\n value: 0,\n prefix: '',\n suffix: '',\n trend: undefined,\n precision: 0,\n tone: 'neutral',\n loading: false,\n})\n\nconst TONE_MAP: Record<SemanticTone, StatTone> = {\n neutral: 'primary',\n positive: 'success',\n negative: 'danger',\n warning: 'warning',\n info: 'info',\n}\n\nconst uidTone = computed<StatTone>(() => TONE_MAP[props.tone])\n</script>\n\n<template>\n <UidStat\n :title=\"title\"\n :value=\"value\"\n :prefix=\"prefix\"\n :suffix=\"suffix\"\n :trend=\"trend\"\n :precision=\"precision\"\n :tone=\"uidTone\"\n :loading=\"loading\"\n />\n</template>\n","<script setup lang=\"ts\">\n/**\n * BarChartWidget — простой SVG-bar chart без внешних зависимостей.\n *\n * Manifest:\n * { type: 'bar-chart', title: '30 дней',\n * data: [{ label: '01', value: 12 }, ...],\n * accent: 'var(--uid-accent)' }\n */\nimport { computed } from 'vue'\nimport { UidCard } from '@dskripchenko/ui'\n\ninterface Datum {\n label: string\n value: number\n}\n\ninterface Props {\n title?: string\n description?: string\n data: Datum[]\n accent?: string\n height?: number\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n title: '',\n description: '',\n accent: 'var(--uid-accent)',\n height: 200,\n})\n\nconst maxValue = computed(() => Math.max(1, ...props.data.map((d) => d.value)))\n\nconst bars = computed(() => {\n const n = Math.max(1, props.data.length)\n const barWidth = 100 / n\n return props.data.map((d, i) => ({\n label: d.label,\n value: d.value,\n x: i * barWidth + barWidth * 0.1,\n width: barWidth * 0.8,\n heightPct: (d.value / maxValue.value) * 100,\n }))\n})\n</script>\n\n<template>\n <UidCard padding=\"md\" class=\"admin-widget\">\n <header v-if=\"title || description\" class=\"admin-widget__hd\">\n <h3 v-if=\"title\" class=\"admin-widget__title\">{{ title }}</h3>\n <p v-if=\"description\" class=\"admin-widget__desc\">{{ description }}</p>\n </header>\n <svg\n class=\"admin-widget-bar-chart\"\n :viewBox=\"`0 0 100 ${height}`\"\n preserveAspectRatio=\"none\"\n :height=\"height\"\n width=\"100%\"\n role=\"img\"\n :aria-label=\"title || 'Bar chart'\"\n >\n <rect\n v-for=\"(bar, idx) in bars\"\n :key=\"idx\"\n :x=\"bar.x\"\n :y=\"height - (bar.heightPct / 100) * height\"\n :width=\"bar.width\"\n :height=\"(bar.heightPct / 100) * height\"\n :fill=\"accent\"\n rx=\"1\"\n :data-label=\"bar.label\"\n :data-value=\"bar.value\"\n >\n <title>{{ bar.label }}: {{ bar.value }}</title>\n </rect>\n </svg>\n </UidCard>\n</template>\n\n<style>\n.admin-widget__hd { margin-bottom: var(--uid-space-sm); }\n.admin-widget__title {\n margin: 0;\n font-size: var(--uid-font-size-sm);\n font-weight: var(--uid-font-weight-semibold);\n color: var(--uid-text-primary);\n}\n.admin-widget__desc {\n margin: var(--uid-space-2xs) 0 0;\n font-size: var(--uid-font-size-xs);\n color: var(--uid-text-tertiary);\n}\n.admin-widget-bar-chart {\n display: block;\n width: 100%;\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * DonutChartWidget — SVG donut + legend.\n *\n * Manifest:\n * { type: 'donut-chart', title: 'Status',\n * data: [{ label: 'Published', value: 156, color: '...' }, ...] }\n */\nimport { computed } from 'vue'\nimport { UidCard } from '@dskripchenko/ui'\n\ninterface Slice {\n label: string\n value: number\n color?: string\n}\n\ninterface Props {\n title?: string\n data: Slice[]\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n title: '',\n})\n\nconst PALETTE = [\n 'var(--uid-color-teal-500, #14b8a6)',\n 'var(--uid-color-zinc-700, #3f3f46)',\n 'var(--uid-color-amber-400, #fbbf24)',\n 'var(--uid-color-rose-400, #fb7185)',\n 'var(--uid-color-blue-400, #60a5fa)',\n]\n\nconst total = computed(() => props.data.reduce((s, x) => s + x.value, 0) || 1)\n\nconst slices = computed(() => {\n let cumulative = 0\n return props.data.map((s, idx) => {\n const startAngle = (cumulative / total.value) * 2 * Math.PI\n cumulative += s.value\n const endAngle = (cumulative / total.value) * 2 * Math.PI\n\n const r = 50\n const cx = 60\n const cy = 60\n\n const x1 = cx + r * Math.cos(startAngle - Math.PI / 2)\n const y1 = cy + r * Math.sin(startAngle - Math.PI / 2)\n const x2 = cx + r * Math.cos(endAngle - Math.PI / 2)\n const y2 = cy + r * Math.sin(endAngle - Math.PI / 2)\n\n const largeArc = endAngle - startAngle > Math.PI ? 1 : 0\n\n const path = props.data.length === 1\n ? `M ${cx - r} ${cy} a ${r} ${r} 0 1 0 ${r * 2} 0 a ${r} ${r} 0 1 0 ${-r * 2} 0`\n : `M ${cx} ${cy} L ${x1} ${y1} A ${r} ${r} 0 ${largeArc} 1 ${x2} ${y2} Z`\n\n return {\n ...s,\n path,\n color: s.color ?? PALETTE[idx % PALETTE.length],\n pct: ((s.value / total.value) * 100).toFixed(1),\n }\n })\n})\n</script>\n\n<template>\n <UidCard padding=\"md\" class=\"admin-widget admin-donut-widget\">\n <header v-if=\"title\" class=\"admin-widget__hd\">\n <h3 class=\"admin-widget__title\">{{ title }}</h3>\n </header>\n <div class=\"admin-donut-widget__row\">\n <svg viewBox=\"0 0 120 120\" class=\"admin-donut-widget__svg\" role=\"img\" :aria-label=\"title\">\n <path\n v-for=\"(s, idx) in slices\"\n :key=\"idx\"\n :d=\"s.path\"\n :fill=\"s.color\"\n >\n <title>{{ s.label }}: {{ s.value }} ({{ s.pct }}%)</title>\n </path>\n <circle cx=\"60\" cy=\"60\" r=\"30\" fill=\"var(--uid-surface-raised)\" />\n </svg>\n <ul class=\"admin-donut-widget__legend\">\n <li v-for=\"(s, idx) in slices\" :key=\"idx\">\n <span class=\"admin-donut-widget__dot\" :style=\"{ background: s.color }\" />\n <span class=\"admin-donut-widget__label\">{{ s.label }}</span>\n <span class=\"admin-donut-widget__value\">{{ s.pct }}%</span>\n </li>\n </ul>\n </div>\n </UidCard>\n</template>\n\n<style>\n.admin-donut-widget__row {\n display: flex;\n align-items: center;\n gap: var(--uid-space-md);\n}\n.admin-donut-widget__svg {\n width: 120px;\n height: 120px;\n flex: none;\n}\n.admin-donut-widget__legend {\n list-style: none;\n margin: 0;\n padding: 0;\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-xs);\n}\n.admin-donut-widget__legend li {\n display: flex;\n align-items: center;\n gap: var(--uid-space-sm);\n font-size: var(--uid-font-size-xs);\n}\n.admin-donut-widget__dot {\n width: 10px;\n height: 10px;\n border-radius: var(--uid-radius-full);\n flex: none;\n}\n.admin-donut-widget__label { flex: 1; color: var(--uid-text-primary); }\n.admin-donut-widget__value {\n color: var(--uid-text-tertiary);\n font-variant-numeric: tabular-nums;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { UidCard, UidTable, type UidTableColumn } from '@dskripchenko/ui'\n\ninterface Props {\n title?: string\n columns: UidTableColumn[]\n rows: Record<string, unknown>[]\n emptyText?: string\n}\n\nwithDefaults(defineProps<Props>(), {\n title: '',\n emptyText: 'Нет данных',\n})\n</script>\n\n<template>\n <UidCard padding=\"md\" class=\"admin-widget\">\n <header v-if=\"title\" class=\"admin-widget__hd\">\n <h3 class=\"admin-widget__title\">{{ title }}</h3>\n </header>\n <UidTable :columns=\"columns\" :data=\"rows\" :empty-text=\"emptyText\" />\n </UidCard>\n</template>\n","<script setup lang=\"ts\">\nimport { UidCard, UidHeatmap } from '@dskripchenko/ui'\n\ninterface HeatmapPoint {\n date: string\n value: number\n}\n\ninterface Props {\n title?: string\n data: HeatmapPoint[]\n levels?: number\n color?: string\n gap?: number\n}\n\nwithDefaults(defineProps<Props>(), {\n title: '',\n levels: 5,\n color: undefined,\n gap: 2,\n})\n</script>\n\n<template>\n <UidCard padding=\"md\" class=\"admin-widget\">\n <header v-if=\"title\" class=\"admin-widget__hd\">\n <h3 class=\"admin-widget__title\">{{ title }}</h3>\n </header>\n <UidHeatmap :data=\"data\" :levels=\"levels\" :color=\"color\" :gap=\"gap\" />\n </UidCard>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { UidCard, UidGauge } from '@dskripchenko/ui'\nimport type { GaugeTone, GaugeRange } from '@dskripchenko/ui'\n\ntype SemanticTone = 'neutral' | 'positive' | 'warning' | 'negative'\n\ninterface Props {\n title?: string\n value?: number\n min?: number\n max?: number\n size?: number\n ranges?: GaugeRange[]\n tone?: SemanticTone\n color?: string\n label?: string\n suffix?: string\n precision?: number\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n title: '',\n value: 0,\n min: 0,\n max: 100,\n size: 160,\n ranges: () => [],\n tone: 'neutral',\n color: undefined,\n label: '',\n suffix: '',\n precision: 0,\n})\n\nconst TONE_MAP: Record<SemanticTone, GaugeTone> = {\n neutral: 'primary',\n positive: 'success',\n warning: 'warning',\n negative: 'danger',\n}\n\nconst uidTone = computed<GaugeTone>(() => TONE_MAP[props.tone])\n</script>\n\n<template>\n <UidCard padding=\"md\" class=\"admin-widget\">\n <header v-if=\"title\" class=\"admin-widget__hd\">\n <h3 class=\"admin-widget__title\">{{ title }}</h3>\n </header>\n <div style=\"display:flex; justify-content:center;\">\n <UidGauge\n :value=\"value\"\n :min=\"min\"\n :max=\"max\"\n :size=\"size\"\n :ranges=\"ranges\"\n :tone=\"uidTone\"\n :color=\"color\"\n :label=\"label\"\n :suffix=\"suffix\"\n :precision=\"precision\"\n />\n </div>\n </UidCard>\n</template>\n","<script setup lang=\"ts\">\n/**\n * Markdown widget — простой preformatted-блок. Для production хост может\n * подкинуть свой widget с marked/MDX через registerWidget('markdown', ...).\n *\n * Тут — fallback с базовым форматированием через line-break preserve.\n */\nimport { UidCard } from '@dskripchenko/ui'\n\ninterface Props {\n title?: string\n content: string\n}\n\nwithDefaults(defineProps<Props>(), { title: '' })\n</script>\n\n<template>\n <UidCard padding=\"md\" class=\"admin-widget\">\n <header v-if=\"title\" class=\"admin-widget__hd\">\n <h3 class=\"admin-widget__title\">{{ title }}</h3>\n </header>\n <div class=\"admin-markdown-widget\">{{ content }}</div>\n </UidCard>\n</template>\n\n<style>\n.admin-markdown-widget {\n font-size: var(--uid-font-size-sm);\n color: var(--uid-text-secondary);\n white-space: pre-wrap;\n line-height: var(--uid-line-height-normal);\n}\n</style>\n","/**\n * Default-bundle с минимальным набором builtin widget-типов.\n */\n\nimport { registerWidgets } from './registry'\nimport StatWidget from './StatWidget.vue'\nimport BarChartWidget from './BarChartWidget.vue'\nimport DonutChartWidget from './DonutChartWidget.vue'\nimport RecentTableWidget from './RecentTableWidget.vue'\nimport HeatmapWidget from './HeatmapWidget.vue'\nimport GaugeWidget from './GaugeWidget.vue'\nimport MarkdownWidget from './MarkdownWidget.vue'\n\nexport function registerBuiltinWidgets(): void {\n registerWidgets({\n stat: StatWidget,\n 'bar-chart': BarChartWidget,\n 'donut-chart': DonutChartWidget,\n 'recent-table': RecentTableWidget,\n heatmap: HeatmapWidget,\n gauge: GaugeWidget,\n markdown: MarkdownWidget,\n })\n}\n","/**\n * Контракт ответов laravel-api: каждое тело — `{success, payload}`.\n *\n * Success: `{success: true, payload: {...}}`\n * Error: `{success: false, payload: {errorKey, message, ...}}`\n *\n * Helper'ы здесь — для type-narrowing'а в потребителях.\n */\n\nexport interface SuccessEnvelope<T = unknown> {\n success: true\n payload: T\n}\n\nexport interface ErrorEnvelope {\n success: false\n payload: {\n errorKey: string\n message: string\n messages?: Record<string, string[]>\n [key: string]: unknown\n }\n}\n\nexport type ApiEnvelope<T = unknown> = SuccessEnvelope<T> | ErrorEnvelope\n\nexport function isSuccess<T>(env: ApiEnvelope<T>): env is SuccessEnvelope<T> {\n return env.success === true\n}\n\nexport function isError(env: ApiEnvelope): env is ErrorEnvelope {\n return env.success === false\n}\n","/**\n * Axios-клиент для admin API.\n *\n * Особенности:\n * - baseURL берётся из bootstrap.apiUrl (либо передаётся явно).\n * - X-XSRF-TOKEN добавляется автоматически из cookie (Laravel Sanctum/web).\n * - X-CSRF-TOKEN — fallback из meta[name=csrf-token] (Blade-injection).\n * - X-Admin-Locale выставляется при наличии текущей локали.\n * - Response interceptor разворачивает envelope и бросает ApiError.\n * - 401 → onUnauthenticated callback (редирект на login на стороне consumer'а).\n */\n\nimport axios, { AxiosError, type AxiosInstance, type AxiosRequestConfig } from 'axios'\nimport { isSuccess, type ApiEnvelope, type ErrorEnvelope } from './envelope'\nimport { NetworkError, toApiError, UnauthenticatedError } from './errors'\n\nexport interface ClientOptions {\n baseURL: string\n csrfToken?: string\n locale?: string\n /** Вызывается при 401. Обычно — push на /admin/login. */\n onUnauthenticated?: () => void\n}\n\nexport interface AdminClient {\n /** Низкоуровневый axios — для специфичных случаев. */\n raw: AxiosInstance\n get<T = unknown>(url: string, config?: AxiosRequestConfig): Promise<T>\n post<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T>\n put<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T>\n patch<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T>\n delete<T = unknown>(url: string, config?: AxiosRequestConfig): Promise<T>\n setLocale(locale: string): void\n}\n\nexport function createAdminClient(opts: ClientOptions): AdminClient {\n const instance = axios.create({\n baseURL: opts.baseURL,\n withCredentials: true,\n headers: {\n Accept: 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n })\n\n if (opts.csrfToken) {\n instance.defaults.headers.common['X-CSRF-TOKEN'] = opts.csrfToken\n }\n if (opts.locale) {\n instance.defaults.headers.common['X-Admin-Locale'] = opts.locale\n }\n\n // Подцепляем XSRF из cookie на каждый запрос — браузер сам обновит\n // его после первого 419, но axios reads на вызове.\n instance.interceptors.request.use((config) => {\n const xsrf = readCookie('XSRF-TOKEN')\n if (xsrf) {\n config.headers.set('X-XSRF-TOKEN', decodeURIComponent(xsrf))\n }\n return config\n })\n\n // Response interceptor — разворачиваем envelope, бросаем правильную ошибку.\n instance.interceptors.response.use(\n (response) => {\n const env = response.data as ApiEnvelope\n if (env && typeof env === 'object' && 'success' in env) {\n if (isSuccess(env)) {\n // payload подменяет data — теперь callers получают чистый payload.\n response.data = env.payload\n return response\n }\n // success: false → throw как ApiError\n throw toApiError(response.status, env.payload)\n }\n // Не envelope (например, бинарный stream) — пропускаем как есть.\n return response\n },\n (error: AxiosError<ErrorEnvelope>) => {\n if (error.response) {\n const status = error.response.status\n const payload =\n error.response.data?.payload ?? {\n errorKey: 'unknown',\n message: error.message,\n }\n const apiError = toApiError(status, payload)\n if (apiError instanceof UnauthenticatedError) {\n opts.onUnauthenticated?.()\n }\n return Promise.reject(apiError)\n }\n // network failure / timeout\n return Promise.reject(new NetworkError(error.message))\n },\n )\n\n const wrap = <T>(method: 'get' | 'delete', url: string, config?: AxiosRequestConfig): Promise<T> =>\n instance[method]<unknown, { data: T }>(url, config).then((r) => r.data)\n\n const wrapBody = <T>(\n method: 'post' | 'put' | 'patch',\n url: string,\n data?: unknown,\n config?: AxiosRequestConfig,\n ): Promise<T> => instance[method]<unknown, { data: T }>(url, data, config).then((r) => r.data)\n\n return {\n raw: instance,\n get: <T>(url: string, config?: AxiosRequestConfig) => wrap<T>('get', url, config),\n delete: <T>(url: string, config?: AxiosRequestConfig) => wrap<T>('delete', url, config),\n post: <T>(url: string, data?: unknown, config?: AxiosRequestConfig) =>\n wrapBody<T>('post', url, data, config),\n put: <T>(url: string, data?: unknown, config?: AxiosRequestConfig) =>\n wrapBody<T>('put', url, data, config),\n patch: <T>(url: string, data?: unknown, config?: AxiosRequestConfig) =>\n wrapBody<T>('patch', url, data, config),\n setLocale: (locale: string): void => {\n instance.defaults.headers.common['X-Admin-Locale'] = locale\n },\n }\n}\n\n/** Читает cookie из document.cookie. Returns null если нет. */\nfunction readCookie(name: string): string | null {\n if (typeof document === 'undefined') return null\n const match = document.cookie.match(new RegExp('(^|; )' + escapeRegex(name) + '=([^;]*)'))\n return match ? match[2] : null\n}\n\nfunction escapeRegex(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n","/**\n * buildRoutesFromManifest — превращает AdminManifest в массив RouteRecordRaw.\n *\n * Маппинг:\n * - resource{slug} → /r/{slug} (index)\n * /r/{slug}/create (create)\n * /r/{slug}/:id/edit (edit)\n * /r/{slug}/:id (view, опционально)\n * - screen{slug} → /screens/{slug}\n * - settings{slug} → /settings/{slug}\n * - dashboard{slug} → /dashboard/{slug}\n *\n * Component'ы передаются через resolver — host-проект решает, что отрисовать.\n * Это позволяет library не тащить рендереры внутрь себя жёстко.\n */\n\nimport type { RouteRecordRaw } from 'vue-router'\nimport type { Component } from 'vue'\nimport type {\n AdminManifest,\n ManifestResourceMeta,\n ManifestScreenMeta,\n ManifestSettingsMeta,\n} from '../stores/manifest'\n\n/** Vue Component либо async-loader (для code-splitting). */\nexport type AdminRouteComponent = Component | (() => Promise<Component>)\n\nexport interface RouteMeta {\n /** Требует залогиненного пользователя. */\n requiresAuth?: boolean\n /** Permissions, нужные для входа. ANY-логика (хотя бы одно совпадение). */\n permissions?: string[]\n /** Заголовок страницы (рендерим в <title> через router.afterEach). */\n title?: string\n /** Тип админ-роута — для UI breadcrumbs/active-state. */\n kind?: 'resource' | 'screen' | 'settings' | 'dashboard' | 'system' | 'auth'\n /** Slug сущности из манифеста — для извлечения мета внутри компонента. */\n slug?: string\n}\n\ndeclare module 'vue-router' {\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n interface RouteMeta extends Record<string, unknown> {}\n}\n\n/**\n * Resolver компонентов для динамических роутов.\n *\n * Host-проект передаёт конкретные Vue-компоненты для каждой роли.\n * Library не зависит от конкретных view'ов.\n */\nexport interface RouteComponentResolver {\n resourceIndex: AdminRouteComponent\n resourceCreate: AdminRouteComponent\n resourceEdit: AdminRouteComponent\n resourceView: AdminRouteComponent\n screen: AdminRouteComponent\n settings: AdminRouteComponent\n dashboard: AdminRouteComponent\n}\n\n/**\n * Извлекает permissions из meta'ы ресурса / скрина / settings'а.\n *\n * resource.permissions = { view: 'admin.users.view', ... } → ['admin.users.view']\n * (для index используется view; для create/edit — соответственно).\n */\nfunction pickResourcePermission(\n resource: ManifestResourceMeta,\n ability: 'view' | 'create' | 'update',\n): string[] {\n const perm = resource.permissions?.[ability]\n return typeof perm === 'string' && perm.length > 0 ? [perm] : []\n}\n\nfunction pickSettingsPermission(s: ManifestSettingsMeta, ability: 'view' | 'update'): string[] {\n const perm = s.permissions?.[ability]\n return typeof perm === 'string' && perm.length > 0 ? [perm] : []\n}\n\nfunction pickScreenPermission(s: ManifestScreenMeta): string[] {\n if (Array.isArray(s.permission)) return s.permission\n if (typeof s.permission === 'string' && s.permission.length > 0) return [s.permission]\n return []\n}\n\nfunction buildResourceRoutes(\n resource: ManifestResourceMeta,\n components: RouteComponentResolver,\n): RouteRecordRaw[] {\n const slug = resource.slug\n const base = `/r/${slug}`\n\n return [\n {\n path: base,\n name: `admin.resource.${slug}.index`,\n component: components.resourceIndex,\n meta: {\n requiresAuth: true,\n kind: 'resource',\n slug,\n title: resource.label,\n permissions: pickResourcePermission(resource, 'view'),\n },\n },\n {\n path: `${base}/create`,\n name: `admin.resource.${slug}.create`,\n component: components.resourceCreate,\n meta: {\n requiresAuth: true,\n kind: 'resource',\n slug,\n title: `${resource.label}: создать`,\n permissions: pickResourcePermission(resource, 'create'),\n },\n },\n {\n path: `${base}/:id/edit`,\n name: `admin.resource.${slug}.edit`,\n component: components.resourceEdit,\n meta: {\n requiresAuth: true,\n kind: 'resource',\n slug,\n title: `${resource.label}: редактирование`,\n permissions: pickResourcePermission(resource, 'update'),\n },\n props: true,\n },\n {\n path: `${base}/:id`,\n name: `admin.resource.${slug}.view`,\n component: components.resourceView,\n meta: {\n requiresAuth: true,\n kind: 'resource',\n slug,\n title: resource.label,\n permissions: pickResourcePermission(resource, 'view'),\n },\n props: true,\n },\n ]\n}\n\nfunction buildScreenRoute(\n screen: ManifestScreenMeta,\n components: RouteComponentResolver,\n): RouteRecordRaw {\n return {\n path: `/screens/${screen.slug}`,\n name: `admin.screen.${screen.slug}`,\n component: components.screen,\n meta: {\n requiresAuth: true,\n kind: 'screen',\n slug: screen.slug,\n title: screen.name,\n permissions: pickScreenPermission(screen),\n },\n }\n}\n\nfunction buildSettingsRoute(\n settings: ManifestSettingsMeta,\n components: RouteComponentResolver,\n): RouteRecordRaw {\n return {\n path: `/settings/${settings.slug}`,\n name: `admin.settings.${settings.slug}`,\n component: components.settings,\n meta: {\n requiresAuth: true,\n kind: 'settings',\n slug: settings.slug,\n title: settings.label,\n permissions: pickSettingsPermission(settings, 'view'),\n },\n }\n}\n\ninterface DashboardMeta {\n slug?: string\n label?: string\n permission?: string | string[] | null\n}\n\nfunction buildDashboardRoute(\n dashboard: DashboardMeta,\n components: RouteComponentResolver,\n): RouteRecordRaw | null {\n if (typeof dashboard.slug !== 'string' || dashboard.slug.length === 0) return null\n const permission = dashboard.permission\n const permissions = Array.isArray(permission)\n ? permission\n : typeof permission === 'string' && permission.length > 0\n ? [permission]\n : []\n return {\n path: `/dashboard/${dashboard.slug}`,\n name: `admin.dashboard.${dashboard.slug}`,\n component: components.dashboard,\n meta: {\n requiresAuth: true,\n kind: 'dashboard',\n slug: dashboard.slug,\n title: dashboard.label ?? 'Dashboard',\n permissions,\n },\n }\n}\n\nexport function buildRoutesFromManifest(\n manifest: AdminManifest | null,\n components: RouteComponentResolver,\n): RouteRecordRaw[] {\n if (manifest === null) return []\n\n const routes: RouteRecordRaw[] = []\n\n for (const resource of manifest.resources) {\n routes.push(...buildResourceRoutes(resource, components))\n }\n for (const screen of manifest.screens) {\n routes.push(buildScreenRoute(screen, components))\n }\n for (const s of manifest.settings) {\n routes.push(buildSettingsRoute(s, components))\n }\n for (const d of manifest.dashboards as DashboardMeta[]) {\n const route = buildDashboardRoute(d, components)\n if (route) routes.push(route)\n }\n\n return routes\n}\n","/**\n * Router-guards: auth + permissions.\n *\n * Логика:\n * 1. Если route.meta.requiresAuth и пользователь не залогинен → /login\n * с ?redirect=...\n * 2. Если у user'а есть pendingChallenge (2FA) — все защищённые роуты\n * редиректят на /login (challenge-form там).\n * 3. Если route.meta.permissions заданы — проверяем hasAnyPermission().\n * Нет ни одного → /forbidden (или роут с name='admin.forbidden').\n *\n * Guards используют useAuthStore — но НЕ берут client напрямую: всё через\n * permissions/isAuthenticated/pendingChallenge state. Stores должны быть\n * захайдрейчены до setup'а router'а.\n */\n\nimport type { RouteLocationNormalized, RouteLocationRaw } from 'vue-router'\nimport { useAuthStore } from '../stores/auth'\n\n/** Тип возвращаемого значения guard'а — true (passthrough) либо redirect-target. */\ntype GuardResult = boolean | RouteLocationRaw\n\n/**\n * Простая 3-арг функция (то что router.beforeEach принимает).\n * Не используем NavigationGuardWithThis<undefined>, т.к. она требует\n * `this: undefined` что неудобно для прямого вызова в тестах.\n */\ntype SimpleGuard = (\n to: RouteLocationNormalized,\n from: RouteLocationNormalized,\n next?: unknown,\n) => GuardResult\n\nexport interface AuthGuardOptions {\n /** Имя login-роута. По умолчанию 'admin.login'. */\n loginRouteName?: string\n /** Имя роута 403-страницы. По умолчанию 'admin.forbidden'. */\n forbiddenRouteName?: string\n /**\n * Имя query-параметра для возврата на исходную страницу после login.\n * По умолчанию 'redirect'.\n */\n redirectQueryKey?: string\n}\n\n/**\n * Создаёт beforeEach guard. Pinia должна быть activeInstance к моменту\n * вызова guard'а (router.beforeEach срабатывает на каждой навигации,\n * включая первую — Pinia уже должна быть установлена).\n */\nexport function createAuthGuard(opts: AuthGuardOptions = {}): SimpleGuard {\n const loginRouteName = opts.loginRouteName ?? 'admin.login'\n const forbiddenRouteName = opts.forbiddenRouteName ?? 'admin.forbidden'\n const redirectQueryKey = opts.redirectQueryKey ?? 'redirect'\n\n return (to: RouteLocationNormalized) => {\n // Login-роут всегда доступен.\n if (to.name === loginRouteName) {\n return true\n }\n\n const auth = useAuthStore()\n const requiresAuth = to.meta?.requiresAuth === true\n\n if (requiresAuth && !auth.isAuthenticated) {\n return {\n name: loginRouteName,\n query: { [redirectQueryKey]: to.fullPath },\n }\n }\n\n // Залогиненный, но в процессе 2FA — нельзя ходить никуда кроме login.\n if (auth.isChallengePending) {\n return {\n name: loginRouteName,\n query: { [redirectQueryKey]: to.fullPath },\n }\n }\n\n // Permission-check. ANY-логика (хотя бы одно permission совпало).\n const permissionsMeta = to.meta?.permissions\n if (Array.isArray(permissionsMeta) && permissionsMeta.length > 0) {\n const allowed = auth.hasAnyPermission(permissionsMeta as string[])\n if (!allowed) {\n return { name: forbiddenRouteName }\n }\n }\n\n return true\n }\n}\n\nexport interface TitleGuardOptions {\n /** Шаблон заголовка. {title} — meta.title, {brand} — название бренда. */\n template?: string\n /** Имя бренда. */\n brand?: string\n /** Default title если в meta нет. */\n fallback?: string\n}\n\n/**\n * Создаёт afterEach hook, обновляющий document.title.\n *\n * Шаблон по умолчанию: '{title} · {brand}' если оба, иначе один из.\n */\nexport function createTitleGuard(\n opts: TitleGuardOptions = {},\n): (to: RouteLocationNormalized, from?: RouteLocationNormalized, failure?: unknown) => void {\n const template = opts.template\n const brand = opts.brand ?? ''\n const fallback = opts.fallback ?? ''\n\n return (to) => {\n if (typeof document === 'undefined') return\n const t = (to.meta?.title as string | undefined) ?? fallback\n let title: string\n if (template) {\n title = template.replace('{title}', t).replace('{brand}', brand)\n } else if (t && brand) {\n title = `${t} · ${brand}`\n } else {\n title = t || brand\n }\n document.title = title\n }\n}\n","/**\n * createAdminRouter — фабрика admin-router'а.\n *\n * Использование:\n *\n * const router = createAdminRouter({\n * base: '/admin',\n * components: { ... },\n * brand: 'My App',\n * })\n * await router.replaceManifestRoutes(manifestStore.manifest)\n * app.use(router)\n *\n * Library намеренно не делает createWebHistory выбор за host'а — host передаёт\n * объект history (createWebHistory / createWebHashHistory).\n */\n\nimport {\n createRouter,\n createWebHistory,\n type Router,\n type RouteRecordRaw,\n type RouterHistory,\n} from 'vue-router'\nimport type { AdminManifest } from '../stores/manifest'\nimport { buildRoutesFromManifest, type RouteComponentResolver, type AdminRouteComponent } from './builder'\nimport { createAuthGuard, createTitleGuard, type AuthGuardOptions, type TitleGuardOptions } from './guards'\n\nexport interface AdminRouterOptions {\n /** Base URL admin-панели. По умолчанию '/admin'. */\n base?: string\n /** History-implementation. По умолчанию createWebHistory(base). */\n history?: RouterHistory\n /** Component resolver для resource/screen/settings/dashboard роутов. */\n components: RouteComponentResolver & {\n /** Login. */\n login: AdminRouteComponent\n /** Главная (либо overview-dashboard). */\n home: AdminRouteComponent\n /** 403 forbidden. */\n forbidden: AdminRouteComponent\n /** 404 not found. */\n notFound: AdminRouteComponent\n /** Страница профиля. */\n profile?: AdminRouteComponent\n /** Страница уведомлений. */\n notifications?: AdminRouteComponent\n }\n /** Дополнительные руты сверху динамики. */\n extraRoutes?: RouteRecordRaw[]\n /** Опции auth-guard. */\n authGuard?: AuthGuardOptions\n /** Опции title-guard. */\n titleGuard?: TitleGuardOptions\n}\n\n/**\n * Расширенный Router с возможностью пере-построить динамические роуты.\n */\nexport interface AdminRouter extends Router {\n /**\n * Пере-собрать динамические роуты из manifest'а.\n * Удаляет старые admin.resource.* / admin.screen.* / admin.settings.* / admin.dashboard.*\n * и заменяет на актуальные. Полезно при перезагрузке manifest'а.\n */\n replaceManifestRoutes(manifest: AdminManifest | null): void\n}\n\n/**\n * Префиксы dynamic-роутов которые подменяются при replaceManifestRoutes.\n */\nconst DYNAMIC_NAME_PREFIXES = [\n 'admin.resource.',\n 'admin.screen.',\n 'admin.settings.',\n 'admin.dashboard.',\n]\n\nfunction isDynamicRouteName(name: unknown): boolean {\n if (typeof name !== 'string') return false\n return DYNAMIC_NAME_PREFIXES.some((p) => name.startsWith(p))\n}\n\nexport function createAdminRouter(opts: AdminRouterOptions): AdminRouter {\n const base = opts.base ?? '/admin'\n const history = opts.history ?? createWebHistory(base)\n\n const staticRoutes: RouteRecordRaw[] = [\n {\n path: '/login',\n name: 'admin.login',\n component: opts.components.login,\n meta: { kind: 'auth', title: 'Вход' },\n },\n {\n path: '/',\n name: 'admin.home',\n component: opts.components.home,\n meta: { requiresAuth: true, kind: 'system', title: 'Главная' },\n },\n {\n path: '/forbidden',\n name: 'admin.forbidden',\n component: opts.components.forbidden,\n meta: { requiresAuth: true, kind: 'system', title: '403 — доступ запрещён' },\n },\n ]\n\n if (opts.components.profile) {\n staticRoutes.push({\n path: '/profile',\n name: 'admin.profile',\n component: opts.components.profile,\n meta: { requiresAuth: true, kind: 'system', title: 'Профиль' },\n })\n }\n\n if (opts.components.notifications) {\n staticRoutes.push({\n path: '/notifications',\n name: 'admin.notifications',\n component: opts.components.notifications,\n meta: { requiresAuth: true, kind: 'system', title: 'Уведомления' },\n })\n }\n\n // Catch-all 404 кладём в конец — vue-router matches in order и динамика\n // может быть добавлена позже через addRoute.\n const notFoundRoute: RouteRecordRaw = {\n path: '/:pathMatch(.*)*',\n name: 'admin.notFound',\n component: opts.components.notFound,\n meta: { kind: 'system', title: '404' },\n }\n\n const router = createRouter({\n history,\n routes: [...staticRoutes, ...(opts.extraRoutes ?? []), notFoundRoute],\n }) as AdminRouter\n\n router.beforeEach(createAuthGuard(opts.authGuard))\n router.afterEach(createTitleGuard(opts.titleGuard))\n\n router.replaceManifestRoutes = (manifest: AdminManifest | null): void => {\n // Удаляем все старые динамические роуты по name.\n const allRoutes = router.getRoutes()\n for (const route of allRoutes) {\n if (isDynamicRouteName(route.name)) {\n router.removeRoute(route.name as string)\n }\n }\n\n // Удаляем catch-all чтобы потом добавить его обратно последним.\n if (router.hasRoute('admin.notFound')) {\n router.removeRoute('admin.notFound')\n }\n\n const dynamic = buildRoutesFromManifest(manifest, opts.components)\n for (const route of dynamic) {\n router.addRoute(route)\n }\n router.addRoute(notFoundRoute)\n }\n\n return router\n}\n\nexport { buildRoutesFromManifest } from './builder'\nexport type { RouteComponentResolver, RouteMeta, AdminRouteComponent } from './builder'\nexport { createAuthGuard, createTitleGuard } from './guards'\nexport type { AuthGuardOptions, TitleGuardOptions } from './guards'\n","<script setup lang=\"ts\">\n/**\n * TextField — wrapper над UidInput из @dskripchenko/ui. Двусторонняя связь\n * с form-state через provideFormState/useFormState. Тип input'а (text/email/\n * url/password/tel/search) пробрасывается как `type`.\n */\nimport { computed } from 'vue'\nimport { UidInput } from '@dskripchenko/ui'\nimport { useFormState } from '../render/formState'\n\ninterface Props {\n name: string\n label?: string | null\n help?: string | null\n required?: boolean\n placeholder?: string | null\n inputType?: 'text' | 'email' | 'url' | 'password' | 'tel' | 'search'\n disabled?: boolean\n readonly?: boolean\n autocomplete?: string | null\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n label: null,\n help: null,\n placeholder: null,\n inputType: 'text',\n required: false,\n disabled: false,\n readonly: false,\n autocomplete: null,\n})\n\nconst form = useFormState()\nconst value = computed<string>(() => (form.getField(props.name) as string | null | undefined) ?? '')\nconst errorMsg = computed<string | undefined>(() => form.errors[props.name]?.[0])\n\nfunction onUpdate(next: string): void {\n form.setField(props.name, next)\n}\n</script>\n\n<template>\n <UidInput\n :model-value=\"value\"\n :type=\"inputType\"\n :label=\"label ?? undefined\"\n :hint=\"help ?? undefined\"\n :error=\"errorMsg\"\n :placeholder=\"placeholder ?? undefined\"\n :required=\"required\"\n :disabled=\"disabled\"\n :readonly=\"readonly\"\n :name=\"name\"\n :autocomplete=\"autocomplete ?? undefined\"\n @update:model-value=\"onUpdate\"\n />\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { UidTextarea, UidFormField } from '@dskripchenko/ui'\nimport { useFormState } from '../render/formState'\n\ninterface Props {\n name: string\n label?: string | null\n help?: string | null\n required?: boolean\n placeholder?: string | null\n rows?: number\n disabled?: boolean\n readonly?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n label: null,\n help: null,\n placeholder: null,\n rows: 4,\n required: false,\n disabled: false,\n readonly: false,\n})\n\nconst form = useFormState()\nconst value = computed<string>(() => (form.getField(props.name) as string | null | undefined) ?? '')\nconst errorMsg = computed<string | undefined>(() => form.errors[props.name]?.[0])\n\nfunction onUpdate(next: string): void {\n form.setField(props.name, next)\n}\n</script>\n\n<template>\n <UidFormField\n :label=\"label ?? undefined\"\n :hint=\"help ?? undefined\"\n :error=\"errorMsg\"\n :required=\"required\"\n :disabled=\"disabled\"\n >\n <UidTextarea\n :model-value=\"value\"\n :rows=\"rows\"\n :placeholder=\"placeholder ?? undefined\"\n :disabled=\"disabled\"\n :readonly=\"readonly\"\n :name=\"name\"\n @update:model-value=\"onUpdate\"\n />\n </UidFormField>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { UidNumberInput, UidFormField } from '@dskripchenko/ui'\nimport { useFormState } from '../render/formState'\n\ninterface Props {\n name: string\n label?: string | null\n help?: string | null\n required?: boolean\n placeholder?: string | null\n min?: number | null\n max?: number | null\n step?: number | null\n disabled?: boolean\n readonly?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n label: null,\n help: null,\n placeholder: null,\n min: null,\n max: null,\n step: null,\n required: false,\n disabled: false,\n readonly: false,\n})\n\nconst form = useFormState()\nconst value = computed<number | null>(() => {\n const v = form.getField(props.name)\n if (v === null || v === undefined || v === '') return null\n return typeof v === 'number' ? v : Number(v)\n})\nconst errorMsg = computed<string | undefined>(() => form.errors[props.name]?.[0])\n\nfunction onUpdate(next: number | null): void {\n form.setField(props.name, next)\n}\n</script>\n\n<template>\n <UidFormField\n :label=\"label ?? undefined\"\n :hint=\"help ?? undefined\"\n :error=\"errorMsg\"\n :required=\"required\"\n :disabled=\"disabled\"\n >\n <UidNumberInput\n :model-value=\"value\"\n :min=\"min ?? undefined\"\n :max=\"max ?? undefined\"\n :step=\"step ?? undefined\"\n :placeholder=\"placeholder ?? undefined\"\n :disabled=\"disabled\"\n :readonly=\"readonly\"\n :name=\"name\"\n @update:model-value=\"onUpdate\"\n />\n </UidFormField>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { UidSelect, UidFormField } from '@dskripchenko/ui'\nimport { useFormState } from '../render/formState'\n\nexport interface SelectOption {\n value: string | number\n label: string\n disabled?: boolean\n}\n\ninterface Props {\n name: string\n options: SelectOption[]\n label?: string | null\n help?: string | null\n required?: boolean\n placeholder?: string | null\n disabled?: boolean\n searchable?: boolean\n clearable?: boolean\n size?: 'sm' | 'md' | 'lg'\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n label: null,\n help: null,\n placeholder: null,\n required: false,\n disabled: false,\n searchable: false,\n clearable: false,\n size: 'md',\n})\n\nconst form = useFormState()\nconst value = computed<string | number | null>(() => {\n const v = form.getField(props.name)\n if (v === null || v === undefined || v === '') return null\n return v as string | number\n})\nconst errorMsg = computed<string | undefined>(() => form.errors[props.name]?.[0])\n\nfunction onUpdate(next: string | number | null): void {\n form.setField(props.name, next)\n}\n</script>\n\n<template>\n <UidFormField\n :label=\"label ?? undefined\"\n :hint=\"help ?? undefined\"\n :error=\"errorMsg\"\n :required=\"required\"\n :disabled=\"disabled\"\n >\n <UidSelect\n :model-value=\"value\"\n :options=\"options\"\n :placeholder=\"placeholder ?? undefined\"\n :disabled=\"disabled\"\n :searchable=\"searchable\"\n :clearable=\"clearable\"\n :size=\"size\"\n @update:model-value=\"onUpdate\"\n />\n </UidFormField>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { UidCheckbox, UidFormField } from '@dskripchenko/ui'\nimport { useFormState } from '../render/formState'\n\ninterface Props {\n name: string\n label?: string | null\n help?: string | null\n required?: boolean\n inlineLabel?: string | null\n disabled?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n label: null,\n help: null,\n inlineLabel: null,\n required: false,\n disabled: false,\n})\n\nconst form = useFormState()\nconst checked = computed<boolean>(() => Boolean(form.getField(props.name)))\nconst errorMsg = computed<string | undefined>(() => form.errors[props.name]?.[0])\n\nfunction onUpdate(next: boolean): void {\n form.setField(props.name, next)\n}\n</script>\n\n<template>\n <UidFormField\n :label=\"label ?? undefined\"\n :hint=\"help ?? undefined\"\n :error=\"errorMsg\"\n :required=\"required\"\n :disabled=\"disabled\"\n >\n <UidCheckbox\n :model-value=\"checked\"\n :disabled=\"disabled\"\n :name=\"name\"\n @update:model-value=\"onUpdate\"\n >\n <template v-if=\"inlineLabel\">{{ inlineLabel }}</template>\n </UidCheckbox>\n </UidFormField>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { UidDatePicker, UidFormField } from '@dskripchenko/ui'\nimport { useFormState } from '../render/formState'\n\ninterface Props {\n name: string\n label?: string | null\n help?: string | null\n required?: boolean\n /**\n * Тип input'а: 'date' (default), 'datetime-local', 'time'.\n * UidDatePicker внутри обрабатывает формат через свои props; для совместимости\n * со старым API оставляем prop.\n */\n inputType?: 'date' | 'datetime-local' | 'time'\n min?: string | null\n max?: string | null\n disabled?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n label: null,\n help: null,\n inputType: 'date',\n min: null,\n max: null,\n required: false,\n disabled: false,\n})\n\nconst form = useFormState()\nconst value = computed<string | null>(() => {\n const v = form.getField(props.name)\n return v === null || v === undefined || v === '' ? null : String(v)\n})\nconst errorMsg = computed<string | undefined>(() => form.errors[props.name]?.[0])\n\nfunction onUpdate(next: string | null): void {\n form.setField(props.name, next)\n}\n</script>\n\n<template>\n <UidFormField\n :label=\"label ?? undefined\"\n :hint=\"help ?? undefined\"\n :error=\"errorMsg\"\n :required=\"required\"\n :disabled=\"disabled\"\n >\n <UidDatePicker\n :model-value=\"value\"\n :min=\"min ?? undefined\"\n :max=\"max ?? undefined\"\n :disabled=\"disabled\"\n :name=\"name\"\n @update:model-value=\"onUpdate\"\n />\n </UidFormField>\n</template>\n","<script setup lang=\"ts\">\n/**\n * Rows-layout — UidStack column.\n */\nimport { UidStack } from '@dskripchenko/ui'\nimport LayoutRenderer from '../render/LayoutRenderer.vue'\nimport type { LayoutNode } from '../render/LayoutRenderer.vue'\n\ninterface Props {\n items: LayoutNode[]\n /** CSS-зазор между элементами (token либо px), по умолчанию --uid-space-md. */\n gap?: string\n}\nwithDefaults(defineProps<Props>(), { gap: 'var(--uid-space-md)' })\n</script>\n\n<template>\n <UidStack direction=\"column\" :gap=\"gap\" align=\"stretch\">\n <LayoutRenderer v-for=\"(child, idx) in items\" :key=\"idx\" :node=\"child\" />\n </UidStack>\n</template>\n","<script setup lang=\"ts\">\n/**\n * Columns: 12-колоночный grid поверх UidGrid из @dskripchenko/ui.\n * Каждый item.span (1..cols) задаёт ширину; default равные доли.\n */\nimport { computed } from 'vue'\nimport { UidGrid } from '@dskripchenko/ui'\nimport LayoutRenderer from '../render/LayoutRenderer.vue'\nimport type { LayoutNode } from '../render/LayoutRenderer.vue'\n\ninterface Props {\n items: LayoutNode[]\n /** Зазор между ячейками (CSS, token или px). */\n gap?: string\n /** Сколько колонок в гриде (default 12). */\n cols?: number\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n gap: 'var(--uid-space-md)',\n cols: 12,\n})\n\nconst defaultSpan = computed(() => {\n if (props.items.length === 0) return props.cols\n return Math.max(1, Math.floor(props.cols / props.items.length))\n})\n\nfunction spanFor(item: LayoutNode): number {\n const s = (item as Record<string, unknown>).span\n if (typeof s === 'number' && s > 0) return Math.min(s, props.cols)\n return defaultSpan.value\n}\n</script>\n\n<template>\n <UidGrid :cols=\"cols\" :gap=\"gap\">\n <div\n v-for=\"(child, idx) in items\"\n :key=\"idx\"\n class=\"admin-columns__item\"\n :style=\"{ gridColumn: `span ${spanFor(child)} / span ${spanFor(child)}` }\"\n >\n <LayoutRenderer :node=\"child\" />\n </div>\n </UidGrid>\n</template>\n","<script setup lang=\"ts\">\n/**\n * Section/Block layout — UidCard с заголовком + опциональным описанием.\n */\nimport { UidCard } from '@dskripchenko/ui'\nimport LayoutRenderer from '../render/LayoutRenderer.vue'\nimport type { LayoutNode } from '../render/LayoutRenderer.vue'\n\ninterface Props {\n items: LayoutNode[]\n title?: string | null\n description?: string | null\n}\n\nwithDefaults(defineProps<Props>(), {\n title: null,\n description: null,\n})\n</script>\n\n<template>\n <UidCard padding=\"md\" class=\"admin-section\">\n <header v-if=\"title || description\" class=\"admin-section__header\">\n <h3 v-if=\"title\" class=\"admin-section__title\">{{ title }}</h3>\n <p v-if=\"description\" class=\"admin-section__description\">{{ description }}</p>\n </header>\n <div class=\"admin-section__body\">\n <LayoutRenderer v-for=\"(child, idx) in items\" :key=\"idx\" :node=\"child\" />\n </div>\n </UidCard>\n</template>\n\n<style>\n.admin-section { margin-bottom: var(--uid-space-md); }\n.admin-section__header { margin-bottom: var(--uid-space-sm); }\n.admin-section__title {\n margin: 0;\n font-size: var(--uid-font-size-sm);\n font-weight: var(--uid-font-weight-semibold);\n color: var(--uid-text-primary);\n}\n.admin-section__description {\n margin: var(--uid-space-2xs) 0 0;\n font-size: var(--uid-font-size-xs);\n color: var(--uid-text-tertiary);\n}\n.admin-section__body {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-sm);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * TabsLayout поверх UidTabs/UidTab/UidTabPanel.\n * Активная вкладка двусторонне связана через v-model:active.\n */\nimport { ref } from 'vue'\nimport { UidTabs, UidTab, UidTabPanel } from '@dskripchenko/ui'\nimport LayoutRenderer from '../render/LayoutRenderer.vue'\nimport type { LayoutNode } from '../render/LayoutRenderer.vue'\n\nexport interface TabNode {\n /** Уникальный ключ вкладки. Если не задан — берётся индекс. */\n key?: string\n /** Текст вкладки. */\n label: string\n icon?: string | null\n items: LayoutNode[]\n}\n\ninterface Props {\n items: TabNode[]\n /** Активная вкладка (key либо индекс при отсутствии key). */\n active?: string | number\n}\n\nconst props = withDefaults(defineProps<Props>(), { active: 0 })\nconst emit = defineEmits<{ 'update:active': [value: string | number] }>()\n\nfunction tabKey(tab: TabNode, idx: number): string | number {\n return tab.key ?? idx\n}\n\nconst localActive = ref<string | number>(props.active ?? tabKey(props.items[0] ?? { label: '' }, 0))\n\nfunction onUpdate(value: string | number): void {\n localActive.value = value\n emit('update:active', value)\n}\n</script>\n\n<template>\n <UidTabs :model-value=\"localActive\" @update:model-value=\"onUpdate\">\n <template #list>\n <UidTab\n v-for=\"(tab, idx) in items\"\n :key=\"tabKey(tab, idx)\"\n :value=\"tabKey(tab, idx)\"\n >\n {{ tab.label }}\n </UidTab>\n </template>\n\n <UidTabPanel\n v-for=\"(tab, idx) in items\"\n :key=\"`panel-${tabKey(tab, idx)}`\"\n :value=\"tabKey(tab, idx)\"\n >\n <LayoutRenderer\n v-for=\"(child, cidx) in tab.items\"\n :key=\"cidx\"\n :node=\"child\"\n />\n </UidTabPanel>\n </UidTabs>\n</template>\n","/**\n * Default-bundle с минимальным набором builtin-компонентов.\n *\n * Использование:\n *\n * import { registerBuiltinComponents } from '@dskripchenko/laravel-admin'\n * registerBuiltinComponents()\n */\n\nimport { registerComponents } from './registry'\nimport TextField from '../fields/TextField.vue'\nimport TextAreaField from '../fields/TextAreaField.vue'\nimport NumberField from '../fields/NumberField.vue'\nimport SelectField from '../fields/SelectField.vue'\nimport CheckboxField from '../fields/CheckboxField.vue'\nimport DateField from '../fields/DateField.vue'\nimport RowsLayout from '../layouts/RowsLayout.vue'\nimport ColumnsLayout from '../layouts/ColumnsLayout.vue'\nimport SectionLayout from '../layouts/SectionLayout.vue'\nimport TabsLayout from '../layouts/TabsLayout.vue'\n\nexport function registerBuiltinComponents(): void {\n registerComponents({\n fields: {\n text: TextField,\n email: TextField,\n url: TextField,\n password: TextField,\n tel: TextField,\n search: TextField,\n textarea: TextAreaField,\n number: NumberField,\n select: SelectField,\n checkbox: CheckboxField,\n switcher: CheckboxField,\n date: DateField,\n datetime: DateField,\n time: DateField,\n },\n layouts: {\n rows: RowsLayout,\n columns: ColumnsLayout,\n section: SectionLayout,\n block: SectionLayout,\n tabs: TabsLayout,\n },\n })\n}\n","<script setup lang=\"ts\">\n/**\n * TextEntry — строковое read-only значение.\n *\n * Источник: prop.value либо record[name].\n * Для empty-state — placeholder («—» по умолчанию).\n */\nimport { computed } from 'vue'\nimport { tryUseRecord } from './recordContext'\n\ninterface Props {\n name?: string\n label?: string\n value?: string | number | null\n /** Заместитель пустого значения. */\n placeholder?: string\n /** Применить mono-font (например для ID/UUID). */\n mono?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n name: '',\n label: '',\n value: undefined,\n placeholder: '—',\n mono: false,\n})\n\nconst record = tryUseRecord()\nconst display = computed<string>(() => {\n let v: unknown = props.value\n if (v === undefined && record && props.name) {\n v = record[props.name]\n }\n if (v === null || v === undefined || v === '') return props.placeholder\n return String(v)\n})\n</script>\n\n<template>\n <span :class=\"['admin-infolist-text', mono ? 'admin-infolist-text--mono' : '']\">\n {{ display }}\n </span>\n</template>\n\n<style>\n.admin-infolist-text {\n font-size: var(--uid-font-size-sm);\n color: var(--uid-text-primary);\n}\n.admin-infolist-text--mono {\n font-family: var(--uid-font-family-mono);\n font-size: var(--uid-font-size-xs);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * BadgeEntry — строковое значение в виде UidBadge с variant'ом по value-mapping.\n *\n * Manifest:\n * { type: 'badge', name: 'status', label: 'Status',\n * map: { published: 'success', draft: 'warning', archived: 'danger' } }\n */\nimport { computed } from 'vue'\nimport { UidBadge } from '@dskripchenko/ui'\nimport { tryUseRecord } from './recordContext'\n\ntype BadgeVariant = 'default' | 'success' | 'warning' | 'danger' | 'info'\n\ninterface Props {\n name?: string\n label?: string\n value?: string | null\n /** map value → variant. Если не задан — default. */\n map?: Record<string, BadgeVariant>\n /** Принудительный variant. */\n variant?: BadgeVariant\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n name: '',\n label: '',\n value: undefined,\n map: () => ({}),\n variant: undefined,\n})\n\nconst record = tryUseRecord()\nconst value = computed<string>(() => {\n let v: unknown = props.value\n if (v === undefined && record && props.name) {\n v = record[props.name]\n }\n return v === null || v === undefined ? '' : String(v)\n})\nconst resolvedVariant = computed<BadgeVariant>(() => {\n if (props.variant) return props.variant\n return props.map[value.value] ?? 'default'\n})\n</script>\n\n<template>\n <UidBadge v-if=\"value\" :variant=\"resolvedVariant\">\n {{ value }}\n </UidBadge>\n <span v-else class=\"admin-infolist-text\">—</span>\n</template>\n","<script setup lang=\"ts\">\n/**\n * IconEntry — boolean-флаг как иконка (true → check, false → x).\n * Опционально labels: '{ true: \"Опубликовано\", false: \"Черновик\" }'.\n */\nimport { computed } from 'vue'\nimport { tryUseRecord } from './recordContext'\n\ninterface Props {\n name?: string\n label?: string\n value?: boolean | null\n /** Имя icon'и для true (lucide-key, например 'check-circle-2'). */\n trueIcon?: string\n /** Имя icon'и для false. */\n falseIcon?: string\n /** Текстовые подписи. */\n trueLabel?: string\n falseLabel?: string\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n name: '',\n label: '',\n value: undefined,\n trueIcon: 'check-circle-2',\n falseIcon: 'circle',\n trueLabel: '',\n falseLabel: '',\n})\n\nconst record = tryUseRecord()\nconst flag = computed<boolean>(() => {\n let v: unknown = props.value\n if (v === undefined && record && props.name) {\n v = record[props.name]\n }\n return Boolean(v)\n})\nconst displayLabel = computed(() => (flag.value ? props.trueLabel : props.falseLabel))\nconst iconName = computed(() => (flag.value ? props.trueIcon : props.falseIcon))\n</script>\n\n<template>\n <span :class=\"['admin-infolist-icon', flag ? 'admin-infolist-icon--on' : 'admin-infolist-icon--off']\">\n <span class=\"admin-infolist-icon__glyph\" :data-icon=\"iconName\" />\n <span v-if=\"displayLabel\">{{ displayLabel }}</span>\n </span>\n</template>\n\n<style>\n.admin-infolist-icon {\n display: inline-flex;\n align-items: center;\n gap: var(--uid-space-xs);\n font-size: var(--uid-font-size-sm);\n}\n.admin-infolist-icon--on { color: var(--uid-success); }\n.admin-infolist-icon--off { color: var(--uid-text-tertiary); }\n.admin-infolist-icon__glyph {\n display: inline-block;\n width: 14px;\n height: 14px;\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * KeyValueEntry — словарь {key: value} как UidDescriptionList.\n * Source: prop.value (Record) либо record[name].\n */\nimport { computed } from 'vue'\nimport { UidDescriptionList, UidDescriptionItem } from '@dskripchenko/ui'\nimport { tryUseRecord } from './recordContext'\n\ninterface Props {\n name?: string\n label?: string\n value?: Record<string, unknown>\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n name: '',\n label: '',\n value: undefined,\n})\n\nconst record = tryUseRecord()\nconst items = computed<Array<[string, unknown]>>(() => {\n let v: unknown = props.value\n if (v === undefined && record && props.name) {\n v = record[props.name]\n }\n if (v === null || v === undefined) return []\n if (typeof v !== 'object') return []\n return Object.entries(v as Record<string, unknown>)\n})\n\nfunction formatValue(v: unknown): string {\n if (v === null || v === undefined) return '—'\n if (typeof v === 'object') return JSON.stringify(v)\n return String(v)\n}\n</script>\n\n<template>\n <UidDescriptionList v-if=\"items.length > 0\" direction=\"vertical\" :columns=\"1\">\n <UidDescriptionItem\n v-for=\"[k, v] in items\"\n :key=\"k\"\n :label=\"k\"\n >\n {{ formatValue(v) }}\n </UidDescriptionItem>\n </UidDescriptionList>\n <span v-else class=\"admin-infolist-text\">—</span>\n</template>\n","/**\n * Default-bundle с минимальным набором builtin infolist-entry'ев.\n */\n\nimport { registerInfolistEntries } from './registry'\nimport TextEntry from './TextEntry.vue'\nimport BadgeEntry from './BadgeEntry.vue'\nimport IconEntry from './IconEntry.vue'\nimport KeyValueEntry from './KeyValueEntry.vue'\n\nexport function registerBuiltinInfolistEntries(): void {\n registerInfolistEntries({\n text: TextEntry,\n badge: BadgeEntry,\n icon: IconEntry,\n keyvalue: KeyValueEntry,\n 'key-value': KeyValueEntry,\n })\n}\n","/**\n * createAdminApp — фабрика-helper для host-проектов.\n *\n * Собирает Vue-app со всем нужным: Pinia, Router, AdminClient, hydrated\n * stores, built-in fields/layouts/widgets/infolist, default страницы.\n * Возвращает объект где `app` готов к `.mount('#admin-app')`.\n *\n * Минимальный пример (host's resources/js/admin.js):\n *\n * import { createAdminApp } from '@dskripchenko/laravel-admin'\n * import '@dskripchenko/laravel-admin/style.css'\n *\n * const { app } = createAdminApp(window.__ADMIN_BOOTSTRAP__)\n * app.mount('#admin-app')\n *\n * Расширенное использование с переопределением страниц:\n *\n * const { app } = createAdminApp(window.__ADMIN_BOOTSTRAP__, {\n * pages: { home: MyDashboard },\n * onAppCreated: (app) => app.use(SomePlugin),\n * })\n */\n\nimport { createApp, type App, type Component } from 'vue'\nimport { createPinia } from 'pinia'\nimport { createWebHistory } from 'vue-router'\n\nimport AdminApp from './components/AdminApp.vue'\nimport HomePage from './components/HomePage.vue'\nimport ForbiddenPage from './components/ForbiddenPage.vue'\nimport NotFoundPage from './components/NotFoundPage.vue'\nimport SettingsPage from './components/SettingsPage.vue'\nimport UnknownScreenPage from './components/UnknownScreenPage.vue'\nimport { LoginPage } from './components/auth'\nimport {\n ResourceIndexPage,\n ResourceFormPage,\n ResourceViewPage,\n} from './components/resource'\nimport { ProfilePage } from './components/profile'\nimport { DashboardPage } from './components/dashboard'\n\nimport { createAdminClient, type AdminClient } from './api/client'\nimport { setAdminClient } from './stores'\nimport { useAuthStore } from './stores/auth'\nimport { useLocaleStore } from './stores/locale'\nimport { useThemeStore } from './stores/theme'\nimport { useNotificationsStore } from './stores/notifications'\nimport { useManifestStore } from './stores/manifest'\n\nimport { createAdminRouter, type AdminRouter, type AdminRouterOptions } from './router'\nimport { registerBuiltinComponents } from './components/render/builtin'\nimport { registerBuiltinWidgets } from './components/dashboard/builtin'\nimport { registerBuiltinInfolistEntries } from './components/infolist/builtin'\n\nimport type { AdminBootstrap } from './types/bootstrap'\n\nexport interface CreateAdminAppPages {\n /** Login page. По умолчанию core'овский LoginPage. */\n login?: Component\n /** Главная (после login). По умолчанию HomePage. */\n home?: Component\n /** 403. По умолчанию ForbiddenPage. */\n forbidden?: Component\n /** 404. По умолчанию NotFoundPage. */\n notFound?: Component\n /** Профиль. По умолчанию ProfilePage. */\n profile?: Component\n /** Resource index/form/view. По умолчанию core'овские. */\n resourceIndex?: Component\n resourceCreate?: Component\n resourceEdit?: Component\n resourceView?: Component\n /** Dashboard страница (для роутов admin.dashboard.*). */\n dashboard?: Component\n /** Settings page (для admin.settings.*). */\n settings?: Component\n /** Custom Screen page (для admin.screen.*). */\n screen?: Component\n}\n\nexport interface CreateAdminAppOptions {\n /**\n * Базовый URL admin-панели. По умолчанию берётся из bootstrap.baseUrl\n * (если он pathname вида '/admin'), иначе '/admin'.\n */\n base?: string\n /** Override отдельных страниц. */\n pages?: CreateAdminAppPages\n /** Дополнительные опции router'а (extraRoutes, history, guards). */\n router?: Partial<Omit<AdminRouterOptions, 'components'>>\n /** Hook для до-настройки app перед mount (app.use(plugin), app.provide(...)). */\n onAppCreated?: (app: App) => void\n /**\n * Не вызывать manifestStore.load() автоматически. По умолчанию false —\n * createAdminApp сам подгружает manifest и выстраивает динамические роуты.\n */\n skipManifestLoad?: boolean\n}\n\nexport interface AdminAppHandle {\n app: App\n router: AdminRouter\n client: AdminClient\n}\n\n/**\n * Создать Vue admin-app, готовый к `.mount('#admin-app')`.\n *\n * Шаги внутри:\n * 1. Pinia + AdminClient (axios через bootstrap.csrf/apiUrl).\n * 2. Hydrate auth/locale/theme/notifications stores из bootstrap.\n * 3. Регистрация built-in fields/layouts/widgets/infolist entries.\n * 4. Router со static-routes (login/home/profile/forbidden/notFound) +\n * async manifest load → replaceManifestRoutes для resource/screen/\n * settings/dashboard.\n * 5. Возврат `{ app, router, client }`. Host вызывает `app.mount(...)`.\n */\nexport function createAdminApp(\n bootstrap: AdminBootstrap,\n options: CreateAdminAppOptions = {},\n): AdminAppHandle {\n const pages = options.pages ?? {}\n const base = options.base ?? deriveBase(bootstrap.baseUrl) ?? '/admin'\n\n // 1. AdminClient\n const client = createAdminClient({\n baseURL: bootstrap.apiUrl,\n csrfToken: bootstrap.csrf,\n })\n setAdminClient(client)\n\n // 2. Vue app + Pinia\n const app = createApp(AdminApp)\n const pinia = createPinia()\n app.use(pinia)\n\n // 3. Pinia stores hydrate\n useAuthStore().hydrate(bootstrap)\n useLocaleStore().hydrate(bootstrap)\n useThemeStore().hydrate(bootstrap)\n useNotificationsStore().hydrate(bootstrap)\n\n // 4. Builtin field/layout/widget/infolist registries\n registerBuiltinComponents()\n registerBuiltinWidgets()\n registerBuiltinInfolistEntries()\n\n // 5. Router\n const router = createAdminRouter({\n base,\n history: options.router?.history ?? createWebHistory(base),\n components: {\n login: pages.login ?? LoginPage,\n home: pages.home ?? HomePage,\n forbidden: pages.forbidden ?? ForbiddenPage,\n notFound: pages.notFound ?? NotFoundPage,\n profile: pages.profile ?? ProfilePage,\n resourceIndex: pages.resourceIndex ?? ResourceIndexPage,\n resourceCreate: pages.resourceCreate ?? ResourceFormPage,\n resourceEdit: pages.resourceEdit ?? ResourceFormPage,\n resourceView: pages.resourceView ?? ResourceViewPage,\n dashboard: pages.dashboard ?? DashboardPage,\n settings: pages.settings ?? SettingsPage,\n screen: pages.screen ?? UnknownScreenPage,\n },\n extraRoutes: options.router?.extraRoutes,\n authGuard: options.router?.authGuard,\n titleGuard: options.router?.titleGuard,\n })\n app.use(router)\n\n // 6. Manifest async-load + dynamic routes\n if (!options.skipManifestLoad) {\n const manifestStore = useManifestStore()\n void manifestStore\n .load()\n .then((manifest) => {\n router.replaceManifestRoutes(manifest)\n })\n .catch((error: unknown) => {\n // Silent fail — пользователь увидит home без resource-роутов;\n // host может перехватить ошибку через onAppCreated → app.config.errorHandler.\n if (typeof console !== 'undefined') {\n console.error('[laravel-admin] manifest load failed:', error)\n }\n })\n }\n\n // 7. host hook\n options.onAppCreated?.(app)\n\n return { app, router, client }\n}\n\n/**\n * Извлечь base path из bootstrap.baseUrl ('http://app.test/admin' → '/admin').\n */\nfunction deriveBase(baseUrl: string | undefined): string | null {\n if (!baseUrl) return null\n try {\n const url = new URL(baseUrl)\n return url.pathname || '/admin'\n } catch {\n return baseUrl.startsWith('/') ? baseUrl : null\n }\n}\n","/**\n * Загрузка bootstrap-payload'а в SPA.\n *\n * Поддерживает обе стратегии:\n * - 'inline' — читает window.__ADMIN_BOOTSTRAP__ (инжект через\n * shell.blade при strategy=inline).\n * - 'xhr' — fetch'ит /api/admin/system/bootstrap.\n *\n * Если оба способа не дали результата — throw'ит. SPA должна это поймать\n * и показать full-screen error.\n */\n\nimport type { AdminBootstrap } from '../types/bootstrap'\nimport type { AdminClient } from './client'\nimport { NetworkError } from './errors'\n\nexport interface LoadBootstrapOptions {\n /** Если задан client — fallback на xhr через него. */\n client?: AdminClient\n /** Override URL для xhr. Default: '/system/bootstrap'. */\n xhrUrl?: string\n}\n\n/**\n * Возвращает bootstrap или null если не загрузился.\n *\n * Порядок:\n * 1. window.__ADMIN_BOOTSTRAP__ (inline-strategy).\n * 2. xhr fetch если передан client.\n * 3. null — caller решает что делать (показать error-screen).\n */\nexport async function loadBootstrap(\n opts: LoadBootstrapOptions = {},\n): Promise<AdminBootstrap | null> {\n const inline = readInlineBootstrap()\n if (inline) {\n return inline\n }\n\n if (opts.client) {\n try {\n const url = opts.xhrUrl ?? '/system/bootstrap'\n return await opts.client.get<AdminBootstrap>(url)\n } catch (err) {\n if (err instanceof NetworkError) {\n // Network failure — caller должен показать offline-screen.\n return null\n }\n throw err\n }\n }\n\n return null\n}\n\n/**\n * Прочитать bootstrap из window — только в браузерном контексте.\n */\nexport function readInlineBootstrap(): AdminBootstrap | null {\n if (typeof window === 'undefined') return null\n return window.__ADMIN_BOOTSTRAP__ ?? null\n}\n\n/**\n * Прочитать CSRF-token из meta-tag (Blade-injection через `csrf_token()`).\n *\n * Используется как fallback если bootstrap.csrf отсутствует.\n */\nexport function readCsrfFromMeta(): string | null {\n if (typeof document === 'undefined') return null\n const meta = document.querySelector('meta[name=\"csrf-token\"]')\n return meta?.getAttribute('content') ?? null\n}\n","<script setup lang=\"ts\">\n/**\n * NotificationsDrawer — UidDrawer (right, 400px) с tabs (Все/Непрочитанные/\n * Прочитанные) и списком notification-items.\n *\n * Эталон handoff'а (screens-secondary.jsx → NotificationDrawer):\n * - Header: «Уведомления (3)» + actions (Прочитать все)\n * - Tabs: counts, активный tab подсвечен accent\n * - Item: kind-coloured icon (info/success/warning/error) +\n * title (bold если unread) + body + relative timestamp;\n * unread items имеют tinted background + dot слева\n * - Click на item → переход на data.url + auto markAsRead\n * - Hover показывает кнопку '×' (destroy)\n */\nimport { computed, watch } from 'vue'\nimport { UidButton, UidDrawer, UidTabs, UidTab, UidTabPanel } from '@dskripchenko/ui'\nimport { useNotificationsStore, type NotificationFilter, type NotificationItem } from '../../stores/notifications'\n\ninterface Props {\n /** v-model:open. */\n open: boolean\n}\n\nconst props = defineProps<Props>()\nconst emit = defineEmits<{\n 'update:open': [value: boolean]\n /** Click on notification item — host обрабатывает navigation на data.url. */\n 'select-item': [item: NotificationItem]\n}>()\n\nconst notifications = useNotificationsStore()\n\nfunction setOpen(v: boolean): void {\n emit('update:open', v)\n}\n\n// Загружаем при открытии.\nwatch(\n () => props.open,\n async (next) => {\n if (next) {\n await notifications.load(notifications.lastFilter ?? 'all', 1).catch(() => undefined)\n }\n },\n { immediate: true },\n)\n\nconst activeFilter = computed<NotificationFilter>(() => notifications.lastFilter ?? 'all')\n\nasync function setFilter(filter: NotificationFilter | string | number): Promise<void> {\n await notifications\n .load(filter as NotificationFilter, 1)\n .catch(() => undefined)\n}\n\nasync function markAllRead(): Promise<void> {\n await notifications.markAllAsRead().catch(() => undefined)\n}\n\nasync function onItemClick(item: NotificationItem): Promise<void> {\n emit('select-item', item)\n if (!item.read_at) {\n await notifications.markAsRead(item.id).catch(() => undefined)\n }\n}\n\nasync function onDestroy(item: NotificationItem, event: Event): Promise<void> {\n event.stopPropagation()\n await notifications.destroy(item.id).catch(() => undefined)\n}\n\nfunction itemKind(item: NotificationItem): 'info' | 'success' | 'warning' | 'danger' {\n const lvl = item.data.level\n if (lvl === 'success' || lvl === 'warning' || lvl === 'danger') return lvl\n return 'info'\n}\n\nfunction itemTitle(item: NotificationItem): string {\n return (item.data.title as string | undefined) ?? '—'\n}\n\nfunction itemBody(item: NotificationItem): string {\n return (item.data.body as string | undefined) ?? ''\n}\n\nfunction relTime(iso: string | null): string {\n if (!iso) return ''\n const dt = new Date(iso)\n const diff = Math.max(0, Date.now() - dt.getTime())\n const mins = Math.floor(diff / 60000)\n if (mins < 1) return 'только что'\n if (mins < 60) return `${mins} мин назад`\n const hours = Math.floor(mins / 60)\n if (hours < 24) return `${hours} ч назад`\n const days = Math.floor(hours / 24)\n if (days < 7) return `${days} д назад`\n return dt.toLocaleDateString('ru-RU')\n}\n</script>\n\n<template>\n <UidDrawer\n :model-value=\"open\"\n side=\"right\"\n width=\"400px\"\n title=\"Уведомления\"\n @update:model-value=\"setOpen\"\n >\n <template #header>\n <div class=\"admin-notifs__hd\">\n <h2 class=\"admin-notifs__title\">\n Уведомления\n <span v-if=\"notifications.unreadCount > 0\" class=\"admin-notifs__count\">\n ({{ notifications.unreadCount }})\n </span>\n </h2>\n <UidButton\n v-if=\"notifications.unreadCount > 0\"\n variant=\"ghost\"\n size=\"sm\"\n @click=\"markAllRead\"\n >\n Прочитать все\n </UidButton>\n </div>\n </template>\n\n <UidTabs :model-value=\"activeFilter\" @update:model-value=\"setFilter\">\n <template #list>\n <UidTab value=\"all\">Все</UidTab>\n <UidTab value=\"unread\">\n Непрочитанные<template v-if=\"notifications.unreadCount > 0\">\n ({{ notifications.unreadCount }})\n </template>\n </UidTab>\n <UidTab value=\"read\">Прочитанные</UidTab>\n </template>\n\n <UidTabPanel v-for=\"filter in (['all','unread','read'] as const)\" :key=\"filter\" :value=\"filter\">\n <ul class=\"admin-notifs__list\">\n <li v-if=\"notifications.loading\" class=\"admin-notifs__empty\">\n Загрузка…\n </li>\n <li v-else-if=\"notifications.items.length === 0\" class=\"admin-notifs__empty\">\n Нет уведомлений\n </li>\n <li\n v-for=\"item in notifications.items\"\n :key=\"item.id\"\n :class=\"[\n 'admin-notifs__item',\n `admin-notifs__item--${itemKind(item)}`,\n { 'admin-notifs__item--unread': !item.read_at },\n ]\"\n @click=\"onItemClick(item)\"\n >\n <span class=\"admin-notifs__icon\" :data-kind=\"itemKind(item)\" />\n <div class=\"admin-notifs__body\">\n <div class=\"admin-notifs__row1\">\n <strong v-if=\"!item.read_at\" class=\"admin-notifs__title-strong\">\n {{ itemTitle(item) }}\n </strong>\n <span v-else class=\"admin-notifs__title-soft\">{{ itemTitle(item) }}</span>\n <span class=\"admin-notifs__time\">{{ relTime(item.created_at) }}</span>\n </div>\n <p v-if=\"itemBody(item)\" class=\"admin-notifs__text\">{{ itemBody(item) }}</p>\n </div>\n <button\n type=\"button\"\n class=\"admin-notifs__close\"\n :aria-label=\"'Удалить'\"\n @click=\"onDestroy(item, $event)\"\n >\n ×\n </button>\n </li>\n </ul>\n </UidTabPanel>\n </UidTabs>\n </UidDrawer>\n</template>\n\n<style>\n.admin-notifs__hd {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--uid-space-sm);\n}\n.admin-notifs__title {\n margin: 0;\n font-size: var(--uid-font-size-md);\n font-weight: var(--uid-font-weight-semibold);\n}\n.admin-notifs__count {\n color: var(--uid-text-tertiary);\n font-weight: var(--uid-font-weight-regular);\n font-size: var(--uid-font-size-sm);\n}\n\n.admin-notifs__list {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n.admin-notifs__empty {\n padding: var(--uid-space-xl) var(--uid-space-md);\n text-align: center;\n color: var(--uid-text-tertiary);\n font-size: var(--uid-font-size-sm);\n}\n.admin-notifs__item {\n position: relative;\n display: flex;\n gap: var(--uid-space-sm);\n padding: var(--uid-space-sm) var(--uid-space-md);\n cursor: pointer;\n border-bottom: 1px solid var(--uid-border-subtle);\n}\n.admin-notifs__item:hover { background: var(--uid-surface-hover); }\n.admin-notifs__item--unread {\n background: color-mix(in srgb, var(--uid-accent) 6%, transparent);\n}\n.admin-notifs__item--unread:hover {\n background: color-mix(in srgb, var(--uid-accent) 10%, transparent);\n}\n\n.admin-notifs__icon {\n width: 28px;\n height: 28px;\n border-radius: var(--uid-radius-md);\n flex: none;\n margin-top: 2px;\n}\n.admin-notifs__icon[data-kind='info'] {\n background: color-mix(in srgb, var(--uid-info) 14%, transparent);\n}\n.admin-notifs__icon[data-kind='success'] {\n background: color-mix(in srgb, var(--uid-success) 14%, transparent);\n}\n.admin-notifs__icon[data-kind='warning'] {\n background: color-mix(in srgb, var(--uid-warning) 14%, transparent);\n}\n.admin-notifs__icon[data-kind='danger'] {\n background: color-mix(in srgb, var(--uid-danger) 14%, transparent);\n}\n\n.admin-notifs__body { flex: 1; min-width: 0; }\n.admin-notifs__row1 {\n display: flex;\n align-items: baseline;\n gap: var(--uid-space-sm);\n margin-bottom: 2px;\n}\n.admin-notifs__title-strong {\n font-size: var(--uid-font-size-sm);\n font-weight: var(--uid-font-weight-semibold);\n color: var(--uid-text-primary);\n flex: 1;\n min-width: 0;\n}\n.admin-notifs__title-soft {\n font-size: var(--uid-font-size-sm);\n color: var(--uid-text-primary);\n flex: 1;\n min-width: 0;\n}\n.admin-notifs__time {\n font-size: 11px;\n color: var(--uid-text-tertiary);\n flex: none;\n font-variant-numeric: tabular-nums;\n}\n.admin-notifs__text {\n margin: 0;\n font-size: var(--uid-font-size-xs);\n color: var(--uid-text-secondary);\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n.admin-notifs__close {\n position: absolute;\n top: 6px;\n right: 8px;\n appearance: none;\n border: 0;\n background: transparent;\n color: var(--uid-text-tertiary);\n cursor: pointer;\n font-size: 18px;\n width: 22px;\n height: 22px;\n border-radius: var(--uid-radius-sm);\n opacity: 0;\n transition: opacity var(--uid-duration-fast, 100ms);\n}\n.admin-notifs__item:hover .admin-notifs__close { opacity: 1; }\n.admin-notifs__close:hover {\n background: var(--uid-surface-hover);\n color: var(--uid-text-primary);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * ImportWizardPage — 4-step wizard для импорта данных в Resource.\n *\n * Эталон: docs/design_handoff_laravel_admin/screens-secondary.jsx (ImportWizard).\n *\n * Шаги:\n * 1. Загрузка файла — UidFileUpload (CSV/TSV/XLSX)\n * 2. Сопоставление колонок — header'ы файла → field-name'ы ресурса\n * 3. Предпросмотр — таблица первых N строк с warning'ами\n * 4. Импорт — progress-bar + KPI (created/updated/errors)\n *\n * Library предоставляет каркас + state. Конкретные API-вызовы (analyze\n * uploaded file → headers/sample, mapping submit → preview, run import →\n * progress events) — host реализует через emit'ы.\n */\nimport { computed, ref } from 'vue'\nimport {\n UidAlert,\n UidButton,\n UidCard,\n UidFileUpload,\n UidProgress,\n UidSelect,\n UidStat,\n UidStepper,\n UidTable,\n type UidTableColumn,\n} from '@dskripchenko/ui'\n\ninterface ColumnHeader {\n key: string\n label: string\n sample?: string\n}\n\ninterface Mapping {\n /** Header из файла. */\n source: string\n /** Field-name в ресурсе либо null = пропустить. */\n target: string | null\n}\n\ninterface PreviewRow extends Record<string, unknown> {\n __warning?: string | null\n}\n\ninterface ImportProgress {\n created: number\n updated: number\n errors: number\n total: number\n}\n\ninterface Props {\n /** Заголовок страницы. */\n title?: string\n /** Опции для select'а target field'а на step 2. */\n fieldOptions: Array<{ value: string; label: string }>\n /** Headers + sample из uploaded file (host передаёт после step 1). */\n headers?: ColumnHeader[]\n /** Preview rows с warning'ами (host передаёт после step 2 submit). */\n preview?: PreviewRow[]\n /** Preview-table columns (host передаёт). */\n previewColumns?: UidTableColumn[]\n /** Финальная сводка импорта. */\n progress?: ImportProgress | null\n /** Внешне controlled-mode current step (опц.). */\n step?: number\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n title: 'Импорт',\n headers: () => [],\n preview: () => [],\n previewColumns: () => [],\n progress: null,\n step: undefined,\n})\n\nconst emit = defineEmits<{\n /** Файл загружен — host анализирует, отдаёт headers через v-bind. */\n 'file-uploaded': [file: File]\n /** Mapping submit — host генерирует preview. */\n 'mapping-submit': [mapping: Mapping[]]\n /** Run import — host выполняет с реальной записью. */\n 'run-import': []\n /** Cancel wizard. */\n cancel: []\n}>()\n\nconst STEPS = [\n { label: 'Загрузка', description: 'CSV / TSV / XLSX' },\n { label: 'Сопоставление', description: 'Колонки файла → поля' },\n { label: 'Предпросмотр', description: 'Проверка первых строк' },\n { label: 'Импорт', description: 'Запуск + сводка' },\n]\n\nconst internalStep = ref(0)\nconst currentStep = computed(() => props.step ?? internalStep.value)\n\nfunction setStep(idx: number): void {\n if (props.step !== undefined) return // controlled mode — host сам сдвигает\n if (idx < 0 || idx >= STEPS.length) return\n internalStep.value = idx\n}\n\n// Step 1: file upload\nconst uploadedFiles = ref<Array<{ file: File; id: string }>>([])\nfunction onUpload(files: Array<{ file: File; id: string }>): void {\n uploadedFiles.value = files\n if (files.length > 0) {\n emit('file-uploaded', files[0].file)\n }\n}\n\n// Step 2: mapping\nconst mapping = ref<Record<string, string | null>>({})\n\nfunction setTarget(source: string, value: string | number | null): void {\n mapping.value[source] = value === null || value === '' ? null : String(value)\n}\n\nfunction buildMapping(): Mapping[] {\n return props.headers.map((h) => ({\n source: h.key,\n target: mapping.value[h.key] ?? null,\n }))\n}\n\nfunction onMappingSubmit(): void {\n emit('mapping-submit', buildMapping())\n setStep(2)\n}\n\n// Step 3 → 4\nfunction onConfirmRun(): void {\n emit('run-import')\n setStep(3)\n}\n\n// Кнопки навигации\nconst canGoBack = computed(() => currentStep.value > 0)\nconst canGoNext = computed(() => {\n switch (currentStep.value) {\n case 0: return uploadedFiles.value.length > 0\n case 1: return Object.values(mapping.value).some((v) => v !== null)\n case 2: return true\n default: return false\n }\n})\n\nconst fileOptions = computed<Array<{ value: string; label: string }>>(() => {\n return [\n { value: '', label: 'Не импортировать' },\n ...props.fieldOptions,\n ]\n})\n\nfunction onCancel(): void {\n emit('cancel')\n}\n</script>\n\n<template>\n <section class=\"admin-page admin-import-wizard\">\n <header class=\"admin-page__hd\">\n <div class=\"admin-page__title-wrap\">\n <h1 class=\"admin-page__title\">{{ title }}</h1>\n </div>\n <div class=\"admin-page__actions\">\n <UidButton variant=\"ghost\" @click=\"onCancel\">Отмена</UidButton>\n </div>\n </header>\n\n <UidStepper :steps=\"STEPS\" :current=\"currentStep\" />\n\n <!-- Step 1: Upload -->\n <UidCard v-if=\"currentStep === 0\" padding=\"md\" class=\"admin-import-wizard__card\">\n <header class=\"admin-import-wizard__card-hd\">\n <h3>1. Загрузите файл</h3>\n <p>CSV / TSV / XLSX, до 50 MB</p>\n </header>\n <UidFileUpload\n :model-value=\"uploadedFiles\"\n accept=\".csv,.tsv,.xlsx\"\n :max-size=\"50 * 1024 * 1024\"\n :max-files=\"1\"\n primary-text=\"Перетащите файл сюда или\"\n secondary-text=\"нажмите чтобы выбрать\"\n @update:model-value=\"onUpload\"\n />\n </UidCard>\n\n <!-- Step 2: Mapping -->\n <UidCard v-else-if=\"currentStep === 1\" padding=\"md\" class=\"admin-import-wizard__card\">\n <header class=\"admin-import-wizard__card-hd\">\n <h3>2. Сопоставьте колонки</h3>\n <p>Выберите поле ресурса для каждой колонки файла</p>\n </header>\n\n <div v-if=\"headers.length === 0\" class=\"admin-import-wizard__empty\">\n Нет данных — host ещё не отдал headers. Загрузите файл сначала.\n </div>\n\n <div v-else class=\"admin-import-wizard__mapping\">\n <div v-for=\"h in headers\" :key=\"h.key\" class=\"admin-import-wizard__map-row\">\n <div class=\"admin-import-wizard__map-source\">\n <strong>{{ h.label }}</strong>\n <span v-if=\"h.sample\" class=\"admin-import-wizard__map-sample\">\n «{{ h.sample }}»\n </span>\n </div>\n <span class=\"admin-import-wizard__map-arrow\">→</span>\n <UidSelect\n :model-value=\"mapping[h.key] ?? ''\"\n :options=\"fileOptions\"\n placeholder=\"Не импортировать\"\n @update:model-value=\"(v) => setTarget(h.key, v)\"\n />\n </div>\n </div>\n </UidCard>\n\n <!-- Step 3: Preview -->\n <UidCard v-else-if=\"currentStep === 2\" padding=\"md\" class=\"admin-import-wizard__card\">\n <header class=\"admin-import-wizard__card-hd\">\n <h3>3. Предпросмотр</h3>\n <p>Первые {{ preview.length }} строк перед импортом</p>\n </header>\n\n <UidAlert\n v-if=\"preview.some((r) => r.__warning)\"\n variant=\"warning\"\n style=\"margin-bottom: var(--uid-space-md);\"\n >\n Часть строк имеет предупреждения — проверьте перед импортом.\n </UidAlert>\n\n <UidTable\n v-if=\"previewColumns.length > 0\"\n :columns=\"previewColumns\"\n :data=\"preview\"\n />\n <div v-else class=\"admin-import-wizard__empty\">\n Host не передал previewColumns/preview.\n </div>\n </UidCard>\n\n <!-- Step 4: Run + Summary -->\n <UidCard v-else padding=\"md\" class=\"admin-import-wizard__card\">\n <header class=\"admin-import-wizard__card-hd\">\n <h3>4. Импорт</h3>\n </header>\n\n <div v-if=\"!progress\" class=\"admin-import-wizard__empty\">\n Запускается импорт…\n </div>\n <template v-else>\n <UidProgress\n v-if=\"progress.total > 0\"\n :model-value=\"progress.created + progress.updated + progress.errors\"\n :max=\"progress.total\"\n />\n <div class=\"admin-import-wizard__kpi\">\n <UidStat title=\"Создано\" :value=\"progress.created\" tone=\"success\" />\n <UidStat title=\"Обновлено\" :value=\"progress.updated\" tone=\"info\" />\n <UidStat title=\"Ошибки\" :value=\"progress.errors\" tone=\"danger\" />\n </div>\n </template>\n </UidCard>\n\n <!-- Navigation buttons -->\n <footer class=\"admin-import-wizard__nav\">\n <UidButton\n v-if=\"canGoBack\"\n variant=\"ghost\"\n @click=\"setStep(currentStep - 1)\"\n >\n Назад\n </UidButton>\n <span style=\"flex:1\" />\n <UidButton\n v-if=\"currentStep === 0\"\n variant=\"primary\"\n :disabled=\"!canGoNext\"\n @click=\"setStep(1)\"\n >\n Далее\n </UidButton>\n <UidButton\n v-else-if=\"currentStep === 1\"\n variant=\"primary\"\n :disabled=\"!canGoNext\"\n @click=\"onMappingSubmit\"\n >\n Подтвердить mapping\n </UidButton>\n <UidButton\n v-else-if=\"currentStep === 2\"\n variant=\"primary\"\n @click=\"onConfirmRun\"\n >\n Запустить импорт\n </UidButton>\n </footer>\n </section>\n</template>\n\n<style>\n.admin-import-wizard {\n max-width: 1100px;\n margin: 0 auto;\n}\n.admin-import-wizard__card {\n margin-top: var(--uid-space-md);\n}\n.admin-import-wizard__card-hd {\n margin-bottom: var(--uid-space-md);\n}\n.admin-import-wizard__card-hd h3 {\n margin: 0 0 var(--uid-space-2xs);\n font-size: var(--uid-font-size-md);\n font-weight: var(--uid-font-weight-semibold);\n}\n.admin-import-wizard__card-hd p {\n margin: 0;\n font-size: var(--uid-font-size-xs);\n color: var(--uid-text-tertiary);\n}\n.admin-import-wizard__empty {\n padding: var(--uid-space-md);\n text-align: center;\n color: var(--uid-text-tertiary);\n font-size: var(--uid-font-size-sm);\n}\n.admin-import-wizard__mapping {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-sm);\n}\n.admin-import-wizard__map-row {\n display: grid;\n grid-template-columns: 1fr auto 1fr;\n gap: var(--uid-space-md);\n align-items: center;\n}\n.admin-import-wizard__map-source {\n display: flex;\n align-items: center;\n gap: var(--uid-space-sm);\n}\n.admin-import-wizard__map-sample {\n color: var(--uid-text-tertiary);\n font-size: var(--uid-font-size-xs);\n font-style: italic;\n}\n.admin-import-wizard__map-arrow {\n color: var(--uid-text-tertiary);\n font-size: var(--uid-font-size-md);\n}\n.admin-import-wizard__kpi {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: var(--uid-space-md);\n margin-top: var(--uid-space-md);\n}\n.admin-import-wizard__nav {\n display: flex;\n align-items: center;\n gap: var(--uid-space-sm);\n margin-top: var(--uid-space-md);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * FieldGalleryPage — каталог field-компонентов.\n *\n * Эталон: docs/design_handoff_laravel_admin/screens-secondary.jsx (FieldGallery).\n *\n * 3-col grid из demo-cards. Каждая card:\n * - Group label (например \"Текстовые\")\n * - Тип поля (json type-key)\n * - Демо-компонент с sample-данными\n * - Краткое описание\n *\n * Используется как:\n * 1. Тестовая площадка для devs (визуально все Uid* fields на одной странице)\n * 2. Docs / referencer для host'ов\n *\n * Все секции рендерятся через FieldRenderer + provideFormState с локальной\n * state-mock'ой.\n */\nimport { reactive } from 'vue'\nimport { UidCard } from '@dskripchenko/ui'\nimport FieldRenderer, { type FieldNode } from '../render/FieldRenderer.vue'\nimport { provideFormState } from '../render/formState'\n\ninterface Demo {\n type: string\n group: string\n title: string\n description: string\n /** Demo node для FieldRenderer'а. */\n node: FieldNode\n /** Initial state для form-context. */\n initial: Record<string, unknown>\n}\n\nconst DEMOS: Demo[] = [\n // Текстовые\n {\n type: 'text',\n group: 'Текстовые',\n title: 'Input',\n description: 'Простой текстовый input. type=email/url/password/tel доступны через inputType.',\n node: { type: 'text', name: 'demo_text', label: 'Заголовок статьи', placeholder: 'Например: Введение в Laravel' },\n initial: { demo_text: 'Hello World' },\n },\n {\n type: 'textarea',\n group: 'Текстовые',\n title: 'Textarea',\n description: 'Многострочный input с настраиваемым числом rows.',\n node: { type: 'textarea', name: 'demo_textarea', label: 'Описание', rows: 4 },\n initial: { demo_textarea: 'Multi-line text...' },\n },\n {\n type: 'number',\n group: 'Текстовые',\n title: 'NumberInput',\n description: 'Числовой input. Empty/NaN автоматически конвертируются в null.',\n node: { type: 'number', name: 'demo_number', label: 'Цена', min: 0, max: 1000 },\n initial: { demo_number: 42 },\n },\n // Выбор\n {\n type: 'select',\n group: 'Выбор',\n title: 'Select',\n description: 'Single-select с options. Поддерживает searchable + clearable.',\n node: {\n type: 'select',\n name: 'demo_select',\n label: 'Категория',\n options: [\n { value: 'frontend', label: 'Frontend' },\n { value: 'backend', label: 'Backend' },\n { value: 'devops', label: 'DevOps' },\n ],\n },\n initial: { demo_select: 'backend' },\n },\n {\n type: 'checkbox',\n group: 'Выбор',\n title: 'Checkbox',\n description: 'Boolean toggle. inlineLabel рядом с боксом.',\n node: { type: 'checkbox', name: 'demo_checkbox', label: 'Опубликовать', inlineLabel: 'Сделать доступным всем' },\n initial: { demo_checkbox: true },\n },\n // Дата/время\n {\n type: 'date',\n group: 'Дата/время',\n title: 'DatePicker',\n description: 'date / datetime-local / time через inputType.',\n node: { type: 'date', name: 'demo_date', label: 'Дата публикации', inputType: 'date' },\n initial: { demo_date: '2026-05-01' },\n },\n]\n\n// Группируем для рендера.\nconst groupedDemos = DEMOS.reduce<Record<string, Demo[]>>((acc, d) => {\n if (!acc[d.group]) acc[d.group] = []\n acc[d.group].push(d)\n return acc\n}, {})\n\n// provideFormState на корневом уровне — все demo'и шарят один form-context\n// (имена не пересекаются благодаря demo_ префиксу).\nconst allInitial = reactive<Record<string, unknown>>(\n DEMOS.reduce<Record<string, unknown>>((acc, d) => Object.assign(acc, d.initial), {}),\n)\nprovideFormState(allInitial)\n</script>\n\n<template>\n <section class=\"admin-page admin-field-gallery\">\n <header class=\"admin-page__hd\">\n <div class=\"admin-page__title-wrap\">\n <h1 class=\"admin-page__title\">Field Gallery</h1>\n <div class=\"admin-page__count\">\n Каталог встроенных field-компонентов library + примеры использования\n </div>\n </div>\n </header>\n\n <section v-for=\"(items, group) in groupedDemos\" :key=\"group\" class=\"admin-gallery__group\">\n <h2 class=\"admin-gallery__group-title\">{{ group }}</h2>\n <div class=\"admin-gallery__grid\">\n <UidCard\n v-for=\"demo in items\"\n :key=\"demo.type + demo.title\"\n padding=\"md\"\n class=\"admin-gallery__card\"\n >\n <header class=\"admin-gallery__card-hd\">\n <h3 class=\"admin-gallery__card-title\">{{ demo.title }}</h3>\n <code class=\"admin-gallery__card-type\">type: {{ demo.type }}</code>\n </header>\n <p class=\"admin-gallery__card-desc\">{{ demo.description }}</p>\n <div class=\"admin-gallery__card-demo\">\n <FieldRenderer :node=\"demo.node\" />\n </div>\n </UidCard>\n </div>\n </section>\n </section>\n</template>\n\n<style>\n.admin-gallery__group {\n margin-bottom: var(--uid-space-2xl);\n}\n.admin-gallery__group-title {\n margin: 0 0 var(--uid-space-md);\n font-size: var(--uid-font-size-lg);\n font-weight: var(--uid-font-weight-semibold);\n color: var(--uid-text-primary);\n}\n.admin-gallery__grid {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: var(--uid-space-md);\n}\n@media (max-width: 960px) {\n .admin-gallery__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }\n}\n@media (max-width: 640px) {\n .admin-gallery__grid { grid-template-columns: 1fr; }\n}\n.admin-gallery__card {\n display: flex;\n flex-direction: column;\n}\n.admin-gallery__card-hd {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--uid-space-sm);\n margin-bottom: var(--uid-space-xs);\n}\n.admin-gallery__card-title {\n margin: 0;\n font-size: var(--uid-font-size-sm);\n font-weight: var(--uid-font-weight-semibold);\n}\n.admin-gallery__card-type {\n font-family: var(--uid-font-family-mono);\n font-size: 11px;\n color: var(--uid-text-tertiary);\n background: var(--uid-surface-base);\n padding: 1px 6px;\n border-radius: var(--uid-radius-sm);\n border: 1px solid var(--uid-border-subtle);\n}\n.admin-gallery__card-desc {\n margin: 0 0 var(--uid-space-md);\n font-size: var(--uid-font-size-xs);\n color: var(--uid-text-tertiary);\n line-height: var(--uid-line-height-normal);\n}\n.admin-gallery__card-demo {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: flex-end;\n}\n</style>\n"],"names":["_client","setAdminClient","client","getAdminClient","clearAdminClient","hasAdminClient","useThemeStore","defineStore","current","ref","available","isDark","computed","hydrate","bootstrap","applyHtmlAttr","applyLocal","theme","setTheme","previous","err","iconName","ariaLabel","toggle","next","_createElementBlock","_createElementVNode","useLocaleStore","applySideEffects","locale","setLocale","pick","loc","_createBlock","_unref","UidMenu","_hoisted_1","_toDisplayString","_openBlock","_Fragment","_renderList","UidMenuItem","$event","_createTextVNode","useNotificationsStore","items","unreadCount","loading","lastFilter","meta","hasUnread","load","filter","page","result","loadUnread","markAsRead","id","item","n","markAllAsRead","now","destroy","index","wasUnread","notifications","display","RouterLink","ApiError","status","payload","UnauthenticatedError","ForbiddenError","NotFoundError","ValidationError","messages","NetworkError","message","toApiError","useAuthStore","user","permissions","pendingChallenge","isAuthenticated","isChallengePending","hasPermission","key","permission","prefix","hasAnyPermission","keys","hasAllPermissions","login","challengeToken","twoFactorChallenge","code","twoFactorRecovery","recoveryCode","cancelChallenge","logout","auth","router","useRouter","goProfile","_createVNode","UidAvatar","_cache","UidMenuSeparator","props","__props","emit","__emit","lastIdx","_hoisted_2","_renderSlot","_ctx","crumb","idx","_hoisted_3","_resolveDynamicComponent","_normalizeClass","NotificationBell","ThemeToggle","LocaleSwitcher","UserMenu","useMenuStore","error","isLoaded","visibleItems","it","filteredChildren","c","i","groupedItems","groups","groupKey","group","list","a","b","orderDiff","force","response","setItems","reset","menu","route","useRoute","isActive","iconSlot","name","h","itemTarget","UidSidebar","_createSlots","_hoisted_4","grp","UidSidebarGroup","UidSidebarItem","_hoisted_5","_hoisted_6","_hoisted_7","HTML_ATTR","onCollapseChange","value","exitImpersonation","watch","val","onBeforeUnmount","UidSidebarLayout","AdminSidebar","AdminTopBar","useShell","AdminShell","_component_router_view","useManifestStore","manifest","version","resources","screens","settings","plugins","getResource","slug","r","getScreen","s","getSettings","userName","UidCard","UidButton","title","email","password","remember","submitting","generalError","fieldErrors","emailError","passwordError","submit","UidAlert","UidInput","UidCheckbox","mode","cells","cellRefs","remaining","totpCode","isValid","setCellRef","el","onCellInput","event","target","digit","nextTick","onCellKeydown","onPaste","digits","res","cancel","switchMode","_","redirectToHome","onMounted","_hoisted_8","TwoFactorForm","LoginForm","DEFAULT_META","useResourceIndexStore","search","filters","sortKey","sortDirection","selection","isEmpty","selectedCount","hasSelection","hasError","selectionState","row","rowId","setSlug","buildParams","override","params","ss","sk","f","k","v","setSearch","setFilter","clearFilters","setSort","direction","toggleSort","setPage","toggleRow","toggleAllOnPage","clearSelection","isSelected","resourceMeta","displayTitle","columns","col","totalLabel","t","prev","onSortUpdate","onPageChange","onHeaderCheckbox","onRowCheckbox","onRowClick","bulkAction","action","retryLoad","$router","_hoisted_9","_withKeys","e","_hoisted_11","UidSkeleton","UidErrorState","UidEmptyState","_hoisted_12","_hoisted_13","UidTable","_withCtx","_hoisted_14","_hoisted_16","UidPagination","useResourceFormStore","recordId","state","initial","errors","saving","deleting","isCreate","isEdit","isView","isDirty","replaceObject","prepareCreate","resourceSlug","defaults","targetMode","setField","setErrors","clearErrors","save","url","newId","createComponentRegistry","store","type","bundle","fields","layouts","registerField","getField","hasField","listFields","registerLayout","getLayout","hasLayout","listLayouts","clearRegistry","registerComponents","component","fieldProps","_type","rest","_normalizeProps","_mergeProps","UnknownField","resolved","layoutComponent","layoutProps","_kind","fieldNode","FieldRenderer","form","ctx","provideFormState","layoutNodes","titleLabel","statusValue","statusBadgeVariant","nextSlug","nextId","onSave","onDelete","onCancel","UidBadge","node","LayoutRenderer","entries","registerInfolistEntry","getInfolistEntry","hasInfolistEntry","listInfolistEntries","clearInfolistRegistry","registerInfolistEntries","KNOWN_LAYOUTS","entry","entryProps","_t","_k","_i","sectionTitle","sectionDescription","tabsActive","tabsList","child","_component_InfolistRenderer","_normalizeStyle","tab","_hoisted_10","UnknownEntry","RecordKey","provideRecord","record","provide","useRecord","inject","tryUseRecord","onEdit","InfolistRenderer","navItems","localSection","selectSection","profile","localeOptions","l","themeOptions","onAvatarReplace","on2FADisable","on2FARegenerate","has2FA","_hoisted_15","UidSelect","_hoisted_17","_hoisted_18","_hoisted_19","_hoisted_20","_hoisted_21","widgets","registerWidget","getWidget","hasWidget","listWidgets","clearWidgetRegistry","registerWidgets","widgetProps","_span","UnknownWidget","dashboard","d","resolvedWidgets","resolvedTitle","resolvedSubtitle","spanFor","w","WidgetRenderer","TONE_MAP","uidTone","UidStat","maxValue","bars","barWidth","bar","PALETTE","total","x","slices","cumulative","startAngle","endAngle","cx","cy","x1","y1","x2","y2","largeArc","path","UidHeatmap","UidGauge","registerBuiltinWidgets","StatWidget","BarChartWidget","DonutChartWidget","RecentTableWidget","HeatmapWidget","GaugeWidget","MarkdownWidget","isSuccess","env","isError","createAdminClient","opts","instance","axios","config","xsrf","readCookie","apiError","wrap","method","wrapBody","data","match","escapeRegex","pickResourcePermission","resource","ability","perm","pickSettingsPermission","pickScreenPermission","buildResourceRoutes","components","base","buildScreenRoute","screen","buildSettingsRoute","buildDashboardRoute","buildRoutesFromManifest","routes","createAuthGuard","loginRouteName","forbiddenRouteName","redirectQueryKey","to","permissionsMeta","createTitleGuard","template","brand","fallback","DYNAMIC_NAME_PREFIXES","isDynamicRouteName","p","createAdminRouter","history","createWebHistory","staticRoutes","notFoundRoute","createRouter","allRoutes","dynamic","useFormState","errorMsg","onUpdate","UidFormField","UidTextarea","UidNumberInput","checked","UidDatePicker","UidStack","defaultSpan","UidGrid","tabKey","localActive","UidTabs","UidTab","UidTabPanel","cidx","registerBuiltinComponents","TextField","TextAreaField","NumberField","SelectField","CheckboxField","DateField","RowsLayout","ColumnsLayout","SectionLayout","TabsLayout","resolvedVariant","flag","displayLabel","formatValue","UidDescriptionList","UidDescriptionItem","registerBuiltinInfolistEntries","TextEntry","BadgeEntry","IconEntry","KeyValueEntry","createAdminApp","options","pages","deriveBase","app","createApp","AdminApp","pinia","createPinia","LoginPage","HomePage","ForbiddenPage","NotFoundPage","ProfilePage","ResourceIndexPage","ResourceFormPage","ResourceViewPage","DashboardPage","SettingsPage","UnknownScreenPage","baseUrl","loadBootstrap","inline","readInlineBootstrap","readCsrfFromMeta","setOpen","activeFilter","markAllRead","onItemClick","onDestroy","itemKind","lvl","itemTitle","itemBody","relTime","iso","dt","diff","mins","hours","days","UidDrawer","STEPS","internalStep","currentStep","setStep","uploadedFiles","onUpload","files","mapping","setTarget","source","buildMapping","onMappingSubmit","onConfirmRun","canGoBack","canGoNext","fileOptions","UidStepper","UidFileUpload","UidProgress","DEMOS","groupedDemos","acc","allInitial","reactive","demo"],"mappings":";;;;;;;AAcA,IAAIA,KAA8B;AAE3B,SAASC,GAAeC,GAA2B;AACxD,EAAAF,KAAUE;AACZ;AAEO,SAASC,IAA8B;AAC5C,MAAIH,OAAY;AACd,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAGJ,SAAOA;AACT;AAEO,SAASI,KAAyB;AACvC,EAAAJ,KAAU;AACZ;AAEO,SAASK,KAA0B;AACxC,SAAOL,OAAY;AACrB;ACvBO,MAAMM,KAAgBC,EAAY,eAAe,MAAM;AAC5D,QAAMC,IAAUC,EAAY,OAAO,GAC7BC,IAAYD,EAAc,CAAC,SAAS,MAAM,CAAC,GAE3CE,IAASC,EAAS,MAAMJ,EAAQ,UAAU,MAAM;AAEtD,WAASK,EAAQC,GAAiC;AAChD,IAAAN,EAAQ,QAAQM,EAAU,OAC1BJ,EAAU,QAAQI,EAAU,iBAC5BC,EAAcD,EAAU,KAAK;AAAA,EAC/B;AAMA,WAASE,EAAWC,GAAqB;AACvC,QAAI,CAACP,EAAU,MAAM,SAASO,CAAK;AACjC,YAAM,IAAI,MAAM,UAAUA,CAAK,oBAAoB;AAErD,IAAAT,EAAQ,QAAQS,GAChBF,EAAcE,CAAK;AAAA,EACrB;AAMA,iBAAeC,EAASD,GAA8B;AACpD,QAAI,CAACP,EAAU,MAAM,SAASO,CAAK;AACjC,YAAM,IAAI,MAAM,UAAUA,CAAK,oBAAoB;AAGrD,UAAME,IAAWX,EAAQ;AACzB,IAAAQ,EAAWC,CAAK;AAEhB,QAAI;AAEF,YADed,EAAA,EACF,KAAK,oBAAoB,EAAE,OAAAc,GAAO;AAAA,IACjD,SAASG,GAAK;AAEZ,YAAAJ,EAAWG,CAAQ,GACbC;AAAA,IACR;AAAA,EACF;AAEA,WAASL,EAAcE,GAAqB;AAC1C,IAAI,OAAO,WAAa,OAAe,SAAS,mBAC9C,SAAS,gBAAgB,aAAa,cAAcA,CAAK;AAAA,EAE7D;AAEA,SAAO;AAAA,IACL,SAAAT;AAAA,IACA,WAAAE;AAAA,IACA,QAAAC;AAAA,IACA,SAAAE;AAAA,IACA,YAAAG;AAAA,IACA,UAAAE;AAAA,EAAA;AAEJ,CAAC;;;AC/DD,UAAMD,IAAQX,GAAA,GAERK,IAASC,EAAS,MAAMK,EAAM,YAAY,MAAM,GAChDI,IAAWT,EAAS,MAAOD,EAAO,QAAQ,QAAQ,MAAO,GACzDW,IAAYV;AAAA,MAAS,MACzBD,EAAO,QAAQ,gCAAgC;AAAA,IAAA;AAGjD,mBAAeY,IAAwB;AACrC,YAAMC,IAAOb,EAAO,QAAQ,UAAU;AACtC,YAAMM,EAAM,SAASO,CAAI;AAAA,IAC3B;2BAIEC,EAQS,UAAA;AAAA,MAPP,MAAK;AAAA,MACL,OAAM;AAAA,MACL,cAAYH,EAAA;AAAA,MACZ,gBAAcX,EAAA;AAAA,MACd,SAAOY;AAAA,IAAA;MAERG,EAAyD,QAAA;AAAA,QAAnD,OAAM;AAAA,QAAsB,aAAWL,EAAA;AAAA,MAAA;;;IChBpCM,KAAiBpB,EAAY,gBAAgB,MAAM;AAC9D,QAAMC,IAAUC,EAAY,IAAI,GAC1BC,IAAYD,EAAc,CAAC,MAAM,IAAI,CAAC;AAE5C,WAASI,EAAQC,GAAiC;AAChD,IAAAN,EAAQ,QAAQM,EAAU,QAC1BJ,EAAU,QAAQI,EAAU,kBAC5Bc,EAAiBd,EAAU,MAAM;AAAA,EACnC;AAEA,WAASE,EAAWa,GAAsB;AACxC,QAAI,CAACnB,EAAU,MAAM,SAASmB,CAAM;AAClC,YAAM,IAAI,MAAM,WAAWA,CAAM,oBAAoB;AAEvD,IAAArB,EAAQ,QAAQqB,GAChBD,EAAiBC,CAAM;AAAA,EACzB;AAEA,iBAAeC,EAAUD,GAA+B;AACtD,QAAI,CAACnB,EAAU,MAAM,SAASmB,CAAM;AAClC,YAAM,IAAI,MAAM,WAAWA,CAAM,oBAAoB;AAGvD,UAAMV,IAAWX,EAAQ;AACzB,IAAAQ,EAAWa,CAAM;AAEjB,QAAI;AAEF,YADe1B,EAAA,EACF,KAAK,qBAAqB,EAAE,QAAA0B,GAAQ;AAAA,IACnD,SAAST,GAAK;AACZ,YAAAJ,EAAWG,CAAQ,GACbC;AAAA,IACR;AAAA,EACF;AAEA,WAASQ,EAAiBC,GAAsB;AAC9C,IAAI,OAAO,WAAa,OAAe,SAAS,mBAC9C,SAAS,gBAAgB,aAAa,QAAQA,CAAM;AAGtD,QAAI;AACF,MAAA1B,EAAA,EAAiB,UAAU0B,CAAM;AAAA,IACnC,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAArB;AAAA,IACA,WAAAE;AAAA,IACA,SAAAG;AAAA,IACA,YAAAG;AAAA,IACA,WAAAc;AAAA,EAAA;AAEJ,CAAC;;;;;;;;AC7DD,UAAMD,IAASF,GAAA;AAEf,mBAAeI,EAAKC,GAA4B;AAC9C,MAAIA,MAAQH,EAAO,WACnB,MAAMA,EAAO,UAAUG,CAAG;AAAA,IAC5B;2BAIEC,EAoBUC,EAAAC,EAAA,GAAA,MAAA;AAAA,MAnBG,WACT,MAQS;AAAA,QARTT,EAQS,UARTU,IAQS;AAAA,0BAFPV,EAAqD,QAAA;AAAA,YAA/C,OAAM;AAAA,YAAqB,aAAU;AAAA,UAAA;UAC3CA,EAAuD,QAAA,MAAAW,GAA7CH,EAAAL,CAAA,EAAO,eAAe,YAAA,CAAW,GAAA,CAAA;AAAA,QAAA;;iBAK7C,MAA+B;AAAA,SADjCS,EAAA,EAAA,GAAAb,EAMcc,GAAA,MAAAC,EALEN,EAAAL,CAAA,EAAO,YAAdG,YADTC,EAMcC,EAAAO,EAAA,GAAA;AAAA,UAJX,KAAKT;AAAA,UACL,SAAK,CAAAU,MAAEX,EAAKC,CAAG;AAAA,QAAA;qBAEhB,MAAuB;AAAA,YAApBW,EAAAN,EAAAL,EAAI,YAAA,CAAW,GAAA,CAAA;AAAA,UAAA;;;;;;;ICZXY,KAAwBrC,EAAY,uBAAuB,MAAM;AAC5E,QAAMsC,IAAQpC,EAAwB,EAAE,GAClCqC,IAAcrC,EAAI,CAAC,GACnBsC,IAAUtC,EAAI,EAAK,GACnBuC,IAAavC,EAAwB,KAAK,GAC1CwC,IAAOxC,EAAiF,IAAI,GAE5FyC,IAAYtC,EAAS,MAAMkC,EAAY,QAAQ,CAAC;AAEtD,WAASjC,EAAQC,GAAiC;AAChD,IAAAgC,EAAY,QAAQhC,EAAU;AAAA,EAChC;AAEA,iBAAeqC,EAAKC,IAA6B,OAAOC,IAAO,GAAkB;AAC/E,IAAAN,EAAQ,QAAQ;AAChB,QAAI;AAEF,YAAMO,IAAS,MADAnD,EAAA,EACa,IAGzB,4BAA4BiD,CAAM,SAASC,CAAI,EAAE;AACpD,MAAAR,EAAM,QAAQS,EAAO,MACrBR,EAAY,QAAQQ,EAAO,KAAK,cAChCL,EAAK,QAAQ;AAAA,QACX,MAAMK,EAAO,KAAK;AAAA,QAClB,UAAUA,EAAO,KAAK;AAAA,QACtB,OAAOA,EAAO,KAAK;AAAA,QACnB,WAAWA,EAAO,KAAK;AAAA,MAAA,GAEzBN,EAAW,QAAQI;AAAA,IACrB,UAAA;AACE,MAAAL,EAAQ,QAAQ;AAAA,IAClB;AAAA,EACF;AAMA,iBAAeQ,IAA4B;AAEzC,UAAMD,IAAS,MADAnD,EAAA,EACa;AAAA,MAC1B;AAAA,IAAA;AAEF,IAAA2C,EAAY,QAAQQ,EAAO,OAEvBN,EAAW,UAAU,aACvBH,EAAM,QAAQS,EAAO;AAAA,EAEzB;AAEA,iBAAeE,EAAWC,GAA2B;AAEnD,UADetD,EAAA,EACF,KAAK,6BAA6B,EAAE,IAAAsD,GAAI;AAErD,UAAMC,IAAOb,EAAM,MAAM,KAAK,CAACc,MAAMA,EAAE,OAAOF,CAAE;AAChD,IAAIC,KAAQA,EAAK,YAAY,SAC3BA,EAAK,WAAU,oBAAI,KAAA,GAAO,YAAA,GAC1BZ,EAAY,QAAQ,KAAK,IAAI,GAAGA,EAAY,QAAQ,CAAC;AAAA,EAEzD;AAEA,iBAAec,IAA+B;AAE5C,UADezD,EAAA,EACF,KAAK,8BAA8B;AAChD,UAAM0D,KAAM,oBAAI,KAAA,GAAO,YAAA;AACvB,eAAWH,KAAQb,EAAM;AACvB,MAAIa,EAAK,YAAY,SAAMA,EAAK,UAAUG;AAE5C,IAAAf,EAAY,QAAQ;AAAA,EACtB;AAEA,iBAAegB,EAAQL,GAA2B;AAEhD,UADetD,EAAA,EACF,KAAK,0BAA0B,EAAE,IAAAsD,GAAI;AAClD,UAAMM,IAAQlB,EAAM,MAAM,UAAU,CAACc,MAAMA,EAAE,OAAOF,CAAE;AACtD,QAAIM,MAAU,IAAI;AAChB,YAAMC,IAAYnB,EAAM,MAAMkB,CAAK,EAAE,YAAY;AACjD,MAAAlB,EAAM,MAAM,OAAOkB,GAAO,CAAC,GACvBC,MACFlB,EAAY,QAAQ,KAAK,IAAI,GAAGA,EAAY,QAAQ,CAAC;AAAA,IAEzD;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAAD;AAAA,IACA,aAAAC;AAAA,IACA,SAAAC;AAAA,IACA,MAAAE;AAAA,IACA,YAAAD;AAAA,IACA,WAAAE;AAAA,IACA,SAAArC;AAAA,IACA,MAAAsC;AAAA,IACA,YAAAI;AAAA,IACA,YAAAC;AAAA,IACA,eAAAI;AAAA,IACA,SAAAE;AAAA,EAAA;AAEJ,CAAC;;;ACjHD,UAAMG,IAAgBrB,GAAA,GAEhBsB,IAAUtD,EAAS,MAAM;AAC7B,YAAM+C,IAAIM,EAAc;AACxB,aAAIN,KAAK,IAAU,OACZA,IAAI,KAAK,QAAQ,OAAOA,CAAC;AAAA,IAClC,CAAC;2BAIC1B,EAaaC,EAAAiC,EAAA,GAAA;AAAA,MAZX,IAAG;AAAA,MACH,OAAM;AAAA,MACN,cAAW;AAAA,IAAA;iBAEX,MAAoD;AAAA,wBAApDzC,EAAoD,QAAA;AAAA,UAA9C,OAAM;AAAA,UAAqB,aAAU;AAAA,QAAA;QAEnCwC,EAAA,UAAO,aADfzC,EAMO,QAAA;AAAA;UAJL,OAAM;AAAA,UACL,OAAK,kBAAoBS,EAAA+B,CAAA,EAAc,WAAW;AAAA,QAAA,KAEhDC,EAAA,KAAO,GAAA,GAAA9B,EAAA;;;;;;ACrBT,MAAMgC,UAAiB,MAAM;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EAEhB,YAAYC,GAAgBC,GAAmC;AAC7D,UAAMA,EAAQ,WAAW,aAAaD,CAAM,EAAE,GAC9C,KAAK,OAAO,YACZ,KAAK,SAASA,GACd,KAAK,WAAWC,EAAQ,YAAY,WACpC,KAAK,UAAUA;AAAA,EACjB;AACF;AAEO,MAAMC,WAA6BH,EAAS;AAAA,EACjD,YAAYE,GAAmC;AAC7C,UAAM,KAAKA,CAAO,GAClB,KAAK,OAAO;AAAA,EACd;AACF;AAEO,MAAME,WAAuBJ,EAAS;AAAA,EAC3C,YAAYE,GAAmC;AAC7C,UAAM,KAAKA,CAAO,GAClB,KAAK,OAAO;AAAA,EACd;AACF;AAEO,MAAMG,WAAsBL,EAAS;AAAA,EAC1C,YAAYE,GAAmC;AAC7C,UAAM,KAAKA,CAAO,GAClB,KAAK,OAAO;AAAA,EACd;AACF;AAEO,MAAMI,WAAwBN,EAAS;AAAA;AAAA,EAE5B;AAAA,EAEhB,YAAYE,GAAmC;AAC7C,UAAM,KAAKA,CAAO,GAClB,KAAK,OAAO,mBACZ,KAAK,SAASA,EAAQ,YAAY,CAAA;AAAA,EACpC;AAAA;AAAA,EAGA,oBAAmC;AACjC,eAAWK,KAAY,OAAO,OAAO,KAAK,MAAM;AAC9C,UAAIA,EAAS,SAAS;AACpB,eAAOA,EAAS,CAAC;AAGrB,WAAO;AAAA,EACT;AACF;AAMO,MAAMC,WAAqB,MAAM;AAAA,EACtC,YAAYC,IAAU,iBAAiB;AACrC,UAAMA,CAAO,GACb,KAAK,OAAO;AAAA,EACd;AACF;AAKO,SAASC,GAAWT,GAAgBC,GAA6C;AACtF,UAAQD,GAAA;AAAA,IACN,KAAK;AAAK,aAAO,IAAIE,GAAqBD,CAAO;AAAA,IACjD,KAAK;AAAK,aAAO,IAAIE,GAAeF,CAAO;AAAA,IAC3C,KAAK;AAAK,aAAO,IAAIG,GAAcH,CAAO;AAAA,IAC1C,KAAK;AAAK,aAAO,IAAII,GAAgBJ,CAAO;AAAA,IAC5C;AAAU,aAAO,IAAIF,EAASC,GAAQC,CAAO;AAAA,EAAA;AAEjD;ACvDO,MAAMS,IAAexE,EAAY,cAAc,MAAM;AAC1D,QAAMyE,IAAOvE,EAAsB,IAAI,GACjCwE,IAAcxE,EAAc,EAAE,GAC9ByE,IAAmBzE,EAA6B,IAAI,GAEpD0E,IAAkBvE,EAAS,MAAMoE,EAAK,UAAU,IAAI,GACpDI,IAAqBxE,EAAS,MAAMsE,EAAiB,UAAU,IAAI;AAGzE,WAASrE,EAAQC,GAAiC;AAChD,IAAAkE,EAAK,QAAQlE,EAAU,MACvBmE,EAAY,QAAQnE,EAAU;AAAA,EAChC;AAOA,WAASuE,EAAcC,GAAsB;AAE3C,WADIL,EAAY,MAAM,SAAS,GAAG,KAC9BA,EAAY,MAAM,SAASK,CAAG,IAAU,KACrCL,EAAY,MAAM,KAAK,CAACM,MAAe;AAC5C,UAAI,CAACA,EAAW,SAAS,IAAI,EAAG,QAAO;AACvC,YAAMC,IAASD,EAAW,MAAM,GAAG,EAAE;AACrC,aAAOD,EAAI,WAAWE,CAAM;AAAA,IAC9B,CAAC;AAAA,EACH;AAEA,WAASC,EAAiBC,GAAyB;AACjD,WAAOA,EAAK,KAAKL,CAAa;AAAA,EAChC;AAEA,WAASM,EAAkBD,GAAyB;AAClD,WAAOA,EAAK,MAAML,CAAa;AAAA,EACjC;AASA,iBAAeO,EAAMtB,GAAyE;AAC5F,UAAMpE,IAASC,EAAA;AACf,QAAI;AACF,YAAMmD,IAAS,MAAMpD,EAAO;AAAA,QAC1B;AAAA,QACAoE;AAAA,MAAA;AAEF,aAAIhB,GAAQ,SACV0B,EAAK,QAAQ1B,EAAO,OAElB,MAAM,QAAQA,GAAQ,WAAW,MACnC2B,EAAY,QAAQ3B,EAAO,cAE7B4B,EAAiB,QAAQ,MAClB;AAAA,IACT,SAAS9D,GAAK;AACZ,UAAIA,aAAegD,KAAYhD,EAAI,aAAa,uBAAuB;AACrE,cAAMyE,IAAkBzE,EAAI,QAAoC;AAChE,eAAA8D,EAAiB,QAAQ;AAAA,UACvB,gBAAgB,OAAOW,KAAmB,WAAWA,IAAiB;AAAA,UACtE,UAAUvB,EAAQ,YAAY;AAAA,QAAA,GAEzB;AAAA,MACT;AACA,YAAMlD;AAAA,IACR;AAAA,EACF;AAGA,iBAAe0E,EAAmBC,GAA6B;AAC7D,QAAIb,EAAiB,UAAU;AAC7B,YAAM,IAAI,MAAM,0BAA0B;AAG5C,UAAM5B,IAAS,MADAnD,EAAA,EACa,KAA0B,4BAA4B;AAAA,MAChF,iBAAiB+E,EAAiB,MAAM;AAAA,MACxC,MAAAa;AAAA,IAAA,CACD;AACD,IAAAf,EAAK,QAAQ1B,EAAO,MACpB4B,EAAiB,QAAQ;AAAA,EAC3B;AAGA,iBAAec,EAAkBC,GAAsD;AACrF,QAAIf,EAAiB,UAAU;AAC7B,YAAM,IAAI,MAAM,0BAA0B;AAG5C,UAAM5B,IAAS,MADAnD,EAAA,EACa,KAGzB,2BAA2B;AAAA,MAC5B,iBAAiB+E,EAAiB,MAAM;AAAA,MACxC,eAAee;AAAA,IAAA,CAChB;AACD,WAAAjB,EAAK,QAAQ1B,EAAO,MACpB4B,EAAiB,QAAQ,MAClB,EAAE,WAAW5B,EAAO,yBAAA;AAAA,EAC7B;AAGA,WAAS4C,IAAwB;AAC/B,IAAAhB,EAAiB,QAAQ;AAAA,EAC3B;AAGA,iBAAeiB,IAAwB;AACrC,UAAMjG,IAASC,EAAA;AACf,QAAI;AACF,YAAMD,EAAO,KAAK,cAAc;AAAA,IAClC,UAAA;AACE,MAAA8E,EAAK,QAAQ,MACbC,EAAY,QAAQ,CAAA,GACpBC,EAAiB,QAAQ;AAAA,IAC3B;AAAA,EACF;AAEA,SAAO;AAAA;AAAA,IAEL,MAAAF;AAAA,IACA,aAAAC;AAAA,IACA,kBAAAC;AAAA;AAAA,IAEA,iBAAAC;AAAA,IACA,oBAAAC;AAAA;AAAA,IAEA,SAAAvE;AAAA,IACA,eAAAwE;AAAA,IACA,kBAAAI;AAAA,IACA,mBAAAE;AAAA,IACA,OAAAC;AAAA,IACA,oBAAAE;AAAA,IACA,mBAAAE;AAAA,IACA,iBAAAE;AAAA,IACA,QAAAC;AAAA,EAAA;AAEJ,CAAC;;;;;;;;;ACnKD,UAAMC,IAAOrB,EAAA,GACPsB,IAASC,GAAA;AAEf,mBAAeH,IAAwB;AACrC,UAAI;AACF,cAAMC,EAAK,OAAA;AAAA,MACb,UAAA;AACE,cAAMC,EAAO,KAAK,EAAE,MAAM,eAAe;AAAA,MAC3C;AAAA,IACF;AAEA,aAASE,IAAkB;AACzB,MAAKF,EAAO,KAAK,EAAE,MAAM,iBAAiB;AAAA,IAC5C;2BAIEpE,EAqBUC,EAAAC,EAAA,GAAA,MAAA;AAAA,MApBG,WACT,MAaS;AAAA,QAbTT,EAaS,UAbTU,IAaS;AAAA,UANPoE,EAKEtE,EAAAuE,EAAA,GAAA;AAAA,YAJC,KAAKvE,EAAAkE,CAAA,EAAK,MAAM,UAAU;AAAA,YAC1B,MAAMlE,EAAAkE,CAAA,EAAK,MAAM,QAAI;AAAA,YACrB,KAAKlE,EAAAkE,CAAA,EAAK,MAAM,QAAI;AAAA,YACrB,MAAK;AAAA,UAAA;;;iBAKX,MAAqD;AAAA,QAArDI,EAAqDtE,EAAAO,EAAA,GAAA,EAAvC,SAAO8D,KAAS;AAAA,qBAAE,MAAO,CAAA,GAAAG,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,cAAP,WAAO,EAAA;AAAA,UAAA;;;QACvCF,EAAoBtE,EAAAyE,EAAA,CAAA;AAAA,QACpBH,EAAiEtE,EAAAO,EAAA,GAAA;AAAA,UAApD,SAAQ;AAAA,UAAU,SAAO0D;AAAA,QAAA;qBAAQ,MAAK,CAAA,GAAAO,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,cAAL,SAAK,EAAA;AAAA,UAAA;;;;;;;;;;;;;;;;;;AChBvD,UAAME,IAAQC,GAKRC,IAAOC,GAIPC,IAAUpG,EAAS,MAAMgG,EAAM,YAAY,SAAS,CAAC;sBAIzDtE,EAAA,GAAAb,EAyCS,UAzCTW,IAyCS;AAAA,MAvCCyE,EAAA,2BADRpF,EAQS,UAAA;AAAA;QANP,MAAK;AAAA,QACL,OAAM;AAAA,QACN,cAAW;AAAA,QACV,gCAAOqF,EAAI,gBAAA;AAAA,MAAA;QAEZpF,EAA0D,QAAA;AAAA,UAApD,OAAM;AAAA,UAAqB,aAAU;AAAA,QAAA;;MAG7CA,EAaM,OAbNuF,IAaM;AAAA,QAZJC,EAWOC,6BAXP,MAWO;AAAA,WAVL7E,EAAA,EAAA,GAAAb,EASWc,GAAA,MAAAC,EATsBqE,EAAA,aAAW,CAA1BO,GAAOC,wBAA2BA,KAAG;AAAA,YACzCA,IAAG,UAAf5F,EAAyC,QAAzC6F,IAAiC,GAAC;kBAClCrF,EAMYsF,GALLH,EAAM,KAAE,MAAA,MAAA,GAAA;AAAA,cACZ,MAAI,OAASA,EAAM,iBAAkBA,EAAM,KAAK;AAAA,cAChD,OAAKI,EAAEH,MAAQL,EAAA,QAAO,QAAA,EAAA;AAAA,YAAA;yBAEvB,MAAiB;AAAA,gBAAdrE,EAAAN,EAAA+E,EAAM,KAAK,GAAA,CAAA;AAAA,cAAA;;;;;;sBAMtB1F,EAAoC,OAAA,EAA/B,OAAM,uBAAA,GAAsB,MAAA,EAAA;AAAA,MAEjCwF,EAMOC,wBANP,MAMO;AAAA,wBALLzF,EAIM,OAAA;AAAA,UAJD,OAAM;AAAA,UAAuB,MAAK;AAAA,UAAS,UAAS;AAAA,QAAA;UACvDA,EAAsD,QAAA;AAAA,YAAhD,OAAM;AAAA,YAAqB,aAAU;AAAA,UAAA;UAC3CA,EAAyB,cAAnB,cAAY;AAAA,UAClBA,EAAa,aAAR,IAAE;AAAA,QAAA;;MAIXwF,EAAuBC,EAAA,QAAA,SAAA;AAAA,MACvBX,EAAoBiB,EAAA;AAAA,MACpBjB,EAAekB,EAAA;AAAA,MACflB,EAAkBmB,EAAA;AAAA,MAClBnB,EAAYoB,EAAA;AAAA,IAAA;;ICrCHC,KAAetH,EAAY,cAAc,MAAM;AAC1D,QAAMsC,IAAQpC,EAAgB,EAAE,GAC1BsC,IAAUtC,EAAI,EAAK,GACnBqH,IAAQrH,EAAkB,IAAI,GAC9BsH,IAAWtH,EAAI,EAAK,GAOpBuH,IAAepH,EAAqB,MAAM;AAC9C,UAAMwF,IAAOrB,EAAA,GACP3B,IAAS,CAAC6E,MAAkC;AAChD,UAAI,MAAM,QAAQA,EAAG,WAAW,KAAKA,EAAG,YAAY,SAAS,KACvD,CAAC7B,EAAK,iBAAiB6B,EAAG,WAAW;AAAG,eAAO;AAErD,YAAMC,KAAoBD,EAAG,YAAY,CAAA,GACtC,IAAI7E,CAAM,EACV,OAAO,CAAC+E,MAAqBA,MAAM,IAAI;AAC1C,aAAO,EAAE,GAAGF,GAAI,UAAUC,EAAA;AAAA,IAC5B;AACA,WAAOrF,EAAM,MAAM,IAAIO,CAAM,EAAE,OAAO,CAACgF,MAAqBA,MAAM,IAAI;AAAA,EACxE,CAAC,GAMKC,IAAezH,EAAsB,MAAM;AAC/C,UAAM0H,wBAAa,IAAA;AACnB,eAAW5E,KAAQsE,EAAa,OAAO;AACrC,YAAMO,IAAW7E,EAAK,SAAS;AAC/B,MAAK4E,EAAO,IAAIC,CAAQ,KAAGD,EAAO,IAAIC,GAAU,EAAE,GAClDD,EAAO,IAAIC,CAAQ,EAAG,KAAK7E,CAAI;AAAA,IACjC;AACA,UAAMJ,IAAsB,CAAA;AAC5B,eAAW,CAACkF,GAAOC,CAAI,KAAKH;AAC1B,MAAAG,EAAK,KAAK,CAACC,GAAGC,MAAM;AAClB,cAAMC,KAAaF,EAAE,SAAS,MAAMC,EAAE,SAAS;AAC/C,eAAIC,MAAc,IAAUA,IACrBF,EAAE,MAAM,cAAcC,EAAE,KAAK;AAAA,MACtC,CAAC,GACDrF,EAAO,KAAK,EAAE,OAAAkF,GAAO,OAAOC,GAAM;AAEpC,WAAOnF;AAAA,EACT,CAAC;AAGD,iBAAeH,EAAK0F,IAAQ,IAA4B;AACtD,QAAId,EAAS,SAAS,CAACc,UAAchG,EAAM;AAC3C,IAAAE,EAAQ,QAAQ,IAChB+E,EAAM,QAAQ;AACd,QAAI;AAEF,YAAMgB,IAAW,MADF3I,EAAA,EACe,IAAkB,cAAc;AAC9D,aAAA0C,EAAM,QAAQ,MAAM,QAAQiG,EAAS,KAAK,IAAIA,EAAS,QAAQ,CAAA,GAC/Df,EAAS,QAAQ,IACVlF,EAAM;AAAA,IACf,SAASzB,GAAK;AACZ,YAAA0G,EAAM,QAAQ1G,aAAe,QAAQA,IAAM,IAAI,MAAM,OAAOA,CAAG,CAAC,GAC1DA;AAAA,IACR,UAAA;AACE,MAAA2B,EAAQ,QAAQ;AAAA,IAClB;AAAA,EACF;AAGA,WAASgG,EAASvH,GAAwB;AACxC,IAAAqB,EAAM,QAAQrB,GACduG,EAAS,QAAQ,IACjBD,EAAM,QAAQ;AAAA,EAChB;AAEA,WAASkB,IAAc;AACrB,IAAAnG,EAAM,QAAQ,CAAA,GACdkF,EAAS,QAAQ,IACjBD,EAAM,QAAQ,MACd/E,EAAQ,QAAQ;AAAA,EAClB;AAEA,SAAO;AAAA,IACL,OAAAF;AAAA,IACA,SAAAE;AAAA,IACA,OAAA+E;AAAA,IACA,UAAAC;AAAA,IACA,cAAAC;AAAA,IACA,cAAAK;AAAA,IACA,MAAAlF;AAAA,IACA,UAAA4F;AAAA,IACA,OAAAC;AAAA,EAAA;AAEJ,CAAC;;;;;;;;;;;;;;;;;;;;ACpGD,UAAMC,IAAOpB,GAAA,GACPqB,IAAQC,GAAA,GAERb,IAAS1H,EAAS,MAAMqI,EAAK,YAAY;AAE/C,aAASG,EAAS1F,GAAyB;AAEzC,aADI,GAAAA,EAAK,aAAawF,EAAM,SAASxF,EAAK,aACtCA,EAAK,OAAOwF,EAAM,SAASxF,EAAK;AAAA,IAEtC;AAQA,aAAS2F,EAASC,GAA6C;AAC7D,UAAKA;AAGL,eAAO,MAAMC,GAAE,QAAQ,EAAE,OAAO,uBAAuB,aAAaD,GAAM;AAAA,IAC5E;AAGA,aAASE,EAAW9F,GAA8D;AAChF,UAAIA,EAAK,UAAW,QAAO,EAAE,MAAMA,EAAK,UAAA;AACxC,UAAIA,EAAK,IAAK,QAAOA,EAAK;AAAA,IAE5B;2BAIEzB,EAyCaC,EAAAuH,EAAA,GAAA,EAzCA,WAAW5C,EAAA,UAAA,GAAS6C,GAAA;AAAA,MACpB,UACT,MAGM;AAAA,QAHNhI,EAGM,OAHNU,IAGM;AAAA,UAFJV,EAA4D,OAA5DuF,IAA4D5E,EAAlBwE,EAAA,SAAS,GAAA,CAAA;AAAA,UACvCA,EAAA,8BAAZpF,EAA8E,OAA9E6F,IAA8EjF,EAAlBwE,EAAA,SAAS,GAAA,CAAA;AAAA;QAE5DA,EAAA,WAAWA,EAAA,aAAtBvE,KAAAb,EAGM,OAHNkI,IAGM;AAAA,UAFJjI,EAA+B,QAAA,MAAAW,EAAtBwE,EAAA,OAAO,KAAK,GAAA,CAAA;AAAA,UACrBnF,EAAwB,KAAA,MAAAW,EAAlBwE,EAAA,OAAO,IAAI,GAAA,CAAA;AAAA,QAAA;;MAIV,OAEP,MAA4B;AAAA,SAD9BvE,EAAA,EAAA,GAAAb,EAiBkBc,GAAA,MAAAC,EAhBK8F,EAAA,OAAM,CAAnBsB,GAAKvC,YADfpF,EAiBkBC,EAAA2H,EAAA,GAAA;AAAA,UAff,YAAYxC,CAAG;AAAA,UACf,OAAOuC,EAAI,SAAS;AAAA,QAAA;qBAGnB,MAAyB;AAAA,aAD3BtH,EAAA,EAAA,GAAAb,EAWiBc,GAAA,MAAAC,EAVAoH,EAAI,QAAZlG,YADTzB,EAWiBC,EAAA4H,EAAA,GAAA;AAAA,cATd,KAAKpG,EAAK;AAAA,cACV,IAAI8F,EAAW9F,CAAI;AAAA,cACnB,QAAQ0F,EAAS1F,CAAI;AAAA,cACrB,OAAOA,EAAK,SAAS;AAAA,YAAA;yBAIX,MACX;AAAA,kBADW,MACXrB,EAAGqB,EAAK,KAAK,GAAA,CAAA;AAAA,cAAA;;;cAHGA,EAAK;sBAAO;AAAA,sBAC1B,MAAuC;AAAA,mBAAvCpB,EAAA,GAAAL,EAAuCsF,GAAvB8B,EAAS3F,EAAK,IAAI,CAAA,CAAA;AAAA,gBAAA;;;;;;;;;;MAO1BmD,EAAA,WAAWA,EAAA;cAAU;AAAA,cACnC,MAKM;AAAA,UALNnF,EAKM,OALNqI,IAKM;AAAA,YAJQlD,EAAA,gBAAZpF,EAA0E,QAA1EuI,IAA0E3H,EAAjBwE,EAAA,OAAO,GAAA,CAAA;YACvDA,EAAA,gBAATpF,EAEI,KAAA;AAAA;cAFe,MAAMoF,EAAA;AAAA,cAAS,OAAM;AAAA,YAAA,GAAoD,UAE5F,GAAAoD,EAAA;;;;;;;;;;;GC1DFC,KAAY;;;;;;;;AAnBlB,UAAMtD,IAAQC,GAKRC,IAAOC;AAKb,aAASoD,EAAiBC,GAAsB;AAC9C,MAAAtD,EAAK,oBAAoBsD,CAAK;AAAA,IAChC;AAEA,aAASC,IAA0B;AACjC,MAAAvD,EAAK,oBAAoB;AAAA,IAC3B;AAKA,WAAAwD;AAAA,MACE,MAAM1D,EAAM;AAAA,MACZ,CAAC2D,MAAQ;AACP,QAAI,OAAO,WAAa,QACpBA,MAAQ,OAAM,SAAS,gBAAgB,aAAaL,IAAW,MAAM,IACpE,SAAS,gBAAgB,gBAAgBA,EAAS;AAAA,MACzD;AAAA,MACA,EAAE,WAAW,GAAA;AAAA,IAAK,GAGpBM,GAAgB,MAAM;AACpB,MAAI,OAAO,WAAa,OACtB,SAAS,gBAAgB,gBAAgBN,EAAS;AAAA,IAEtD,CAAC,cAIC5H,EAAA,GAAAb,EA6BM,OA7BNW,IA6BM;AAAA,MA5BOyE,EAAA,iBAAXvE,EAAA,GAAAb,EAWM,OAXNwF,IAWM;AAAA,QAVJvF,EAEO,QAAA,MAAA;AAAA,4BAFD,kBACS,EAAA;AAAA,UAAAA,EAAiC,KAAA,MAAAW,EAA3BwE,EAAA,cAAc,MAAM,GAAA,CAAA;AAAA,4BAAO,0BAChD,EAAA;AAAA,QAAA;QACAnF,EAMS,UAAA;AAAA,UALP,MAAK;AAAA,UACL,OAAM;AAAA,UACL,SAAO2I;AAAA,QAAA,GACT,mBAED;AAAA,MAAA;MAEF7D,EAemBtE,EAAAuI,EAAA,GAAA;AAAA,QAdhB,eAAa5D,EAAA;AAAA,QACb,uBAAoBsD;AAAA,MAAA;QAEV,WACT,MAEO;AAAA,UAFPjD,EAEOC,yBAFP,MAEO;AAAA,YADLX,EAAuCkE,IAAA,EAAxB,WAAW7D,EAAA,UAAA,GAAS,MAAA,GAAA,CAAA,WAAA,CAAA;AAAA,UAAA;;QAG5B,UACT,MAEO;AAAA,UAFPK,EAEOC,wBAFP,MAEO;AAAA,YADLX,EAA8DmE,IAAA;AAAA,cAAhD,iBAAcjE,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA,CAAAhE,MAAEyH,EAAgB,CAAEtD,EAAA,SAAS;AAAA,YAAA;;;mBAG7D,MAAQ;AAAA,UAARK,EAAQC,EAAA,QAAA,SAAA;AAAA,QAAA;;;;;;;;ACpFd,UAAM+B,IAAQC,GAAA,GAERyB,IAAWhK,EAAkB,MAC7B,EAAAsI,EAAM,MAAM,eAAe,MAE3BA,EAAM,MAAM,SAAS,UAErBA,EAAM,SAAS,iBAEpB;;;aAImB0B,EAAA,cAAlB3I,EAEa4I,IAAA,EAAA,KAAA,KAAA;AAAA,mBADX,MAAe;AAAA,UAAfrE,EAAesE,CAAA;AAAA,QAAA;;kBAEjB7I,EAAsB6I,GAAA,EAAA,KAAA,EAAA,CAAA;AAAA;;ICmCXC,KAAmBxK,EAAY,kBAAkB,MAAM;AAClE,QAAMyK,IAAWvK,EAA0B,IAAI,GACzCsC,IAAUtC,EAAI,EAAK,GACnBqH,IAAQrH,EAAkB,IAAI,GAE9BsH,IAAWnH,EAAS,MAAMoK,EAAS,UAAU,IAAI,GACjDC,IAAUrK,EAAS,MAAMoK,EAAS,OAAO,WAAW,IAAI,GACxDE,IAAYtK,EAAS,MAAMoK,EAAS,OAAO,aAAa,EAAE,GAC1DG,IAAUvK,EAAS,MAAMoK,EAAS,OAAO,WAAW,EAAE,GACtDI,IAAWxK,EAAS,MAAMoK,EAAS,OAAO,YAAY,EAAE,GACxDK,IAAUzK,EAAS,MAAMoK,EAAS,OAAO,WAAW,EAAE;AAE5D,WAASM,EAAYC,GAA2C;AAC9D,WAAOL,EAAU,MAAM,KAAK,CAACM,MAAMA,EAAE,SAASD,CAAI,KAAK;AAAA,EACzD;AAEA,WAASE,EAAUF,GAAyC;AAC1D,WAAOJ,EAAQ,MAAM,KAAK,CAACO,MAAMA,EAAE,SAASH,CAAI,KAAK;AAAA,EACvD;AAEA,WAASI,EAAYJ,GAA2C;AAC9D,WAAOH,EAAS,MAAM,KAAK,CAACM,MAAMA,EAAE,SAASH,CAAI,KAAK;AAAA,EACxD;AAMA,iBAAepI,EAAK0F,IAAQ,IAA+B;AACzD,QAAImC,EAAS,UAAU,QAAQ,CAACnC;AAC9B,aAAOmC,EAAS;AAGlB,IAAAjI,EAAQ,QAAQ,IAChB+E,EAAM,QAAQ;AACd,QAAI;AAEF,YAAMxE,IAAS,MADAnD,EAAA,EACa,IAAmB,kBAAkB;AACjE,aAAA6K,EAAS,QAAQ1H,GACVA;AAAA,IACT,SAASlC,GAAK;AACZ,YAAA0G,EAAM,QAAQ1G,aAAe,QAAQA,IAAM,IAAI,MAAM,OAAOA,CAAG,CAAC,GAC1DA;AAAA,IACR,UAAA;AACE,MAAA2B,EAAQ,QAAQ;AAAA,IAClB;AAAA,EACF;AAEA,WAASiG,IAAc;AACrB,IAAAgC,EAAS,QAAQ,MACjBlD,EAAM,QAAQ,MACd/E,EAAQ,QAAQ;AAAA,EAClB;AAEA,SAAO;AAAA;AAAA,IAEL,UAAAiI;AAAA,IACA,SAAAjI;AAAA,IACA,OAAA+E;AAAA;AAAA,IAEA,UAAAC;AAAA,IACA,SAAAkD;AAAA,IACA,WAAAC;AAAA,IACA,SAAAC;AAAA,IACA,UAAAC;AAAA,IACA,SAAAC;AAAA;AAAA,IAEA,aAAAC;AAAA,IACA,WAAAG;AAAA,IACA,aAAAE;AAAA,IACA,MAAAxI;AAAA,IACA,OAAA6F;AAAA,EAAA;AAEJ,CAAC;;;;;;AC5HD,UAAMgC,IAAWD,GAAA,GACX3E,IAAOrB,EAAA,GACPsB,IAASC,GAAA,GAETsF,IAAWhL,EAAS,MAAMwF,EAAK,MAAM,QAAQ,EAAE,GAC/C8E,IAAYtK,EAAS,MAAMoK,EAAS,UAAU,aAAa,EAAE;sBAIjE1I,EAAA,GAAAb,EAuBM,OAvBNW,IAuBM;AAAA,MAtBJoE,EAKUtE,EAAA2J,CAAA,GAAA;AAAA,QALD,SAAQ;AAAA,QAAK,OAAM;AAAA,MAAA;mBAC1B,MAAwF;AAAA,UAAxFnK,EAAwF,MAAxFuF,IAA8B,qBAAgB5E,EAAGuJ,EAAA,eAAkBA,EAAA,QAAQ,EAAA,GAAA,CAAA;AAAA,UAC3ElF,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAAhF,EAEI,KAAA,EAFD,OAAM,sBAAmB,mFAE5B,EAAA;AAAA,QAAA;;;MAGawJ,EAAA,MAAU,UAAzB5I,KAAAb,EAcU,WAdV6F,IAcU;AAAA,QAbRZ,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAAhF,EAA4C,MAAA,EAAxC,OAAM,sBAAA,GAAsB,WAAO,EAAA;AAAA,QACvCA,EAWK,MAXLiI,IAWK;AAAA,kBAVHlI,EASKc,GAAA,MAAAC,EATW0I,EAAA,OAAS,CAAdM,YAAX/J,EASK,MAAA;AAAA,YATuB,KAAK+J,EAAE;AAAA,UAAA;YACjC9J,EAOS,UAAA;AAAA,cANP,MAAK;AAAA,cACL,OAAM;AAAA,cACL,gBAAOQ,EAAAmE,CAAA,EAAO,KAAI,EAAA,MAAA,kBAA2BmF,EAAE,IAAI,UAAA;AAAA,YAAA;cAEpD9J,EAAyD,QAAzDsI,IAAyD3H,EAAjBmJ,EAAE,KAAK,GAAA,CAAA;AAAA,cAC/C9J,EAAuD,QAAvDuI,IAAuD5H,EAAhBmJ,EAAE,IAAI,GAAA,CAAA;AAAA,YAAA;;;;;;;;;AClCzD,UAAMnF,IAASC,GAAA;sBAIbhE,EAAA,GAAAb,EAQM,OARNW,IAQM;AAAA,MAPJoE,EAMUtE,EAAA2J,CAAA,GAAA;AAAA,QAND,SAAQ;AAAA,QAAK,OAAM;AAAA,MAAA;mBAC1B,MAA4C;AAAA,UAA5CnF,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAAhF,EAA4C,MAAA,EAAxC,OAAM,0BAAA,GAA0B,OAAG,EAAA;AAAA,UACvCgF,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAAhF,EAA0D,KAAA,EAAvD,OAAM,6BAAA,GAA6B,oBAAgB,EAAA;AAAA,UACtD8E,EAEYtE,EAAA4J,CAAA,GAAA;AAAA,YAFD,SAAQ;AAAA,YAAS,SAAKpF,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA,CAAAhE,MAAER,EAAAmE,CAAA,EAAO,QAAO,EAAA,MAAA,cAAA;AAAA,UAAA;uBAA0B,MAE3E,CAAA,GAAAK,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,gBAF2E,gBAE3E,EAAA;AAAA,YAAA;;;;;;;;;;;ACVN,UAAML,IAASC,GAAA;sBAIbhE,EAAA,GAAAb,EAQM,OARNW,IAQM;AAAA,MAPJoE,EAMUtE,EAAA2J,CAAA,GAAA;AAAA,QAND,SAAQ;AAAA,QAAK,OAAM;AAAA,MAAA;mBAC1B,MAA4C;AAAA,UAA5CnF,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAAhF,EAA4C,MAAA,EAAxC,OAAM,0BAAA,GAA0B,OAAG,EAAA;AAAA,UACvCgF,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAAhF,EAA8D,KAAA,EAA3D,OAAM,6BAAA,GAA6B,wBAAoB,EAAA;AAAA,UAC1D8E,EAEYtE,EAAA4J,CAAA,GAAA;AAAA,YAFD,SAAQ;AAAA,YAAS,SAAKpF,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA,CAAAhE,MAAER,EAAAmE,CAAA,EAAO,QAAO,EAAA,MAAA,cAAA;AAAA,UAAA;uBAA0B,MAE3E,CAAA,GAAAK,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,gBAF2E,gBAE3E,EAAA;AAAA,YAAA;;;;;;;;;;;;;;;;;ACHN,UAAMwC,IAAQC,GAAA,GACR6B,IAAWD,GAAA,GAEXQ,IAAO3K,EAAS,MAAM,OAAOsI,EAAM,OAAO,QAAQ,EAAE,CAAC,GACrDjG,IAAOrC,EAAS,MAAMoK,EAAS,UAAU,UAAU,KAAK,CAACU,MAAMA,EAAE,SAASH,EAAK,KAAK,KAAK,IAAI;sBAIjGjJ,EAAA,GAAAb,EAQM,OARNW,IAQM;AAAA,MAPJoE,EAMUtE,EAAA2J,CAAA,GAAA,EAND,SAAQ,QAAI;AAAA,mBACnB,MAAqE;AAAA,UAArEnK,EAAqE,MAArEuF,IAAqE5E,EAA3BY,SAAM,SAASsI,EAAA,KAAI,GAAA,CAAA;AAAA,UACnDtI,EAAA,cAGVxB,EAA+F,OAA/FkI,IAA+FtH,EAA7C,KAAK,UAAUY,EAAA,MAAK,QAAM,MAAA,CAAA,CAAA,GAAA,CAAA,MAH5EX,EAAA,GAAAb,EAEI,KAFJ6F,IAAkD,gBACtCjF,EAAGkJ,EAAA,KAAI,IAAG,+BACtB,CAAA;AAAA,QAC4E;;;;;;;;AClBlF,UAAMrC,IAAQC,GAAA,GACRoC,IAAO3K,EAAS,MAAM,OAAOsI,EAAM,OAAO,QAAQ,EAAE,CAAC,GACrD6C,IAAQnL,EAAS,MAAM,OAAOsI,EAAM,MAAM,SAASqC,EAAK,KAAK,CAAC;sBAIlEjJ,EAAA,GAAAb,EAQM,OARNW,IAQM;AAAA,MAPJoE,EAMUtE,EAAA2J,CAAA,GAAA;AAAA,QAND,SAAQ;AAAA,QAAK,OAAM;AAAA,MAAA;mBAC1B,MAAqD;AAAA,UAArDnK,EAAqD,MAArDuF,IAAqD5E,EAAb0J,EAAA,KAAK,GAAA,CAAA;AAAA,UAC7CrK,EAGI,KAHJ4F,IAGI;AAAA,cAH+B,+BACRjF,EAAGkJ,EAAA,KAAI,IAAG,sCACnC,CAAA;AAAA,YAAA7E,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAAhF,EAA4F,cAAtF,oBAAeW,EAAG,GAAG,IAAG,aAAQA,EAAG,GAAG,IAAG,yBAAqB,GAAG,IAAG,MAACA,EAAG,GAAG,IAAG,KAAC,EAAA;AAAA,8BAAO,MAC9F,EAAA;AAAA,UAAA;;;;;;;;;;;;;;;;;;ACGN,UAAMyE,IAAOC,GAIPX,IAAOrB,EAAA,GAEPiH,IAAQvL,EAAI,EAAE,GACdwL,IAAWxL,EAAI,EAAE,GACjByL,IAAWzL,EAAI,EAAK,GAEpB0L,IAAa1L,EAAI,EAAK,GACtB2L,IAAe3L,EAAmB,IAAI,GACtC4L,IAAc5L,EAA8B,EAAE,GAE9C6L,IAAa1L,EAA6B,MAAMyL,EAAY,MAAM,QAAQ,CAAC,CAAC,GAC5EE,IAAgB3L,EAA6B,MAAMyL,EAAY,MAAM,WAAW,CAAC,CAAC;AAExF,mBAAeG,IAAwB;AACrC,UAAI,CAAAL,EAAW,OACf;AAAA,QAAAA,EAAW,QAAQ,IACnBC,EAAa,QAAQ,MACrBC,EAAY,QAAQ,CAAA;AAEpB,YAAI;AACF,gBAAM/I,IAAS,MAAM8C,EAAK,MAAM;AAAA,YAC9B,OAAO4F,EAAM;AAAA,YACb,UAAUC,EAAS;AAAA,YACnB,UAAUC,EAAS;AAAA,UAAA,CACpB;AACD,UAAApF,EAAK,WAAWxD,CAAM;AAAA,QACxB,SAASlC,GAAK;AACZ,UAAIA,aAAesD,MACjB2H,EAAY,QAAQjL,EAAI,QACxBgL,EAAa,QAAQhL,EAAI,kBAAA,KAChBA,aAAewD,KACxBwH,EAAa,QAAQ,8BACZhL,aAAegD,IACxBgI,EAAa,QAAQhL,EAAI,WAAW,qBAEpCgL,EAAa,QAAShL,EAAc;AAAA,QAExC,UAAA;AACE,UAAA+K,EAAW,QAAQ;AAAA,QACrB;AAAA;AAAA,IACF;2BAIE1K,EA2DO,QAAA;AAAA,MA3DD,OAAM;AAAA,MAAsB,YAAA;AAAA,MAAY,aAAgB+K,GAAM,CAAA,SAAA,CAAA;AAAA,IAAA;MAE1DJ,EAAA,cADRnK,EAOWC,EAAAuK,CAAA,GAAA;AAAA;QALT,SAAQ;AAAA,QACR,OAAM;AAAA,QACN,MAAK;AAAA,MAAA;mBAEL,MAAkB;AAAA,cAAfL,EAAA,KAAY,GAAA,CAAA;AAAA,QAAA;;;MAGjB5F,EAUEtE,EAAAwK,EAAA,GAAA;AAAA,oBATSV,EAAA;AAAA,sDAAAA,EAAK,QAAAtJ;AAAA,QACd,MAAK;AAAA,QACL,OAAM;AAAA,QACN,aAAY;AAAA,QACZ,cAAa;AAAA,QACZ,UAAU;AAAA,QACV,UAAUyJ,EAAA;AAAA,QACV,OAAOG,EAAA;AAAA,QACR,MAAK;AAAA,MAAA;MAGP9F,EASEtE,EAAAwK,EAAA,GAAA;AAAA,oBARST,EAAA;AAAA,sDAAAA,EAAQ,QAAAvJ;AAAA,QACjB,MAAK;AAAA,QACL,OAAM;AAAA,QACN,cAAa;AAAA,QACZ,UAAU;AAAA,QACV,UAAUyJ,EAAA;AAAA,QACV,OAAOI,EAAA;AAAA,QACR,MAAK;AAAA,MAAA;MAGP7K,EAOM,OAPNU,IAOM;AAAA,QANJoE,EAEctE,EAAAyK,EAAA,GAAA;AAAA,sBAFQT,EAAA;AAAA,wDAAAA,EAAQ,QAAAxJ;AAAA,UAAG,UAAUyJ,EAAA;AAAA,QAAA;qBAAY,MAEvD,CAAA,GAAAzF,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,cAFuD,oBAEvD,EAAA;AAAA,UAAA;;;QACSG,EAAA,kBAATpF,EAEI,KAAA;AAAA;UAFiB,MAAMoF,EAAA;AAAA,UAAW,OAAM;AAAA,QAAA,GAAwB,oBAEpE,GAAAI,EAAA;;MAGFT,EAQYtE,EAAA4J,CAAA,GAAA;AAAA,QAPV,MAAK;AAAA,QACL,SAAQ;AAAA,QACR,MAAK;AAAA,QACJ,SAASK,EAAA;AAAA,QACT,UAAUA,EAAA;AAAA,MAAA;mBAEX,MAAoC;AAAA,cAAjCA,EAAA,QAAU,UAAA,OAAA,GAAA,CAAA;AAAA,QAAA;;;MAIPtF,EAAA,gBAAgBA,EAAA,UADxBvE,KAAAb,EAMM,OANN6F,IAMM;AAAA,0BAHL,uBAEC,EAAA;AAAA,QAAA5F,EAAsE,KAAA;AAAA,UAAlE,MAAMmF,EAAA;AAAA,UAAQ,OAAM;AAAA,QAAA,KAA2BA,EAAA,YAAY,GAAA,GAAA8C,EAAA;AAAA,MAAA;;;;;;;ACrHrE,UAAM7C,IAAOC,GAKPX,IAAOrB,EAAA,GAEP6H,IAAOnM,EAAyB,MAAM,GACtCoM,IAAQpM,EAAc,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC,GAC9CwF,IAAexF,EAAI,EAAE,GACrBqM,IAAWrM,EAAwB,EAAE,GAErC0L,IAAa1L,EAAI,EAAK,GACtB2L,IAAe3L,EAAmB,IAAI,GACtCsM,IAAYtM,EAAmB,IAAI,GAEnCuM,IAAWpM,EAAS,MAAMiM,EAAM,MAAM,KAAK,EAAE,CAAC,GAC9CI,IAAUrM,EAAS,MACnBgM,EAAK,UAAU,SAAeI,EAAS,MAAM,WAAW,IACrD/G,EAAa,MAAM,KAAA,EAAO,SAAS,CAC3C;AAED,aAASiH,EAAW7F,GAAa8F,GAA0B;AACzD,MAAIA,aAAc,qBAAkBL,EAAS,MAAMzF,CAAG,IAAI8F;AAAA,IAC5D;AAEA,aAASC,EAAY/F,GAAagG,GAAoB;AACpD,YAAMC,IAASD,EAAM,QAEfE,IAAQD,EAAO,MAAM,QAAQ,OAAO,EAAE,EAAE,MAAM,EAAE;AACtD,MAAAT,EAAM,MAAMxF,CAAG,IAAIkG,GACnBD,EAAO,QAAQC,GACXA,KAASlG,IAAMwF,EAAM,MAAM,SAAS,KACjCW,GAAS,MAAMV,EAAS,MAAMzF,IAAM,CAAC,GAAG,OAAO,GAElD2F,EAAS,MAAM,WAAWH,EAAM,MAAM,UACnCL,EAAA;AAAA,IAET;AAEA,aAASiB,EAAcpG,GAAagG,GAA4B;AAC9D,MAAIA,EAAM,QAAQ,eAAe,CAACR,EAAM,MAAMxF,CAAG,KAAKA,IAAM,IACrDmG,GAAS,MAAMV,EAAS,MAAMzF,IAAM,CAAC,GAAG,OAAO,IAC3CgG,EAAM,QAAQ,eAAehG,IAAM,KAC5CyF,EAAS,MAAMzF,IAAM,CAAC,GAAG,MAAA,GACzBgG,EAAM,eAAA,KACGA,EAAM,QAAQ,gBAAgBhG,IAAMwF,EAAM,MAAM,SAAS,MAClEC,EAAS,MAAMzF,IAAM,CAAC,GAAG,MAAA,GACzBgG,EAAM,eAAA;AAAA,IAEV;AAEA,aAASK,EAAQL,GAA6B;AAE5C,YAAMM,KADSN,EAAM,eAAe,QAAQ,MAAM,KAAK,IACjC,QAAQ,OAAO,EAAE,EAAE,MAAM,GAAGR,EAAM,MAAM,MAAM;AACpE,UAAIc,EAAO,WAAW,GACtB;AAAA,QAAAN,EAAM,eAAA;AACN,iBAASjF,IAAI,GAAGA,IAAIyE,EAAM,MAAM,QAAQzE;AACtC,UAAAyE,EAAM,MAAMzE,CAAC,IAAIuF,EAAOvF,CAAC,KAAK;AAEhC,QAAKoF,GAAS,MAAM;AAClB,UAAAV,EAAS,MAAM,KAAK,IAAIa,EAAO,QAAQd,EAAM,MAAM,SAAS,CAAC,CAAC,GAAG,MAAA,GAC7Dc,EAAO,WAAWd,EAAM,MAAM,UAAaL,EAAA;AAAA,QACjD,CAAC;AAAA;AAAA,IACH;AAEA,mBAAeA,IAAwB;AACrC,UAAI,EAAAL,EAAW,SAAS,CAACc,EAAQ,QACjC;AAAA,QAAAd,EAAW,QAAQ,IACnBC,EAAa,QAAQ;AAErB,YAAI;AACF,cAAIQ,EAAK,UAAU;AACjB,kBAAMxG,EAAK,mBAAmB4G,EAAS,KAAK;AAAA,eACvC;AACL,kBAAMY,IAAM,MAAMxH,EAAK,kBAAkBH,EAAa,MAAM,MAAM;AAClE,YAAA8G,EAAU,QAAQa,EAAI;AAAA,UACxB;AACA,UAAA9G,EAAK,SAAS;AAAA,QAChB,SAAS1F,GAAK;AACZ,UAAIA,aAAesD,KACjB0H,EAAa,QAAQhL,EAAI,kBAAA,KAAuB,iBACvCA,aAAewD,KACxBwH,EAAa,QAAQ,8BACZhL,aAAegD,IACxBgI,EAAa,QAAQhL,EAAI,WAAW,6BAEpCgL,EAAa,QAAShL,EAAc;AAAA,QAExC,UAAA;AACE,UAAA+K,EAAW,QAAQ;AAAA,QACrB;AAAA;AAAA,IACF;AAEA,aAAS0B,IAAe;AACtB,MAAAzH,EAAK,gBAAA,GACLU,EAAK,QAAQ;AAAA,IACf;AAEA,aAASgH,IAAmB;AAC1B,MAAAlB,EAAK,QAAQA,EAAK,UAAU,SAAS,aAAa,QAClDR,EAAa,QAAQ;AAAA,IACvB;2BAIE3K,EAgEO,QAAA;AAAA,MAhED,OAAM;AAAA,MAAsB,YAAA;AAAA,MAAY,aAAgB+K,GAAM,CAAA,SAAA,CAAA;AAAA,IAAA;MAE1DJ,EAAA,cADRnK,EAOWC,EAAAuK,CAAA,GAAA;AAAA;QALT,SAAQ;AAAA,QACR,OAAM;AAAA,QACN,MAAK;AAAA,MAAA;mBAEL,MAAkB;AAAA,cAAfL,EAAA,KAAY,GAAA,CAAA;AAAA,QAAA;;;MAGTW,EAAA,UAAS,aADjB9K,EAOWC,EAAAuK,CAAA,GAAA;AAAA;QALT,SAAQ;AAAA,QACR,OAAM;AAAA,QACN,MAAK;AAAA,MAAA;mBACN,MACqC;AAAA,UADrC9J,EAAA,4CACwCoK,EAAA,KAAS,GAAA,CAAA;AAAA,QAAA;;;MAGvCH,EAAA,UAAI,eAAfnL,EAeM,OAAA;AAAA;QAfsB,OAAM;AAAA,QAAoB,SAAAiM;AAAA,MAAA;SACpDpL,EAAA,EAAA,GAAAb,EAaEc,GAAA,MAAAC,EAZmBqK,EAAA,OAAK,CAAhBkB,GAAG1G,YADb5F,EAaE,SAAA;AAAA,UAXC,KAAK4F;AAAA;UACL,MAAM8F,MAAOD,EAAW7F,GAAK8F,CAAE;AAAA,UAC/B,OAAON,EAAA,MAAMxF,CAAG;AAAA,UACjB,MAAK;AAAA,UACL,WAAU;AAAA,UACV,cAAa;AAAA,UACb,WAAU;AAAA,UACT,UAAU8E,EAAA;AAAA,UACV,uBAAqB9E,IAAG,CAAA;AAAA,UACxB,SAAK,CAAA3E,MAAE0K,EAAY/F,GAAK3E,CAAM;AAAA,UAC9B,WAAO,CAAAA,MAAE+K,EAAcpG,GAAK3E,CAAM;AAAA,QAAA;sBAIvCT,EAQEC,EAAAwK,EAAA,GAAA;AAAA;oBANSzG,EAAA;AAAA,sDAAAA,EAAY,QAAAvD;AAAA,QACrB,MAAK;AAAA,QACL,OAAM;AAAA,QACN,cAAa;AAAA,QACZ,UAAUyJ,EAAA;AAAA,QACX,MAAK;AAAA,MAAA;MAGP3F,EAQYtE,EAAA4J,CAAA,GAAA;AAAA,QAPV,MAAK;AAAA,QACL,SAAQ;AAAA,QACR,MAAK;AAAA,QACJ,SAASK,EAAA;AAAA,QACT,UAAUA,EAAA,SAAU,CAAKc,EAAA;AAAA,MAAA;mBAE1B,MAA8C;AAAA,cAA3Cd,EAAA,QAAU,cAAA,aAAA,GAAA,CAAA;AAAA,QAAA;;;MAGfzK,EAQM,OARNuF,IAQM;AAAA,QAPJvF,EAGS,UAAA;AAAA,UAHD,MAAK;AAAA,UAAS,OAAM;AAAA,UAAyB,SAAOoM;AAAA,QAAA;UAC1ClB,EAAA,UAAI,eAApBnL,EAAqEc,GAAA,EAAA,KAAA,KAAA;AAAA,cAApC,2BAAyB;AAAA,UAAA,gBAC1Dd,EAA0Dc,GAAA,EAAA,KAAA,KAAA;AAAA,cAAzC,gCAA8B;AAAA,UAAA;;QAEjDb,EAES,UAAA;AAAA,UAFD,MAAK;AAAA,UAAS,OAAM;AAAA,UAAyB,SAAOmM;AAAA,QAAA,GAAQ,UAEpE;AAAA,MAAA;;;;;;;;;;;;;;;;;;;;;;;ACjJN,UAAMjH,IAAQC,GAYRT,IAAOrB,EAAA,GACPsB,IAASC,GAAA,GACT4C,IAAQC,GAAA;AAEd,mBAAe6E,IAAgC;AAC7C,YAAMV,IAASpE,EAAM,MAAMtC,EAAM,gBAAgB;AACjD,UAAI,OAAO0G,KAAW,YAAYA,EAAO,SAAS,KAAKA,EAAO,WAAW,GAAG,GAAG;AAC7E,cAAMjH,EAAO,KAAKiH,CAAM;AACxB;AAAA,MACF;AACA,YAAMjH,EAAO,KAAK,EAAE,MAAMO,EAAM,eAAe;AAAA,IACjD;AAEA,WAAA0D;AAAA,MACE,MAAMlE,EAAK;AAAA,MACX,CAAC5E,MAAS;AACR,QAAIA,KAAWwM,EAAA;AAAA,MACjB;AAAA,IAAA,GAEFC,GAAU,MAAM;AACd,MAAI7H,EAAK,mBAAsB4H,EAAA;AAAA,IACjC,CAAC,cAIC1L,EAAA,GAAAb,EA2CM,OA3CNW,IA2CM;AAAA,MA1COyE,EAAA,qBAAXvE,EAAA,GAAAb,EAGM,OAHNwF,IAGM;AAAA,QAFJT,EAAekB,EAAA;AAAA,QACflB,EAAkBmB,EAAA;AAAA,MAAA;MAGpBnB,EAoCUtE,EAAA2J,CAAA,GAAA;AAAA,QAnCP,OAAKrE,EAAA,CAAA,mBAAsBtF,EAAAkE,CAAA,EAAK,qBAAkB,0BAAA,EAAA,CAAA;AAAA,QACnD,SAAQ;AAAA,MAAA;mBAER,MAkBM;AAAA,UAlBN1E,EAkBM,OAlBN4F,IAkBM;AAAA,YAjBJ5F,EAMM,OAAA;AAAA,cALH,OAAK8F,EAAA,CAAA,yBAA4BtF,EAAAkE,CAAA,EAAK,qBAAkB,kCAAA,EAAA,CAAA;AAAA,YAAA;cAE9CS,EAAA,aAAS,CAAK3E,EAAAkE,CAAA,EAAK,2BAA9B3E,EAAsF,OAAA;AAAA;gBAAnC,KAAKoF,EAAA;AAAA,gBAAY,KAAKA,EAAA;AAAA,cAAA,mBACxD3E,EAAAkE,CAAA,EAAK,2BAAtB3E,EAAsE,QAAtEsI,IAA6D,IAAE,MAC/DzH,KAAAb,EAAmC,cAAnBoF,EAAA,SAAS,GAAA,CAAA;AAAA,YAAA;YAE3BnF,EAGM,OAHNuI,IAGM;AAAA,cAFY/H,EAAAkE,CAAA,EAAK,2BAArB3E,EAA0Ec,GAAA,EAAA,KAAA,KAAA;AAAA,kBAAjC,wBAAsB;AAAA,cAAA,gBAC/Dd,EAA2Cc,GAAA,EAAA,KAAA,KAAA;AAAA,oBAAvBsE,EAAA,SAAS,GAAA,CAAA;AAAA,cAAA;;YAE/BnF,EAKM,OALNwM,IAKM;AAAA,cAJYhM,EAAAkE,CAAA,EAAK,2BAArB3E,EAEWc,GAAA,EAAA,KAAA,KAAA;AAAA,kBAF8B,uDAEzC;AAAA,cAAA,gBACAd,EAA4Dc,GAAA,EAAA,KAAA,KAAA;AAAA,kBAA3C,kCAAgC;AAAA,cAAA;;;UAK7CL,EAAAkE,CAAA,EAAK,2BADbnE,EAIEkM,IAAA;AAAA;YAFC;;YACA;;UAAc,YAEjBlM,EAMEmM,IAAA;AAAA;YAJC,cAAYvH,EAAA;AAAA,YACZ,kBAAgBA,EAAA;AAAA,YAChB,WAASA,EAAA;AAAA,YACT;;UAAe;;;;;;ICzElBwH,KAA0B,EAAE,MAAM,GAAG,UAAU,IAAI,OAAO,GAAG,WAAW,EAAA,GAEjEC,KAAwB/N,EAAY,wBAAwB,MAAM;AAE7E,QAAMgL,IAAO9K,EAAmB,IAAI,GAE9BoC,IAAQpC,EAAoC,EAAE,GAC9CwC,IAAOxC,EAAe,EAAE,GAAG4N,IAAc,GAEzCtL,IAAUtC,EAAI,EAAK,GACnBqH,IAAQrH,EAAkB,IAAI,GAE9B8N,IAAS9N,EAAY,EAAE,GACvB+N,IAAU/N,EAA6B,EAAE,GACzCgO,IAAUhO,EAAmB,IAAI,GACjCiO,IAAgBjO,EAAoB,KAAK,GAGzCkO,IAAYlO,EAA0B,oBAAI,KAAK,GAE/CmO,IAAUhO,EAAS,MAAM,CAACmC,EAAQ,SAAS+E,EAAM,UAAU,QAAQjF,EAAM,MAAM,WAAW,CAAC,GAC3FgM,IAAgBjO,EAAS,MAAM+N,EAAU,MAAM,IAAI,GACnDG,IAAelO,EAAS,MAAM+N,EAAU,MAAM,OAAO,CAAC,GACtDI,IAAWnO,EAAS,MAAMkH,EAAM,UAAU,IAAI,GAG9CkH,IAAiBpO,EAAmC,MACpD+N,EAAU,MAAM,SAAS,KACzB9L,EAAM,MAAM,WAAW,IAAU,SACjBA,EAAM,MAAM,MAAM,CAACoM,MAAQN,EAAU,MAAM,IAAIO,EAAMD,CAAG,CAAC,CAAC,IACzD,QAAQ,OAC9B;AAGD,WAASC,EAAMD,GAA+C;AAC5D,WAAQA,EAAI,MAAMA,EAAI,OAAO;AAAA,EAC/B;AAGA,WAASE,EAAQ3N,GAA2B;AAC1C,IAAI+J,EAAK,UAAU/J,MACnB+J,EAAK,QAAQ/J,GACbwH,EAAA;AAAA,EACF;AAEA,WAASA,IAAc;AACrB,IAAAnG,EAAM,QAAQ,CAAA,GACdI,EAAK,QAAQ,EAAE,GAAGoL,GAAA,GAClBtL,EAAQ,QAAQ,IAChB+E,EAAM,QAAQ,MACdyG,EAAO,QAAQ,IACfC,EAAQ,QAAQ,CAAA,GAChBC,EAAQ,QAAQ,MAChBC,EAAc,QAAQ,OACtBC,EAAU,4BAAY,IAAA;AAAA,EACxB;AAEA,WAASS,EAAYC,IAAwB,IAA6B;AACxE,UAAMC,IAAkC;AAAA,MACtC,MAAMD,EAAS,QAAQpM,EAAK,MAAM;AAAA,MAClC,UAAUoM,EAAS,YAAYpM,EAAK,MAAM;AAAA,IAAA,GAEtCsM,KAAKF,EAAS,UAAUd,EAAO;AACrC,IAAIgB,SAAW,SAASA;AAExB,UAAMC,KAAKH,EAAS,QAAQZ,EAAQ;AACpC,IAAIe,OACFF,EAAO,OAAOE,IACdF,EAAO,YAAYD,EAAS,aAAaX,EAAc;AAGzD,UAAMe,KAAIJ,EAAS,WAAWb,EAAQ;AACtC,eAAW,CAACkB,IAAGC,EAAC,KAAK,OAAO,QAAQF,EAAC;AACnC,MAAIE,MAAM,QAA2BA,OAAM,OAC3CL,EAAO,UAAUI,EAAC,GAAG,IAAI,MAAM,QAAQC,EAAC,IAAIA,GAAE,KAAK,GAAG,IAAI,OAAOA,EAAC;AAGpE,WAAOL;AAAA,EACT;AAGA,iBAAenM,EAAKkM,IAAwB,IAAmB;AAC7D,QAAI,CAAC9D,EAAK;AACR,YAAM,IAAI,MAAM,sDAAsD;AAExE,IAAAxI,EAAQ,QAAQ,IAChB+E,EAAM,QAAQ;AACd,QAAI;AACF,YAAM5H,IAASC,EAAA,GACTmP,KAASF,EAAYC,CAAQ,GAC7BzB,KAAM,MAAM1N,EAAO,IAAkB,cAAcqL,EAAK,KAAK,SAAS,EAAE,QAAA+D,GAAA,CAAQ;AACtF,MAAAzM,EAAM,QAAQ+K,GAAI,MAClB3K,EAAK,QAAQ2K,GAAI;AAAA,IACnB,SAASxM,GAAK;AACZ,YAAA0G,EAAM,QAAQ1G,aAAe,QAAQA,IAAM,IAAI,MAAM,OAAOA,CAAG,CAAC,GAC1DA;AAAA,IACR,UAAA;AACE,MAAA2B,EAAQ,QAAQ;AAAA,IAClB;AAAA,EACF;AAEA,iBAAe6M,EAAUxF,GAA8B;AACrD,IAAAmE,EAAO,QAAQnE,GACfnH,EAAK,MAAM,OAAO,GAClB,MAAME,EAAA;AAAA,EACR;AAEA,iBAAe0M,EAAUvK,GAAa8E,GAA+B;AACnE,IAAIA,KAAU,QAA+BA,MAAU,KACrD,OAAOoE,EAAQ,MAAMlJ,CAAG,IAExBkJ,EAAQ,MAAMlJ,CAAG,IAAI8E,GAEvBnH,EAAK,MAAM,OAAO,GAClB,MAAME,EAAA;AAAA,EACR;AAEA,iBAAe2M,IAA8B;AAC3C,IAAAtB,EAAQ,QAAQ,CAAA,GAChBvL,EAAK,MAAM,OAAO,GAClB,MAAME,EAAA;AAAA,EACR;AAEA,iBAAe4M,EAAQzK,GAAa0K,IAA4B,OAAsB;AACpF,IAAAvB,EAAQ,QAAQnJ,GAChBoJ,EAAc,QAAQsB,GACtB,MAAM7M,EAAA;AAAA,EACR;AAEA,iBAAe8M,EAAW3K,GAA4B;AACpD,IAAImJ,EAAQ,UAAUnJ,IACpBoJ,EAAc,QAAQA,EAAc,UAAU,QAAQ,SAAS,SAE/DD,EAAQ,QAAQnJ,GAChBoJ,EAAc,QAAQ,QAExB,MAAMvL,EAAA;AAAA,EACR;AAEA,iBAAe+M,EAAQ7M,GAA6B;AAClD,IAAAJ,EAAK,MAAM,OAAOI,GAClB,MAAMF,EAAA;AAAA,EACR;AAEA,WAASgN,EAAU1M,GAA2B;AAC5C,UAAMjC,IAAO,IAAI,IAAImN,EAAU,KAAK;AACpC,IAAInN,EAAK,IAAIiC,CAAE,IAAGjC,EAAK,OAAOiC,CAAE,IAC3BjC,EAAK,IAAIiC,CAAE,GAChBkL,EAAU,QAAQnN;AAAA,EACpB;AAGA,WAAS4O,IAAwB;AAC/B,QAAIpB,EAAe,UAAU,OAAO;AAClC,MAAAL,EAAU,4BAAY,IAAA;AACtB;AAAA,IACF;AACA,UAAMnN,IAAO,IAAI,IAAImN,EAAU,KAAK;AACpC,eAAWM,KAAOpM,EAAM,SAAY,IAAIqM,EAAMD,CAAG,CAAC;AAClD,IAAAN,EAAU,QAAQnN;AAAA,EACpB;AAEA,WAAS6O,KAAuB;AAC9B,IAAA1B,EAAU,4BAAY,IAAA;AAAA,EACxB;AAGA,WAAS2B,GAAW7M,GAA8B;AAChD,WAAOkL,EAAU,MAAM,IAAIlL,CAAE;AAAA,EAC/B;AAEA,SAAO;AAAA;AAAA,IAEL,MAAA8H;AAAA,IACA,OAAA1I;AAAA,IACA,MAAAI;AAAA,IACA,SAAAF;AAAA,IACA,OAAA+E;AAAA,IACA,QAAAyG;AAAA,IACA,SAAAC;AAAA,IACA,SAAAC;AAAA,IACA,eAAAC;AAAA,IACA,WAAAC;AAAA;AAAA,IAEA,SAAAC;AAAA,IACA,UAAAG;AAAA,IACA,cAAAD;AAAA,IACA,eAAAD;AAAA,IACA,gBAAAG;AAAA;AAAA,IAEA,SAAAG;AAAA,IACA,OAAAnG;AAAA,IACA,MAAA7F;AAAA,IACA,WAAAyM;AAAA,IACA,WAAAC;AAAA,IACA,cAAAC;AAAA,IACA,SAAAC;AAAA,IACA,YAAAE;AAAA,IACA,SAAAC;AAAA,IACA,WAAAC;AAAA,IACA,iBAAAC;AAAA,IACA,gBAAAC;AAAA,IACA,YAAAC;AAAA,IACA,OAAApB;AAAA,EAAA;AAEJ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC1MD,UAAMtI,IAAQC,GAORC,IAAOC,GAOPhD,IAAQuK,GAAA,GACRtD,IAAWD,GAAA,GAEXwF,IAAe3P,EAAS,MAAMoK,EAAS,YAAYpE,EAAM,IAAI,CAAC,GAE9D4J,IAAe5P;AAAA,MACnB,MAAMgG,EAAM,SAAS2J,EAAa,OAAO,SAAS3J,EAAM;AAAA,IAAA,GAGpD6J,IAAU7P,EAA2B,OAC5B2P,EAAa,OAAO,WAAW,CAAA,GAChC,IAAI,CAACpI,MAAM;AACrB,YAAMuI,IAAMvI;AACZ,aAAO;AAAA,QACL,KAAK,OAAOuI,EAAI,OAAOA,EAAI,QAAQ,EAAE;AAAA,QACrC,OAAO,OAAOA,EAAI,SAASA,EAAI,QAAQ,EAAE;AAAA,QACzC,UAAU,EAAQA,EAAI;AAAA,QACtB,OAAQA,EAAI,SAAqD;AAAA,QACjE,OAAO,OAAOA,EAAI,SAAU,WAAWA,EAAI,QAAQ;AAAA,MAAA;AAAA,IAEvD,CAAC,EAAE,OAAO,CAACvI,MAAMA,EAAE,GAAG,CACvB,GAEKwI,IAAa/P,EAAS,MAAM;AAChC,YAAMgQ,IAAI7M,EAAM,KAAK;AACrB,aAAI6M,MAAM,IAAU,KACb,GAAG7M,EAAM,MAAM,MAAM,OAAO6M,CAAC;AAAA,IACtC,CAAC;AAED,IAAA3C,GAAU,YAAY;AACpB,MAAAlK,EAAM,QAAQ6C,EAAM,IAAI,GACpBoE,EAAS,aAAa,QACxB,MAAMA,EAAS,KAAA,EAAO,MAAM,MAAA;AAAA,OAAe,GAE7C,MAAMjH,EAAM,KAAA,EAAO,MAAM,MAAA;AAAA,OAAe;AAAA,IAC1C,CAAC,GAEDuG;AAAA,MACE,MAAM1D,EAAM;AAAA,MACZ,OAAOpF,GAAMqP,MAAS;AACpB,QAAIrP,MAASqP,MACb9M,EAAM,QAAQvC,CAAI,GAClB,MAAMuC,EAAM,KAAA,EAAO,MAAM,MAAA;AAAA,SAAe;AAAA,MAC1C;AAAA,IAAA;AAGF,mBAAe+M,EAAaxL,GAA4B;AACtD,YAAMvB,EAAM,WAAWuB,CAAG;AAAA,IAC5B;AAEA,mBAAeyL,EAAa1N,GAA6B;AACvD,YAAMU,EAAM,QAAQV,CAAI;AAAA,IAC1B;AAEA,aAAS2N,IAAyB;AAChC,MAAAjN,EAAM,gBAAA;AAAA,IACR;AAEA,aAASkN,EAAcxN,GAA2B;AAChD,MAAAM,EAAM,UAAUN,CAAE;AAAA,IACpB;AAEA,aAASyN,EAAWjC,GAAoC;AACtD,MAAAnI,EAAK,aAAamI,CAAG;AAAA,IACvB;AAEA,aAASkC,EAAWC,GAAsB;AACxC,MAAAtK,EAAK,eAAesK,GAAQ,CAAC,GAAGrN,EAAM,SAAS,CAAC;AAAA,IAClD;AAEA,mBAAesN,IAA2B;AACxC,YAAMtN,EAAM,KAAA,EAAO,MAAM,MAAA;AAAA,OAAe;AAAA,IAC1C;sBAIEzB,EAAA,GAAAb,EAsJU,WAtJVW,IAsJU;AAAA,MApJRV,EAmBS,UAnBTuF,IAmBS;AAAA,QAlBPvF,EAOM,OAPN4F,IAOM;AAAA,UANJ5F,EAAqD,MAArDiI,IAAqDtH,EAApBmO,EAAA,KAAY,GAAA,CAAA;AAAA,UAClC3J,EAAA,YAAY8J,EAAA,SAAvBrO,KAAAb,EAIM,OAJNsI,IAIM;AAAA,YAHYlD,EAAA,iBAAhBpF,EAAmDc,GAAA,EAAA,KAAA,KAAA;AAAA,kBAAtBsE,EAAA,QAAQ,GAAA,CAAA;AAAA,YAAA;YACrBA,EAAA,YAAY8J,EAAA,cAA5BlP,EAAsDc,GAAA,EAAA,KAAA,KAAA;AAAA,gBAAd,KAAG;AAAA,YAAA;YAC3BoO,EAAA,cAAhBlP,EAAuDc,GAAA,EAAA,KAAA,KAAA;AAAA,kBAAxBoO,EAAA,KAAU,GAAA,CAAA;AAAA,YAAA;;;QAG7CjP,EASM,OATNsI,IASM;AAAA,UARJ9C,EAAuBC,EAAA,QAAA,SAAA;AAAA,UAEfN,EAAA,wBADR5E,EAMYC,EAAA4J,CAAA,GAAA;AAAA;YAJV,SAAQ;AAAA,YACP,SAAKpF,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA,CAAAhE,MAAE4O,EAAAA,QAAQ,aAAazK,EAAA,iBAAe;AAAA,UAAA;uBAE5C,MAAiB;AAAA,kBAAdA,EAAA,WAAW,GAAA,CAAA;AAAA,YAAA;;;;;MAMT3E,EAAA6B,CAAA,EAAM,gBAAjBzB,KAAAb,EAaM,OAbNwI,IAaM;AAAA,QAZJvI,EAEO,QAFPwM,IAEO;AAAA,4BAFiC,aAC9B,EAAA;AAAA,UAAAxM,EAAgC,KAAA,MAAAW,EAA1BH,EAAA6B,CAAA,EAAM,aAAa,GAAA,CAAA;AAAA,QAAA;0BAEnCrC,EAA4C,QAAA,EAAtC,OAAM,8BAAA,GAA6B,MAAA,EAAA;AAAA,QACzC8E,EAA4FtE,EAAA4J,CAAA,GAAA;AAAA,UAAjF,MAAK;AAAA,UAAK,SAAQ;AAAA,UAAS,gCAAOqF,EAAU,SAAA;AAAA,QAAA;qBAAa,MAAY,CAAA,GAAAzK,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,cAAZ,gBAAY,EAAA;AAAA,UAAA;;;QAChFF,EAA4FtE,EAAA4J,CAAA,GAAA;AAAA,UAAjF,MAAK;AAAA,UAAK,SAAQ;AAAA,UAAS,gCAAOqF,EAAU,SAAA;AAAA,QAAA;qBAAa,MAAY,CAAA,GAAAzK,EAAA,EAAA,MAAAA,EAAA,EAAA,IAAA;AAAA,cAAZ,gBAAY,EAAA;AAAA,UAAA;;;QAChFF,EAAsFtE,EAAA4J,CAAA,GAAA;AAAA,UAA3E,MAAK;AAAA,UAAK,SAAQ;AAAA,UAAS,gCAAOqF,EAAU,QAAA;AAAA,QAAA;qBAAY,MAAO,CAAA,GAAAzK,EAAA,EAAA,MAAAA,EAAA,EAAA,IAAA;AAAA,cAAP,WAAO,EAAA;AAAA,UAAA;;;QAC1EF,EAAuFtE,EAAA4J,CAAA,GAAA;AAAA,UAA5E,MAAK;AAAA,UAAK,SAAQ;AAAA,UAAU,gCAAOqF,EAAU,QAAA;AAAA,QAAA;qBAAY,MAAO,CAAA,GAAAzK,EAAA,EAAA,MAAAA,EAAA,EAAA,IAAA;AAAA,cAAP,WAAO,EAAA;AAAA,UAAA;;;0BAC3EhF,EAA2C,QAAA,EAArC,OAAM,6BAAA,GAA4B,MAAA,EAAA;AAAA,QACxC8E,EAEYtE,EAAA4J,CAAA,GAAA;AAAA,UAFD,MAAK;AAAA,UAAK,SAAQ;AAAA,UAAS,SAAO5J,EAAA6B,CAAA,EAAM;AAAA,QAAA;qBAAgB,MAEnE,CAAA,GAAA2C,EAAA,EAAA,MAAAA,EAAA,EAAA,IAAA;AAAA,cAFmE,qBAEnE,EAAA;AAAA,UAAA;;;aAGFpE,EAAA,GAAAb,EAkBM,OAlBN8P,IAkBM;AAAA,QAjBJ7P,EAME,SAAA;AAAA,UALC,OAAOQ,EAAA6B,CAAA,EAAM;AAAA,UACd,MAAK;AAAA,UACL,aAAY;AAAA,UACZ,OAAM;AAAA,UACL,WAAO2C,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA8K,GAAA,CAASC,MAAMvP,EAAA6B,CAAA,EAAM,UAAW0N,EAAE,OAA4B,KAAK,GAAA,CAAA,OAAA,CAAA;AAAA,QAAA;QAE7EvK,EAA8EC,EAAA,QAAA,WAAA;AAAA,UAAxD,SAASjF,EAAA6B,CAAA,EAAM;AAAA,UAAU,WAAY7B,EAAA6B,CAAA,EAAM;AAAA,QAAA;0BACjErC,EAAyC,QAAA,EAAnC,OAAM,2BAAA,GAA0B,MAAA,EAAA;AAAA,QAE9B,OAAO,KAAKQ,KAAM,OAAO,EAAE,SAAM,UADzCD,EAOYC,EAAA4J,CAAA,GAAA;AAAA;UALV,MAAK;AAAA,UACL,SAAQ;AAAA,UACP,SAAO5J,EAAA6B,CAAA,EAAM;AAAA,QAAA;qBACf,MAED,CAAA,GAAA2C,EAAA,EAAA,MAAAA,EAAA,EAAA,IAAA;AAAA,cAFC,WAED,EAAA;AAAA,UAAA;;;;MAISxE,EAAA6B,CAAA,EAAM,WAAjBzB,KAAAb,EAEM,OAFNiQ,IAEM;AAAA,cADJjQ,EAAqDc,GAAA,MAAAC,EAA5B,GAAC,CAAN4F,MAApB5B,EAAqDtE,EAAAyP,EAAA,GAAA;AAAA,UAAxB,KAAKvJ;AAAA,UAAG,QAAO;AAAA,QAAA;YAGjClG,EAAA6B,CAAA,EAAM,iBADnB9B,EASgBC,EAAA0P,EAAA,GAAA;AAAA;QAPd,OAAM;AAAA,QACL,aAAa1P,EAAA6B,CAAA,EAAM,OAAO,WAAO;AAAA,QAClC,OAAM;AAAA,MAAA;QAEK,WACT,MAAoE;AAAA,UAApEyC,EAAoEtE,EAAA4J,CAAA,GAAA;AAAA,YAAzD,SAAQ;AAAA,YAAW,SAAOuF;AAAA,UAAA;uBAAW,MAAQ,CAAA,GAAA3K,EAAA,EAAA,MAAAA,EAAA,EAAA,IAAA;AAAA,gBAAR,YAAQ,EAAA;AAAA,YAAA;;;;;gCAI/CxE,EAAA6B,CAAA,EAAM,gBADnB9B,EAegBC,EAAA2P,EAAA,GAAA;AAAA;QAbd,OAAM;AAAA,QACN,aAAY;AAAA,QACZ,OAAM;AAAA,MAAA;QAEK,WACT,MAMY;AAAA,UALJhL,EAAA,wBADR5E,EAMYC,EAAA4J,CAAA,GAAA;AAAA;YAJV,SAAQ;AAAA,YACP,SAAKpF,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA,CAAAhE,MAAE4O,EAAAA,QAAQ,aAAazK,EAAA,iBAAe;AAAA,UAAA;uBAE5C,MAAiB;AAAA,kBAAdA,EAAA,WAAW,GAAA,CAAA;AAAA,YAAA;;;;;aAMpBvE,EAAA,GAAAb,EA6CM,OA7CNqQ,IA6CM;AAAA,QA3CJpQ,EAOM,OAPNqQ,IAOM;AAAA,UANJvL,EAKEtE,EAAAyK,EAAA,GAAA;AAAA,YAJC,eAAazK,EAAA6B,CAAA,EAAM,mBAAc;AAAA,YACjC,eAAe7B,EAAA6B,CAAA,EAAM,mBAAc;AAAA,YACpC,cAAW;AAAA,YACV,uBAAoBiN;AAAA,UAAA;;QAGzBxK,EAcWtE,EAAA8P,EAAA,GAAA;AAAA,UAbR,SAASvB,EAAA;AAAA,UACT,MAAMvO,EAAA6B,CAAA,EAAM;AAAA,UACZ,YAAU7B,EAAA6B,CAAA,EAAM,WAAO;AAAA,UACvB,kBAAgB7B,EAAA6B,CAAA,EAAM;AAAA,UACtB,oBAAiB+M;AAAA,QAAA;UAGFtO,EAAAiO,EAAA,QAAPC;YACE,MAAA,QAAAA,EAAI,GAAG;AAAA,YAGhB,IAAAuB,EAAA,CAHsBhD,MAAG;AAAA,cAGzB/H,EAAsEC,EAAA,QAAA,QAAjDuJ,EAAI,GAAG,MAAK,KAAAzB,EAAA,GAAjC,MAAsE;AAAA,oBAAxBA,IAAMyB,EAAI,GAAG,CAAA,GAAA,CAAA;AAAA,cAAA;;;;QAK/DhP,EAiBM,OAjBNwQ,IAiBM;AAAA,WAhBJ5P,EAAA,EAAA,GAAAb,EAeMc,GAAA,MAAAC,EAdUN,EAAA6B,CAAA,EAAM,QAAbkL,YADTxN,EAeM,OAAA;AAAA,YAbH,KAAK,OAAOS,KAAM,MAAM+M,CAAG,CAAA;AAAA,YAC3B,OAAKzH,EAAA;AAAA;cAAkG,EAAA,uCAAAtF,EAAA6B,CAAA,EAAM,WAAW7B,KAAM,MAAM+M,CAAG,CAAA,EAAA;AAAA,YAAA;YAIvI,SAAK,CAAAvM,MAAEwO,EAAWjC,CAAG;AAAA,UAAA;YAEtBzI,EAKEtE,EAAAyK,EAAA,GAAA;AAAA,cAJC,eAAazK,KAAM,WAAWA,EAAA6B,CAAA,EAAM,MAAMkL,CAAG,CAAA;AAAA,cAC7C,cAAU,UAAY/M,EAAA6B,CAAA,EAAM,MAAMkL,CAAG,CAAA;AAAA,cACrC,8BAAoBgC,EAAc/O,KAAM,MAAM+M,CAAG,CAAA;AAAA,cACjD,4BAAD,MAAA;AAAA,cAAA,GAAW,CAAA,MAAA,CAAA;AAAA,YAAA;;;;OAQV/M,EAAA6B,CAAA,EAAM,WAAO,CAAK7B,EAAA6B,CAAA,EAAM,YAAQ,CAAK7B,EAAA6B,CAAA,EAAM,WADpDzB,KAAAb,EAUS,UAVT0Q,IAUS;AAAA,QANP3L,EAKEtE,EAAAkQ,EAAA,GAAA;AAAA,UAJC,eAAalQ,EAAA6B,CAAA,EAAM,KAAK;AAAA,UACxB,OAAO7B,EAAA6B,CAAA,EAAM,KAAK;AAAA,UAClB,YAAU7B,EAAA6B,CAAA,EAAM,KAAK;AAAA,UACrB,uBAAoBgN;AAAA,QAAA;;;;ICrPhBsB,KAAuB9R,EAAY,uBAAuB,MAAM;AAC3E,QAAMgL,IAAO9K,EAAmB,IAAI,GAC9BmM,IAAOnM,EAAc,QAAQ,GAC7B6R,IAAW7R,EAA4B,IAAI,GAG3C8R,IAAQ9R,EAA6B,EAAE,GAEvC+R,IAAU/R,EAA6B,EAAE,GAGzCgS,IAAShS,EAA8B,EAAE,GAEzCsC,IAAUtC,EAAI,EAAK,GACnBiS,IAASjS,EAAI,EAAK,GAClBkS,IAAWlS,EAAI,EAAK,GACpBqH,IAAQrH,EAAkB,IAAI,GAE9BmS,IAAWhS,EAAS,MAAMgM,EAAK,UAAU,QAAQ,GACjDiG,IAASjS,EAAS,MAAMgM,EAAK,UAAU,MAAM,GAC7CkG,IAASlS,EAAS,MAAMgM,EAAK,UAAU,MAAM,GAC7CmC,IAAWnO,EAAS,MAAMkH,EAAM,UAAU,IAAI,GAG9CiL,IAAUnS,EAAS,MAAM;AAC7B,UAAM8H,IAAI6J,EAAM,OACV5J,IAAI6J,EAAQ,OACZ9M,IAAO,oBAAI,IAAI,CAAC,GAAG,OAAO,KAAKgD,CAAC,GAAG,GAAG,OAAO,KAAKC,CAAC,CAAC,CAAC;AAC3D,eAAW+G,KAAKhK;AACd,UAAI,CAAC,OAAO,GAAGgD,EAAEgH,CAAC,GAAG/G,EAAE+G,CAAC,CAAC;AAEvB,YAAI,OAAOhH,EAAEgH,CAAC,KAAM,YAAY,OAAO/G,EAAE+G,CAAC,KAAM;AAC9C,cAAI,KAAK,UAAUhH,EAAEgH,CAAC,CAAC,MAAM,KAAK,UAAU/G,EAAE+G,CAAC,CAAC,EAAG,QAAO;AAAA;AAE1D,iBAAO;AAIb,WAAO;AAAA,EACT,CAAC;AAGD,WAASsD,EAAc1F,GAAiC9L,GAAqC;AAC3F,eAAWkO,KAAK,OAAO,KAAKpC,CAAM,EAAG,QAAOA,EAAOoC,CAAC;AACpD,WAAO,OAAOpC,GAAQ9L,CAAI;AAAA,EAC5B;AAEA,WAASwH,IAAc;AACrB,IAAAgK,EAAcT,EAAM,OAAO,EAAE,GAC7BS,EAAcR,EAAQ,OAAO,EAAE,GAC/BC,EAAO,QAAQ,CAAA,GACf1P,EAAQ,QAAQ,IAChB2P,EAAO,QAAQ,IACfC,EAAS,QAAQ,IACjB7K,EAAM,QAAQ,MACdwK,EAAS,QAAQ;AAAA,EACnB;AAGA,WAASW,EAAcC,GAAsBC,IAAoC,IAAU;AACzF,IAAA5H,EAAK,QAAQ2H,GACbtG,EAAK,QAAQ,UACb0F,EAAS,QAAQ,MACjBU,EAAcT,EAAM,OAAOY,CAAQ,GACnCH,EAAcR,EAAQ,OAAOW,CAAQ,GACrCV,EAAO,QAAQ,CAAA,GACf3K,EAAM,QAAQ;AAAA,EAChB;AAGA,iBAAe3E,EACb+P,GACAzP,GACA2P,IAA8B,QACf;AACf,IAAA7H,EAAK,QAAQ2H,GACbtG,EAAK,QAAQwG,GACbd,EAAS,QAAQ7O,GACjBV,EAAQ,QAAQ,IAChB+E,EAAM,QAAQ,MACd2K,EAAO,QAAQ,CAAA;AAEf,QAAI;AAEF,YAAM7E,KAAM,MADGzN,EAAA,EACU,IAAkB,cAAc+S,CAAY,SAAS;AAAA,QAC5E,QAAQ,EAAE,cAAczP,EAAA;AAAA,MAAG,CAC5B;AACD,MAAAuP,EAAcT,EAAM,OAAO3E,GAAI,IAAI,GACnCoF,EAAcR,EAAQ,OAAO5E,GAAI,IAAI;AAAA,IACvC,SAASxM,GAAK;AACZ,YAAA0G,EAAM,QAAQ1G,aAAe,QAAQA,IAAM,IAAI,MAAM,OAAOA,CAAG,CAAC,GAC1DA;AAAA,IACR,UAAA;AACE,MAAA2B,EAAQ,QAAQ;AAAA,IAClB;AAAA,EACF;AAGA,WAASsQ,EAAS/J,GAAcc,GAAsB;AAEpD,QADAmI,EAAM,MAAMjJ,CAAI,IAAIc,GAChBqI,EAAO,MAAMnJ,CAAI,GAAG;AAEtB,YAAM9H,IAAO,EAAE,GAAGiR,EAAO,MAAA;AACzB,aAAOjR,EAAK8H,CAAI,GAChBmJ,EAAO,QAAQjR;AAAA,IACjB;AAAA,EACF;AAEA,WAAS8R,EAAU9R,GAAsC;AACvD,IAAAiR,EAAO,QAAQ,EAAE,GAAGjR,EAAA;AAAA,EACtB;AAEA,WAAS+R,IAAoB;AAC3B,IAAAd,EAAO,QAAQ,CAAA;AAAA,EACjB;AAMA,iBAAee,IAAiC;AAC9C,QAAI,CAACjI,EAAK,MAAO,OAAM,IAAI,MAAM,6CAA6C;AAC9E,QAAImH,EAAO,MAAO,OAAM,IAAI,MAAM,gBAAgB;AAElD,IAAAA,EAAO,QAAQ,IACf5K,EAAM,QAAQ,MACd2K,EAAO,QAAQ,CAAA;AAEf,QAAI;AACF,YAAMvS,IAASC,EAAA,GACTsT,IACJ7G,EAAK,UAAU,WACX,cAAcrB,EAAK,KAAK,YACxB,cAAcA,EAAK,KAAK,WAExBjH,IACJsI,EAAK,UAAU,WACX2F,EAAM,QACN,EAAE,IAAID,EAAS,OAAO,GAAGC,EAAM,MAAA,GAG/BmB,MADM,MAAMxT,EAAO,KAAmBuT,GAAKnP,CAAO,GACtC;AAClB,aAAAgO,EAAS,QAAQoB,IAEjBV,EAAcR,EAAQ,OAAO,EAAE,GAAGD,EAAM,OAAO,GAC/C3F,EAAK,QAAQ,QACN8G;AAAA,IACT,SAAStS,GAAK;AACZ,YAAIA,aAAesD,KACjB+N,EAAO,QAAQ,EAAE,GAAGrR,EAAI,OAAA,KACfA,aAAegD,KAEfhD,aAAe,WACxB0G,EAAM,QAAQ1G,IAEVA;AAAA,IACR,UAAA;AACE,MAAAsR,EAAO,QAAQ;AAAA,IACjB;AAAA,EACF;AAGA,iBAAe5O,IAAyB;AACtC,QAAI,CAACyH,EAAK,SAAS+G,EAAS,UAAU;AACpC,YAAM,IAAI,MAAM,mBAAmB;AAErC,QAAIK,EAAS,MAAO,OAAM,IAAI,MAAM,kBAAkB;AAEtD,IAAAA,EAAS,QAAQ,IACjB7K,EAAM,QAAQ;AACd,QAAI;AAEF,YADe3H,EAAA,EACF,KAAK,cAAcoL,EAAK,KAAK,YAAY,EAAE,IAAI+G,EAAS,MAAA,CAAO;AAAA,IAC9E,SAASlR,GAAK;AACZ,YAAIA,aAAe,UAAO0G,EAAM,QAAQ1G,IAClCA;AAAA,IACR,UAAA;AACE,MAAAuR,EAAS,QAAQ;AAAA,IACnB;AAAA,EACF;AAEA,SAAO;AAAA;AAAA,IAEL,MAAApH;AAAA,IACA,MAAAqB;AAAA,IACA,UAAA0F;AAAA,IACA,OAAAC;AAAA,IACA,SAAAC;AAAA,IACA,QAAAC;AAAA,IACA,SAAA1P;AAAA,IACA,QAAA2P;AAAA,IACA,UAAAC;AAAA,IACA,OAAA7K;AAAA;AAAA,IAEA,UAAA8K;AAAA,IACA,QAAAC;AAAA,IACA,QAAAC;AAAA,IACA,SAAAC;AAAA,IACA,UAAAhE;AAAA;AAAA,IAEA,OAAA/F;AAAA,IACA,eAAAiK;AAAA,IACA,MAAA9P;AAAA,IACA,UAAAkQ;AAAA,IACA,WAAAC;AAAA,IACA,aAAAC;AAAA,IACA,MAAAC;AAAA,IACA,SAAA1P;AAAA,EAAA;AAEJ,CAAC;AC7NM,SAAS6P,KAAmD;AACjE,QAAMC,wBAAY,IAAA;AAElB,SAAO;AAAA,IACL,SAASC,GAAMzJ,GAAO;AACpB,MAAAwJ,EAAM,IAAIC,GAAMzJ,CAAK;AAAA,IACvB;AAAA,IACA,IAAIyJ,GAAM;AACR,aAAOD,EAAM,IAAIC,CAAI,KAAK;AAAA,IAC5B;AAAA,IACA,IAAIA,GAAM;AACR,aAAOD,EAAM,IAAIC,CAAI;AAAA,IACvB;AAAA,IACA,OAAO;AACL,aAAO,CAAC,GAAGD,EAAM,MAAM;AAAA,IACzB;AAAA,IACA,QAAQ;AACN,MAAAA,EAAM,MAAA;AAAA,IACR;AAAA,IACA,eAAeE,GAAQ;AACrB,iBAAW,CAACD,GAAMzJ,CAAK,KAAK,OAAO,QAAQ0J,CAAM;AAC/C,QAAAF,EAAM,IAAIC,GAAMzJ,CAAK;AAAA,IAEzB;AAAA,EAAA;AAEJ;ACjCA,MAAM2J,KAASJ,GAAA,GACTK,KAAUL,GAAA,GAEHM,KAAgBF,GAAO,UACvBG,KAAWH,GAAO,KAClBI,KAAWJ,GAAO,KAClBK,KAAaL,GAAO,MAEpBM,KAAiBL,GAAQ,UACzBM,KAAYN,GAAQ,KACpBO,KAAYP,GAAQ,KACpBQ,KAAcR,GAAQ;AAG5B,SAASS,KAAsB;AACpC,EAAAV,GAAO,MAAA,GACPC,GAAQ,MAAA;AACV;AAeO,SAASU,GAAmBZ,GAA+B;AAChE,EAAIA,EAAO,UAAQC,GAAO,eAAeD,EAAO,MAAM,GAClDA,EAAO,WAASE,GAAQ,eAAeF,EAAO,OAAO;AAC3D;;;;;;;;2BCnCE7R,EAMWC,EAAAuK,CAAA,GAAA,EAND,SAAQ,aAAS;AAAA,MACd,SAAM,MAAsB;AAAA,QAAtB9J,EAAA,6BAAyBkE,EAAA,IAAI,GAAA,CAAA;AAAA,MAAA;iBAC9C,MAGW;AAAA,QAHKA,EAAA,aAAhBpF,EAGWc,GAAA,EAAA,KAAA,KAAA;AAAA,UAFTb,EAAuB,gBAAdmF,EAAA,IAAI,GAAA,CAAA;AAAA,4BAAU,6CACvB,EAAA;AAAA,UAAAnF,EAAuD,QAAA,MAAjD,oBAAeW,EAAGwE,EAAA,IAAI,IAAG,qBAAiB,CAAA;AAAA,4BAAO,MACzD,EAAA;AAAA,QAAA;;;;;;;;;;;ACKJ,UAAMD,IAAQC,GACR8N,IAAY/T,EAAS,MAAMsT,GAAStN,EAAM,KAAK,IAAI,CAAC,GACpDgO,IAAahU,EAAS,MAAM;AAChC,YAAM,EAAE,MAAMiU,GAAO,GAAGC,EAAA,IAASlO,EAAM;AACvC,aAAOkO;AAAA,IACT,CAAC;qBAIkCH,EAAA,cAAjC1S,EAAkEsF,GAAlDoN,EAAA,KAAS,GAAAI,GAAAC,GAAA,EAAA,KAAA,KAA2BJ,EAAA,KAAU,CAAA,GAAA,MAAA,EAAA,WAC9D3S,EAA2DgT,IAAA;AAAA;MAArC,MAAMpO,EAAA,KAAK;AAAA,MAAO,MAAMA,EAAA,KAAK;AAAA,IAAA;;;;;;;;ACTrD,UAAMD,IAAQC,GAORqO,IAAWtU,EAAmB,MAAM;AAExC,UAAIgG,EAAM,KAAK,SAAS;AACtB,eAAO,EAAE,MAAM,QAAA;AAEjB,UAAIA,EAAM,KAAK,SAAS,UAAU;AAChC,cAAM+N,IAAYL,GAAU1N,EAAM,KAAK,IAAI;AAC3C,eAAO+N,IAAY,EAAE,MAAM,UAAU,WAAAA,MAAc,EAAE,MAAM,UAAA;AAAA,MAC7D;AAEA,YAAMQ,IAAkBb,GAAU1N,EAAM,KAAK,IAAI;AACjD,aAAIuO,IAAwB,EAAE,MAAM,UAAU,WAAWA,EAAA,IACrDjB,GAAStN,EAAM,KAAK,IAAI,IAAU,EAAE,MAAM,QAAA,IACvC,EAAE,MAAM,UAAA;AAAA,IACjB,CAAC,GAEKwO,IAAcxU,EAAS,MAAM;AACjC,YAAM,EAAE,MAAMiU,GAAO,MAAMQ,GAAO,GAAGP,EAAA,IAASlO,EAAM;AACpD,aAAOkO;AAAA,IACT,CAAC,GAEKQ,IAAY1U,EAAoB,MAAMgG,EAAM,IAA4B;qBAMpEsO,EAAA,MAAS,SAAI,YAAiBA,EAAA,MAAS,aAF/C5S,EAAA,GAAAL,EAIEsF,GAHK2N,EAAA,MAAS,SAAS,qBAEfE,EAAA,KAAW,CAAA,GAAA,MAAA,EAAA,KAEKF,EAAA,MAAS,SAAI,gBAAvCjT,EAAyEsT,IAAA;AAAA;MAAnB,MAAMD,EAAA;AAAA,IAAA,+BAC5DrT,EAAmFgT,IAAA;AAAA;MAA7D,MAAMpO,EAAA,KAAK;AAAA,MAAO,MAAOA,EAAA,KAAK;AAAA,IAAA;;;;;;;;;;;;;;;;ACxBtD,UAAMD,IAAQC,GAKR2O,IAAOnD,GAAA,GACPrH,IAAWD,GAAA,GACX1E,IAASC,GAAA,GAITmP,IAAMC,GAAiBF,EAAK,OAAOA,EAAK,MAAM;AAMpD,IAAAlL;AAAA,MACE,MAAMkL,EAAK;AAAA,MACX,CAAChU,MAAS;AAER,QAAAiU,EAAI,UAAU,EAAE,GAAGjU,GAAM;AAAA,MAC3B;AAAA,IAAA;AAGF,UAAM+O,IAAe3P,EAAS,MAAMoK,EAAS,YAAYpE,EAAM,IAAI,CAAC,GAE9D+O,IAAc/U;AAAA,MAClB,MAAM2P,EAAa,OAAO,UAAU,CAAA;AAAA,IAAC,GAGjCqF,IAAahV,EAAS,MACtB4U,EAAK,WAAiB,YAAYjF,EAAa,OAAO,SAAS3J,EAAM,IAAI,KACtE,GAAG2J,EAAa,OAAO,SAAS3J,EAAM,IAAI,aAAaA,EAAM,EAAE,EACvE,GAEKiP,IAAcjV,EAAwB,MAAM;AAChD,YAAM+O,IAAI6F,EAAK,MAAM;AACrB,aAAO,OAAO7F,KAAM,WAAWA,IAAI;AAAA,IACrC,CAAC,GAEKmG,IAAqBlV,EAAuD,MAAM;AACtF,cAAQiV,EAAY,OAAA;AAAA,QAClB,KAAK;AAAa,iBAAO;AAAA,QACzB,KAAK;AAAA,QACL,KAAK;AAAS,iBAAO;AAAA,QACrB,KAAK;AAAY,iBAAO;AAAA,QACxB;AAAS,iBAAO;AAAA,MAAA;AAAA,IAEpB,CAAC;AAED,IAAA5H,GAAU,YAAY;AACpB,MAAIjD,EAAS,aAAa,QACxB,MAAMA,EAAS,KAAA,EAAO,MAAM,MAAA;AAAA,OAAe,GAEzCpE,EAAM,OAAO,QAAQA,EAAM,OAAO,SACpC,MAAM4O,EAAK,KAAK5O,EAAM,MAAMA,EAAM,IAAI,MAAM,EAAE,MAAM,MAAA;AAAA,OAAe,IAEnE4O,EAAK,cAAc5O,EAAM,IAAI;AAAA,IAEjC,CAAC,GAED0D;AAAA,MACE,MAAM,CAAC1D,EAAM,MAAMA,EAAM,EAAE;AAAA,MAC3B,OAAO,CAACmP,GAAUC,CAAM,MAAM;AAC5B,QAAIA,KAAW,OACb,MAAMR,EAAK,KAAKO,GAAUC,GAAQ,MAAM,EAAE,MAAM,MAAA;AAAA,SAAe,IAE/DR,EAAK,cAAcO,CAAQ;AAAA,MAE/B;AAAA,IAAA;AAGF,mBAAeE,IAAwB;AACrC,UAAI;AACF,cAAMvC,IAAQ,MAAM8B,EAAK,KAAA;AACzB,QAAIA,EAAK,YAEFnP,EAAO,KAAK;AAAA,UACf,MAAM,kBAAkBO,EAAM,IAAI;AAAA,UAClC,QAAQ,EAAE,IAAI8M,EAAA;AAAA,QAAM,CACrB,EAAE,MAAM,MAAA;AAAA,SAAe;AAAA,MAE5B,QAAQ;AAAA,MAGR;AAAA,IACF;AAEA,mBAAewC,IAA0B;AACvC,MAAK,QAAQ,iBAAiB,MAC9B,MAAMV,EAAK,QAAA,EAAU,MAAM,MAAA;AAAA,OAAe,GACrCA,EAAK,YACHnP,EAAO,KAAK,EAAE,MAAMO,EAAM,gBAAgB,EAAE,MAAM,MAAA;AAAA,OAAe;AAAA,IAE1E;AAEA,aAASuP,IAAiB;AACxB,MAAIX,EAAK,WAAW,CAAC,QAAQ,qDAAqD,KAG7EnP,EAAO,KAAK,EAAE,MAAMO,EAAM,gBAAgB,EAAE,MAAM,MAAA;AAAA,OAAe;AAAA,IACxE;sBAIEtE,EAAA,GAAAb,EA4EU,WA5EVW,IA4EU;AAAA,MA3ERV,EAkCS,UAlCTuF,IAkCS;AAAA,QAjCPvF,EAMM,OANN4F,IAMM;AAAA,UALJ5F,EAAkE,KAAA;AAAA,YAA/D,OAAM;AAAA,YAA6B,SAAOyU;AAAA,UAAA,GAAU,SAAO;AAAA,UAC9DzU,EAAmD,MAAnDiI,IAAmDtH,EAAlBuT,EAAA,KAAU,GAAA,CAAA;AAAA,UAC3BC,EAAA,cAAhB5T,EAEWC,EAAAkU,EAAA,GAAA;AAAA;YAFmB,SAASN,EAAA;AAAA,UAAA;uBACrC,MAAiB;AAAA,kBAAdD,EAAA,KAAW,GAAA,CAAA;AAAA,YAAA;;;;QAGlBnU,EAyBM,OAzBNqI,IAyBM;AAAA,UAxBJvD,EAMYtE,EAAA4J,CAAA,GAAA;AAAA,YALV,SAAQ;AAAA,YACP,UAAU5J,EAAAsT,CAAA,EAAK,UAAUtT,EAAAsT,CAAA,EAAK;AAAA,YAC9B,SAAOW;AAAA,UAAA;uBACT,MAED,CAAA,GAAAzP,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,gBAFC,YAED,EAAA;AAAA,YAAA;;;UAEQxE,EAAAsT,CAAA,EAAK,eADbvT,EAQYC,EAAA4J,CAAA,GAAA;AAAA;YANV,SAAQ;AAAA,YACP,UAAU5J,EAAAsT,CAAA,EAAK,UAAUtT,EAAAsT,CAAA,EAAK;AAAA,YAC9B,SAAStT,EAAAsT,CAAA,EAAK;AAAA,YACd,SAAOU;AAAA,UAAA;uBACT,MAED,CAAA,GAAAxP,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,gBAFC,aAED,EAAA;AAAA,YAAA;;;UACAF,EAOYtE,EAAA4J,CAAA,GAAA;AAAA,YANV,SAAQ;AAAA,YACP,UAAU5J,EAAAsT,CAAA,EAAK,UAAUtT,EAAAsT,CAAA,EAAK;AAAA,YAC9B,SAAStT,EAAAsT,CAAA,EAAK;AAAA,YACd,SAAOS;AAAA,UAAA;uBAER,MAA6C;AAAA,cAA1CtT,EAAAN,EAAAH,EAAAsT,CAAA,EAAK,WAAQ,YAAA,WAAA,GAAA,CAAA;AAAA,YAAA;;;;;MAMdtT,EAAAsT,CAAA,EAAK,iBADbvT,EAOWC,EAAAuK,CAAA,GAAA;AAAA;QALT,SAAQ;AAAA,QACR,OAAM;AAAA,QACN,MAAK;AAAA,MAAA;mBAEL,MAA0D;AAAA,cAAvDvK,EAAAsT,CAAA,EAAK,OAAO,WAAO,6BAAA,GAAA,CAAA;AAAA,QAAA;;;MAIbtT,EAAAsT,CAAA,EAAK,WAAhBlT,KAAAb,EAEM,OAFNuI,IAEM;AAAA,cADJvI,EAAqDc,GAAA,MAAAC,EAA5B,GAAC,CAAN4F,MAApB5B,EAAqDtE,EAAAyP,EAAA,GAAA;AAAA,UAAxB,KAAKvJ;AAAA,UAAG,QAAO;AAAA,QAAA;kBAI9CnG,EAMUC,EAAA2J,CAAA,GAAA;AAAA;QANM,SAAQ;AAAA,QAAK,OAAM;AAAA,MAAA;mBAE/B,MAAkC;AAAA,WADpCvJ,EAAA,EAAA,GAAAb,EAIEc,GAAA,MAAAC,EAHsBmT,EAAA,OAAW,CAAzBU,GAAMhP,YADhBpF,EAIEqU,IAAA;AAAA,YAFC,KAAKjP;AAAA,YACL,MAAAgP;AAAA,UAAA;;;;MAKMnU,EAAAsT,CAAA,EAAK,WAAO,CAAKtT,EAAAsT,CAAA,EAAK,WAAjClT,EAAA,GAAAb,EAcM,OAdNwI,IAcM;AAAA,QAbJvD,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAAhF,EAEO,QAAA,EAFD,OAAM,oCAAA,GAAoC,kCAEhD,EAAA;AAAA,QACA8E,EAAyEtE,EAAA4J,CAAA,GAAA;AAAA,UAA9D,SAAQ;AAAA,UAAQ,MAAK;AAAA,UAAM,SAAOqK;AAAA,QAAA;qBAAU,MAAM,CAAA,GAAAzP,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,cAAN,UAAM,EAAA;AAAA,UAAA;;;QAC7DF,EAQYtE,EAAA4J,CAAA,GAAA;AAAA,UAPV,SAAQ;AAAA,UACR,MAAK;AAAA,UACJ,SAAS5J,EAAAsT,CAAA,EAAK;AAAA,UACd,UAAUtT,EAAAsT,CAAA,EAAK;AAAA,UACf,SAAOS;AAAA,QAAA;qBACT,MAED,CAAA,GAAAvP,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,cAFC,eAED,EAAA;AAAA,UAAA;;;;;;IC5MA6P,KAAU5C,GAAA,GAEH6C,KAAwBD,GAAQ,UAChCE,KAAmBF,GAAQ,KAC3BG,KAAmBH,GAAQ,KAC3BI,KAAsBJ,GAAQ,MAC9BK,KAAwBL,GAAQ,OAChCM,KAA0BN,GAAQ;;;;;;;2BCZ7CtU,EAGWC,EAAAuK,CAAA,GAAA,EAHD,SAAQ,aAAS;AAAA,MACd,SAAM,MAAgC;AAAA,QAAhC9J,EAAA,uCAAmCkE,EAAA,IAAI,GAAA,CAAA;AAAA,MAAA;iBAAc,MAChD;AAAA,0BADgD,2BAChD,EAAA;AAAA,QAAAnF,EAA+D,QAAA,MAAzD,4BAAuBW,EAAGwE,EAAA,IAAI,IAAG,qBAAiB,CAAA;AAAA,0BAAO,MACvF,EAAA;AAAA,MAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACeF,UAAMD,IAAQC,GAERiQ,wBAAoB,IAAI,CAAC,QAAQ,WAAW,WAAW,SAAS,MAAM,CAAC,GAOvE5B,IAAWtU,EAAmB,MAAM;AACxC,UAAIgG,EAAM,KAAK,SAAS,SAAS;AAC/B,cAAMuB,IAAIsO,GAAiB7P,EAAM,KAAK,IAAI;AAC1C,eAAOuB,IAAI,EAAE,MAAM,SAAS,WAAWA,EAAA,IAAM,EAAE,MAAM,UAAA;AAAA,MACvD;AACA,UAAIvB,EAAM,KAAK,SAAS;AACtB,eAAOkQ,EAAc,IAAIlQ,EAAM,KAAK,IAAI,IACpC,EAAE,MAAM,UAAU,YAAYA,EAAM,KAAK,KAAA,IACzC,EAAE,MAAM,UAAA;AAGd,UAAIkQ,EAAc,IAAIlQ,EAAM,KAAK,IAAI;AACnC,eAAO,EAAE,MAAM,UAAU,YAAYA,EAAM,KAAK,KAAA;AAElD,YAAMmQ,IAAQN,GAAiB7P,EAAM,KAAK,IAAI;AAC9C,aAAImQ,IAAc,EAAE,MAAM,SAAS,WAAWA,EAAA,IACvC,EAAE,MAAM,UAAA;AAAA,IACjB,CAAC,GAEKC,IAAapW,EAAS,MAAM;AAChC,YAAM,EAAE,MAAMqW,GAAI,MAAMC,GAAI,OAAOC,GAAI,GAAGrC,MAASlO,EAAM;AACzD,aAAOkO;AAAA,IACT,CAAC,GAEKjS,IAAQjC;AAAA,MACZ,MAAOgG,EAAM,KAAK,SAAS,CAAA;AAAA,IAAC,GAGxBwQ,IAAexW,EAAS,MAAOgG,EAAM,KAAK,SAAgC,IAAI,GAC9EyQ,IAAqBzW;AAAA,MACzB,MAAOgG,EAAM,KAAK,eAAsC;AAAA,IAAA,GAEpD0Q,IAAa1W,EAAiB,MAAM;AACxC,YAAM8H,IAAI9B,EAAM,KAAK;AACrB,aAAO,OAAO8B,KAAM,WAAWA,IAAI;AAAA,IACrC,CAAC,GAOK6O,IAAW3W,EAAwB,MAC/BgG,EAAM,KAAK,SAAS,CAAA,CAC7B;;;AAOS,aAAAsO,EAAA,MAAS,SAAI,WAFrB5S,EAAA,GAAAL,EAIEsF,GAHK2N,EAAA,MAAS,SAAS,qBAEf8B,EAAA,KAAU,CAAA,GAAA,MAAA,EAAA,KAKP9B,EAAA,MAAS,SAAI,YAAiBA,EAAA,MAAS,eAAU,UAD9D5S,KAAAb,EASM,OATNW,IASM;AAAA,SALJE,EAAA,EAAA,GAAAb,EAIEc,GAAA,MAAAC,EAHuBK,EAAA,OAAK,CAApB2U,GAAOnQ,YADjBpF,EAIEwV,GAAA;AAAA,UAFC,KAAKpQ;AAAA,UACL,MAAMmQ;AAAA,QAAA;YAMEtC,EAAA,MAAS,SAAI,YAAiBA,EAAA,MAAS,eAAU,aAD9D5S,EAAA,GAAAb,EAkBM,OAlBNwF,IAkBM;AAAA,SAdJ3E,EAAA,EAAA,GAAAb,EAaMc,GAAA,MAAAC,EAZmBK,EAAA,OAAK,CAApB2U,GAAOnQ,YADjB5F,EAaM,OAAA;AAAA,UAXH,KAAK4F;AAAA,UACN,OAAM;AAAA,UACL,OAAKqQ,GAAA;AAAA,gCAAmD,OAAAF,EAAkC,QAAI,WAA6BA,EAAkC,OAAmB,KAAK,IAAG,GAAI,KAAK,MAAK,KAAM3U,EAAA,MAAM,MAAM,CAAA;;;UAQzN2D,EAAkCiR,GAAA,EAAf,MAAMD,EAAA,GAAK,MAAA,GAAA,CAAA,MAAA,CAAA;AAAA,QAAA;YAMrBtC,EAAA,MAAS,SAAI,aAAkBA,EAAA,MAAS,eAAU,aAAkBA,EAAA,MAAS,eAAU,YADpG5S,KAAAb,EAiBU,WAjBV6F,IAiBU;AAAA,QAbM8P,EAAA,SAAgBC,EAAA,SAA9B/U,KAAAb,EAKS,UALTkI,IAKS;AAAA,UAJGyN,EAAA,cAAV3V,EAAqF,MAArFsI,IAAqF1H,EAApB+U,EAAA,KAAY,GAAA,CAAA;UACpEC,EAAA,cAAT5V,EAEI,KAFJuI,IAEI3H,EADCgV,EAAA,KAAkB,GAAA,CAAA;;QAGzB3V,EAMM,OANNuI,IAMM;AAAA,WALJ3H,EAAA,EAAA,GAAAb,EAIEc,GAAA,MAAAC,EAHuBK,EAAA,OAAK,CAApB2U,GAAOnQ,YADjBpF,EAIEwV,GAAA;AAAA,YAFC,KAAKpQ;AAAA,YACL,MAAMmQ;AAAA,UAAA;;YAOAtC,EAAA,MAAS,SAAI,YAAiBA,EAAA,MAAS,eAAU,UAD9D5S,EAAA,GAAAb,EAuBM,OAvBNyM,IAuBM;AAAA,QAnBJxM,EAWK,MAXL6P,IAWK;AAAA,WAVHjP,EAAA,EAAA,GAAAb,EASKc,GAAA,MAAAC,EARkB+U,EAAA,OAAQ,CAArBI,GAAKtQ,YADf5F,EASK,MAAA;AAAA,YAPF,KAAKkW,EAAI,OAAOtQ;AAAA,YAChB,OAAKG,EAAA;AAAA;cAA0F,EAAA,oCAAAH,MAAQiQ,EAAA,MAAA;AAAA,YAAU;aAK/GjV,EAAAsV,EAAI,KAAK,GAAA,CAAA;;QAGhBjW,EAMM,OANNkW,IAMM;AAAA,kBALJnW,EAIEc,GAAA,MAAAC,EAHuB+U,QAASD,EAAA,KAAU,GAAG,SAAK,CAAA,GAAA,CAA1CE,GAAOnQ,YADjBpF,EAIEwV,GAAA;AAAA,YAFC,KAAKpQ;AAAA,YACL,MAAMmQ;AAAA,UAAA;;kBAKbvV,EAAmF4V,IAAA;AAAA;QAA7D,MAAMhR,EAAA,KAAK;AAAA,QAAO,MAAOA,EAAA,KAAK;AAAA,MAAA;;;ICnKhDiR,4BAA0D,uBAAuB;AAEhF,SAASC,GAAcC,GAAuC;AACnE,EAAAC,GAAQH,IAAWE,CAAM;AAC3B;AAEO,SAASE,KAAqC;AACnD,QAAM1M,IAAI2M,GAAOL,EAAS;AAC1B,MAAI,CAACtM;AACH,UAAM,IAAI,MAAM,qDAAqD;AAEvE,SAAOA;AACT;AAEO,SAAS4M,KAA+C;AAC7D,SAAOD,GAAOL,IAAW,IAAI;AAC/B;;;;;;;;;;;;;ACQA,UAAMlR,IAAQC,GAKR2O,IAAOnD,GAAA,GACPrH,IAAWD,GAAA,GACX1E,IAASC,GAAA;AAGf,IAAAyR,GAAcvC,EAAK,KAAK;AAExB,UAAMjF,IAAe3P,EAAS,MAAMoK,EAAS,YAAYpE,EAAM,IAAI,CAAC,GAC9D+O,IAAc/U;AAAA,MAClB,MAAM2P,EAAa,OAAO,UAAU,CAAA;AAAA,IAAC,GAEjCqF,IAAahV;AAAA,MACjB,MAAM,GAAG2P,EAAa,OAAO,SAAS3J,EAAM,IAAI,aAAaA,EAAM,EAAE;AAAA,IAAA;AAGvE,IAAAqH,GAAU,YAAY;AACpB,MAAIjD,EAAS,aAAa,QACxB,MAAMA,EAAS,KAAA,EAAO,MAAM,MAAA;AAAA,OAAe,GAE7C,MAAMwK,EAAK,KAAK5O,EAAM,MAAMA,EAAM,IAAI,MAAM,EAAE,MAAM,MAAA;AAAA,OAAe;AAAA,IACrE,CAAC,GAED0D;AAAA,MACE,MAAM,CAAC1D,EAAM,MAAMA,EAAM,EAAE;AAAA,MAC3B,OAAO,CAAC8E,GAAGjI,CAAE,MAAM;AACjB,cAAM+R,EAAK,KAAK9J,GAAGjI,GAAI,MAAM,EAAE,MAAM,MAAA;AAAA,SAAe;AAAA,MACtD;AAAA,IAAA;AAGF,aAAS4U,IAAe;AACtB,UAAI,CAACzR,EAAM,eAAe;AACxB,QAAAP,EACG,KAAK,MAAMO,EAAM,IAAI,IAAIA,EAAM,EAAE,OAAO,EACxC,MAAM,MAAA;AAAA,SAAe;AACxB;AAAA,MACF;AACA,MAAAP,EACG,KAAK,EAAE,MAAMO,EAAM,eAAe,QAAQ,EAAE,IAAIA,EAAM,KAAG,CAAG,EAC5D,MAAM,MAAA;AAAA,OAAe;AAAA,IAC1B;AAEA,mBAAesP,IAA0B;AACvC,MAAK,QAAQ,iBAAiB,MAC9B,MAAMV,EAAK,QAAA,EAAU,MAAM,MAAA;AAAA,OAAe,GACrCA,EAAK,YACRnP,EAAO,KAAK,EAAE,MAAMO,EAAM,gBAAgB,EAAE,MAAM,MAAA;AAAA,OAAe;AAAA,IAErE;sBAIEtE,EAAA,GAAAb,EAsCU,WAtCVW,IAsCU;AAAA,MArCRV,EAeS,UAfTuF,IAeS;AAAA,QAdPvF,EAEM,OAFN4F,IAEM;AAAA,UADJ5F,EAAmD,MAAnDiI,IAAmDtH,EAAlBuT,EAAA,KAAU,GAAA,CAAA;AAAA,QAAA;QAE7ClU,EAUM,OAVNqI,IAUM;AAAA,UATJvD,EAAoEtE,EAAA4J,CAAA,GAAA;AAAA,YAAzD,SAAQ;AAAA,YAAS,SAAOuM;AAAA,UAAA;uBAAQ,MAAa,CAAA,GAAA3R,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,gBAAb,iBAAa,EAAA;AAAA,YAAA;;;UACxDF,EAOYtE,EAAA4J,CAAA,GAAA;AAAA,YANV,SAAQ;AAAA,YACP,SAAS5J,EAAAsT,CAAA,EAAK;AAAA,YACd,UAAUtT,EAAAsT,CAAA,EAAK;AAAA,YACf,SAAOU;AAAA,UAAA;uBACT,MAED,CAAA,GAAAxP,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,gBAFC,aAED,EAAA;AAAA,YAAA;;;;;MAKIxE,EAAAsT,CAAA,EAAK,iBADbvT,EAOWC,EAAAuK,CAAA,GAAA;AAAA;QALT,SAAQ;AAAA,QACR,OAAM;AAAA,QACN,MAAK;AAAA,MAAA;mBAEL,MAA0D;AAAA,cAAvDvK,EAAAsT,CAAA,EAAK,OAAO,WAAO,6BAAA,GAAA,CAAA;AAAA,QAAA;;;MAGbtT,EAAAsT,CAAA,EAAK,WAAhBlT,KAAAb,EAEM,OAFNuI,IAEM;AAAA,cADJvI,EAAqDc,GAAA,MAAAC,EAA5B,GAAC,CAAN4F,MAApB5B,EAAqDtE,EAAAyP,EAAA,GAAA;AAAA,UAAxB,KAAKvJ;AAAA,UAAG,QAAO;AAAA,QAAA;kBAG9CnG,EAMUC,EAAA2J,CAAA,GAAA;AAAA;QANM,SAAQ;AAAA,QAAK,OAAM;AAAA,MAAA;mBAE/B,MAAkC;AAAA,WADpCvJ,EAAA,EAAA,GAAAb,EAIEc,GAAA,MAAAC,EAHsBmT,EAAA,OAAW,CAAzBU,GAAMhP,YADhBpF,EAIEqW,IAAA;AAAA,YAFC,KAAKjR;AAAA,YACL,MAAAgP;AAAA,UAAA;;;;;;;;;;;;;;;;;;;;;;;;AC7FT,UAAMzP,IAAQC,GAMRC,IAAOC,GAYPX,IAAOrB,EAAA,GACP9D,IAAQX,GAAA,GACRuB,IAASF,GAAA,GAET4W,IAAW;AAAA,MACf,EAAE,IAAI,WAAW,OAAO,YAAY,MAAM,OAAA;AAAA,MAC1C,EAAE,IAAI,YAAY,OAAO,gBAAgB,MAAM,SAAA;AAAA,MAC/C,EAAE,IAAI,UAAU,OAAO,cAAc,MAAM,MAAA;AAAA,MAC3C,EAAE,IAAI,YAAY,OAAO,UAAU,MAAM,UAAA;AAAA,IAAU,GAG/CC,IAAe/X,EAAImG,EAAM,OAAO;AACtC,aAAS6R,EAAchV,GAAkB;AACvC,MAAA+U,EAAa,QAAQ/U,GACrBqD,EAAK,kBAAkBrD,CAAE;AAAA,IAC3B;AAGA,UAAMiV,IAAUjY,EAAI;AAAA,MAClB,MAAM2F,EAAK,MAAM,QAAQ;AAAA,MACzB,OAAOA,EAAK,MAAM,SAAS;AAAA,MAC3B,QAAQvE,EAAO;AAAA,MACf,OAAOZ,EAAM;AAAA,IAAA,CACd,GAEK0X,IAAgB/X;AAAA,MAAS,MAC7BiB,EAAO,UAAU,IAAI,CAAC+W,OAAO,EAAE,OAAOA,GAAG,OAAOA,EAAE,YAAA,IAAgB;AAAA,IAAA,GAE9DC,IAAejY;AAAA,MAAS,MAC5BK,EAAM,UAAU,IAAI,CAAC2P,OAAO,EAAE,OAAOA,GAAG,OAAOA,MAAM,SAAS,WAAWA,MAAM,UAAU,YAAYA,IAAI;AAAA,IAAA;AAG3G,aAASqF,IAAe;AACtB,MAAAnP,EAAK,QAAQ,EAAE,GAAG4R,EAAQ,OAAO;AAAA,IACnC;AAEA,aAASI,IAAwB;AAC/B,MAAAhS,EAAK,gBAAgB;AAAA,IACvB;AAEA,aAASiS,IAAqB;AAC5B,MAAAjS,EAAK,oBAAoB;AAAA,IAC3B;AAEA,aAASkS,IAAwB;AAC/B,MAAAlS,EAAK,uBAAuB;AAAA,IAC9B;AAEA,UAAMmS,IAASrY,EAAS,MAAM,EAAQwF,EAAK,MAAM,gBAAiB;sBAIhE9D,EAAA,GAAAb,EA6HU,WA7HVW,IA6HU;AAAA,MA5HRV,EAKS,UALTuF,IAKS;AAAA,QAJPvF,EAGM,OAHN4F,IAGM;AAAA,UAFJ5F,EAA8C,MAA9CiI,IAA8CtH,EAAbwE,EAAA,KAAK,GAAA,CAAA;AAAA,UACtCnF,EAAmD,OAAnDqI,IAAmD1H,EAAjBwE,EAAA,QAAQ,GAAA,CAAA;AAAA,QAAA;;MAI9CnF,EAoHM,OApHNsI,IAoHM;AAAA,QAnHJtI,EAcM,OAdNuI,IAcM;AAAA,gBAbJxI,EAYSc,GAAA,MAAAC,EAXQ+V,GAAQ,CAAhB7U,MADThC,EAYS,UAAA;AAAA,YAVN,KAAKgC,EAAK;AAAA,YACX,MAAK;AAAA,YACJ,OAAK8D,EAAA;AAAA;mDAA4FgR,EAAA,UAAiB9U,EAAK,GAAA;AAAA,YAAE;YAIzH,SAAK,CAAAhB,MAAE+V,EAAc/U,EAAK,EAAE;AAAA,UAAA;YAE7BhC,EAA+D,QAAA;AAAA,cAAzD,OAAM;AAAA,cAA2B,aAAWgC,EAAK;AAAA,YAAA;YACvDhC,EAA6B,QAAA,MAAAW,EAApBqB,EAAK,KAAK,GAAA,CAAA;AAAA,UAAA;;QAIvBhC,EAkGM,OAlGNkW,IAkGM;AAAA,UAhGWY,EAAA,UAAY,kBAA3BvW,EAkDUC,EAAA2J,CAAA,GAAA;AAAA;YAlDiC,SAAQ;AAAA,UAAA;uBACjD,MAES;AAAA,8BAFTnK,EAES,UAAA,EAFD,OAAM,4BAAwB;AAAA,gBACpCA,EAAkD,MAAA,EAA9C,OAAM,4BAAA,GAA4B,SAAO;AAAA,cAAA;cAG/CA,EAgBM,OAhBNgQ,IAgBM;AAAA,gBAfJlL,EAIEtE,EAAAuE,EAAA,GAAA;AAAA,kBAHC,KAAKvE,EAAAkE,CAAA,EAAK,MAAM,UAAU;AAAA,kBAC1B,MAAMlE,EAAAkE,CAAA,EAAK,MAAM,QAAI;AAAA,kBACtB,MAAK;AAAA,gBAAA;gBAEP1E,EAKM,OALNoQ,IAKM;AAAA,kBAJJpQ,EAAwE,OAAxEqQ,IAAwE1P,EAA/BH,KAAK,MAAM,QAAI,GAAA,GAAA,CAAA;AAAA,kBACxDR,EAEM,OAFNwQ,IAEM7P,EADDH,KAAK,MAAM,SAAK,GAAA,GAAA,CAAA;AAAA,gBAAA;gCAGvBR,EAAsB,OAAA,EAAjB,OAAA,EAAA,MAAA,IAAA,EAAA,GAAc,MAAA,EAAA;AAAA,gBACnB8E,EAEYtE,EAAA4J,CAAA,GAAA;AAAA,kBAFD,SAAQ;AAAA,kBAAQ,MAAK;AAAA,kBAAM,SAAOgN;AAAA,gBAAA;6BAAiB,MAE9D,CAAA,GAAApS,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,sBAF8D,cAE9D,EAAA;AAAA,kBAAA;;;;cAGFhF,EAsBM,OAtBNwX,IAsBM;AAAA,gBArBJ1S,EAIEtE,EAAAwK,EAAA,GAAA;AAAA,kBAHS,YAAAgM,EAAA,MAAQ;AAAA,kBAAR,uBAAAhS,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA,CAAAhE,MAAAgW,EAAA,MAAQ,OAAIhW;AAAA,kBACrB,OAAM;AAAA,kBACN,MAAK;AAAA,gBAAA;gBAEP8D,EAKEtE,EAAAwK,EAAA,GAAA;AAAA,kBAJS,YAAAgM,EAAA,MAAQ;AAAA,kBAAR,uBAAAhS,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA,CAAAhE,MAAAgW,EAAA,MAAQ,QAAKhW;AAAA,kBACtB,OAAM;AAAA,kBACN,MAAK;AAAA,kBACL,MAAK;AAAA,gBAAA;gBAEP8D,EAIEtE,EAAAiX,EAAA,GAAA;AAAA,kBAHS,YAAAT,EAAA,MAAQ;AAAA,kBAAR,uBAAAhS,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA,CAAAhE,MAAAgW,EAAA,MAAQ,SAAMhW;AAAA,kBACtB,SAASiW,EAAA;AAAA,kBACV,OAAM;AAAA,gBAAA;gBAERnS,EAIEtE,EAAAiX,EAAA,GAAA;AAAA,kBAHS,YAAAT,EAAA,MAAQ;AAAA,kBAAR,uBAAAhS,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA,CAAAhE,MAAAgW,EAAA,MAAQ,QAAKhW;AAAA,kBACrB,SAASmW,EAAA;AAAA,kBACV,OAAM;AAAA,gBAAA;;cAIVnX,EAES,UAFTyQ,IAES;AAAA,gBADP3L,EAAkEtE,EAAA4J,CAAA,GAAA;AAAA,kBAAvD,SAAQ;AAAA,kBAAW,SAAOmK;AAAA,gBAAA;6BAAQ,MAAS,CAAA,GAAAvP,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,sBAAT,aAAS,EAAA;AAAA,kBAAA;;;;;;gBAKtC8R,EAAA,UAAY,mBAAhCvW,EAgCUC,EAAA2J,CAAA,GAAA;AAAA;YAhCuC,SAAQ;AAAA,UAAA;uBACvD,MAKS;AAAA,cALTnK,EAKS,UALT0X,IAKS;AAAA,gBAJP1S,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAAhF,EAAuE,MAAA,EAAnE,OAAM,4BAAA,GAA4B,gCAA4B,EAAA;AAAA,gBAClE8E,EAEWtE,EAAAkU,EAAA,GAAA;AAAA,kBAFA,SAAS6C,EAAA,QAAM,YAAA;AAAA,gBAAA;6BACxB,MAAuC;AAAA,wBAApCA,EAAA,QAAM,aAAA,WAAA,GAAA,CAAA;AAAA,kBAAA;;;;cAIJA,EAAA,cAATxX,EAEI,KAFJ4X,IAA6C,2EAE7C,WACA5X,EAEI,KAFJ6X,IAAsC,oDAEtC;AAAA,cAEA5X,EAgBS,UAhBT6X,IAgBS;AAAA,gBAfSN,EAAA,cAAhBxX,EAOWc,GAAA,EAAA,KAAA,KAAA;AAAA,kBANTiE,EAEYtE,EAAA4J,CAAA,GAAA;AAAA,oBAFD,SAAQ;AAAA,oBAAQ,MAAK;AAAA,oBAAM,SAAOkN;AAAA,kBAAA;+BAAiB,MAE9D,CAAA,GAAAtS,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,wBAF8D,2BAE9D,EAAA;AAAA,oBAAA;;;kBACAF,EAEYtE,EAAA4J,CAAA,GAAA;AAAA,oBAFD,SAAQ;AAAA,oBAAS,MAAK;AAAA,oBAAM,SAAOiN;AAAA,kBAAA;+BAAc,MAE5D,CAAA,GAAArS,EAAA,EAAA,MAAAA,EAAA,EAAA,IAAA;AAAA,wBAF4D,mBAE5D,EAAA;AAAA,oBAAA;;;0BAGAQ,EAIOC,oCAJP,MAIO;AAAA,kBAHLX,EAEYtE,EAAA4J,CAAA,GAAA;AAAA,oBAFD,SAAQ;AAAA,oBAAU,UAAA;AAAA,kBAAA;+BAAS,MAEtC,CAAA,GAAApF,EAAA,EAAA,MAAAA,EAAA,EAAA,IAAA;AAAA,wBAFsC,mCAEtC,EAAA;AAAA,oBAAA;;;;;;;gBAORQ,EAOOC,UAPaqR,EAAA,OAAY;AAAA;YAAG,SAASA,EAAA;AAAA,UAAA,GAA5C,MAOO;AAAA,YANLhS,EAKUtE,EAAA2J,CAAA,GAAA,EALD,SAAQ,QAAI;AAAA,yBACnB,MAGI;AAAA,gBAHJnK,EAGI,KAHJ8X,IAA+B,eACpBnX,EAAGmW,EAAA,KAAY,IAAG,yEACUnW,EAAGmW,EAAA,KAAY,IAAG,MACzD,CAAA;AAAA,cAAA;;;;;;;;ICvMNiB,KAAU9F,GAAA,GAEH+F,KAAiBD,GAAQ,UACzBE,KAAYF,GAAQ,KACpBG,KAAYH,GAAQ,KACpBI,KAAcJ,GAAQ,MACtBK,KAAsBL,GAAQ,OAC9BM,KAAkBN,GAAQ;;;;;;2BCnBrCxX,EAGWC,EAAAuK,CAAA,GAAA,EAHD,SAAQ,aAAS;AAAA,MACd,SAAM,MAAwB;AAAA,QAAxB9J,EAAA,+BAA2BkE,EAAA,IAAI,GAAA,CAAA;AAAA,MAAA;iBAAc,MACxC;AAAA,0BADwC,2BACxC,EAAA;AAAA,QAAAnF,EAAwD,QAAA,MAAlD,qBAAgBW,EAAGwE,EAAA,IAAI,IAAG,qBAAiB,CAAA;AAAA,0BAAO,MAChF,EAAA;AAAA,MAAA;;;;;;;;;;ACIF,UAAMD,IAAQC,GAER8N,IAAY/T,EAAS,MAAM+Y,GAAU/S,EAAM,KAAK,IAAI,CAAC,GACrDoT,IAAcpZ,EAAS,MAAM;AACjC,YAAM,EAAE,MAAMiU,GAAO,MAAMoF,GAAO,GAAGnF,EAAA,IAASlO,EAAM;AACpD,aAAOkO;AAAA,IACT,CAAC;qBAIkCH,EAAA,cAAjC1S,EAAmEsF,GAAnDoN,EAAA,KAAS,GAAAI,GAAAC,GAAA,EAAA,KAAA,KAA2BgF,EAAA,KAAW,CAAA,GAAA,MAAA,EAAA,WAC/D/X,EAA0CiY,IAAA;AAAA;MAAnB,MAAMrT,EAAA,KAAK;AAAA,IAAA;;;;;;;;;;;;;;ACMpC,UAAMD,IAAQC,GAORmE,IAAWD,GAAA,GAEXoP,IAAYvZ,EAAmC,MAC/C,CAACgG,EAAM,QAAQ,CAACoE,EAAS,WAAiB,OAC3BA,EAAS,SAAS,YAClB,KAAK,CAACoP,MAAMA,EAAE,SAASxT,EAAM,IAAI,KAAK,IAC1D,GAEKyT,IAAkBzZ,EAAuB,MACzCgG,EAAM,UAAgBA,EAAM,UAC5BuT,EAAU,QAAcA,EAAU,MAAM,WAAW,CAAA,IAChD,CAAA,CACR,GAEKG,IAAgB1Z;AAAA,MACpB,MAAMgG,EAAM,SAASuT,EAAU,OAAO,SAAS;AAAA,IAAA,GAE3CI,IAAmB3Z;AAAA,MACvB,MAAMgG,EAAM,YAAYuT,EAAU,OAAO,eAAe;AAAA,IAAA;AAG1D,aAASK,EAAQC,GAAuB;AACtC,YAAM/O,IAAI,OAAO+O,EAAE,QAAS,WAAWA,EAAE,OAAO;AAChD,aAAO,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI/O,CAAC,CAAC;AAAA,IACpC;sBAIEpJ,EAAA,GAAAb,EAuBU,WAvBVW,IAuBU;AAAA,MAtBRV,EAUS,UAVTuF,IAUS;AAAA,QATPvF,EAKM,OALN4F,IAKM;AAAA,UAJJ5F,EAAsD,MAAtDiI,IAAsDtH,EAArBiY,EAAA,KAAa,GAAA,CAAA;AAAA,UACnCC,EAAA,cAAX9Y,EAEM,OAFNsI,IAEM1H,EADDkY,EAAA,KAAgB,GAAA,CAAA;;QAGvB7Y,EAEM,OAFNsI,IAEM;AAAA,UADJ9C,EAAuBC,EAAA,QAAA,SAAA;AAAA,QAAA;;MAI3BzF,EASM,OATNuI,IASM;AAAA,SARJ3H,EAAA,EAAA,GAAAb,EAOMc,GAAA,MAAAC,EANe6X,EAAA,OAAe,CAA1B,GAAGhT,YADb5F,EAOM,OAAA;AAAA,UALH,KAAK4F;AAAA,UACN,OAAM;AAAA,UACL,gCAA6BmT,EAAQ,CAAC,CAAA,WAAYA,EAAQ,CAAC,CAAA,IAAA;AAAA,QAAA;UAE5DhU,EAA4BkU,IAAA,EAAX,MAAM,EAAA,GAAC,MAAA,GAAA,CAAA,MAAA,CAAA;AAAA,QAAA;;;;;;;;;;;;;;;;;ACvEhC,UAAM9T,IAAQC,GAWR8T,IAA2C;AAAA,MAC/C,SAAS;AAAA,MACT,UAAU;AAAA,MACV,UAAU;AAAA,MACV,SAAS;AAAA,MACT,MAAM;AAAA,IAAA,GAGFC,IAAUha,EAAmB,MAAM+Z,EAAS/T,EAAM,IAAI,CAAC;2BAI3D3E,EASEC,EAAA2Y,EAAA,GAAA;AAAA,MARC,OAAOhU,EAAA;AAAA,MACP,OAAOA,EAAA;AAAA,MACP,QAAQA,EAAA;AAAA,MACR,QAAQA,EAAA;AAAA,MACR,OAAOA,EAAA;AAAA,MACP,WAAWA,EAAA;AAAA,MACX,MAAM+T,EAAA;AAAA,MACN,SAAS/T,EAAA;AAAA,IAAA;;;;;;;;;;;;;;;;;;;;;ACxBd,UAAMD,IAAQC,GAORiU,IAAWla,EAAS,MAAM,KAAK,IAAI,GAAG,GAAGgG,EAAM,KAAK,IAAI,CAACwT,MAAMA,EAAE,KAAK,CAAC,CAAC,GAExEW,IAAOna,EAAS,MAAM;AAE1B,YAAMoa,IAAW,MADP,KAAK,IAAI,GAAGpU,EAAM,KAAK,MAAM;AAEvC,aAAOA,EAAM,KAAK,IAAI,CAACwT,GAAGhS,OAAO;AAAA,QAC/B,OAAOgS,EAAE;AAAA,QACT,OAAOA,EAAE;AAAA,QACT,GAAGhS,IAAI4S,IAAWA,IAAW;AAAA,QAC7B,OAAOA,IAAW;AAAA,QAClB,WAAYZ,EAAE,QAAQU,EAAS,QAAS;AAAA,MAAA,EACxC;AAAA,IACJ,CAAC;2BAIC7Y,EA6BUC,EAAA2J,CAAA,GAAA;AAAA,MA7BD,SAAQ;AAAA,MAAK,OAAM;AAAA,IAAA;iBAC1B,MAGS;AAAA,QAHKhF,EAAA,SAASA,EAAA,eAAvBvE,KAAAb,EAGS,UAHTW,IAGS;AAAA,UAFGyE,EAAA,cAAVpF,EAA6D,MAA7DwF,IAA6D5E,EAAbwE,EAAA,KAAK,GAAA,CAAA;UAC5CA,EAAA,oBAATpF,EAAsE,KAAtE6F,IAAsEjF,EAAlBwE,EAAA,WAAW,GAAA,CAAA;;cAEjEpF,EAuBM,OAAA;AAAA,UAtBJ,OAAM;AAAA,UACL,oBAAoBoF,EAAA,MAAM;AAAA,UAC3B,qBAAoB;AAAA,UACnB,QAAQA,EAAA;AAAA,UACT,OAAM;AAAA,UACN,MAAK;AAAA,UACJ,cAAYA,EAAA,SAAK;AAAA,QAAA;WAElBvE,EAAA,EAAA,GAAAb,EAaOc,GAAA,MAAAC,EAZgBuY,EAAA,OAAI,CAAjBE,GAAK5T,YADf5F,EAaO,QAAA;AAAA,YAXJ,KAAK4F;AAAA,YACL,GAAG4T,EAAI;AAAA,YACP,GAAGpU,EAAA,SAAUoU,EAAI,kBAAmBpU,EAAA;AAAA,YACpC,OAAOoU,EAAI;AAAA,YACX,QAASA,EAAI,kBAAmBpU,EAAA;AAAA,YAChC,MAAMA,EAAA;AAAA,YACP,IAAG;AAAA,YACF,cAAYoU,EAAI;AAAA,YAChB,cAAYA,EAAI;AAAA,UAAA;YAEjBvZ,EAA+C,SAAA,MAAAW,EAArC4Y,EAAI,KAAK,IAAG,OAAE5Y,EAAG4Y,EAAI,KAAK,GAAA,CAAA;AAAA,UAAA;;;;;;;;;;;;;;;;ACpD5C,UAAMrU,IAAQC,GAIRqU,IAAU;AAAA,MACd;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA,GAGIC,IAAQva,EAAS,MAAMgG,EAAM,KAAK,OAAO,CAAC8E,GAAG0P,MAAM1P,IAAI0P,EAAE,OAAO,CAAC,KAAK,CAAC,GAEvEC,IAASza,EAAS,MAAM;AAC5B,UAAI0a,IAAa;AACjB,aAAO1U,EAAM,KAAK,IAAI,CAAC8E,GAAGrE,MAAQ;AAChC,cAAMkU,IAAcD,IAAaH,EAAM,QAAS,IAAI,KAAK;AACzD,QAAAG,KAAc5P,EAAE;AAChB,cAAM8P,IAAYF,IAAaH,EAAM,QAAS,IAAI,KAAK,IAEjD3P,IAAI,IACJiQ,IAAK,IACLC,IAAK,IAELC,IAAKF,IAAKjQ,IAAI,KAAK,IAAI+P,IAAa,KAAK,KAAK,CAAC,GAC/CK,IAAKF,IAAKlQ,IAAI,KAAK,IAAI+P,IAAa,KAAK,KAAK,CAAC,GAC/CM,IAAKJ,IAAKjQ,IAAI,KAAK,IAAIgQ,IAAW,KAAK,KAAK,CAAC,GAC7CM,IAAKJ,IAAKlQ,IAAI,KAAK,IAAIgQ,IAAW,KAAK,KAAK,CAAC,GAE7CO,IAAWP,IAAWD,IAAa,KAAK,KAAK,IAAI,GAEjDS,IAAOpV,EAAM,KAAK,WAAW,IAC/B,KAAK6U,IAAKjQ,CAAC,IAAIkQ,CAAE,MAAMlQ,CAAC,IAAIA,CAAC,UAAUA,IAAI,CAAC,QAAQA,CAAC,IAAIA,CAAC,UAAU,CAACA,IAAI,CAAC,OAC1E,KAAKiQ,CAAE,IAAIC,CAAE,MAAMC,CAAE,IAAIC,CAAE,MAAMpQ,CAAC,IAAIA,CAAC,MAAMuQ,CAAQ,MAAMF,CAAE,IAAIC,CAAE;AAEvE,eAAO;AAAA,UACL,GAAGpQ;AAAA,UACH,MAAAsQ;AAAA,UACA,OAAOtQ,EAAE,SAASwP,EAAQ7T,IAAM6T,EAAQ,MAAM;AAAA,UAC9C,MAAOxP,EAAE,QAAQyP,EAAM,QAAS,KAAK,QAAQ,CAAC;AAAA,QAAA;AAAA,MAElD,CAAC;AAAA,IACH,CAAC;2BAIClZ,EAwBUC,EAAA2J,CAAA,GAAA;AAAA,MAxBD,SAAQ;AAAA,MAAK,OAAM;AAAA,IAAA;iBAC1B,MAES;AAAA,QAFKhF,EAAA,SAAdvE,EAAA,GAAAb,EAES,UAFTW,IAES;AAAA,UADPV,EAAgD,MAAhDuF,IAAgD5E,EAAbwE,EAAA,KAAK,GAAA,CAAA;AAAA,QAAA;QAE1CnF,EAmBM,OAnBN4F,IAmBM;AAAA,gBAlBJ7F,EAUM,OAAA;AAAA,YAVD,SAAQ;AAAA,YAAc,OAAM;AAAA,YAA0B,MAAK;AAAA,YAAO,cAAYoF,EAAA;AAAA,UAAA;aACjFvE,EAAA,EAAA,GAAAb,EAOOc,GAAA,MAAAC,EANc6Y,EAAA,OAAM,CAAjB3P,GAAGrE,YADb5F,EAOO,QAAA;AAAA,cALJ,KAAK4F;AAAA,cACL,GAAGqE,EAAE;AAAA,cACL,MAAMA,EAAE;AAAA,YAAA;cAEThK,EAA0D,iBAAhDgK,EAAE,KAAK,IAAG,OAAErJ,EAAGqJ,EAAE,KAAK,IAAG,OAAErJ,EAAGqJ,EAAE,GAAG,IAAG,MAAE,CAAA;AAAA,YAAA;4BAEpDhK,EAAkE,UAAA;AAAA,cAA1D,IAAG;AAAA,cAAK,IAAG;AAAA,cAAK,GAAE;AAAA,cAAK,MAAK;AAAA,YAAA;;UAEtCA,EAMK,MANLsI,IAMK;AAAA,aALH1H,EAAA,EAAA,GAAAb,EAIKc,GAAA,MAAAC,EAJkB6Y,EAAA,OAAM,CAAjB3P,GAAGrE,YAAf5F,EAIK,MAAA,EAJ2B,KAAK4F,KAAG;AAAA,cACtC3F,EAAyE,QAAA;AAAA,gBAAnE,OAAM;AAAA,gBAA2B,OAAKgW,GAAA,EAAA,YAAgBhM,EAAE,OAAK;AAAA,cAAA;cACnEhK,EAA4D,QAA5DuI,IAA4D5H,EAAjBqJ,EAAE,KAAK,GAAA,CAAA;AAAA,cAClDhK,EAA2D,QAA3DwM,IAA2D7L,EAAhBqJ,EAAE,GAAG,IAAG,KAAC,CAAA;AAAA,YAAA;;;;;;;;;;;;;;;;;;;2BCxE5DzJ,EAKUC,EAAA2J,CAAA,GAAA;AAAA,MALD,SAAQ;AAAA,MAAK,OAAM;AAAA,IAAA;iBAC1B,MAES;AAAA,QAFKhF,EAAA,SAAdvE,EAAA,GAAAb,EAES,UAFTW,IAES;AAAA,UADPV,EAAgD,MAAhDuF,IAAgD5E,EAAbwE,EAAA,KAAK,GAAA,CAAA;AAAA,QAAA;QAE1CL,EAAoEtE,EAAA8P,EAAA,GAAA;AAAA,UAAzD,SAASnL,EAAA;AAAA,UAAU,MAAMA,EAAA;AAAA,UAAO,cAAYA,EAAA;AAAA,QAAA;;;;;;;;;;;;;;;;;;2BCIzD5E,EAKUC,EAAA2J,CAAA,GAAA;AAAA,MALD,SAAQ;AAAA,MAAK,OAAM;AAAA,IAAA;iBAC1B,MAES;AAAA,QAFKhF,EAAA,SAAdvE,EAAA,GAAAb,EAES,UAFTW,IAES;AAAA,UADPV,EAAgD,MAAhDuF,IAAgD5E,EAAbwE,EAAA,KAAK,GAAA,CAAA;AAAA,QAAA;QAE1CL,EAAsEtE,EAAA+Z,EAAA,GAAA;AAAA,UAAzD,MAAMpV,EAAA;AAAA,UAAO,QAAQA,EAAA;AAAA,UAAS,OAAOA,EAAA;AAAA,UAAQ,KAAKA,EAAA;AAAA,QAAA;;;;;;;;;;;;;;;;;;;;;;;;ACRnE,UAAMD,IAAQC,GAcR8T,IAA4C;AAAA,MAChD,SAAS;AAAA,MACT,UAAU;AAAA,MACV,SAAS;AAAA,MACT,UAAU;AAAA,IAAA,GAGNC,IAAUha,EAAoB,MAAM+Z,EAAS/T,EAAM,IAAI,CAAC;2BAI5D3E,EAkBUC,EAAA2J,CAAA,GAAA;AAAA,MAlBD,SAAQ;AAAA,MAAK,OAAM;AAAA,IAAA;iBAC1B,MAES;AAAA,QAFKhF,EAAA,SAAdvE,EAAA,GAAAb,EAES,UAFTW,IAES;AAAA,UADPV,EAAgD,MAAhDuF,IAAgD5E,EAAbwE,EAAA,KAAK,GAAA,CAAA;AAAA,QAAA;QAE1CnF,EAaM,OAbN4F,IAaM;AAAA,UAZJd,EAWEtE,EAAAga,EAAA,GAAA;AAAA,YAVC,OAAOrV,EAAA;AAAA,YACP,KAAKA,EAAA;AAAA,YACL,KAAKA,EAAA;AAAA,YACL,MAAMA,EAAA;AAAA,YACN,QAAQA,EAAA;AAAA,YACR,MAAM+T,EAAA;AAAA,YACN,OAAO/T,EAAA;AAAA,YACP,OAAOA,EAAA;AAAA,YACP,QAAQA,EAAA;AAAA,YACR,WAAWA,EAAA;AAAA,UAAA;;;;;;;;;;;;;;;;2BC3ClB5E,EAKUC,EAAA2J,CAAA,GAAA;AAAA,MALD,SAAQ;AAAA,MAAK,OAAM;AAAA,IAAA;iBAC1B,MAES;AAAA,QAFKhF,EAAA,SAAdvE,EAAA,GAAAb,EAES,UAFTW,IAES;AAAA,UADPV,EAAgD,MAAhDuF,IAAgD5E,EAAbwE,EAAA,KAAK,GAAA,CAAA;AAAA,QAAA;QAE1CnF,EAAsD,OAAtD4F,IAAsDjF,EAAhBwE,EAAA,OAAO,GAAA,CAAA;AAAA,MAAA;;;;;ACT1C,SAASsV,KAA+B;AAC7C,EAAApC,GAAgB;AAAA,IACd,MAAMqC;AAAAA,IACN,aAAaC;AAAAA,IACb,eAAeC;AAAAA,IACf,gBAAgBC;AAAAA,IAChB,SAASC;AAAAA,IACT,OAAOC;AAAAA,IACP,UAAUC;AAAAA,EAAA,CACX;AACH;ACGO,SAASC,GAAaC,GAAgD;AAC3E,SAAOA,EAAI,YAAY;AACzB;AAEO,SAASC,GAAQD,GAAwC;AAC9D,SAAOA,EAAI,YAAY;AACzB;ACGO,SAASE,GAAkBC,GAAkC;AAClE,QAAMC,IAAWC,GAAM,OAAO;AAAA,IAC5B,SAASF,EAAK;AAAA,IACd,iBAAiB;AAAA,IACjB,SAAS;AAAA,MACP,QAAQ;AAAA,MACR,oBAAoB;AAAA,IAAA;AAAA,EACtB,CACD;AAED,EAAIA,EAAK,cACPC,EAAS,SAAS,QAAQ,OAAO,cAAc,IAAID,EAAK,YAEtDA,EAAK,WACPC,EAAS,SAAS,QAAQ,OAAO,gBAAgB,IAAID,EAAK,SAK5DC,EAAS,aAAa,QAAQ,IAAI,CAACE,MAAW;AAC5C,UAAMC,IAAOC,GAAW,YAAY;AACpC,WAAID,KACFD,EAAO,QAAQ,IAAI,gBAAgB,mBAAmBC,CAAI,CAAC,GAEtDD;AAAA,EACT,CAAC,GAGDF,EAAS,aAAa,SAAS;AAAA,IAC7B,CAAClU,MAAa;AACZ,YAAM8T,IAAM9T,EAAS;AACrB,UAAI8T,KAAO,OAAOA,KAAQ,YAAY,aAAaA,GAAK;AACtD,YAAID,GAAUC,CAAG;AAEf,iBAAA9T,EAAS,OAAO8T,EAAI,SACb9T;AAGT,cAAMhE,GAAWgE,EAAS,QAAQ8T,EAAI,OAAO;AAAA,MAC/C;AAEA,aAAO9T;AAAA,IACT;AAAA,IACA,CAAChB,MAAqC;AACpC,UAAIA,EAAM,UAAU;AAClB,cAAMzD,IAASyD,EAAM,SAAS,QACxBxD,IACJwD,EAAM,SAAS,MAAM,WAAW;AAAA,UAC9B,UAAU;AAAA,UACV,SAASA,EAAM;AAAA,QAAA,GAEbuV,IAAWvY,GAAWT,GAAQC,CAAO;AAC3C,eAAI+Y,aAAoB9Y,MACtBwY,EAAK,oBAAA,GAEA,QAAQ,OAAOM,CAAQ;AAAA,MAChC;AAEA,aAAO,QAAQ,OAAO,IAAIzY,GAAakD,EAAM,OAAO,CAAC;AAAA,IACvD;AAAA,EAAA;AAGF,QAAMwV,IAAO,CAAIC,GAA0B9J,GAAayJ,MACtDF,EAASO,CAAM,EAAwB9J,GAAKyJ,CAAM,EAAE,KAAK,CAAC1R,MAAMA,EAAE,IAAI,GAElEgS,IAAW,CACfD,GACA9J,GACAgK,GACAP,MACeF,EAASO,CAAM,EAAwB9J,GAAKgK,GAAMP,CAAM,EAAE,KAAK,CAAC1R,MAAMA,EAAE,IAAI;AAE7F,SAAO;AAAA,IACL,KAAKwR;AAAA,IACL,KAAK,CAAIvJ,GAAayJ,MAAgCI,EAAQ,OAAO7J,GAAKyJ,CAAM;AAAA,IAChF,QAAQ,CAAIzJ,GAAayJ,MAAgCI,EAAQ,UAAU7J,GAAKyJ,CAAM;AAAA,IACtF,MAAM,CAAIzJ,GAAagK,GAAgBP,MACrCM,EAAY,QAAQ/J,GAAKgK,GAAMP,CAAM;AAAA,IACvC,KAAK,CAAIzJ,GAAagK,GAAgBP,MACpCM,EAAY,OAAO/J,GAAKgK,GAAMP,CAAM;AAAA,IACtC,OAAO,CAAIzJ,GAAagK,GAAgBP,MACtCM,EAAY,SAAS/J,GAAKgK,GAAMP,CAAM;AAAA,IACxC,WAAW,CAACrb,MAAyB;AACnC,MAAAmb,EAAS,SAAS,QAAQ,OAAO,gBAAgB,IAAInb;AAAA,IACvD;AAAA,EAAA;AAEJ;AAGA,SAASub,GAAW9T,GAA6B;AAC/C,MAAI,OAAO,WAAa,IAAa,QAAO;AAC5C,QAAMoU,IAAQ,SAAS,OAAO,MAAM,IAAI,OAAO,WAAWC,GAAYrU,CAAI,IAAI,UAAU,CAAC;AACzF,SAAOoU,IAAQA,EAAM,CAAC,IAAI;AAC5B;AAEA,SAASC,GAAYjS,GAAmB;AACtC,SAAOA,EAAE,QAAQ,uBAAuB,MAAM;AAChD;AChEA,SAASkS,GACPC,GACAC,GACU;AACV,QAAMC,IAAOF,EAAS,cAAcC,CAAO;AAC3C,SAAO,OAAOC,KAAS,YAAYA,EAAK,SAAS,IAAI,CAACA,CAAI,IAAI,CAAA;AAChE;AAEA,SAASC,GAAuBtS,GAAyBoS,GAAsC;AAC7F,QAAMC,IAAOrS,EAAE,cAAcoS,CAAO;AACpC,SAAO,OAAOC,KAAS,YAAYA,EAAK,SAAS,IAAI,CAACA,CAAI,IAAI,CAAA;AAChE;AAEA,SAASE,GAAqBvS,GAAiC;AAC7D,SAAI,MAAM,QAAQA,EAAE,UAAU,IAAUA,EAAE,aACtC,OAAOA,EAAE,cAAe,YAAYA,EAAE,WAAW,SAAS,IAAU,CAACA,EAAE,UAAU,IAC9E,CAAA;AACT;AAEA,SAASwS,GACPL,GACAM,GACkB;AAClB,QAAM5S,IAAOsS,EAAS,MAChBO,IAAO,MAAM7S,CAAI;AAEvB,SAAO;AAAA,IACL;AAAA,MACE,MAAM6S;AAAA,MACN,MAAM,kBAAkB7S,CAAI;AAAA,MAC5B,WAAW4S,EAAW;AAAA,MACtB,MAAM;AAAA,QACJ,cAAc;AAAA,QACd,MAAM;AAAA,QACN,MAAA5S;AAAA,QACA,OAAOsS,EAAS;AAAA,QAChB,aAAaD,GAAuBC,GAAU,MAAM;AAAA,MAAA;AAAA,IACtD;AAAA,IAEF;AAAA,MACE,MAAM,GAAGO,CAAI;AAAA,MACb,MAAM,kBAAkB7S,CAAI;AAAA,MAC5B,WAAW4S,EAAW;AAAA,MACtB,MAAM;AAAA,QACJ,cAAc;AAAA,QACd,MAAM;AAAA,QACN,MAAA5S;AAAA,QACA,OAAO,GAAGsS,EAAS,KAAK;AAAA,QACxB,aAAaD,GAAuBC,GAAU,QAAQ;AAAA,MAAA;AAAA,IACxD;AAAA,IAEF;AAAA,MACE,MAAM,GAAGO,CAAI;AAAA,MACb,MAAM,kBAAkB7S,CAAI;AAAA,MAC5B,WAAW4S,EAAW;AAAA,MACtB,MAAM;AAAA,QACJ,cAAc;AAAA,QACd,MAAM;AAAA,QACN,MAAA5S;AAAA,QACA,OAAO,GAAGsS,EAAS,KAAK;AAAA,QACxB,aAAaD,GAAuBC,GAAU,QAAQ;AAAA,MAAA;AAAA,MAExD,OAAO;AAAA,IAAA;AAAA,IAET;AAAA,MACE,MAAM,GAAGO,CAAI;AAAA,MACb,MAAM,kBAAkB7S,CAAI;AAAA,MAC5B,WAAW4S,EAAW;AAAA,MACtB,MAAM;AAAA,QACJ,cAAc;AAAA,QACd,MAAM;AAAA,QACN,MAAA5S;AAAA,QACA,OAAOsS,EAAS;AAAA,QAChB,aAAaD,GAAuBC,GAAU,MAAM;AAAA,MAAA;AAAA,MAEtD,OAAO;AAAA,IAAA;AAAA,EACT;AAEJ;AAEA,SAASQ,GACPC,GACAH,GACgB;AAChB,SAAO;AAAA,IACL,MAAM,YAAYG,EAAO,IAAI;AAAA,IAC7B,MAAM,gBAAgBA,EAAO,IAAI;AAAA,IACjC,WAAWH,EAAW;AAAA,IACtB,MAAM;AAAA,MACJ,cAAc;AAAA,MACd,MAAM;AAAA,MACN,MAAMG,EAAO;AAAA,MACb,OAAOA,EAAO;AAAA,MACd,aAAaL,GAAqBK,CAAM;AAAA,IAAA;AAAA,EAC1C;AAEJ;AAEA,SAASC,GACPnT,GACA+S,GACgB;AAChB,SAAO;AAAA,IACL,MAAM,aAAa/S,EAAS,IAAI;AAAA,IAChC,MAAM,kBAAkBA,EAAS,IAAI;AAAA,IACrC,WAAW+S,EAAW;AAAA,IACtB,MAAM;AAAA,MACJ,cAAc;AAAA,MACd,MAAM;AAAA,MACN,MAAM/S,EAAS;AAAA,MACf,OAAOA,EAAS;AAAA,MAChB,aAAa4S,GAAuB5S,GAAU,MAAM;AAAA,IAAA;AAAA,EACtD;AAEJ;AAQA,SAASoT,GACPrE,GACAgE,GACuB;AACvB,MAAI,OAAOhE,EAAU,QAAS,YAAYA,EAAU,KAAK,WAAW,EAAG,QAAO;AAC9E,QAAM5U,IAAa4U,EAAU,YACvBlV,IAAc,MAAM,QAAQM,CAAU,IACxCA,IACA,OAAOA,KAAe,YAAYA,EAAW,SAAS,IACpD,CAACA,CAAU,IACX,CAAA;AACN,SAAO;AAAA,IACL,MAAM,cAAc4U,EAAU,IAAI;AAAA,IAClC,MAAM,mBAAmBA,EAAU,IAAI;AAAA,IACvC,WAAWgE,EAAW;AAAA,IACtB,MAAM;AAAA,MACJ,cAAc;AAAA,MACd,MAAM;AAAA,MACN,MAAMhE,EAAU;AAAA,MAChB,OAAOA,EAAU,SAAS;AAAA,MAC1B,aAAAlV;AAAA,IAAA;AAAA,EACF;AAEJ;AAEO,SAASwZ,GACdzT,GACAmT,GACkB;AAClB,MAAInT,MAAa,KAAM,QAAO,CAAA;AAE9B,QAAM0T,IAA2B,CAAA;AAEjC,aAAWb,KAAY7S,EAAS;AAC9B,IAAA0T,EAAO,KAAK,GAAGR,GAAoBL,GAAUM,CAAU,CAAC;AAE1D,aAAWG,KAAUtT,EAAS;AAC5B,IAAA0T,EAAO,KAAKL,GAAiBC,GAAQH,CAAU,CAAC;AAElD,aAAWzS,KAAKV,EAAS;AACvB,IAAA0T,EAAO,KAAKH,GAAmB7S,GAAGyS,CAAU,CAAC;AAE/C,aAAW/D,KAAKpP,EAAS,YAA+B;AACtD,UAAM9B,IAAQsV,GAAoBpE,GAAG+D,CAAU;AAC/C,IAAIjV,KAAOwV,EAAO,KAAKxV,CAAK;AAAA,EAC9B;AAEA,SAAOwV;AACT;AC5LO,SAASC,GAAgB5B,IAAyB,IAAiB;AACxE,QAAM6B,IAAiB7B,EAAK,kBAAkB,eACxC8B,IAAqB9B,EAAK,sBAAsB,mBAChD+B,IAAmB/B,EAAK,oBAAoB;AAElD,SAAO,CAACgC,MAAgC;AAEtC,QAAIA,EAAG,SAASH;AACd,aAAO;AAGT,UAAMxY,IAAOrB,EAAA;AAGb,QAFqBga,EAAG,MAAM,iBAAiB,MAE3B,CAAC3Y,EAAK;AACxB,aAAO;AAAA,QACL,MAAMwY;AAAA,QACN,OAAO,EAAE,CAACE,CAAgB,GAAGC,EAAG,SAAA;AAAA,MAAS;AAK7C,QAAI3Y,EAAK;AACP,aAAO;AAAA,QACL,MAAMwY;AAAA,QACN,OAAO,EAAE,CAACE,CAAgB,GAAGC,EAAG,SAAA;AAAA,MAAS;AAK7C,UAAMC,IAAkBD,EAAG,MAAM;AACjC,WAAI,MAAM,QAAQC,CAAe,KAAKA,EAAgB,SAAS,KAEzD,CADY5Y,EAAK,iBAAiB4Y,CAA2B,IAExD,EAAE,MAAMH,EAAA,IAIZ;AAAA,EACT;AACF;AAgBO,SAASI,GACdlC,IAA0B,IACgE;AAC1F,QAAMmC,IAAWnC,EAAK,UAChBoC,IAAQpC,EAAK,SAAS,IACtBqC,IAAWrC,EAAK,YAAY;AAElC,SAAO,CAACgC,MAAO;AACb,QAAI,OAAO,WAAa,IAAa;AACrC,UAAMnO,IAAKmO,EAAG,MAAM,SAAgCK;AACpD,QAAIrT;AACJ,IAAImT,IACFnT,IAAQmT,EAAS,QAAQ,WAAWtO,CAAC,EAAE,QAAQ,WAAWuO,CAAK,IACtDvO,KAAKuO,IACdpT,IAAQ,GAAG6E,CAAC,MAAMuO,CAAK,KAEvBpT,IAAQ6E,KAAKuO,GAEf,SAAS,QAAQpT;AAAA,EACnB;AACF;ACvDA,MAAMsT,KAAwB;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAASC,GAAmBhW,GAAwB;AAClD,SAAI,OAAOA,KAAS,WAAiB,KAC9B+V,GAAsB,KAAK,CAACE,MAAMjW,EAAK,WAAWiW,CAAC,CAAC;AAC7D;AAEO,SAASC,GAAkBzC,GAAuC;AACvE,QAAMqB,IAAOrB,EAAK,QAAQ,UACpB0C,IAAU1C,EAAK,WAAW2C,GAAiBtB,CAAI,GAE/CuB,IAAiC;AAAA,IACrC;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,WAAW5C,EAAK,WAAW;AAAA,MAC3B,MAAM,EAAE,MAAM,QAAQ,OAAO,OAAA;AAAA,IAAO;AAAA,IAEtC;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,WAAWA,EAAK,WAAW;AAAA,MAC3B,MAAM,EAAE,cAAc,IAAM,MAAM,UAAU,OAAO,UAAA;AAAA,IAAU;AAAA,IAE/D;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,WAAWA,EAAK,WAAW;AAAA,MAC3B,MAAM,EAAE,cAAc,IAAM,MAAM,UAAU,OAAO,wBAAA;AAAA,IAAwB;AAAA,EAC7E;AAGF,EAAIA,EAAK,WAAW,WAClB4C,EAAa,KAAK;AAAA,IAChB,MAAM;AAAA,IACN,MAAM;AAAA,IACN,WAAW5C,EAAK,WAAW;AAAA,IAC3B,MAAM,EAAE,cAAc,IAAM,MAAM,UAAU,OAAO,UAAA;AAAA,EAAU,CAC9D,GAGCA,EAAK,WAAW,iBAClB4C,EAAa,KAAK;AAAA,IAChB,MAAM;AAAA,IACN,MAAM;AAAA,IACN,WAAW5C,EAAK,WAAW;AAAA,IAC3B,MAAM,EAAE,cAAc,IAAM,MAAM,UAAU,OAAO,cAAA;AAAA,EAAc,CAClE;AAKH,QAAM6C,IAAgC;AAAA,IACpC,MAAM;AAAA,IACN,MAAM;AAAA,IACN,WAAW7C,EAAK,WAAW;AAAA,IAC3B,MAAM,EAAE,MAAM,UAAU,OAAO,MAAA;AAAA,EAAM,GAGjC1W,IAASwZ,GAAa;AAAA,IAC1B,SAAAJ;AAAA,IACA,QAAQ,CAAC,GAAGE,GAAc,GAAI5C,EAAK,eAAe,CAAA,GAAK6C,CAAa;AAAA,EAAA,CACrE;AAED,SAAAvZ,EAAO,WAAWsY,GAAgB5B,EAAK,SAAS,CAAC,GACjD1W,EAAO,UAAU4Y,GAAiBlC,EAAK,UAAU,CAAC,GAElD1W,EAAO,wBAAwB,CAAC2E,MAAyC;AAEvE,UAAM8U,IAAYzZ,EAAO,UAAA;AACzB,eAAW6C,KAAS4W;AAClB,MAAIR,GAAmBpW,EAAM,IAAI,KAC/B7C,EAAO,YAAY6C,EAAM,IAAc;AAK3C,IAAI7C,EAAO,SAAS,gBAAgB,KAClCA,EAAO,YAAY,gBAAgB;AAGrC,UAAM0Z,IAAUtB,GAAwBzT,GAAU+R,EAAK,UAAU;AACjE,eAAW7T,KAAS6W;AAClB,MAAA1Z,EAAO,SAAS6C,CAAK;AAEvB,IAAA7C,EAAO,SAASuZ,CAAa;AAAA,EAC/B,GAEOvZ;AACT;;;;;;;;;;;;;;;AC/IA,UAAMO,IAAQC,GAWR2O,IAAOwK,GAAA,GACP5V,IAAQxJ,EAAiB,MAAO4U,EAAK,SAAS5O,EAAM,IAAI,KAAmC,EAAE,GAC7FqZ,IAAWrf,EAA6B,MAAM4U,EAAK,OAAO5O,EAAM,IAAI,IAAI,CAAC,CAAC;AAEhF,aAASsZ,EAAS1e,GAAoB;AACpC,MAAAgU,EAAK,SAAS5O,EAAM,MAAMpF,CAAI;AAAA,IAChC;2BAIES,EAaEC,EAAAwK,EAAA,GAAA;AAAA,MAZC,eAAatC,EAAA;AAAA,MACb,MAAMvD,EAAA;AAAA,MACN,OAAOA,EAAA,SAAS;AAAA,MAChB,MAAMA,EAAA,QAAQ;AAAA,MACd,OAAOoZ,EAAA;AAAA,MACP,aAAapZ,EAAA,eAAe;AAAA,MAC5B,UAAUA,EAAA;AAAA,MACV,UAAUA,EAAA;AAAA,MACV,UAAUA,EAAA;AAAA,MACV,MAAMA,EAAA;AAAA,MACN,cAAcA,EAAA,gBAAgB;AAAA,MAC9B,uBAAoBqZ;AAAA,IAAA;;;;;;;;;;;;;;;ACvCzB,UAAMtZ,IAAQC,GAUR2O,IAAOwK,GAAA,GACP5V,IAAQxJ,EAAiB,MAAO4U,EAAK,SAAS5O,EAAM,IAAI,KAAmC,EAAE,GAC7FqZ,IAAWrf,EAA6B,MAAM4U,EAAK,OAAO5O,EAAM,IAAI,IAAI,CAAC,CAAC;AAEhF,aAASsZ,EAAS1e,GAAoB;AACpC,MAAAgU,EAAK,SAAS5O,EAAM,MAAMpF,CAAI;AAAA,IAChC;2BAIES,EAgBeC,EAAAie,EAAA,GAAA;AAAA,MAfZ,OAAOtZ,EAAA,SAAS;AAAA,MAChB,MAAMA,EAAA,QAAQ;AAAA,MACd,OAAOoZ,EAAA;AAAA,MACP,UAAUpZ,EAAA;AAAA,MACV,UAAUA,EAAA;AAAA,IAAA;iBAEX,MAQE;AAAA,QARFL,EAQEtE,EAAAke,EAAA,GAAA;AAAA,UAPC,eAAahW,EAAA;AAAA,UACb,MAAMvD,EAAA;AAAA,UACN,aAAaA,EAAA,eAAe;AAAA,UAC5B,UAAUA,EAAA;AAAA,UACV,UAAUA,EAAA;AAAA,UACV,MAAMA,EAAA;AAAA,UACN,uBAAoBqZ;AAAA,QAAA;;;;;;;;;;;;;;;;;;;;AChC3B,UAAMtZ,IAAQC,GAYR2O,IAAOwK,GAAA,GACP5V,IAAQxJ,EAAwB,MAAM;AAC1C,YAAM+O,IAAI6F,EAAK,SAAS5O,EAAM,IAAI;AAClC,aAAI+I,KAAM,QAA2BA,MAAM,KAAW,OAC/C,OAAOA,KAAM,WAAWA,IAAI,OAAOA,CAAC;AAAA,IAC7C,CAAC,GACKsQ,IAAWrf,EAA6B,MAAM4U,EAAK,OAAO5O,EAAM,IAAI,IAAI,CAAC,CAAC;AAEhF,aAASsZ,EAAS1e,GAA2B;AAC3C,MAAAgU,EAAK,SAAS5O,EAAM,MAAMpF,CAAI;AAAA,IAChC;2BAIES,EAkBeC,EAAAie,EAAA,GAAA;AAAA,MAjBZ,OAAOtZ,EAAA,SAAS;AAAA,MAChB,MAAMA,EAAA,QAAQ;AAAA,MACd,OAAOoZ,EAAA;AAAA,MACP,UAAUpZ,EAAA;AAAA,MACV,UAAUA,EAAA;AAAA,IAAA;iBAEX,MAUE;AAAA,QAVFL,EAUEtE,EAAAme,EAAA,GAAA;AAAA,UATC,eAAajW,EAAA;AAAA,UACb,KAAKvD,EAAA,OAAO;AAAA,UACZ,KAAKA,EAAA,OAAO;AAAA,UACZ,MAAMA,EAAA,QAAQ;AAAA,UACd,aAAaA,EAAA,eAAe;AAAA,UAC5B,UAAUA,EAAA;AAAA,UACV,UAAUA,EAAA;AAAA,UACV,MAAMA,EAAA;AAAA,UACN,uBAAoBqZ;AAAA,QAAA;;;;;;;;;;;;;;;;;;;;ACpC3B,UAAMtZ,IAAQC,GAWR2O,IAAOwK,GAAA,GACP5V,IAAQxJ,EAAiC,MAAM;AACnD,YAAM+O,IAAI6F,EAAK,SAAS5O,EAAM,IAAI;AAClC,aAAI+I,KAAM,QAA2BA,MAAM,KAAW,OAC/CA;AAAA,IACT,CAAC,GACKsQ,IAAWrf,EAA6B,MAAM4U,EAAK,OAAO5O,EAAM,IAAI,IAAI,CAAC,CAAC;AAEhF,aAASsZ,EAAS1e,GAAoC;AACpD,MAAAgU,EAAK,SAAS5O,EAAM,MAAMpF,CAAI;AAAA,IAChC;2BAIES,EAiBeC,EAAAie,EAAA,GAAA;AAAA,MAhBZ,OAAOtZ,EAAA,SAAS;AAAA,MAChB,MAAMA,EAAA,QAAQ;AAAA,MACd,OAAOoZ,EAAA;AAAA,MACP,UAAUpZ,EAAA;AAAA,MACV,UAAUA,EAAA;AAAA,IAAA;iBAEX,MASE;AAAA,QATFL,EASEtE,EAAAiX,EAAA,GAAA;AAAA,UARC,eAAa/O,EAAA;AAAA,UACb,SAASvD,EAAA;AAAA,UACT,aAAaA,EAAA,eAAe;AAAA,UAC5B,UAAUA,EAAA;AAAA,UACV,YAAYA,EAAA;AAAA,UACZ,WAAWA,EAAA;AAAA,UACX,MAAMA,EAAA;AAAA,UACN,uBAAoBqZ;AAAA,QAAA;;;;;;;;;;;;;;;;AClD3B,UAAMtZ,IAAQC,GAQR2O,IAAOwK,GAAA,GACPM,IAAU1f,EAAkB,MAAM,EAAQ4U,EAAK,SAAS5O,EAAM,IAAI,CAAE,GACpEqZ,IAAWrf,EAA6B,MAAM4U,EAAK,OAAO5O,EAAM,IAAI,IAAI,CAAC,CAAC;AAEhF,aAASsZ,EAAS1e,GAAqB;AACrC,MAAAgU,EAAK,SAAS5O,EAAM,MAAMpF,CAAI;AAAA,IAChC;2BAIES,EAeeC,EAAAie,EAAA,GAAA;AAAA,MAdZ,OAAOtZ,EAAA,SAAS;AAAA,MAChB,MAAMA,EAAA,QAAQ;AAAA,MACd,OAAOoZ,EAAA;AAAA,MACP,UAAUpZ,EAAA;AAAA,MACV,UAAUA,EAAA;AAAA,IAAA;iBAEX,MAOc;AAAA,QAPdL,EAOctE,EAAAyK,EAAA,GAAA;AAAA,UANX,eAAa2T,EAAA;AAAA,UACb,UAAUzZ,EAAA;AAAA,UACV,MAAMA,EAAA;AAAA,UACN,uBAAoBqZ;AAAA,QAAA;qBAErB,MAAyD;AAAA,YAAzCrZ,EAAA,oBAAhBpF,EAAyDc,GAAA,EAAA,KAAA,KAAA;AAAA,kBAAzBsE,EAAA,WAAW,GAAA,CAAA;AAAA,YAAA;;;;;;;;;;;;;;;;;;;;;ACxBjD,UAAMD,IAAQC,GAUR2O,IAAOwK,GAAA,GACP5V,IAAQxJ,EAAwB,MAAM;AAC1C,YAAM+O,IAAI6F,EAAK,SAAS5O,EAAM,IAAI;AAClC,aAAO+I,KAAM,QAA2BA,MAAM,KAAK,OAAO,OAAOA,CAAC;AAAA,IACpE,CAAC,GACKsQ,IAAWrf,EAA6B,MAAM4U,EAAK,OAAO5O,EAAM,IAAI,IAAI,CAAC,CAAC;AAEhF,aAASsZ,EAAS1e,GAA2B;AAC3C,MAAAgU,EAAK,SAAS5O,EAAM,MAAMpF,CAAI;AAAA,IAChC;2BAIES,EAeeC,EAAAie,EAAA,GAAA;AAAA,MAdZ,OAAOtZ,EAAA,SAAS;AAAA,MAChB,MAAMA,EAAA,QAAQ;AAAA,MACd,OAAOoZ,EAAA;AAAA,MACP,UAAUpZ,EAAA;AAAA,MACV,UAAUA,EAAA;AAAA,IAAA;iBAEX,MAOE;AAAA,QAPFL,EAOEtE,EAAAqe,EAAA,GAAA;AAAA,UANC,eAAanW,EAAA;AAAA,UACb,KAAKvD,EAAA,OAAO;AAAA,UACZ,KAAKA,EAAA,OAAO;AAAA,UACZ,UAAUA,EAAA;AAAA,UACV,MAAMA,EAAA;AAAA,UACN,uBAAoBqZ;AAAA,QAAA;;;;;;;;;;;;2BCxCzBje,EAEWC,EAAAse,EAAA,GAAA;AAAA,MAFD,WAAU;AAAA,MAAU,KAAK3Z,EAAA;AAAA,MAAK,OAAM;AAAA,IAAA;iBAC5B,MAA6B;AAAA,SAA7CvE,EAAA,EAAA,GAAAb,EAAyEc,GAAA,MAAAC,EAAlCqE,EAAA,OAAK,CAApB2Q,GAAOnQ,YAA/BpF,EAAyEqU,IAAA;AAAA,UAA1B,KAAKjP;AAAA,UAAM,MAAMmQ;AAAA,QAAA;;;;;;;;;;;;;ACApE,UAAM5Q,IAAQC,GAKR4Z,IAAc7f,EAAS,MACvBgG,EAAM,MAAM,WAAW,IAAUA,EAAM,OACpC,KAAK,IAAI,GAAG,KAAK,MAAMA,EAAM,OAAOA,EAAM,MAAM,MAAM,CAAC,CAC/D;AAED,aAAS4T,EAAQ9W,GAA0B;AACzC,YAAMgI,IAAKhI,EAAiC;AAC5C,aAAI,OAAOgI,KAAM,YAAYA,IAAI,IAAU,KAAK,IAAIA,GAAG9E,EAAM,IAAI,IAC1D6Z,EAAY;AAAA,IACrB;2BAIExe,EASUC,EAAAwe,EAAA,GAAA;AAAA,MATA,MAAM7Z,EAAA;AAAA,MAAO,KAAKA,EAAA;AAAA,IAAA;iBAExB,MAA6B;AAAA,SAD/BvE,EAAA,EAAA,GAAAb,EAOMc,GAAA,MAAAC,EANmBqE,EAAA,OAAK,CAApB2Q,GAAOnQ,YADjB5F,EAOM,OAAA;AAAA,UALH,KAAK4F;AAAA,UACN,OAAM;AAAA,UACL,gCAA6BmT,EAAQhD,CAAK,CAAA,WAAYgD,EAAQhD,CAAK,CAAA,IAAA;AAAA,QAAA;UAEpEhR,EAAgC8P,IAAA,EAAf,MAAMkB,EAAA,GAAK,MAAA,GAAA,CAAA,MAAA,CAAA;AAAA,QAAA;;;;;;;;;;;;;;;;;;;;;;2BCtBhCvV,EAQUC,EAAA2J,CAAA,GAAA;AAAA,MARD,SAAQ;AAAA,MAAK,OAAM;AAAA,IAAA;iBAC1B,MAGS;AAAA,QAHKhF,EAAA,SAASA,EAAA,eAAvBvE,KAAAb,EAGS,UAHTW,IAGS;AAAA,UAFGyE,EAAA,cAAVpF,EAA8D,MAA9DwF,IAA8D5E,EAAbwE,EAAA,KAAK,GAAA,CAAA;UAC7CA,EAAA,oBAATpF,EAA8E,KAA9E6F,IAA8EjF,EAAlBwE,EAAA,WAAW,GAAA,CAAA;;QAEzEnF,EAEM,OAFNiI,IAEM;AAAA,WADJrH,EAAA,EAAA,GAAAb,EAAyEc,GAAA,MAAAC,EAAlCqE,EAAA,OAAK,CAApB2Q,GAAOnQ,YAA/BpF,EAAyEqU,IAAA;AAAA,YAA1B,KAAKjP;AAAA,YAAM,MAAMmQ;AAAA,UAAA;;;;;;;;;;;;;;ACFtE,UAAM5Q,IAAQC,GACRC,IAAOC;AAEb,aAAS4Z,EAAOhJ,GAActQ,GAA8B;AAC1D,aAAOsQ,EAAI,OAAOtQ;AAAA,IACpB;AAEA,UAAMuZ,IAAcngB,EAAqBmG,EAAM,UAAU+Z,EAAO/Z,EAAM,MAAM,CAAC,KAAK,CAAY,GAAG,CAAC,CAAC;AAEnG,aAASsZ,EAAS9V,GAA8B;AAC9C,MAAAwW,EAAY,QAAQxW,GACpBtD,EAAK,iBAAiBsD,CAAK;AAAA,IAC7B;2BAIEnI,EAsBUC,EAAA2e,EAAA,GAAA;AAAA,MAtBA,eAAaD,EAAA;AAAA,MAAc,uBAAoBV;AAAA,IAAA;MAC5C,QAEP,MAA2B;AAAA,SAD7B5d,EAAA,EAAA,GAAAb,EAMSc,GAAA,MAAAC,EALcqE,EAAA,OAAK,CAAlB8Q,GAAKtQ,YADfpF,EAMSC,EAAA4e,EAAA,GAAA;AAAA,UAJN,KAAKH,EAAOhJ,GAAKtQ,CAAG;AAAA,UACpB,OAAOsZ,EAAOhJ,GAAKtQ,CAAG;AAAA,QAAA;qBAEvB,MAAe;AAAA,YAAZ1E,EAAAN,EAAAsV,EAAI,KAAK,GAAA,CAAA;AAAA,UAAA;;;;iBAKd,MAA2B;AAAA,SAD7BrV,EAAA,EAAA,GAAAb,EAUcc,GAAA,MAAAC,EATSqE,EAAA,OAAK,CAAlB8Q,GAAKtQ,YADfpF,EAUcC,EAAA6e,EAAA,GAAA;AAAA,UARX,KAAG,SAAWJ,EAAOhJ,GAAKtQ,CAAG,CAAA;AAAA,UAC7B,OAAOsZ,EAAOhJ,GAAKtQ,CAAG;AAAA,QAAA;qBAGrB,MAAkC;AAAA,aADpC/E,EAAA,EAAA,GAAAb,EAIEc,WAHwBoV,EAAI,OAAK,CAAzBH,GAAOwJ,YADjB/e,EAIEqU,IAAA;AAAA,cAFC,KAAK0K;AAAA,cACL,MAAMxJ;AAAA,YAAA;;;;;;;;;ACvCR,SAASyJ,KAAkC;AAChD,EAAAvM,GAAmB;AAAA,IACjB,QAAQ;AAAA,MACN,MAAMwM;AAAAA,MACN,OAAOA;AAAAA,MACP,KAAKA;AAAAA,MACL,UAAUA;AAAAA,MACV,KAAKA;AAAAA,MACL,QAAQA;AAAAA,MACR,UAAUC;AAAAA,MACV,QAAQC;AAAAA,MACR,QAAQC;AAAAA,MACR,UAAUC;AAAAA,MACV,UAAUA;AAAAA,MACV,MAAMC;AAAAA,MACN,UAAUA;AAAAA,MACV,MAAMA;AAAAA,IAAA;AAAA,IAER,SAAS;AAAA,MACP,MAAMC;AAAAA,MACN,SAASC;AAAAA,MACT,SAASC;AAAAA,MACT,OAAOA;AAAAA,MACP,MAAMC;AAAAA,IAAA;AAAA,EACR,CACD;AACH;;;;;;;;;;;AC3BA,UAAM/a,IAAQC,GAQRmR,IAASI,GAAA,GACTlU,IAAUtD,EAAiB,MAAM;AACrC,UAAI+O,IAAa/I,EAAM;AAIvB,aAHI+I,MAAM,UAAaqI,KAAUpR,EAAM,SACrC+I,IAAIqI,EAAOpR,EAAM,IAAI,IAEnB+I,KAAM,QAA2BA,MAAM,KAAW/I,EAAM,cACrD,OAAO+I,CAAC;AAAA,IACjB,CAAC;2BAIClO,EAEO,QAAA;AAAA,MAFA,iCAA+BoF,EAAA,OAAI,8BAAA,EAAA,CAAA;AAAA,IAAA,KACrC3C,EAAA,KAAO,GAAA,CAAA;AAAA;;;;;;;;;;;;;;ACjBd,UAAM0C,IAAQC,GAQRmR,IAASI,GAAA,GACThO,IAAQxJ,EAAiB,MAAM;AACnC,UAAI+O,IAAa/I,EAAM;AACvB,aAAI+I,MAAM,UAAaqI,KAAUpR,EAAM,SACrC+I,IAAIqI,EAAOpR,EAAM,IAAI,IAEhB+I,KAAM,OAA0B,KAAK,OAAOA,CAAC;AAAA,IACtD,CAAC,GACKiS,IAAkBhhB,EAAuB,MACzCgG,EAAM,UAAgBA,EAAM,UACzBA,EAAM,IAAIwD,EAAM,KAAK,KAAK,SAClC;qBAIiBA,EAAA,cAAhBnI,EAEWC,EAAAkU,EAAA,GAAA;AAAA;MAFa,SAASwL,EAAA;AAAA,IAAA;iBAC/B,MAAW;AAAA,YAARxX,EAAA,KAAK,GAAA,CAAA;AAAA,MAAA;;gCAEV3I,EAAiD,QAAjDW,IAAyC,GAAC;AAAA;;;;;;;;;;;;;AC7B5C,UAAMwE,IAAQC,GAURmR,IAASI,GAAA,GACTyJ,IAAOjhB,EAAkB,MAAM;AACnC,UAAI+O,IAAa/I,EAAM;AACvB,aAAI+I,MAAM,UAAaqI,KAAUpR,EAAM,SACrC+I,IAAIqI,EAAOpR,EAAM,IAAI,IAEhB,EAAQ+I;AAAA,IACjB,CAAC,GACKmS,IAAelhB,EAAS,MAAOihB,EAAK,QAAQjb,EAAM,YAAYA,EAAM,UAAW,GAC/EvF,IAAWT,EAAS,MAAOihB,EAAK,QAAQjb,EAAM,WAAWA,EAAM,SAAU;2BAI7EnF,EAGO,QAAA;AAAA,MAHA,iCAA+BogB,EAAA,QAAI,4BAAA,0BAAA,CAAA;AAAA,IAAA;MACxCngB,EAAiE,QAAA;AAAA,QAA3D,OAAM;AAAA,QAA8B,aAAWL,EAAA;AAAA,MAAA;MACzCygB,EAAA,SAAZxf,EAAA,GAAAb,EAAmD,cAAtBqgB,EAAA,KAAY,GAAA,CAAA;;;;;;;;;;;;;;AC/B7C,UAAMlb,IAAQC,GAMRmR,IAASI,GAAA,GACTvV,IAAQjC,EAAmC,MAAM;AACrD,UAAI+O,IAAa/I,EAAM;AAIvB,aAHI+I,MAAM,UAAaqI,KAAUpR,EAAM,SACrC+I,IAAIqI,EAAOpR,EAAM,IAAI,IAEnB+I,KAAM,OAAgC,CAAA,IACtC,OAAOA,KAAM,WAAiB,CAAA,IAC3B,OAAO,QAAQA,CAA4B;AAAA,IACpD,CAAC;AAED,aAASoS,EAAYpS,GAAoB;AACvC,aAAIA,KAAM,OAAgC,MACtC,OAAOA,KAAM,WAAiB,KAAK,UAAUA,CAAC,IAC3C,OAAOA,CAAC;AAAA,IACjB;qBAI4B9M,EAAA,MAAM,SAAM,UAAtCZ,EAQqBC,EAAA8f,EAAA,GAAA;AAAA;MARuB,WAAU;AAAA,MAAY,SAAS;AAAA,IAAA;iBAEvE,MAAuB;AAAA,SADzB1f,EAAA,EAAA,GAAAb,EAMqBc,GAAA,MAAAC,EALFK,EAAA,OAAK,CAAA,CAAd6M,GAAGC,CAAC,YADd1N,EAMqBC,EAAA+f,EAAA,GAAA;AAAA,UAJlB,KAAKvS;AAAA,UACL,OAAOA;AAAA,QAAA;qBAER,MAAoB;AAAA,YAAjB/M,EAAAN,EAAA0f,EAAYpS,CAAC,CAAA,GAAA,CAAA;AAAA,UAAA;;;;;gBAGpBlO,EAAiD,QAAjDW,IAAyC,GAAC;AAAA;;ACvCrC,SAAS8f,KAAuC;AACrD,EAAArL,GAAwB;AAAA,IACtB,MAAMsL;AAAAA,IACN,OAAOC;AAAAA,IACP,MAAMC;AAAAA,IACN,UAAUC;AAAAA,IACV,aAAaA;AAAAA,EAAA,CACd;AACH;ACoGO,SAASC,GACdzhB,GACA0hB,IAAiC,IACjB;AAChB,QAAMC,IAAQD,EAAQ,SAAS,CAAA,GACzBpE,IAAOoE,EAAQ,QAAQE,GAAW5hB,EAAU,OAAO,KAAK,UAGxDZ,IAAS4c,GAAkB;AAAA,IAC/B,SAAShc,EAAU;AAAA,IACnB,WAAWA,EAAU;AAAA,EAAA,CACtB;AACD,EAAAb,GAAeC,CAAM;AAGrB,QAAMyiB,IAAMC,GAAUC,EAAQ,GACxBC,IAAQC,GAAA;AACd,EAAAJ,EAAI,IAAIG,CAAK,GAGb/d,EAAA,EAAe,QAAQjE,CAAS,GAChCa,GAAA,EAAiB,QAAQb,CAAS,GAClCR,GAAA,EAAgB,QAAQQ,CAAS,GACjC8B,GAAA,EAAwB,QAAQ9B,CAAS,GAGzCmgB,GAAA,GACA9E,GAAA,GACA+F,GAAA;AAGA,QAAM7b,IAASmZ,GAAkB;AAAA,IAC/B,MAAApB;AAAA,IACA,SAASoE,EAAQ,QAAQ,WAAW9C,GAAiBtB,CAAI;AAAA,IACzD,YAAY;AAAA,MACV,OAAOqE,EAAM,SAASO;AAAAA,MACtB,MAAMP,EAAM,QAAQQ;AAAAA,MACpB,WAAWR,EAAM,aAAaS;AAAAA,MAC9B,UAAUT,EAAM,YAAYU;AAAAA,MAC5B,SAASV,EAAM,WAAWW;AAAAA,MAC1B,eAAeX,EAAM,iBAAiBY;AAAAA,MACtC,gBAAgBZ,EAAM,kBAAkBa;AAAAA,MACxC,cAAcb,EAAM,gBAAgBa;AAAAA,MACpC,cAAcb,EAAM,gBAAgBc;AAAAA,MACpC,WAAWd,EAAM,aAAae;AAAAA,MAC9B,UAAUf,EAAM,YAAYgB;AAAAA,MAC5B,QAAQhB,EAAM,UAAUiB;AAAAA,IAAA;AAAA,IAE1B,aAAalB,EAAQ,QAAQ;AAAA,IAC7B,WAAWA,EAAQ,QAAQ;AAAA,IAC3B,YAAYA,EAAQ,QAAQ;AAAA,EAAA,CAC7B;AACD,SAAAG,EAAI,IAAItc,CAAM,GAGTmc,EAAQ,oBACWzX,GAAA,EAEnB,KAAA,EACA,KAAK,CAACC,MAAa;AAClB,IAAA3E,EAAO,sBAAsB2E,CAAQ;AAAA,EACvC,CAAC,EACA,MAAM,CAAClD,MAAmB;AAGzB,IAAI,OAAO,UAAY,OACrB,QAAQ,MAAM,yCAAyCA,CAAK;AAAA,EAEhE,CAAC,GAIL0a,EAAQ,eAAeG,CAAG,GAEnB,EAAE,KAAAA,GAAK,QAAAtc,GAAQ,QAAAnG,EAAA;AACxB;AAKA,SAASwiB,GAAWiB,GAA4C;AAC9D,MAAI,CAACA,EAAS,QAAO;AACrB,MAAI;AAEF,WADY,IAAI,IAAIA,CAAO,EAChB,YAAY;AAAA,EACzB,QAAQ;AACN,WAAOA,EAAQ,WAAW,GAAG,IAAIA,IAAU;AAAA,EAC7C;AACF;AC/KA,eAAsBC,GACpB7G,IAA6B,IACG;AAChC,QAAM8G,IAASC,GAAA;AACf,MAAID;AACF,WAAOA;AAGT,MAAI9G,EAAK;AACP,QAAI;AACF,YAAMtJ,IAAMsJ,EAAK,UAAU;AAC3B,aAAO,MAAMA,EAAK,OAAO,IAAoBtJ,CAAG;AAAA,IAClD,SAASrS,GAAK;AACZ,UAAIA,aAAewD;AAEjB,eAAO;AAET,YAAMxD;AAAA,IACR;AAGF,SAAO;AACT;AAKO,SAAS0iB,KAA6C;AAC3D,SAAI,OAAO,SAAW,MAAoB,OACnC,OAAO,uBAAuB;AACvC;AAOO,SAASC,KAAkC;AAChD,SAAI,OAAO,WAAa,MAAoB,OAC/B,SAAS,cAAc,yBAAyB,GAChD,aAAa,SAAS,KAAK;AAC1C;;;;;;;;;;;;;;;;;;;;;;;;;;ACjDA,UAAMnd,IAAQC,GACRC,IAAOC,GAMP9C,IAAgBrB,GAAA;AAEtB,aAASohB,EAAQrU,GAAkB;AACjC,MAAA7I,EAAK,eAAe6I,CAAC;AAAA,IACvB;AAGA,IAAArF;AAAA,MACE,MAAM1D,EAAM;AAAA,MACZ,OAAOpF,MAAS;AACd,QAAIA,KACF,MAAMyC,EAAc,KAAKA,EAAc,cAAc,OAAO,CAAC,EAAE,MAAM,MAAA;AAAA,SAAe;AAAA,MAExF;AAAA,MACA,EAAE,WAAW,GAAA;AAAA,IAAK;AAGpB,UAAMggB,IAAerjB,EAA6B,MAAMqD,EAAc,cAAc,KAAK;AAEzF,mBAAe4L,EAAUzM,GAA6D;AACpF,YAAMa,EACH,KAAKb,GAA8B,CAAC,EACpC,MAAM,MAAA;AAAA,OAAe;AAAA,IAC1B;AAEA,mBAAe8gB,IAA6B;AAC1C,YAAMjgB,EAAc,cAAA,EAAgB,MAAM,MAAA;AAAA,OAAe;AAAA,IAC3D;AAEA,mBAAekgB,EAAYzgB,GAAuC;AAChE,MAAAoD,EAAK,eAAepD,CAAI,GACnBA,EAAK,WACR,MAAMO,EAAc,WAAWP,EAAK,EAAE,EAAE,MAAM,MAAA;AAAA,OAAe;AAAA,IAEjE;AAEA,mBAAe0gB,EAAU1gB,GAAwB2J,GAA6B;AAC5E,MAAAA,EAAM,gBAAA,GACN,MAAMpJ,EAAc,QAAQP,EAAK,EAAE,EAAE,MAAM,MAAA;AAAA,OAAe;AAAA,IAC5D;AAEA,aAAS2gB,EAAS3gB,GAAmE;AACnF,YAAM4gB,IAAM5gB,EAAK,KAAK;AACtB,aAAI4gB,MAAQ,aAAaA,MAAQ,aAAaA,MAAQ,WAAiBA,IAChE;AAAA,IACT;AAEA,aAASC,EAAU7gB,GAAgC;AACjD,aAAQA,EAAK,KAAK,SAAgC;AAAA,IACpD;AAEA,aAAS8gB,EAAS9gB,GAAgC;AAChD,aAAQA,EAAK,KAAK,QAA+B;AAAA,IACnD;AAEA,aAAS+gB,EAAQC,GAA4B;AAC3C,UAAI,CAACA,EAAK,QAAO;AACjB,YAAMC,IAAK,IAAI,KAAKD,CAAG,GACjBE,IAAO,KAAK,IAAI,GAAG,KAAK,IAAA,IAAQD,EAAG,SAAS,GAC5CE,IAAO,KAAK,MAAMD,IAAO,GAAK;AACpC,UAAIC,IAAO,EAAG,QAAO;AACrB,UAAIA,IAAO,GAAI,QAAO,GAAGA,CAAI;AAC7B,YAAMC,IAAQ,KAAK,MAAMD,IAAO,EAAE;AAClC,UAAIC,IAAQ,GAAI,QAAO,GAAGA,CAAK;AAC/B,YAAMC,IAAO,KAAK,MAAMD,IAAQ,EAAE;AAClC,aAAIC,IAAO,IAAU,GAAGA,CAAI,aACrBJ,EAAG,mBAAmB,OAAO;AAAA,IACtC;2BAIE1iB,EA8EYC,EAAA8iB,EAAA,GAAA;AAAA,MA7ET,eAAane,EAAA;AAAA,MACd,MAAK;AAAA,MACL,OAAM;AAAA,MACN,OAAM;AAAA,MACL,uBAAoBmd;AAAA,IAAA;MAEV,UACT,MAeM;AAAA,QAfNtiB,EAeM,OAfNU,IAeM;AAAA,UAdJV,EAKK,MALLuF,IAKK;AAAA,8BAL2B,iBAE9B,EAAA;AAAA,YAAY/E,EAAA+B,CAAA,EAAc,cAAW,UAArCxC,EAEO,QAFP6F,IAAuE,SACjEpF,EAAA+B,CAAA,EAAc,WAAW,IAAG,MAClC,CAAA;;UAGM/B,EAAA+B,CAAA,EAAc,cAAW,UADjChC,EAOYC,EAAA4J,CAAA,GAAA;AAAA;YALV,SAAQ;AAAA,YACR,MAAK;AAAA,YACJ,SAAOoY;AAAA,UAAA;uBACT,MAED,CAAA,GAAAxd,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,gBAFC,mBAED,EAAA;AAAA,YAAA;;;;;iBAIJ,MAmDU;AAAA,QAnDVF,EAmDUtE,EAAA2e,EAAA,GAAA;AAAA,UAnDA,eAAaoD,EAAA;AAAA,UAAe,uBAAoBpU;AAAA,QAAA;UAC7C,QACT,MAAgC;AAAA,YAAhCrJ,EAAgCtE,EAAA4e,EAAA,GAAA,EAAxB,OAAM,SAAK;AAAA,yBAAC,MAAG,CAAA,GAAApa,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,kBAAH,OAAG,EAAA;AAAA,cAAA;;;YACvBF,EAIStE,EAAA4e,EAAA,GAAA,EAJD,OAAM,YAAQ;AAAA,yBAAC,MACR;AAAA,kCADQ,kBACR,EAAA;AAAA,gBAAgB5e,EAAA+B,CAAA,EAAc,cAAW,UAAzCxC,EAEFc,GAAA,EAAA,KAAA,EAAA,GAAA;AAAA,kBAFiDI,EAAA,OACzDN,EAAGH,EAAA+B,CAAA,EAAc,WAAW,IAAG,MAClC,CAAA;AAAA,gBAAA;;;;YAEFuC,EAAyCtE,EAAA4e,EAAA,GAAA,EAAjC,OAAM,UAAM;AAAA,yBAAC,MAAW,CAAA,GAAApa,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,kBAAX,eAAW,EAAA;AAAA,cAAA;;;;qBAGrB,MAAoD;AAAA,kBAAjEjF,EAuCcc,GAAA,MAAAC,EAvCgB,CAAA,OAAA,UAAA,MAAA,GAAkC,CAA5CY,MAApBoD,EAuCctE,EAAA6e,EAAA,GAAA;AAAA,cAvCqD,KAAK3d;AAAA,cAAS,OAAOA;AAAA,YAAA;yBACtF,MAqCK;AAAA,gBArCL1B,EAqCK,MArCLiI,IAqCK;AAAA,kBApCOzH,EAAA+B,CAAA,EAAc,gBAAxBxC,EAEK,MAFLsI,IAA6D,aAE7D,KACe7H,EAAA+B,CAAA,EAAc,MAAM,WAAM,UAAzCxC,EAEK,MAFLuI,IAA6E,mBAE7E;mBACA1H,EAAA,EAAA,GAAAb,EA6BKc,GAAA,MAAAC,EA5BYN,EAAA+B,CAAA,EAAc,QAAtBP,YADTjC,EA6BK,MAAA;AAAA,oBA3BF,KAAKiC,EAAK;AAAA,oBACV,OAAK8D,EAAA;AAAA;sBAA6E,uBAAA6c,EAAS3gB,CAAI,CAAA;AAAA,sBAAoD,EAAA,8BAAA,CAAAA,EAAK,QAAA;AAAA,oBAAO;oBAK/J,SAAK,CAAAhB,MAAEyhB,EAAYzgB,CAAI;AAAA,kBAAA;oBAExBhC,EAA+D,QAAA;AAAA,sBAAzD,OAAM;AAAA,sBAAsB,aAAW2iB,EAAS3gB,CAAI;AAAA,oBAAA;oBAC1DhC,EASM,OATN6P,IASM;AAAA,sBARJ7P,EAMM,OANNkW,IAMM;AAAA,wBALWlU,EAAK,WAGpBpB,EAAA,GAAAb,EAA0E,QAA1EqQ,IAA0EzP,EAAzBkiB,EAAU7gB,CAAI,CAAA,GAAA,CAAA,MAH/DpB,EAAA,GAAAb,EAES,UAFTiQ,IAESrP,EADJkiB,EAAU7gB,CAAI,CAAA,GAAA,CAAA;AAAA,wBAGnBhC,EAAsE,QAAtEqQ,IAAsE1P,EAAlCoiB,EAAQ/gB,EAAK,UAAU,CAAA,GAAA,CAAA;AAAA,sBAAA;sBAEpD8gB,EAAS9gB,CAAI,KAAtBpB,EAAA,GAAAb,EAA4E,KAA5EyQ,IAA4E7P,EAArBmiB,EAAS9gB,CAAI,CAAA,GAAA,CAAA;;oBAEtEhC,EAOS,UAAA;AAAA,sBANP,MAAK;AAAA,sBACL,OAAM;AAAA,sBACL,cAAY;AAAA,sBACZ,SAAK,CAAAgB,MAAE0hB,EAAU1gB,GAAMhB,CAAM;AAAA,oBAAA,GAC/B,OAED,GAAAwW,EAAA;AAAA,kBAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACvGZ,UAAMtS,IAAQC,GASRC,IAAOC,GAWPke,IAAQ;AAAA,MACZ,EAAE,OAAO,YAAY,aAAa,mBAAA;AAAA,MAClC,EAAE,OAAO,iBAAiB,aAAa,uBAAA;AAAA,MACvC,EAAE,OAAO,gBAAgB,aAAa,wBAAA;AAAA,MACtC,EAAE,OAAO,UAAU,aAAa,kBAAA;AAAA,IAAkB,GAG9CC,IAAezkB,EAAI,CAAC,GACpB0kB,IAAcvkB,EAAS,MAAMgG,EAAM,QAAQse,EAAa,KAAK;AAEnE,aAASE,EAAQ/d,GAAmB;AAClC,MAAIT,EAAM,SAAS,WACfS,IAAM,KAAKA,KAAO4d,EAAM,WAC5BC,EAAa,QAAQ7d;AAAA,IACvB;AAGA,UAAMge,IAAgB5kB,EAAuC,EAAE;AAC/D,aAAS6kB,EAASC,GAAgD;AAChE,MAAAF,EAAc,QAAQE,GAClBA,EAAM,SAAS,KACjBze,EAAK,iBAAiBye,EAAM,CAAC,EAAE,IAAI;AAAA,IAEvC;AAGA,UAAMC,IAAU/kB,EAAmC,EAAE;AAErD,aAASglB,EAAUC,GAAgBtb,GAAqC;AACtE,MAAAob,EAAQ,MAAME,CAAM,IAAItb,MAAU,QAAQA,MAAU,KAAK,OAAO,OAAOA,CAAK;AAAA,IAC9E;AAEA,aAASub,IAA0B;AACjC,aAAO/e,EAAM,QAAQ,IAAI,CAAC2C,OAAO;AAAA,QAC/B,QAAQA,EAAE;AAAA,QACV,QAAQic,EAAQ,MAAMjc,EAAE,GAAG,KAAK;AAAA,MAAA,EAChC;AAAA,IACJ;AAEA,aAASqc,IAAwB;AAC/B,MAAA9e,EAAK,kBAAkB6e,GAAc,GACrCP,EAAQ,CAAC;AAAA,IACX;AAGA,aAASS,IAAqB;AAC5B,MAAA/e,EAAK,YAAY,GACjBse,EAAQ,CAAC;AAAA,IACX;AAGA,UAAMU,IAAYllB,EAAS,MAAMukB,EAAY,QAAQ,CAAC,GAChDY,IAAYnlB,EAAS,MAAM;AAC/B,cAAQukB,EAAY,OAAA;AAAA,QAClB,KAAK;AAAG,iBAAOE,EAAc,MAAM,SAAS;AAAA,QAC5C,KAAK;AAAG,iBAAO,OAAO,OAAOG,EAAQ,KAAK,EAAE,KAAK,CAAC7V,MAAMA,MAAM,IAAI;AAAA,QAClE,KAAK;AAAG,iBAAO;AAAA,QACf;AAAS,iBAAO;AAAA,MAAA;AAAA,IAEpB,CAAC,GAEKqW,IAAcplB,EAAkD,MAC7D;AAAA,MACL,EAAE,OAAO,IAAI,OAAO,mBAAA;AAAA,MACpB,GAAGgG,EAAM;AAAA,IAAA,CAEZ;AAED,aAASuP,IAAiB;AACxB,MAAArP,EAAK,QAAQ;AAAA,IACf;sBAIExE,EAAA,GAAAb,EA6IU,WA7IVW,IA6IU;AAAA,MA5IRV,EAOS,UAPTuF,IAOS;AAAA,QANPvF,EAEM,OAFN4F,IAEM;AAAA,UADJ5F,EAA8C,MAA9CiI,IAA8CtH,EAAbwE,EAAA,KAAK,GAAA,CAAA;AAAA,QAAA;QAExCnF,EAEM,OAFNqI,IAEM;AAAA,UADJvD,EAA+DtE,EAAA4J,CAAA,GAAA;AAAA,YAApD,SAAQ;AAAA,YAAS,SAAOqK;AAAA,UAAA;uBAAU,MAAM,CAAA,GAAAzP,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,gBAAN,UAAM,EAAA;AAAA,YAAA;;;;;MAIvDF,EAAoDtE,EAAA+jB,EAAA,GAAA;AAAA,QAAvC,OAAOhB;AAAA,QAAQ,SAASE,EAAA;AAAA,MAAA;MAGtBA,EAAA,UAAW,UAA1BljB,EAcUC,EAAA2J,CAAA,GAAA;AAAA;QAdwB,SAAQ;AAAA,QAAK,OAAM;AAAA,MAAA;mBACnD,MAGS;AAAA,0BAHTnK,EAGS,UAAA,EAHD,OAAM,kCAA8B;AAAA,YAC1CA,EAA0B,YAAtB,mBAAiB;AAAA,YACrBA,EAAiC,WAA9B,4BAA0B;AAAA,UAAA;UAE/B8E,EAQEtE,EAAAgkB,EAAA,GAAA;AAAA,YAPC,eAAab,EAAA;AAAA,YACd,QAAO;AAAA,YACN,YAAU,KAAA,OAAA;AAAA,YACV,aAAW;AAAA,YACZ,gBAAa;AAAA,YACb,kBAAe;AAAA,YACd,uBAAoBC;AAAA,UAAA;;;YAKLH,EAAA,UAAW,UAA/BljB,EA2BUC,EAAA2J,CAAA,GAAA;AAAA;QA3B6B,SAAQ;AAAA,QAAK,OAAM;AAAA,MAAA;mBACxD,MAGS;AAAA,0BAHTnK,EAGS,UAAA,EAHD,OAAM,kCAA8B;AAAA,YAC1CA,EAA+B,YAA3B,wBAAsB;AAAA,YAC1BA,EAAqD,WAAlD,gDAA8C;AAAA,UAAA;UAGxCmF,EAAA,QAAQ,WAAM,UAAzBpF,EAEM,OAFNuI,IAAoE,mEAEpE,MAEA1H,EAAA,GAAAb,EAgBM,OAhBNwI,IAgBM;AAAA,oBAfJxI,EAcMc,GAAA,MAAAC,EAdWqE,EAAA,SAAO,CAAZ0C,YAAZ9H,EAcM,OAAA;AAAA,cAdqB,KAAK8H,EAAE;AAAA,cAAK,OAAM;AAAA,YAAA;cAC3C7H,EAKM,OALNwM,IAKM;AAAA,gBAJJxM,EAA8B,UAAA,MAAAW,EAAnBkH,EAAE,KAAK,GAAA,CAAA;AAAA,gBACNA,EAAE,eAAd9H,EAEO,QAFP8P,IAA8D,SACxDhI,EAAE,MAAM,IAAG,MACjB,CAAA;;cAEF7C,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAAhF,EAAqD,QAAA,EAA/C,OAAM,iCAAA,GAAiC,KAAC,EAAA;AAAA,cAC9C8E,EAKEtE,EAAAiX,EAAA,GAAA;AAAA,gBAJC,eAAaqM,EAAA,MAAQjc,EAAE,GAAG,KAAA;AAAA,gBAC1B,SAASyc,EAAA;AAAA,gBACV,aAAY;AAAA,gBACX,uBAAkB,CAAGrW,MAAM8V,EAAUlc,EAAE,KAAKoG,CAAC;AAAA,cAAA;;;;;YAOlCwV,EAAA,UAAW,UAA/BljB,EAsBUC,EAAA2J,CAAA,GAAA;AAAA;QAtB6B,SAAQ;AAAA,QAAK,OAAM;AAAA,MAAA;mBACxD,MAGS;AAAA,UAHTnK,EAGS,UAHTkW,IAGS;AAAA,YAFPlR,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAAhF,EAAwB,YAApB,mBAAe,EAAA;AAAA,YACnBA,EAAuD,WAApD,YAAOW,EAAGwE,UAAQ,MAAM,IAAG,yBAAqB,CAAA;AAAA,UAAA;UAI7CA,EAAA,QAAQ,KAAI,CAAE2E,MAAMA,EAAE,SAAS,UADvCvJ,EAMWC,EAAAuK,CAAA,GAAA;AAAA;YAJT,SAAQ;AAAA,YACR,OAAA,EAAA,iBAAA,sBAAA;AAAA,UAAA;uBACD,MAED,CAAA,GAAA/F,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,gBAFC,kEAED,EAAA;AAAA,YAAA;;;UAGQG,EAAA,eAAe,SAAM,UAD7B5E,EAIEC,EAAA8P,EAAA,GAAA;AAAA;YAFC,SAASnL,EAAA;AAAA,YACT,MAAMA,EAAA;AAAA,UAAA,0CAETpF,EAEM,OAFNiQ,IAA+C,2CAE/C;AAAA,QAAA;;kBAIFzP,EAoBUC,EAAA2J,CAAA,GAAA;AAAA;QApBM,SAAQ;AAAA,QAAK,OAAM;AAAA,MAAA;mBACjC,MAES;AAAA,0BAFTnK,EAES,UAAA,EAFD,OAAM,kCAA8B;AAAA,YAC1CA,EAAkB,YAAd,WAAS;AAAA,UAAA;UAGHmF,EAAA,iBAGZpF,EAWWc,GAAA,EAAA,KAAA,KAAA;AAAA,YATDsE,EAAA,SAAS,QAAK,UADtB5E,EAIEC,EAAAikB,EAAA,GAAA;AAAA;cAFC,eAAatf,EAAA,SAAS,UAAUA,EAAA,SAAS,UAAUA,EAAA,SAAS;AAAA,cAC5D,KAAKA,EAAA,SAAS;AAAA,YAAA;YAEjBnF,EAIM,OAJNqQ,IAIM;AAAA,cAHJvL,EAAoEtE,EAAA2Y,EAAA,GAAA;AAAA,gBAA3D,OAAM;AAAA,gBAAW,OAAOhU,EAAA,SAAS;AAAA,gBAAS,MAAK;AAAA,cAAA;cACxDL,EAAmEtE,EAAA2Y,EAAA,GAAA;AAAA,gBAA1D,OAAM;AAAA,gBAAa,OAAOhU,EAAA,SAAS;AAAA,gBAAS,MAAK;AAAA,cAAA;cAC1DL,EAAiEtE,EAAA2Y,EAAA,GAAA;AAAA,gBAAxD,OAAM;AAAA,gBAAU,OAAOhU,EAAA,SAAS;AAAA,gBAAQ,MAAK;AAAA,cAAA;;0BAZ1DpF,EAEM,OAFNqQ,IAAyD,uBAEzD;AAAA;;;MAgBFpQ,EAgCS,UAhCTwQ,IAgCS;AAAA,QA9BC4T,EAAA,cADR7jB,EAMYC,EAAA4J,CAAA,GAAA;AAAA;UAJV,SAAQ;AAAA,UACP,SAAKpF,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA,CAAAhE,MAAE0iB,EAAQD,EAAA,QAAW,CAAA;AAAA,QAAA;qBAC5B,MAED,CAAA,GAAAze,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,cAFC,WAED,EAAA;AAAA,UAAA;;;0BACAhF,EAAuB,QAAA,EAAjB,OAAA,EAAA,MAAA,IAAA,EAAA,GAAc,MAAA,EAAA;AAAA,QAEZyjB,EAAA,UAAW,UADnBljB,EAOYC,EAAA4J,CAAA,GAAA;AAAA;UALV,SAAQ;AAAA,UACP,WAAWia,EAAA;AAAA,UACX,gCAAOX,EAAO,CAAA;AAAA,QAAA;qBAChB,MAED,CAAA,GAAA1e,EAAA,EAAA,MAAAA,EAAA,EAAA,IAAA;AAAA,cAFC,WAED,EAAA;AAAA,UAAA;;+BAEaye,EAAA,UAAW,UADxBljB,EAOYC,EAAA4J,CAAA,GAAA;AAAA;UALV,SAAQ;AAAA,UACP,WAAWia,EAAA;AAAA,UACX,SAAOH;AAAA,QAAA;qBACT,MAED,CAAA,GAAAlf,EAAA,EAAA,MAAAA,EAAA,EAAA,IAAA;AAAA,cAFC,yBAED,EAAA;AAAA,UAAA;;+BAEaye,EAAA,UAAW,UADxBljB,EAMYC,EAAA4J,CAAA,GAAA;AAAA;UAJV,SAAQ;AAAA,UACP,SAAO+Z;AAAA,QAAA;qBACT,MAED,CAAA,GAAAnf,EAAA,EAAA,MAAAA,EAAA,EAAA,IAAA;AAAA,cAFC,sBAED,EAAA;AAAA,UAAA;;;;;;;;;AC7QN,UAAM0f,IAAgB;AAAA;AAAA,MAEpB;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,OAAO;AAAA,QACP,aAAa;AAAA,QACb,MAAM,EAAE,MAAM,QAAQ,MAAM,aAAa,OAAO,oBAAoB,aAAa,+BAAA;AAAA,QACjF,SAAS,EAAE,WAAW,cAAA;AAAA,MAAc;AAAA,MAEtC;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,OAAO;AAAA,QACP,aAAa;AAAA,QACb,MAAM,EAAE,MAAM,YAAY,MAAM,iBAAiB,OAAO,YAAY,MAAM,EAAA;AAAA,QAC1E,SAAS,EAAE,eAAe,qBAAA;AAAA,MAAqB;AAAA,MAEjD;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,OAAO;AAAA,QACP,aAAa;AAAA,QACb,MAAM,EAAE,MAAM,UAAU,MAAM,eAAe,OAAO,QAAQ,KAAK,GAAG,KAAK,IAAA;AAAA,QACzE,SAAS,EAAE,aAAa,GAAA;AAAA,MAAG;AAAA;AAAA,MAG7B;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,OAAO;AAAA,QACP,aAAa;AAAA,QACb,MAAM;AAAA,UACJ,MAAM;AAAA,UACN,MAAM;AAAA,UACN,OAAO;AAAA,UACP,SAAS;AAAA,YACP,EAAE,OAAO,YAAY,OAAO,WAAA;AAAA,YAC5B,EAAE,OAAO,WAAW,OAAO,UAAA;AAAA,YAC3B,EAAE,OAAO,UAAU,OAAO,SAAA;AAAA,UAAS;AAAA,QACrC;AAAA,QAEF,SAAS,EAAE,aAAa,UAAA;AAAA,MAAU;AAAA,MAEpC;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,OAAO;AAAA,QACP,aAAa;AAAA,QACb,MAAM,EAAE,MAAM,YAAY,MAAM,iBAAiB,OAAO,gBAAgB,aAAa,yBAAA;AAAA,QACrF,SAAS,EAAE,eAAe,GAAA;AAAA,MAAK;AAAA;AAAA,MAGjC;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,OAAO;AAAA,QACP,aAAa;AAAA,QACb,MAAM,EAAE,MAAM,QAAQ,MAAM,aAAa,OAAO,mBAAmB,WAAW,OAAA;AAAA,QAC9E,SAAS,EAAE,WAAW,aAAA;AAAA,MAAa;AAAA,IACrC,GAIIC,IAAeD,EAAM,OAA+B,CAACE,GAAKlM,OACzDkM,EAAIlM,EAAE,KAAK,MAAGkM,EAAIlM,EAAE,KAAK,IAAI,CAAA,IAClCkM,EAAIlM,EAAE,KAAK,EAAE,KAAKA,CAAC,GACZkM,IACN,CAAA,CAAE,GAICC,IAAaC;AAAA,MACjBJ,EAAM,OAAgC,CAACE,GAAKlM,MAAM,OAAO,OAAOkM,GAAKlM,EAAE,OAAO,GAAG,CAAA,CAAE;AAAA,IAAA;AAErF,WAAA1E,GAAiB6Q,CAAU,cAIzBjkB,EAAA,GAAAb,EA8BU,WA9BVW,IA8BU;AAAA,sBA7BRV,EAOS,UAAA,EAPD,OAAM,oBAAgB;AAAA,QAC5BA,EAKM,OAAA,EALD,OAAM,4BAAwB;AAAA,UACjCA,EAAgD,MAAA,EAA5C,OAAM,oBAAA,GAAoB,eAAa;AAAA,UAC3CA,EAEM,OAAA,EAFD,OAAM,oBAAA,GAAoB,wEAE/B;AAAA,QAAA;;OAIJY,EAAA,EAAA,GAAAb,EAmBUc,GAAA,MAAAC,EAnBwBN,EAAAmkB,CAAA,GAAY,CAA7BxjB,GAAO2F,YAAxB/G,EAmBU,WAAA;AAAA,QAnBuC,KAAK+G;AAAA,QAAO,OAAM;AAAA,MAAA;QACjE9G,EAAuD,MAAvDuF,IAAuD5E,EAAbmG,CAAK,GAAA,CAAA;AAAA,QAC/C9G,EAgBM,OAhBN4F,IAgBM;AAAA,kBAfJ7F,EAcUc,GAAA,MAAAC,EAbOK,GAAK,CAAb4jB,YADTxkB,EAcUC,EAAA2J,CAAA,GAAA;AAAA,YAZP,KAAK4a,EAAK,OAAOA,EAAK;AAAA,YACvB,SAAQ;AAAA,YACR,OAAM;AAAA,UAAA;uBAEN,MAGS;AAAA,cAHT/kB,EAGS,UAHTiI,IAGS;AAAA,gBAFPjI,EAA2D,MAA3DqI,IAA2D1H,EAAlBokB,EAAK,KAAK,GAAA,CAAA;AAAA,gBACnD/kB,EAAmE,QAAnEsI,IAAuC,WAAM3H,EAAGokB,EAAK,IAAI,GAAA,CAAA;AAAA,cAAA;cAE3D/kB,EAA8D,KAA9DuI,IAA8D5H,EAAvBokB,EAAK,WAAW,GAAA,CAAA;AAAA,cACvD/kB,EAEM,OAFNwM,IAEM;AAAA,gBADJ1H,EAAmC+O,IAAA;AAAA,kBAAnB,MAAMkR,EAAK;AAAA,gBAAA;;;;;;;;;;"}