@flyos/design-system 2.7.0 → 3.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.
@@ -47,7 +47,7 @@ import { CdkConnectedOverlay, CdkOverlayOrigin } from '@angular/cdk/overlay';
47
47
  // tools/publish-library.ps1 at bump time, and asserted by the spec beside this file.
48
48
  // Used only for the diagnostic message; the duplicate-instance detection itself is
49
49
  // version-agnostic, so a stale literal misnames a fork rather than hiding one.
50
- const FLY_DS_VERSION = '2.7.0';
50
+ const FLY_DS_VERSION = '3.1.0';
51
51
  const FLY_DS_REGISTRY_KEY = '__FLY_DS_INSTANCES__';
52
52
  /**
53
53
  * Records this design-system instance on the shared `scope` and returns the
@@ -1323,6 +1323,15 @@ const DS_BASELINE_LOCALES = {
1323
1323
  'app_unavailable.unreachable.title': 'App unavailable',
1324
1324
  'app_unavailable.unreachable.message': "{{app}} can't be reached right now. Nothing was changed — please try again in a moment.",
1325
1325
  'common.action.cancel': 'Cancel',
1326
+ 'common.action.close': 'Close',
1327
+ 'common.abort': 'Abort',
1328
+ 'common.ignore': 'Ignore',
1329
+ 'common.retry': 'Retry',
1330
+ 'common.loading': 'Loading…',
1331
+ 'common.remove': 'Remove',
1332
+ 'common.yes': 'Yes',
1333
+ 'common.no': 'No',
1334
+ 'common.ok': 'OK',
1326
1335
  'common.label.apply': 'Apply',
1327
1336
  'common.label.formatting_toolbar': 'Formatting toolbar',
1328
1337
  'common.label.https': 'https://…',
@@ -1423,7 +1432,7 @@ const DS_BASELINE_LOCALES = {
1423
1432
  'search.placeholder': 'Search…',
1424
1433
  'search.clear': 'Clear search',
1425
1434
  'search.open': 'Search',
1426
- 'search.filters': "Filters",
1435
+ 'search.filters': 'Filters',
1427
1436
  // skeleton (fly-skeleton)
1428
1437
  'skeleton.loading': 'Loading…',
1429
1438
  // typeahead (fly-typeahead)
@@ -1697,6 +1706,15 @@ const DS_BASELINE_LOCALES = {
1697
1706
  'app_unavailable.unreachable.title': 'التطبيق غير متاح',
1698
1707
  'app_unavailable.unreachable.message': 'تعذّر الوصول إلى {{app}} حاليًا. لم يتم تغيير أي شيء — يرجى المحاولة بعد قليل.',
1699
1708
  'common.action.cancel': 'إلغاء',
1709
+ 'common.action.close': 'إغلاق',
1710
+ 'common.abort': 'إلغاء العملية',
1711
+ 'common.ignore': 'تجاهل',
1712
+ 'common.retry': 'إعادة المحاولة',
1713
+ 'common.loading': 'جارٍ التحميل…',
1714
+ 'common.remove': 'إزالة',
1715
+ 'common.yes': 'نعم',
1716
+ 'common.no': 'لا',
1717
+ 'common.ok': 'موافق',
1700
1718
  'common.label.apply': 'تطبيق',
1701
1719
  'common.label.formatting_toolbar': 'شريط أدوات التنسيق',
1702
1720
  'common.label.https': 'https://…',
@@ -1796,7 +1814,7 @@ const DS_BASELINE_LOCALES = {
1796
1814
  'search.placeholder': 'بحث…',
1797
1815
  'search.clear': 'مسح البحث',
1798
1816
  'search.open': 'بحث',
1799
- 'search.filters': "عوامل التصفية",
1817
+ 'search.filters': 'عوامل التصفية',
1800
1818
  // skeleton (fly-skeleton)
1801
1819
  'skeleton.loading': 'جارٍ التحميل…',
1802
1820
  // typeahead (fly-typeahead)
@@ -2070,6 +2088,15 @@ const DS_BASELINE_LOCALES = {
2070
2088
  'app_unavailable.unreachable.title': 'Application indisponible',
2071
2089
  'app_unavailable.unreachable.message': '{{app}} est injoignable pour le moment. Rien n’a été modifié — veuillez réessayer dans un instant.',
2072
2090
  'common.action.cancel': 'Annuler',
2091
+ 'common.action.close': 'Fermer',
2092
+ 'common.abort': 'Abandonner',
2093
+ 'common.ignore': 'Ignorer',
2094
+ 'common.retry': 'Réessayer',
2095
+ 'common.loading': 'Chargement…',
2096
+ 'common.remove': 'Supprimer',
2097
+ 'common.yes': 'Oui',
2098
+ 'common.no': 'Non',
2099
+ 'common.ok': 'OK',
2073
2100
  'common.label.apply': 'Appliquer',
2074
2101
  'common.label.formatting_toolbar': "Barre d'outils de mise en forme",
2075
2102
  'common.label.https': 'https://…',
@@ -2169,7 +2196,7 @@ const DS_BASELINE_LOCALES = {
2169
2196
  'search.placeholder': 'Rechercher…',
2170
2197
  'search.clear': 'Effacer la recherche',
2171
2198
  'search.open': 'Rechercher',
2172
- 'search.filters': "Filtres",
2199
+ 'search.filters': 'Filtres',
2173
2200
  // skeleton (fly-skeleton)
2174
2201
  'skeleton.loading': 'Chargement…',
2175
2202
  // typeahead (fly-typeahead)
@@ -2387,14 +2414,14 @@ const DS_BASELINE_LOCALES = {
2387
2414
  'chat_composer.label.mention_suggestions': 'Suggestions de mention',
2388
2415
  // app-surface component library (fly-card / -data-table / -pagination /
2389
2416
  // -filter-panel / forms / overlays). Absorbed with the kit from Circles.
2390
- 'ui.action.addMoreOptions': 'Plus d\'options',
2417
+ 'ui.action.addMoreOptions': "Plus d'options",
2391
2418
  'ui.action.cancel': 'Annuler',
2392
2419
  'ui.action.clear': 'Effacer',
2393
2420
  'ui.action.clearFilters': 'Effacer les filtres',
2394
2421
  'ui.action.close': 'Fermer',
2395
2422
  'ui.action.confirm': 'Confirmer',
2396
2423
  'ui.action.dismiss': 'Ignorer',
2397
- 'ui.action.fewerOptions': 'Moins d\'options',
2424
+ 'ui.action.fewerOptions': "Moins d'options",
2398
2425
  'ui.action.open': 'Ouvrir',
2399
2426
  'ui.action.retry': 'Réessayer',
2400
2427
  'ui.action.save': 'Enregistrer',
@@ -2403,7 +2430,7 @@ const DS_BASELINE_LOCALES = {
2403
2430
  'ui.confirm.typeToConfirm': 'Saisissez {{text}} pour confirmer',
2404
2431
  'ui.filters.title': 'Filtres',
2405
2432
  'ui.form.autoSaving': 'Enregistrement automatique',
2406
- 'ui.nav.breadcrumbs': 'Fil d\'Ariane',
2433
+ 'ui.nav.breadcrumbs': "Fil d'Ariane",
2407
2434
  'ui.nav.home': 'Accueil',
2408
2435
  'ui.nav.modules': 'Modules',
2409
2436
  'ui.nav.selectModule': 'Choisir un module',
@@ -2443,6 +2470,15 @@ const DS_BASELINE_LOCALES = {
2443
2470
  'app_unavailable.unreachable.title': 'ایپ دستیاب نہیں',
2444
2471
  'app_unavailable.unreachable.message': '{{app}} تک ابھی رسائی ممکن نہیں۔ کچھ تبدیل نہیں ہوا — براہِ کرم تھوڑی دیر بعد کوشش کریں۔',
2445
2472
  'common.action.cancel': 'منسوخ کریں',
2473
+ 'common.action.close': 'بند کریں',
2474
+ 'common.abort': 'منسوخ کریں',
2475
+ 'common.ignore': 'نظرانداز کریں',
2476
+ 'common.retry': 'دوبارہ کوشش کریں',
2477
+ 'common.loading': 'لوڈ ہو رہا ہے…',
2478
+ 'common.remove': 'ہٹائیں',
2479
+ 'common.yes': 'ہاں',
2480
+ 'common.no': 'نہیں',
2481
+ 'common.ok': 'ٹھیک ہے',
2446
2482
  'common.label.apply': 'لاگو کریں',
2447
2483
  'common.label.formatting_toolbar': 'فارمیٹنگ ٹول بار',
2448
2484
  'common.label.https': 'https://…',
@@ -2541,7 +2577,7 @@ const DS_BASELINE_LOCALES = {
2541
2577
  'search.placeholder': 'تلاش کریں…',
2542
2578
  'search.clear': 'تلاش صاف کریں',
2543
2579
  'search.open': 'تلاش کریں',
2544
- 'search.filters': "فلٹرز",
2580
+ 'search.filters': 'فلٹرز',
2545
2581
  // skeleton (fly-skeleton)
2546
2582
  'skeleton.loading': 'لوڈ ہو رہا ہے…',
2547
2583
  // typeahead (fly-typeahead)
@@ -9747,11 +9783,11 @@ class FlyAppUnavailableComponent {
9747
9783
  */
9748
9784
  trimmedAppName = computed(() => this.appName()?.trim() ?? '', ...(ngDevMode ? [{ debugName: "trimmedAppName" }] : /* istanbul ignore next */ []));
9749
9785
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyAppUnavailableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
9750
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.19", type: FlyAppUnavailableComponent, isStandalone: true, selector: "fly-app-unavailable", inputs: { state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: false, transformFunction: null }, appName: { classPropertyName: "appName", publicName: "appName", isSignal: true, isRequired: false, transformFunction: null }, titleKey: { classPropertyName: "titleKey", publicName: "titleKey", isSignal: true, isRequired: false, transformFunction: null }, messageKey: { classPropertyName: "messageKey", publicName: "messageKey", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, compact: { classPropertyName: "compact", publicName: "compact", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\n class=\"fly-app-unavailable\"\n [class.fly-app-unavailable--compact]=\"compact()\"\n [attr.data-state]=\"state()\"\n role=\"status\"\n aria-live=\"polite\">\n <i class=\"pi {{ resolvedIcon() }} fly-app-unavailable__icon\" aria-hidden=\"true\"></i>\n\n <div class=\"fly-app-unavailable__body\">\n <p class=\"fly-app-unavailable__title\">{{ resolvedTitleKey() | translate }}</p>\n <p class=\"fly-app-unavailable__message\">\n {{\n resolvedMessageKey()\n | translate: { app: trimmedAppName() || ('app_unavailable.fallback_app' | translate) }\n }}\n </p>\n </div>\n\n <div class=\"fly-app-unavailable__actions\">\n <ng-content />\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:block;container-type:inline-size}.fly-app-unavailable{display:flex;align-items:flex-start;gap:12px;padding:20px;text-align:start;border:1px solid var(--surface-border);border-radius:10px;background:var(--surface-card);color:var(--text-color)}.fly-app-unavailable__icon{flex:0 0 auto;margin-block-start:2px;font-size:1.25rem;line-height:1;color:var(--text-color-secondary)}.fly-app-unavailable[data-state=unreachable] .fly-app-unavailable__icon{color:var(--system-red, var(--text-color-secondary))}.fly-app-unavailable__body{flex:1 1 auto;min-width:0}.fly-app-unavailable__title{margin:0;font-weight:600;font-size:.95rem;color:var(--text-color)}.fly-app-unavailable__message{margin:4px 0 0;font-size:.875rem;line-height:1.5;color:var(--text-color-secondary);overflow-wrap:anywhere}.fly-app-unavailable__actions{flex:0 0 auto;display:flex;align-items:center;gap:8px}.fly-app-unavailable__actions:empty{display:none}.fly-app-unavailable--compact{padding:12px 14px;border-radius:8px;gap:10px}.fly-app-unavailable--compact .fly-app-unavailable__icon{font-size:1rem}.fly-app-unavailable--compact .fly-app-unavailable__title{font-size:.875rem}.fly-app-unavailable--compact .fly-app-unavailable__message{font-size:.8125rem}@container (max-width: 380px){.fly-app-unavailable{flex-wrap:wrap}.fly-app-unavailable__actions{inline-size:100%;padding-inline-start:32px}}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
9786
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.19", type: FlyAppUnavailableComponent, isStandalone: true, selector: "fly-app-unavailable", inputs: { state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: false, transformFunction: null }, appName: { classPropertyName: "appName", publicName: "appName", isSignal: true, isRequired: false, transformFunction: null }, titleKey: { classPropertyName: "titleKey", publicName: "titleKey", isSignal: true, isRequired: false, transformFunction: null }, messageKey: { classPropertyName: "messageKey", publicName: "messageKey", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, compact: { classPropertyName: "compact", publicName: "compact", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\r\n class=\"fly-app-unavailable\"\r\n [class.fly-app-unavailable--compact]=\"compact()\"\r\n [attr.data-state]=\"state()\"\r\n role=\"status\"\r\n aria-live=\"polite\">\r\n <i class=\"pi {{ resolvedIcon() }} fly-app-unavailable__icon\" aria-hidden=\"true\"></i>\r\n\r\n <div class=\"fly-app-unavailable__body\">\r\n <p class=\"fly-app-unavailable__title\">{{ resolvedTitleKey() | translate }}</p>\r\n <p class=\"fly-app-unavailable__message\">\r\n {{\r\n resolvedMessageKey()\r\n | translate: { app: trimmedAppName() || ('app_unavailable.fallback_app' | translate) }\r\n }}\r\n </p>\r\n </div>\r\n\r\n <div class=\"fly-app-unavailable__actions\">\r\n <ng-content />\r\n </div>\r\n</div>\r\n", styles: ["@charset \"UTF-8\";:host{display:block;container-type:inline-size}.fly-app-unavailable{display:flex;align-items:flex-start;gap:12px;padding:20px;text-align:start;border:1px solid var(--surface-border);border-radius:10px;background:var(--surface-card);color:var(--text-color)}.fly-app-unavailable__icon{flex:0 0 auto;margin-block-start:2px;font-size:1.25rem;line-height:1;color:var(--text-color-secondary)}.fly-app-unavailable[data-state=unreachable] .fly-app-unavailable__icon{color:var(--system-red, var(--text-color-secondary))}.fly-app-unavailable__body{flex:1 1 auto;min-width:0}.fly-app-unavailable__title{margin:0;font-weight:600;font-size:.95rem;color:var(--text-color)}.fly-app-unavailable__message{margin:4px 0 0;font-size:.875rem;line-height:1.5;color:var(--text-color-secondary);overflow-wrap:anywhere}.fly-app-unavailable__actions{flex:0 0 auto;display:flex;align-items:center;gap:8px}.fly-app-unavailable__actions:empty{display:none}.fly-app-unavailable--compact{padding:12px 14px;border-radius:8px;gap:10px}.fly-app-unavailable--compact .fly-app-unavailable__icon{font-size:1rem}.fly-app-unavailable--compact .fly-app-unavailable__title{font-size:.875rem}.fly-app-unavailable--compact .fly-app-unavailable__message{font-size:.8125rem}@container (max-width: 380px){.fly-app-unavailable{flex-wrap:wrap}.fly-app-unavailable__actions{inline-size:100%;padding-inline-start:32px}}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
9751
9787
  }
9752
9788
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyAppUnavailableComponent, decorators: [{
9753
9789
  type: Component,
9754
- args: [{ selector: 'fly-app-unavailable', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"fly-app-unavailable\"\n [class.fly-app-unavailable--compact]=\"compact()\"\n [attr.data-state]=\"state()\"\n role=\"status\"\n aria-live=\"polite\">\n <i class=\"pi {{ resolvedIcon() }} fly-app-unavailable__icon\" aria-hidden=\"true\"></i>\n\n <div class=\"fly-app-unavailable__body\">\n <p class=\"fly-app-unavailable__title\">{{ resolvedTitleKey() | translate }}</p>\n <p class=\"fly-app-unavailable__message\">\n {{\n resolvedMessageKey()\n | translate: { app: trimmedAppName() || ('app_unavailable.fallback_app' | translate) }\n }}\n </p>\n </div>\n\n <div class=\"fly-app-unavailable__actions\">\n <ng-content />\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:block;container-type:inline-size}.fly-app-unavailable{display:flex;align-items:flex-start;gap:12px;padding:20px;text-align:start;border:1px solid var(--surface-border);border-radius:10px;background:var(--surface-card);color:var(--text-color)}.fly-app-unavailable__icon{flex:0 0 auto;margin-block-start:2px;font-size:1.25rem;line-height:1;color:var(--text-color-secondary)}.fly-app-unavailable[data-state=unreachable] .fly-app-unavailable__icon{color:var(--system-red, var(--text-color-secondary))}.fly-app-unavailable__body{flex:1 1 auto;min-width:0}.fly-app-unavailable__title{margin:0;font-weight:600;font-size:.95rem;color:var(--text-color)}.fly-app-unavailable__message{margin:4px 0 0;font-size:.875rem;line-height:1.5;color:var(--text-color-secondary);overflow-wrap:anywhere}.fly-app-unavailable__actions{flex:0 0 auto;display:flex;align-items:center;gap:8px}.fly-app-unavailable__actions:empty{display:none}.fly-app-unavailable--compact{padding:12px 14px;border-radius:8px;gap:10px}.fly-app-unavailable--compact .fly-app-unavailable__icon{font-size:1rem}.fly-app-unavailable--compact .fly-app-unavailable__title{font-size:.875rem}.fly-app-unavailable--compact .fly-app-unavailable__message{font-size:.8125rem}@container (max-width: 380px){.fly-app-unavailable{flex-wrap:wrap}.fly-app-unavailable__actions{inline-size:100%;padding-inline-start:32px}}\n"] }]
9790
+ args: [{ selector: 'fly-app-unavailable', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\r\n class=\"fly-app-unavailable\"\r\n [class.fly-app-unavailable--compact]=\"compact()\"\r\n [attr.data-state]=\"state()\"\r\n role=\"status\"\r\n aria-live=\"polite\">\r\n <i class=\"pi {{ resolvedIcon() }} fly-app-unavailable__icon\" aria-hidden=\"true\"></i>\r\n\r\n <div class=\"fly-app-unavailable__body\">\r\n <p class=\"fly-app-unavailable__title\">{{ resolvedTitleKey() | translate }}</p>\r\n <p class=\"fly-app-unavailable__message\">\r\n {{\r\n resolvedMessageKey()\r\n | translate: { app: trimmedAppName() || ('app_unavailable.fallback_app' | translate) }\r\n }}\r\n </p>\r\n </div>\r\n\r\n <div class=\"fly-app-unavailable__actions\">\r\n <ng-content />\r\n </div>\r\n</div>\r\n", styles: ["@charset \"UTF-8\";:host{display:block;container-type:inline-size}.fly-app-unavailable{display:flex;align-items:flex-start;gap:12px;padding:20px;text-align:start;border:1px solid var(--surface-border);border-radius:10px;background:var(--surface-card);color:var(--text-color)}.fly-app-unavailable__icon{flex:0 0 auto;margin-block-start:2px;font-size:1.25rem;line-height:1;color:var(--text-color-secondary)}.fly-app-unavailable[data-state=unreachable] .fly-app-unavailable__icon{color:var(--system-red, var(--text-color-secondary))}.fly-app-unavailable__body{flex:1 1 auto;min-width:0}.fly-app-unavailable__title{margin:0;font-weight:600;font-size:.95rem;color:var(--text-color)}.fly-app-unavailable__message{margin:4px 0 0;font-size:.875rem;line-height:1.5;color:var(--text-color-secondary);overflow-wrap:anywhere}.fly-app-unavailable__actions{flex:0 0 auto;display:flex;align-items:center;gap:8px}.fly-app-unavailable__actions:empty{display:none}.fly-app-unavailable--compact{padding:12px 14px;border-radius:8px;gap:10px}.fly-app-unavailable--compact .fly-app-unavailable__icon{font-size:1rem}.fly-app-unavailable--compact .fly-app-unavailable__title{font-size:.875rem}.fly-app-unavailable--compact .fly-app-unavailable__message{font-size:.8125rem}@container (max-width: 380px){.fly-app-unavailable{flex-wrap:wrap}.fly-app-unavailable__actions{inline-size:100%;padding-inline-start:32px}}\n"] }]
9755
9791
  }], propDecorators: { state: [{ type: i0.Input, args: [{ isSignal: true, alias: "state", required: false }] }], appName: [{ type: i0.Input, args: [{ isSignal: true, alias: "appName", required: false }] }], titleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleKey", required: false }] }], messageKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "messageKey", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], compact: [{ type: i0.Input, args: [{ isSignal: true, alias: "compact", required: false }] }] } });
9756
9792
 
9757
9793
  /**
@@ -15855,7 +15891,9 @@ function actionFingerprint(action) {
15855
15891
  paramsFingerprint(menu.titleParams),
15856
15892
  menu.value,
15857
15893
  menu.defaultValue,
15858
- menu.options.map((o) => [o.value, o.labelKey, paramsFingerprint(o.labelParams)]),
15894
+ // `label ?? null` so a RENAMED tenant row (campaign, area) repaints; null keeps a
15895
+ // key-only option's fingerprint byte-identical to what it was before the field existed.
15896
+ menu.options.map((o) => [o.value, o.labelKey, paramsFingerprint(o.labelParams), o.label ?? null]),
15859
15897
  !!menu.onSelect,
15860
15898
  ]
15861
15899
  : null,
@@ -15945,6 +15983,9 @@ function projectMenu(action, handlers) {
15945
15983
  value: o.value,
15946
15984
  labelKey: o.labelKey,
15947
15985
  ...(o.labelParams === undefined ? {} : { labelParams: o.labelParams }),
15986
+ // Conditional, like every other optional field here: an explicit `label: undefined` is
15987
+ // `in`-visible on the object and would make "absent" and "present but empty" compare equal.
15988
+ ...(o.label === undefined ? {} : { label: o.label }),
15948
15989
  })),
15949
15990
  value: menu.value,
15950
15991
  defaultValue: menu.defaultValue,
@@ -16118,10 +16159,7 @@ class MagicBarRegistry {
16118
16159
  */
16119
16160
  active = computed(() => {
16120
16161
  const owner = this._activeOwner();
16121
- if (!owner)
16122
- return null;
16123
- const views = this._views();
16124
- return resolveView((key) => views.get(key), owner);
16162
+ return owner ? this.resolve(owner) : null;
16125
16163
  }, ...(ngDevMode ? [{ debugName: "active" }] : /* istanbul ignore next */ []));
16126
16164
  constructor() {
16127
16165
  const g = globalThis;
@@ -16224,6 +16262,20 @@ class MagicBarRegistry {
16224
16262
  this.sync();
16225
16263
  emitSync();
16226
16264
  }
16265
+ /**
16266
+ * Resolve one owner's view from the reactive MIRROR — {@link viewFor}'s
16267
+ * signal-consuming sibling, and the read behind {@link active}. Calling it
16268
+ * inside a `computed()`/`effect()` tracks the mirror, so the caller re-runs
16269
+ * whenever this owner's slot changes — which is what an inline renderer
16270
+ * outside the shell (an External App's standalone chrome, D5 §4 dynamic 6's
16271
+ * mobile bar) needs, since no shell ever nominates an owner there. Applies
16272
+ * the same resolution as {@link active}: exact slot, then the `appId`
16273
+ * fallback, then the ownership assertion.
16274
+ */
16275
+ resolve(owner) {
16276
+ const views = this._views();
16277
+ return resolveView((key) => views.get(key), owner);
16278
+ }
16227
16279
  /**
16228
16280
  * Direct, non-reactive read of one owner's contribution — the split-proof
16229
16281
  * escape hatch for callers outside an injection/reactive context. Applies the
@@ -16834,7 +16886,13 @@ class FlyMagicActionsComponent {
16834
16886
  if (!menu)
16835
16887
  return this.resolvedLabel(action);
16836
16888
  const current = menu.options.find((o) => o.value === menu.value);
16837
- const value = current ? this.i18n.t(current.labelKey, current.labelParams) : menu.value;
16889
+ // Same precedence as the rows otherwise the trigger would announce a translated
16890
+ // placeholder while the open menu shows the tenant's actual name.
16891
+ const value = current
16892
+ ? current.label?.trim()
16893
+ ? current.label
16894
+ : this.i18n.t(current.labelKey, current.labelParams)
16895
+ : menu.value;
16838
16896
  return this.i18n.t('magic_actions.radio_menu.trigger_label', {
16839
16897
  label: this.resolvedLabel(action),
16840
16898
  value,
@@ -16884,7 +16942,10 @@ class FlyMagicActionsComponent {
16884
16942
  return [];
16885
16943
  const items = menu.options.map((option) => ({
16886
16944
  id: option.value,
16887
- label: this.i18n.t(option.labelKey, option.labelParams),
16945
+ // Tenant data wins over the key: `label` is a campaign/area name read from the publisher's
16946
+ // own rows, which no locale bundle can contain. Falls back to the key when absent OR when
16947
+ // the data-derived text is empty, so a blank row can never render as a nameless option.
16948
+ label: option.label?.trim() ? option.label : this.i18n.t(option.labelKey, option.labelParams),
16888
16949
  // `selected` is what makes this a real radio menu rather than a list with
16889
16950
  // a tick: `fly-context-menu` renders a selected row as
16890
16951
  // `role="menuitemradio"` + `aria-checked`, with the check indicator and
@@ -16971,13 +17032,13 @@ class FlyMagicActionsComponent {
16971
17032
  this.isOverflowing.set(!!el && el.scrollWidth - el.clientWidth > 1);
16972
17033
  }
16973
17034
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyMagicActionsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
16974
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyMagicActionsComponent, isStandalone: true, selector: "fly-magic-actions", inputs: { groups: { classPropertyName: "groups", publicName: "groups", isSignal: true, isRequired: true, transformFunction: null }, primary: { classPropertyName: "primary", publicName: "primary", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.dir": "i18n.direction()" } }, viewQueries: [{ propertyName: "rowRef", first: true, predicate: ["row"], descendants: true, isSignal: true }], ngImport: i0, template: "<!--\r\n Icon-only buttons carry the accessible name via [attr.aria-label] \u2014 the SVG\r\n glyph itself is aria-hidden (decorative, skill \u00A7accessibility rule 5). `kind:\r\n 'text'` actions rely on their own visible text instead. Disabled rows stay\r\n `aria-disabled` (never native `disabled`) so they remain focusable/hoverable \u2014\r\n a disabled action's whole point is to explain ITSELF via the auto-suffixed\r\n tooltip, which native `disabled` would suppress.\r\n\r\n The glyph is composed from ALLOWLISTED nodes bound as real attributes, never\r\n from `[innerHTML]`: `iconPath` is publisher-supplied, and an `<svg>` fragment\r\n is not a closed world (`<foreignObject>` is an HTML integration point, `<a\r\n xlink:href=\"javascript:\u2026\">` is live under the very click this button invites).\r\n `magic-actions-icon.ts` carries the full rationale; the shape below is its\r\n consequence \u2014 an attribute binding cannot introduce an element or a handler,\r\n so there is nothing left to sanitize.\r\n\r\n That block is authored ONCE, as `#actionButton`, and stamped by every place a\r\n contributed action is painted (group items and `primary`). It used to be\r\n inline in the group loop, which was fine while this component rendered groups\r\n only; with `primary` here too, a second copy would mean the next edit to the\r\n SECURITY-CRITICAL binding shape has to be made twice and can be made once.\r\n-->\r\n<ng-template #actionButton let-projected>\r\n <!--\r\n `let-projected` is `any` \u2014 Angular infers nothing for an `ngTemplateOutlet`\r\n context, and there is no built-in way to declare one. `asAction` is an\r\n identity function whose only job is to give this block a TYPED local, so\r\n every read below (`.kind`, `.disabled`, `.menu`) is checked by the template\r\n compiler instead of silently resolving to `undefined` on a typo. Without it\r\n the one place a `MagicBarActionView` is actually painted would be the one\r\n place its shape is not verified.\r\n -->\r\n @let action = asAction(projected);\r\n @if (action.kind === 'text') {\r\n <button\r\n type=\"button\"\r\n class=\"fma-btn fma-btn--text\"\r\n [attr.data-tone]=\"toneAttr(action)\"\r\n [attr.aria-disabled]=\"action.disabled ? 'true' : null\"\r\n [attr.aria-pressed]=\"pressedAttr(action)\"\r\n [flyTooltip]=\"tooltipFor(action)\"\r\n [flyTooltipDelay]=\"450\"\r\n (click)=\"activate(action, $event)\"\r\n >{{ resolvedLabel(action) }}</button>\r\n } @else {\r\n <button\r\n type=\"button\"\r\n class=\"fma-btn\"\r\n [class.fma-btn--badge]=\"hasBadge(action)\"\r\n [attr.data-tone]=\"toneAttr(action)\"\r\n [attr.aria-disabled]=\"action.disabled ? 'true' : null\"\r\n [attr.aria-pressed]=\"pressedAttr(action)\"\r\n [attr.aria-haspopup]=\"action.menu ? 'menu' : null\"\r\n [attr.aria-expanded]=\"action.menu ? (openMenuActionId() === action.id ? 'true' : 'false') : null\"\r\n [attr.aria-label]=\"action.menu ? triggerAriaLabel(action) : resolvedLabel(action)\"\r\n [flyTooltip]=\"tooltipFor(action)\"\r\n [flyTooltipDelay]=\"450\"\r\n (click)=\"activate(action, $event)\"\r\n >\r\n <svg\r\n class=\"fma-btn__icon\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"1.8\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n aria-hidden=\"true\"\r\n >\r\n @for (node of iconNodes(action); track $index) {\r\n @switch (node.tag) {\r\n @case ('path') {\r\n <svg:path\r\n [attr.d]=\"node.attrs['d']\"\r\n [attr.fill-rule]=\"node.attrs['fill-rule']\"\r\n [attr.clip-rule]=\"node.attrs['clip-rule']\"\r\n />\r\n }\r\n @case ('circle') {\r\n <svg:circle\r\n [attr.cx]=\"node.attrs['cx']\"\r\n [attr.cy]=\"node.attrs['cy']\"\r\n [attr.r]=\"node.attrs['r']\"\r\n />\r\n }\r\n @case ('rect') {\r\n <svg:rect\r\n [attr.x]=\"node.attrs['x']\"\r\n [attr.y]=\"node.attrs['y']\"\r\n [attr.width]=\"node.attrs['width']\"\r\n [attr.height]=\"node.attrs['height']\"\r\n [attr.rx]=\"node.attrs['rx']\"\r\n [attr.ry]=\"node.attrs['ry']\"\r\n />\r\n }\r\n @case ('ellipse') {\r\n <svg:ellipse\r\n [attr.cx]=\"node.attrs['cx']\"\r\n [attr.cy]=\"node.attrs['cy']\"\r\n [attr.rx]=\"node.attrs['rx']\"\r\n [attr.ry]=\"node.attrs['ry']\"\r\n />\r\n }\r\n @case ('line') {\r\n <svg:line\r\n [attr.x1]=\"node.attrs['x1']\"\r\n [attr.y1]=\"node.attrs['y1']\"\r\n [attr.x2]=\"node.attrs['x2']\"\r\n [attr.y2]=\"node.attrs['y2']\"\r\n />\r\n }\r\n @case ('polyline') {\r\n <svg:polyline [attr.points]=\"node.attrs['points']\" />\r\n }\r\n @case ('polygon') {\r\n <svg:polygon [attr.points]=\"node.attrs['points']\" />\r\n }\r\n }\r\n }\r\n </svg>\r\n @if (hasBadge(action)) {\r\n <span class=\"fma-btn__badge\" aria-hidden=\"true\"></span>\r\n }\r\n </button>\r\n }\r\n</ng-template>\r\n\r\n<!--\r\n `.fma` is the SCROLLING row and holds the contributed groups only. The accent\r\n CTA is a SIBLING of it, outside the fade mask and outside the scroll container,\r\n because it is the row's anchor \u2014 a call to action that dissolves into a\r\n gradient, or that you have to scroll sideways to reach, inverts the affordance.\r\n It is also what makes `isOverflowing` measurable at all: see the component.\r\n-->\r\n@if (groups().length) {\r\n <div #row class=\"fma\" [class.fma--overflow]=\"isOverflowing()\">\r\n @for (group of groups(); track group.id) {\r\n <div\r\n class=\"fma-group\"\r\n [class.fma-group--framed]=\"group.framed\"\r\n role=\"group\"\r\n [attr.aria-label]=\"i18n.t(group.labelKey)\"\r\n >\r\n @for (action of group.items; track action.id) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"actionButton\"\r\n [ngTemplateOutletContext]=\"{ $implicit: action }\"\r\n />\r\n }\r\n </div>\r\n @if (group.framed) {\r\n <span class=\"fma-sep\" aria-hidden=\"true\"></span>\r\n }\r\n }\r\n </div>\r\n}\r\n\r\n<!--\r\n The accent CTA. The disc is a WRAPPER, not a modifier on the button, and that\r\n is load-bearing rather than cosmetic: `.fma-btn`'s hover/press feedback is an\r\n `animation` (`iconWiggle` / `iconBounce`), and an animation that touches\r\n `transform` beats a declared `transform` \u2014 so a hover lift authored on the\r\n button itself would simply never render. The wrapper owns the disc, the lift\r\n and the shadow; the button stays transparent and keeps the DS's own toolbar\r\n feedback. It re-points `--chrome-ink` rather than styling `.fma-btn` through a\r\n descendant selector so the glyph colour inherits the way custom properties do.\r\n-->\r\n@if (primary(); as p) {\r\n <span class=\"fma-primary\" [class.fma-primary--disabled]=\"p.disabled\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"actionButton\"\r\n [ngTemplateOutletContext]=\"{ $implicit: p }\"\r\n />\r\n </span>\r\n}\r\n\r\n<!--\r\n ONE radio menu, hoisted out of the group loops (S1-review F9). Only one is open\r\n at a time (`openMenuActionId`), so a single instance is enough \u2014 and rendering\r\n it beside its button would insert a non-`.fma-btn` element into the group,\r\n silently shifting every later button's `:nth-child` index and with it the\r\n `toolbarPopIn` stagger delay the `.fma-btn` rule assigns. Keeping every\r\n staggered parent's children homogeneous is what makes that rule's comment true.\r\n It portals itself to <body>, so its position is unaffected by where it is\r\n declared.\r\n-->\r\n@if (openAction(); as open) {\r\n <fly-context-menu\r\n [anchor]=\"menuAnchorEl()\"\r\n [sections]=\"menuSections(open)\"\r\n (action)=\"onMenuAction(open, $event)\"\r\n (closed)=\"closeMenu()\"\r\n />\r\n}\r\n", styles: [":host{display:flex;align-items:center;gap:8px;min-inline-size:0}.fma{display:flex;align-items:center;gap:8px;flex:0 1 auto;min-inline-size:0;overflow:hidden;flex-wrap:nowrap}.fma--overflow{overflow-x:auto;scrollbar-width:none;-ms-overflow-style:none;-webkit-mask-image:linear-gradient(to right,#000 calc(100% - 28px),transparent 100%);mask-image:linear-gradient(to right,#000 calc(100% - 28px),transparent 100%)}.fma--overflow::-webkit-scrollbar{display:none}:host([dir=rtl]) .fma--overflow{-webkit-mask-image:linear-gradient(to left,#000 calc(100% - 28px),transparent 100%);mask-image:linear-gradient(to left,#000 calc(100% - 28px),transparent 100%)}.fma-group{display:flex;align-items:center;gap:8px;flex:none}.fma-group--framed{gap:2px}.fma-sep{flex:0 0 auto;inline-size:1px;block-size:18px;background:var(--w14)}.fma-btn{position:relative;flex:0 0 auto;inline-size:30px;block-size:30px;display:grid;place-items:center;border:0;border-radius:50%;background:transparent;color:var(--chrome-ink);cursor:pointer;padding:0;animation:toolbarPopIn .3s var(--nova-ease-structural) both}.fma-btn:nth-child(1){animation-delay:0ms}.fma-btn:nth-child(2){animation-delay:40ms}.fma-btn:nth-child(3){animation-delay:80ms}.fma-btn:nth-child(4){animation-delay:.12s}.fma-btn:nth-child(5){animation-delay:.16s}.fma-btn:nth-child(6){animation-delay:.2s}.fma-btn:nth-child(7){animation-delay:.24s}.fma-btn:nth-child(8){animation-delay:.28s}.fma-btn:nth-child(9){animation-delay:.32s}.fma-btn:nth-child(10){animation-delay:.36s}.fma-btn:nth-child(11){animation-delay:.4s}.fma-btn:nth-child(12){animation-delay:.44s}.fma-btn:nth-child(n+13){animation-delay:.44s}.fma-btn:not([aria-disabled=true]):hover{background:var(--w1);color:var(--chrome-ink-hover);animation:iconWiggle .5s ease}.fma-btn:not([aria-disabled=true]):active{animation:iconBounce .38s var(--nova-ease-overshoot)}.fma-btn:focus-visible{outline:3px solid var(--accent);outline-offset:3px;border-radius:inherit}.fma-btn[data-tone=danger]{color:var(--sys-red)}.fma-btn[data-tone=danger]:not([aria-disabled=true]):hover{background:color-mix(in oklab,var(--sys-red) 18%,transparent);color:var(--sys-red)}.fma-btn[data-tone=success]{color:var(--sys-green)}.fma-btn[data-tone=success]:not([aria-disabled=true]):hover{background:color-mix(in oklab,var(--sys-green) 18%,transparent);color:var(--sys-green)}.fma-btn[aria-pressed=true]{background:var(--tint-sel);color:var(--chrome-ink-hover)}.fma-btn[aria-pressed=true][data-tone=success]{background:color-mix(in oklab,var(--sys-green) 22%,transparent);color:var(--sys-green)}.fma-btn[aria-disabled=true]{opacity:.38;filter:saturate(.6);animation:none;cursor:default}.fma-btn__icon{inline-size:16px;block-size:16px;pointer-events:none}.fma-btn__badge{position:absolute;inset-block-start:3px;inset-inline-end:3px;inline-size:7px;block-size:7px;border-radius:50%;background:var(--accent);pointer-events:none}.fma-primary{--chrome-ink: var(--on-accent);--chrome-ink-hover: var(--on-accent);flex:none;display:grid;place-items:center;inline-size:30px;block-size:30px;border-radius:50%;background:var(--accent);transition:box-shadow var(--nova-duration-hover) var(--nova-ease-micro),transform var(--nova-duration-hover) var(--nova-ease-micro)}.fma-primary:hover{box-shadow:0 8px 20px var(--tint-sel);transform:translateY(-1px)}.fma-primary--disabled{opacity:.38;filter:saturate(.6)}.fma-primary--disabled:hover{box-shadow:none;transform:none}.fma-btn--text{inline-size:auto;block-size:30px;border-radius:99px;padding-inline:12px;font-family:inherit;font-size:12.5px;font-weight:600;line-height:1;white-space:nowrap}@media(pointer:coarse){.fma-btn{inline-size:44px;block-size:44px}.fma-btn--text{inline-size:auto;min-inline-size:44px}.fma-primary{inline-size:44px;block-size:44px}}\n"], dependencies: [{ kind: "component", type: ContextMenuComponent, selector: "fly-context-menu", inputs: ["x", "y", "anchor", "align", "placement", "sections", "boundary"], outputs: ["action", "closed"] }, { kind: "directive", type: FlyTooltipDirective, selector: "[flyTooltip], [data-tooltip]", inputs: ["flyTooltip", "flyTooltipPlacement", "flyTooltipDisabled", "flyTooltipDelay"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
17035
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyMagicActionsComponent, isStandalone: true, selector: "fly-magic-actions", inputs: { groups: { classPropertyName: "groups", publicName: "groups", isSignal: true, isRequired: true, transformFunction: null }, primary: { classPropertyName: "primary", publicName: "primary", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.dir": "i18n.direction()" } }, viewQueries: [{ propertyName: "rowRef", first: true, predicate: ["row"], descendants: true, isSignal: true }], ngImport: i0, template: "<!--\n Icon-only buttons carry the accessible name via [attr.aria-label] \u2014 the SVG\n glyph itself is aria-hidden (decorative, skill \u00A7accessibility rule 5). `kind:\n 'text'` actions rely on their own visible text instead. Disabled rows stay\n `aria-disabled` (never native `disabled`) so they remain focusable/hoverable \u2014\n a disabled action's whole point is to explain ITSELF via the auto-suffixed\n tooltip, which native `disabled` would suppress.\n\n The glyph is composed from ALLOWLISTED nodes bound as real attributes, never\n from `[innerHTML]`: `iconPath` is publisher-supplied, and an `<svg>` fragment\n is not a closed world (`<foreignObject>` is an HTML integration point, `<a\n xlink:href=\"javascript:\u2026\">` is live under the very click this button invites).\n `magic-actions-icon.ts` carries the full rationale; the shape below is its\n consequence \u2014 an attribute binding cannot introduce an element or a handler,\n so there is nothing left to sanitize.\n\n That block is authored ONCE, as `#actionButton`, and stamped by every place a\n contributed action is painted (group items and `primary`). It used to be\n inline in the group loop, which was fine while this component rendered groups\n only; with `primary` here too, a second copy would mean the next edit to the\n SECURITY-CRITICAL binding shape has to be made twice and can be made once.\n-->\n<!--\n `data-action` carries the publisher's action `id` verbatim \u2014 the one stable, LOCALE-INDEPENDENT\n handle on a rendered action. Every other identifying attribute here is translated\n (`aria-label`, the tooltip), so an e2e suite that targeted them had to assert in one language,\n and one that targeted a bespoke button lost its hook entirely when the action moved into the\n bar. That is not hypothetical: PPM's project-closure suite could not adopt the contract for\n exactly this reason. It is an ATTRIBUTE, not a class, so it never participates in styling, and\n `id` is already unique across the whole contribution (the projection enforces it), so it is\n unique in the DOM too.\n-->\n<ng-template #actionButton let-projected>\n <!--\n `let-projected` is `any` \u2014 Angular infers nothing for an `ngTemplateOutlet`\n context, and there is no built-in way to declare one. `asAction` is an\n identity function whose only job is to give this block a TYPED local, so\n every read below (`.kind`, `.disabled`, `.menu`) is checked by the template\n compiler instead of silently resolving to `undefined` on a typo. Without it\n the one place a `MagicBarActionView` is actually painted would be the one\n place its shape is not verified.\n -->\n @let action = asAction(projected);\n @if (action.kind === 'text') {\n <button\n type=\"button\"\n class=\"fma-btn fma-btn--text\"\n [attr.data-action]=\"action.id\"\n [attr.data-tone]=\"toneAttr(action)\"\n [attr.aria-disabled]=\"action.disabled ? 'true' : null\"\n [attr.aria-pressed]=\"pressedAttr(action)\"\n [flyTooltip]=\"tooltipFor(action)\"\n [flyTooltipDelay]=\"450\"\n (click)=\"activate(action, $event)\"\n >{{ resolvedLabel(action) }}</button>\n } @else {\n <button\n type=\"button\"\n class=\"fma-btn\"\n [class.fma-btn--badge]=\"hasBadge(action)\"\n [attr.data-action]=\"action.id\"\n [attr.data-tone]=\"toneAttr(action)\"\n [attr.aria-disabled]=\"action.disabled ? 'true' : null\"\n [attr.aria-pressed]=\"pressedAttr(action)\"\n [attr.aria-haspopup]=\"action.menu ? 'menu' : null\"\n [attr.aria-expanded]=\"action.menu ? (openMenuActionId() === action.id ? 'true' : 'false') : null\"\n [attr.aria-label]=\"action.menu ? triggerAriaLabel(action) : resolvedLabel(action)\"\n [flyTooltip]=\"tooltipFor(action)\"\n [flyTooltipDelay]=\"450\"\n (click)=\"activate(action, $event)\"\n >\n <svg\n class=\"fma-btn__icon\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.8\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n @for (node of iconNodes(action); track $index) {\n @switch (node.tag) {\n @case ('path') {\n <svg:path\n [attr.d]=\"node.attrs['d']\"\n [attr.fill-rule]=\"node.attrs['fill-rule']\"\n [attr.clip-rule]=\"node.attrs['clip-rule']\"\n />\n }\n @case ('circle') {\n <svg:circle\n [attr.cx]=\"node.attrs['cx']\"\n [attr.cy]=\"node.attrs['cy']\"\n [attr.r]=\"node.attrs['r']\"\n />\n }\n @case ('rect') {\n <svg:rect\n [attr.x]=\"node.attrs['x']\"\n [attr.y]=\"node.attrs['y']\"\n [attr.width]=\"node.attrs['width']\"\n [attr.height]=\"node.attrs['height']\"\n [attr.rx]=\"node.attrs['rx']\"\n [attr.ry]=\"node.attrs['ry']\"\n />\n }\n @case ('ellipse') {\n <svg:ellipse\n [attr.cx]=\"node.attrs['cx']\"\n [attr.cy]=\"node.attrs['cy']\"\n [attr.rx]=\"node.attrs['rx']\"\n [attr.ry]=\"node.attrs['ry']\"\n />\n }\n @case ('line') {\n <svg:line\n [attr.x1]=\"node.attrs['x1']\"\n [attr.y1]=\"node.attrs['y1']\"\n [attr.x2]=\"node.attrs['x2']\"\n [attr.y2]=\"node.attrs['y2']\"\n />\n }\n @case ('polyline') {\n <svg:polyline [attr.points]=\"node.attrs['points']\" />\n }\n @case ('polygon') {\n <svg:polygon [attr.points]=\"node.attrs['points']\" />\n }\n }\n }\n </svg>\n @if (hasBadge(action)) {\n <span class=\"fma-btn__badge\" aria-hidden=\"true\"></span>\n }\n </button>\n }\n</ng-template>\n\n<!--\n `.fma` is the SCROLLING row and holds the contributed groups only. The accent\n CTA is a SIBLING of it, outside the fade mask and outside the scroll container,\n because it is the row's anchor \u2014 a call to action that dissolves into a\n gradient, or that you have to scroll sideways to reach, inverts the affordance.\n It is also what makes `isOverflowing` measurable at all: see the component.\n-->\n@if (groups().length) {\n <div #row class=\"fma\" [class.fma--overflow]=\"isOverflowing()\">\n @for (group of groups(); track group.id) {\n <div\n class=\"fma-group\"\n [class.fma-group--framed]=\"group.framed\"\n role=\"group\"\n [attr.aria-label]=\"i18n.t(group.labelKey)\"\n >\n @for (action of group.items; track action.id) {\n <ng-container\n [ngTemplateOutlet]=\"actionButton\"\n [ngTemplateOutletContext]=\"{ $implicit: action }\"\n />\n }\n </div>\n @if (group.framed) {\n <span class=\"fma-sep\" aria-hidden=\"true\"></span>\n }\n }\n </div>\n}\n\n<!--\n The accent CTA. The disc is a WRAPPER, not a modifier on the button, and that\n is load-bearing rather than cosmetic: `.fma-btn`'s hover/press feedback is an\n `animation` (`iconWiggle` / `iconBounce`), and an animation that touches\n `transform` beats a declared `transform` \u2014 so a hover lift authored on the\n button itself would simply never render. The wrapper owns the disc, the lift\n and the shadow; the button stays transparent and keeps the DS's own toolbar\n feedback. It re-points `--chrome-ink` rather than styling `.fma-btn` through a\n descendant selector so the glyph colour inherits the way custom properties do.\n-->\n@if (primary(); as p) {\n <span class=\"fma-primary\" [class.fma-primary--disabled]=\"p.disabled\">\n <ng-container\n [ngTemplateOutlet]=\"actionButton\"\n [ngTemplateOutletContext]=\"{ $implicit: p }\"\n />\n </span>\n}\n\n<!--\n ONE radio menu, hoisted out of the group loops (S1-review F9). Only one is open\n at a time (`openMenuActionId`), so a single instance is enough \u2014 and rendering\n it beside its button would insert a non-`.fma-btn` element into the group,\n silently shifting every later button's `:nth-child` index and with it the\n `toolbarPopIn` stagger delay the `.fma-btn` rule assigns. Keeping every\n staggered parent's children homogeneous is what makes that rule's comment true.\n It portals itself to <body>, so its position is unaffected by where it is\n declared.\n-->\n@if (openAction(); as open) {\n <fly-context-menu\n [anchor]=\"menuAnchorEl()\"\n [sections]=\"menuSections(open)\"\n (action)=\"onMenuAction(open, $event)\"\n (closed)=\"closeMenu()\"\n />\n}\n", styles: [":host{display:flex;align-items:center;gap:8px;min-inline-size:0}.fma{display:flex;align-items:center;gap:8px;flex:0 1 auto;min-inline-size:0;overflow:hidden;flex-wrap:nowrap}.fma--overflow{overflow-x:auto;scrollbar-width:none;-ms-overflow-style:none;-webkit-mask-image:linear-gradient(to right,#000 calc(100% - 28px),transparent 100%);mask-image:linear-gradient(to right,#000 calc(100% - 28px),transparent 100%)}.fma--overflow::-webkit-scrollbar{display:none}:host([dir=rtl]) .fma--overflow{-webkit-mask-image:linear-gradient(to left,#000 calc(100% - 28px),transparent 100%);mask-image:linear-gradient(to left,#000 calc(100% - 28px),transparent 100%)}.fma-group{display:flex;align-items:center;gap:8px;flex:none}.fma-group--framed{gap:2px}.fma-sep{flex:0 0 auto;inline-size:1px;block-size:18px;background:var(--w14)}.fma-btn{position:relative;flex:0 0 auto;inline-size:30px;block-size:30px;display:grid;place-items:center;border:0;border-radius:50%;background:transparent;color:var(--chrome-ink);cursor:pointer;padding:0;animation:toolbarPopIn .3s var(--nova-ease-structural) both}.fma-btn:nth-child(1){animation-delay:0ms}.fma-btn:nth-child(2){animation-delay:40ms}.fma-btn:nth-child(3){animation-delay:80ms}.fma-btn:nth-child(4){animation-delay:.12s}.fma-btn:nth-child(5){animation-delay:.16s}.fma-btn:nth-child(6){animation-delay:.2s}.fma-btn:nth-child(7){animation-delay:.24s}.fma-btn:nth-child(8){animation-delay:.28s}.fma-btn:nth-child(9){animation-delay:.32s}.fma-btn:nth-child(10){animation-delay:.36s}.fma-btn:nth-child(11){animation-delay:.4s}.fma-btn:nth-child(12){animation-delay:.44s}.fma-btn:nth-child(n+13){animation-delay:.44s}.fma-btn:not([aria-disabled=true]):hover{background:var(--w1);color:var(--chrome-ink-hover);animation:iconWiggle .5s ease}.fma-btn:not([aria-disabled=true]):active{animation:iconBounce .38s var(--nova-ease-overshoot)}.fma-btn:focus-visible{outline:3px solid var(--accent);outline-offset:3px;border-radius:inherit}.fma-btn[data-tone=danger]{color:var(--sys-red)}.fma-btn[data-tone=danger]:not([aria-disabled=true]):hover{background:color-mix(in oklab,var(--sys-red) 18%,transparent);color:var(--sys-red)}.fma-btn[data-tone=success]{color:var(--sys-green)}.fma-btn[data-tone=success]:not([aria-disabled=true]):hover{background:color-mix(in oklab,var(--sys-green) 18%,transparent);color:var(--sys-green)}.fma-btn[aria-pressed=true]{background:var(--tint-sel);color:var(--chrome-ink-hover)}.fma-btn[aria-pressed=true][data-tone=success]{background:color-mix(in oklab,var(--sys-green) 22%,transparent);color:var(--sys-green)}.fma-btn[aria-disabled=true]{opacity:.38;filter:saturate(.6);animation:none;cursor:default}.fma-btn__icon{inline-size:16px;block-size:16px;pointer-events:none}.fma-btn__badge{position:absolute;inset-block-start:3px;inset-inline-end:3px;inline-size:7px;block-size:7px;border-radius:50%;background:var(--accent);pointer-events:none}.fma-primary{--chrome-ink: var(--on-accent);--chrome-ink-hover: var(--on-accent);flex:none;display:grid;place-items:center;inline-size:30px;block-size:30px;border-radius:50%;background:var(--accent);transition:box-shadow var(--nova-duration-hover) var(--nova-ease-micro),transform var(--nova-duration-hover) var(--nova-ease-micro)}.fma-primary:hover{box-shadow:0 8px 20px var(--tint-sel);transform:translateY(-1px)}.fma-primary--disabled{opacity:.38;filter:saturate(.6)}.fma-primary--disabled:hover{box-shadow:none;transform:none}.fma-btn--text{inline-size:auto;block-size:30px;border-radius:99px;padding-inline:12px;font-family:inherit;font-size:12.5px;font-weight:600;line-height:1;white-space:nowrap}@media(pointer:coarse){.fma-btn{inline-size:44px;block-size:44px}.fma-btn--text{inline-size:auto;min-inline-size:44px}.fma-primary{inline-size:44px;block-size:44px}}\n"], dependencies: [{ kind: "component", type: ContextMenuComponent, selector: "fly-context-menu", inputs: ["x", "y", "anchor", "align", "placement", "sections", "boundary"], outputs: ["action", "closed"] }, { kind: "directive", type: FlyTooltipDirective, selector: "[flyTooltip], [data-tooltip]", inputs: ["flyTooltip", "flyTooltipPlacement", "flyTooltipDisabled", "flyTooltipDelay"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
16975
17036
  }
16976
17037
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyMagicActionsComponent, decorators: [{
16977
17038
  type: Component,
16978
17039
  args: [{ selector: 'fly-magic-actions', standalone: true, imports: [ContextMenuComponent, FlyTooltipDirective, NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, host: {
16979
17040
  '[attr.dir]': 'i18n.direction()',
16980
- }, template: "<!--\r\n Icon-only buttons carry the accessible name via [attr.aria-label] \u2014 the SVG\r\n glyph itself is aria-hidden (decorative, skill \u00A7accessibility rule 5). `kind:\r\n 'text'` actions rely on their own visible text instead. Disabled rows stay\r\n `aria-disabled` (never native `disabled`) so they remain focusable/hoverable \u2014\r\n a disabled action's whole point is to explain ITSELF via the auto-suffixed\r\n tooltip, which native `disabled` would suppress.\r\n\r\n The glyph is composed from ALLOWLISTED nodes bound as real attributes, never\r\n from `[innerHTML]`: `iconPath` is publisher-supplied, and an `<svg>` fragment\r\n is not a closed world (`<foreignObject>` is an HTML integration point, `<a\r\n xlink:href=\"javascript:\u2026\">` is live under the very click this button invites).\r\n `magic-actions-icon.ts` carries the full rationale; the shape below is its\r\n consequence \u2014 an attribute binding cannot introduce an element or a handler,\r\n so there is nothing left to sanitize.\r\n\r\n That block is authored ONCE, as `#actionButton`, and stamped by every place a\r\n contributed action is painted (group items and `primary`). It used to be\r\n inline in the group loop, which was fine while this component rendered groups\r\n only; with `primary` here too, a second copy would mean the next edit to the\r\n SECURITY-CRITICAL binding shape has to be made twice and can be made once.\r\n-->\r\n<ng-template #actionButton let-projected>\r\n <!--\r\n `let-projected` is `any` \u2014 Angular infers nothing for an `ngTemplateOutlet`\r\n context, and there is no built-in way to declare one. `asAction` is an\r\n identity function whose only job is to give this block a TYPED local, so\r\n every read below (`.kind`, `.disabled`, `.menu`) is checked by the template\r\n compiler instead of silently resolving to `undefined` on a typo. Without it\r\n the one place a `MagicBarActionView` is actually painted would be the one\r\n place its shape is not verified.\r\n -->\r\n @let action = asAction(projected);\r\n @if (action.kind === 'text') {\r\n <button\r\n type=\"button\"\r\n class=\"fma-btn fma-btn--text\"\r\n [attr.data-tone]=\"toneAttr(action)\"\r\n [attr.aria-disabled]=\"action.disabled ? 'true' : null\"\r\n [attr.aria-pressed]=\"pressedAttr(action)\"\r\n [flyTooltip]=\"tooltipFor(action)\"\r\n [flyTooltipDelay]=\"450\"\r\n (click)=\"activate(action, $event)\"\r\n >{{ resolvedLabel(action) }}</button>\r\n } @else {\r\n <button\r\n type=\"button\"\r\n class=\"fma-btn\"\r\n [class.fma-btn--badge]=\"hasBadge(action)\"\r\n [attr.data-tone]=\"toneAttr(action)\"\r\n [attr.aria-disabled]=\"action.disabled ? 'true' : null\"\r\n [attr.aria-pressed]=\"pressedAttr(action)\"\r\n [attr.aria-haspopup]=\"action.menu ? 'menu' : null\"\r\n [attr.aria-expanded]=\"action.menu ? (openMenuActionId() === action.id ? 'true' : 'false') : null\"\r\n [attr.aria-label]=\"action.menu ? triggerAriaLabel(action) : resolvedLabel(action)\"\r\n [flyTooltip]=\"tooltipFor(action)\"\r\n [flyTooltipDelay]=\"450\"\r\n (click)=\"activate(action, $event)\"\r\n >\r\n <svg\r\n class=\"fma-btn__icon\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"1.8\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n aria-hidden=\"true\"\r\n >\r\n @for (node of iconNodes(action); track $index) {\r\n @switch (node.tag) {\r\n @case ('path') {\r\n <svg:path\r\n [attr.d]=\"node.attrs['d']\"\r\n [attr.fill-rule]=\"node.attrs['fill-rule']\"\r\n [attr.clip-rule]=\"node.attrs['clip-rule']\"\r\n />\r\n }\r\n @case ('circle') {\r\n <svg:circle\r\n [attr.cx]=\"node.attrs['cx']\"\r\n [attr.cy]=\"node.attrs['cy']\"\r\n [attr.r]=\"node.attrs['r']\"\r\n />\r\n }\r\n @case ('rect') {\r\n <svg:rect\r\n [attr.x]=\"node.attrs['x']\"\r\n [attr.y]=\"node.attrs['y']\"\r\n [attr.width]=\"node.attrs['width']\"\r\n [attr.height]=\"node.attrs['height']\"\r\n [attr.rx]=\"node.attrs['rx']\"\r\n [attr.ry]=\"node.attrs['ry']\"\r\n />\r\n }\r\n @case ('ellipse') {\r\n <svg:ellipse\r\n [attr.cx]=\"node.attrs['cx']\"\r\n [attr.cy]=\"node.attrs['cy']\"\r\n [attr.rx]=\"node.attrs['rx']\"\r\n [attr.ry]=\"node.attrs['ry']\"\r\n />\r\n }\r\n @case ('line') {\r\n <svg:line\r\n [attr.x1]=\"node.attrs['x1']\"\r\n [attr.y1]=\"node.attrs['y1']\"\r\n [attr.x2]=\"node.attrs['x2']\"\r\n [attr.y2]=\"node.attrs['y2']\"\r\n />\r\n }\r\n @case ('polyline') {\r\n <svg:polyline [attr.points]=\"node.attrs['points']\" />\r\n }\r\n @case ('polygon') {\r\n <svg:polygon [attr.points]=\"node.attrs['points']\" />\r\n }\r\n }\r\n }\r\n </svg>\r\n @if (hasBadge(action)) {\r\n <span class=\"fma-btn__badge\" aria-hidden=\"true\"></span>\r\n }\r\n </button>\r\n }\r\n</ng-template>\r\n\r\n<!--\r\n `.fma` is the SCROLLING row and holds the contributed groups only. The accent\r\n CTA is a SIBLING of it, outside the fade mask and outside the scroll container,\r\n because it is the row's anchor \u2014 a call to action that dissolves into a\r\n gradient, or that you have to scroll sideways to reach, inverts the affordance.\r\n It is also what makes `isOverflowing` measurable at all: see the component.\r\n-->\r\n@if (groups().length) {\r\n <div #row class=\"fma\" [class.fma--overflow]=\"isOverflowing()\">\r\n @for (group of groups(); track group.id) {\r\n <div\r\n class=\"fma-group\"\r\n [class.fma-group--framed]=\"group.framed\"\r\n role=\"group\"\r\n [attr.aria-label]=\"i18n.t(group.labelKey)\"\r\n >\r\n @for (action of group.items; track action.id) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"actionButton\"\r\n [ngTemplateOutletContext]=\"{ $implicit: action }\"\r\n />\r\n }\r\n </div>\r\n @if (group.framed) {\r\n <span class=\"fma-sep\" aria-hidden=\"true\"></span>\r\n }\r\n }\r\n </div>\r\n}\r\n\r\n<!--\r\n The accent CTA. The disc is a WRAPPER, not a modifier on the button, and that\r\n is load-bearing rather than cosmetic: `.fma-btn`'s hover/press feedback is an\r\n `animation` (`iconWiggle` / `iconBounce`), and an animation that touches\r\n `transform` beats a declared `transform` \u2014 so a hover lift authored on the\r\n button itself would simply never render. The wrapper owns the disc, the lift\r\n and the shadow; the button stays transparent and keeps the DS's own toolbar\r\n feedback. It re-points `--chrome-ink` rather than styling `.fma-btn` through a\r\n descendant selector so the glyph colour inherits the way custom properties do.\r\n-->\r\n@if (primary(); as p) {\r\n <span class=\"fma-primary\" [class.fma-primary--disabled]=\"p.disabled\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"actionButton\"\r\n [ngTemplateOutletContext]=\"{ $implicit: p }\"\r\n />\r\n </span>\r\n}\r\n\r\n<!--\r\n ONE radio menu, hoisted out of the group loops (S1-review F9). Only one is open\r\n at a time (`openMenuActionId`), so a single instance is enough \u2014 and rendering\r\n it beside its button would insert a non-`.fma-btn` element into the group,\r\n silently shifting every later button's `:nth-child` index and with it the\r\n `toolbarPopIn` stagger delay the `.fma-btn` rule assigns. Keeping every\r\n staggered parent's children homogeneous is what makes that rule's comment true.\r\n It portals itself to <body>, so its position is unaffected by where it is\r\n declared.\r\n-->\r\n@if (openAction(); as open) {\r\n <fly-context-menu\r\n [anchor]=\"menuAnchorEl()\"\r\n [sections]=\"menuSections(open)\"\r\n (action)=\"onMenuAction(open, $event)\"\r\n (closed)=\"closeMenu()\"\r\n />\r\n}\r\n", styles: [":host{display:flex;align-items:center;gap:8px;min-inline-size:0}.fma{display:flex;align-items:center;gap:8px;flex:0 1 auto;min-inline-size:0;overflow:hidden;flex-wrap:nowrap}.fma--overflow{overflow-x:auto;scrollbar-width:none;-ms-overflow-style:none;-webkit-mask-image:linear-gradient(to right,#000 calc(100% - 28px),transparent 100%);mask-image:linear-gradient(to right,#000 calc(100% - 28px),transparent 100%)}.fma--overflow::-webkit-scrollbar{display:none}:host([dir=rtl]) .fma--overflow{-webkit-mask-image:linear-gradient(to left,#000 calc(100% - 28px),transparent 100%);mask-image:linear-gradient(to left,#000 calc(100% - 28px),transparent 100%)}.fma-group{display:flex;align-items:center;gap:8px;flex:none}.fma-group--framed{gap:2px}.fma-sep{flex:0 0 auto;inline-size:1px;block-size:18px;background:var(--w14)}.fma-btn{position:relative;flex:0 0 auto;inline-size:30px;block-size:30px;display:grid;place-items:center;border:0;border-radius:50%;background:transparent;color:var(--chrome-ink);cursor:pointer;padding:0;animation:toolbarPopIn .3s var(--nova-ease-structural) both}.fma-btn:nth-child(1){animation-delay:0ms}.fma-btn:nth-child(2){animation-delay:40ms}.fma-btn:nth-child(3){animation-delay:80ms}.fma-btn:nth-child(4){animation-delay:.12s}.fma-btn:nth-child(5){animation-delay:.16s}.fma-btn:nth-child(6){animation-delay:.2s}.fma-btn:nth-child(7){animation-delay:.24s}.fma-btn:nth-child(8){animation-delay:.28s}.fma-btn:nth-child(9){animation-delay:.32s}.fma-btn:nth-child(10){animation-delay:.36s}.fma-btn:nth-child(11){animation-delay:.4s}.fma-btn:nth-child(12){animation-delay:.44s}.fma-btn:nth-child(n+13){animation-delay:.44s}.fma-btn:not([aria-disabled=true]):hover{background:var(--w1);color:var(--chrome-ink-hover);animation:iconWiggle .5s ease}.fma-btn:not([aria-disabled=true]):active{animation:iconBounce .38s var(--nova-ease-overshoot)}.fma-btn:focus-visible{outline:3px solid var(--accent);outline-offset:3px;border-radius:inherit}.fma-btn[data-tone=danger]{color:var(--sys-red)}.fma-btn[data-tone=danger]:not([aria-disabled=true]):hover{background:color-mix(in oklab,var(--sys-red) 18%,transparent);color:var(--sys-red)}.fma-btn[data-tone=success]{color:var(--sys-green)}.fma-btn[data-tone=success]:not([aria-disabled=true]):hover{background:color-mix(in oklab,var(--sys-green) 18%,transparent);color:var(--sys-green)}.fma-btn[aria-pressed=true]{background:var(--tint-sel);color:var(--chrome-ink-hover)}.fma-btn[aria-pressed=true][data-tone=success]{background:color-mix(in oklab,var(--sys-green) 22%,transparent);color:var(--sys-green)}.fma-btn[aria-disabled=true]{opacity:.38;filter:saturate(.6);animation:none;cursor:default}.fma-btn__icon{inline-size:16px;block-size:16px;pointer-events:none}.fma-btn__badge{position:absolute;inset-block-start:3px;inset-inline-end:3px;inline-size:7px;block-size:7px;border-radius:50%;background:var(--accent);pointer-events:none}.fma-primary{--chrome-ink: var(--on-accent);--chrome-ink-hover: var(--on-accent);flex:none;display:grid;place-items:center;inline-size:30px;block-size:30px;border-radius:50%;background:var(--accent);transition:box-shadow var(--nova-duration-hover) var(--nova-ease-micro),transform var(--nova-duration-hover) var(--nova-ease-micro)}.fma-primary:hover{box-shadow:0 8px 20px var(--tint-sel);transform:translateY(-1px)}.fma-primary--disabled{opacity:.38;filter:saturate(.6)}.fma-primary--disabled:hover{box-shadow:none;transform:none}.fma-btn--text{inline-size:auto;block-size:30px;border-radius:99px;padding-inline:12px;font-family:inherit;font-size:12.5px;font-weight:600;line-height:1;white-space:nowrap}@media(pointer:coarse){.fma-btn{inline-size:44px;block-size:44px}.fma-btn--text{inline-size:auto;min-inline-size:44px}.fma-primary{inline-size:44px;block-size:44px}}\n"] }]
17041
+ }, template: "<!--\n Icon-only buttons carry the accessible name via [attr.aria-label] \u2014 the SVG\n glyph itself is aria-hidden (decorative, skill \u00A7accessibility rule 5). `kind:\n 'text'` actions rely on their own visible text instead. Disabled rows stay\n `aria-disabled` (never native `disabled`) so they remain focusable/hoverable \u2014\n a disabled action's whole point is to explain ITSELF via the auto-suffixed\n tooltip, which native `disabled` would suppress.\n\n The glyph is composed from ALLOWLISTED nodes bound as real attributes, never\n from `[innerHTML]`: `iconPath` is publisher-supplied, and an `<svg>` fragment\n is not a closed world (`<foreignObject>` is an HTML integration point, `<a\n xlink:href=\"javascript:\u2026\">` is live under the very click this button invites).\n `magic-actions-icon.ts` carries the full rationale; the shape below is its\n consequence \u2014 an attribute binding cannot introduce an element or a handler,\n so there is nothing left to sanitize.\n\n That block is authored ONCE, as `#actionButton`, and stamped by every place a\n contributed action is painted (group items and `primary`). It used to be\n inline in the group loop, which was fine while this component rendered groups\n only; with `primary` here too, a second copy would mean the next edit to the\n SECURITY-CRITICAL binding shape has to be made twice and can be made once.\n-->\n<!--\n `data-action` carries the publisher's action `id` verbatim \u2014 the one stable, LOCALE-INDEPENDENT\n handle on a rendered action. Every other identifying attribute here is translated\n (`aria-label`, the tooltip), so an e2e suite that targeted them had to assert in one language,\n and one that targeted a bespoke button lost its hook entirely when the action moved into the\n bar. That is not hypothetical: PPM's project-closure suite could not adopt the contract for\n exactly this reason. It is an ATTRIBUTE, not a class, so it never participates in styling, and\n `id` is already unique across the whole contribution (the projection enforces it), so it is\n unique in the DOM too.\n-->\n<ng-template #actionButton let-projected>\n <!--\n `let-projected` is `any` \u2014 Angular infers nothing for an `ngTemplateOutlet`\n context, and there is no built-in way to declare one. `asAction` is an\n identity function whose only job is to give this block a TYPED local, so\n every read below (`.kind`, `.disabled`, `.menu`) is checked by the template\n compiler instead of silently resolving to `undefined` on a typo. Without it\n the one place a `MagicBarActionView` is actually painted would be the one\n place its shape is not verified.\n -->\n @let action = asAction(projected);\n @if (action.kind === 'text') {\n <button\n type=\"button\"\n class=\"fma-btn fma-btn--text\"\n [attr.data-action]=\"action.id\"\n [attr.data-tone]=\"toneAttr(action)\"\n [attr.aria-disabled]=\"action.disabled ? 'true' : null\"\n [attr.aria-pressed]=\"pressedAttr(action)\"\n [flyTooltip]=\"tooltipFor(action)\"\n [flyTooltipDelay]=\"450\"\n (click)=\"activate(action, $event)\"\n >{{ resolvedLabel(action) }}</button>\n } @else {\n <button\n type=\"button\"\n class=\"fma-btn\"\n [class.fma-btn--badge]=\"hasBadge(action)\"\n [attr.data-action]=\"action.id\"\n [attr.data-tone]=\"toneAttr(action)\"\n [attr.aria-disabled]=\"action.disabled ? 'true' : null\"\n [attr.aria-pressed]=\"pressedAttr(action)\"\n [attr.aria-haspopup]=\"action.menu ? 'menu' : null\"\n [attr.aria-expanded]=\"action.menu ? (openMenuActionId() === action.id ? 'true' : 'false') : null\"\n [attr.aria-label]=\"action.menu ? triggerAriaLabel(action) : resolvedLabel(action)\"\n [flyTooltip]=\"tooltipFor(action)\"\n [flyTooltipDelay]=\"450\"\n (click)=\"activate(action, $event)\"\n >\n <svg\n class=\"fma-btn__icon\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.8\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n @for (node of iconNodes(action); track $index) {\n @switch (node.tag) {\n @case ('path') {\n <svg:path\n [attr.d]=\"node.attrs['d']\"\n [attr.fill-rule]=\"node.attrs['fill-rule']\"\n [attr.clip-rule]=\"node.attrs['clip-rule']\"\n />\n }\n @case ('circle') {\n <svg:circle\n [attr.cx]=\"node.attrs['cx']\"\n [attr.cy]=\"node.attrs['cy']\"\n [attr.r]=\"node.attrs['r']\"\n />\n }\n @case ('rect') {\n <svg:rect\n [attr.x]=\"node.attrs['x']\"\n [attr.y]=\"node.attrs['y']\"\n [attr.width]=\"node.attrs['width']\"\n [attr.height]=\"node.attrs['height']\"\n [attr.rx]=\"node.attrs['rx']\"\n [attr.ry]=\"node.attrs['ry']\"\n />\n }\n @case ('ellipse') {\n <svg:ellipse\n [attr.cx]=\"node.attrs['cx']\"\n [attr.cy]=\"node.attrs['cy']\"\n [attr.rx]=\"node.attrs['rx']\"\n [attr.ry]=\"node.attrs['ry']\"\n />\n }\n @case ('line') {\n <svg:line\n [attr.x1]=\"node.attrs['x1']\"\n [attr.y1]=\"node.attrs['y1']\"\n [attr.x2]=\"node.attrs['x2']\"\n [attr.y2]=\"node.attrs['y2']\"\n />\n }\n @case ('polyline') {\n <svg:polyline [attr.points]=\"node.attrs['points']\" />\n }\n @case ('polygon') {\n <svg:polygon [attr.points]=\"node.attrs['points']\" />\n }\n }\n }\n </svg>\n @if (hasBadge(action)) {\n <span class=\"fma-btn__badge\" aria-hidden=\"true\"></span>\n }\n </button>\n }\n</ng-template>\n\n<!--\n `.fma` is the SCROLLING row and holds the contributed groups only. The accent\n CTA is a SIBLING of it, outside the fade mask and outside the scroll container,\n because it is the row's anchor \u2014 a call to action that dissolves into a\n gradient, or that you have to scroll sideways to reach, inverts the affordance.\n It is also what makes `isOverflowing` measurable at all: see the component.\n-->\n@if (groups().length) {\n <div #row class=\"fma\" [class.fma--overflow]=\"isOverflowing()\">\n @for (group of groups(); track group.id) {\n <div\n class=\"fma-group\"\n [class.fma-group--framed]=\"group.framed\"\n role=\"group\"\n [attr.aria-label]=\"i18n.t(group.labelKey)\"\n >\n @for (action of group.items; track action.id) {\n <ng-container\n [ngTemplateOutlet]=\"actionButton\"\n [ngTemplateOutletContext]=\"{ $implicit: action }\"\n />\n }\n </div>\n @if (group.framed) {\n <span class=\"fma-sep\" aria-hidden=\"true\"></span>\n }\n }\n </div>\n}\n\n<!--\n The accent CTA. The disc is a WRAPPER, not a modifier on the button, and that\n is load-bearing rather than cosmetic: `.fma-btn`'s hover/press feedback is an\n `animation` (`iconWiggle` / `iconBounce`), and an animation that touches\n `transform` beats a declared `transform` \u2014 so a hover lift authored on the\n button itself would simply never render. The wrapper owns the disc, the lift\n and the shadow; the button stays transparent and keeps the DS's own toolbar\n feedback. It re-points `--chrome-ink` rather than styling `.fma-btn` through a\n descendant selector so the glyph colour inherits the way custom properties do.\n-->\n@if (primary(); as p) {\n <span class=\"fma-primary\" [class.fma-primary--disabled]=\"p.disabled\">\n <ng-container\n [ngTemplateOutlet]=\"actionButton\"\n [ngTemplateOutletContext]=\"{ $implicit: p }\"\n />\n </span>\n}\n\n<!--\n ONE radio menu, hoisted out of the group loops (S1-review F9). Only one is open\n at a time (`openMenuActionId`), so a single instance is enough \u2014 and rendering\n it beside its button would insert a non-`.fma-btn` element into the group,\n silently shifting every later button's `:nth-child` index and with it the\n `toolbarPopIn` stagger delay the `.fma-btn` rule assigns. Keeping every\n staggered parent's children homogeneous is what makes that rule's comment true.\n It portals itself to <body>, so its position is unaffected by where it is\n declared.\n-->\n@if (openAction(); as open) {\n <fly-context-menu\n [anchor]=\"menuAnchorEl()\"\n [sections]=\"menuSections(open)\"\n (action)=\"onMenuAction(open, $event)\"\n (closed)=\"closeMenu()\"\n />\n}\n", styles: [":host{display:flex;align-items:center;gap:8px;min-inline-size:0}.fma{display:flex;align-items:center;gap:8px;flex:0 1 auto;min-inline-size:0;overflow:hidden;flex-wrap:nowrap}.fma--overflow{overflow-x:auto;scrollbar-width:none;-ms-overflow-style:none;-webkit-mask-image:linear-gradient(to right,#000 calc(100% - 28px),transparent 100%);mask-image:linear-gradient(to right,#000 calc(100% - 28px),transparent 100%)}.fma--overflow::-webkit-scrollbar{display:none}:host([dir=rtl]) .fma--overflow{-webkit-mask-image:linear-gradient(to left,#000 calc(100% - 28px),transparent 100%);mask-image:linear-gradient(to left,#000 calc(100% - 28px),transparent 100%)}.fma-group{display:flex;align-items:center;gap:8px;flex:none}.fma-group--framed{gap:2px}.fma-sep{flex:0 0 auto;inline-size:1px;block-size:18px;background:var(--w14)}.fma-btn{position:relative;flex:0 0 auto;inline-size:30px;block-size:30px;display:grid;place-items:center;border:0;border-radius:50%;background:transparent;color:var(--chrome-ink);cursor:pointer;padding:0;animation:toolbarPopIn .3s var(--nova-ease-structural) both}.fma-btn:nth-child(1){animation-delay:0ms}.fma-btn:nth-child(2){animation-delay:40ms}.fma-btn:nth-child(3){animation-delay:80ms}.fma-btn:nth-child(4){animation-delay:.12s}.fma-btn:nth-child(5){animation-delay:.16s}.fma-btn:nth-child(6){animation-delay:.2s}.fma-btn:nth-child(7){animation-delay:.24s}.fma-btn:nth-child(8){animation-delay:.28s}.fma-btn:nth-child(9){animation-delay:.32s}.fma-btn:nth-child(10){animation-delay:.36s}.fma-btn:nth-child(11){animation-delay:.4s}.fma-btn:nth-child(12){animation-delay:.44s}.fma-btn:nth-child(n+13){animation-delay:.44s}.fma-btn:not([aria-disabled=true]):hover{background:var(--w1);color:var(--chrome-ink-hover);animation:iconWiggle .5s ease}.fma-btn:not([aria-disabled=true]):active{animation:iconBounce .38s var(--nova-ease-overshoot)}.fma-btn:focus-visible{outline:3px solid var(--accent);outline-offset:3px;border-radius:inherit}.fma-btn[data-tone=danger]{color:var(--sys-red)}.fma-btn[data-tone=danger]:not([aria-disabled=true]):hover{background:color-mix(in oklab,var(--sys-red) 18%,transparent);color:var(--sys-red)}.fma-btn[data-tone=success]{color:var(--sys-green)}.fma-btn[data-tone=success]:not([aria-disabled=true]):hover{background:color-mix(in oklab,var(--sys-green) 18%,transparent);color:var(--sys-green)}.fma-btn[aria-pressed=true]{background:var(--tint-sel);color:var(--chrome-ink-hover)}.fma-btn[aria-pressed=true][data-tone=success]{background:color-mix(in oklab,var(--sys-green) 22%,transparent);color:var(--sys-green)}.fma-btn[aria-disabled=true]{opacity:.38;filter:saturate(.6);animation:none;cursor:default}.fma-btn__icon{inline-size:16px;block-size:16px;pointer-events:none}.fma-btn__badge{position:absolute;inset-block-start:3px;inset-inline-end:3px;inline-size:7px;block-size:7px;border-radius:50%;background:var(--accent);pointer-events:none}.fma-primary{--chrome-ink: var(--on-accent);--chrome-ink-hover: var(--on-accent);flex:none;display:grid;place-items:center;inline-size:30px;block-size:30px;border-radius:50%;background:var(--accent);transition:box-shadow var(--nova-duration-hover) var(--nova-ease-micro),transform var(--nova-duration-hover) var(--nova-ease-micro)}.fma-primary:hover{box-shadow:0 8px 20px var(--tint-sel);transform:translateY(-1px)}.fma-primary--disabled{opacity:.38;filter:saturate(.6)}.fma-primary--disabled:hover{box-shadow:none;transform:none}.fma-btn--text{inline-size:auto;block-size:30px;border-radius:99px;padding-inline:12px;font-family:inherit;font-size:12.5px;font-weight:600;line-height:1;white-space:nowrap}@media(pointer:coarse){.fma-btn{inline-size:44px;block-size:44px}.fma-btn--text{inline-size:auto;min-inline-size:44px}.fma-primary{inline-size:44px;block-size:44px}}\n"] }]
16981
17042
  }], ctorParameters: () => [], propDecorators: { groups: [{ type: i0.Input, args: [{ isSignal: true, alias: "groups", required: true }] }], primary: [{ type: i0.Input, args: [{ isSignal: true, alias: "primary", required: false }] }], rowRef: [{ type: i0.ViewChild, args: ['row', { isSignal: true }] }] } });
16982
17043
 
16983
17044
  /**
@@ -17066,6 +17127,86 @@ const FLY_MAGIC_BAR_ICONS = {
17066
17127
  ...ORIGINAL_SAME_CONVENTION,
17067
17128
  };
17068
17129
 
17130
+ /**
17131
+ * `<fly-standalone-magic-actions>` — renders an app's OWN magic-bar contribution
17132
+ * inline, for the one mode that has no shell chrome to render it: an External
17133
+ * App running standalone.
17134
+ *
17135
+ * ## The gap this closes
17136
+ * A view publishes one `MagicBarContribution` (skill: `magic-bar-actions.md`)
17137
+ * and, embedded in the desktop shell, the top-bar pill renders it. Standalone,
17138
+ * nothing did — so every screen also kept a bespoke header-actions row
17139
+ * (`[page-header-actions]` buttons) that duplicated the published actions in
17140
+ * BOTH modes: two Create buttons inside the shell, and a second diverging
17141
+ * toolbar implementation outside it. With this component the contribution is
17142
+ * authored once and rendered by whichever chrome exists: the shell's pill when
17143
+ * embedded, this inline cluster when standalone.
17144
+ *
17145
+ * ## Usage — the `[page-header-actions]` slot is the intended position
17146
+ * ```html
17147
+ * <fly-page-header variant="listing" titleKey="…">
17148
+ * <div page-header-actions>
17149
+ * <fly-standalone-magic-actions appId="ppm" />
17150
+ * </div>
17151
+ * </fly-page-header>
17152
+ * ```
17153
+ * `appId` is the same id the view passes to `MagicBarRegistry.publisher`.
17154
+ * Nothing else to wire: the screen's existing publish `effect` feeds both
17155
+ * renderers.
17156
+ *
17157
+ * ## Embedded, it renders NOTHING — by its own decision, not the consumer's
17158
+ * `FlyRemoteRouter.isEmbedded` is read here precisely so every consumer does
17159
+ * not re-author the `@if (!isEmbedded)` guard (and so none can forget it: the
17160
+ * shell pill already renders the same contribution, and a second copy in the
17161
+ * page header is exactly the duplication this component exists to delete).
17162
+ *
17163
+ * ## What it resolves, and why not `active()`
17164
+ * `MagicBarRegistry.active` is arbitrated by the SHELL (focused window →
17165
+ * `setActiveOwner`), and standalone no shell exists to nominate anyone — it is
17166
+ * permanently `null` there by design. This component instead resolves the
17167
+ * caller-named owner via {@link MagicBarRegistry.resolve}, the reactive
17168
+ * per-owner read, with the same slot fallback the shell applies. No `windowId`
17169
+ * input: standalone there is no window manager, so the publisher's
17170
+ * `WINDOW_DATA` is null and its contribution lands in the `appId`-keyed
17171
+ * fallback slot — which an `{ appId }` owner resolves exactly.
17172
+ *
17173
+ * ## What it deliberately does NOT render
17174
+ * - **`search`** — standalone screens keep their in-page `fly-search-input`
17175
+ * (the shell's expanding search field is shell chrome, not part of
17176
+ * `fly-magic-actions`). A second search box is the exact bug the embedded
17177
+ * mode's `@if` guards exist to avoid; standalone the in-page field is the
17178
+ * only one.
17179
+ * - **`overflow` / `quickCommandIds`** — the kebab is a deliberate deferral
17180
+ * (see `magic-actions.component.ts`), and quick commands resolve against the
17181
+ * shell's `AgentCommandRegistry` + Ask-AI orb, which do not exist standalone.
17182
+ */
17183
+ class FlyStandaloneMagicActionsComponent {
17184
+ registry = inject(MagicBarRegistry);
17185
+ remoteRouter = inject(FlyRemoteRouter);
17186
+ /** The publishing app whose contribution to mirror — the `appId` its view passes to `MagicBarRegistry.publisher`. */
17187
+ appId = input.required(...(ngDevMode ? [{ debugName: "appId" }] : /* istanbul ignore next */ []));
17188
+ /**
17189
+ * The view to paint, or `null` for "render nothing": embedded (the shell's
17190
+ * pill owns the contribution there), unpublished, or published with no
17191
+ * painted actions (a bare `viewKey` is "no toolbar", not "an empty toolbar" —
17192
+ * same rule the shell pill applies).
17193
+ */
17194
+ standaloneView = computed(() => {
17195
+ if (this.remoteRouter.isEmbedded)
17196
+ return null;
17197
+ const view = this.registry.resolve({ appId: this.appId() });
17198
+ if (!view)
17199
+ return null;
17200
+ return view.groups.length > 0 || view.primary ? view : null;
17201
+ }, ...(ngDevMode ? [{ debugName: "standaloneView" }] : /* istanbul ignore next */ []));
17202
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyStandaloneMagicActionsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
17203
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyStandaloneMagicActionsComponent, isStandalone: true, selector: "fly-standalone-magic-actions", inputs: { appId: { classPropertyName: "appId", publicName: "appId", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<!-- Null when embedded, unpublished, or nothing painted \u2014 see standaloneView. -->\r\n@if (standaloneView(); as view) {\r\n <fly-magic-actions [groups]=\"view.groups\" [primary]=\"view.primary\" />\r\n}\r\n", styles: [":host{display:contents}\n"], dependencies: [{ kind: "component", type: FlyMagicActionsComponent, selector: "fly-magic-actions", inputs: ["groups", "primary"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
17204
+ }
17205
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyStandaloneMagicActionsComponent, decorators: [{
17206
+ type: Component,
17207
+ args: [{ selector: 'fly-standalone-magic-actions', standalone: true, imports: [FlyMagicActionsComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Null when embedded, unpublished, or nothing painted \u2014 see standaloneView. -->\r\n@if (standaloneView(); as view) {\r\n <fly-magic-actions [groups]=\"view.groups\" [primary]=\"view.primary\" />\r\n}\r\n", styles: [":host{display:contents}\n"] }]
17208
+ }], propDecorators: { appId: [{ type: i0.Input, args: [{ isSignal: true, alias: "appId", required: true }] }] } });
17209
+
17069
17210
  /**
17070
17211
  * Strict whitelist for the ghost element id. Letter-led ASCII, allows word/hyphen/colon/dot,
17071
17212
  * capped at 128 chars. Anything else is rejected before reaching `getElementById` so a
@@ -21512,7 +21653,7 @@ class FlyCardComponent {
21512
21653
  <ng-content select="fly-card-status" />
21513
21654
  <ng-content select="fly-card-footer" />
21514
21655
  <ng-content select="fly-card-actions" />
21515
- `, isInline: true, styles: ["@charset \"UTF-8\";:host{background:var(--bg-2);border:1px solid var(--line);border-radius:var(--r-lg);box-shadow:var(--shadow-card);padding:var(--sp-4);position:relative;min-width:0}:host(.is-interactive){cursor:pointer;transition:transform var(--t-overlay),box-shadow var(--t-overlay),border-color var(--t-overlay)}:host(.is-interactive):hover{border-color:var(--line-2);box-shadow:var(--shadow-card)}:host(.is-interactive):focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}:host(.is-interactive.is-lift){transition:transform var(--t-overlay),box-shadow var(--t-overlay),border-color var(--t-overlay)}:host(.is-interactive.is-lift):hover{transform:translateY(-2px);box-shadow:var(--shadow-filter)}:host([aria-disabled=true]){opacity:.5;cursor:default}:host([data-layout=column]){display:grid;grid-template:\"status actions\" auto \"media media\" auto \"main main\" 1fr \"footer footer\" auto/1fr auto;align-items:start;column-gap:var(--sp-2);animation:riseIn .34s var(--nova-ease-micro) both}:host([data-layout=column]):nth-child(1){animation-delay:0ms}:host([data-layout=column]):nth-child(2){animation-delay:55ms}:host([data-layout=column]):nth-child(3){animation-delay:.11s}:host([data-layout=column]):nth-child(4){animation-delay:165ms}:host([data-layout=column]):nth-child(5){animation-delay:.22s}:host([data-layout=column]):nth-child(6){animation-delay:275ms}:host([data-layout=column]):nth-child(7){animation-delay:.33s}:host([data-layout=column]):nth-child(8){animation-delay:385ms}:host([data-layout=column]):nth-child(9){animation-delay:.44s}:host([data-layout=column]):nth-child(10){animation-delay:495ms}:host([data-layout=column]):nth-child(11){animation-delay:.55s}:host([data-layout=column]):nth-child(12){animation-delay:605ms}:host([data-layout=column]):nth-child(n+13){animation-delay:605ms}:host([data-layout=row]){display:flex;align-items:flex-start;gap:12px;padding:14px 12px;border-color:transparent;background:transparent;box-shadow:none;animation:itemIn .4s var(--nova-ease-micro) both}:host([data-layout=row]):nth-child(1){animation-delay:0ms}:host([data-layout=row]):nth-child(2){animation-delay:40ms}:host([data-layout=row]):nth-child(3){animation-delay:80ms}:host([data-layout=row]):nth-child(4){animation-delay:.12s}:host([data-layout=row]):nth-child(5){animation-delay:.16s}:host([data-layout=row]):nth-child(6){animation-delay:.2s}:host([data-layout=row]):nth-child(7){animation-delay:.24s}:host([data-layout=row]):nth-child(8){animation-delay:.28s}:host([data-layout=row]):nth-child(9){animation-delay:.32s}:host([data-layout=row]):nth-child(10){animation-delay:.36s}:host([data-layout=row]):nth-child(11){animation-delay:.4s}:host([data-layout=row]):nth-child(12){animation-delay:.44s}:host([data-layout=row]):nth-child(n+13){animation-delay:.44s}:host([data-layout=row]){transition:padding-inline-start var(--t-overlay),background var(--t-state),border-color var(--t-state),box-shadow var(--t-state)}:host([data-layout=row]):hover{background:var(--w04)}:host([data-layout=row]):not(.is-selectable,:first-child):before{content:\"\";position:absolute;inset-block-start:0;inset-inline:12px;block-size:1px;background:var(--w07)}:host([data-layout=row].is-selectable:hover),:host([data-layout=row].is-selectable.is-selected){padding-inline-start:48px}:host([data-layout=row].is-selectable){padding:13px 14px;border:1px solid var(--w07);background:var(--w04)}:host([data-layout=row].is-selectable):hover{background:var(--w06);border-color:var(--w14)}:host([data-layout=row].is-selected){background:var(--tint-sel);border-color:var(--accent)}:host([data-layout=row].is-selected):hover{background:var(--tint-sel);border-color:var(--accent)}:host([data-layout=column].is-selected){background:color-mix(in srgb,var(--accent-soft) 65%,var(--bg-2));border-color:color-mix(in srgb,var(--accent) 45%,transparent)}.card__check{position:absolute;inset-inline-start:14px;inset-block-start:15px;display:inline-flex;align-items:center;justify-content:center;opacity:0;pointer-events:none;transition:opacity var(--t-state)}.card__check input{position:absolute;opacity:0;width:14px;height:14px;margin:0;cursor:pointer}:host(:hover) .card__check,:host(:focus-visible) .card__check,:host(:has(:focus-visible)) .card__check,:host(.is-selected) .card__check{opacity:1;pointer-events:auto}.card__check-box{position:relative;display:inline-block;width:14px;height:14px;border:1.5px solid var(--ink-4);border-radius:4px;background:var(--bg-2);transition:background var(--t-state),border-color var(--t-state);flex-shrink:0}.card__check-box:after{content:\"\";position:absolute;inset:0;margin:auto;width:4px;height:7px;border:solid var(--ink-inverse);border-width:0 1.6px 1.6px 0;transform:translateY(-1px) rotate(45deg);opacity:0;transition:opacity var(--t-state)}input:checked+.card__check-box{background:var(--accent);border-color:var(--accent)}input:checked+.card__check-box:after{opacity:1}.card__main{display:flex;flex-direction:column;gap:var(--sp-2);min-width:0;flex:1}:host([data-layout=column]) .card__main{grid-area:main;gap:var(--sp-3);height:100%}:host([data-layout=row]) .card__main{font-size:13px;line-height:1.5;color:var(--w55);text-wrap:pretty}:host([data-layout=column]) .card__main ::ng-deep fly-card-body{margin-block-start:auto}:host([data-layout=column]) .card__main ::ng-deep fly-card-meta{margin-block-start:auto}:host([data-layout=column]) .card__main ::ng-deep fly-card-body~fly-card-meta{margin-block-start:0}:host ::ng-deep fly-card-media{display:block;flex-shrink:0}:host([data-layout=column]) ::ng-deep fly-card-media{grid-area:media;margin-block-end:var(--sp-3)}:host ::ng-deep fly-card-title{display:block;font-size:15px;color:var(--ink);letter-spacing:-.01em;overflow:hidden;min-width:0}:host([data-layout=column]) ::ng-deep fly-card-title{font-weight:var(--fw-medium);line-height:1.35;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}:host([data-layout=row]) ::ng-deep fly-card-title{font-weight:var(--fw-semibold);font-size:14px;line-height:1.35;text-wrap:pretty;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;white-space:normal;transition:font-size var(--t-state)}:host([data-density=compact]) ::ng-deep fly-card-title{font-size:12.5px}:host([data-density=compact]) ::ng-deep fly-card-status{display:none}:host ::ng-deep fly-card-meta{display:flex;flex-wrap:wrap;gap:var(--sp-1);min-width:0}:host([data-layout=row]) ::ng-deep fly-card-meta{align-items:center;gap:8px;font-size:11.5px;color:var(--w55)}:host([data-layout=row]) ::ng-deep fly-card-meta>span{display:inline-flex;align-items:center}:host([data-layout=row]) ::ng-deep fly-card-meta>span:not(:first-child){position:relative;padding-inline-start:8px}:host([data-layout=row]) ::ng-deep fly-card-meta>span:not(:first-child):before{content:\"\";position:absolute;inset-inline-start:0;inset-block:2px;inline-size:1px;background:var(--w12)}:host ::ng-deep fly-card-meta dl{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);gap:var(--sp-2);width:100%;margin:0}:host ::ng-deep fly-card-meta dl>div{display:flex;flex-direction:column;gap:var(--sp-1);min-width:0}:host ::ng-deep fly-card-meta dl dt{margin:0;font-size:10px;font-weight:var(--fw-medium);letter-spacing:.08em;text-transform:uppercase;color:var(--ink-4)}:host ::ng-deep fly-card-meta dl dd{margin:0;font-size:var(--text-sm);color:var(--ink-2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host ::ng-deep fly-card-status{display:inline-flex;align-items:center;min-width:0}:host([data-layout=column]) ::ng-deep fly-card-status{grid-area:status;place-self:center start;min-height:24px;margin-block-end:var(--sp-3)}:host([data-layout=row]) ::ng-deep fly-card-status{flex-shrink:0;align-self:center}:host ::ng-deep fly-card-body{display:block;min-width:0}:host ::ng-deep fly-card-footer{display:flex;align-items:center;gap:6px}:host([data-layout=column]) ::ng-deep fly-card-footer{grid-area:footer;justify-content:space-between;margin-block-start:var(--sp-3);padding-block-start:10px;border-block-start:1px solid var(--line-3);font-size:10.5px;font-weight:var(--fw-medium);letter-spacing:var(--tracking-wide);text-transform:uppercase;color:var(--ink-4)}:host([data-layout=row]) ::ng-deep fly-card-footer{flex-shrink:0;align-self:center;font-family:var(--font-mono);font-size:var(--text-sm);color:var(--ink-3);font-variant-numeric:tabular-nums}:host ::ng-deep fly-card-actions{display:inline-flex;align-items:center;gap:2px}:host([data-layout=column]) ::ng-deep fly-card-actions{grid-area:actions;place-self:center end;margin-block-end:var(--sp-3)}:host([data-layout=row]) ::ng-deep fly-card-actions{flex-shrink:0;align-self:center}@media(width<=640px){:host([data-layout=row]){padding:14px var(--sp-4);gap:var(--sp-3)}:host([data-layout=row].is-selectable:hover),:host([data-layout=row].is-selectable.is-selected){padding-inline-start:44px}.card__check{inset-inline-start:14px}}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
21656
+ `, isInline: true, styles: ["@charset \"UTF-8\";:host{background:var(--bg-2);border:1px solid var(--w08);border-radius:var(--r-lg);box-shadow:var(--shadow-card);padding:var(--sp-4);position:relative;min-width:0}:host(.is-interactive){cursor:pointer;transition:transform var(--t-overlay),box-shadow var(--t-overlay),border-color var(--t-overlay)}:host(.is-interactive):hover{border-color:var(--line-2);box-shadow:var(--shadow-card)}:host(.is-interactive):focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}:host(.is-interactive.is-lift){transition:transform var(--t-overlay),box-shadow var(--t-overlay),border-color var(--t-overlay)}:host(.is-interactive.is-lift):hover{transform:translateY(-2px);box-shadow:var(--shadow-filter)}:host([aria-disabled=true]){opacity:.5;cursor:default}:host([data-layout=column]){display:grid;grid-template:\"status actions\" auto \"media media\" auto \"main main\" 1fr \"footer footer\" auto/1fr auto;align-items:start;column-gap:var(--sp-2);animation:riseIn .34s var(--nova-ease-micro) both}:host([data-layout=column]):nth-child(1){animation-delay:0ms}:host([data-layout=column]):nth-child(2){animation-delay:55ms}:host([data-layout=column]):nth-child(3){animation-delay:.11s}:host([data-layout=column]):nth-child(4){animation-delay:165ms}:host([data-layout=column]):nth-child(5){animation-delay:.22s}:host([data-layout=column]):nth-child(6){animation-delay:275ms}:host([data-layout=column]):nth-child(7){animation-delay:.33s}:host([data-layout=column]):nth-child(8){animation-delay:385ms}:host([data-layout=column]):nth-child(9){animation-delay:.44s}:host([data-layout=column]):nth-child(10){animation-delay:495ms}:host([data-layout=column]):nth-child(11){animation-delay:.55s}:host([data-layout=column]):nth-child(12){animation-delay:605ms}:host([data-layout=column]):nth-child(n+13){animation-delay:605ms}:host([data-layout=row]){display:flex;align-items:flex-start;gap:12px;padding:14px 12px;border-color:transparent;background:transparent;box-shadow:none;animation:itemIn .4s var(--nova-ease-micro) both}:host([data-layout=row]):nth-child(1){animation-delay:0ms}:host([data-layout=row]):nth-child(2){animation-delay:40ms}:host([data-layout=row]):nth-child(3){animation-delay:80ms}:host([data-layout=row]):nth-child(4){animation-delay:.12s}:host([data-layout=row]):nth-child(5){animation-delay:.16s}:host([data-layout=row]):nth-child(6){animation-delay:.2s}:host([data-layout=row]):nth-child(7){animation-delay:.24s}:host([data-layout=row]):nth-child(8){animation-delay:.28s}:host([data-layout=row]):nth-child(9){animation-delay:.32s}:host([data-layout=row]):nth-child(10){animation-delay:.36s}:host([data-layout=row]):nth-child(11){animation-delay:.4s}:host([data-layout=row]):nth-child(12){animation-delay:.44s}:host([data-layout=row]):nth-child(n+13){animation-delay:.44s}:host([data-layout=row]){transition:padding-inline-start var(--t-overlay),background var(--t-state),border-color var(--t-state),box-shadow var(--t-state)}:host([data-layout=row]):hover{background:var(--w04)}:host([data-layout=row]):not(.is-selectable,:first-child):before{content:\"\";position:absolute;inset-block-start:0;inset-inline:12px;block-size:1px;background:var(--w07)}:host([data-layout=row].is-selectable:hover),:host([data-layout=row].is-selectable.is-selected){padding-inline-start:48px}:host([data-layout=row].is-selectable){padding:13px 14px;border:1px solid var(--w07);background:var(--w04)}:host([data-layout=row].is-selectable):hover{background:var(--w06);border-color:var(--w14)}:host([data-layout=row].is-selected){background:var(--tint-sel);border-color:var(--accent)}:host([data-layout=row].is-selected):hover{background:var(--tint-sel);border-color:var(--accent)}:host([data-layout=column].is-selected){background:color-mix(in srgb,var(--accent-soft) 65%,var(--bg-2));border-color:color-mix(in srgb,var(--accent) 45%,transparent)}.card__check{position:absolute;inset-inline-start:14px;inset-block-start:15px;display:inline-flex;align-items:center;justify-content:center;opacity:0;pointer-events:none;transition:opacity var(--t-state)}.card__check input{position:absolute;opacity:0;width:14px;height:14px;margin:0;cursor:pointer}:host(:hover) .card__check,:host(:focus-visible) .card__check,:host(:has(:focus-visible)) .card__check,:host(.is-selected) .card__check{opacity:1;pointer-events:auto}.card__check-box{position:relative;display:inline-block;width:14px;height:14px;border:1.5px solid var(--ink-4);border-radius:4px;background:var(--bg-2);transition:background var(--t-state),border-color var(--t-state);flex-shrink:0}.card__check-box:after{content:\"\";position:absolute;inset:0;margin:auto;width:4px;height:7px;border:solid var(--ink-inverse);border-width:0 1.6px 1.6px 0;transform:translateY(-1px) rotate(45deg);opacity:0;transition:opacity var(--t-state)}input:checked+.card__check-box{background:var(--accent);border-color:var(--accent)}input:checked+.card__check-box:after{opacity:1}.card__main{display:flex;flex-direction:column;gap:var(--sp-2);min-width:0;flex:1}:host([data-layout=column]) .card__main{grid-area:main;gap:var(--sp-3);height:100%}:host([data-layout=row]) .card__main{font-size:13px;line-height:1.5;color:var(--w55);text-wrap:pretty}:host([data-layout=column]) .card__main ::ng-deep fly-card-body{margin-block-start:auto}:host([data-layout=column]) .card__main ::ng-deep fly-card-meta{margin-block-start:auto}:host([data-layout=column]) .card__main ::ng-deep fly-card-body~fly-card-meta{margin-block-start:0}:host ::ng-deep fly-card-media{display:block;flex-shrink:0}:host([data-layout=column]) ::ng-deep fly-card-media{grid-area:media;margin-block-end:var(--sp-3)}:host ::ng-deep fly-card-title{display:block;font-size:15px;color:var(--ink);letter-spacing:-.01em;overflow:hidden;min-width:0}:host([data-layout=column]) ::ng-deep fly-card-title{font-weight:var(--fw-medium);line-height:1.35;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}:host([data-layout=row]) ::ng-deep fly-card-title{font-weight:var(--fw-semibold);font-size:14px;line-height:1.35;text-wrap:pretty;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;white-space:normal;transition:font-size var(--t-state)}:host([data-density=compact]) ::ng-deep fly-card-title{font-size:12.5px}:host([data-density=compact]) ::ng-deep fly-card-status{display:none}:host ::ng-deep fly-card-meta{display:flex;flex-wrap:wrap;gap:var(--sp-1);min-width:0}:host([data-layout=row]) ::ng-deep fly-card-meta{align-items:center;gap:8px;font-size:11.5px;color:var(--w55)}:host([data-layout=row]) ::ng-deep fly-card-meta>span{display:inline-flex;align-items:center}:host([data-layout=row]) ::ng-deep fly-card-meta>span:not(:first-child){position:relative;padding-inline-start:8px}:host([data-layout=row]) ::ng-deep fly-card-meta>span:not(:first-child):before{content:\"\";position:absolute;inset-inline-start:0;inset-block:2px;inline-size:1px;background:var(--w12)}:host ::ng-deep fly-card-meta dl{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);gap:var(--sp-2);width:100%;margin:0}:host ::ng-deep fly-card-meta dl>div{display:flex;flex-direction:column;gap:var(--sp-1);min-width:0}:host ::ng-deep fly-card-meta dl dt{margin:0;font-size:10px;font-weight:var(--fw-medium);letter-spacing:.08em;text-transform:uppercase;color:var(--ink-4)}:host ::ng-deep fly-card-meta dl dd{margin:0;font-size:var(--text-sm);color:var(--ink-2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host ::ng-deep fly-card-status{display:inline-flex;align-items:center;min-width:0}:host([data-layout=column]) ::ng-deep fly-card-status{grid-area:status;place-self:center start;min-height:24px;margin-block-end:var(--sp-3)}:host([data-layout=row]) ::ng-deep fly-card-status{flex-shrink:0;align-self:center}:host ::ng-deep fly-card-body{display:block;min-width:0}:host ::ng-deep fly-card-footer{display:flex;align-items:center;gap:6px}:host([data-layout=column]) ::ng-deep fly-card-footer{grid-area:footer;justify-content:space-between;margin-block-start:var(--sp-3);padding-block-start:10px;border-block-start:1px solid var(--line-3);font-size:10.5px;font-weight:var(--fw-medium);letter-spacing:var(--tracking-wide);text-transform:uppercase;color:var(--ink-4)}:host([data-layout=row]) ::ng-deep fly-card-footer{flex-shrink:0;align-self:center;font-family:var(--font-mono);font-size:var(--text-sm);color:var(--ink-3);font-variant-numeric:tabular-nums}:host ::ng-deep fly-card-actions{display:inline-flex;align-items:center;gap:2px}:host([data-layout=column]) ::ng-deep fly-card-actions{grid-area:actions;place-self:center end;margin-block-end:var(--sp-3)}:host([data-layout=row]) ::ng-deep fly-card-actions{flex-shrink:0;align-self:center}@media(width<=640px){:host([data-layout=row]){padding:14px var(--sp-4);gap:var(--sp-3)}:host([data-layout=row].is-selectable:hover),:host([data-layout=row].is-selectable.is-selected){padding-inline-start:44px}.card__check{inset-inline-start:14px}}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
21516
21657
  }
21517
21658
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyCardComponent, decorators: [{
21518
21659
  type: Component,
@@ -21552,7 +21693,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
21552
21693
  <ng-content select="fly-card-status" />
21553
21694
  <ng-content select="fly-card-footer" />
21554
21695
  <ng-content select="fly-card-actions" />
21555
- `, styles: ["@charset \"UTF-8\";:host{background:var(--bg-2);border:1px solid var(--line);border-radius:var(--r-lg);box-shadow:var(--shadow-card);padding:var(--sp-4);position:relative;min-width:0}:host(.is-interactive){cursor:pointer;transition:transform var(--t-overlay),box-shadow var(--t-overlay),border-color var(--t-overlay)}:host(.is-interactive):hover{border-color:var(--line-2);box-shadow:var(--shadow-card)}:host(.is-interactive):focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}:host(.is-interactive.is-lift){transition:transform var(--t-overlay),box-shadow var(--t-overlay),border-color var(--t-overlay)}:host(.is-interactive.is-lift):hover{transform:translateY(-2px);box-shadow:var(--shadow-filter)}:host([aria-disabled=true]){opacity:.5;cursor:default}:host([data-layout=column]){display:grid;grid-template:\"status actions\" auto \"media media\" auto \"main main\" 1fr \"footer footer\" auto/1fr auto;align-items:start;column-gap:var(--sp-2);animation:riseIn .34s var(--nova-ease-micro) both}:host([data-layout=column]):nth-child(1){animation-delay:0ms}:host([data-layout=column]):nth-child(2){animation-delay:55ms}:host([data-layout=column]):nth-child(3){animation-delay:.11s}:host([data-layout=column]):nth-child(4){animation-delay:165ms}:host([data-layout=column]):nth-child(5){animation-delay:.22s}:host([data-layout=column]):nth-child(6){animation-delay:275ms}:host([data-layout=column]):nth-child(7){animation-delay:.33s}:host([data-layout=column]):nth-child(8){animation-delay:385ms}:host([data-layout=column]):nth-child(9){animation-delay:.44s}:host([data-layout=column]):nth-child(10){animation-delay:495ms}:host([data-layout=column]):nth-child(11){animation-delay:.55s}:host([data-layout=column]):nth-child(12){animation-delay:605ms}:host([data-layout=column]):nth-child(n+13){animation-delay:605ms}:host([data-layout=row]){display:flex;align-items:flex-start;gap:12px;padding:14px 12px;border-color:transparent;background:transparent;box-shadow:none;animation:itemIn .4s var(--nova-ease-micro) both}:host([data-layout=row]):nth-child(1){animation-delay:0ms}:host([data-layout=row]):nth-child(2){animation-delay:40ms}:host([data-layout=row]):nth-child(3){animation-delay:80ms}:host([data-layout=row]):nth-child(4){animation-delay:.12s}:host([data-layout=row]):nth-child(5){animation-delay:.16s}:host([data-layout=row]):nth-child(6){animation-delay:.2s}:host([data-layout=row]):nth-child(7){animation-delay:.24s}:host([data-layout=row]):nth-child(8){animation-delay:.28s}:host([data-layout=row]):nth-child(9){animation-delay:.32s}:host([data-layout=row]):nth-child(10){animation-delay:.36s}:host([data-layout=row]):nth-child(11){animation-delay:.4s}:host([data-layout=row]):nth-child(12){animation-delay:.44s}:host([data-layout=row]):nth-child(n+13){animation-delay:.44s}:host([data-layout=row]){transition:padding-inline-start var(--t-overlay),background var(--t-state),border-color var(--t-state),box-shadow var(--t-state)}:host([data-layout=row]):hover{background:var(--w04)}:host([data-layout=row]):not(.is-selectable,:first-child):before{content:\"\";position:absolute;inset-block-start:0;inset-inline:12px;block-size:1px;background:var(--w07)}:host([data-layout=row].is-selectable:hover),:host([data-layout=row].is-selectable.is-selected){padding-inline-start:48px}:host([data-layout=row].is-selectable){padding:13px 14px;border:1px solid var(--w07);background:var(--w04)}:host([data-layout=row].is-selectable):hover{background:var(--w06);border-color:var(--w14)}:host([data-layout=row].is-selected){background:var(--tint-sel);border-color:var(--accent)}:host([data-layout=row].is-selected):hover{background:var(--tint-sel);border-color:var(--accent)}:host([data-layout=column].is-selected){background:color-mix(in srgb,var(--accent-soft) 65%,var(--bg-2));border-color:color-mix(in srgb,var(--accent) 45%,transparent)}.card__check{position:absolute;inset-inline-start:14px;inset-block-start:15px;display:inline-flex;align-items:center;justify-content:center;opacity:0;pointer-events:none;transition:opacity var(--t-state)}.card__check input{position:absolute;opacity:0;width:14px;height:14px;margin:0;cursor:pointer}:host(:hover) .card__check,:host(:focus-visible) .card__check,:host(:has(:focus-visible)) .card__check,:host(.is-selected) .card__check{opacity:1;pointer-events:auto}.card__check-box{position:relative;display:inline-block;width:14px;height:14px;border:1.5px solid var(--ink-4);border-radius:4px;background:var(--bg-2);transition:background var(--t-state),border-color var(--t-state);flex-shrink:0}.card__check-box:after{content:\"\";position:absolute;inset:0;margin:auto;width:4px;height:7px;border:solid var(--ink-inverse);border-width:0 1.6px 1.6px 0;transform:translateY(-1px) rotate(45deg);opacity:0;transition:opacity var(--t-state)}input:checked+.card__check-box{background:var(--accent);border-color:var(--accent)}input:checked+.card__check-box:after{opacity:1}.card__main{display:flex;flex-direction:column;gap:var(--sp-2);min-width:0;flex:1}:host([data-layout=column]) .card__main{grid-area:main;gap:var(--sp-3);height:100%}:host([data-layout=row]) .card__main{font-size:13px;line-height:1.5;color:var(--w55);text-wrap:pretty}:host([data-layout=column]) .card__main ::ng-deep fly-card-body{margin-block-start:auto}:host([data-layout=column]) .card__main ::ng-deep fly-card-meta{margin-block-start:auto}:host([data-layout=column]) .card__main ::ng-deep fly-card-body~fly-card-meta{margin-block-start:0}:host ::ng-deep fly-card-media{display:block;flex-shrink:0}:host([data-layout=column]) ::ng-deep fly-card-media{grid-area:media;margin-block-end:var(--sp-3)}:host ::ng-deep fly-card-title{display:block;font-size:15px;color:var(--ink);letter-spacing:-.01em;overflow:hidden;min-width:0}:host([data-layout=column]) ::ng-deep fly-card-title{font-weight:var(--fw-medium);line-height:1.35;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}:host([data-layout=row]) ::ng-deep fly-card-title{font-weight:var(--fw-semibold);font-size:14px;line-height:1.35;text-wrap:pretty;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;white-space:normal;transition:font-size var(--t-state)}:host([data-density=compact]) ::ng-deep fly-card-title{font-size:12.5px}:host([data-density=compact]) ::ng-deep fly-card-status{display:none}:host ::ng-deep fly-card-meta{display:flex;flex-wrap:wrap;gap:var(--sp-1);min-width:0}:host([data-layout=row]) ::ng-deep fly-card-meta{align-items:center;gap:8px;font-size:11.5px;color:var(--w55)}:host([data-layout=row]) ::ng-deep fly-card-meta>span{display:inline-flex;align-items:center}:host([data-layout=row]) ::ng-deep fly-card-meta>span:not(:first-child){position:relative;padding-inline-start:8px}:host([data-layout=row]) ::ng-deep fly-card-meta>span:not(:first-child):before{content:\"\";position:absolute;inset-inline-start:0;inset-block:2px;inline-size:1px;background:var(--w12)}:host ::ng-deep fly-card-meta dl{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);gap:var(--sp-2);width:100%;margin:0}:host ::ng-deep fly-card-meta dl>div{display:flex;flex-direction:column;gap:var(--sp-1);min-width:0}:host ::ng-deep fly-card-meta dl dt{margin:0;font-size:10px;font-weight:var(--fw-medium);letter-spacing:.08em;text-transform:uppercase;color:var(--ink-4)}:host ::ng-deep fly-card-meta dl dd{margin:0;font-size:var(--text-sm);color:var(--ink-2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host ::ng-deep fly-card-status{display:inline-flex;align-items:center;min-width:0}:host([data-layout=column]) ::ng-deep fly-card-status{grid-area:status;place-self:center start;min-height:24px;margin-block-end:var(--sp-3)}:host([data-layout=row]) ::ng-deep fly-card-status{flex-shrink:0;align-self:center}:host ::ng-deep fly-card-body{display:block;min-width:0}:host ::ng-deep fly-card-footer{display:flex;align-items:center;gap:6px}:host([data-layout=column]) ::ng-deep fly-card-footer{grid-area:footer;justify-content:space-between;margin-block-start:var(--sp-3);padding-block-start:10px;border-block-start:1px solid var(--line-3);font-size:10.5px;font-weight:var(--fw-medium);letter-spacing:var(--tracking-wide);text-transform:uppercase;color:var(--ink-4)}:host([data-layout=row]) ::ng-deep fly-card-footer{flex-shrink:0;align-self:center;font-family:var(--font-mono);font-size:var(--text-sm);color:var(--ink-3);font-variant-numeric:tabular-nums}:host ::ng-deep fly-card-actions{display:inline-flex;align-items:center;gap:2px}:host([data-layout=column]) ::ng-deep fly-card-actions{grid-area:actions;place-self:center end;margin-block-end:var(--sp-3)}:host([data-layout=row]) ::ng-deep fly-card-actions{flex-shrink:0;align-self:center}@media(width<=640px){:host([data-layout=row]){padding:14px var(--sp-4);gap:var(--sp-3)}:host([data-layout=row].is-selectable:hover),:host([data-layout=row].is-selectable.is-selected){padding-inline-start:44px}.card__check{inset-inline-start:14px}}\n"] }]
21696
+ `, styles: ["@charset \"UTF-8\";:host{background:var(--bg-2);border:1px solid var(--w08);border-radius:var(--r-lg);box-shadow:var(--shadow-card);padding:var(--sp-4);position:relative;min-width:0}:host(.is-interactive){cursor:pointer;transition:transform var(--t-overlay),box-shadow var(--t-overlay),border-color var(--t-overlay)}:host(.is-interactive):hover{border-color:var(--line-2);box-shadow:var(--shadow-card)}:host(.is-interactive):focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}:host(.is-interactive.is-lift){transition:transform var(--t-overlay),box-shadow var(--t-overlay),border-color var(--t-overlay)}:host(.is-interactive.is-lift):hover{transform:translateY(-2px);box-shadow:var(--shadow-filter)}:host([aria-disabled=true]){opacity:.5;cursor:default}:host([data-layout=column]){display:grid;grid-template:\"status actions\" auto \"media media\" auto \"main main\" 1fr \"footer footer\" auto/1fr auto;align-items:start;column-gap:var(--sp-2);animation:riseIn .34s var(--nova-ease-micro) both}:host([data-layout=column]):nth-child(1){animation-delay:0ms}:host([data-layout=column]):nth-child(2){animation-delay:55ms}:host([data-layout=column]):nth-child(3){animation-delay:.11s}:host([data-layout=column]):nth-child(4){animation-delay:165ms}:host([data-layout=column]):nth-child(5){animation-delay:.22s}:host([data-layout=column]):nth-child(6){animation-delay:275ms}:host([data-layout=column]):nth-child(7){animation-delay:.33s}:host([data-layout=column]):nth-child(8){animation-delay:385ms}:host([data-layout=column]):nth-child(9){animation-delay:.44s}:host([data-layout=column]):nth-child(10){animation-delay:495ms}:host([data-layout=column]):nth-child(11){animation-delay:.55s}:host([data-layout=column]):nth-child(12){animation-delay:605ms}:host([data-layout=column]):nth-child(n+13){animation-delay:605ms}:host([data-layout=row]){display:flex;align-items:flex-start;gap:12px;padding:14px 12px;border-color:transparent;background:transparent;box-shadow:none;animation:itemIn .4s var(--nova-ease-micro) both}:host([data-layout=row]):nth-child(1){animation-delay:0ms}:host([data-layout=row]):nth-child(2){animation-delay:40ms}:host([data-layout=row]):nth-child(3){animation-delay:80ms}:host([data-layout=row]):nth-child(4){animation-delay:.12s}:host([data-layout=row]):nth-child(5){animation-delay:.16s}:host([data-layout=row]):nth-child(6){animation-delay:.2s}:host([data-layout=row]):nth-child(7){animation-delay:.24s}:host([data-layout=row]):nth-child(8){animation-delay:.28s}:host([data-layout=row]):nth-child(9){animation-delay:.32s}:host([data-layout=row]):nth-child(10){animation-delay:.36s}:host([data-layout=row]):nth-child(11){animation-delay:.4s}:host([data-layout=row]):nth-child(12){animation-delay:.44s}:host([data-layout=row]):nth-child(n+13){animation-delay:.44s}:host([data-layout=row]){transition:padding-inline-start var(--t-overlay),background var(--t-state),border-color var(--t-state),box-shadow var(--t-state)}:host([data-layout=row]):hover{background:var(--w04)}:host([data-layout=row]):not(.is-selectable,:first-child):before{content:\"\";position:absolute;inset-block-start:0;inset-inline:12px;block-size:1px;background:var(--w07)}:host([data-layout=row].is-selectable:hover),:host([data-layout=row].is-selectable.is-selected){padding-inline-start:48px}:host([data-layout=row].is-selectable){padding:13px 14px;border:1px solid var(--w07);background:var(--w04)}:host([data-layout=row].is-selectable):hover{background:var(--w06);border-color:var(--w14)}:host([data-layout=row].is-selected){background:var(--tint-sel);border-color:var(--accent)}:host([data-layout=row].is-selected):hover{background:var(--tint-sel);border-color:var(--accent)}:host([data-layout=column].is-selected){background:color-mix(in srgb,var(--accent-soft) 65%,var(--bg-2));border-color:color-mix(in srgb,var(--accent) 45%,transparent)}.card__check{position:absolute;inset-inline-start:14px;inset-block-start:15px;display:inline-flex;align-items:center;justify-content:center;opacity:0;pointer-events:none;transition:opacity var(--t-state)}.card__check input{position:absolute;opacity:0;width:14px;height:14px;margin:0;cursor:pointer}:host(:hover) .card__check,:host(:focus-visible) .card__check,:host(:has(:focus-visible)) .card__check,:host(.is-selected) .card__check{opacity:1;pointer-events:auto}.card__check-box{position:relative;display:inline-block;width:14px;height:14px;border:1.5px solid var(--ink-4);border-radius:4px;background:var(--bg-2);transition:background var(--t-state),border-color var(--t-state);flex-shrink:0}.card__check-box:after{content:\"\";position:absolute;inset:0;margin:auto;width:4px;height:7px;border:solid var(--ink-inverse);border-width:0 1.6px 1.6px 0;transform:translateY(-1px) rotate(45deg);opacity:0;transition:opacity var(--t-state)}input:checked+.card__check-box{background:var(--accent);border-color:var(--accent)}input:checked+.card__check-box:after{opacity:1}.card__main{display:flex;flex-direction:column;gap:var(--sp-2);min-width:0;flex:1}:host([data-layout=column]) .card__main{grid-area:main;gap:var(--sp-3);height:100%}:host([data-layout=row]) .card__main{font-size:13px;line-height:1.5;color:var(--w55);text-wrap:pretty}:host([data-layout=column]) .card__main ::ng-deep fly-card-body{margin-block-start:auto}:host([data-layout=column]) .card__main ::ng-deep fly-card-meta{margin-block-start:auto}:host([data-layout=column]) .card__main ::ng-deep fly-card-body~fly-card-meta{margin-block-start:0}:host ::ng-deep fly-card-media{display:block;flex-shrink:0}:host([data-layout=column]) ::ng-deep fly-card-media{grid-area:media;margin-block-end:var(--sp-3)}:host ::ng-deep fly-card-title{display:block;font-size:15px;color:var(--ink);letter-spacing:-.01em;overflow:hidden;min-width:0}:host([data-layout=column]) ::ng-deep fly-card-title{font-weight:var(--fw-medium);line-height:1.35;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}:host([data-layout=row]) ::ng-deep fly-card-title{font-weight:var(--fw-semibold);font-size:14px;line-height:1.35;text-wrap:pretty;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;white-space:normal;transition:font-size var(--t-state)}:host([data-density=compact]) ::ng-deep fly-card-title{font-size:12.5px}:host([data-density=compact]) ::ng-deep fly-card-status{display:none}:host ::ng-deep fly-card-meta{display:flex;flex-wrap:wrap;gap:var(--sp-1);min-width:0}:host([data-layout=row]) ::ng-deep fly-card-meta{align-items:center;gap:8px;font-size:11.5px;color:var(--w55)}:host([data-layout=row]) ::ng-deep fly-card-meta>span{display:inline-flex;align-items:center}:host([data-layout=row]) ::ng-deep fly-card-meta>span:not(:first-child){position:relative;padding-inline-start:8px}:host([data-layout=row]) ::ng-deep fly-card-meta>span:not(:first-child):before{content:\"\";position:absolute;inset-inline-start:0;inset-block:2px;inline-size:1px;background:var(--w12)}:host ::ng-deep fly-card-meta dl{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);gap:var(--sp-2);width:100%;margin:0}:host ::ng-deep fly-card-meta dl>div{display:flex;flex-direction:column;gap:var(--sp-1);min-width:0}:host ::ng-deep fly-card-meta dl dt{margin:0;font-size:10px;font-weight:var(--fw-medium);letter-spacing:.08em;text-transform:uppercase;color:var(--ink-4)}:host ::ng-deep fly-card-meta dl dd{margin:0;font-size:var(--text-sm);color:var(--ink-2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host ::ng-deep fly-card-status{display:inline-flex;align-items:center;min-width:0}:host([data-layout=column]) ::ng-deep fly-card-status{grid-area:status;place-self:center start;min-height:24px;margin-block-end:var(--sp-3)}:host([data-layout=row]) ::ng-deep fly-card-status{flex-shrink:0;align-self:center}:host ::ng-deep fly-card-body{display:block;min-width:0}:host ::ng-deep fly-card-footer{display:flex;align-items:center;gap:6px}:host([data-layout=column]) ::ng-deep fly-card-footer{grid-area:footer;justify-content:space-between;margin-block-start:var(--sp-3);padding-block-start:10px;border-block-start:1px solid var(--line-3);font-size:10.5px;font-weight:var(--fw-medium);letter-spacing:var(--tracking-wide);text-transform:uppercase;color:var(--ink-4)}:host([data-layout=row]) ::ng-deep fly-card-footer{flex-shrink:0;align-self:center;font-family:var(--font-mono);font-size:var(--text-sm);color:var(--ink-3);font-variant-numeric:tabular-nums}:host ::ng-deep fly-card-actions{display:inline-flex;align-items:center;gap:2px}:host([data-layout=column]) ::ng-deep fly-card-actions{grid-area:actions;place-self:center end;margin-block-end:var(--sp-3)}:host([data-layout=row]) ::ng-deep fly-card-actions{flex-shrink:0;align-self:center}@media(width<=640px){:host([data-layout=row]){padding:14px var(--sp-4);gap:var(--sp-3)}:host([data-layout=row].is-selectable:hover),:host([data-layout=row].is-selectable.is-selected){padding-inline-start:44px}.card__check{inset-inline-start:14px}}\n"] }]
21556
21697
  }], propDecorators: { layout: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout", required: false }] }], density: [{ type: i0.Input, args: [{ isSignal: true, alias: "density", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }, { type: i0.Output, args: ["selectedChange"] }], interactive: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactive", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], lift: [{ type: i0.Input, args: [{ isSignal: true, alias: "lift", required: false }] }], selectLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectLabelKey", required: false }] }], selectLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectLabel", required: false }] }], activated: [{ type: i0.Output, args: ["activated"] }] } });
21557
21698
 
21558
21699
  /**
@@ -21953,11 +22094,11 @@ class FlyDataTableComponent {
21953
22094
  this.sortChange.emit(nextSort(this.sort(), col.id));
21954
22095
  }
21955
22096
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyDataTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
21956
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyDataTableComponent, isStandalone: true, selector: "fly-data-table", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: true, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelKey: { classPropertyName: "ariaLabelKey", publicName: "ariaLabelKey", isSignal: true, isRequired: false, transformFunction: null }, sort: { classPropertyName: "sort", publicName: "sort", isSignal: true, isRequired: false, transformFunction: null }, emptyKey: { classPropertyName: "emptyKey", publicName: "emptyKey", isSignal: true, isRequired: false, transformFunction: null }, emptyIconClass: { classPropertyName: "emptyIconClass", publicName: "emptyIconClass", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sortChange: "sortChange", rowActivated: "rowActivated" }, queries: [{ propertyName: "cellTemplates", predicate: FlyCellDirective, isSignal: true }], ngImport: i0, template: "<table class=\"dt\" [attr.aria-label]=\"ariaLabelKey() ? (ariaLabelKey()! | translate) : null\">\r\n <thead>\r\n <tr>\r\n @for (col of columns(); track col.id) {\r\n <th\r\n scope=\"col\"\r\n [class.dt__th--end]=\"col.align === 'end'\"\r\n [attr.aria-sort]=\"headerAriaSort(col)\"\r\n >\r\n @if (col.sortable) {\r\n <button type=\"button\" class=\"dt__sort\" (click)=\"onHeaderClick(col)\">\r\n <span>{{ col.headerKey | translate }}</span>\r\n <span class=\"dt__sort-icon\" [attr.data-dir]=\"sortDirFor(col)\" aria-hidden=\"true\"></span>\r\n </button>\r\n } @else {\r\n {{ col.headerKey | translate }}\r\n }\r\n </th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @if (loading()) {\r\n @for (i of skeletonRows; track i) {\r\n <tr class=\"dt__row dt__row--skel\">\r\n <td [attr.colspan]=\"columns().length\">\r\n <!-- shape=\"lines\" is the DS skeleton's no-chrome text shimmer\r\n (the kit's former shape=\"text\"); one line per collapsed row.\r\n No backticks in here: this is an INLINE template literal. -->\r\n <fly-skeleton shape=\"lines\" [lines]=\"1\" />\r\n </td>\r\n </tr>\r\n }\r\n } @else {\r\n @for (row of rows(); track $index) {\r\n <tr\r\n class=\"dt__row\"\r\n tabindex=\"0\"\r\n (click)=\"onRowActivate($event, row)\"\r\n (keydown.enter)=\"onRowActivate($event, row)\"\r\n >\r\n @for (col of columns(); track col.id) {\r\n <td\r\n [class.dt__td--end]=\"col.align === 'end'\"\r\n [class.mono]=\"col.kind === 'mono'\"\r\n [class.dt__td--date]=\"col.kind === 'date'\"\r\n [class.dt__td--num]=\"col.kind === 'number'\"\r\n [attr.data-label]=\"col.headerKey | translate\"\r\n >\r\n @if (templateFor(col.id); as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl; context: { $implicit: row }\" />\r\n } @else {\r\n @switch (col.kind ?? 'text') {\r\n @case ('date') {\r\n @if (cellValue(row, col); as value) {\r\n {{ $any(value) | date: 'yyyy-MM-dd' : 'UTC' }}\r\n } @else { \u2014 }\r\n }\r\n @default {\r\n {{ displayValue(row, col) }}\r\n }\r\n }\r\n }\r\n </td>\r\n }\r\n </tr>\r\n }\r\n }\r\n </tbody>\r\n</table>\r\n@if (!loading() && rows().length === 0 && emptyKey()) {\r\n <fly-state-message kind=\"empty\" [messageKey]=\"emptyKey()\" [iconClass]=\"emptyIconClass()\" />\r\n}\r\n", styles: ["@charset \"UTF-8\";:host{display:block;background:var(--bg-2);border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden;box-shadow:var(--shadow-card);container-type:inline-size}.dt{width:100%;border-collapse:collapse;font-size:var(--text-base)}.dt thead th{text-align:start;padding:var(--sp-2) var(--sp-3);font-size:12px;font-weight:var(--fw-bold);text-transform:uppercase;letter-spacing:.03em;color:var(--ink-3);background:var(--bg-3);border-block-end:1px solid var(--line)}.dt__th--end{text-align:end}.dt__sort{display:inline-flex;align-items:center;gap:var(--sp-1);padding:0;border:0;background:transparent;font:inherit;letter-spacing:inherit;text-transform:inherit;color:inherit;cursor:pointer}.dt__sort:hover{color:var(--ink)}.dt__sort:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.dt__sort-icon{inline-size:0;block-size:0;border-inline:4px solid transparent;border-block-start:5px solid var(--ink-4);opacity:.45;transition:transform var(--t-state),opacity var(--t-state)}.dt__sort-icon[data-dir=asc]{opacity:1;border-block-start-color:var(--accent);transform:rotate(180deg)}.dt__sort-icon[data-dir=desc]{opacity:1;border-block-start-color:var(--accent)}.dt tbody td{height:var(--row-h);padding:var(--sp-2) var(--sp-3);border-block-end:1px solid var(--line-3);color:var(--ink);transition:background var(--t-state)}.dt tbody tr:last-child td{border-block-end:0}.dt__row{cursor:pointer}.dt__row:hover td{background:var(--bg-hover)}.dt__row:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px;outline-offset:-2px}.dt__row--skel{cursor:default}.dt__row--skel:hover td{background:transparent}.dt__td--end{text-align:end}.dt__td--date,.dt__td--num{color:var(--ink-3);font-size:var(--text-sm);font-variant-numeric:tabular-nums}@container (width <= 720px){.dt thead{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.dt,.dt tbody,.dt tbody tr,.dt tbody td{display:block}.dt__row{padding:var(--sp-2) 0;border-block-end:1px solid var(--line-3)}.dt__row:last-child{border-block-end:0}.dt tbody td{display:flex;align-items:baseline;justify-content:space-between;gap:var(--sp-3);height:auto;border-block-end:0;padding:var(--sp-1) var(--sp-3);text-align:end}.dt tbody td:before{content:attr(data-label);flex-shrink:0;font-size:var(--text-xs);font-weight:var(--fw-medium);letter-spacing:var(--tracking-wide);text-transform:uppercase;color:var(--ink-4);text-align:start}}@media(width<=720px){.dt thead{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.dt,.dt tbody,.dt tbody tr,.dt tbody td{display:block}.dt__row{padding:var(--sp-2) 0;border-block-end:1px solid var(--line-3)}.dt__row:last-child{border-block-end:0}.dt tbody td{display:flex;align-items:baseline;justify-content:space-between;gap:var(--sp-3);height:auto;border-block-end:0;padding:var(--sp-1) var(--sp-3);text-align:end}.dt tbody td:before{content:attr(data-label);flex-shrink:0;font-size:var(--text-xs);font-weight:var(--fw-medium);letter-spacing:var(--tracking-wide);text-transform:uppercase;color:var(--ink-4);text-align:start}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: FlyStateMessageComponent, selector: "fly-state-message", inputs: ["kind", "messageKey", "iconClass", "noteKey", "retryLabelKey", "showRetry"], outputs: ["retried"] }, { kind: "component", type: FlySkeletonComponent, selector: "fly-skeleton", inputs: ["layout", "shape", "count", "lines", "animation", "fill", "messageKey", "announce"] }, { kind: "pipe", type: DatePipe, name: "date" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
22097
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyDataTableComponent, isStandalone: true, selector: "fly-data-table", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: true, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelKey: { classPropertyName: "ariaLabelKey", publicName: "ariaLabelKey", isSignal: true, isRequired: false, transformFunction: null }, sort: { classPropertyName: "sort", publicName: "sort", isSignal: true, isRequired: false, transformFunction: null }, emptyKey: { classPropertyName: "emptyKey", publicName: "emptyKey", isSignal: true, isRequired: false, transformFunction: null }, emptyIconClass: { classPropertyName: "emptyIconClass", publicName: "emptyIconClass", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sortChange: "sortChange", rowActivated: "rowActivated" }, queries: [{ propertyName: "cellTemplates", predicate: FlyCellDirective, isSignal: true }], ngImport: i0, template: "<table class=\"dt\" [attr.aria-label]=\"ariaLabelKey() ? (ariaLabelKey()! | translate) : null\">\r\n <thead>\r\n <tr>\r\n @for (col of columns(); track col.id) {\r\n <th\r\n scope=\"col\"\r\n [class.dt__th--end]=\"col.align === 'end'\"\r\n [attr.aria-sort]=\"headerAriaSort(col)\"\r\n >\r\n @if (col.sortable) {\r\n <button type=\"button\" class=\"dt__sort\" (click)=\"onHeaderClick(col)\">\r\n <span>{{ col.headerKey | translate }}</span>\r\n <span class=\"dt__sort-icon\" [attr.data-dir]=\"sortDirFor(col)\" aria-hidden=\"true\"></span>\r\n </button>\r\n } @else {\r\n {{ col.headerKey | translate }}\r\n }\r\n </th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @if (loading()) {\r\n @for (i of skeletonRows; track i) {\r\n <tr class=\"dt__row dt__row--skel\">\r\n <td [attr.colspan]=\"columns().length\">\r\n <!-- shape=\"lines\" is the DS skeleton's no-chrome text shimmer\r\n (the kit's former shape=\"text\"); one line per collapsed row.\r\n No backticks in here: this is an INLINE template literal. -->\r\n <fly-skeleton shape=\"lines\" [lines]=\"1\" />\r\n </td>\r\n </tr>\r\n }\r\n } @else {\r\n @for (row of rows(); track $index) {\r\n <tr\r\n class=\"dt__row\"\r\n tabindex=\"0\"\r\n (click)=\"onRowActivate($event, row)\"\r\n (keydown.enter)=\"onRowActivate($event, row)\"\r\n >\r\n @for (col of columns(); track col.id) {\r\n <td\r\n [class.dt__td--end]=\"col.align === 'end'\"\r\n [class.mono]=\"col.kind === 'mono'\"\r\n [class.dt__td--date]=\"col.kind === 'date'\"\r\n [class.dt__td--num]=\"col.kind === 'number'\"\r\n [attr.data-label]=\"col.headerKey | translate\"\r\n >\r\n @if (templateFor(col.id); as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl; context: { $implicit: row }\" />\r\n } @else {\r\n @switch (col.kind ?? 'text') {\r\n @case ('date') {\r\n @if (cellValue(row, col); as value) {\r\n {{ $any(value) | date: 'yyyy-MM-dd' : 'UTC' }}\r\n } @else { \u2014 }\r\n }\r\n @default {\r\n {{ displayValue(row, col) }}\r\n }\r\n }\r\n }\r\n </td>\r\n }\r\n </tr>\r\n }\r\n }\r\n </tbody>\r\n</table>\r\n@if (!loading() && rows().length === 0 && emptyKey()) {\r\n <fly-state-message kind=\"empty\" [messageKey]=\"emptyKey()\" [iconClass]=\"emptyIconClass()\" />\r\n}\r\n", styles: ["@charset \"UTF-8\";:host{display:block;background:var(--bg-2);border:1px solid var(--w08);border-radius:var(--r-lg);overflow:hidden;box-shadow:var(--shadow-card);container-type:inline-size}.dt{width:100%;border-collapse:collapse;font-size:var(--text-base)}.dt thead th{text-align:start;padding:var(--sp-2) var(--sp-3);font-size:12px;font-weight:var(--fw-bold);color:var(--ink-3);background:var(--bg-3);border-block-end:1px solid var(--w1)}.dt__th--end{text-align:end}.dt__sort{display:inline-flex;align-items:center;gap:var(--sp-1);padding:0;border:0;background:transparent;font:inherit;letter-spacing:inherit;text-transform:inherit;color:inherit;cursor:pointer}.dt__sort:hover{color:var(--ink)}.dt__sort:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.dt__sort-icon{inline-size:0;block-size:0;border-inline:4px solid transparent;border-block-start:5px solid var(--ink-4);opacity:.45;transition:transform var(--t-state),opacity var(--t-state)}.dt__sort-icon[data-dir=asc]{opacity:1;border-block-start-color:var(--accent);transform:rotate(180deg)}.dt__sort-icon[data-dir=desc]{opacity:1;border-block-start-color:var(--accent)}.dt tbody td{height:var(--row-h);padding:var(--sp-2) var(--sp-3);border-block-end:1px solid var(--line-3);color:var(--ink);transition:background var(--t-state)}.dt tbody tr:last-child td{border-block-end:0}.dt__row{cursor:pointer}.dt__row:hover td{background:var(--bg-hover)}.dt__row:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px;outline-offset:-2px}.dt__row--skel{cursor:default}.dt__row--skel:hover td{background:transparent}.dt__td--end{text-align:end}.dt__td--date,.dt__td--num{color:var(--ink-3);font-size:var(--text-sm);font-variant-numeric:tabular-nums}@container (width <= 720px){.dt thead{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.dt,.dt tbody,.dt tbody tr,.dt tbody td{display:block}.dt__row{padding:var(--sp-2) 0;border-block-end:1px solid var(--line-3)}.dt__row:last-child{border-block-end:0}.dt tbody td{display:flex;align-items:baseline;justify-content:space-between;gap:var(--sp-3);height:auto;border-block-end:0;padding:var(--sp-1) var(--sp-3);text-align:end}.dt tbody td:before{content:attr(data-label);flex-shrink:0;font-size:var(--text-xs);font-weight:var(--fw-medium);color:var(--ink-4);text-align:start}}@media(width<=720px){.dt thead{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.dt,.dt tbody,.dt tbody tr,.dt tbody td{display:block}.dt__row{padding:var(--sp-2) 0;border-block-end:1px solid var(--line-3)}.dt__row:last-child{border-block-end:0}.dt tbody td{display:flex;align-items:baseline;justify-content:space-between;gap:var(--sp-3);height:auto;border-block-end:0;padding:var(--sp-1) var(--sp-3);text-align:end}.dt tbody td:before{content:attr(data-label);flex-shrink:0;font-size:var(--text-xs);font-weight:var(--fw-medium);color:var(--ink-4);text-align:start}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: FlyStateMessageComponent, selector: "fly-state-message", inputs: ["kind", "messageKey", "iconClass", "noteKey", "retryLabelKey", "showRetry"], outputs: ["retried"] }, { kind: "component", type: FlySkeletonComponent, selector: "fly-skeleton", inputs: ["layout", "shape", "count", "lines", "animation", "fill", "messageKey", "announce"] }, { kind: "pipe", type: DatePipe, name: "date" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
21957
22098
  }
21958
22099
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyDataTableComponent, decorators: [{
21959
22100
  type: Component,
21960
- args: [{ selector: 'fly-data-table', standalone: true, imports: [DatePipe, NgTemplateOutlet, TranslatePipe, FlyStateMessageComponent, FlySkeletonComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<table class=\"dt\" [attr.aria-label]=\"ariaLabelKey() ? (ariaLabelKey()! | translate) : null\">\r\n <thead>\r\n <tr>\r\n @for (col of columns(); track col.id) {\r\n <th\r\n scope=\"col\"\r\n [class.dt__th--end]=\"col.align === 'end'\"\r\n [attr.aria-sort]=\"headerAriaSort(col)\"\r\n >\r\n @if (col.sortable) {\r\n <button type=\"button\" class=\"dt__sort\" (click)=\"onHeaderClick(col)\">\r\n <span>{{ col.headerKey | translate }}</span>\r\n <span class=\"dt__sort-icon\" [attr.data-dir]=\"sortDirFor(col)\" aria-hidden=\"true\"></span>\r\n </button>\r\n } @else {\r\n {{ col.headerKey | translate }}\r\n }\r\n </th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @if (loading()) {\r\n @for (i of skeletonRows; track i) {\r\n <tr class=\"dt__row dt__row--skel\">\r\n <td [attr.colspan]=\"columns().length\">\r\n <!-- shape=\"lines\" is the DS skeleton's no-chrome text shimmer\r\n (the kit's former shape=\"text\"); one line per collapsed row.\r\n No backticks in here: this is an INLINE template literal. -->\r\n <fly-skeleton shape=\"lines\" [lines]=\"1\" />\r\n </td>\r\n </tr>\r\n }\r\n } @else {\r\n @for (row of rows(); track $index) {\r\n <tr\r\n class=\"dt__row\"\r\n tabindex=\"0\"\r\n (click)=\"onRowActivate($event, row)\"\r\n (keydown.enter)=\"onRowActivate($event, row)\"\r\n >\r\n @for (col of columns(); track col.id) {\r\n <td\r\n [class.dt__td--end]=\"col.align === 'end'\"\r\n [class.mono]=\"col.kind === 'mono'\"\r\n [class.dt__td--date]=\"col.kind === 'date'\"\r\n [class.dt__td--num]=\"col.kind === 'number'\"\r\n [attr.data-label]=\"col.headerKey | translate\"\r\n >\r\n @if (templateFor(col.id); as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl; context: { $implicit: row }\" />\r\n } @else {\r\n @switch (col.kind ?? 'text') {\r\n @case ('date') {\r\n @if (cellValue(row, col); as value) {\r\n {{ $any(value) | date: 'yyyy-MM-dd' : 'UTC' }}\r\n } @else { \u2014 }\r\n }\r\n @default {\r\n {{ displayValue(row, col) }}\r\n }\r\n }\r\n }\r\n </td>\r\n }\r\n </tr>\r\n }\r\n }\r\n </tbody>\r\n</table>\r\n@if (!loading() && rows().length === 0 && emptyKey()) {\r\n <fly-state-message kind=\"empty\" [messageKey]=\"emptyKey()\" [iconClass]=\"emptyIconClass()\" />\r\n}\r\n", styles: ["@charset \"UTF-8\";:host{display:block;background:var(--bg-2);border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden;box-shadow:var(--shadow-card);container-type:inline-size}.dt{width:100%;border-collapse:collapse;font-size:var(--text-base)}.dt thead th{text-align:start;padding:var(--sp-2) var(--sp-3);font-size:12px;font-weight:var(--fw-bold);text-transform:uppercase;letter-spacing:.03em;color:var(--ink-3);background:var(--bg-3);border-block-end:1px solid var(--line)}.dt__th--end{text-align:end}.dt__sort{display:inline-flex;align-items:center;gap:var(--sp-1);padding:0;border:0;background:transparent;font:inherit;letter-spacing:inherit;text-transform:inherit;color:inherit;cursor:pointer}.dt__sort:hover{color:var(--ink)}.dt__sort:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.dt__sort-icon{inline-size:0;block-size:0;border-inline:4px solid transparent;border-block-start:5px solid var(--ink-4);opacity:.45;transition:transform var(--t-state),opacity var(--t-state)}.dt__sort-icon[data-dir=asc]{opacity:1;border-block-start-color:var(--accent);transform:rotate(180deg)}.dt__sort-icon[data-dir=desc]{opacity:1;border-block-start-color:var(--accent)}.dt tbody td{height:var(--row-h);padding:var(--sp-2) var(--sp-3);border-block-end:1px solid var(--line-3);color:var(--ink);transition:background var(--t-state)}.dt tbody tr:last-child td{border-block-end:0}.dt__row{cursor:pointer}.dt__row:hover td{background:var(--bg-hover)}.dt__row:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px;outline-offset:-2px}.dt__row--skel{cursor:default}.dt__row--skel:hover td{background:transparent}.dt__td--end{text-align:end}.dt__td--date,.dt__td--num{color:var(--ink-3);font-size:var(--text-sm);font-variant-numeric:tabular-nums}@container (width <= 720px){.dt thead{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.dt,.dt tbody,.dt tbody tr,.dt tbody td{display:block}.dt__row{padding:var(--sp-2) 0;border-block-end:1px solid var(--line-3)}.dt__row:last-child{border-block-end:0}.dt tbody td{display:flex;align-items:baseline;justify-content:space-between;gap:var(--sp-3);height:auto;border-block-end:0;padding:var(--sp-1) var(--sp-3);text-align:end}.dt tbody td:before{content:attr(data-label);flex-shrink:0;font-size:var(--text-xs);font-weight:var(--fw-medium);letter-spacing:var(--tracking-wide);text-transform:uppercase;color:var(--ink-4);text-align:start}}@media(width<=720px){.dt thead{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.dt,.dt tbody,.dt tbody tr,.dt tbody td{display:block}.dt__row{padding:var(--sp-2) 0;border-block-end:1px solid var(--line-3)}.dt__row:last-child{border-block-end:0}.dt tbody td{display:flex;align-items:baseline;justify-content:space-between;gap:var(--sp-3);height:auto;border-block-end:0;padding:var(--sp-1) var(--sp-3);text-align:end}.dt tbody td:before{content:attr(data-label);flex-shrink:0;font-size:var(--text-xs);font-weight:var(--fw-medium);letter-spacing:var(--tracking-wide);text-transform:uppercase;color:var(--ink-4);text-align:start}}\n"] }]
22101
+ args: [{ selector: 'fly-data-table', standalone: true, imports: [DatePipe, NgTemplateOutlet, TranslatePipe, FlyStateMessageComponent, FlySkeletonComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<table class=\"dt\" [attr.aria-label]=\"ariaLabelKey() ? (ariaLabelKey()! | translate) : null\">\r\n <thead>\r\n <tr>\r\n @for (col of columns(); track col.id) {\r\n <th\r\n scope=\"col\"\r\n [class.dt__th--end]=\"col.align === 'end'\"\r\n [attr.aria-sort]=\"headerAriaSort(col)\"\r\n >\r\n @if (col.sortable) {\r\n <button type=\"button\" class=\"dt__sort\" (click)=\"onHeaderClick(col)\">\r\n <span>{{ col.headerKey | translate }}</span>\r\n <span class=\"dt__sort-icon\" [attr.data-dir]=\"sortDirFor(col)\" aria-hidden=\"true\"></span>\r\n </button>\r\n } @else {\r\n {{ col.headerKey | translate }}\r\n }\r\n </th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @if (loading()) {\r\n @for (i of skeletonRows; track i) {\r\n <tr class=\"dt__row dt__row--skel\">\r\n <td [attr.colspan]=\"columns().length\">\r\n <!-- shape=\"lines\" is the DS skeleton's no-chrome text shimmer\r\n (the kit's former shape=\"text\"); one line per collapsed row.\r\n No backticks in here: this is an INLINE template literal. -->\r\n <fly-skeleton shape=\"lines\" [lines]=\"1\" />\r\n </td>\r\n </tr>\r\n }\r\n } @else {\r\n @for (row of rows(); track $index) {\r\n <tr\r\n class=\"dt__row\"\r\n tabindex=\"0\"\r\n (click)=\"onRowActivate($event, row)\"\r\n (keydown.enter)=\"onRowActivate($event, row)\"\r\n >\r\n @for (col of columns(); track col.id) {\r\n <td\r\n [class.dt__td--end]=\"col.align === 'end'\"\r\n [class.mono]=\"col.kind === 'mono'\"\r\n [class.dt__td--date]=\"col.kind === 'date'\"\r\n [class.dt__td--num]=\"col.kind === 'number'\"\r\n [attr.data-label]=\"col.headerKey | translate\"\r\n >\r\n @if (templateFor(col.id); as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl; context: { $implicit: row }\" />\r\n } @else {\r\n @switch (col.kind ?? 'text') {\r\n @case ('date') {\r\n @if (cellValue(row, col); as value) {\r\n {{ $any(value) | date: 'yyyy-MM-dd' : 'UTC' }}\r\n } @else { \u2014 }\r\n }\r\n @default {\r\n {{ displayValue(row, col) }}\r\n }\r\n }\r\n }\r\n </td>\r\n }\r\n </tr>\r\n }\r\n }\r\n </tbody>\r\n</table>\r\n@if (!loading() && rows().length === 0 && emptyKey()) {\r\n <fly-state-message kind=\"empty\" [messageKey]=\"emptyKey()\" [iconClass]=\"emptyIconClass()\" />\r\n}\r\n", styles: ["@charset \"UTF-8\";:host{display:block;background:var(--bg-2);border:1px solid var(--w08);border-radius:var(--r-lg);overflow:hidden;box-shadow:var(--shadow-card);container-type:inline-size}.dt{width:100%;border-collapse:collapse;font-size:var(--text-base)}.dt thead th{text-align:start;padding:var(--sp-2) var(--sp-3);font-size:12px;font-weight:var(--fw-bold);color:var(--ink-3);background:var(--bg-3);border-block-end:1px solid var(--w1)}.dt__th--end{text-align:end}.dt__sort{display:inline-flex;align-items:center;gap:var(--sp-1);padding:0;border:0;background:transparent;font:inherit;letter-spacing:inherit;text-transform:inherit;color:inherit;cursor:pointer}.dt__sort:hover{color:var(--ink)}.dt__sort:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.dt__sort-icon{inline-size:0;block-size:0;border-inline:4px solid transparent;border-block-start:5px solid var(--ink-4);opacity:.45;transition:transform var(--t-state),opacity var(--t-state)}.dt__sort-icon[data-dir=asc]{opacity:1;border-block-start-color:var(--accent);transform:rotate(180deg)}.dt__sort-icon[data-dir=desc]{opacity:1;border-block-start-color:var(--accent)}.dt tbody td{height:var(--row-h);padding:var(--sp-2) var(--sp-3);border-block-end:1px solid var(--line-3);color:var(--ink);transition:background var(--t-state)}.dt tbody tr:last-child td{border-block-end:0}.dt__row{cursor:pointer}.dt__row:hover td{background:var(--bg-hover)}.dt__row:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px;outline-offset:-2px}.dt__row--skel{cursor:default}.dt__row--skel:hover td{background:transparent}.dt__td--end{text-align:end}.dt__td--date,.dt__td--num{color:var(--ink-3);font-size:var(--text-sm);font-variant-numeric:tabular-nums}@container (width <= 720px){.dt thead{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.dt,.dt tbody,.dt tbody tr,.dt tbody td{display:block}.dt__row{padding:var(--sp-2) 0;border-block-end:1px solid var(--line-3)}.dt__row:last-child{border-block-end:0}.dt tbody td{display:flex;align-items:baseline;justify-content:space-between;gap:var(--sp-3);height:auto;border-block-end:0;padding:var(--sp-1) var(--sp-3);text-align:end}.dt tbody td:before{content:attr(data-label);flex-shrink:0;font-size:var(--text-xs);font-weight:var(--fw-medium);color:var(--ink-4);text-align:start}}@media(width<=720px){.dt thead{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.dt,.dt tbody,.dt tbody tr,.dt tbody td{display:block}.dt__row{padding:var(--sp-2) 0;border-block-end:1px solid var(--line-3)}.dt__row:last-child{border-block-end:0}.dt tbody td{display:flex;align-items:baseline;justify-content:space-between;gap:var(--sp-3);height:auto;border-block-end:0;padding:var(--sp-1) var(--sp-3);text-align:end}.dt tbody td:before{content:attr(data-label);flex-shrink:0;font-size:var(--text-xs);font-weight:var(--fw-medium);color:var(--ink-4);text-align:start}}\n"] }]
21961
22102
  }], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: true }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], ariaLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabelKey", required: false }] }], sort: [{ type: i0.Input, args: [{ isSignal: true, alias: "sort", required: false }] }], sortChange: [{ type: i0.Output, args: ["sortChange"] }], rowActivated: [{ type: i0.Output, args: ["rowActivated"] }], emptyKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyKey", required: false }] }], emptyIconClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyIconClass", required: false }] }], cellTemplates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => FlyCellDirective), { isSignal: true }] }] } });
21962
22103
 
21963
22104
  /**
@@ -22170,11 +22311,11 @@ class PageHeaderComponent {
22170
22311
  return '#';
22171
22312
  }
22172
22313
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: PageHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
22173
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: PageHeaderComponent, isStandalone: true, selector: "fly-page-header", inputs: { variant: "variant", title: "title", titleKey: "titleKey", subtitle: "subtitle", subtitleKey: "subtitleKey", titleAr: "titleAr", eyebrow: "eyebrow", eyebrowKey: "eyebrowKey", metricValue: "metricValue", metricLabel: "metricLabel", metricLabelKey: "metricLabelKey", breadcrumbs: "breadcrumbs" }, outputs: { crumbClick: "crumbClick" }, ngImport: i0, template: "<header class=\"ph\" [ngClass]=\"'ph--' + variant\">\r\n <!-- \u2500\u2500\u2500 Breadcrumbs \u2500\u2500\u2500 -->\r\n @if (breadcrumbs?.length) {\r\n <nav class=\"crumbs\" [attr.aria-label]=\"'ui.nav.breadcrumbs' | translate\">\r\n @for (bc of breadcrumbs; track $index; let i = $index, last = $last) {\r\n @if (i > 0) {\r\n <span class=\"crumb__sep\" aria-hidden=\"true\">/</span>\r\n }\r\n @if (last || bc.ariaCurrent) {\r\n <span class=\"crumb crumb--active\" aria-current=\"page\">\r\n {{ bc.labelKey ? (bc.labelKey | translate) : bc.label }}\r\n </span>\r\n } @else if (bc.onClick) {\r\n <button type=\"button\" class=\"crumb crumb--link\" (click)=\"onCrumb(bc)\">\r\n {{ bc.labelKey ? (bc.labelKey | translate) : bc.label }}\r\n </button>\r\n } @else if (bc.link) {\r\n <a class=\"crumb crumb--link\" (click)=\"onCrumb(bc); $event.preventDefault()\" [attr.href]=\"hrefFor(bc)\">\r\n {{ bc.labelKey ? (bc.labelKey | translate) : bc.label }}\r\n </a>\r\n } @else if (bc.href) {\r\n <a class=\"crumb crumb--link\" [attr.href]=\"bc.href\">\r\n {{ bc.labelKey ? (bc.labelKey | translate) : bc.label }}\r\n </a>\r\n } @else {\r\n <span class=\"crumb\">\r\n {{ bc.labelKey ? (bc.labelKey | translate) : bc.label }}\r\n </span>\r\n }\r\n }\r\n </nav>\r\n }\r\n\r\n <!-- \u2500\u2500\u2500 Title row \u2500\u2500\u2500 -->\r\n <div class=\"ph__row\">\r\n <div class=\"ph__l\">\r\n @if (eyebrow || eyebrowKey) {\r\n <div class=\"ph__eyebrow\">\r\n @if (eyebrow) { <span class=\"mono\">{{ eyebrow }}</span> }\r\n @if (eyebrowKey) { <span>{{ eyebrowKey | translate }}</span> }\r\n </div>\r\n }\r\n <h1 class=\"ph__title\" [ngClass]=\"{ 'ph__title--detail': variant === 'detail' }\">\r\n {{ titleKey ? (titleKey | translate) : title }}\r\n </h1>\r\n @if (subtitle || subtitleKey) {\r\n <p class=\"ph__sub\">{{ subtitleKey ? (subtitleKey | translate) : subtitle }}</p>\r\n }\r\n @if (titleAr) {\r\n <p class=\"ph__title-ar\">{{ titleAr }}</p>\r\n }\r\n </div>\r\n\r\n <div class=\"ph__r\">\r\n <!-- Right-side metric (listing) -->\r\n @if (metricValue || metricLabel || metricLabelKey) {\r\n <div class=\"ph__metric\">\r\n @if (metricValue) { <div class=\"ph__metric-v mono\">{{ metricValue }}</div> }\r\n <div class=\"ph__metric-l\">{{ metricLabelKey ? (metricLabelKey | translate) : metricLabel }}</div>\r\n </div>\r\n }\r\n\r\n <!-- Status chip (detail) stacked over the action button row. Listing/circles/module\r\n project no status, so this collapses to just the right-aligned action row.\r\n NOTE: a single [page-header-actions] slot \u2014 duplicating it across @if branches\r\n silently drops projected content in the non-first branch (Angular binds projection\r\n to the first declared matching <ng-content>). -->\r\n <div class=\"ph__hd-actions\">\r\n <ng-content select=\"[page-header-status]\"></ng-content>\r\n <div class=\"ph__hd-btns\">\r\n <ng-content select=\"[page-header-actions]\"></ng-content>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Default slot: anything the consumer wants directly below the title row\r\n (e.g. a detail-page stat bar). -->\r\n <ng-content></ng-content>\r\n</header>\r\n", styles: ["@charset \"UTF-8\";:host{display:block;margin-block-end:var(--sp-6);container-type:inline-size}.ph{display:flex;flex-direction:column;gap:0;color:var(--ink);font-family:var(--font-sans, var(--font-family, system-ui, sans-serif))}.crumbs{display:flex;align-items:center;gap:6px;flex-wrap:wrap;font-size:12px;margin-bottom:14px;color:var(--ink-3)}.crumb{font-size:12px;line-height:1.4;color:var(--ink-3);padding:2px 0;background:none;border:0;font-family:inherit;letter-spacing:-.005em;text-decoration:none}.crumb--link{cursor:pointer;padding-inline:4px;margin-inline:-4px;border-radius:6px;transition:color var(--t-state),background var(--t-state)}.crumb--link:hover{color:var(--ink);background:var(--w08)}.crumb--active{color:var(--ink);font-weight:var(--fw-medium);max-width:480px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.crumb__sep{color:var(--ink-4);font-size:11px;-webkit-user-select:none;user-select:none}.ph__row{display:flex;align-items:flex-end;justify-content:space-between;gap:12px 32px;flex-wrap:wrap}.ph--detail .ph__row{align-items:flex-start}.ph__l{flex:1;min-width:min(100%,320px)}.ph__r{display:flex;align-items:flex-end;gap:16px;flex-shrink:0}.ph--detail .ph__r{align-items:flex-end;flex-direction:column}.ph__eyebrow{display:inline-flex;align-items:center;gap:6px;font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-4);font-weight:var(--fw-medium);margin-bottom:4px}.ph__eyebrow .mono{font-size:10.5px;color:var(--ink-3);letter-spacing:.04em;font-family:var(--font-mono, ui-monospace, monospace)}.ph__title{margin:0 0 6px;font-size:32px;font-weight:var(--fw-semibold);letter-spacing:-.02em;line-height:1.1;color:var(--ink)}.ph__title--detail{font-size:28px;letter-spacing:-.02em;line-height:1.2;margin:0}.ph__sub{margin:0;font-size:13.5px;color:var(--ink-3)}.ph__title-ar{margin:6px 0 0;font-size:17px;color:var(--ink-3);font-family:Noto Kufi Arabic,sans-serif;letter-spacing:0;line-height:1.5;font-weight:var(--fw-medium)}.ph__metric{text-align:end}.ph__metric-v{font-family:var(--font-mono, ui-monospace, monospace);font-variant-numeric:tabular-nums;font-size:22px;font-weight:var(--fw-medium);letter-spacing:-.02em;color:var(--ink)}.ph__metric-l{font-size:11px;color:var(--ink-3);text-transform:uppercase;letter-spacing:.06em}.ph__hd-actions{display:flex;flex-direction:column;align-items:flex-end;gap:10px}.ph__hd-btns{display:flex;gap:6px;flex-wrap:wrap;justify-content:flex-end}.ph--listing,.ph--detail{margin-bottom:0}@container (width <= 640px){.ph__row{flex-direction:column;align-items:flex-start;gap:16px}.ph__r{align-items:flex-start;flex-flow:row wrap}.ph--detail .ph__r{flex-direction:row-reverse}.ph__title{font-size:26px}.ph__title--detail{font-size:24px}}@media(width<=640px){.ph__row{flex-direction:column;align-items:flex-start;gap:16px}.ph__r{align-items:flex-start;flex-flow:row wrap}.ph--detail .ph__r{flex-direction:row-reverse}.ph__title{font-size:26px}.ph__title--detail{font-size:24px}}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
22314
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: PageHeaderComponent, isStandalone: true, selector: "fly-page-header", inputs: { variant: "variant", title: "title", titleKey: "titleKey", subtitle: "subtitle", subtitleKey: "subtitleKey", titleAr: "titleAr", eyebrow: "eyebrow", eyebrowKey: "eyebrowKey", metricValue: "metricValue", metricLabel: "metricLabel", metricLabelKey: "metricLabelKey", breadcrumbs: "breadcrumbs" }, outputs: { crumbClick: "crumbClick" }, ngImport: i0, template: "<header class=\"ph\" [ngClass]=\"'ph--' + variant\">\r\n <!-- \u2500\u2500\u2500 Breadcrumbs \u2500\u2500\u2500 -->\r\n @if (breadcrumbs?.length) {\r\n <nav class=\"crumbs\" [attr.aria-label]=\"'ui.nav.breadcrumbs' | translate\">\r\n @for (bc of breadcrumbs; track $index; let i = $index, last = $last) {\r\n @if (i > 0) {\r\n <span class=\"crumb__sep\" aria-hidden=\"true\">/</span>\r\n }\r\n @if (last || bc.ariaCurrent) {\r\n <span class=\"crumb crumb--active\" aria-current=\"page\">\r\n {{ bc.labelKey ? (bc.labelKey | translate) : bc.label }}\r\n </span>\r\n } @else if (bc.onClick) {\r\n <button type=\"button\" class=\"crumb crumb--link\" (click)=\"onCrumb(bc)\">\r\n {{ bc.labelKey ? (bc.labelKey | translate) : bc.label }}\r\n </button>\r\n } @else if (bc.link) {\r\n <a class=\"crumb crumb--link\" (click)=\"onCrumb(bc); $event.preventDefault()\" [attr.href]=\"hrefFor(bc)\">\r\n {{ bc.labelKey ? (bc.labelKey | translate) : bc.label }}\r\n </a>\r\n } @else if (bc.href) {\r\n <a class=\"crumb crumb--link\" [attr.href]=\"bc.href\">\r\n {{ bc.labelKey ? (bc.labelKey | translate) : bc.label }}\r\n </a>\r\n } @else {\r\n <span class=\"crumb\">\r\n {{ bc.labelKey ? (bc.labelKey | translate) : bc.label }}\r\n </span>\r\n }\r\n }\r\n </nav>\r\n }\r\n\r\n <!-- \u2500\u2500\u2500 Title row \u2500\u2500\u2500 -->\r\n <div class=\"ph__row\">\r\n <div class=\"ph__l\">\r\n @if (eyebrow || eyebrowKey) {\r\n <div class=\"ph__eyebrow\">\r\n @if (eyebrow) { <span class=\"mono\">{{ eyebrow }}</span> }\r\n @if (eyebrowKey) { <span>{{ eyebrowKey | translate }}</span> }\r\n </div>\r\n }\r\n <h1 class=\"ph__title\" [ngClass]=\"{ 'ph__title--detail': variant === 'detail' }\">\r\n {{ titleKey ? (titleKey | translate) : title }}\r\n </h1>\r\n @if (subtitle || subtitleKey) {\r\n <p class=\"ph__sub\">{{ subtitleKey ? (subtitleKey | translate) : subtitle }}</p>\r\n }\r\n @if (titleAr) {\r\n <p class=\"ph__title-ar\">{{ titleAr }}</p>\r\n }\r\n </div>\r\n\r\n <div class=\"ph__r\">\r\n <!-- Right-side metric (listing) -->\r\n @if (metricValue || metricLabel || metricLabelKey) {\r\n <div class=\"ph__metric\">\r\n @if (metricValue) { <div class=\"ph__metric-v mono\">{{ metricValue }}</div> }\r\n <div class=\"ph__metric-l\">{{ metricLabelKey ? (metricLabelKey | translate) : metricLabel }}</div>\r\n </div>\r\n }\r\n\r\n <!-- Status chip (detail) stacked over the action button row. Listing/circles/module\r\n project no status, so this collapses to just the right-aligned action row.\r\n NOTE: a single [page-header-actions] slot \u2014 duplicating it across @if branches\r\n silently drops projected content in the non-first branch (Angular binds projection\r\n to the first declared matching <ng-content>). -->\r\n <div class=\"ph__hd-actions\">\r\n <ng-content select=\"[page-header-status]\"></ng-content>\r\n <div class=\"ph__hd-btns\">\r\n <ng-content select=\"[page-header-actions]\"></ng-content>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Default slot: anything the consumer wants directly below the title row\r\n (e.g. a detail-page stat bar). -->\r\n <ng-content></ng-content>\r\n</header>\r\n", styles: ["@charset \"UTF-8\";:host{display:block;margin-block-end:var(--sp-6);container-type:inline-size}.ph{display:flex;flex-direction:column;gap:0;color:var(--ink);font-family:var(--font-sans, var(--font-family, system-ui, sans-serif))}.crumbs{display:flex;align-items:center;gap:6px;flex-wrap:wrap;font-size:12px;margin-bottom:14px;color:var(--ink-3)}.crumb{font-size:12px;line-height:1.4;color:var(--ink-3);padding:2px 0;background:none;border:0;font-family:inherit;letter-spacing:-.005em;text-decoration:none}.crumb--link{cursor:pointer;padding-inline:4px;margin-inline:-4px;border-radius:6px;transition:color var(--t-state),background var(--t-state)}.crumb--link:hover{color:var(--ink);background:var(--w08)}.crumb--active{color:var(--ink);font-weight:var(--fw-medium);max-width:480px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.crumb__sep{color:var(--ink-4);font-size:11px;-webkit-user-select:none;user-select:none}.ph__row{display:flex;align-items:flex-end;justify-content:space-between;gap:12px 32px;flex-wrap:wrap}.ph--detail .ph__row{align-items:flex-start}.ph__l{flex:1}.ph__r{display:flex;align-items:flex-end;gap:16px;flex-shrink:0}.ph--detail .ph__r{align-items:flex-end;flex-direction:column}.ph__eyebrow{display:inline-flex;align-items:center;gap:6px;font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-4);font-weight:var(--fw-medium);margin-bottom:4px}.ph__eyebrow .mono{font-size:10.5px;color:var(--ink-3);letter-spacing:.04em;font-family:var(--font-mono, ui-monospace, monospace)}.ph__title{margin:0 0 6px;font-size:32px;font-weight:var(--fw-semibold);letter-spacing:-.02em;line-height:1.1;color:var(--ink)}.ph__title--detail{font-size:28px;letter-spacing:-.02em;line-height:1.2;margin:0}.ph__sub{margin:0;font-size:13.5px;color:var(--ink-3)}.ph__title-ar{margin:6px 0 0;font-size:17px;color:var(--ink-3);font-family:Noto Kufi Arabic,sans-serif;letter-spacing:0;line-height:1.5;font-weight:var(--fw-medium)}.ph__metric{text-align:end}.ph__metric-v{font-family:var(--font-mono, ui-monospace, monospace);font-variant-numeric:tabular-nums;font-size:22px;font-weight:var(--fw-medium);letter-spacing:-.02em;color:var(--ink)}.ph__metric-l{font-size:11px;color:var(--ink-3);text-transform:uppercase;letter-spacing:.06em}.ph__hd-actions{display:flex;flex-direction:column;align-items:flex-end;gap:10px}.ph__hd-btns{display:flex;gap:6px;flex-wrap:wrap;justify-content:flex-end}.ph--listing,.ph--detail{margin-bottom:0}@container (width <= 640px){.ph__row{flex-direction:column;align-items:flex-start;gap:16px}.ph__r{align-items:flex-start;flex-flow:row wrap}.ph--detail .ph__r{flex-direction:row-reverse}.ph__title{font-size:26px}.ph__title--detail{font-size:24px}}@media(width<=640px){.ph__row{flex-direction:column;align-items:flex-start;gap:16px}.ph__r{align-items:flex-start;flex-flow:row wrap}.ph--detail .ph__r{flex-direction:row-reverse}.ph__title{font-size:26px}.ph__title--detail{font-size:24px}}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
22174
22315
  }
22175
22316
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: PageHeaderComponent, decorators: [{
22176
22317
  type: Component,
22177
- args: [{ selector: 'fly-page-header', standalone: true, imports: [NgClass, TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<header class=\"ph\" [ngClass]=\"'ph--' + variant\">\r\n <!-- \u2500\u2500\u2500 Breadcrumbs \u2500\u2500\u2500 -->\r\n @if (breadcrumbs?.length) {\r\n <nav class=\"crumbs\" [attr.aria-label]=\"'ui.nav.breadcrumbs' | translate\">\r\n @for (bc of breadcrumbs; track $index; let i = $index, last = $last) {\r\n @if (i > 0) {\r\n <span class=\"crumb__sep\" aria-hidden=\"true\">/</span>\r\n }\r\n @if (last || bc.ariaCurrent) {\r\n <span class=\"crumb crumb--active\" aria-current=\"page\">\r\n {{ bc.labelKey ? (bc.labelKey | translate) : bc.label }}\r\n </span>\r\n } @else if (bc.onClick) {\r\n <button type=\"button\" class=\"crumb crumb--link\" (click)=\"onCrumb(bc)\">\r\n {{ bc.labelKey ? (bc.labelKey | translate) : bc.label }}\r\n </button>\r\n } @else if (bc.link) {\r\n <a class=\"crumb crumb--link\" (click)=\"onCrumb(bc); $event.preventDefault()\" [attr.href]=\"hrefFor(bc)\">\r\n {{ bc.labelKey ? (bc.labelKey | translate) : bc.label }}\r\n </a>\r\n } @else if (bc.href) {\r\n <a class=\"crumb crumb--link\" [attr.href]=\"bc.href\">\r\n {{ bc.labelKey ? (bc.labelKey | translate) : bc.label }}\r\n </a>\r\n } @else {\r\n <span class=\"crumb\">\r\n {{ bc.labelKey ? (bc.labelKey | translate) : bc.label }}\r\n </span>\r\n }\r\n }\r\n </nav>\r\n }\r\n\r\n <!-- \u2500\u2500\u2500 Title row \u2500\u2500\u2500 -->\r\n <div class=\"ph__row\">\r\n <div class=\"ph__l\">\r\n @if (eyebrow || eyebrowKey) {\r\n <div class=\"ph__eyebrow\">\r\n @if (eyebrow) { <span class=\"mono\">{{ eyebrow }}</span> }\r\n @if (eyebrowKey) { <span>{{ eyebrowKey | translate }}</span> }\r\n </div>\r\n }\r\n <h1 class=\"ph__title\" [ngClass]=\"{ 'ph__title--detail': variant === 'detail' }\">\r\n {{ titleKey ? (titleKey | translate) : title }}\r\n </h1>\r\n @if (subtitle || subtitleKey) {\r\n <p class=\"ph__sub\">{{ subtitleKey ? (subtitleKey | translate) : subtitle }}</p>\r\n }\r\n @if (titleAr) {\r\n <p class=\"ph__title-ar\">{{ titleAr }}</p>\r\n }\r\n </div>\r\n\r\n <div class=\"ph__r\">\r\n <!-- Right-side metric (listing) -->\r\n @if (metricValue || metricLabel || metricLabelKey) {\r\n <div class=\"ph__metric\">\r\n @if (metricValue) { <div class=\"ph__metric-v mono\">{{ metricValue }}</div> }\r\n <div class=\"ph__metric-l\">{{ metricLabelKey ? (metricLabelKey | translate) : metricLabel }}</div>\r\n </div>\r\n }\r\n\r\n <!-- Status chip (detail) stacked over the action button row. Listing/circles/module\r\n project no status, so this collapses to just the right-aligned action row.\r\n NOTE: a single [page-header-actions] slot \u2014 duplicating it across @if branches\r\n silently drops projected content in the non-first branch (Angular binds projection\r\n to the first declared matching <ng-content>). -->\r\n <div class=\"ph__hd-actions\">\r\n <ng-content select=\"[page-header-status]\"></ng-content>\r\n <div class=\"ph__hd-btns\">\r\n <ng-content select=\"[page-header-actions]\"></ng-content>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Default slot: anything the consumer wants directly below the title row\r\n (e.g. a detail-page stat bar). -->\r\n <ng-content></ng-content>\r\n</header>\r\n", styles: ["@charset \"UTF-8\";:host{display:block;margin-block-end:var(--sp-6);container-type:inline-size}.ph{display:flex;flex-direction:column;gap:0;color:var(--ink);font-family:var(--font-sans, var(--font-family, system-ui, sans-serif))}.crumbs{display:flex;align-items:center;gap:6px;flex-wrap:wrap;font-size:12px;margin-bottom:14px;color:var(--ink-3)}.crumb{font-size:12px;line-height:1.4;color:var(--ink-3);padding:2px 0;background:none;border:0;font-family:inherit;letter-spacing:-.005em;text-decoration:none}.crumb--link{cursor:pointer;padding-inline:4px;margin-inline:-4px;border-radius:6px;transition:color var(--t-state),background var(--t-state)}.crumb--link:hover{color:var(--ink);background:var(--w08)}.crumb--active{color:var(--ink);font-weight:var(--fw-medium);max-width:480px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.crumb__sep{color:var(--ink-4);font-size:11px;-webkit-user-select:none;user-select:none}.ph__row{display:flex;align-items:flex-end;justify-content:space-between;gap:12px 32px;flex-wrap:wrap}.ph--detail .ph__row{align-items:flex-start}.ph__l{flex:1;min-width:min(100%,320px)}.ph__r{display:flex;align-items:flex-end;gap:16px;flex-shrink:0}.ph--detail .ph__r{align-items:flex-end;flex-direction:column}.ph__eyebrow{display:inline-flex;align-items:center;gap:6px;font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-4);font-weight:var(--fw-medium);margin-bottom:4px}.ph__eyebrow .mono{font-size:10.5px;color:var(--ink-3);letter-spacing:.04em;font-family:var(--font-mono, ui-monospace, monospace)}.ph__title{margin:0 0 6px;font-size:32px;font-weight:var(--fw-semibold);letter-spacing:-.02em;line-height:1.1;color:var(--ink)}.ph__title--detail{font-size:28px;letter-spacing:-.02em;line-height:1.2;margin:0}.ph__sub{margin:0;font-size:13.5px;color:var(--ink-3)}.ph__title-ar{margin:6px 0 0;font-size:17px;color:var(--ink-3);font-family:Noto Kufi Arabic,sans-serif;letter-spacing:0;line-height:1.5;font-weight:var(--fw-medium)}.ph__metric{text-align:end}.ph__metric-v{font-family:var(--font-mono, ui-monospace, monospace);font-variant-numeric:tabular-nums;font-size:22px;font-weight:var(--fw-medium);letter-spacing:-.02em;color:var(--ink)}.ph__metric-l{font-size:11px;color:var(--ink-3);text-transform:uppercase;letter-spacing:.06em}.ph__hd-actions{display:flex;flex-direction:column;align-items:flex-end;gap:10px}.ph__hd-btns{display:flex;gap:6px;flex-wrap:wrap;justify-content:flex-end}.ph--listing,.ph--detail{margin-bottom:0}@container (width <= 640px){.ph__row{flex-direction:column;align-items:flex-start;gap:16px}.ph__r{align-items:flex-start;flex-flow:row wrap}.ph--detail .ph__r{flex-direction:row-reverse}.ph__title{font-size:26px}.ph__title--detail{font-size:24px}}@media(width<=640px){.ph__row{flex-direction:column;align-items:flex-start;gap:16px}.ph__r{align-items:flex-start;flex-flow:row wrap}.ph--detail .ph__r{flex-direction:row-reverse}.ph__title{font-size:26px}.ph__title--detail{font-size:24px}}\n"] }]
22318
+ args: [{ selector: 'fly-page-header', standalone: true, imports: [NgClass, TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<header class=\"ph\" [ngClass]=\"'ph--' + variant\">\r\n <!-- \u2500\u2500\u2500 Breadcrumbs \u2500\u2500\u2500 -->\r\n @if (breadcrumbs?.length) {\r\n <nav class=\"crumbs\" [attr.aria-label]=\"'ui.nav.breadcrumbs' | translate\">\r\n @for (bc of breadcrumbs; track $index; let i = $index, last = $last) {\r\n @if (i > 0) {\r\n <span class=\"crumb__sep\" aria-hidden=\"true\">/</span>\r\n }\r\n @if (last || bc.ariaCurrent) {\r\n <span class=\"crumb crumb--active\" aria-current=\"page\">\r\n {{ bc.labelKey ? (bc.labelKey | translate) : bc.label }}\r\n </span>\r\n } @else if (bc.onClick) {\r\n <button type=\"button\" class=\"crumb crumb--link\" (click)=\"onCrumb(bc)\">\r\n {{ bc.labelKey ? (bc.labelKey | translate) : bc.label }}\r\n </button>\r\n } @else if (bc.link) {\r\n <a class=\"crumb crumb--link\" (click)=\"onCrumb(bc); $event.preventDefault()\" [attr.href]=\"hrefFor(bc)\">\r\n {{ bc.labelKey ? (bc.labelKey | translate) : bc.label }}\r\n </a>\r\n } @else if (bc.href) {\r\n <a class=\"crumb crumb--link\" [attr.href]=\"bc.href\">\r\n {{ bc.labelKey ? (bc.labelKey | translate) : bc.label }}\r\n </a>\r\n } @else {\r\n <span class=\"crumb\">\r\n {{ bc.labelKey ? (bc.labelKey | translate) : bc.label }}\r\n </span>\r\n }\r\n }\r\n </nav>\r\n }\r\n\r\n <!-- \u2500\u2500\u2500 Title row \u2500\u2500\u2500 -->\r\n <div class=\"ph__row\">\r\n <div class=\"ph__l\">\r\n @if (eyebrow || eyebrowKey) {\r\n <div class=\"ph__eyebrow\">\r\n @if (eyebrow) { <span class=\"mono\">{{ eyebrow }}</span> }\r\n @if (eyebrowKey) { <span>{{ eyebrowKey | translate }}</span> }\r\n </div>\r\n }\r\n <h1 class=\"ph__title\" [ngClass]=\"{ 'ph__title--detail': variant === 'detail' }\">\r\n {{ titleKey ? (titleKey | translate) : title }}\r\n </h1>\r\n @if (subtitle || subtitleKey) {\r\n <p class=\"ph__sub\">{{ subtitleKey ? (subtitleKey | translate) : subtitle }}</p>\r\n }\r\n @if (titleAr) {\r\n <p class=\"ph__title-ar\">{{ titleAr }}</p>\r\n }\r\n </div>\r\n\r\n <div class=\"ph__r\">\r\n <!-- Right-side metric (listing) -->\r\n @if (metricValue || metricLabel || metricLabelKey) {\r\n <div class=\"ph__metric\">\r\n @if (metricValue) { <div class=\"ph__metric-v mono\">{{ metricValue }}</div> }\r\n <div class=\"ph__metric-l\">{{ metricLabelKey ? (metricLabelKey | translate) : metricLabel }}</div>\r\n </div>\r\n }\r\n\r\n <!-- Status chip (detail) stacked over the action button row. Listing/circles/module\r\n project no status, so this collapses to just the right-aligned action row.\r\n NOTE: a single [page-header-actions] slot \u2014 duplicating it across @if branches\r\n silently drops projected content in the non-first branch (Angular binds projection\r\n to the first declared matching <ng-content>). -->\r\n <div class=\"ph__hd-actions\">\r\n <ng-content select=\"[page-header-status]\"></ng-content>\r\n <div class=\"ph__hd-btns\">\r\n <ng-content select=\"[page-header-actions]\"></ng-content>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Default slot: anything the consumer wants directly below the title row\r\n (e.g. a detail-page stat bar). -->\r\n <ng-content></ng-content>\r\n</header>\r\n", styles: ["@charset \"UTF-8\";:host{display:block;margin-block-end:var(--sp-6);container-type:inline-size}.ph{display:flex;flex-direction:column;gap:0;color:var(--ink);font-family:var(--font-sans, var(--font-family, system-ui, sans-serif))}.crumbs{display:flex;align-items:center;gap:6px;flex-wrap:wrap;font-size:12px;margin-bottom:14px;color:var(--ink-3)}.crumb{font-size:12px;line-height:1.4;color:var(--ink-3);padding:2px 0;background:none;border:0;font-family:inherit;letter-spacing:-.005em;text-decoration:none}.crumb--link{cursor:pointer;padding-inline:4px;margin-inline:-4px;border-radius:6px;transition:color var(--t-state),background var(--t-state)}.crumb--link:hover{color:var(--ink);background:var(--w08)}.crumb--active{color:var(--ink);font-weight:var(--fw-medium);max-width:480px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.crumb__sep{color:var(--ink-4);font-size:11px;-webkit-user-select:none;user-select:none}.ph__row{display:flex;align-items:flex-end;justify-content:space-between;gap:12px 32px;flex-wrap:wrap}.ph--detail .ph__row{align-items:flex-start}.ph__l{flex:1}.ph__r{display:flex;align-items:flex-end;gap:16px;flex-shrink:0}.ph--detail .ph__r{align-items:flex-end;flex-direction:column}.ph__eyebrow{display:inline-flex;align-items:center;gap:6px;font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-4);font-weight:var(--fw-medium);margin-bottom:4px}.ph__eyebrow .mono{font-size:10.5px;color:var(--ink-3);letter-spacing:.04em;font-family:var(--font-mono, ui-monospace, monospace)}.ph__title{margin:0 0 6px;font-size:32px;font-weight:var(--fw-semibold);letter-spacing:-.02em;line-height:1.1;color:var(--ink)}.ph__title--detail{font-size:28px;letter-spacing:-.02em;line-height:1.2;margin:0}.ph__sub{margin:0;font-size:13.5px;color:var(--ink-3)}.ph__title-ar{margin:6px 0 0;font-size:17px;color:var(--ink-3);font-family:Noto Kufi Arabic,sans-serif;letter-spacing:0;line-height:1.5;font-weight:var(--fw-medium)}.ph__metric{text-align:end}.ph__metric-v{font-family:var(--font-mono, ui-monospace, monospace);font-variant-numeric:tabular-nums;font-size:22px;font-weight:var(--fw-medium);letter-spacing:-.02em;color:var(--ink)}.ph__metric-l{font-size:11px;color:var(--ink-3);text-transform:uppercase;letter-spacing:.06em}.ph__hd-actions{display:flex;flex-direction:column;align-items:flex-end;gap:10px}.ph__hd-btns{display:flex;gap:6px;flex-wrap:wrap;justify-content:flex-end}.ph--listing,.ph--detail{margin-bottom:0}@container (width <= 640px){.ph__row{flex-direction:column;align-items:flex-start;gap:16px}.ph__r{align-items:flex-start;flex-flow:row wrap}.ph--detail .ph__r{flex-direction:row-reverse}.ph__title{font-size:26px}.ph__title--detail{font-size:24px}}@media(width<=640px){.ph__row{flex-direction:column;align-items:flex-start;gap:16px}.ph__r{align-items:flex-start;flex-flow:row wrap}.ph--detail .ph__r{flex-direction:row-reverse}.ph__title{font-size:26px}.ph__title--detail{font-size:24px}}\n"] }]
22178
22319
  }], propDecorators: { variant: [{
22179
22320
  type: Input
22180
22321
  }], title: [{
@@ -22589,6 +22730,38 @@ function nextModuleIndex(modules, from, step) {
22589
22730
  function firstModuleIndex(modules) {
22590
22731
  return modules.findIndex(m => !m.disabled);
22591
22732
  }
22733
+ /**
22734
+ * Attribute a HOST CHROME stamps on an empty element to say "an app's header row
22735
+ * belongs in here". The desktop shell puts one in its window titlebar; nothing
22736
+ * else in the design system knows or cares which chrome that is.
22737
+ */
22738
+ const TITLEBAR_DOCK_ATTR = 'data-fly-titlebar-dock';
22739
+ /**
22740
+ * The dock this topbar should move itself into, or `null` when it is rendering
22741
+ * standalone (its own page, no host chrome around it).
22742
+ *
22743
+ * Walks ANCESTORS rather than searching the document, which is what makes it
22744
+ * safe with several windows open: the first ancestor that contains a dock is
22745
+ * this topbar's own window, because a sibling window's chrome is never an
22746
+ * ancestor of this element.
22747
+ *
22748
+ * `dock.contains(host)` is the re-entry guard. Once docked, the walk would find
22749
+ * the very dock we are already sitting in and re-append us — harmless today
22750
+ * (the caller runs once) but a trap for anyone who later re-runs it on a
22751
+ * re-render.
22752
+ */
22753
+ function findTitlebarDock(host) {
22754
+ const selector = `[${TITLEBAR_DOCK_ATTR}]`;
22755
+ const root = host.ownerDocument.documentElement;
22756
+ for (let el = host.parentElement; el; el = el.parentElement) {
22757
+ const dock = el.querySelector(selector);
22758
+ if (dock)
22759
+ return dock.contains(host) ? null : dock;
22760
+ if (el === root)
22761
+ break;
22762
+ }
22763
+ return null;
22764
+ }
22592
22765
 
22593
22766
  /**
22594
22767
  * Per-module icon template: `<ng-template flyModuleIcon="signals">…</ng-template>`.
@@ -22630,6 +22803,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
22630
22803
  * per module, so adding a module meant editing the component. Here the modules
22631
22804
  * are data ({@link FlyAppModule}) and the icons are projected templates.
22632
22805
  *
22806
+ * ## Docking into a host chrome's titlebar
22807
+ *
22808
+ * The desktop shell draws its own header strip on every window (app icon, title,
22809
+ * window controls). An app rendering this bar underneath it printed the app name
22810
+ * twice, one line apart — and the design draws exactly ONE such row
22811
+ * (`UX/FlyOS Desktop-app/MainContent.dc.html`: app crumb ▸ module crumb ▸ close).
22812
+ *
22813
+ * So when a host chrome offers a dock ({@link findTitlebarDock}), this component
22814
+ * MOVES ITS OWN HOST ELEMENT into it once, after the first render, and flips to a
22815
+ * flat presentation ({@link docked}) that inherits the strip's plate instead of
22816
+ * painting its own. Relocating the element rather than re-implementing the row in
22817
+ * the shell is what keeps the switcher — its popover, roving focus, projected
22818
+ * icon templates and i18n — in ONE place: Angular binds a view to its component,
22819
+ * not to a position in the DOM, so everything keeps working from the new parent.
22820
+ *
22821
+ * Standalone (no dock anywhere above), nothing happens and the bar renders as the
22822
+ * app's own first row, exactly as before.
22823
+ *
22633
22824
  * a11y: the trigger is `aria-haspopup="menu"` + `aria-expanded`; the popover is
22634
22825
  * `role="menu"` with `role="menuitem"` rows carrying `aria-current="page"` on
22635
22826
  * the active one. Arrow keys rove (RTL-aware, wrapping, skipping disabled),
@@ -22651,12 +22842,19 @@ class FlyAppTopbarComponent {
22651
22842
  /** The brand was clicked — conventionally "go to this app's home". */
22652
22843
  brandSelected = output();
22653
22844
  i18n = inject(I18nService);
22845
+ host = inject(ElementRef);
22654
22846
  icons = contentChildren(FlyModuleIconDirective, ...(ngDevMode ? [{ debugName: "icons" }] : /* istanbul ignore next */ []));
22655
22847
  rows = viewChildren('row', ...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
22656
22848
  trigger = viewChildren('trigger', ...(ngDevMode ? [{ debugName: "trigger" }] : /* istanbul ignore next */ []));
22657
22849
  open = signal(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
22658
22850
  focusIndex = signal(0, ...(ngDevMode ? [{ debugName: "focusIndex" }] : /* istanbul ignore next */ []));
22659
22851
  stackHandle = null;
22852
+ /**
22853
+ * True once this bar has moved itself into a host chrome's titlebar dock — see
22854
+ * the class doc. Drives `.fly-topbar--docked`, which drops the bar's own plate
22855
+ * and hairline so it reads as part of the strip rather than a row inside it.
22856
+ */
22857
+ docked = signal(false, ...(ngDevMode ? [{ debugName: "docked" }] : /* istanbul ignore next */ []));
22660
22858
  /**
22661
22859
  * Set when the menu opens, cleared once focus has actually landed on a row.
22662
22860
  *
@@ -22686,6 +22884,12 @@ class FlyAppTopbarComponent {
22686
22884
  }, ...(ngDevMode ? [{ debugName: "triggerAriaLabel" }] : /* istanbul ignore next */ []));
22687
22885
  constructor() {
22688
22886
  inject(DestroyRef).onDestroy(() => overlayStack.remove(this.stackHandle));
22887
+ // After the FIRST render, not on every one: the dock is host chrome, which is
22888
+ // already on screen before a remote's first paint, and re-checking would cost
22889
+ // an ancestor walk per change-detection pass for a decision that cannot
22890
+ // change. No teardown pairs with it — Angular removes a destroyed component's
22891
+ // host element through the node itself, so the move does not strand it.
22892
+ afterNextRender(() => this.dockIntoHostChrome());
22689
22893
  effect(() => {
22690
22894
  const rows = this.rows();
22691
22895
  if (!this.pendingFocus() || rows.length === 0)
@@ -22694,6 +22898,14 @@ class FlyAppTopbarComponent {
22694
22898
  this.pendingFocus.set(false);
22695
22899
  });
22696
22900
  }
22901
+ dockIntoHostChrome() {
22902
+ const el = this.host.nativeElement;
22903
+ const dock = findTitlebarDock(el);
22904
+ if (!dock)
22905
+ return;
22906
+ dock.appendChild(el);
22907
+ this.docked.set(true);
22908
+ }
22697
22909
  iconFor(key) {
22698
22910
  return this.icons().find(d => d.flyModuleIcon() === key)?.template ?? null;
22699
22911
  }
@@ -22789,11 +23001,14 @@ class FlyAppTopbarComponent {
22789
23001
  this.rows()[index]?.nativeElement.focus();
22790
23002
  }
22791
23003
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyAppTopbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
22792
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyAppTopbarComponent, isStandalone: true, selector: "fly-app-topbar", inputs: { brandLabelKey: { classPropertyName: "brandLabelKey", publicName: "brandLabelKey", isSignal: true, isRequired: false, transformFunction: null }, sections: { classPropertyName: "sections", publicName: "sections", isSignal: true, isRequired: false, transformFunction: null }, activeKey: { classPropertyName: "activeKey", publicName: "activeKey", isSignal: true, isRequired: false, transformFunction: null }, footerLabel: { classPropertyName: "footerLabel", publicName: "footerLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { moduleSelected: "moduleSelected", brandSelected: "brandSelected" }, host: { listeners: { "document:keydown.escape": "onEscape()" } }, queries: [{ propertyName: "icons", predicate: FlyModuleIconDirective, isSignal: true }], viewQueries: [{ propertyName: "rows", predicate: ["row"], descendants: true, isSignal: true }, { propertyName: "trigger", predicate: ["trigger"], descendants: true, isSignal: true }], ngImport: i0, template: "<header class=\"fly-topbar\">\r\n <div class=\"fly-topbar__lead\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-topbar__brand\"\r\n (click)=\"brandSelected.emit()\"\r\n [attr.aria-label]=\"brandAriaLabel()\"\r\n >\r\n <span class=\"fly-topbar__brand-mark\"><ng-content select=\"[app-topbar-brand]\" /></span>\r\n @if (brandLabelKey(); as key) {\r\n <span class=\"fly-topbar__brand-name\">{{ key | translate }}</span>\r\n }\r\n </button>\r\n\r\n @if (activeModule()) {\r\n <span class=\"fly-topbar__sep\" aria-hidden=\"true\">/</span>\r\n }\r\n\r\n <div class=\"fly-topbar__anchor\" (flyClickOutside)=\"close()\" [flyClickOutsideEnabled]=\"open()\">\r\n <button\r\n #trigger\r\n type=\"button\"\r\n class=\"fly-topbar__module\"\r\n [class.fly-topbar__module--on]=\"open()\"\r\n (click)=\"toggle()\"\r\n (keydown)=\"onTriggerKeydown($event)\"\r\n aria-haspopup=\"menu\"\r\n [attr.aria-expanded]=\"open()\"\r\n [attr.aria-label]=\"triggerAriaLabel()\"\r\n >\r\n @if (activeModule(); as active) {\r\n <span class=\"fly-topbar__module-icon\">\r\n @if (iconFor(active.key); as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl\" />\r\n } @else if (active.iconClass) {\r\n <i [class]=\"active.iconClass\" aria-hidden=\"true\"></i>\r\n }\r\n </span>\r\n <span class=\"fly-topbar__module-label\">{{ active.labelKey | translate }}</span>\r\n } @else {\r\n <span class=\"fly-topbar__module-label fly-topbar__module-label--empty\">\r\n {{ 'ui.nav.selectModule' | translate }}\r\n </span>\r\n }\r\n <svg class=\"fly-topbar__chevron\" width=\"11\" height=\"11\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"2.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\r\n aria-hidden=\"true\">\r\n <polyline points=\"6 9 12 15 18 9\" />\r\n </svg>\r\n </button>\r\n\r\n @if (open()) {\r\n <div class=\"fly-topbar__pop\" role=\"menu\" [attr.aria-label]=\"switchAriaLabel()\">\r\n <div class=\"fly-topbar__cols\">\r\n @for (section of sections(); track $index) {\r\n <div class=\"fly-topbar__col\">\r\n @if (section.titleKey; as titleKey) {\r\n <div class=\"fly-topbar__col-title\">{{ titleKey | translate }}</div>\r\n }\r\n @for (mod of section.modules; track mod.key) {\r\n <button\r\n #row\r\n type=\"button\"\r\n class=\"fly-topbar__item\"\r\n [class.fly-topbar__item--on]=\"mod.key === activeKey()\"\r\n role=\"menuitem\"\r\n [disabled]=\"mod.disabled ?? false\"\r\n [attr.tabindex]=\"indexOf(mod) === focusIndex() ? 0 : -1\"\r\n [attr.aria-current]=\"mod.key === activeKey() ? 'page' : null\"\r\n (click)=\"select(mod)\"\r\n (keydown)=\"onRowKeydown($event)\"\r\n >\r\n <span class=\"fly-topbar__item-icon\">\r\n @if (iconFor(mod.key); as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl\" />\r\n } @else if (mod.iconClass) {\r\n <i [class]=\"mod.iconClass\" aria-hidden=\"true\"></i>\r\n }\r\n </span>\r\n <span class=\"fly-topbar__item-main\">\r\n <span class=\"fly-topbar__item-label\">{{ mod.labelKey | translate }}</span>\r\n @if (mod.descKey; as descKey) {\r\n <span class=\"fly-topbar__item-desc\">{{ descKey | translate }}</span>\r\n }\r\n </span>\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n @if (footerLabel()) {\r\n <div class=\"fly-topbar__foot\">{{ footerLabel() }}</div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div class=\"fly-topbar__actions\"><ng-content select=\"[app-topbar-actions]\" /></div>\r\n</header>\r\n", styles: [":host{display:block;position:relative;z-index:var(--z-sticky)}.fly-topbar{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);padding:var(--sp-2) var(--sp-3);border-block-end:1px solid var(--line);background:var(--bg-3)}.fly-topbar__lead{display:flex;align-items:center;gap:var(--sp-2);min-inline-size:0}.fly-topbar__brand,.fly-topbar__module{display:inline-flex;align-items:center;gap:var(--sp-2);appearance:none;border:0;background:transparent;cursor:pointer;font:inherit;color:var(--ink);padding:var(--sp-1) var(--sp-2);border-radius:var(--r-md);transition:background var(--t-state)}.fly-topbar__brand:hover,.fly-topbar__module:hover{background:var(--bg-hover)}.fly-topbar__brand:focus-visible,.fly-topbar__module:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.fly-topbar__brand-name{font-weight:var(--fw-semibold);white-space:nowrap}.fly-topbar__brand-mark{display:inline-flex;align-items:center;max-block-size:var(--icon-lg)}.fly-topbar__sep{color:var(--ink-4);-webkit-user-select:none;user-select:none}.fly-topbar__module{min-inline-size:0}.fly-topbar__module--on{background:var(--bg-hover)}.fly-topbar__module-label{font-weight:var(--fw-medium);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-topbar__module-label--empty{color:var(--ink-3)}.fly-topbar__module-icon,.fly-topbar__item-icon{display:inline-flex;align-items:center;justify-content:center;inline-size:var(--icon-md);block-size:var(--icon-md);flex:0 0 auto;color:var(--accent)}.fly-topbar__chevron{flex:0 0 auto;color:var(--ink-3);transition:transform var(--t-state)}.fly-topbar__module--on .fly-topbar__chevron{transform:rotate(180deg)}.fly-topbar__anchor{position:relative}.fly-topbar__pop{position:absolute;inset-block-start:calc(100% + var(--sp-1));inset-inline-start:0;z-index:var(--z-overlay);min-inline-size:260px;max-inline-size:min(680px,92vw);padding:var(--sp-3);border-radius:var(--r-lg);border:1px solid var(--glass2-border);background-image:radial-gradient(70% 60% at 50% 100%,var(--w07),transparent 70%),linear-gradient(180deg,var(--w08),transparent 20%),linear-gradient(180deg,var(--mat-menu-solid-a),var(--mat-menu-solid-b));box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset)}@media(prefers-reduced-transparency:reduce){.fly-topbar__pop{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.fly-topbar__pop:before,.fly-topbar__pop:after{display:none}}@media(prefers-contrast:more){.fly-topbar__pop{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.fly-topbar__pop:after{animation:none}}.fly-topbar__cols{display:flex;gap:var(--sp-4);align-items:flex-start}@media(width<=720px){.fly-topbar__cols{flex-direction:column;gap:var(--sp-3)}}.fly-topbar__col{display:flex;flex-direction:column;gap:2px;min-inline-size:220px;flex:1 1 0}.fly-topbar__col-title{font-size:var(--text-2xs);font-weight:var(--fw-semibold);letter-spacing:var(--tracking-wide);text-transform:uppercase;color:var(--ink-3);padding:var(--sp-2) var(--sp-2) var(--sp-1)}.fly-topbar__item{display:flex;align-items:flex-start;gap:var(--sp-2);inline-size:100%;text-align:start;appearance:none;border:0;background:transparent;cursor:pointer;font:inherit;color:var(--ink);padding:var(--sp-2);border-radius:var(--r-md);transition:background var(--t-state)}.fly-topbar__item:hover:not(:disabled){background:var(--w1)}.fly-topbar__item:focus-visible{outline:2px solid var(--focus-ring);outline-offset:-2px}.fly-topbar__item:disabled{opacity:.5;cursor:default}.fly-topbar__item--on{background:var(--accent-soft);color:var(--on-accent-soft);box-shadow:inset 2px 0 0 0 var(--accent)}.fly-topbar__item-main{display:flex;flex-direction:column;gap:1px;min-inline-size:0}.fly-topbar__item-label{font-weight:var(--fw-medium);line-height:1.3}.fly-topbar__item-desc{font-size:var(--text-xs);color:var(--ink-3);line-height:1.35}.fly-topbar__foot{margin-block-start:var(--sp-3);padding-block-start:var(--sp-2);border-block-start:.5px solid var(--w08);font-size:var(--text-2xs);color:var(--ink-4)}.fly-topbar__actions{display:flex;align-items:center;gap:var(--sp-2);flex:0 0 auto}@media(forced-colors:active){.fly-topbar__item--on{border-inline-start:2px solid CanvasText}}@media(prefers-reduced-motion:reduce){.fly-topbar__brand,.fly-topbar__module,.fly-topbar__item,.fly-topbar__chevron{transition:none}}\n"], dependencies: [{ kind: "directive", type: FlyClickOutsideDirective, selector: "[flyClickOutside]", inputs: ["flyClickOutsideEnabled"], outputs: ["flyClickOutside"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
23004
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyAppTopbarComponent, isStandalone: true, selector: "fly-app-topbar", inputs: { brandLabelKey: { classPropertyName: "brandLabelKey", publicName: "brandLabelKey", isSignal: true, isRequired: false, transformFunction: null }, sections: { classPropertyName: "sections", publicName: "sections", isSignal: true, isRequired: false, transformFunction: null }, activeKey: { classPropertyName: "activeKey", publicName: "activeKey", isSignal: true, isRequired: false, transformFunction: null }, footerLabel: { classPropertyName: "footerLabel", publicName: "footerLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { moduleSelected: "moduleSelected", brandSelected: "brandSelected" }, host: { listeners: { "document:keydown.escape": "onEscape()" }, properties: { "class.fly-topbar--docked": "docked()" } }, queries: [{ propertyName: "icons", predicate: FlyModuleIconDirective, isSignal: true }], viewQueries: [{ propertyName: "rows", predicate: ["row"], descendants: true, isSignal: true }, { propertyName: "trigger", predicate: ["trigger"], descendants: true, isSignal: true }], ngImport: i0, template: "<header class=\"fly-topbar\">\r\n <div class=\"fly-topbar__lead\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-topbar__brand\"\r\n (click)=\"brandSelected.emit()\"\r\n [attr.aria-label]=\"brandAriaLabel()\"\r\n >\r\n <span class=\"fly-topbar__brand-mark\"><ng-content select=\"[app-topbar-brand]\" /></span>\r\n @if (brandLabelKey(); as key) {\r\n <span class=\"fly-topbar__brand-name\">{{ key | translate }}</span>\r\n }\r\n </button>\r\n\r\n @if (activeModule()) {\r\n <span class=\"fly-topbar__sep\" aria-hidden=\"true\">/</span>\r\n }\r\n\r\n <div class=\"fly-topbar__anchor\" (flyClickOutside)=\"close()\" [flyClickOutsideEnabled]=\"open()\">\r\n <button\r\n #trigger\r\n type=\"button\"\r\n class=\"fly-topbar__module\"\r\n [class.fly-topbar__module--on]=\"open()\"\r\n (click)=\"toggle()\"\r\n (keydown)=\"onTriggerKeydown($event)\"\r\n aria-haspopup=\"menu\"\r\n [attr.aria-expanded]=\"open()\"\r\n [attr.aria-label]=\"triggerAriaLabel()\"\r\n >\r\n @if (activeModule(); as active) {\r\n <span class=\"fly-topbar__module-icon\">\r\n @if (iconFor(active.key); as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl\" />\r\n } @else if (active.iconClass) {\r\n <i [class]=\"active.iconClass\" aria-hidden=\"true\"></i>\r\n }\r\n </span>\r\n <span class=\"fly-topbar__module-label\">{{ active.labelKey | translate }}</span>\r\n } @else {\r\n <span class=\"fly-topbar__module-label fly-topbar__module-label--empty\">\r\n {{ 'ui.nav.selectModule' | translate }}\r\n </span>\r\n }\r\n <svg class=\"fly-topbar__chevron\" width=\"11\" height=\"11\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"2.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\r\n aria-hidden=\"true\">\r\n <polyline points=\"6 9 12 15 18 9\" />\r\n </svg>\r\n </button>\r\n\r\n @if (open()) {\r\n <div class=\"fly-topbar__pop\" role=\"menu\" [attr.aria-label]=\"switchAriaLabel()\">\r\n <div class=\"fly-topbar__cols\">\r\n @for (section of sections(); track $index) {\r\n <div class=\"fly-topbar__col\">\r\n @if (section.titleKey; as titleKey) {\r\n <div class=\"fly-topbar__col-title\">{{ titleKey | translate }}</div>\r\n }\r\n @for (mod of section.modules; track mod.key) {\r\n <button\r\n #row\r\n type=\"button\"\r\n class=\"fly-topbar__item\"\r\n [class.fly-topbar__item--on]=\"mod.key === activeKey()\"\r\n role=\"menuitem\"\r\n [disabled]=\"mod.disabled ?? false\"\r\n [attr.tabindex]=\"indexOf(mod) === focusIndex() ? 0 : -1\"\r\n [attr.aria-current]=\"mod.key === activeKey() ? 'page' : null\"\r\n (click)=\"select(mod)\"\r\n (keydown)=\"onRowKeydown($event)\"\r\n >\r\n <span class=\"fly-topbar__item-icon\">\r\n @if (iconFor(mod.key); as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl\" />\r\n } @else if (mod.iconClass) {\r\n <i [class]=\"mod.iconClass\" aria-hidden=\"true\"></i>\r\n }\r\n </span>\r\n <span class=\"fly-topbar__item-main\">\r\n <span class=\"fly-topbar__item-label\">{{ mod.labelKey | translate }}</span>\r\n @if (mod.descKey; as descKey) {\r\n <span class=\"fly-topbar__item-desc\">{{ descKey | translate }}</span>\r\n }\r\n </span>\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n @if (footerLabel()) {\r\n <div class=\"fly-topbar__foot\">{{ footerLabel() }}</div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div class=\"fly-topbar__actions\"><ng-content select=\"[app-topbar-actions]\" /></div>\r\n</header>\r\n", styles: [":host{display:block;position:relative;z-index:var(--z-sticky)}.fly-topbar{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);padding:var(--sp-2) var(--sp-3);border-block-end:1px solid var(--w1);background:var(--bg-3)}.fly-topbar__lead{display:flex;align-items:center;gap:var(--sp-2);min-inline-size:0}.fly-topbar__brand,.fly-topbar__module{display:inline-flex;align-items:center;gap:var(--sp-2);appearance:none;border:0;background:transparent;cursor:pointer;font:inherit;color:var(--ink);padding:var(--sp-1) var(--sp-2);border-radius:var(--r-md);transition:background var(--t-state)}.fly-topbar__brand:hover,.fly-topbar__module:hover{background:var(--bg-hover)}.fly-topbar__brand:focus-visible,.fly-topbar__module:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.fly-topbar__brand-name{font-weight:var(--fw-semibold);white-space:nowrap}.fly-topbar__brand-mark{display:inline-flex;align-items:center;max-block-size:var(--icon-lg)}.fly-topbar__sep{color:var(--ink-4);-webkit-user-select:none;user-select:none}.fly-topbar__module{min-inline-size:0}.fly-topbar__module--on{background:var(--bg-hover)}.fly-topbar__module-label{font-weight:var(--fw-medium);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-topbar__module-label--empty{color:var(--ink-3)}.fly-topbar__module-icon,.fly-topbar__item-icon{display:inline-flex;align-items:center;justify-content:center;inline-size:var(--icon-md);block-size:var(--icon-md);flex:0 0 auto;color:var(--accent)}.fly-topbar__chevron{flex:0 0 auto;color:var(--ink-3);transition:transform var(--t-state)}.fly-topbar__module--on .fly-topbar__chevron{transform:rotate(180deg)}.fly-topbar__anchor{position:relative}:host(.fly-topbar--docked){flex:1 1 auto;min-inline-size:0;z-index:auto}:host(.fly-topbar--docked) .fly-topbar{padding:0;background:transparent;border-block-end:0}:host(.fly-topbar--docked) .fly-topbar__lead{gap:2px}:host(.fly-topbar--docked) .fly-topbar__brand,:host(.fly-topbar--docked) .fly-topbar__module{block-size:26px;padding-block:0;padding-inline:var(--sp-2);border-radius:var(--r-sm);font-size:var(--text-sm);line-height:1;color:var(--label-secondary)}:host(.fly-topbar--docked) .fly-topbar__brand:hover,:host(.fly-topbar--docked) .fly-topbar__module:hover{background:var(--w08);color:var(--label-primary)}:host(.fly-topbar--docked) .fly-topbar__module{color:var(--label-primary)}:host(.fly-topbar--docked) .fly-topbar__module--on{background:var(--w08)}:host(.fly-topbar--docked) .fly-topbar__brand-name{font-weight:var(--fw-medium)}:host(.fly-topbar--docked) .fly-topbar__module-label{font-weight:var(--fw-semibold)}:host(.fly-topbar--docked) .fly-topbar__sep{color:var(--w28)}:host(.fly-topbar--docked) .fly-topbar__module-icon{inline-size:14px;block-size:14px}:host(.fly-topbar--docked) .fly-topbar__brand-mark{max-block-size:22px}:host(.fly-topbar--docked) .fly-topbar__brand-mark ::ng-deep *{max-inline-size:22px;max-block-size:22px}.fly-topbar__pop{position:absolute;inset-block-start:calc(100% + var(--sp-1));inset-inline-start:0;z-index:var(--z-overlay);min-inline-size:260px;max-inline-size:min(680px,92vw);padding:var(--sp-3);border-radius:var(--r-lg);border:1px solid var(--glass2-border);background-image:radial-gradient(70% 60% at 50% 100%,var(--w07),transparent 70%),linear-gradient(180deg,var(--w08),transparent 20%),linear-gradient(180deg,var(--mat-menu-solid-a),var(--mat-menu-solid-b));box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset)}@media(prefers-reduced-transparency:reduce){.fly-topbar__pop{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.fly-topbar__pop:before,.fly-topbar__pop:after{display:none}}@media(prefers-contrast:more){.fly-topbar__pop{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.fly-topbar__pop:after{animation:none}}.fly-topbar__cols{display:flex;gap:var(--sp-4);align-items:flex-start}@media(width<=720px){.fly-topbar__cols{flex-direction:column;gap:var(--sp-3)}}.fly-topbar__col{display:flex;flex-direction:column;gap:2px;min-inline-size:220px;flex:1 1 0}.fly-topbar__col-title{font-size:var(--text-2xs);font-weight:var(--fw-semibold);letter-spacing:var(--tracking-wide);text-transform:uppercase;color:var(--ink-3);padding:var(--sp-2) var(--sp-2) var(--sp-1)}.fly-topbar__item{display:flex;align-items:flex-start;gap:var(--sp-2);inline-size:100%;text-align:start;appearance:none;border:0;background:transparent;cursor:pointer;font:inherit;color:var(--ink);padding:var(--sp-2);border-radius:var(--r-md);transition:background var(--t-state)}.fly-topbar__item:hover:not(:disabled){background:var(--w1)}.fly-topbar__item:focus-visible{outline:2px solid var(--focus-ring);outline-offset:-2px}.fly-topbar__item:disabled{opacity:.5;cursor:default}.fly-topbar__item--on{background:var(--accent-soft);color:var(--on-accent-soft);box-shadow:inset 2px 0 0 0 var(--accent)}.fly-topbar__item-main{display:flex;flex-direction:column;gap:1px;min-inline-size:0}.fly-topbar__item-label{font-weight:var(--fw-medium);line-height:1.3}.fly-topbar__item-desc{font-size:var(--text-xs);color:var(--ink-3);line-height:1.35}.fly-topbar__foot{margin-block-start:var(--sp-3);padding-block-start:var(--sp-2);border-block-start:.5px solid var(--w08);font-size:var(--text-2xs);color:var(--ink-4)}.fly-topbar__actions{display:flex;align-items:center;gap:var(--sp-2);flex:0 0 auto}@media(forced-colors:active){.fly-topbar__item--on{border-inline-start:2px solid CanvasText}}@media(prefers-reduced-motion:reduce){.fly-topbar__brand,.fly-topbar__module,.fly-topbar__item,.fly-topbar__chevron{transition:none}}\n"], dependencies: [{ kind: "directive", type: FlyClickOutsideDirective, selector: "[flyClickOutside]", inputs: ["flyClickOutsideEnabled"], outputs: ["flyClickOutside"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
22793
23005
  }
22794
23006
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyAppTopbarComponent, decorators: [{
22795
23007
  type: Component,
22796
- args: [{ selector: 'fly-app-topbar', standalone: true, imports: [TranslatePipe, FlyClickOutsideDirective, NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, host: { '(document:keydown.escape)': 'onEscape()' }, template: "<header class=\"fly-topbar\">\r\n <div class=\"fly-topbar__lead\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-topbar__brand\"\r\n (click)=\"brandSelected.emit()\"\r\n [attr.aria-label]=\"brandAriaLabel()\"\r\n >\r\n <span class=\"fly-topbar__brand-mark\"><ng-content select=\"[app-topbar-brand]\" /></span>\r\n @if (brandLabelKey(); as key) {\r\n <span class=\"fly-topbar__brand-name\">{{ key | translate }}</span>\r\n }\r\n </button>\r\n\r\n @if (activeModule()) {\r\n <span class=\"fly-topbar__sep\" aria-hidden=\"true\">/</span>\r\n }\r\n\r\n <div class=\"fly-topbar__anchor\" (flyClickOutside)=\"close()\" [flyClickOutsideEnabled]=\"open()\">\r\n <button\r\n #trigger\r\n type=\"button\"\r\n class=\"fly-topbar__module\"\r\n [class.fly-topbar__module--on]=\"open()\"\r\n (click)=\"toggle()\"\r\n (keydown)=\"onTriggerKeydown($event)\"\r\n aria-haspopup=\"menu\"\r\n [attr.aria-expanded]=\"open()\"\r\n [attr.aria-label]=\"triggerAriaLabel()\"\r\n >\r\n @if (activeModule(); as active) {\r\n <span class=\"fly-topbar__module-icon\">\r\n @if (iconFor(active.key); as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl\" />\r\n } @else if (active.iconClass) {\r\n <i [class]=\"active.iconClass\" aria-hidden=\"true\"></i>\r\n }\r\n </span>\r\n <span class=\"fly-topbar__module-label\">{{ active.labelKey | translate }}</span>\r\n } @else {\r\n <span class=\"fly-topbar__module-label fly-topbar__module-label--empty\">\r\n {{ 'ui.nav.selectModule' | translate }}\r\n </span>\r\n }\r\n <svg class=\"fly-topbar__chevron\" width=\"11\" height=\"11\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"2.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\r\n aria-hidden=\"true\">\r\n <polyline points=\"6 9 12 15 18 9\" />\r\n </svg>\r\n </button>\r\n\r\n @if (open()) {\r\n <div class=\"fly-topbar__pop\" role=\"menu\" [attr.aria-label]=\"switchAriaLabel()\">\r\n <div class=\"fly-topbar__cols\">\r\n @for (section of sections(); track $index) {\r\n <div class=\"fly-topbar__col\">\r\n @if (section.titleKey; as titleKey) {\r\n <div class=\"fly-topbar__col-title\">{{ titleKey | translate }}</div>\r\n }\r\n @for (mod of section.modules; track mod.key) {\r\n <button\r\n #row\r\n type=\"button\"\r\n class=\"fly-topbar__item\"\r\n [class.fly-topbar__item--on]=\"mod.key === activeKey()\"\r\n role=\"menuitem\"\r\n [disabled]=\"mod.disabled ?? false\"\r\n [attr.tabindex]=\"indexOf(mod) === focusIndex() ? 0 : -1\"\r\n [attr.aria-current]=\"mod.key === activeKey() ? 'page' : null\"\r\n (click)=\"select(mod)\"\r\n (keydown)=\"onRowKeydown($event)\"\r\n >\r\n <span class=\"fly-topbar__item-icon\">\r\n @if (iconFor(mod.key); as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl\" />\r\n } @else if (mod.iconClass) {\r\n <i [class]=\"mod.iconClass\" aria-hidden=\"true\"></i>\r\n }\r\n </span>\r\n <span class=\"fly-topbar__item-main\">\r\n <span class=\"fly-topbar__item-label\">{{ mod.labelKey | translate }}</span>\r\n @if (mod.descKey; as descKey) {\r\n <span class=\"fly-topbar__item-desc\">{{ descKey | translate }}</span>\r\n }\r\n </span>\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n @if (footerLabel()) {\r\n <div class=\"fly-topbar__foot\">{{ footerLabel() }}</div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div class=\"fly-topbar__actions\"><ng-content select=\"[app-topbar-actions]\" /></div>\r\n</header>\r\n", styles: [":host{display:block;position:relative;z-index:var(--z-sticky)}.fly-topbar{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);padding:var(--sp-2) var(--sp-3);border-block-end:1px solid var(--line);background:var(--bg-3)}.fly-topbar__lead{display:flex;align-items:center;gap:var(--sp-2);min-inline-size:0}.fly-topbar__brand,.fly-topbar__module{display:inline-flex;align-items:center;gap:var(--sp-2);appearance:none;border:0;background:transparent;cursor:pointer;font:inherit;color:var(--ink);padding:var(--sp-1) var(--sp-2);border-radius:var(--r-md);transition:background var(--t-state)}.fly-topbar__brand:hover,.fly-topbar__module:hover{background:var(--bg-hover)}.fly-topbar__brand:focus-visible,.fly-topbar__module:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.fly-topbar__brand-name{font-weight:var(--fw-semibold);white-space:nowrap}.fly-topbar__brand-mark{display:inline-flex;align-items:center;max-block-size:var(--icon-lg)}.fly-topbar__sep{color:var(--ink-4);-webkit-user-select:none;user-select:none}.fly-topbar__module{min-inline-size:0}.fly-topbar__module--on{background:var(--bg-hover)}.fly-topbar__module-label{font-weight:var(--fw-medium);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-topbar__module-label--empty{color:var(--ink-3)}.fly-topbar__module-icon,.fly-topbar__item-icon{display:inline-flex;align-items:center;justify-content:center;inline-size:var(--icon-md);block-size:var(--icon-md);flex:0 0 auto;color:var(--accent)}.fly-topbar__chevron{flex:0 0 auto;color:var(--ink-3);transition:transform var(--t-state)}.fly-topbar__module--on .fly-topbar__chevron{transform:rotate(180deg)}.fly-topbar__anchor{position:relative}.fly-topbar__pop{position:absolute;inset-block-start:calc(100% + var(--sp-1));inset-inline-start:0;z-index:var(--z-overlay);min-inline-size:260px;max-inline-size:min(680px,92vw);padding:var(--sp-3);border-radius:var(--r-lg);border:1px solid var(--glass2-border);background-image:radial-gradient(70% 60% at 50% 100%,var(--w07),transparent 70%),linear-gradient(180deg,var(--w08),transparent 20%),linear-gradient(180deg,var(--mat-menu-solid-a),var(--mat-menu-solid-b));box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset)}@media(prefers-reduced-transparency:reduce){.fly-topbar__pop{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.fly-topbar__pop:before,.fly-topbar__pop:after{display:none}}@media(prefers-contrast:more){.fly-topbar__pop{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.fly-topbar__pop:after{animation:none}}.fly-topbar__cols{display:flex;gap:var(--sp-4);align-items:flex-start}@media(width<=720px){.fly-topbar__cols{flex-direction:column;gap:var(--sp-3)}}.fly-topbar__col{display:flex;flex-direction:column;gap:2px;min-inline-size:220px;flex:1 1 0}.fly-topbar__col-title{font-size:var(--text-2xs);font-weight:var(--fw-semibold);letter-spacing:var(--tracking-wide);text-transform:uppercase;color:var(--ink-3);padding:var(--sp-2) var(--sp-2) var(--sp-1)}.fly-topbar__item{display:flex;align-items:flex-start;gap:var(--sp-2);inline-size:100%;text-align:start;appearance:none;border:0;background:transparent;cursor:pointer;font:inherit;color:var(--ink);padding:var(--sp-2);border-radius:var(--r-md);transition:background var(--t-state)}.fly-topbar__item:hover:not(:disabled){background:var(--w1)}.fly-topbar__item:focus-visible{outline:2px solid var(--focus-ring);outline-offset:-2px}.fly-topbar__item:disabled{opacity:.5;cursor:default}.fly-topbar__item--on{background:var(--accent-soft);color:var(--on-accent-soft);box-shadow:inset 2px 0 0 0 var(--accent)}.fly-topbar__item-main{display:flex;flex-direction:column;gap:1px;min-inline-size:0}.fly-topbar__item-label{font-weight:var(--fw-medium);line-height:1.3}.fly-topbar__item-desc{font-size:var(--text-xs);color:var(--ink-3);line-height:1.35}.fly-topbar__foot{margin-block-start:var(--sp-3);padding-block-start:var(--sp-2);border-block-start:.5px solid var(--w08);font-size:var(--text-2xs);color:var(--ink-4)}.fly-topbar__actions{display:flex;align-items:center;gap:var(--sp-2);flex:0 0 auto}@media(forced-colors:active){.fly-topbar__item--on{border-inline-start:2px solid CanvasText}}@media(prefers-reduced-motion:reduce){.fly-topbar__brand,.fly-topbar__module,.fly-topbar__item,.fly-topbar__chevron{transition:none}}\n"] }]
23008
+ args: [{ selector: 'fly-app-topbar', standalone: true, imports: [TranslatePipe, FlyClickOutsideDirective, NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, host: {
23009
+ '(document:keydown.escape)': 'onEscape()',
23010
+ '[class.fly-topbar--docked]': 'docked()',
23011
+ }, template: "<header class=\"fly-topbar\">\r\n <div class=\"fly-topbar__lead\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-topbar__brand\"\r\n (click)=\"brandSelected.emit()\"\r\n [attr.aria-label]=\"brandAriaLabel()\"\r\n >\r\n <span class=\"fly-topbar__brand-mark\"><ng-content select=\"[app-topbar-brand]\" /></span>\r\n @if (brandLabelKey(); as key) {\r\n <span class=\"fly-topbar__brand-name\">{{ key | translate }}</span>\r\n }\r\n </button>\r\n\r\n @if (activeModule()) {\r\n <span class=\"fly-topbar__sep\" aria-hidden=\"true\">/</span>\r\n }\r\n\r\n <div class=\"fly-topbar__anchor\" (flyClickOutside)=\"close()\" [flyClickOutsideEnabled]=\"open()\">\r\n <button\r\n #trigger\r\n type=\"button\"\r\n class=\"fly-topbar__module\"\r\n [class.fly-topbar__module--on]=\"open()\"\r\n (click)=\"toggle()\"\r\n (keydown)=\"onTriggerKeydown($event)\"\r\n aria-haspopup=\"menu\"\r\n [attr.aria-expanded]=\"open()\"\r\n [attr.aria-label]=\"triggerAriaLabel()\"\r\n >\r\n @if (activeModule(); as active) {\r\n <span class=\"fly-topbar__module-icon\">\r\n @if (iconFor(active.key); as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl\" />\r\n } @else if (active.iconClass) {\r\n <i [class]=\"active.iconClass\" aria-hidden=\"true\"></i>\r\n }\r\n </span>\r\n <span class=\"fly-topbar__module-label\">{{ active.labelKey | translate }}</span>\r\n } @else {\r\n <span class=\"fly-topbar__module-label fly-topbar__module-label--empty\">\r\n {{ 'ui.nav.selectModule' | translate }}\r\n </span>\r\n }\r\n <svg class=\"fly-topbar__chevron\" width=\"11\" height=\"11\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"2.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\r\n aria-hidden=\"true\">\r\n <polyline points=\"6 9 12 15 18 9\" />\r\n </svg>\r\n </button>\r\n\r\n @if (open()) {\r\n <div class=\"fly-topbar__pop\" role=\"menu\" [attr.aria-label]=\"switchAriaLabel()\">\r\n <div class=\"fly-topbar__cols\">\r\n @for (section of sections(); track $index) {\r\n <div class=\"fly-topbar__col\">\r\n @if (section.titleKey; as titleKey) {\r\n <div class=\"fly-topbar__col-title\">{{ titleKey | translate }}</div>\r\n }\r\n @for (mod of section.modules; track mod.key) {\r\n <button\r\n #row\r\n type=\"button\"\r\n class=\"fly-topbar__item\"\r\n [class.fly-topbar__item--on]=\"mod.key === activeKey()\"\r\n role=\"menuitem\"\r\n [disabled]=\"mod.disabled ?? false\"\r\n [attr.tabindex]=\"indexOf(mod) === focusIndex() ? 0 : -1\"\r\n [attr.aria-current]=\"mod.key === activeKey() ? 'page' : null\"\r\n (click)=\"select(mod)\"\r\n (keydown)=\"onRowKeydown($event)\"\r\n >\r\n <span class=\"fly-topbar__item-icon\">\r\n @if (iconFor(mod.key); as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl\" />\r\n } @else if (mod.iconClass) {\r\n <i [class]=\"mod.iconClass\" aria-hidden=\"true\"></i>\r\n }\r\n </span>\r\n <span class=\"fly-topbar__item-main\">\r\n <span class=\"fly-topbar__item-label\">{{ mod.labelKey | translate }}</span>\r\n @if (mod.descKey; as descKey) {\r\n <span class=\"fly-topbar__item-desc\">{{ descKey | translate }}</span>\r\n }\r\n </span>\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n @if (footerLabel()) {\r\n <div class=\"fly-topbar__foot\">{{ footerLabel() }}</div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div class=\"fly-topbar__actions\"><ng-content select=\"[app-topbar-actions]\" /></div>\r\n</header>\r\n", styles: [":host{display:block;position:relative;z-index:var(--z-sticky)}.fly-topbar{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);padding:var(--sp-2) var(--sp-3);border-block-end:1px solid var(--w1);background:var(--bg-3)}.fly-topbar__lead{display:flex;align-items:center;gap:var(--sp-2);min-inline-size:0}.fly-topbar__brand,.fly-topbar__module{display:inline-flex;align-items:center;gap:var(--sp-2);appearance:none;border:0;background:transparent;cursor:pointer;font:inherit;color:var(--ink);padding:var(--sp-1) var(--sp-2);border-radius:var(--r-md);transition:background var(--t-state)}.fly-topbar__brand:hover,.fly-topbar__module:hover{background:var(--bg-hover)}.fly-topbar__brand:focus-visible,.fly-topbar__module:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.fly-topbar__brand-name{font-weight:var(--fw-semibold);white-space:nowrap}.fly-topbar__brand-mark{display:inline-flex;align-items:center;max-block-size:var(--icon-lg)}.fly-topbar__sep{color:var(--ink-4);-webkit-user-select:none;user-select:none}.fly-topbar__module{min-inline-size:0}.fly-topbar__module--on{background:var(--bg-hover)}.fly-topbar__module-label{font-weight:var(--fw-medium);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-topbar__module-label--empty{color:var(--ink-3)}.fly-topbar__module-icon,.fly-topbar__item-icon{display:inline-flex;align-items:center;justify-content:center;inline-size:var(--icon-md);block-size:var(--icon-md);flex:0 0 auto;color:var(--accent)}.fly-topbar__chevron{flex:0 0 auto;color:var(--ink-3);transition:transform var(--t-state)}.fly-topbar__module--on .fly-topbar__chevron{transform:rotate(180deg)}.fly-topbar__anchor{position:relative}:host(.fly-topbar--docked){flex:1 1 auto;min-inline-size:0;z-index:auto}:host(.fly-topbar--docked) .fly-topbar{padding:0;background:transparent;border-block-end:0}:host(.fly-topbar--docked) .fly-topbar__lead{gap:2px}:host(.fly-topbar--docked) .fly-topbar__brand,:host(.fly-topbar--docked) .fly-topbar__module{block-size:26px;padding-block:0;padding-inline:var(--sp-2);border-radius:var(--r-sm);font-size:var(--text-sm);line-height:1;color:var(--label-secondary)}:host(.fly-topbar--docked) .fly-topbar__brand:hover,:host(.fly-topbar--docked) .fly-topbar__module:hover{background:var(--w08);color:var(--label-primary)}:host(.fly-topbar--docked) .fly-topbar__module{color:var(--label-primary)}:host(.fly-topbar--docked) .fly-topbar__module--on{background:var(--w08)}:host(.fly-topbar--docked) .fly-topbar__brand-name{font-weight:var(--fw-medium)}:host(.fly-topbar--docked) .fly-topbar__module-label{font-weight:var(--fw-semibold)}:host(.fly-topbar--docked) .fly-topbar__sep{color:var(--w28)}:host(.fly-topbar--docked) .fly-topbar__module-icon{inline-size:14px;block-size:14px}:host(.fly-topbar--docked) .fly-topbar__brand-mark{max-block-size:22px}:host(.fly-topbar--docked) .fly-topbar__brand-mark ::ng-deep *{max-inline-size:22px;max-block-size:22px}.fly-topbar__pop{position:absolute;inset-block-start:calc(100% + var(--sp-1));inset-inline-start:0;z-index:var(--z-overlay);min-inline-size:260px;max-inline-size:min(680px,92vw);padding:var(--sp-3);border-radius:var(--r-lg);border:1px solid var(--glass2-border);background-image:radial-gradient(70% 60% at 50% 100%,var(--w07),transparent 70%),linear-gradient(180deg,var(--w08),transparent 20%),linear-gradient(180deg,var(--mat-menu-solid-a),var(--mat-menu-solid-b));box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset)}@media(prefers-reduced-transparency:reduce){.fly-topbar__pop{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.fly-topbar__pop:before,.fly-topbar__pop:after{display:none}}@media(prefers-contrast:more){.fly-topbar__pop{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.fly-topbar__pop:after{animation:none}}.fly-topbar__cols{display:flex;gap:var(--sp-4);align-items:flex-start}@media(width<=720px){.fly-topbar__cols{flex-direction:column;gap:var(--sp-3)}}.fly-topbar__col{display:flex;flex-direction:column;gap:2px;min-inline-size:220px;flex:1 1 0}.fly-topbar__col-title{font-size:var(--text-2xs);font-weight:var(--fw-semibold);letter-spacing:var(--tracking-wide);text-transform:uppercase;color:var(--ink-3);padding:var(--sp-2) var(--sp-2) var(--sp-1)}.fly-topbar__item{display:flex;align-items:flex-start;gap:var(--sp-2);inline-size:100%;text-align:start;appearance:none;border:0;background:transparent;cursor:pointer;font:inherit;color:var(--ink);padding:var(--sp-2);border-radius:var(--r-md);transition:background var(--t-state)}.fly-topbar__item:hover:not(:disabled){background:var(--w1)}.fly-topbar__item:focus-visible{outline:2px solid var(--focus-ring);outline-offset:-2px}.fly-topbar__item:disabled{opacity:.5;cursor:default}.fly-topbar__item--on{background:var(--accent-soft);color:var(--on-accent-soft);box-shadow:inset 2px 0 0 0 var(--accent)}.fly-topbar__item-main{display:flex;flex-direction:column;gap:1px;min-inline-size:0}.fly-topbar__item-label{font-weight:var(--fw-medium);line-height:1.3}.fly-topbar__item-desc{font-size:var(--text-xs);color:var(--ink-3);line-height:1.35}.fly-topbar__foot{margin-block-start:var(--sp-3);padding-block-start:var(--sp-2);border-block-start:.5px solid var(--w08);font-size:var(--text-2xs);color:var(--ink-4)}.fly-topbar__actions{display:flex;align-items:center;gap:var(--sp-2);flex:0 0 auto}@media(forced-colors:active){.fly-topbar__item--on{border-inline-start:2px solid CanvasText}}@media(prefers-reduced-motion:reduce){.fly-topbar__brand,.fly-topbar__module,.fly-topbar__item,.fly-topbar__chevron{transition:none}}\n"] }]
22797
23012
  }], ctorParameters: () => [], propDecorators: { brandLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "brandLabelKey", required: false }] }], sections: [{ type: i0.Input, args: [{ isSignal: true, alias: "sections", required: false }] }], activeKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeKey", required: false }] }], footerLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "footerLabel", required: false }] }], moduleSelected: [{ type: i0.Output, args: ["moduleSelected"] }], brandSelected: [{ type: i0.Output, args: ["brandSelected"] }], icons: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => FlyModuleIconDirective), { isSignal: true }] }], rows: [{ type: i0.ViewChildren, args: ['row', { isSignal: true }] }], trigger: [{ type: i0.ViewChildren, args: ['trigger', { isSignal: true }] }] } });
22798
23013
 
22799
23014
  /**
@@ -22924,11 +23139,11 @@ class FlyAppHomeComponent {
22924
23139
  return `fly-app-home-sec-${index}`;
22925
23140
  }
22926
23141
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyAppHomeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
22927
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyAppHomeComponent, isStandalone: true, selector: "fly-app-home", inputs: { brandLabelKey: { classPropertyName: "brandLabelKey", publicName: "brandLabelKey", isSignal: true, isRequired: false, transformFunction: null }, titleKey: { classPropertyName: "titleKey", publicName: "titleKey", isSignal: true, isRequired: false, transformFunction: null }, subtitleKey: { classPropertyName: "subtitleKey", publicName: "subtitleKey", isSignal: true, isRequired: false, transformFunction: null }, sections: { classPropertyName: "sections", publicName: "sections", isSignal: true, isRequired: false, transformFunction: null }, modulesLabelKey: { classPropertyName: "modulesLabelKey", publicName: "modulesLabelKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { moduleSelected: "moduleSelected", brandSelected: "brandSelected" }, queries: [{ propertyName: "icons", predicate: FlyModuleIconDirective, isSignal: true }], ngImport: i0, template: "<div class=\"ah\">\r\n <header class=\"ah__util\">\r\n <button type=\"button\" class=\"ah__brand\" (click)=\"brandSelected.emit()\">\r\n <span class=\"ah__brand-mark\"><ng-content select=\"[app-home-brand]\" /></span>\r\n @if (brandLabelKey(); as key) {\r\n <span class=\"ah__brand-name\">{{ key | translate }}</span>\r\n }\r\n </button>\r\n <ng-content select=\"[app-home-actions]\" />\r\n </header>\r\n\r\n <main class=\"ah__main\">\r\n @if (titleKey() || subtitleKey()) {\r\n <section class=\"ah__hero\">\r\n @if (titleKey(); as key) {\r\n <h1 class=\"ah__title\">{{ key | translate }}</h1>\r\n }\r\n @if (subtitleKey(); as key) {\r\n <p class=\"ah__sub\">{{ key | translate }}</p>\r\n }\r\n </section>\r\n }\r\n\r\n @for (row of rows(); track row.index) {\r\n <section\r\n class=\"ah__sec\"\r\n [class.ah__sec--secondary]=\"row.index > 0\"\r\n [attr.aria-label]=\"row.section.titleKey ? null : (modulesLabelKey() | translate)\"\r\n >\r\n @if (row.section.titleKey; as titleKey) {\r\n @if (row.section.collapsible) {\r\n <button\r\n type=\"button\"\r\n class=\"ah__sec-hd\"\r\n (click)=\"toggle(row.index)\"\r\n [attr.aria-expanded]=\"row.expanded\"\r\n [attr.aria-controls]=\"sectionId(row.index)\"\r\n >\r\n <!-- Points end-ward when shut, down when open. `--open` wins over the RTL\r\n flip below because a downward chevron has no direction to mirror. -->\r\n <svg\r\n class=\"ah__sec-chev\"\r\n [class.ah__sec-chev--open]=\"row.expanded\"\r\n width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"9 6 15 12 9 18\" />\r\n </svg>\r\n <span class=\"ah__sec-title\">{{ titleKey | translate }}</span>\r\n <span class=\"ah__sec-count\">{{ row.section.modules.length }}</span>\r\n @if (row.hintKey; as hint) {\r\n <span class=\"ah__sec-hint\">{{ hint | translate }}</span>\r\n }\r\n </button>\r\n } @else {\r\n <h2 class=\"ah__sec-title ah__sec-title--static\">{{ titleKey | translate }}</h2>\r\n }\r\n }\r\n\r\n @if (row.expanded) {\r\n <div class=\"ah__grid\" [class.ah__grid--compact]=\"row.layout === 'compact'\" [id]=\"sectionId(row.index)\">\r\n @for (mod of row.section.modules; track mod.key) {\r\n <button\r\n type=\"button\"\r\n class=\"ah__card\"\r\n [class.ah__card--compact]=\"row.layout === 'compact'\"\r\n [disabled]=\"mod.disabled\"\r\n (click)=\"select(mod)\"\r\n >\r\n <span class=\"ah__card-ico\">\r\n @if (iconFor(mod.key); as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl\" />\r\n } @else if (mod.iconClass) {\r\n <i [class]=\"mod.iconClass\" aria-hidden=\"true\"></i>\r\n }\r\n </span>\r\n\r\n @if (row.layout === 'compact') {\r\n <span class=\"ah__card-main\">\r\n <span class=\"ah__card-title\">{{ mod.labelKey | translate }}</span>\r\n @if (mod.descKey; as descKey) {\r\n <span class=\"ah__card-desc\">{{ descKey | translate }}</span>\r\n }\r\n </span>\r\n <svg\r\n class=\"ah__card-arrow\" width=\"11\" height=\"11\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"2.6\" stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"9 6 15 12 9 18\" />\r\n </svg>\r\n } @else {\r\n <span class=\"ah__card-title ah__card-title--feature\">{{ mod.labelKey | translate }}</span>\r\n @if (mod.descKey; as descKey) {\r\n <span class=\"ah__card-desc ah__card-desc--feature\">{{ descKey | translate }}</span>\r\n }\r\n <span class=\"ah__card-open\">\r\n {{ 'ui.action.open' | translate }}\r\n <svg\r\n class=\"ah__card-arrow\" width=\"11\" height=\"11\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"2.6\" stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"9 6 15 12 9 18\" />\r\n </svg>\r\n </span>\r\n }\r\n </button>\r\n }\r\n </div>\r\n }\r\n </section>\r\n }\r\n </main>\r\n</div>\r\n", styles: [":host{display:flex;flex-direction:column;min-height:100%;container-type:inline-size}.ah{display:flex;flex-direction:column;flex:1;min-height:100%}.ah__util{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-4);padding:var(--sp-4) var(--sp-6)}.ah__brand{display:inline-flex;align-items:center;gap:var(--sp-2);padding:0;border:0;background:none;color:var(--ink);font-family:inherit;cursor:pointer}.ah__brand:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.ah__brand-name{font-size:var(--text-md);font-weight:var(--fw-semibold);letter-spacing:-.01em}.ah__main{flex:1;inline-size:100%;max-inline-size:1120px;margin-inline:auto;padding:56px 40px;display:flex;flex-direction:column;justify-content:center;gap:44px}.ah__hero{max-inline-size:640px}.ah__title{margin:0 0 var(--sp-3);font-size:44px;font-weight:var(--fw-semibold);letter-spacing:-.03em;text-wrap:balance;background:linear-gradient(180deg,var(--ink),var(--ink-2));-webkit-background-clip:text;background-clip:text;color:transparent}.ah__sub{margin:0;max-inline-size:560px;font-size:var(--text-lg);line-height:1.55;color:var(--ink-3);text-wrap:pretty}.ah__sec{display:flex;flex-direction:column;gap:var(--sp-4)}.ah__sec--secondary{padding-block-start:28px;border-block-start:1px solid var(--line)}.ah__sec-hd{display:flex;align-items:center;gap:var(--sp-3);inline-size:100%;padding:0;background:none;border:0;cursor:pointer;font-family:inherit;color:var(--ink);text-align:start}.ah__sec-hd:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.ah__sec-chev{flex-shrink:0;color:var(--ink-3);transition:transform var(--t-overlay)}.ah__sec-title{font-size:var(--text-md);font-weight:var(--fw-semibold);letter-spacing:-.01em}.ah__sec-title--static{margin:0;color:var(--ink-3);font-size:var(--text-xs);letter-spacing:var(--tracking-wide);text-transform:uppercase}.ah__sec-count{display:inline-grid;place-items:center;min-inline-size:22px;block-size:20px;padding-inline:6px;border-radius:999px;background:var(--bg-3);border:1px solid var(--line);font-size:var(--text-2xs);font-weight:var(--fw-medium);font-variant-numeric:tabular-nums;color:var(--ink-3)}.ah__sec-hint{margin-inline-start:auto;font-size:var(--text-xs);color:var(--ink-3)}.ah__grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--sp-3)}.ah__card{display:flex;flex-direction:column;align-items:stretch;position:relative;overflow:hidden;text-align:start;padding:20px 20px 18px;background-color:var(--bg);background-image:linear-gradient(160deg,var(--w055),var(--w02));border:1px solid var(--w09);border-radius:20px;color:inherit;font-family:inherit;cursor:pointer;animation:appTileIn .3s var(--nova-ease-micro) both}.ah__card:nth-child(1){animation-delay:0ms}.ah__card:nth-child(2){animation-delay:20ms}.ah__card:nth-child(3){animation-delay:40ms}.ah__card:nth-child(4){animation-delay:60ms}.ah__card:nth-child(5){animation-delay:80ms}.ah__card:nth-child(6){animation-delay:.1s}.ah__card:nth-child(7){animation-delay:.12s}.ah__card:nth-child(8){animation-delay:.14s}.ah__card:nth-child(9){animation-delay:.16s}.ah__card:nth-child(10){animation-delay:.18s}.ah__card:nth-child(11){animation-delay:.2s}.ah__card:nth-child(12){animation-delay:.22s}.ah__card:nth-child(n+13){animation-delay:.22s}.ah__card{transition:transform var(--t-overlay),box-shadow var(--t-overlay),border-color var(--t-state),background-image var(--t-state)}.ah__card:hover:not(:disabled){transform:translateY(-3px);border-color:color-mix(in oklab,var(--accent) 50%,transparent);background-image:linear-gradient(160deg,var(--tint-hover),transparent);box-shadow:0 20px 46px color-mix(in oklab,var(--accent) 16%,transparent),var(--shadow-filter)}.ah__card:focus-visible{outline:0;border-color:color-mix(in oklab,var(--accent) 50%,transparent);background-image:linear-gradient(160deg,var(--tint-hover),transparent);box-shadow:0 0 0 3px var(--accent-soft),0 20px 46px color-mix(in oklab,var(--accent) 16%,transparent),var(--shadow-filter)}.ah__card:disabled{cursor:default;opacity:.5}.ah__card-ico{display:grid;place-items:center;inline-size:42px;block-size:42px;margin-block-end:18px;border-radius:13px;background:linear-gradient(135deg,var(--accent),var(--sys-teal));box-shadow:inset 0 1px 0 var(--edge-highlight);border:0;color:var(--on-accent);font-size:var(--icon-lg)}.ah__card--compact:hover:not(:disabled) .ah__card-ico,.ah__card--compact:focus-visible .ah__card-ico{background:linear-gradient(135deg,var(--accent),var(--sys-teal));box-shadow:inset 0 1px 0 var(--edge-highlight);color:var(--on-accent)}.ah__card-title{font-size:var(--text-sm);font-weight:var(--fw-semibold);letter-spacing:-.01em;color:var(--ink)}.ah__card-title--feature{margin-block-end:4px;font-size:18px;letter-spacing:-.015em}.ah__card-desc{font-size:var(--text-xs);line-height:1.45;color:var(--ink-3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ah__card-desc--feature{margin-block-end:18px;font-size:var(--text-sm);line-height:1.5;text-wrap:pretty;overflow:visible;white-space:normal}.ah__card-open{display:inline-flex;align-items:center;gap:4px;margin-block-start:auto;font-size:var(--text-2xs);color:var(--ink-3);transition:color var(--t-overlay),gap var(--t-overlay)}.ah__card:hover:not(:disabled) .ah__card-open,.ah__card:focus-visible .ah__card-open{color:var(--accent);gap:8px}.ah__card-arrow{flex-shrink:0;transition:color var(--t-overlay),transform var(--t-overlay)}.ah__card--compact{flex-direction:row;align-items:center;gap:var(--sp-3);padding:14px 16px;background-color:var(--bg);background-image:linear-gradient(160deg,var(--w035),var(--w035));border-radius:16px;border-color:var(--w08)}.ah__card--compact:hover:not(:disabled),.ah__card--compact:focus-visible{border-color:color-mix(in oklab,var(--accent) 40%,transparent);background-image:linear-gradient(160deg,var(--tint-hover),transparent)}.ah__card--compact .ah__card-ico{inline-size:32px;block-size:32px;margin-block-end:0;flex-shrink:0;border-radius:10px;font-size:var(--icon-md);background:var(--bg-3);box-shadow:none;color:var(--ink)}.ah__card-main{display:flex;flex-direction:column;gap:2px;flex:1;min-inline-size:0}.ah__card--compact .ah__card-arrow{color:var(--ink-4)}.ah__card--compact:hover:not(:disabled) .ah__card-arrow{color:var(--accent);transform:translate(2px)}:host-context([dir=rtl]) .ah__card-arrow{transform:scaleX(-1)}:host-context([dir=rtl]) .ah__sec-chev:not(.ah__sec-chev--open){transform:scaleX(-1)}:host-context([dir=rtl]) .ah__card--compact:hover:not(:disabled) .ah__card-arrow{transform:scaleX(-1) translate(2px)}.ah__sec-chev--open{transform:rotate(90deg)}@container (width <= 900px){.ah__grid{grid-template-columns:repeat(2,minmax(0,1fr))}.ah__main{padding:40px 24px;gap:36px}.ah__title{font-size:36px}.ah__util{padding:var(--sp-3) var(--sp-5)}}@media(width<=900px){.ah__grid{grid-template-columns:repeat(2,minmax(0,1fr))}.ah__main{padding:40px 24px;gap:36px}.ah__title{font-size:36px}.ah__util{padding:var(--sp-3) var(--sp-5)}}@container (width <= 560px){.ah__grid{grid-template-columns:1fr}.ah__title{font-size:30px}.ah__sub{font-size:var(--text-sm)}.ah__sec-hint{display:none}}@media(width<=560px){.ah__grid{grid-template-columns:1fr}.ah__title{font-size:30px}.ah__sub{font-size:var(--text-sm)}.ah__sec-hint{display:none}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
23142
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyAppHomeComponent, isStandalone: true, selector: "fly-app-home", inputs: { brandLabelKey: { classPropertyName: "brandLabelKey", publicName: "brandLabelKey", isSignal: true, isRequired: false, transformFunction: null }, titleKey: { classPropertyName: "titleKey", publicName: "titleKey", isSignal: true, isRequired: false, transformFunction: null }, subtitleKey: { classPropertyName: "subtitleKey", publicName: "subtitleKey", isSignal: true, isRequired: false, transformFunction: null }, sections: { classPropertyName: "sections", publicName: "sections", isSignal: true, isRequired: false, transformFunction: null }, modulesLabelKey: { classPropertyName: "modulesLabelKey", publicName: "modulesLabelKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { moduleSelected: "moduleSelected", brandSelected: "brandSelected" }, queries: [{ propertyName: "icons", predicate: FlyModuleIconDirective, isSignal: true }], ngImport: i0, template: "<div class=\"ah\">\r\n <header class=\"ah__util\">\r\n <button type=\"button\" class=\"ah__brand\" (click)=\"brandSelected.emit()\">\r\n <span class=\"ah__brand-mark\"><ng-content select=\"[app-home-brand]\" /></span>\r\n @if (brandLabelKey(); as key) {\r\n <span class=\"ah__brand-name\">{{ key | translate }}</span>\r\n }\r\n </button>\r\n <ng-content select=\"[app-home-actions]\" />\r\n </header>\r\n\r\n <main class=\"ah__main\">\r\n @if (titleKey() || subtitleKey()) {\r\n <section class=\"ah__hero\">\r\n @if (titleKey(); as key) {\r\n <h1 class=\"ah__title\">{{ key | translate }}</h1>\r\n }\r\n @if (subtitleKey(); as key) {\r\n <p class=\"ah__sub\">{{ key | translate }}</p>\r\n }\r\n </section>\r\n }\r\n\r\n @for (row of rows(); track row.index) {\r\n <section\r\n class=\"ah__sec\"\r\n [class.ah__sec--secondary]=\"row.index > 0\"\r\n [attr.aria-label]=\"row.section.titleKey ? null : (modulesLabelKey() | translate)\"\r\n >\r\n @if (row.section.titleKey; as titleKey) {\r\n @if (row.section.collapsible) {\r\n <button\r\n type=\"button\"\r\n class=\"ah__sec-hd\"\r\n (click)=\"toggle(row.index)\"\r\n [attr.aria-expanded]=\"row.expanded\"\r\n [attr.aria-controls]=\"sectionId(row.index)\"\r\n >\r\n <!-- Points end-ward when shut, down when open. `--open` wins over the RTL\r\n flip below because a downward chevron has no direction to mirror. -->\r\n <svg\r\n class=\"ah__sec-chev\"\r\n [class.ah__sec-chev--open]=\"row.expanded\"\r\n width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"9 6 15 12 9 18\" />\r\n </svg>\r\n <span class=\"ah__sec-title\">{{ titleKey | translate }}</span>\r\n <span class=\"ah__sec-count\">{{ row.section.modules.length }}</span>\r\n @if (row.hintKey; as hint) {\r\n <span class=\"ah__sec-hint\">{{ hint | translate }}</span>\r\n }\r\n </button>\r\n } @else {\r\n <h2 class=\"ah__sec-title ah__sec-title--static\">{{ titleKey | translate }}</h2>\r\n }\r\n }\r\n\r\n @if (row.expanded) {\r\n <div class=\"ah__grid\" [class.ah__grid--compact]=\"row.layout === 'compact'\" [id]=\"sectionId(row.index)\">\r\n @for (mod of row.section.modules; track mod.key) {\r\n <button\r\n type=\"button\"\r\n class=\"ah__card\"\r\n [class.ah__card--compact]=\"row.layout === 'compact'\"\r\n [disabled]=\"mod.disabled\"\r\n (click)=\"select(mod)\"\r\n >\r\n <span class=\"ah__card-ico\">\r\n @if (iconFor(mod.key); as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl\" />\r\n } @else if (mod.iconClass) {\r\n <i [class]=\"mod.iconClass\" aria-hidden=\"true\"></i>\r\n }\r\n </span>\r\n\r\n @if (row.layout === 'compact') {\r\n <span class=\"ah__card-main\">\r\n <span class=\"ah__card-title\">{{ mod.labelKey | translate }}</span>\r\n @if (mod.descKey; as descKey) {\r\n <span class=\"ah__card-desc\">{{ descKey | translate }}</span>\r\n }\r\n </span>\r\n <svg\r\n class=\"ah__card-arrow\" width=\"11\" height=\"11\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"2.6\" stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"9 6 15 12 9 18\" />\r\n </svg>\r\n } @else {\r\n <!-- No \"Open \u203A\" affordance row \u2014 the design's module card (MainContent.dc.html)\r\n ends at the description; the whole card is the click target and hover carries\r\n the affordance. Removed at the 2026-08-17 fidelity pass. -->\r\n <span class=\"ah__card-title ah__card-title--feature\">{{ mod.labelKey | translate }}</span>\r\n @if (mod.descKey; as descKey) {\r\n <span class=\"ah__card-desc ah__card-desc--feature\">{{ descKey | translate }}</span>\r\n }\r\n }\r\n </button>\r\n }\r\n </div>\r\n }\r\n </section>\r\n }\r\n </main>\r\n</div>\r\n", styles: [":host{display:flex;flex-direction:column;min-height:100%;container-type:inline-size}.ah{display:flex;flex-direction:column;flex:1;min-height:100%}.ah__util{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-4);padding:var(--sp-4) var(--sp-6)}:host-context(.window-content) .ah__brand{display:none}:host-context(.window-content) .ah__util{justify-content:flex-end}:host-context(.window-content) .ah__util:not(:has(>:not(.ah__brand))){display:none}.ah__brand{display:inline-flex;align-items:center;gap:var(--sp-2);padding:0;border:0;background:none;color:var(--ink);font-family:inherit;cursor:pointer}.ah__brand:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.ah__brand-name{font-size:var(--text-md);font-weight:var(--fw-semibold);letter-spacing:-.01em}.ah__main{flex:1;inline-size:100%;max-inline-size:1120px;margin-inline:auto;padding:56px 40px;display:flex;flex-direction:column;justify-content:center;gap:44px}.ah__hero{max-inline-size:640px}.ah__title{margin:0 0 var(--sp-3);font-size:44px;font-weight:var(--fw-semibold);letter-spacing:-.03em;text-wrap:balance;background:linear-gradient(180deg,var(--ink),var(--ink-2));-webkit-background-clip:text;background-clip:text;color:transparent}.ah__sub{margin:0;max-inline-size:560px;font-size:var(--text-lg);line-height:1.55;color:var(--ink-3);text-wrap:pretty}.ah__sec{display:flex;flex-direction:column;gap:var(--sp-4)}.ah__sec--secondary{padding-block-start:28px;border-block-start:1px solid var(--w08)}.ah__sec-hd{display:flex;align-items:center;gap:var(--sp-3);inline-size:100%;padding:0;background:none;border:0;cursor:pointer;font-family:inherit;color:var(--ink);text-align:start}.ah__sec-hd:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.ah__sec-chev{flex-shrink:0;color:var(--ink-3);transition:transform var(--t-overlay)}.ah__sec-title{font-size:var(--text-md);font-weight:var(--fw-semibold);letter-spacing:-.01em}.ah__sec-title--static{margin:0;color:var(--ink-3);font-size:var(--text-xs);letter-spacing:var(--tracking-wide);text-transform:uppercase}.ah__sec-count{display:inline-grid;place-items:center;min-inline-size:22px;block-size:20px;padding-inline:6px;border-radius:999px;background:var(--bg-3);border:1px solid var(--line);font-size:var(--text-2xs);font-weight:var(--fw-medium);font-variant-numeric:tabular-nums;color:var(--ink-3)}.ah__sec-hint{margin-inline-start:auto;font-size:var(--text-xs);color:var(--ink-3)}.ah__grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:14px}.ah__card{display:flex;flex-direction:column;align-items:stretch;position:relative;overflow:hidden;text-align:start;padding:20px;background-image:linear-gradient(160deg,var(--w055),var(--w02));border:1px solid var(--w09);border-radius:20px;color:inherit;font-family:inherit;cursor:pointer;animation:appTileIn .3s var(--nova-ease-micro) both}.ah__card:nth-child(1){animation-delay:0ms}.ah__card:nth-child(2){animation-delay:20ms}.ah__card:nth-child(3){animation-delay:40ms}.ah__card:nth-child(4){animation-delay:60ms}.ah__card:nth-child(5){animation-delay:80ms}.ah__card:nth-child(6){animation-delay:.1s}.ah__card:nth-child(7){animation-delay:.12s}.ah__card:nth-child(8){animation-delay:.14s}.ah__card:nth-child(9){animation-delay:.16s}.ah__card:nth-child(10){animation-delay:.18s}.ah__card:nth-child(11){animation-delay:.2s}.ah__card:nth-child(12){animation-delay:.22s}.ah__card:nth-child(n+13){animation-delay:.22s}.ah__card{transition:transform var(--t-overlay),box-shadow var(--t-overlay),border-color var(--t-state),background-image var(--t-state)}.ah__card:hover:not(:disabled){transform:translateY(-3px);border-color:color-mix(in oklab,var(--accent) 50%,transparent);background-image:linear-gradient(160deg,var(--tint-hover),transparent);box-shadow:0 20px 46px color-mix(in oklab,var(--accent) 16%,transparent),var(--shadow-filter)}.ah__card:focus-visible{outline:0;border-color:color-mix(in oklab,var(--accent) 50%,transparent);background-image:linear-gradient(160deg,var(--tint-hover),transparent);box-shadow:0 0 0 3px var(--accent-soft),0 20px 46px color-mix(in oklab,var(--accent) 16%,transparent),var(--shadow-filter)}.ah__card:disabled{cursor:default;opacity:.5}.ah__card-ico{display:grid;place-items:center;inline-size:42px;block-size:42px;margin-block-end:16px;border-radius:13px;background:linear-gradient(140deg,color-mix(in srgb,var(--accent) 50%,transparent),color-mix(in srgb,var(--sys-teal) 22%,transparent));box-shadow:0 6px 16px color-mix(in srgb,var(--accent) 30%,transparent),inset 0 1px 0 var(--edge-highlight);border:0;color:var(--on-accent);font-size:var(--icon-lg)}.ah__card--compact:hover:not(:disabled) .ah__card-ico,.ah__card--compact:focus-visible .ah__card-ico{background:linear-gradient(135deg,var(--accent),var(--sys-teal));box-shadow:inset 0 1px 0 var(--edge-highlight);color:var(--on-accent)}.ah__card-title{font-size:var(--text-sm);font-weight:var(--fw-semibold);letter-spacing:-.01em;color:var(--ink)}.ah__card-title--feature{margin-block-end:5px;font-size:16.5px;line-height:1.25;letter-spacing:-.005em}.ah__card-desc{font-size:var(--text-xs);line-height:1.45;color:var(--ink-3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ah__card-desc--feature{margin-block-end:0;font-size:13px;line-height:1.45;text-wrap:pretty;overflow:visible;white-space:normal}.ah__card-arrow{flex-shrink:0;transition:color var(--t-overlay),transform var(--t-overlay)}.ah__card--compact{flex-direction:row;align-items:center;gap:var(--sp-3);padding:14px 16px;background-color:var(--bg);background-image:linear-gradient(160deg,var(--w035),var(--w035));border-radius:16px;border-color:var(--w08)}.ah__card--compact:hover:not(:disabled),.ah__card--compact:focus-visible{border-color:color-mix(in oklab,var(--accent) 40%,transparent);background-image:linear-gradient(160deg,var(--tint-hover),transparent)}.ah__card--compact .ah__card-ico{inline-size:32px;block-size:32px;margin-block-end:0;flex-shrink:0;border-radius:10px;font-size:var(--icon-md);background:var(--bg-3);box-shadow:none;color:var(--ink)}.ah__card-main{display:flex;flex-direction:column;gap:2px;flex:1;min-inline-size:0}.ah__card--compact .ah__card-arrow{color:var(--ink-4)}.ah__card--compact:hover:not(:disabled) .ah__card-arrow{color:var(--accent);transform:translate(2px)}:host-context([dir=rtl]) .ah__card-arrow{transform:scaleX(-1)}:host-context([dir=rtl]) .ah__sec-chev:not(.ah__sec-chev--open){transform:scaleX(-1)}:host-context([dir=rtl]) .ah__card--compact:hover:not(:disabled) .ah__card-arrow{transform:scaleX(-1) translate(2px)}.ah__sec-chev--open{transform:rotate(90deg)}@container (width <= 900px){.ah__main{padding:40px 24px;gap:36px}.ah__title{font-size:36px}.ah__util{padding:var(--sp-3) var(--sp-5)}}@media(width<=900px){.ah__main{padding:40px 24px;gap:36px}.ah__title{font-size:36px}.ah__util{padding:var(--sp-3) var(--sp-5)}}@container (width <= 560px){.ah__title{font-size:30px}.ah__sub{font-size:var(--text-sm)}.ah__sec-hint{display:none}}@media(width<=560px){.ah__title{font-size:30px}.ah__sub{font-size:var(--text-sm)}.ah__sec-hint{display:none}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
22928
23143
  }
22929
23144
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyAppHomeComponent, decorators: [{
22930
23145
  type: Component,
22931
- args: [{ selector: 'fly-app-home', standalone: true, imports: [NgTemplateOutlet, TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ah\">\r\n <header class=\"ah__util\">\r\n <button type=\"button\" class=\"ah__brand\" (click)=\"brandSelected.emit()\">\r\n <span class=\"ah__brand-mark\"><ng-content select=\"[app-home-brand]\" /></span>\r\n @if (brandLabelKey(); as key) {\r\n <span class=\"ah__brand-name\">{{ key | translate }}</span>\r\n }\r\n </button>\r\n <ng-content select=\"[app-home-actions]\" />\r\n </header>\r\n\r\n <main class=\"ah__main\">\r\n @if (titleKey() || subtitleKey()) {\r\n <section class=\"ah__hero\">\r\n @if (titleKey(); as key) {\r\n <h1 class=\"ah__title\">{{ key | translate }}</h1>\r\n }\r\n @if (subtitleKey(); as key) {\r\n <p class=\"ah__sub\">{{ key | translate }}</p>\r\n }\r\n </section>\r\n }\r\n\r\n @for (row of rows(); track row.index) {\r\n <section\r\n class=\"ah__sec\"\r\n [class.ah__sec--secondary]=\"row.index > 0\"\r\n [attr.aria-label]=\"row.section.titleKey ? null : (modulesLabelKey() | translate)\"\r\n >\r\n @if (row.section.titleKey; as titleKey) {\r\n @if (row.section.collapsible) {\r\n <button\r\n type=\"button\"\r\n class=\"ah__sec-hd\"\r\n (click)=\"toggle(row.index)\"\r\n [attr.aria-expanded]=\"row.expanded\"\r\n [attr.aria-controls]=\"sectionId(row.index)\"\r\n >\r\n <!-- Points end-ward when shut, down when open. `--open` wins over the RTL\r\n flip below because a downward chevron has no direction to mirror. -->\r\n <svg\r\n class=\"ah__sec-chev\"\r\n [class.ah__sec-chev--open]=\"row.expanded\"\r\n width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"9 6 15 12 9 18\" />\r\n </svg>\r\n <span class=\"ah__sec-title\">{{ titleKey | translate }}</span>\r\n <span class=\"ah__sec-count\">{{ row.section.modules.length }}</span>\r\n @if (row.hintKey; as hint) {\r\n <span class=\"ah__sec-hint\">{{ hint | translate }}</span>\r\n }\r\n </button>\r\n } @else {\r\n <h2 class=\"ah__sec-title ah__sec-title--static\">{{ titleKey | translate }}</h2>\r\n }\r\n }\r\n\r\n @if (row.expanded) {\r\n <div class=\"ah__grid\" [class.ah__grid--compact]=\"row.layout === 'compact'\" [id]=\"sectionId(row.index)\">\r\n @for (mod of row.section.modules; track mod.key) {\r\n <button\r\n type=\"button\"\r\n class=\"ah__card\"\r\n [class.ah__card--compact]=\"row.layout === 'compact'\"\r\n [disabled]=\"mod.disabled\"\r\n (click)=\"select(mod)\"\r\n >\r\n <span class=\"ah__card-ico\">\r\n @if (iconFor(mod.key); as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl\" />\r\n } @else if (mod.iconClass) {\r\n <i [class]=\"mod.iconClass\" aria-hidden=\"true\"></i>\r\n }\r\n </span>\r\n\r\n @if (row.layout === 'compact') {\r\n <span class=\"ah__card-main\">\r\n <span class=\"ah__card-title\">{{ mod.labelKey | translate }}</span>\r\n @if (mod.descKey; as descKey) {\r\n <span class=\"ah__card-desc\">{{ descKey | translate }}</span>\r\n }\r\n </span>\r\n <svg\r\n class=\"ah__card-arrow\" width=\"11\" height=\"11\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"2.6\" stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"9 6 15 12 9 18\" />\r\n </svg>\r\n } @else {\r\n <span class=\"ah__card-title ah__card-title--feature\">{{ mod.labelKey | translate }}</span>\r\n @if (mod.descKey; as descKey) {\r\n <span class=\"ah__card-desc ah__card-desc--feature\">{{ descKey | translate }}</span>\r\n }\r\n <span class=\"ah__card-open\">\r\n {{ 'ui.action.open' | translate }}\r\n <svg\r\n class=\"ah__card-arrow\" width=\"11\" height=\"11\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"2.6\" stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"9 6 15 12 9 18\" />\r\n </svg>\r\n </span>\r\n }\r\n </button>\r\n }\r\n </div>\r\n }\r\n </section>\r\n }\r\n </main>\r\n</div>\r\n", styles: [":host{display:flex;flex-direction:column;min-height:100%;container-type:inline-size}.ah{display:flex;flex-direction:column;flex:1;min-height:100%}.ah__util{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-4);padding:var(--sp-4) var(--sp-6)}.ah__brand{display:inline-flex;align-items:center;gap:var(--sp-2);padding:0;border:0;background:none;color:var(--ink);font-family:inherit;cursor:pointer}.ah__brand:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.ah__brand-name{font-size:var(--text-md);font-weight:var(--fw-semibold);letter-spacing:-.01em}.ah__main{flex:1;inline-size:100%;max-inline-size:1120px;margin-inline:auto;padding:56px 40px;display:flex;flex-direction:column;justify-content:center;gap:44px}.ah__hero{max-inline-size:640px}.ah__title{margin:0 0 var(--sp-3);font-size:44px;font-weight:var(--fw-semibold);letter-spacing:-.03em;text-wrap:balance;background:linear-gradient(180deg,var(--ink),var(--ink-2));-webkit-background-clip:text;background-clip:text;color:transparent}.ah__sub{margin:0;max-inline-size:560px;font-size:var(--text-lg);line-height:1.55;color:var(--ink-3);text-wrap:pretty}.ah__sec{display:flex;flex-direction:column;gap:var(--sp-4)}.ah__sec--secondary{padding-block-start:28px;border-block-start:1px solid var(--line)}.ah__sec-hd{display:flex;align-items:center;gap:var(--sp-3);inline-size:100%;padding:0;background:none;border:0;cursor:pointer;font-family:inherit;color:var(--ink);text-align:start}.ah__sec-hd:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.ah__sec-chev{flex-shrink:0;color:var(--ink-3);transition:transform var(--t-overlay)}.ah__sec-title{font-size:var(--text-md);font-weight:var(--fw-semibold);letter-spacing:-.01em}.ah__sec-title--static{margin:0;color:var(--ink-3);font-size:var(--text-xs);letter-spacing:var(--tracking-wide);text-transform:uppercase}.ah__sec-count{display:inline-grid;place-items:center;min-inline-size:22px;block-size:20px;padding-inline:6px;border-radius:999px;background:var(--bg-3);border:1px solid var(--line);font-size:var(--text-2xs);font-weight:var(--fw-medium);font-variant-numeric:tabular-nums;color:var(--ink-3)}.ah__sec-hint{margin-inline-start:auto;font-size:var(--text-xs);color:var(--ink-3)}.ah__grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--sp-3)}.ah__card{display:flex;flex-direction:column;align-items:stretch;position:relative;overflow:hidden;text-align:start;padding:20px 20px 18px;background-color:var(--bg);background-image:linear-gradient(160deg,var(--w055),var(--w02));border:1px solid var(--w09);border-radius:20px;color:inherit;font-family:inherit;cursor:pointer;animation:appTileIn .3s var(--nova-ease-micro) both}.ah__card:nth-child(1){animation-delay:0ms}.ah__card:nth-child(2){animation-delay:20ms}.ah__card:nth-child(3){animation-delay:40ms}.ah__card:nth-child(4){animation-delay:60ms}.ah__card:nth-child(5){animation-delay:80ms}.ah__card:nth-child(6){animation-delay:.1s}.ah__card:nth-child(7){animation-delay:.12s}.ah__card:nth-child(8){animation-delay:.14s}.ah__card:nth-child(9){animation-delay:.16s}.ah__card:nth-child(10){animation-delay:.18s}.ah__card:nth-child(11){animation-delay:.2s}.ah__card:nth-child(12){animation-delay:.22s}.ah__card:nth-child(n+13){animation-delay:.22s}.ah__card{transition:transform var(--t-overlay),box-shadow var(--t-overlay),border-color var(--t-state),background-image var(--t-state)}.ah__card:hover:not(:disabled){transform:translateY(-3px);border-color:color-mix(in oklab,var(--accent) 50%,transparent);background-image:linear-gradient(160deg,var(--tint-hover),transparent);box-shadow:0 20px 46px color-mix(in oklab,var(--accent) 16%,transparent),var(--shadow-filter)}.ah__card:focus-visible{outline:0;border-color:color-mix(in oklab,var(--accent) 50%,transparent);background-image:linear-gradient(160deg,var(--tint-hover),transparent);box-shadow:0 0 0 3px var(--accent-soft),0 20px 46px color-mix(in oklab,var(--accent) 16%,transparent),var(--shadow-filter)}.ah__card:disabled{cursor:default;opacity:.5}.ah__card-ico{display:grid;place-items:center;inline-size:42px;block-size:42px;margin-block-end:18px;border-radius:13px;background:linear-gradient(135deg,var(--accent),var(--sys-teal));box-shadow:inset 0 1px 0 var(--edge-highlight);border:0;color:var(--on-accent);font-size:var(--icon-lg)}.ah__card--compact:hover:not(:disabled) .ah__card-ico,.ah__card--compact:focus-visible .ah__card-ico{background:linear-gradient(135deg,var(--accent),var(--sys-teal));box-shadow:inset 0 1px 0 var(--edge-highlight);color:var(--on-accent)}.ah__card-title{font-size:var(--text-sm);font-weight:var(--fw-semibold);letter-spacing:-.01em;color:var(--ink)}.ah__card-title--feature{margin-block-end:4px;font-size:18px;letter-spacing:-.015em}.ah__card-desc{font-size:var(--text-xs);line-height:1.45;color:var(--ink-3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ah__card-desc--feature{margin-block-end:18px;font-size:var(--text-sm);line-height:1.5;text-wrap:pretty;overflow:visible;white-space:normal}.ah__card-open{display:inline-flex;align-items:center;gap:4px;margin-block-start:auto;font-size:var(--text-2xs);color:var(--ink-3);transition:color var(--t-overlay),gap var(--t-overlay)}.ah__card:hover:not(:disabled) .ah__card-open,.ah__card:focus-visible .ah__card-open{color:var(--accent);gap:8px}.ah__card-arrow{flex-shrink:0;transition:color var(--t-overlay),transform var(--t-overlay)}.ah__card--compact{flex-direction:row;align-items:center;gap:var(--sp-3);padding:14px 16px;background-color:var(--bg);background-image:linear-gradient(160deg,var(--w035),var(--w035));border-radius:16px;border-color:var(--w08)}.ah__card--compact:hover:not(:disabled),.ah__card--compact:focus-visible{border-color:color-mix(in oklab,var(--accent) 40%,transparent);background-image:linear-gradient(160deg,var(--tint-hover),transparent)}.ah__card--compact .ah__card-ico{inline-size:32px;block-size:32px;margin-block-end:0;flex-shrink:0;border-radius:10px;font-size:var(--icon-md);background:var(--bg-3);box-shadow:none;color:var(--ink)}.ah__card-main{display:flex;flex-direction:column;gap:2px;flex:1;min-inline-size:0}.ah__card--compact .ah__card-arrow{color:var(--ink-4)}.ah__card--compact:hover:not(:disabled) .ah__card-arrow{color:var(--accent);transform:translate(2px)}:host-context([dir=rtl]) .ah__card-arrow{transform:scaleX(-1)}:host-context([dir=rtl]) .ah__sec-chev:not(.ah__sec-chev--open){transform:scaleX(-1)}:host-context([dir=rtl]) .ah__card--compact:hover:not(:disabled) .ah__card-arrow{transform:scaleX(-1) translate(2px)}.ah__sec-chev--open{transform:rotate(90deg)}@container (width <= 900px){.ah__grid{grid-template-columns:repeat(2,minmax(0,1fr))}.ah__main{padding:40px 24px;gap:36px}.ah__title{font-size:36px}.ah__util{padding:var(--sp-3) var(--sp-5)}}@media(width<=900px){.ah__grid{grid-template-columns:repeat(2,minmax(0,1fr))}.ah__main{padding:40px 24px;gap:36px}.ah__title{font-size:36px}.ah__util{padding:var(--sp-3) var(--sp-5)}}@container (width <= 560px){.ah__grid{grid-template-columns:1fr}.ah__title{font-size:30px}.ah__sub{font-size:var(--text-sm)}.ah__sec-hint{display:none}}@media(width<=560px){.ah__grid{grid-template-columns:1fr}.ah__title{font-size:30px}.ah__sub{font-size:var(--text-sm)}.ah__sec-hint{display:none}}\n"] }]
23146
+ args: [{ selector: 'fly-app-home', standalone: true, imports: [NgTemplateOutlet, TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ah\">\r\n <header class=\"ah__util\">\r\n <button type=\"button\" class=\"ah__brand\" (click)=\"brandSelected.emit()\">\r\n <span class=\"ah__brand-mark\"><ng-content select=\"[app-home-brand]\" /></span>\r\n @if (brandLabelKey(); as key) {\r\n <span class=\"ah__brand-name\">{{ key | translate }}</span>\r\n }\r\n </button>\r\n <ng-content select=\"[app-home-actions]\" />\r\n </header>\r\n\r\n <main class=\"ah__main\">\r\n @if (titleKey() || subtitleKey()) {\r\n <section class=\"ah__hero\">\r\n @if (titleKey(); as key) {\r\n <h1 class=\"ah__title\">{{ key | translate }}</h1>\r\n }\r\n @if (subtitleKey(); as key) {\r\n <p class=\"ah__sub\">{{ key | translate }}</p>\r\n }\r\n </section>\r\n }\r\n\r\n @for (row of rows(); track row.index) {\r\n <section\r\n class=\"ah__sec\"\r\n [class.ah__sec--secondary]=\"row.index > 0\"\r\n [attr.aria-label]=\"row.section.titleKey ? null : (modulesLabelKey() | translate)\"\r\n >\r\n @if (row.section.titleKey; as titleKey) {\r\n @if (row.section.collapsible) {\r\n <button\r\n type=\"button\"\r\n class=\"ah__sec-hd\"\r\n (click)=\"toggle(row.index)\"\r\n [attr.aria-expanded]=\"row.expanded\"\r\n [attr.aria-controls]=\"sectionId(row.index)\"\r\n >\r\n <!-- Points end-ward when shut, down when open. `--open` wins over the RTL\r\n flip below because a downward chevron has no direction to mirror. -->\r\n <svg\r\n class=\"ah__sec-chev\"\r\n [class.ah__sec-chev--open]=\"row.expanded\"\r\n width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"9 6 15 12 9 18\" />\r\n </svg>\r\n <span class=\"ah__sec-title\">{{ titleKey | translate }}</span>\r\n <span class=\"ah__sec-count\">{{ row.section.modules.length }}</span>\r\n @if (row.hintKey; as hint) {\r\n <span class=\"ah__sec-hint\">{{ hint | translate }}</span>\r\n }\r\n </button>\r\n } @else {\r\n <h2 class=\"ah__sec-title ah__sec-title--static\">{{ titleKey | translate }}</h2>\r\n }\r\n }\r\n\r\n @if (row.expanded) {\r\n <div class=\"ah__grid\" [class.ah__grid--compact]=\"row.layout === 'compact'\" [id]=\"sectionId(row.index)\">\r\n @for (mod of row.section.modules; track mod.key) {\r\n <button\r\n type=\"button\"\r\n class=\"ah__card\"\r\n [class.ah__card--compact]=\"row.layout === 'compact'\"\r\n [disabled]=\"mod.disabled\"\r\n (click)=\"select(mod)\"\r\n >\r\n <span class=\"ah__card-ico\">\r\n @if (iconFor(mod.key); as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl\" />\r\n } @else if (mod.iconClass) {\r\n <i [class]=\"mod.iconClass\" aria-hidden=\"true\"></i>\r\n }\r\n </span>\r\n\r\n @if (row.layout === 'compact') {\r\n <span class=\"ah__card-main\">\r\n <span class=\"ah__card-title\">{{ mod.labelKey | translate }}</span>\r\n @if (mod.descKey; as descKey) {\r\n <span class=\"ah__card-desc\">{{ descKey | translate }}</span>\r\n }\r\n </span>\r\n <svg\r\n class=\"ah__card-arrow\" width=\"11\" height=\"11\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"2.6\" stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"9 6 15 12 9 18\" />\r\n </svg>\r\n } @else {\r\n <!-- No \"Open \u203A\" affordance row \u2014 the design's module card (MainContent.dc.html)\r\n ends at the description; the whole card is the click target and hover carries\r\n the affordance. Removed at the 2026-08-17 fidelity pass. -->\r\n <span class=\"ah__card-title ah__card-title--feature\">{{ mod.labelKey | translate }}</span>\r\n @if (mod.descKey; as descKey) {\r\n <span class=\"ah__card-desc ah__card-desc--feature\">{{ descKey | translate }}</span>\r\n }\r\n }\r\n </button>\r\n }\r\n </div>\r\n }\r\n </section>\r\n }\r\n </main>\r\n</div>\r\n", styles: [":host{display:flex;flex-direction:column;min-height:100%;container-type:inline-size}.ah{display:flex;flex-direction:column;flex:1;min-height:100%}.ah__util{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-4);padding:var(--sp-4) var(--sp-6)}:host-context(.window-content) .ah__brand{display:none}:host-context(.window-content) .ah__util{justify-content:flex-end}:host-context(.window-content) .ah__util:not(:has(>:not(.ah__brand))){display:none}.ah__brand{display:inline-flex;align-items:center;gap:var(--sp-2);padding:0;border:0;background:none;color:var(--ink);font-family:inherit;cursor:pointer}.ah__brand:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.ah__brand-name{font-size:var(--text-md);font-weight:var(--fw-semibold);letter-spacing:-.01em}.ah__main{flex:1;inline-size:100%;max-inline-size:1120px;margin-inline:auto;padding:56px 40px;display:flex;flex-direction:column;justify-content:center;gap:44px}.ah__hero{max-inline-size:640px}.ah__title{margin:0 0 var(--sp-3);font-size:44px;font-weight:var(--fw-semibold);letter-spacing:-.03em;text-wrap:balance;background:linear-gradient(180deg,var(--ink),var(--ink-2));-webkit-background-clip:text;background-clip:text;color:transparent}.ah__sub{margin:0;max-inline-size:560px;font-size:var(--text-lg);line-height:1.55;color:var(--ink-3);text-wrap:pretty}.ah__sec{display:flex;flex-direction:column;gap:var(--sp-4)}.ah__sec--secondary{padding-block-start:28px;border-block-start:1px solid var(--w08)}.ah__sec-hd{display:flex;align-items:center;gap:var(--sp-3);inline-size:100%;padding:0;background:none;border:0;cursor:pointer;font-family:inherit;color:var(--ink);text-align:start}.ah__sec-hd:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.ah__sec-chev{flex-shrink:0;color:var(--ink-3);transition:transform var(--t-overlay)}.ah__sec-title{font-size:var(--text-md);font-weight:var(--fw-semibold);letter-spacing:-.01em}.ah__sec-title--static{margin:0;color:var(--ink-3);font-size:var(--text-xs);letter-spacing:var(--tracking-wide);text-transform:uppercase}.ah__sec-count{display:inline-grid;place-items:center;min-inline-size:22px;block-size:20px;padding-inline:6px;border-radius:999px;background:var(--bg-3);border:1px solid var(--line);font-size:var(--text-2xs);font-weight:var(--fw-medium);font-variant-numeric:tabular-nums;color:var(--ink-3)}.ah__sec-hint{margin-inline-start:auto;font-size:var(--text-xs);color:var(--ink-3)}.ah__grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:14px}.ah__card{display:flex;flex-direction:column;align-items:stretch;position:relative;overflow:hidden;text-align:start;padding:20px;background-image:linear-gradient(160deg,var(--w055),var(--w02));border:1px solid var(--w09);border-radius:20px;color:inherit;font-family:inherit;cursor:pointer;animation:appTileIn .3s var(--nova-ease-micro) both}.ah__card:nth-child(1){animation-delay:0ms}.ah__card:nth-child(2){animation-delay:20ms}.ah__card:nth-child(3){animation-delay:40ms}.ah__card:nth-child(4){animation-delay:60ms}.ah__card:nth-child(5){animation-delay:80ms}.ah__card:nth-child(6){animation-delay:.1s}.ah__card:nth-child(7){animation-delay:.12s}.ah__card:nth-child(8){animation-delay:.14s}.ah__card:nth-child(9){animation-delay:.16s}.ah__card:nth-child(10){animation-delay:.18s}.ah__card:nth-child(11){animation-delay:.2s}.ah__card:nth-child(12){animation-delay:.22s}.ah__card:nth-child(n+13){animation-delay:.22s}.ah__card{transition:transform var(--t-overlay),box-shadow var(--t-overlay),border-color var(--t-state),background-image var(--t-state)}.ah__card:hover:not(:disabled){transform:translateY(-3px);border-color:color-mix(in oklab,var(--accent) 50%,transparent);background-image:linear-gradient(160deg,var(--tint-hover),transparent);box-shadow:0 20px 46px color-mix(in oklab,var(--accent) 16%,transparent),var(--shadow-filter)}.ah__card:focus-visible{outline:0;border-color:color-mix(in oklab,var(--accent) 50%,transparent);background-image:linear-gradient(160deg,var(--tint-hover),transparent);box-shadow:0 0 0 3px var(--accent-soft),0 20px 46px color-mix(in oklab,var(--accent) 16%,transparent),var(--shadow-filter)}.ah__card:disabled{cursor:default;opacity:.5}.ah__card-ico{display:grid;place-items:center;inline-size:42px;block-size:42px;margin-block-end:16px;border-radius:13px;background:linear-gradient(140deg,color-mix(in srgb,var(--accent) 50%,transparent),color-mix(in srgb,var(--sys-teal) 22%,transparent));box-shadow:0 6px 16px color-mix(in srgb,var(--accent) 30%,transparent),inset 0 1px 0 var(--edge-highlight);border:0;color:var(--on-accent);font-size:var(--icon-lg)}.ah__card--compact:hover:not(:disabled) .ah__card-ico,.ah__card--compact:focus-visible .ah__card-ico{background:linear-gradient(135deg,var(--accent),var(--sys-teal));box-shadow:inset 0 1px 0 var(--edge-highlight);color:var(--on-accent)}.ah__card-title{font-size:var(--text-sm);font-weight:var(--fw-semibold);letter-spacing:-.01em;color:var(--ink)}.ah__card-title--feature{margin-block-end:5px;font-size:16.5px;line-height:1.25;letter-spacing:-.005em}.ah__card-desc{font-size:var(--text-xs);line-height:1.45;color:var(--ink-3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ah__card-desc--feature{margin-block-end:0;font-size:13px;line-height:1.45;text-wrap:pretty;overflow:visible;white-space:normal}.ah__card-arrow{flex-shrink:0;transition:color var(--t-overlay),transform var(--t-overlay)}.ah__card--compact{flex-direction:row;align-items:center;gap:var(--sp-3);padding:14px 16px;background-color:var(--bg);background-image:linear-gradient(160deg,var(--w035),var(--w035));border-radius:16px;border-color:var(--w08)}.ah__card--compact:hover:not(:disabled),.ah__card--compact:focus-visible{border-color:color-mix(in oklab,var(--accent) 40%,transparent);background-image:linear-gradient(160deg,var(--tint-hover),transparent)}.ah__card--compact .ah__card-ico{inline-size:32px;block-size:32px;margin-block-end:0;flex-shrink:0;border-radius:10px;font-size:var(--icon-md);background:var(--bg-3);box-shadow:none;color:var(--ink)}.ah__card-main{display:flex;flex-direction:column;gap:2px;flex:1;min-inline-size:0}.ah__card--compact .ah__card-arrow{color:var(--ink-4)}.ah__card--compact:hover:not(:disabled) .ah__card-arrow{color:var(--accent);transform:translate(2px)}:host-context([dir=rtl]) .ah__card-arrow{transform:scaleX(-1)}:host-context([dir=rtl]) .ah__sec-chev:not(.ah__sec-chev--open){transform:scaleX(-1)}:host-context([dir=rtl]) .ah__card--compact:hover:not(:disabled) .ah__card-arrow{transform:scaleX(-1) translate(2px)}.ah__sec-chev--open{transform:rotate(90deg)}@container (width <= 900px){.ah__main{padding:40px 24px;gap:36px}.ah__title{font-size:36px}.ah__util{padding:var(--sp-3) var(--sp-5)}}@media(width<=900px){.ah__main{padding:40px 24px;gap:36px}.ah__title{font-size:36px}.ah__util{padding:var(--sp-3) var(--sp-5)}}@container (width <= 560px){.ah__title{font-size:30px}.ah__sub{font-size:var(--text-sm)}.ah__sec-hint{display:none}}@media(width<=560px){.ah__title{font-size:30px}.ah__sub{font-size:var(--text-sm)}.ah__sec-hint{display:none}}\n"] }]
22932
23147
  }], propDecorators: { brandLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "brandLabelKey", required: false }] }], titleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleKey", required: false }] }], subtitleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitleKey", required: false }] }], sections: [{ type: i0.Input, args: [{ isSignal: true, alias: "sections", required: false }] }], modulesLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "modulesLabelKey", required: false }] }], moduleSelected: [{ type: i0.Output, args: ["moduleSelected"] }], brandSelected: [{ type: i0.Output, args: ["brandSelected"] }], icons: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => FlyModuleIconDirective), { isSignal: true }] }] } });
22933
23148
 
22934
23149
  /**
@@ -23037,7 +23252,7 @@ class FlyTabsComponent {
23037
23252
  }
23038
23253
  </div>
23039
23254
  <ng-content />
23040
- `, isInline: true, styles: [":host{display:block}.tb{display:flex;gap:0;min-inline-size:0;border-block-end:1px solid var(--line)}.tb__tab{display:inline-flex;align-items:center;gap:6px;padding:6px 12px 10px;background:transparent;border:0;border-block-end:2px solid transparent;font-size:var(--text-sm);font-weight:var(--fw-medium);color:var(--ink-3);cursor:pointer;font-family:inherit;margin-block-end:-1px;white-space:nowrap;transition:color var(--t-state),border-color var(--t-state)}.tb__tab:hover{color:var(--ink)}.tb__tab:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px;outline-offset:-2px}.tb__tab.tb__tab--active{color:var(--ink);border-block-end-color:var(--accent);font-weight:var(--fw-semibold)}.tb__count{font-family:var(--font-mono);font-size:10.5px;padding:1px 5px;background:var(--bg-3);border-radius:4px;color:var(--ink-4);font-variant-numeric:tabular-nums}.tb__tab--active .tb__count{color:var(--ink-3)}:host([data-variant=segmented]) .tb{display:inline-flex;gap:2px;padding:3px;border-radius:99px;background:var(--w07);border:1px solid var(--w08);border-block-end:1px solid var(--w08)}:host([data-variant=segmented]) .tb__tab{min-block-size:28px;padding:0 13px;margin-block-end:0;border-radius:99px;border-block-end:0;font-weight:var(--fw-medium);color:var(--w55)}:host([data-variant=segmented]) .tb__tab--active{background:var(--w14);box-shadow:var(--shadow-raised),inset 0 .5px 0 var(--w22);font-weight:var(--fw-semibold);color:var(--ink)}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
23255
+ `, isInline: true, styles: [":host{display:block}.tb{display:flex;gap:0;min-inline-size:0;border-block-end:1px solid var(--w1)}.tb__tab{display:inline-flex;align-items:center;gap:6px;padding:6px 12px 10px;background:transparent;border:0;border-block-end:2px solid transparent;font-size:var(--text-sm);font-weight:var(--fw-medium);color:var(--ink-3);cursor:pointer;font-family:inherit;margin-block-end:-1px;white-space:nowrap;transition:color var(--t-state),border-color var(--t-state)}.tb__tab:hover{color:var(--ink)}.tb__tab:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px;outline-offset:-2px}.tb__tab.tb__tab--active{color:var(--ink);border-block-end-color:var(--accent);font-weight:var(--fw-semibold)}.tb__count{font-family:var(--font-mono);font-size:10.5px;padding:1px 5px;background:var(--bg-3);border-radius:4px;color:var(--ink-4);font-variant-numeric:tabular-nums}.tb__tab--active .tb__count{color:var(--ink-3)}:host([data-variant=segmented]) .tb{display:inline-flex;gap:2px;padding:3px;border-radius:99px;background:var(--w07);border:1px solid var(--w08);border-block-end:1px solid var(--w08)}:host([data-variant=segmented]) .tb__tab{min-block-size:28px;padding:0 13px;margin-block-end:0;border-radius:99px;border-block-end:0;font-weight:var(--fw-medium);color:var(--w55)}:host([data-variant=segmented]) .tb__tab--active{background:var(--w14);box-shadow:var(--shadow-raised),inset 0 .5px 0 var(--w22);font-weight:var(--fw-semibold);color:var(--ink)}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
23041
23256
  }
23042
23257
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyTabsComponent, decorators: [{
23043
23258
  type: Component,
@@ -23072,7 +23287,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
23072
23287
  }
23073
23288
  </div>
23074
23289
  <ng-content />
23075
- `, styles: [":host{display:block}.tb{display:flex;gap:0;min-inline-size:0;border-block-end:1px solid var(--line)}.tb__tab{display:inline-flex;align-items:center;gap:6px;padding:6px 12px 10px;background:transparent;border:0;border-block-end:2px solid transparent;font-size:var(--text-sm);font-weight:var(--fw-medium);color:var(--ink-3);cursor:pointer;font-family:inherit;margin-block-end:-1px;white-space:nowrap;transition:color var(--t-state),border-color var(--t-state)}.tb__tab:hover{color:var(--ink)}.tb__tab:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px;outline-offset:-2px}.tb__tab.tb__tab--active{color:var(--ink);border-block-end-color:var(--accent);font-weight:var(--fw-semibold)}.tb__count{font-family:var(--font-mono);font-size:10.5px;padding:1px 5px;background:var(--bg-3);border-radius:4px;color:var(--ink-4);font-variant-numeric:tabular-nums}.tb__tab--active .tb__count{color:var(--ink-3)}:host([data-variant=segmented]) .tb{display:inline-flex;gap:2px;padding:3px;border-radius:99px;background:var(--w07);border:1px solid var(--w08);border-block-end:1px solid var(--w08)}:host([data-variant=segmented]) .tb__tab{min-block-size:28px;padding:0 13px;margin-block-end:0;border-radius:99px;border-block-end:0;font-weight:var(--fw-medium);color:var(--w55)}:host([data-variant=segmented]) .tb__tab--active{background:var(--w14);box-shadow:var(--shadow-raised),inset 0 .5px 0 var(--w22);font-weight:var(--fw-semibold);color:var(--ink)}\n"] }]
23290
+ `, styles: [":host{display:block}.tb{display:flex;gap:0;min-inline-size:0;border-block-end:1px solid var(--w1)}.tb__tab{display:inline-flex;align-items:center;gap:6px;padding:6px 12px 10px;background:transparent;border:0;border-block-end:2px solid transparent;font-size:var(--text-sm);font-weight:var(--fw-medium);color:var(--ink-3);cursor:pointer;font-family:inherit;margin-block-end:-1px;white-space:nowrap;transition:color var(--t-state),border-color var(--t-state)}.tb__tab:hover{color:var(--ink)}.tb__tab:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px;outline-offset:-2px}.tb__tab.tb__tab--active{color:var(--ink);border-block-end-color:var(--accent);font-weight:var(--fw-semibold)}.tb__count{font-family:var(--font-mono);font-size:10.5px;padding:1px 5px;background:var(--bg-3);border-radius:4px;color:var(--ink-4);font-variant-numeric:tabular-nums}.tb__tab--active .tb__count{color:var(--ink-3)}:host([data-variant=segmented]) .tb{display:inline-flex;gap:2px;padding:3px;border-radius:99px;background:var(--w07);border:1px solid var(--w08);border-block-end:1px solid var(--w08)}:host([data-variant=segmented]) .tb__tab{min-block-size:28px;padding:0 13px;margin-block-end:0;border-radius:99px;border-block-end:0;font-weight:var(--fw-medium);color:var(--w55)}:host([data-variant=segmented]) .tb__tab--active{background:var(--w14);box-shadow:var(--shadow-raised),inset 0 .5px 0 var(--w22);font-weight:var(--fw-semibold);color:var(--ink)}\n"] }]
23076
23291
  }], propDecorators: { tablist: [{ type: i0.ViewChild, args: ['tablist', { isSignal: true }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }, { type: i0.Output, args: ["selectedChange"] }], ariaLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabelKey", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], tabItems: [{ type: i0.ContentChildren, args: [forwardRef(() => FlyTabComponent), { isSignal: true }] }] } });
23077
23292
  /**
23078
23293
  * One tab of a `fly-tabs` group: declares the tab button (id, label, optional
@@ -24708,7 +24923,7 @@ class ToastHostComponent {
24708
24923
  </div>
24709
24924
  }
24710
24925
  </div>
24711
- `, isInline: true, styles: [".ts{position:fixed;inset-inline-end:20px;inset-block-end:20px;z-index:var(--z-toast);display:flex;flex-direction:column-reverse;gap:10px;pointer-events:none;max-width:calc(100vw - 40px);width:min(400px,100vw - 40px)}.ts__t{pointer-events:auto;background:var(--bg-2);border:1px solid var(--line);border-radius:var(--r-md);padding-block:11px;padding-inline:13px 12px;display:flex;align-items:flex-start;gap:11px;box-shadow:var(--shadow-card),var(--shadow-toast);animation:ts-in .28s cubic-bezier(.32,.72,0,1);position:relative}.ts__t--leave{animation:ts-out .22s ease forwards}@keyframes ts-in{0%{opacity:0;transform:translate(16px) translateY(4px)}to{opacity:1;transform:none}}@keyframes ts-out{to{opacity:0;transform:translate(20px) scale(.97)}}:host-context(.rtl) .ts__t,:host-context([dir=rtl]) .ts__t{animation-name:ts-in-rtl}:host-context(.rtl) .ts__t--leave,:host-context([dir=rtl]) .ts__t--leave{animation-name:ts-out-rtl}@keyframes ts-in-rtl{0%{opacity:0;transform:translate(-16px) translateY(4px)}to{opacity:1;transform:none}}@keyframes ts-out-rtl{to{opacity:0;transform:translate(-20px) scale(.97)}}.ts__t--success{border-inline-start:3px solid var(--success)}.ts__t--warn{border-inline-start:3px solid var(--warning)}.ts__t--danger{border-inline-start:3px solid var(--danger)}.ts__t--neutral{border-inline-start:3px solid var(--ink-3)}.ts__icon{width:22px;height:22px;border-radius:50%;display:grid;place-items:center;flex-shrink:0;margin-block-start:1px}.ts__icon--success{background:var(--success-bg);color:var(--success)}.ts__icon--warn{background:var(--warning-bg);color:var(--warning-fg)}.ts__icon--danger{background:var(--danger-bg);color:var(--danger)}.ts__icon--neutral{background:var(--bg-3);color:var(--ink-2)}.ts__body{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px;padding-inline-end:4px}.ts__title{font-size:13px;font-weight:var(--fw-semibold);color:var(--ink);letter-spacing:-.005em;line-height:1.35}.ts__msg{font-size:var(--text-sm);color:var(--ink-2);line-height:1.45;word-break:break-word}.ts__action{background:transparent;border:1px solid var(--line-2);color:var(--ink);font-size:var(--text-2xs);font-weight:var(--fw-medium);padding:4px 9px;border-radius:var(--r-sm);cursor:pointer;flex-shrink:0;font-family:inherit;transition:background var(--t-state),border-color var(--t-state)}.ts__action:hover{background:var(--bg-hover);border-color:var(--ink-4)}.ts__close{width:24px;height:24px;border:0;background:transparent;color:var(--ink-3);cursor:pointer;border-radius:var(--r-sm);font-size:16px;line-height:1;display:grid;place-items:center;flex-shrink:0;font-family:inherit;transition:background var(--t-state),color var(--t-state)}.ts__close:hover{color:var(--ink);background:var(--bg-hover)}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
24926
+ `, isInline: true, styles: [".ts{position:fixed;inset-inline-end:20px;inset-block-end:20px;z-index:var(--z-toast);display:flex;flex-direction:column-reverse;gap:10px;pointer-events:none;max-width:calc(100vw - 40px);width:min(400px,100vw - 40px)}.ts__t{pointer-events:auto;background:var(--surface-overlay, var(--bg-2));border:1px solid var(--line);border-radius:var(--r-md);padding-block:11px;padding-inline:13px 12px;display:flex;align-items:flex-start;gap:11px;box-shadow:var(--shadow-card),var(--shadow-toast);animation:ts-in .28s cubic-bezier(.32,.72,0,1);position:relative}.ts__t--leave{animation:ts-out .22s ease forwards}@keyframes ts-in{0%{opacity:0;transform:translate(16px) translateY(4px)}to{opacity:1;transform:none}}@keyframes ts-out{to{opacity:0;transform:translate(20px) scale(.97)}}:host-context(.rtl) .ts__t,:host-context([dir=rtl]) .ts__t{animation-name:ts-in-rtl}:host-context(.rtl) .ts__t--leave,:host-context([dir=rtl]) .ts__t--leave{animation-name:ts-out-rtl}@keyframes ts-in-rtl{0%{opacity:0;transform:translate(-16px) translateY(4px)}to{opacity:1;transform:none}}@keyframes ts-out-rtl{to{opacity:0;transform:translate(-20px) scale(.97)}}.ts__t--success{border-inline-start:3px solid var(--success)}.ts__t--warn{border-inline-start:3px solid var(--warning)}.ts__t--danger{border-inline-start:3px solid var(--danger)}.ts__t--neutral{border-inline-start:3px solid var(--ink-3)}.ts__icon{width:22px;height:22px;border-radius:50%;display:grid;place-items:center;flex-shrink:0;margin-block-start:1px}.ts__icon--success{background:var(--success-bg);color:var(--success)}.ts__icon--warn{background:var(--warning-bg);color:var(--warning-fg)}.ts__icon--danger{background:var(--danger-bg);color:var(--danger)}.ts__icon--neutral{background:var(--bg-3);color:var(--ink-2)}.ts__body{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px;padding-inline-end:4px}.ts__title{font-size:13px;font-weight:var(--fw-semibold);color:var(--ink);letter-spacing:-.005em;line-height:1.35}.ts__msg{font-size:var(--text-sm);color:var(--ink-2);line-height:1.45;word-break:break-word}.ts__action{background:transparent;border:1px solid var(--line-2);color:var(--ink);font-size:var(--text-2xs);font-weight:var(--fw-medium);padding:4px 9px;border-radius:var(--r-sm);cursor:pointer;flex-shrink:0;font-family:inherit;transition:background var(--t-state),border-color var(--t-state)}.ts__action:hover{background:var(--bg-hover);border-color:var(--ink-4)}.ts__close{width:24px;height:24px;border:0;background:transparent;color:var(--ink-3);cursor:pointer;border-radius:var(--r-sm);font-size:16px;line-height:1;display:grid;place-items:center;flex-shrink:0;font-family:inherit;transition:background var(--t-state),color var(--t-state)}.ts__close:hover{color:var(--ink);background:var(--bg-hover)}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
24712
24927
  }
24713
24928
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: ToastHostComponent, decorators: [{
24714
24929
  type: Component,
@@ -24759,7 +24974,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
24759
24974
  </div>
24760
24975
  }
24761
24976
  </div>
24762
- `, styles: [".ts{position:fixed;inset-inline-end:20px;inset-block-end:20px;z-index:var(--z-toast);display:flex;flex-direction:column-reverse;gap:10px;pointer-events:none;max-width:calc(100vw - 40px);width:min(400px,100vw - 40px)}.ts__t{pointer-events:auto;background:var(--bg-2);border:1px solid var(--line);border-radius:var(--r-md);padding-block:11px;padding-inline:13px 12px;display:flex;align-items:flex-start;gap:11px;box-shadow:var(--shadow-card),var(--shadow-toast);animation:ts-in .28s cubic-bezier(.32,.72,0,1);position:relative}.ts__t--leave{animation:ts-out .22s ease forwards}@keyframes ts-in{0%{opacity:0;transform:translate(16px) translateY(4px)}to{opacity:1;transform:none}}@keyframes ts-out{to{opacity:0;transform:translate(20px) scale(.97)}}:host-context(.rtl) .ts__t,:host-context([dir=rtl]) .ts__t{animation-name:ts-in-rtl}:host-context(.rtl) .ts__t--leave,:host-context([dir=rtl]) .ts__t--leave{animation-name:ts-out-rtl}@keyframes ts-in-rtl{0%{opacity:0;transform:translate(-16px) translateY(4px)}to{opacity:1;transform:none}}@keyframes ts-out-rtl{to{opacity:0;transform:translate(-20px) scale(.97)}}.ts__t--success{border-inline-start:3px solid var(--success)}.ts__t--warn{border-inline-start:3px solid var(--warning)}.ts__t--danger{border-inline-start:3px solid var(--danger)}.ts__t--neutral{border-inline-start:3px solid var(--ink-3)}.ts__icon{width:22px;height:22px;border-radius:50%;display:grid;place-items:center;flex-shrink:0;margin-block-start:1px}.ts__icon--success{background:var(--success-bg);color:var(--success)}.ts__icon--warn{background:var(--warning-bg);color:var(--warning-fg)}.ts__icon--danger{background:var(--danger-bg);color:var(--danger)}.ts__icon--neutral{background:var(--bg-3);color:var(--ink-2)}.ts__body{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px;padding-inline-end:4px}.ts__title{font-size:13px;font-weight:var(--fw-semibold);color:var(--ink);letter-spacing:-.005em;line-height:1.35}.ts__msg{font-size:var(--text-sm);color:var(--ink-2);line-height:1.45;word-break:break-word}.ts__action{background:transparent;border:1px solid var(--line-2);color:var(--ink);font-size:var(--text-2xs);font-weight:var(--fw-medium);padding:4px 9px;border-radius:var(--r-sm);cursor:pointer;flex-shrink:0;font-family:inherit;transition:background var(--t-state),border-color var(--t-state)}.ts__action:hover{background:var(--bg-hover);border-color:var(--ink-4)}.ts__close{width:24px;height:24px;border:0;background:transparent;color:var(--ink-3);cursor:pointer;border-radius:var(--r-sm);font-size:16px;line-height:1;display:grid;place-items:center;flex-shrink:0;font-family:inherit;transition:background var(--t-state),color var(--t-state)}.ts__close:hover{color:var(--ink);background:var(--bg-hover)}\n"] }]
24977
+ `, styles: [".ts{position:fixed;inset-inline-end:20px;inset-block-end:20px;z-index:var(--z-toast);display:flex;flex-direction:column-reverse;gap:10px;pointer-events:none;max-width:calc(100vw - 40px);width:min(400px,100vw - 40px)}.ts__t{pointer-events:auto;background:var(--surface-overlay, var(--bg-2));border:1px solid var(--line);border-radius:var(--r-md);padding-block:11px;padding-inline:13px 12px;display:flex;align-items:flex-start;gap:11px;box-shadow:var(--shadow-card),var(--shadow-toast);animation:ts-in .28s cubic-bezier(.32,.72,0,1);position:relative}.ts__t--leave{animation:ts-out .22s ease forwards}@keyframes ts-in{0%{opacity:0;transform:translate(16px) translateY(4px)}to{opacity:1;transform:none}}@keyframes ts-out{to{opacity:0;transform:translate(20px) scale(.97)}}:host-context(.rtl) .ts__t,:host-context([dir=rtl]) .ts__t{animation-name:ts-in-rtl}:host-context(.rtl) .ts__t--leave,:host-context([dir=rtl]) .ts__t--leave{animation-name:ts-out-rtl}@keyframes ts-in-rtl{0%{opacity:0;transform:translate(-16px) translateY(4px)}to{opacity:1;transform:none}}@keyframes ts-out-rtl{to{opacity:0;transform:translate(-20px) scale(.97)}}.ts__t--success{border-inline-start:3px solid var(--success)}.ts__t--warn{border-inline-start:3px solid var(--warning)}.ts__t--danger{border-inline-start:3px solid var(--danger)}.ts__t--neutral{border-inline-start:3px solid var(--ink-3)}.ts__icon{width:22px;height:22px;border-radius:50%;display:grid;place-items:center;flex-shrink:0;margin-block-start:1px}.ts__icon--success{background:var(--success-bg);color:var(--success)}.ts__icon--warn{background:var(--warning-bg);color:var(--warning-fg)}.ts__icon--danger{background:var(--danger-bg);color:var(--danger)}.ts__icon--neutral{background:var(--bg-3);color:var(--ink-2)}.ts__body{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px;padding-inline-end:4px}.ts__title{font-size:13px;font-weight:var(--fw-semibold);color:var(--ink);letter-spacing:-.005em;line-height:1.35}.ts__msg{font-size:var(--text-sm);color:var(--ink-2);line-height:1.45;word-break:break-word}.ts__action{background:transparent;border:1px solid var(--line-2);color:var(--ink);font-size:var(--text-2xs);font-weight:var(--fw-medium);padding:4px 9px;border-radius:var(--r-sm);cursor:pointer;flex-shrink:0;font-family:inherit;transition:background var(--t-state),border-color var(--t-state)}.ts__action:hover{background:var(--bg-hover);border-color:var(--ink-4)}.ts__close{width:24px;height:24px;border:0;background:transparent;color:var(--ink-3);cursor:pointer;border-radius:var(--r-sm);font-size:16px;line-height:1;display:grid;place-items:center;flex-shrink:0;font-family:inherit;transition:background var(--t-state),color var(--t-state)}.ts__close:hover{color:var(--ink);background:var(--bg-hover)}\n"] }]
24763
24978
  }], ctorParameters: () => [] });
24764
24979
 
24765
24980
  // Barrel for the app-surface component library — the business-app CRUD/list/form
@@ -25253,6 +25468,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
25253
25468
  * does not yet ship a magic-bar search-field renderer, so this ships as a pure
25254
25469
  * helper for that future consumer rather than as UI. See
25255
25470
  * `.workflow/plans/ux-refresh/notes/S1.4-magic-actions.md`.
25471
+ * v2.8.0: `FlyStandaloneMagicActionsComponent` (`<fly-standalone-magic-actions appId="…">`) —
25472
+ * inline renderer of an app's OWN magic-bar contribution for standalone mode, closing
25473
+ * the gap that made every External App screen keep a bespoke `[page-header-actions]`
25474
+ * button row duplicating the actions it already publishes: drop this in that slot and
25475
+ * the contribution is authored once, rendered by the shell's pill when embedded and by
25476
+ * this cluster when standalone (it renders NOTHING embedded — it reads
25477
+ * `FlyRemoteRouter.isEmbedded` itself so consumers cannot forget the guard). Renders
25478
+ * `groups` + `primary` only; search stays the screen's in-page field, and
25479
+ * `overflow`/`quickCommandIds` are shell-chrome concerns that do not exist standalone.
25480
+ * Backed by new `MagicBarRegistry.resolve(owner)` — the reactive per-owner sibling of
25481
+ * `viewFor` (same slot fallback + ownership assertion as `active()`, but read from the
25482
+ * signal mirror so a `computed()` tracks it); needed because `active()` is arbitrated
25483
+ * by the shell's `setActiveOwner`, which never fires standalone.
25256
25484
  * See docs/ExternalAppsGuide/03-frontend-app.md.
25257
25485
  */
25258
25486
  // ─── Federation singleton self-check (side effect; must run first) ───────────
@@ -25274,5 +25502,5 @@ const AUDIENCE_ERROR_CODES = {
25274
25502
  * Generated bundle index. Do not edit.
25275
25503
  */
25276
25504
 
25277
- export { AGENT_DRAG_MIME, AGENT_PAYLOAD_VERSION, APP_LOOKUP, AUDIENCE_ERROR_CODES, AUDIENCE_LIMITS, AUDIENCE_PRESETS, AUDIENCE_TERM_KINDS, AgentActionBus, AgentActionUnsupportedDispatchError, AgentCommandRegistry, AgentDropRegistry, AgentFlightAnimator, AgentLookupRegistry, AgentPayloadOversizeError, AudienceBuilderComponent, AuthService, BilingualFieldComponent, CRON_MODES, CRON_WEEKDAYS, ContextMenuComponent, DEFAULT_AGENT_PAYLOAD_LIMITS, DEFAULT_FLY_THEME_MODE, DS_BASELINE_LOCALES, DashboardKpiComponent, DialogResult, ENTITY_LINK_LAUNCHER, EntityLookupComponent, FLYOS_LAUNCH_EVENT, FLYOS_LAUNCH_REQUEST_EVENT, FLYOS_REMOTE_ROUTE_EVENT, FLY_ACCENT_PROPERTY, FLY_ADMIN_ROLES, FLY_CHUNK_RELOAD_FLAG, FLY_COMPACT_THRESHOLD, FLY_COUNTRIES, FLY_CURRENCIES_BRIEF_ENDPOINT, FLY_EMOJI_BY_ID, FLY_EMOJI_CATEGORIES, FLY_EMOJI_CATEGORY_BY_ID, FLY_EMOJI_DEFAULT_CATEGORIES, FLY_EMOJI_PACK, FLY_EMOJI_PACK_MISSING_MESSAGE, FLY_EMOJI_PREVIEW_COUNT, FLY_EMPTY_VALUE, FLY_LOCALE_CATALOG, FLY_MAGIC_BAR_EVENT, FLY_MAGIC_BAR_ICONS, FLY_MAGIC_BAR_STORE_KEY, FLY_NF_CACHE_HEAL_FLAG, FLY_RELOAD_DEBOUNCE_MS, FLY_RELOAD_REARM_MS, FLY_REMOTE_BASE_PATH, FLY_REMOTE_CONTEXT_EVENT, FLY_REMOTE_CONTEXT_STORE_KEY, FLY_REMOTE_ROUTES, FLY_SCAN_PENDING_DEFAULT_DELAY_MS, FLY_SCAN_PENDING_MAX_RETRIES, FLY_SCAN_PENDING_STATUS, FLY_SEARCH_DEBOUNCE_MS, FLY_SKIN_TONES, FLY_STANDALONE_AUTH_CONFIG, FLY_THEME_MODE_IDS, FLY_VIEWPORT_IS_MOBILE, FLY_WINDOW_HELP_HINT_EVENT, FLY_WINDOW_PAGE_TITLE_EVENT, FlyAchievementProgressComponent, FlyActionMenuComponent, FlyActionStackComponent, FlyAgentDraggableDirective, FlyAnimatedEmojiComponent, FlyAppHomeComponent, FlyAppTopbarComponent, FlyAppUnavailableComponent, FlyAuthLiveRefresh, FlyBadgeWallComponent, FlyBlockUiComponent, FlyBreadcrumbComponent, FlyButtonComponent, FlyBytesPipe, FlyCaptchaComponent, FlyCardActionsComponent, FlyCardBodyComponent, FlyCardComponent, FlyCardFooterComponent, FlyCardGridComponent, FlyCardMediaComponent, FlyCardMetaComponent, FlyCardStatusComponent, FlyCardTitleComponent, FlyCellDirective, FlyCheckboxComponent, FlyChipComponent, FlyChunkReloadErrorHandler, FlyClickOutsideDirective, FlyCollapsibleComponent, FlyCommentThreadComponent, FlyCompactNumberPipe, FlyConfirmDialogComponent, FlyControlDirective, FlyCronBuilderComponent, FlyCurrencyCatalogService, FlyCurrencySelectorComponent, FlyDataTableComponent, FlyDatePipe, FlyDateTimePipe, FlyDebouncer, FlyDecimalNumberPipe, FlyDeepLinkPrefetchService, FlyDetailCardComponent, FlyDetailShellComponent, FlyDrawerComponent, FlyDurationPipe, FlyDynamicFormComponent, FlyEmojiPickerComponent, FlyFieldComponent, FlyFileDownloadService, FlyFileUploadComponent, FlyFilterPanelComponent, FlyFormBannerComponent, FlyFormFooterComponent, FlyFormGridComponent, FlyFormSectionComponent, FlyFullNumberPipe, FlyGanttComponent, FlyHubClient, FlyIconButtonComponent, FlyIfAdminDirective, FlyIfRoleDirective, FlyImageUploadComponent, FlyLeaderboardComponent, FlyMagicActionsComponent, FlyMetaListComponent, FlyModalComponent, FlyModerationQueueComponent, FlyModuleIconDirective, FlyMoneyPipe, FlyPaginationComponent, FlyPeoplePickerComponent, FlyPointsTierComponent, FlyProgressComponent, FlyRelativeTimePipe, FlyRemoteContextService, FlyRemoteRouter, FlyRemoteRouterOutletComponent, FlySearchInputComponent, FlySectionHeaderComponent, FlySecureSrcDirective, FlySegmentedComponent, FlySelectComponent, FlySkeletonComponent, FlySliderComponent, FlySparklineComponent, FlySpinnerComponent, FlyStandaloneAuthCallbackComponent, FlyStandaloneAuthService, FlyStateMessageComponent, FlyDynamicFormComponent as FlySurveyFormComponent, FlyTabComponent, FlyTabsComponent, FlyTagsInputComponent, FlyThemeService, FlyTimePipe, FlyToastService, FlyToggleComponent, FlyTooltipDirective, FlyTreeNavComponent, FlyTypeaheadComponent, FlyUserDirectoryService, FlyWindowHelpService, FlyWindowTitleService, FlyosPendingLaunchesGlobalKey, FlyosShellHandlesLaunchRequestsGlobalKey, FlyosShellOwnsHistoryGlobalKey, GANTT_ZOOMS, I18nService, LAUNCH_CONTEXT, MAGIC_BAR_SEARCH_WIDTH_DEFAULT, MAGIC_BAR_SEARCH_WIDTH_MAX, MAGIC_BAR_SEARCH_WIDTH_MIN, MagicBarRegistry, MessageBoxButtons, MessageBoxComponent, MessageBoxIcon, MessageBoxService, MockAuthService, NOVA_PRIORITY_TONE, NOVA_STATUS_TONE, NOVA_TONE_FALLBACK, OverlayStack, PRESENCE_COLORS, PageHeaderComponent, RTL_LOCALE_SET, SHARE_ORG_CHART_SYSTEM_KEY_APPS, SHARE_ORG_CHART_SYSTEM_KEY_DEFAULT, SHARE_PANEL_DEFAULT_FILE_LEVELS, STATE_DEFAULT_ICONS, STATE_DEFAULT_MESSAGE_KEYS, STEP_UP_CODE, STEP_UP_REAUTH_HANDLER, STEP_UP_RETURN_KEY, SUPPORTED_AGENT_PAYLOAD_VERSIONS, SharePanelComponent, SourceAppResolver, StandaloneWindowManagerService, StatusBadgeComponent, StepUpService, ToastHostComponent, TranslatePipe, WINDOW_DATA, WINDOW_HELP_HINT, WindowManagerService, applySkinTone, applySuggestion, ariaSort, buildCron, canConfirm, canGoNext, canGoPrev, captureFocus, clampMagicBarSearchWidth, clampPage, clampSliderValue, connectRemoteLaunch, enterActivatesNatively, filterGroup, filterSuggestions, findLocaleByDialect, findLocaleByPrefix, firstEnabledIndex, firstModuleIndex, flattenModules, flyAdminGuard, flyApiErrorMessage, flyCaptchaBase64Utf8, flyCaptchaBuildToken, flyCaptchaSha256Hex, flyCompactNumber, flyDebounced, flyDecimalNumber, flyDownloadBlob, flyDuration, flyEmojiFor, flyEmojiIsTonable, flyEmojiPackUrl, flyExportFileName, flyFirstEnabledIndex, flyFormatBytes, flyFormatDate, flyFormatDateTime, flyFormatMoney, flyFormatTime, flyFullNumber, flyNextEnabledIndex, flyNextSegmentIndex, flyRelativeTime, flyResolveActiveTab, flyRoleGuard, flyScanPendingDelayMs, flyScanRetry, flySignedCompact, flySkinToneLabelKey, flyStandaloneAuthGuard, flyStandaloneAuthInterceptor, flyToDateOnly, flyToPage, flyUnwrap, flyUnwrapCurrencies, flyUnwrapLenient, hasAnyRoleIn, healNativeFederationCacheOnce, initialExpanded, isAccentColor, isChunkLoadError, isFlyAuthStorePopulated, isNativeFederationCacheError, isRtlLocale, isRtlLocaleEntry, isValidCron, isValidSingleField, loadRemoteStyles, magicBarOwnerKey, magicBarSearchText, matchFlyRoutePattern, nextEnabledIndex, nextModuleIndex, nextSegmentIndex, nextSort, normalizeFlyTheme, normalizeRoles, novaPriorityToneVar, novaStatusToneVar, overlayStack, parseCron, parseStepUpChallenge, parseTags, prefetchRemoteStyles, presenceColorFor, printConsoleSecurityWarning, provideFlyChunkReloadRecovery, provideFlyEmojiPack, provideFlyStandaloneAuth, reloadOnceForChunkError, requestAppLaunch, resolveActiveModule, resolveActiveSection, resolveActiveTab, resolveCellValue, resolveStateIcon, resolveStateMessageKey, restoreFocus, sameTags, sectionHintKey, sectionLayout, sliderTrackGradient, sparklinePath, sparklinePoints, stepUpInterceptor, stepUpReturnKey, trimAgentPayload, trimAgentString, unloadRemoteStyles, utf8ByteLength, validateAgentPayload, warnIfEmbeddedSessionMissing };
25505
+ export { AGENT_DRAG_MIME, AGENT_PAYLOAD_VERSION, APP_LOOKUP, AUDIENCE_ERROR_CODES, AUDIENCE_LIMITS, AUDIENCE_PRESETS, AUDIENCE_TERM_KINDS, AgentActionBus, AgentActionUnsupportedDispatchError, AgentCommandRegistry, AgentDropRegistry, AgentFlightAnimator, AgentLookupRegistry, AgentPayloadOversizeError, AudienceBuilderComponent, AuthService, BilingualFieldComponent, CRON_MODES, CRON_WEEKDAYS, ContextMenuComponent, DEFAULT_AGENT_PAYLOAD_LIMITS, DEFAULT_FLY_THEME_MODE, DS_BASELINE_LOCALES, DashboardKpiComponent, DialogResult, ENTITY_LINK_LAUNCHER, EntityLookupComponent, FLYOS_LAUNCH_EVENT, FLYOS_LAUNCH_REQUEST_EVENT, FLYOS_REMOTE_ROUTE_EVENT, FLY_ACCENT_PROPERTY, FLY_ADMIN_ROLES, FLY_CHUNK_RELOAD_FLAG, FLY_COMPACT_THRESHOLD, FLY_COUNTRIES, FLY_CURRENCIES_BRIEF_ENDPOINT, FLY_EMOJI_BY_ID, FLY_EMOJI_CATEGORIES, FLY_EMOJI_CATEGORY_BY_ID, FLY_EMOJI_DEFAULT_CATEGORIES, FLY_EMOJI_PACK, FLY_EMOJI_PACK_MISSING_MESSAGE, FLY_EMOJI_PREVIEW_COUNT, FLY_EMPTY_VALUE, FLY_LOCALE_CATALOG, FLY_MAGIC_BAR_EVENT, FLY_MAGIC_BAR_ICONS, FLY_MAGIC_BAR_STORE_KEY, FLY_NF_CACHE_HEAL_FLAG, FLY_RELOAD_DEBOUNCE_MS, FLY_RELOAD_REARM_MS, FLY_REMOTE_BASE_PATH, FLY_REMOTE_CONTEXT_EVENT, FLY_REMOTE_CONTEXT_STORE_KEY, FLY_REMOTE_ROUTES, FLY_SCAN_PENDING_DEFAULT_DELAY_MS, FLY_SCAN_PENDING_MAX_RETRIES, FLY_SCAN_PENDING_STATUS, FLY_SEARCH_DEBOUNCE_MS, FLY_SKIN_TONES, FLY_STANDALONE_AUTH_CONFIG, FLY_THEME_MODE_IDS, FLY_VIEWPORT_IS_MOBILE, FLY_WINDOW_HELP_HINT_EVENT, FLY_WINDOW_PAGE_TITLE_EVENT, FlyAchievementProgressComponent, FlyActionMenuComponent, FlyActionStackComponent, FlyAgentDraggableDirective, FlyAnimatedEmojiComponent, FlyAppHomeComponent, FlyAppTopbarComponent, FlyAppUnavailableComponent, FlyAuthLiveRefresh, FlyBadgeWallComponent, FlyBlockUiComponent, FlyBreadcrumbComponent, FlyButtonComponent, FlyBytesPipe, FlyCaptchaComponent, FlyCardActionsComponent, FlyCardBodyComponent, FlyCardComponent, FlyCardFooterComponent, FlyCardGridComponent, FlyCardMediaComponent, FlyCardMetaComponent, FlyCardStatusComponent, FlyCardTitleComponent, FlyCellDirective, FlyCheckboxComponent, FlyChipComponent, FlyChunkReloadErrorHandler, FlyClickOutsideDirective, FlyCollapsibleComponent, FlyCommentThreadComponent, FlyCompactNumberPipe, FlyConfirmDialogComponent, FlyControlDirective, FlyCronBuilderComponent, FlyCurrencyCatalogService, FlyCurrencySelectorComponent, FlyDataTableComponent, FlyDatePipe, FlyDateTimePipe, FlyDebouncer, FlyDecimalNumberPipe, FlyDeepLinkPrefetchService, FlyDetailCardComponent, FlyDetailShellComponent, FlyDrawerComponent, FlyDurationPipe, FlyDynamicFormComponent, FlyEmojiPickerComponent, FlyFieldComponent, FlyFileDownloadService, FlyFileUploadComponent, FlyFilterPanelComponent, FlyFormBannerComponent, FlyFormFooterComponent, FlyFormGridComponent, FlyFormSectionComponent, FlyFullNumberPipe, FlyGanttComponent, FlyHubClient, FlyIconButtonComponent, FlyIfAdminDirective, FlyIfRoleDirective, FlyImageUploadComponent, FlyLeaderboardComponent, FlyMagicActionsComponent, FlyMetaListComponent, FlyModalComponent, FlyModerationQueueComponent, FlyModuleIconDirective, FlyMoneyPipe, FlyPaginationComponent, FlyPeoplePickerComponent, FlyPointsTierComponent, FlyProgressComponent, FlyRelativeTimePipe, FlyRemoteContextService, FlyRemoteRouter, FlyRemoteRouterOutletComponent, FlySearchInputComponent, FlySectionHeaderComponent, FlySecureSrcDirective, FlySegmentedComponent, FlySelectComponent, FlySkeletonComponent, FlySliderComponent, FlySparklineComponent, FlySpinnerComponent, FlyStandaloneAuthCallbackComponent, FlyStandaloneAuthService, FlyStandaloneMagicActionsComponent, FlyStateMessageComponent, FlyDynamicFormComponent as FlySurveyFormComponent, FlyTabComponent, FlyTabsComponent, FlyTagsInputComponent, FlyThemeService, FlyTimePipe, FlyToastService, FlyToggleComponent, FlyTooltipDirective, FlyTreeNavComponent, FlyTypeaheadComponent, FlyUserDirectoryService, FlyWindowHelpService, FlyWindowTitleService, FlyosPendingLaunchesGlobalKey, FlyosShellHandlesLaunchRequestsGlobalKey, FlyosShellOwnsHistoryGlobalKey, GANTT_ZOOMS, I18nService, LAUNCH_CONTEXT, MAGIC_BAR_SEARCH_WIDTH_DEFAULT, MAGIC_BAR_SEARCH_WIDTH_MAX, MAGIC_BAR_SEARCH_WIDTH_MIN, MagicBarRegistry, MessageBoxButtons, MessageBoxComponent, MessageBoxIcon, MessageBoxService, MockAuthService, NOVA_PRIORITY_TONE, NOVA_STATUS_TONE, NOVA_TONE_FALLBACK, OverlayStack, PRESENCE_COLORS, PageHeaderComponent, RTL_LOCALE_SET, SHARE_ORG_CHART_SYSTEM_KEY_APPS, SHARE_ORG_CHART_SYSTEM_KEY_DEFAULT, SHARE_PANEL_DEFAULT_FILE_LEVELS, STATE_DEFAULT_ICONS, STATE_DEFAULT_MESSAGE_KEYS, STEP_UP_CODE, STEP_UP_REAUTH_HANDLER, STEP_UP_RETURN_KEY, SUPPORTED_AGENT_PAYLOAD_VERSIONS, SharePanelComponent, SourceAppResolver, StandaloneWindowManagerService, StatusBadgeComponent, StepUpService, ToastHostComponent, TranslatePipe, WINDOW_DATA, WINDOW_HELP_HINT, WindowManagerService, applySkinTone, applySuggestion, ariaSort, buildCron, canConfirm, canGoNext, canGoPrev, captureFocus, clampMagicBarSearchWidth, clampPage, clampSliderValue, connectRemoteLaunch, enterActivatesNatively, filterGroup, filterSuggestions, findLocaleByDialect, findLocaleByPrefix, firstEnabledIndex, firstModuleIndex, flattenModules, flyAdminGuard, flyApiErrorMessage, flyCaptchaBase64Utf8, flyCaptchaBuildToken, flyCaptchaSha256Hex, flyCompactNumber, flyDebounced, flyDecimalNumber, flyDownloadBlob, flyDuration, flyEmojiFor, flyEmojiIsTonable, flyEmojiPackUrl, flyExportFileName, flyFirstEnabledIndex, flyFormatBytes, flyFormatDate, flyFormatDateTime, flyFormatMoney, flyFormatTime, flyFullNumber, flyNextEnabledIndex, flyNextSegmentIndex, flyRelativeTime, flyResolveActiveTab, flyRoleGuard, flyScanPendingDelayMs, flyScanRetry, flySignedCompact, flySkinToneLabelKey, flyStandaloneAuthGuard, flyStandaloneAuthInterceptor, flyToDateOnly, flyToPage, flyUnwrap, flyUnwrapCurrencies, flyUnwrapLenient, hasAnyRoleIn, healNativeFederationCacheOnce, initialExpanded, isAccentColor, isChunkLoadError, isFlyAuthStorePopulated, isNativeFederationCacheError, isRtlLocale, isRtlLocaleEntry, isValidCron, isValidSingleField, loadRemoteStyles, magicBarOwnerKey, magicBarSearchText, matchFlyRoutePattern, nextEnabledIndex, nextModuleIndex, nextSegmentIndex, nextSort, normalizeFlyTheme, normalizeRoles, novaPriorityToneVar, novaStatusToneVar, overlayStack, parseCron, parseStepUpChallenge, parseTags, prefetchRemoteStyles, presenceColorFor, printConsoleSecurityWarning, provideFlyChunkReloadRecovery, provideFlyEmojiPack, provideFlyStandaloneAuth, reloadOnceForChunkError, requestAppLaunch, resolveActiveModule, resolveActiveSection, resolveActiveTab, resolveCellValue, resolveStateIcon, resolveStateMessageKey, restoreFocus, sameTags, sectionHintKey, sectionLayout, sliderTrackGradient, sparklinePath, sparklinePoints, stepUpInterceptor, stepUpReturnKey, trimAgentPayload, trimAgentString, unloadRemoteStyles, utf8ByteLength, validateAgentPayload, warnIfEmbeddedSessionMissing };
25278
25506
  //# sourceMappingURL=flyos-design-system.mjs.map